From 4bf5f598fbe2372605306372b1f52d6c0d099327 Mon Sep 17 00:00:00 2001 From: laurent Date: Sun, 2 Jun 2019 16:59:32 +0200 Subject: [PATCH 001/240] begining functional split 6 --- executables/dl_fs6.c | 229 ++++++++++++++++++++++++ executables/split_headers.h | 13 ++ openair1/SCHED/phy_procedures_lte_eNb.c | 2 +- openair1/SIMULATION/LTE_PHY/ulsim.c | 2 +- targets/ARCH/COMMON/common_lib.c | 2 +- targets/ARCH/COMMON/common_lib.h | 46 ++++- targets/ARCH/rfsimulator/simulator.c | 204 ++++++++++++--------- targets/RT/USER/lte-ru.c | 38 ++-- 8 files changed, 436 insertions(+), 100 deletions(-) create mode 100644 executables/dl_fs6.c create mode 100644 executables/split_headers.h diff --git a/executables/dl_fs6.c b/executables/dl_fs6.c new file mode 100644 index 0000000000..4eae805eb7 --- /dev/null +++ b/executables/dl_fs6.c @@ -0,0 +1,229 @@ +#define MTU 65536 +#define UDP_TIMEOUT 100000L // in nano second + +receiveSubFrame(int sock) { + //read all subframe data from the control unit + char * buf[MTU]; + int ret=recv(sock, buf, sizeof(buf), 0); + if ( ret==-1) { + if ( errno == EWOULDBLOCK || errno== EINTR ) { + finishSubframeRecv(); + } else { + LOG_E(HW,"Critical issue in socket: %s\n", strerror(errno)); + return; + } + } else { + } + +} + +void pdsch_procedures(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, + int harq_pid, + LTE_eNB_DLSCH_t *dlsch, + LTE_eNB_DLSCH_t *dlsch1, + LTE_eNB_UE_stats *ue_stats, + int ra_flag) { + + int frame=proc->frame_tx; + int subframe=proc->subframe_tx; + LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch->harq_processes[harq_pid]; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + + // 36-212 + if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { // monolthic OR PNF - do not need turbo encoding on VNF + + // Replace dlsch_encoding + // data is in + // dlsch->harq_processes[harq_pid]->e + feedDlschBuffers(eNB, + dlsch_harq->pdu, + dlsch_harq->pdsch_start, + dlsch, + frame, + subframe, + &eNB->dlsch_rate_matching_stats, + &eNB->dlsch_turbo_encoding_stats, + &eNB->dlsch_turbo_encoding_waiting_stats, + &eNB->dlsch_turbo_encoding_main_stats, + &eNB->dlsch_turbo_encoding_wakeup_stats0, + &eNB->dlsch_turbo_encoding_wakeup_stats1, + &eNB->dlsch_interleaving_stats); + + // 36-211 + dlsch_scrambling(fp, + 0, + dlsch, + harq_pid, + get_G(fp, + dlsch_harq->nb_rb, + dlsch_harq->rb_alloc, + dlsch_harq->Qm, + dlsch_harq->Nl, + dlsch_harq->pdsch_start, + frame,subframe, + 0), + 0, + frame, + subframe<<1); + dlsch_modulation(eNB, + eNB->common_vars.txdataF, + AMP, + frame, + subframe, + dlsch_harq->pdsch_start, + dlsch, + dlsch->ue_type==0 ? dlsch1 : (LTE_eNB_DLSCH_t *)NULL); + } + + dlsch->active = 0; + dlsch_harq->round++; +} + +phy_procedures_eNB_TX_fs6() { + + receiveSubFrame(); + + // We got + // subframe number + // + + for (aa = 0; aa < fp->nb_antenna_ports_eNB; aa++) { + memset (&eNB->common_vars.txdataF[aa][subframe * fp->ofdm_symbol_size * fp->symbols_per_tti], + 0, + fp->ofdm_symbol_size * (fp->symbols_per_tti) * sizeof (int32_t)); + } + + if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { + if (is_pmch_subframe(frame,subframe,fp)) { + pmch_procedures(eNB,proc); + } else { + // this is not a pmch subframe, so generate PSS/SSS/PBCH + common_signal_procedures(eNB,proc->frame_tx, proc->subframe_tx); + } + } + + if (ul_subframe < 10)if (ul_subframe < 10) { // This means that there is a potential UL subframe that will be scheduled here + for (i=0; i= MAKE_VERSION(14, 0, 0)) + + if (eNB->ulsch[i] && eNB->ulsch[i]->ue_type >0) harq_pid = 0; + else +#endif + harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe); + + if (eNB->ulsch[i]) { + ulsch_harq = eNB->ulsch[i]->harq_processes[harq_pid]; + /* Store first_rb and n_DMRS for correct PHICH generation below. + * For PHICH generation we need "old" values of last scheduling + * for this HARQ process. 'generate_eNB_dlsch_params' below will + * overwrite first_rb and n_DMRS and 'generate_phich_top', done + * after 'generate_eNB_dlsch_params', would use the "new" values + * instead of the "old" ones. + * + * This has been tested for FDD only, may be wrong for TDD. + * + * TODO: maybe we should restructure the code to be sure it + * is done correctly. The main concern is if the code + * changes and first_rb and n_DMRS are modified before + * we reach here, then the PHICH processing will be wrong, + * using wrong first_rb and n_DMRS values to compute + * ngroup_PHICH and nseq_PHICH. + * + * TODO: check if that works with TDD. + */ + ulsch_harq->previous_first_rb = ulsch_harq->first_rb; + ulsch_harq->previous_n_DMRS = ulsch_harq->n_DMRS; + } + } + } + + num_pdcch_symbols = eNB->pdcch_vars[subframe&1].num_pdcch_symbols; + num_dci = eNB->pdcch_vars[subframe&1].num_dci; + if (num_dci > 0) + if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { + generate_dci_top(num_pdcch_symbols, + num_dci, + &eNB->pdcch_vars[subframe&1].dci_alloc[0], + 0, + AMP, + fp, + eNB->common_vars.txdataF, + subframe); + num_mdci = eNB->mpdcch_vars[subframe &1].num_dci; + + if (num_mdci > 0) { + generate_mdci_top (eNB, frame, subframe, AMP, eNB->common_vars.txdataF); + } + } + + // Now scan UE specific DLSCH + LTE_eNB_DLSCH_t *dlsch0,*dlsch1; + + for (UE_id=0; UE_iddlsch[(uint8_t)UE_id][0]; + dlsch1 = eNB->dlsch[(uint8_t)UE_id][1]; + + if ((dlsch0)&&(dlsch0->rnti>0)&& + (dlsch0->active == 1) + ) { + // get harq_pid + harq_pid = dlsch0->harq_ids[frame%2][subframe]; + AssertFatal(harq_pid>=0,"harq_pid is negative\n"); + + if (harq_pid>=8) { + if (dlsch0->ue_type==0) + LOG_E(PHY,"harq_pid:%d corrupt must be 0-7 UE_id:%d frame:%d subframe:%d rnti:%x \n", + harq_pid,UE_id,frame,subframe,dlsch0->rnti); + } else { + // generate pdsch + pdsch_procedures_fs6(eNB, + proc, + harq_pid, + dlsch0, + dlsch1, + &eNB->UE_stats[(uint32_t)UE_id], + 0); + } + } else if ((dlsch0)&&(dlsch0->rnti>0)&& + (dlsch0->active == 0) + ) { + // clear subframe TX flag since UE is not scheduled for PDSCH in this subframe (so that we don't look for PUCCH later) + dlsch0->subframe_tx[subframe]=0; + } + } + generate_phich_top(eNB, + proc, + AMP); + +} + +DL_thread_fs6() { + receiveSubFrame(); + phy_procedures_eNB_TX_fs6(); + ru->feptx_prec(ru); + ru->feptx_ofdm(ru); + ru->fh_south_out(ru); +} + +int createListner (port) { + int sock; + AssertFatal((sock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) >= 0, ""); + struct sockaddr_in addr = { +sin_family: + AF_INET, +sin_port: +htons(port), +sin_addr: + { s_addr: INADDR_ANY } + }; + AssertFatal(bind(sock, const struct sockaddr *addr, socklen_t addrlen)==0,""); + struct timeval tv={0,UDP_TIMEOUT}; + AssertFatal(setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(tv)) ==0,""); +} + + +DL_thread_frequency() { + frequency_t header; + + full_read(&header, diff --git a/executables/split_headers.h b/executables/split_headers.h new file mode 100644 index 0000000000..7a580affd4 --- /dev/null +++ b/executables/split_headers.h @@ -0,0 +1,13 @@ +#ifndef __SPLIT_HEADERS_H +#define __SPLIT_HEADERS_H + +struct frequency_s { + int frame; + int subframe; + int timestamp; + int sampleSize; + int nbAnt + int nbSamples; +} frequency_t; + +#endif diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 3b3b9336d4..9a209f06a5 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -431,7 +431,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) if (eNB->ulsch[i] && eNB->ulsch[i]->ue_type >0) harq_pid = 0; - else + else #endif harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe); diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c index 588a96ca6d..d05ffbd8fa 100644 --- a/openair1/SIMULATION/LTE_PHY/ulsim.c +++ b/openair1/SIMULATION/LTE_PHY/ulsim.c @@ -1354,7 +1354,7 @@ int main(int argc, char **argv) { printStatIndent2(&eNB->ulsch_deinterleaving_stats,"sub-block interleaving" ); printStatIndent2(&eNB->ulsch_demultiplexing_stats,"sub-block demultiplexing" ); printStatIndent2(&eNB->ulsch_rate_unmatching_stats,"sub-block rate-matching" ); - printf("|__ turbo_decoder(%d bits), avg iterations: %.1f %.2f us (%d cycles, %d trials)\n", + printf(" |__ turbo_decoder(%d bits), avg iterations: %.1f %.2f us (%d cycles, %d trials)\n", eNB->ulsch[0]->harq_processes[harq_pid]->Cminus ? eNB->ulsch[0]->harq_processes[harq_pid]->Kminus : eNB->ulsch[0]->harq_processes[harq_pid]->Kplus, diff --git a/targets/ARCH/COMMON/common_lib.c b/targets/ARCH/COMMON/common_lib.c index 3f81816aa1..23c979a6e1 100644 --- a/targets/ARCH/COMMON/common_lib.c +++ b/targets/ARCH/COMMON/common_lib.c @@ -105,7 +105,7 @@ int load_lib(openair0_device *device, openair0_config_t *openair0_cfg, eth_param if ( IS_SOFTMODEM_BASICSIM ) { libname=OAI_BASICSIM_LIBNAME; shlib_fdesc[0].fname="device_init"; - } else if ( IS_SOFTMODEM_RFSIM ) { + } else if ( IS_SOFTMODEM_RFSIM && flag == RAU_LOCAL_RADIO_HEAD) { libname=OAI_RFSIM_LIBNAME; shlib_fdesc[0].fname="device_init"; } else if (flag == RAU_LOCAL_RADIO_HEAD) { diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index 0af6fa9c5e..03fe4fb789 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -102,6 +102,10 @@ 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; @@ -214,6 +218,14 @@ typedef struct { int iq_rxrescale; //! Configuration file for LMS7002M char *configFilename; + //! remote IP/MAC addr for Ethernet interface + char *remote_addr; + //! remote port number for Ethernet interface + unsigned int remote_port; + //! local IP/MAC addr for Ethernet interface (eNB/BBU, UE) + char *my_addr; + //! local port number for Ethernet interface (eNB/BBU, UE) + unsigned int my_port; #if defined(USRP_REC_PLAY) unsigned short sf_mode; // 1=record, 2=replay char sf_filename[1024]; // subframes file path @@ -223,6 +235,13 @@ typedef struct { unsigned int sf_write_delay; // write delay in replay mode unsigned int eth_mtu; // ethernet MTU #endif + + //! number of samples per tti + unsigned int samples_per_tti; + //! the sample rate for receive. + double rx_sample_rate; + //! the sample rate for transmit. + double tx_sample_rate; } openair0_config_t; /*! \brief RF mapping */ @@ -384,6 +403,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 uint32_t // 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" @@ -408,7 +452,7 @@ openair0_timestamp get_usrp_time(openair0_device *device); * \returns 0 in success */ int openair0_set_rx_frequencies(openair0_device *device, openair0_config_t *openair0_cfg); - +#define gettid() syscall(__NR_gettid) /*@}*/ #ifdef __cplusplus diff --git a/targets/ARCH/rfsimulator/simulator.c b/targets/ARCH/rfsimulator/simulator.c index a17327b03e..21d3d5dc7e 100644 --- a/targets/ARCH/rfsimulator/simulator.c +++ b/targets/ARCH/rfsimulator/simulator.c @@ -24,28 +24,23 @@ #define PORT 4043 //TCP port for this simulator #define CirSize 3072000 // 100ms is enough +#define MaxBlock 30000 #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 sample_t uint32_t // 2*16 bits complex number typedef struct buffer_s { int conn_sock; - bool alreadyRead; + bool readEnabled; uint64_t lastReceivedTS; + uint64_t lastWroteTS; bool headerMode; - transferHeader th; + samplesBlockHeader_t th; char *transferPtr; uint64_t remainToTransfer; - char *circularBufEnd; + int nbAnt; sample_t *circularBuf; } buffer_t; @@ -55,19 +50,22 @@ typedef struct { uint64_t typeStamp; uint64_t initialAhead; char *ip; + int saveIQfile; buffer_t buf[FD_SETSIZE]; } rfsimulator_state_t; 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->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, ""); + AssertFatal ( setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &sendbuff, sizeof(sendbuff)) == 0, ""); + int tcp_maxseg = 1400; + AssertFatal ( setsockopt(sock, IPPROTO_TCP, TCP_MAXSEG, &tcp_maxseg,sizeof(tcp_maxseg)) == 0, ""); struct epoll_event ev= {0}; ev.events = EPOLLIN | EPOLLRDHUP; ev.data.fd = sock; @@ -87,7 +85,7 @@ 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); } } @@ -120,6 +118,11 @@ void setblocking(int sock, enum blocking_t active) { static bool flushInput(rfsimulator_state_t *t); void fullwrite(int fd, void *_buf, int 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)); + } + char *buf = _buf; int l; setblocking(fd, notBlocking); @@ -145,7 +148,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 +171,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 = { @@ -196,43 +199,104 @@ sin_addr: setblocking(sock, notBlocking); allocCirBuf(t, sock); - t->buf[sock].alreadyRead=true; // UE will start blocking on read + t->buf[sock].readEnabled=true; // UE will start blocking on read return 0; } +uint64_t lwrote; int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) { rfsimulator_state_t *t = device->priv; + // We do small blocks because the UE and the eNB are not aligned + // So large blocks can lead to deadlock (each side waits a incoming block completed) + int curBeg=0; - for (int i=0; ibuf[i]; + do { + int sizeToSend=min(nsamps-curBeg,MaxBlock); - if (ptr->conn_sock >= 0 ) { - transferHeader header= {t->typeStamp, nsamps, nbAnt, timestamp}; - fullwrite(ptr->conn_sock,&header, sizeof(header), t); - sample_t tmpSamples[nsamps][nbAnt]; + for (int i=0; ibuf[i]; - for(int a=0; aconn_sock >= 0 ) { + samplesBlockHeader_t header= {t->typeStamp, sizeToSend, nbAnt, timestamp+curBeg}; + fullwrite(ptr->conn_sock,&header, sizeof(header), t); + sample_t tmpSamples[sizeToSend][nbAnt]; - for(int s=0; sconn_sock >= 0 ) { + fullwrite(ptr->conn_sock, (void *)tmpSamples, sampleToByte(sizeToSend,nbAnt), t); + ptr->lastWroteTS=timestamp+curBeg+sizeToSend; + } } - - if (ptr->conn_sock >= 0 ) - fullwrite(ptr->conn_sock, (void *)tmpSamples, sampleToByte(nsamps,nbAnt), t); } - } - 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) ); + LOG_D(HW,"sent %d samples at time: %ld->%ld, energy in first antenna: %d\n", + sizeToSend, timestamp+curBeg, timestamp+curBeg+sizeToSend, + signal_energy(samplesVoid[0]+curBeg, sizeToSend) ); + curBeg+=sizeToSend; + } while ( curBeg < nsamps ) ; + return nsamps; } +static void oneTransferDone(rfsimulator_state_t *t, buffer_t *b) { + // check the header and start block transfer + if ( b->headerMode==true) { + 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; + + if ( b->lastReceivedTS != b->th.timestamp && b->readEnabled && b->lastReceivedTS ) { + 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; + + LOG_W(HW,"gap of: %ld in reception\n", b->th.timestamp-b->lastReceivedTS ); + } + + if ( b->readEnabled && b->lastReceivedTS && b->lastWroteTS) + AssertFatal( fabs((double)b->lastReceivedTS - (double)b->lastWroteTS) < (double)CirSize, + "Difference between Rx/Tx timestamps impossible, Rx: %lu, T:%lu\n", + b->lastReceivedTS, b->lastWroteTS); + else + printf("diff: %f\n", abs((double)b->lastReceivedTS - (double)b->lastWroteTS)/1000.0); + + + b->transferPtr=(char *)&b->circularBuf[b->lastReceivedTS%CirSize]; + b->remainToTransfer=sampleToByte(b->th.size, b->th.nbAnt); + } else { + LOG_I(HW,"Completed block reception: %ld\n", b->lastReceivedTS); + // in NB case, the UE started to write, since this event, we will wait it's data + // This is needed because the UE doesn't write in initial sync mode + // in UE case, the UE is already in this state (at connection time) + b->readEnabled=true; + b->lastReceivedTS=b->th.timestamp+b->th.size; + + // First block in UE, resync with the eNB current TS + if ( t->nextTimestamp == 0 ) { + t->nextTimestamp=b->lastReceivedTS-b->th.size; + LOG_I(HW,"Ue synchro on NB timestamp: %lu\n", t->nextTimestamp); + } + + b->headerMode=true; + b->transferPtr=(char *)&b->th; + b->remainToTransfer=sizeof(samplesBlockHeader_t); + b->th.magic=-1; + } +} + static bool flushInput(rfsimulator_state_t *t) { // 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, 2); if ( nfds==-1 ) { if ( errno==EINTR || errno==EAGAIN ) @@ -264,13 +328,14 @@ static bool flushInput(rfsimulator_state_t *t) { } int blockSz; + char * circularBufEnd=((char *)b->circularBuf)+sampleToByte(CirSize,1); if ( b->headerMode) blockSz=b->remainToTransfer; else - blockSz= b->transferPtr+b->remainToTransfer < b->circularBufEnd ? + blockSz= b->transferPtr+b->remainToTransfer < circularBufEnd ? b->remainToTransfer : - b->circularBufEnd - 1 - b->transferPtr ; + circularBufEnd - 1 - b->transferPtr ; int sz=recv(fd, b->transferPtr, blockSz, MSG_DONTWAIT); @@ -285,46 +350,11 @@ static bool flushInput(rfsimulator_state_t *t) { AssertFatal((b->remainToTransfer-=sz) >= 0, ""); b->transferPtr+=sz; - if (b->transferPtr==b->circularBufEnd - 1) + if (b->transferPtr==circularBufEnd - 1) b->transferPtr=(char *)b->circularBuf; - // 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"); - 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; - - LOG_W(HW,"gap of: %ld in reception\n", b->th.timestamp-b->lastReceivedTS ); - } - - b->lastReceivedTS=b->th.timestamp; - b->transferPtr=(char *)&b->circularBuf[b->lastReceivedTS%CirSize]; - b->remainToTransfer=sampleToByte(b->th.size, b->th.nbAnt); - } - - if ( b->headerMode==false ) { - 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; - - b->headerMode=true; - b->transferPtr=(char *)&b->th; - b->remainToTransfer=sizeof(transferHeader); - b->th.magic=-1; - } + if ( b->remainToTransfer==0) { + oneTransferDone(t,b); } } } @@ -367,7 +397,7 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo for ( int sock=0; sockbuf[sock].circularBuf && - t->buf[sock].alreadyRead && //>= t->initialAhead && + t->buf[sock].readEnabled && (t->nextTimestamp+nsamps) > t->buf[sock].lastReceivedTS ) { have_to_wait=true; break; @@ -390,7 +420,7 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo for (int sock=0; sockbuf[sock]; - if ( ptr->circularBuf && ptr->alreadyRead ) { + if ( ptr->circularBuf && ptr->readEnabled ) { for (int a=0; aip=getenv("RFSIMULATOR")) == NULL ) { @@ -447,10 +477,22 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { } 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 ? + ENB_MAGICDL_FDD: + UE_MAGICDL_FDD; + LOG_I(HW,"rfsimulator: running as %s\n", rfsimulator-> typeStamp == ENB_MAGICDL_FDD ? "eNB" : "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; diff --git a/targets/RT/USER/lte-ru.c b/targets/RT/USER/lte-ru.c index 93a2440b94..9d2fd5d084 100644 --- a/targets/RT/USER/lte-ru.c +++ b/targets/RT/USER/lte-ru.c @@ -148,7 +148,7 @@ int attach_rru(RU_t *ru) { RRU_CONFIG_msg_t rru_config_msg; int received_capabilities=0; wait_eNBs(); - + LOG_ENTER(PHY); // Wait for capabilities while (received_capabilities==0) { memset((void *)&rru_config_msg,0,sizeof(rru_config_msg)); @@ -208,7 +208,7 @@ int connect_rau(RU_t *ru) { RRU_capabilities_t *cap; int i; int len; - + LOG_ENTER(PHY); // wait for RAU_tick while (tick_received == 0) { msg_len = sizeof(RRU_CONFIG_msg_t)-MAX_RRU_CONFIG_SIZE; @@ -299,7 +299,7 @@ int connect_rau(RU_t *ru) { // southbound IF5 fronthaul for 16-bit OAI format static inline void fh_if5_south_out(RU_t *ru) { if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff ); - + LOG_ENTER(PHY); send_IF5(ru, ru->proc.timestamp_tx, ru->proc.subframe_tx, &ru->seqno, IF5_RRH_GW_DL); } @@ -315,7 +315,7 @@ static inline void fh_if4p5_south_out(RU_t *ru) { if (ru == RC.ru[0]) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff ); LOG_D(PHY,"Sending IF4p5 for frame %d subframe %d\n",ru->proc.frame_tx,ru->proc.subframe_tx); - + LOG_ENTER(PHY); if (subframe_select(&ru->frame_parms,ru->proc.subframe_tx)!=SF_UL) send_IF4p5(ru,ru->proc.frame_tx, ru->proc.subframe_tx, IF4p5_PDLFFT); } @@ -327,6 +327,7 @@ static inline void fh_if4p5_south_out(RU_t *ru) { void fh_if5_south_in(RU_t *ru,int *frame, int *subframe) { LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; RU_proc_t *proc = &ru->proc; + LOG_ENTER(PHY); recv_IF5(ru, &proc->timestamp_rx, *subframe, IF5_RRH_GW_UL); proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; @@ -358,14 +359,14 @@ void fh_if4p5_south_in(RU_t *ru,int *frame,int *subframe) { uint16_t packet_type; uint32_t symbol_number=0; uint32_t symbol_mask_full; - + LOG_ENTER(PHY); if ((fp->frame_type == TDD) && (subframe_select(fp,*subframe)==SF_S)) symbol_mask_full = (1<ul_symbols_in_S_subframe)-1; else symbol_mask_full = (1<symbols_per_tti)-1; AssertFatal(proc->symbol_mask[*subframe]==0,"rx_fh_if4p5: proc->symbol_mask[%d] = %x\n",*subframe,proc->symbol_mask[*subframe]); - + LOG_D(PHY,"start rcv IF4p5 \n"); do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!! recv_IF4p5(ru, &f, &sf, &packet_type, &symbol_number); @@ -382,6 +383,7 @@ void fh_if4p5_south_in(RU_t *ru,int *frame,int *subframe) { LOG_D(PHY,"rx_fh_if4p5: subframe %d symbol mask %x\n",*subframe,proc->symbol_mask[*subframe]); } while(proc->symbol_mask[*subframe] != symbol_mask_full); + LOG_D(PHY,"Done rcv IF4p5 \n"); //caculate timestamp_rx, timestamp_tx based on frame and subframe proc->subframe_rx = sf; @@ -482,6 +484,7 @@ void fh_if4p5_south_asynch_in(RU_t *ru,int *frame,int *subframe) { symbol_mask = (1<symbols_per_tti)-1; prach_rx = 0; + LOG_D(PHY,"start rcv IF4p5 \n"); do { // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!! recv_IF4p5(ru, &proc->frame_rx, &proc->subframe_rx, &packet_type, &symbol_number); @@ -578,6 +581,7 @@ void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *subframe) { uint16_t packet_type; uint32_t symbol_number,symbol_mask,symbol_mask_full; int subframe_tx,frame_tx; + LOG_ENTER(PHY); LOG_D(PHY, "%s(ru:%p frame, subframe)\n", __FUNCTION__, ru); symbol_number = 0; symbol_mask = 0; @@ -643,7 +647,7 @@ void fh_if4p5_north_out(RU_t *ru) { RU_proc_t *proc=&ru->proc; LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; const int subframe = proc->subframe_rx; - + LOG_ENTER(PHY); if (ru->idx==0) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_RU, proc->subframe_rx ); if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) { @@ -712,6 +716,8 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) { unsigned int rxs; int i; openair0_timestamp ts=0,old_ts=0; + LOG_ENTER(PHY); + LOG_D(PHY,"%s:%d start rx_rf \n", __FILE__,__LINE__); for (i=0; inb_rx; i++) rxp[i] = (void *)&ru->common.rxdata[i][*subframe*fp->samples_per_tti]; @@ -820,6 +826,7 @@ void tx_rf(RU_t *ru) { lte_subframe_t SF_type = subframe_select(fp,proc->subframe_tx%10); lte_subframe_t prevSF_type = subframe_select(fp,(proc->subframe_tx+9)%10); int sf_extension = 0; + LOG_D(PHY,"start tx_rf \n"); if ((SF_type == SF_DL) || (SF_type == SF_S)) { @@ -935,6 +942,7 @@ static void *ru_thread_asynch_rxtx( void *param ) { printf( "devices ok (ru_thread_asynch_rx)\n"); while (!oai_exit) { + LOG_ENTER(PHY); if (oai_exit) break; if (subframe==9) { @@ -968,7 +976,7 @@ void wakeup_slaves(RU_proc_t *proc) { struct timespec wait; wait.tv_sec=0; wait.tv_nsec=5000000L; - + LOG_ENTER(PHY); for (i=0; inum_slaves; i++) { RU_proc_t *slave_proc = proc->slave_proc[i]; @@ -1029,7 +1037,7 @@ static void *ru_thread_prach( void *param ) { if (oai_exit) break; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 1 ); - + LOG_ENTER(PHY); if (ru->eNB_list[0]) { prach_procedures( ru->eNB_list[0] @@ -1075,7 +1083,7 @@ static void *ru_thread_prach_br( void *param ) { if (wait_on_condition(&proc->mutex_prach_br,&proc->cond_prach_br,&proc->instance_cnt_prach_br,"ru_prach_thread_br") < 0) break; if (oai_exit) break; - + LOG_ENTER(PHY); rx_prach(NULL, ru, NULL, @@ -1098,7 +1106,7 @@ int wakeup_synch(RU_t *ru) { struct timespec wait; wait.tv_sec=0; wait.tv_nsec=5000000L; - + LOG_ENTER(PHY); // wake up synch thread // lock the synch mutex and make sure the thread is ready if (pthread_mutex_timedlock(&ru->proc.mutex_synch,&wait) != 0) { @@ -1135,7 +1143,7 @@ void do_ru_synch(RU_t *ru) { double temp_freq1 = ru->rfdevice.openair0_cfg->rx_freq[0]; double temp_freq2 = ru->rfdevice.openair0_cfg->tx_freq[0]; - + LOG_ENTER(PHY); for (i=0; i<4; i++) { ru->rfdevice.openair0_cfg->rx_freq[i] = ru->rfdevice.openair0_cfg->tx_freq[i]; ru->rfdevice.openair0_cfg->tx_freq[i] = temp_freq1; @@ -1198,7 +1206,7 @@ void wakeup_L1s(RU_t *ru) { int i; PHY_VARS_eNB **eNB_list = ru->eNB_list; LOG_D(PHY,"wakeup_L1s (num %d) for RU %d ru->eNB_top:%p\n",ru->num_eNB,ru->idx, ru->eNB_top); - + LOG_ENTER(PHY); if (ru->num_eNB==1 && ru->eNB_top!=0 && get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD) { // call eNB function directly char string[20]; @@ -1496,7 +1504,7 @@ static void *ru_thread_tx( void *param ) { wait_on_condition(&proc->mutex_eNBs,&proc->cond_eNBs,&proc->instance_cnt_eNBs,"ru_thread_tx"); if (oai_exit) break; - + LOG_ENTER(PHY); // do TX front-end processing if needed (precoding and/or IDFTs) if (ru->feptx_prec) ru->feptx_prec(ru); @@ -1644,7 +1652,7 @@ static void *ru_thread( void *param ) { // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices while (!oai_exit) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_CPUID_RU_THREAD,sched_getcpu()); - + LOG_ENTER(PHY); // these are local subframe/frame counters to check that we are in synch with the fronthaul timing. // They are set on the first rx/tx in the underly FH routines. if (subframe==9) { From 17d5bcd396bcd41a81a1a2f7929119b95ad4da2f Mon Sep 17 00:00:00 2001 From: laurent Date: Tue, 18 Jun 2019 08:57:08 +0200 Subject: [PATCH 002/240] dev continue --- common/utils/system.c | 104 ++++++++++--- common/utils/system.h | 25 ++++ executables/dl_fs6.c | 33 +---- executables/split_headers.h | 21 ++- executables/transport_split.c | 65 +++++++++ openair1/SIMULATION/TOOLS/random_channel.c | 4 + targets/RT/USER/lte-softmodem.c | 161 ++++----------------- 7 files changed, 225 insertions(+), 188 deletions(-) create mode 100644 executables/transport_split.c diff --git a/common/utils/system.c b/common/utils/system.c index dcec681e2d..31c1035129 100644 --- a/common/utils/system.c +++ b/common/utils/system.c @@ -28,13 +28,23 @@ * separate process solves this problem. */ +#define _GNU_SOURCE #include "system.h" #include #include #include #include #include - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #define MAX_COMMAND 4096 static int command_pipe_read; @@ -50,37 +60,37 @@ static int module_initialized = 0; /* util functions */ /********************************************************************/ -static void lock_system(void) -{ +static void lock_system(void) { if (pthread_mutex_lock(&lock) != 0) { printf("pthread_mutex_lock fails\n"); abort(); } } -static void unlock_system(void) -{ +static void unlock_system(void) { if (pthread_mutex_unlock(&lock) != 0) { printf("pthread_mutex_unlock fails\n"); abort(); } } -static void write_pipe(int p, char *b, int size) -{ +static void write_pipe(int p, char *b, int size) { while (size) { int ret = write(p, b, size); + if (ret <= 0) exit(0); + b += ret; size -= ret; } } -static void read_pipe(int p, char *b, int size) -{ +static void read_pipe(int p, char *b, int size) { while (size) { int ret = read(p, b, size); + if (ret <= 0) exit(0); + b += ret; size -= ret; } @@ -95,14 +105,13 @@ static void read_pipe(int p, char *b, int size) * when the main process exits, because then a "read" on the pipe * will return 0, in which case "read_pipe" exits. */ -static void background_system_process(void) -{ +static void background_system_process(void) { int len; int ret; char command[MAX_COMMAND+1]; while (1) { - read_pipe(command_pipe_read, (char*)&len, sizeof(int)); + read_pipe(command_pipe_read, (char *)&len, sizeof(int)); read_pipe(command_pipe_read, command, len); ret = system(command); write_pipe(result_pipe_write, (char *)&ret, sizeof(int)); @@ -114,8 +123,7 @@ static void background_system_process(void) /* return -1 on error, 0 on success */ /********************************************************************/ -int background_system(char *command) -{ +int background_system(char *command) { int res; int len; @@ -125,18 +133,22 @@ int background_system(char *command) } len = strlen(command)+1; + if (len > MAX_COMMAND) { printf("FATAL: command too long. Increase MAX_COMMAND (%d).\n", MAX_COMMAND); printf("command was: '%s'\n", command); abort(); } + /* only one command can run at a time, so let's lock/unlock */ lock_system(); - write_pipe(command_pipe_write, (char*)&len, sizeof(int)); + write_pipe(command_pipe_write, (char *)&len, sizeof(int)); write_pipe(command_pipe_write, command, len); - read_pipe(result_pipe_read, (char*)&res, sizeof(int)); + read_pipe(result_pipe_read, (char *)&res, sizeof(int)); unlock_system(); + if (res == -1 || !WIFEXITED(res) || WEXITSTATUS(res) != 0) return -1; + return 0; } @@ -146,17 +158,16 @@ int background_system(char *command) /* to be called very early by the main processing */ /********************************************************************/ -void start_background_system(void) -{ +void start_background_system(void) { int p[2]; pid_t son; - module_initialized = 1; if (pipe(p) == -1) { perror("pipe"); exit(1); } + command_pipe_read = p[0]; command_pipe_write = p[1]; @@ -164,10 +175,11 @@ void start_background_system(void) perror("pipe"); exit(1); } + result_pipe_read = p[0]; result_pipe_write = p[1]; - son = fork(); + if (son == -1) { perror("fork"); exit(1); @@ -181,6 +193,56 @@ void start_background_system(void) close(result_pipe_read); close(command_pipe_write); - background_system_process(); } + + +void threadCreate(pthread_t* t, void * (*func)(void*), void * param, char* name, int affinity, int priority){ + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); + pthread_attr_setschedpolicy(&attr, SCHED_FIFO); + struct sched_param sparam={0}; + sparam.sched_priority = priority; + pthread_attr_setschedparam(&attr, &sparam); + + pthread_create(t, &attr, func, param); + + pthread_setname_np(*t, name); + if (affinity != -1 ) { + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + CPU_SET(affinity, &cpuset); + AssertFatal( pthread_setaffinity_np(*t, sizeof(cpu_set_t), &cpuset) == 0, "Error setting processor affinity"); + } + + pthread_attr_destroy(&attr); +} + +// Block CPU C-states deep sleep +void configure_linux(void) { + int ret; + static int latency_target_fd=-1; + uint32_t latency_target_value=10; // in microseconds + if (latency_target_fd == -1) { + if ( (latency_target_fd = open("/dev/cpu_dma_latency", O_RDWR)) != -1 ) { + ret = write(latency_target_fd, &latency_target_value, sizeof(latency_target_value)); + if (ret == 0) { + printf("# error setting cpu_dma_latency to %d!: %s\n", latency_target_value, strerror(errno)); + close(latency_target_fd); + latency_target_fd=-1; + return; + } + } + } + if (latency_target_fd != -1) + LOG_I(HW,"# /dev/cpu_dma_latency set to %dus\n", latency_target_value); + else + LOG_E(HW,"Can't set /dev/cpu_dma_latency to %dus\n", latency_target_value); + + // Set CPU frequency to it's maximum + if ( 0 != system("for d in /sys/devices/system/cpu/cpu[0-9]*; do cat $d/cpufreq/cpuinfo_max_freq > $d/cpufreq/scaling_min_freq; done")) + LOG_W(HW,"Can't set cpu frequency\n"); + +} diff --git a/common/utils/system.h b/common/utils/system.h index 658c17adc1..a89a6c5b17 100644 --- a/common/utils/system.h +++ b/common/utils/system.h @@ -21,6 +21,12 @@ #ifndef _SYSTEM_H_OAI_ #define _SYSTEM_H_OAI_ +#include +#include +#ifdef __cplusplus +extern "C" { +#endif + /**************************************************** * send a command to the background process @@ -36,4 +42,23 @@ int background_system(char *command); void start_background_system(void); +void set_latency_target(void); +void configure_linux(void); + +void threadCreate(pthread_t* t, void * (*func)(void*), void * param, char* name, int affinity, int priority); +#define OAI_PRIORITY_RT_LOW sched_get_priority_min(SCHED_FIFO) +#define OAI_PRIORITY_RT sched_get_priority_max(SCHED_FIFO)-10 +#define OAI_PRIORITY_RT_MAX sched_get_priority_max(SCHED_FIFO) + +void thread_top_init(char *thread_name, + int affinity, + uint64_t runtime, + uint64_t deadline, + uint64_t period); + +#ifdef __cplusplus +} +#endif + + #endif /* _SYSTEM_H_OAI_ */ diff --git a/executables/dl_fs6.c b/executables/dl_fs6.c index 4eae805eb7..079f368f1d 100644 --- a/executables/dl_fs6.c +++ b/executables/dl_fs6.c @@ -1,21 +1,5 @@ -#define MTU 65536 -#define UDP_TIMEOUT 100000L // in nano second +#include -receiveSubFrame(int sock) { - //read all subframe data from the control unit - char * buf[MTU]; - int ret=recv(sock, buf, sizeof(buf), 0); - if ( ret==-1) { - if ( errno == EWOULDBLOCK || errno== EINTR ) { - finishSubframeRecv(); - } else { - LOG_E(HW,"Critical issue in socket: %s\n", strerror(errno)); - return; - } - } else { - } - -} void pdsch_procedures(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, @@ -206,21 +190,6 @@ DL_thread_fs6() { ru->fh_south_out(ru); } -int createListner (port) { - int sock; - AssertFatal((sock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) >= 0, ""); - struct sockaddr_in addr = { -sin_family: - AF_INET, -sin_port: -htons(port), -sin_addr: - { s_addr: INADDR_ANY } - }; - AssertFatal(bind(sock, const struct sockaddr *addr, socklen_t addrlen)==0,""); - struct timeval tv={0,UDP_TIMEOUT}; - AssertFatal(setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(tv)) ==0,""); -} DL_thread_frequency() { diff --git a/executables/split_headers.h b/executables/split_headers.h index 7a580affd4..1fe4088971 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -1,13 +1,28 @@ #ifndef __SPLIT_HEADERS_H #define __SPLIT_HEADERS_H -struct frequency_s { +#define MTU 65536 +#define UDP_TIMEOUT 100000L // in nano second +#define MAX_BLOCKS 16 +#define blockAlign 32 //bytes + +typedef struct commonUDP_s { + uint64_t timestamp; // id of the group (subframe for LTE) + uint16_t nbBlocks; // total number of blocks for this timestamp + uint16_t blockID; // id: 0..nbBocks-1 + uint16_t contentType; // defines the content format + uint16_t contentBytes; // will be sent in a UDP packet, so must be < 2^16 bytes +} commonUDP_t; + +typedef struct frequency_s { int frame; int subframe; - int timestamp; int sampleSize; int nbAnt int nbSamples; } frequency_t; - + +int createListner (port); +int receiveSubFrame(int sock, uint64_t expectedTS, void* bufferZone, int bufferSize); +int sendSubFrame(int sock, void* bufferZone, int nbBlocks);} #endif diff --git a/executables/transport_split.c b/executables/transport_split.c new file mode 100644 index 0000000000..a1e0738458 --- /dev/null +++ b/executables/transport_split.c @@ -0,0 +1,65 @@ +#include + +int createListner (port) { + int sock; + AssertFatal((sock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) >= 0, ""); + struct sockaddr_in addr = { +sin_family: + AF_INET, +sin_port: +htons(port), +sin_addr: + { s_addr: INADDR_ANY } + }; + int enable=1; + AssertFatal(setsockopt(eth->sockfdc, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable))==0,""); + AssertFatal(bind(sock, const struct sockaddr *addr, socklen_t addrlen)==0,""); + struct timeval tv={0,UDP_TIMEOUT}; + AssertFatal(setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(tv)) ==0,""); + // Make a send/recv buffer larger than a a couple of subframe + // so the kernel will store for us in and out paquets + int buff=1000*1000*10; + AssertFatal ( setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &buff, sizeof(buff)) == 0, ""); + AssertFatal ( setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &buff, sizeof(buff)) == 0, ""); +} + +// sock: udp socket +// expectedTS: the expected timestamp, 0 if unknown +// bufferZone: a reception area of bufferSize +int receiveSubFrame(int sock, uint64_t expectedTS, void* bufferZone, int bufferSize) { + int rcved=0; + do { + //read all subframe data from the control unit + int ret=recv(sock, bufferZone, bufferSize, 0); + if ( ret==-1) { + if ( errno == EWOULDBLOCK || errno== EINTR ) { + return rcved; // Timeout, subframe incomplete + } else { + LOG_E(HW,"Critical issue in socket: %s\n", strerror(errno)); + return -1; + } + } else { + commonUDP_t * tmp=(commonUDP_t *)bufferZone; + if ( expectedTS && tmp->timestamp != expectedTS) { + LOG_W(HW,"Received a paquet in mixed subframes, dropping it\n"); + } else { + rcved++; + bufferZone+=ret; + } + } + } while ( !recved || recved < tmp->nbBlocks); + return recv; +} + +int sendSubFrame(int sock, void* bufferZone, int nbBlocks) { + do { + int sz=alignedSize(bufferZone); + int ret=send(sock, bufferZone, sz, 0); + if ( ret != sz ) + LOG_W(HW,"Wrote socket doesn't return size %d (val: %d, errno:%d)\n", + sz, ret, errno); + bufferZone+=sz; + nbBlocks--; + } while (nbBlocks); + return 0; +} diff --git a/openair1/SIMULATION/TOOLS/random_channel.c b/openair1/SIMULATION/TOOLS/random_channel.c index 8341c574da..f056d51b5d 100644 --- a/openair1/SIMULATION/TOOLS/random_channel.c +++ b/openair1/SIMULATION/TOOLS/random_channel.c @@ -1204,6 +1204,10 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx, return(chan_desc); } +void free_channel_desc_scm(channel_desc_t * ch) { + // Must be made cleanly, a lot of leaks... + free(ch); +} int random_channel(channel_desc_t *desc, uint8_t abstraction_flag) { diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 0dfbcff954..50e866358b 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -108,10 +108,6 @@ pthread_mutex_t sync_mutex; int sync_var=-1; //!< protected by mutex \ref sync_mutex. int config_sync_var=-1; -uint16_t runtime_phy_rx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100] -uint16_t runtime_phy_tx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100] - - volatile int oai_exit = 0; uint32_t downlink_frequency[MAX_NUM_CCs][4]; @@ -149,21 +145,13 @@ uint8_t nb_antenna_rx = 1; char ref[128] = "internal"; char channels[128] = "0"; -int rx_input_level_dBm; - - -int otg_enabled; - - +int rx_input_level_dBm; +int otg_enabled; uint8_t exit_missed_slots=1; uint64_t num_missed_slots=0; // counter for the number of missed slots - -extern void reset_opp_meas(void); -extern void print_opp_meas(void); - - extern void init_eNB_afterRU(void); +extern void phy_free_RU(RU_t *); int transmission_mode=1; int emulate_rf = 0; @@ -172,73 +160,11 @@ int numerology = 0; THREAD_STRUCT thread_struct; /* struct for ethernet specific parameters given in eNB conf file */ eth_params_t *eth_params; - double cpuf; - - /* forward declarations */ void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]); -/*---------------------BMC: timespec helpers -----------------------------*/ - -struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 }; -struct timespec max_diff_time = { .tv_sec = 0, .tv_nsec = 0 }; - -struct timespec clock_difftime(struct timespec start, struct timespec end) { - struct timespec temp; - - if ((end.tv_nsec-start.tv_nsec)<0) { - temp.tv_sec = end.tv_sec-start.tv_sec-1; - temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec; - } else { - temp.tv_sec = end.tv_sec-start.tv_sec; - temp.tv_nsec = end.tv_nsec-start.tv_nsec; - } - - return temp; -} - -void print_difftimes(void) { -#ifdef DEBUG - printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec); -#else - LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec); -#endif -} - -void update_difftimes(struct timespec start, struct timespec end) { - struct timespec diff_time = { .tv_sec = 0, .tv_nsec = 0 }; - int changed = 0; - diff_time = clock_difftime(start, end); - - if ((min_diff_time.tv_nsec == 0) || (diff_time.tv_nsec < min_diff_time.tv_nsec)) { - min_diff_time.tv_nsec = diff_time.tv_nsec; - changed = 1; - } - - if ((max_diff_time.tv_nsec == 0) || (diff_time.tv_nsec > max_diff_time.tv_nsec)) { - max_diff_time.tv_nsec = diff_time.tv_nsec; - changed = 1; - } - -#if 1 - - if (changed) print_difftimes(); - -#endif -} - -/*------------------------------------------------------------------------*/ - -unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) { - return (txi + (txq<<6) + (rxi<<12) + (rxq<<18)); -} -unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe) { - return (dcoff_i_rxfe + (dcoff_q_rxfe<<8)); -} - - void signal_handler(int sig) { void *array[10]; size_t size; @@ -256,7 +182,6 @@ void signal_handler(int sig) { } } - void exit_function(const char *file, const char *function, const int line, const char *s) { int ru_id; @@ -285,8 +210,6 @@ void exit_function(const char *file, const char *function, const int line, const exit(1); } - - static void get_options(void) { CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP); get_common_options(); @@ -297,11 +220,11 @@ static void get_options(void) { /* Read RC configuration file */ RCConfig(); NB_eNB_INST = RC.nb_inst; - printf("Configuration: nb_rrc_inst %d, nb_L1_inst %d, nb_ru %d\n",NB_eNB_INST,RC.nb_L1_inst,RC.nb_RU); + LOG_I(ENB_APP,"Configuration: nb_rrc_inst %d, nb_L1_inst %d, nb_ru %d\n",NB_eNB_INST,RC.nb_L1_inst,RC.nb_RU); if (!IS_SOFTMODEM_NONBIOT) { load_NB_IoT(); - printf(" nb_nbiot_rrc_inst %d, nb_nbiot_L1_inst %d, nb_nbiot_macrlc_inst %d\n", + LOG_I(ENB_APP," nb_nbiot_rrc_inst %d, nb_nbiot_L1_inst %d, nb_nbiot_macrlc_inst %d\n", RC.nb_nb_iot_rrc_inst, RC.nb_nb_iot_L1_inst, RC.nb_nb_iot_macrlc_inst); } else { printf("All Nb-IoT instances disabled\n"); @@ -310,10 +233,6 @@ static void get_options(void) { } } - - - - void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) { int CC_id; @@ -528,75 +447,58 @@ int main( int argc, char **argv ) { int CC_id = 0; int ru_id; - if ( load_configmodule(argc,argv,0) == NULL) { - exit_fun("[SOFTMODEM] Error, configuration module init failed\n"); - } - + AssertFatal(load_configmodule(argc,argv,0) != NULL, + "[SOFTMODEM] Error, configuration module init failed\n"); mode = normal_txrx; - set_latency_target(); + logInit(); - printf("Reading in command-line options\n"); get_options (); + AssertFatal(!CONFIG_ISFLAGSET(CONFIG_ABORT),"Getting configuration failed\n"); + + configure_linux(); + // to make a graceful exit when ctrl-c is pressed + signal(SIGSEGV, signal_handler); + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); + signal(SIGABRT, signal_handler); + cpuf=get_cpu_freq_GHz(); + + #ifndef PACKAGE_VERSION +# define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL" +#endif + LOG_I(HW, "OAI Version: %s\n", PACKAGE_VERSION); if (is_nos1exec(argv[0]) ) set_softmodem_optmask(SOFTMODEM_NOS1_BIT); EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1; - if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) { - fprintf(stderr,"Getting configuration failed\n"); - exit(-1); - } - #if T_TRACER T_Config_Init(); #endif //randominit (0); set_taus_seed (0); - printf("configuring for RAU/RRU\n"); - if (opp_enabled ==1) { + if (opp_enabled ==1) reset_opp_meas(); - } - cpuf=get_cpu_freq_GHz(); - printf("ITTI init, useMME: %i\n",EPC_MODE_ENABLED); itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info); - - // initialize mscgen log after ITTI - if (get_softmodem_params()->start_msc) { - load_module_shlib("msc",NULL,0,&msc_interface); - } - - MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX); + // allows to forward in wireshark L2 protocol for decoding init_opt(); - // to make a graceful exit when ctrl-c is pressed - signal(SIGSEGV, signal_handler); - signal(SIGINT, signal_handler); - signal(SIGTERM, signal_handler); - signal(SIGABRT, signal_handler); - check_clock(); -#ifndef PACKAGE_VERSION -# define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL" -#endif - LOG_I(HW, "Version: %s\n", PACKAGE_VERSION); - printf("Runtime table\n"); - fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx); /* Read configuration */ if (RC.nb_inst > 0) { read_config_and_init(); /* Start the agent. If it is turned off in the configuration, it won't start */ RCconfig_flexran(); - - for (i = 0; i < RC.nb_inst; i++) { + + for (i = 0; i < RC.nb_inst; i++) flexran_agent_start(i); - } - + /* initializes PDCP and sets correct RLC Request/PDCP Indication callbacks * for monolithic/F1 modes */ init_pdcp(); - + if (create_tasks(1) < 0) { printf("cannot create ITTI tasks\n"); exit(-1); @@ -685,15 +587,11 @@ int main( int argc, char **argv ) { } printf("wait RUs\n"); - // CI -- Flushing the std outputs for the previous marker to show on the eNB / RRU log file - fflush(stdout); - fflush(stderr); // end of CI modifications wait_RUs(); LOG_I(ENB_APP,"RC.nb_RU:%d\n", RC.nb_RU); // once all RUs are ready intiailize the rest of the eNBs ((dependence on final RU parameters after configuration) - printf("ALL RUs ready - init eNBs\n"); - + if (NFAPI_MODE!=NFAPI_MODE_PNF && NFAPI_MODE!=NFAPI_MODE_VNF) { LOG_I(ENB_APP,"Not NFAPI mode - call init_eNB_afterRU()\n"); init_eNB_afterRU(); @@ -738,7 +636,6 @@ int main( int argc, char **argv ) { * threads have been stopped (they partially use the same memory) */ for (int inst = 0; inst < NB_eNB_INST; inst++) { for (int cc_id = 0; cc_id < RC.nb_CC[inst]; cc_id++) { - free_transport(RC.eNB[inst][cc_id]); phy_free_lte_eNB(RC.eNB[inst][cc_id]); } } From 0ba0422df7229bdd1a7e0dc769aca5e5c638192e Mon Sep 17 00:00:00 2001 From: laurent Date: Mon, 24 Jun 2019 22:04:14 +0200 Subject: [PATCH 003/240] add simple main --- cmake_targets/CMakeLists.txt | 34 + executables/dl_fs6.c | 130 ++- executables/simple_main.c | 1121 ++++++++++++++++++++++++++ executables/transport_split.c | 53 +- targets/ARCH/rfsimulator/simulator.c | 3 - targets/RT/USER/lte-enb.c | 2 +- targets/RT/USER/lte-ru.c | 126 +-- targets/RT/USER/lte-softmodem.c | 17 +- 8 files changed, 1280 insertions(+), 206 deletions(-) create mode 100644 executables/simple_main.c diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 50acfc4ce6..f2a5163219 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -2115,6 +2115,40 @@ target_link_libraries (lte-softmodem NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB -Wl,--end-group z dl) + +add_executable(simple-softmodem + ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c + ${OPENAIR_DIR}/executables/simple_main.c + ${OPENAIR_TARGETS}/RT/USER/lte-softmodem.c + ${OPENAIR_TARGETS}/RT/USER/lte-softmodem-common.c + ${OPENAIR2_DIR}/ENB_APP/NB_IoT_interface.c + ${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c + ${OPENAIR_TARGETS}/COMMON/create_tasks.c + ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c + ${OPENAIR2_DIR}/RRC/NAS/nas_config.c + ${OPENAIR2_DIR}/RRC/NAS/rb_config.c + ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c + ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/multicast_link.c + ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/socket.c + ${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c + ${OPENAIR_DIR}/common/utils/utils.c + ${OPENAIR_DIR}/common/utils/system.c + ${GTPU_need_ITTI} + ${XFORMSINTERFACE_SOURCE} + ${T_SOURCE} + ${CONFIG_SOURCES} + ${SHLIB_LOADER_SOURCES} + ) +add_dependencies(simple-softmodem rrc_flag s1ap_flag x2_flag) + +target_link_libraries (simple-softmodem + -Wl,--start-group + RRC_LIB S1AP_LIB S1AP_ENB F1AP_LIB F1AP X2AP_LIB X2AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB SCHED_RU_LIB PHY_COMMON PHY PHY_RU LFDS L2 + ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} ${FSPT_MSG_LIB} ${PROTO_AGENT_LIB} LFDS7 + NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB + -Wl,--end-group z dl) +target_link_libraries (simple-softmodem ${LIBXML2_LIBRARIES} pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES} ${LIB_LMS_LIBRARIES} ${T_LIB}) + add_executable(cu_test ${OPENAIR2_DIR}/LAYER2/PROTO_AGENT/cu_test.c ${OPENAIR2_DIR}/LAYER2/PROTO_AGENT/proto_agent_handler.c diff --git a/executables/dl_fs6.c b/executables/dl_fs6.c index 079f368f1d..c583a4bc45 100644 --- a/executables/dl_fs6.c +++ b/executables/dl_fs6.c @@ -8,7 +8,6 @@ void pdsch_procedures(PHY_VARS_eNB *eNB, LTE_eNB_DLSCH_t *dlsch1, LTE_eNB_UE_stats *ue_stats, int ra_flag) { - int frame=proc->frame_tx; int subframe=proc->subframe_tx; LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch->harq_processes[harq_pid]; @@ -16,24 +15,22 @@ void pdsch_procedures(PHY_VARS_eNB *eNB, // 36-212 if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { // monolthic OR PNF - do not need turbo encoding on VNF - // Replace dlsch_encoding - // data is in + // data is in // dlsch->harq_processes[harq_pid]->e feedDlschBuffers(eNB, - dlsch_harq->pdu, - dlsch_harq->pdsch_start, - dlsch, - frame, - subframe, - &eNB->dlsch_rate_matching_stats, - &eNB->dlsch_turbo_encoding_stats, - &eNB->dlsch_turbo_encoding_waiting_stats, - &eNB->dlsch_turbo_encoding_main_stats, - &eNB->dlsch_turbo_encoding_wakeup_stats0, - &eNB->dlsch_turbo_encoding_wakeup_stats1, - &eNB->dlsch_interleaving_stats); - + dlsch_harq->pdu, + dlsch_harq->pdsch_start, + dlsch, + frame, + subframe, + &eNB->dlsch_rate_matching_stats, + &eNB->dlsch_turbo_encoding_stats, + &eNB->dlsch_turbo_encoding_waiting_stats, + &eNB->dlsch_turbo_encoding_main_stats, + &eNB->dlsch_turbo_encoding_wakeup_stats0, + &eNB->dlsch_turbo_encoding_wakeup_stats1, + &eNB->dlsch_interleaving_stats); // 36-211 dlsch_scrambling(fp, 0, @@ -65,7 +62,6 @@ void pdsch_procedures(PHY_VARS_eNB *eNB, } phy_procedures_eNB_TX_fs6() { - receiveSubFrame(); // We got @@ -74,10 +70,10 @@ phy_procedures_eNB_TX_fs6() { for (aa = 0; aa < fp->nb_antenna_ports_eNB; aa++) { memset (&eNB->common_vars.txdataF[aa][subframe * fp->ofdm_symbol_size * fp->symbols_per_tti], - 0, - fp->ofdm_symbol_size * (fp->symbols_per_tti) * sizeof (int32_t)); + 0, + fp->ofdm_symbol_size * (fp->symbols_per_tti) * sizeof (int32_t)); } - + if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { if (is_pmch_subframe(frame,subframe,fp)) { pmch_procedures(eNB,proc); @@ -88,59 +84,60 @@ phy_procedures_eNB_TX_fs6() { } if (ul_subframe < 10)if (ul_subframe < 10) { // This means that there is a potential UL subframe that will be scheduled here - for (i=0; i= MAKE_VERSION(14, 0, 0)) - if (eNB->ulsch[i] && eNB->ulsch[i]->ue_type >0) harq_pid = 0; - else + if (eNB->ulsch[i] && eNB->ulsch[i]->ue_type >0) harq_pid = 0; + else #endif - harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe); + harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe); - if (eNB->ulsch[i]) { - ulsch_harq = eNB->ulsch[i]->harq_processes[harq_pid]; - /* Store first_rb and n_DMRS for correct PHICH generation below. - * For PHICH generation we need "old" values of last scheduling - * for this HARQ process. 'generate_eNB_dlsch_params' below will - * overwrite first_rb and n_DMRS and 'generate_phich_top', done - * after 'generate_eNB_dlsch_params', would use the "new" values - * instead of the "old" ones. - * - * This has been tested for FDD only, may be wrong for TDD. - * - * TODO: maybe we should restructure the code to be sure it - * is done correctly. The main concern is if the code - * changes and first_rb and n_DMRS are modified before - * we reach here, then the PHICH processing will be wrong, - * using wrong first_rb and n_DMRS values to compute - * ngroup_PHICH and nseq_PHICH. - * - * TODO: check if that works with TDD. - */ - ulsch_harq->previous_first_rb = ulsch_harq->first_rb; - ulsch_harq->previous_n_DMRS = ulsch_harq->n_DMRS; + if (eNB->ulsch[i]) { + ulsch_harq = eNB->ulsch[i]->harq_processes[harq_pid]; + /* Store first_rb and n_DMRS for correct PHICH generation below. + * For PHICH generation we need "old" values of last scheduling + * for this HARQ process. 'generate_eNB_dlsch_params' below will + * overwrite first_rb and n_DMRS and 'generate_phich_top', done + * after 'generate_eNB_dlsch_params', would use the "new" values + * instead of the "old" ones. + * + * This has been tested for FDD only, may be wrong for TDD. + * + * TODO: maybe we should restructure the code to be sure it + * is done correctly. The main concern is if the code + * changes and first_rb and n_DMRS are modified before + * we reach here, then the PHICH processing will be wrong, + * using wrong first_rb and n_DMRS values to compute + * ngroup_PHICH and nseq_PHICH. + * + * TODO: check if that works with TDD. + */ + ulsch_harq->previous_first_rb = ulsch_harq->first_rb; + ulsch_harq->previous_n_DMRS = ulsch_harq->n_DMRS; + } } } - } num_pdcch_symbols = eNB->pdcch_vars[subframe&1].num_pdcch_symbols; num_dci = eNB->pdcch_vars[subframe&1].num_dci; + if (num_dci > 0) if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { generate_dci_top(num_pdcch_symbols, - num_dci, - &eNB->pdcch_vars[subframe&1].dci_alloc[0], - 0, - AMP, - fp, - eNB->common_vars.txdataF, - subframe); + num_dci, + &eNB->pdcch_vars[subframe&1].dci_alloc[0], + 0, + AMP, + fp, + eNB->common_vars.txdataF, + subframe); num_mdci = eNB->mpdcch_vars[subframe &1].num_dci; - + if (num_mdci > 0) { - generate_mdci_top (eNB, frame, subframe, AMP, eNB->common_vars.txdataF); + generate_mdci_top (eNB, frame, subframe, AMP, eNB->common_vars.txdataF); } } - + // Now scan UE specific DLSCH LTE_eNB_DLSCH_t *dlsch0,*dlsch1; @@ -158,16 +155,16 @@ phy_procedures_eNB_TX_fs6() { if (harq_pid>=8) { if (dlsch0->ue_type==0) LOG_E(PHY,"harq_pid:%d corrupt must be 0-7 UE_id:%d frame:%d subframe:%d rnti:%x \n", - harq_pid,UE_id,frame,subframe,dlsch0->rnti); + harq_pid,UE_id,frame,subframe,dlsch0->rnti); } else { // generate pdsch pdsch_procedures_fs6(eNB, - proc, - harq_pid, - dlsch0, - dlsch1, - &eNB->UE_stats[(uint32_t)UE_id], - 0); + proc, + harq_pid, + dlsch0, + dlsch1, + &eNB->UE_stats[(uint32_t)UE_id], + 0); } } else if ((dlsch0)&&(dlsch0->rnti>0)&& (dlsch0->active == 0) @@ -176,10 +173,10 @@ phy_procedures_eNB_TX_fs6() { dlsch0->subframe_tx[subframe]=0; } } + generate_phich_top(eNB, proc, AMP); - } DL_thread_fs6() { @@ -194,5 +191,4 @@ DL_thread_fs6() { DL_thread_frequency() { frequency_t header; - - full_read(&header, + full_read(&header, \ No newline at end of file diff --git a/executables/simple_main.c b/executables/simple_main.c new file mode 100644 index 0000000000..04ab39e7a7 --- /dev/null +++ b/executables/simple_main.c @@ -0,0 +1,1121 @@ +/* + * Author: Laurent Thomas + * Copyright: Open Cells Project company + */ + +#include +static int DEFBANDS[] = {7}; +static int DEFENBS[] = {0}; +#include +#include +#include +#include +#include +#include +#include +#include +extern uint16_t sf_ahead; +extern void oai_subframe_ind(uint16_t sfn, uint16_t sf); +extern void fep_full(RU_t *ru); +extern void feptx_ofdm(RU_t *ru); +extern void feptx_prec(RU_t *ru); +extern void phy_init_RU(RU_t *); + +static void *ru_thread( void *param ); +void kill_RU_proc(RU_t *ru) { +} +void kill_eNB_proc(int inst) { +} +void free_transport(PHY_VARS_eNB *eNB) { +} +void reset_opp_meas(void) { +} + +void init_eNB_proc(int inst) { + /*int i=0;*/ + int CC_id; + PHY_VARS_eNB *eNB; + L1_proc_t *proc; + L1_rxtx_proc_t *L1_proc, *L1_proc_tx; + + for (CC_id=0; CC_idproc; + L1_proc = &proc->L1_proc; + L1_proc_tx = &proc->L1_proc_tx; + L1_proc->instance_cnt = -1; + L1_proc_tx->instance_cnt = -1; + L1_proc->instance_cnt_RUs = 0; + L1_proc_tx->instance_cnt_RUs = 0; + proc->instance_cnt_prach = -1; + proc->instance_cnt_asynch_rxtx = -1; + proc->instance_cnt_synch = -1; + proc->CC_id = CC_id; + proc->first_rx =1; + proc->first_tx =1; + proc->RU_mask_tx = (1<num_RU)-1; + proc->RU_mask =0; + proc->RU_mask_prach =0; + pthread_mutex_init( &eNB->UL_INFO_mutex, NULL); + pthread_mutex_init( &L1_proc->mutex, NULL); + pthread_mutex_init( &L1_proc_tx->mutex, NULL); + pthread_cond_init( &L1_proc->cond, NULL); + pthread_cond_init( &L1_proc_tx->cond, NULL); + pthread_mutex_init( &L1_proc->mutex_RUs, NULL); + pthread_mutex_init( &L1_proc_tx->mutex_RUs, NULL); + pthread_cond_init( &L1_proc->cond_RUs, NULL); + pthread_cond_init( &L1_proc_tx->cond_RUs, NULL); + pthread_mutex_init( &proc->mutex_prach, NULL); + pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL); + pthread_mutex_init( &proc->mutex_RU,NULL); + pthread_mutex_init( &proc->mutex_RU_tx,NULL); + pthread_mutex_init( &proc->mutex_RU_PRACH,NULL); + pthread_cond_init( &proc->cond_prach, NULL); + pthread_cond_init( &proc->cond_asynch_rxtx, NULL); + pthread_attr_init( &proc->attr_prach); + pthread_attr_init( &proc->attr_asynch_rxtx); + pthread_attr_init( &L1_proc->attr); + pthread_attr_init( &L1_proc_tx->attr); + proc->instance_cnt_prach_br = -1; + proc->RU_mask_prach_br=0; + pthread_mutex_init( &proc->mutex_prach_br, NULL); + pthread_mutex_init( &proc->mutex_RU_PRACH_br,NULL); + pthread_cond_init( &proc->cond_prach_br, NULL); + pthread_attr_init( &proc->attr_prach_br); + } + + //for multiple CCs: setup master and slaves + /* + for (CC_id=0; CC_idnode_timing == synch_to_ext_device) { //master + eNB->proc.num_slaves = MAX_NUM_CCs-1; + eNB->proc.slave_proc = (L1_proc_t**)malloc(eNB->proc.num_slaves*sizeof(L1_proc_t*)); + + for (i=0; i< eNB->proc.num_slaves; i++) { + if (i < CC_id) eNB->proc.slave_proc[i] = &(PHY_vars_eNB_g[inst][i]->proc); + if (i >= CC_id) eNB->proc.slave_proc[i] = &(PHY_vars_eNB_g[inst][i+1]->proc); + } + } + } + */ +} + +void init_RU_proc(RU_t *ru) { + int i=0; + RU_proc_t *proc; + pthread_attr_t *attr_FH=NULL; + //pthread_attr_t *attr_fep=NULL; + proc = &ru->proc; + memset((void *)proc,0,sizeof(RU_proc_t)); + proc->ru = ru; + proc->instance_cnt_prach = -1; + proc->instance_cnt_synch = -1; + proc->instance_cnt_FH = -1; + proc->instance_cnt_FH1 = -1; + proc->instance_cnt_emulateRF = -1; + proc->instance_cnt_asynch_rxtx = -1; + proc->instance_cnt_eNBs = -1; + proc->first_rx = 1; + proc->first_tx = 1; + proc->frame_offset = 0; + proc->num_slaves = 0; + proc->frame_tx_unwrap = 0; + + for (i=0; i<10; i++) proc->symbol_mask[i]=0; + + pthread_mutex_init( &proc->mutex_prach, NULL); + pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL); + pthread_mutex_init( &proc->mutex_synch,NULL); + pthread_mutex_init( &proc->mutex_FH,NULL); + pthread_mutex_init( &proc->mutex_FH1,NULL); + pthread_mutex_init( &proc->mutex_emulateRF,NULL); + pthread_mutex_init( &proc->mutex_eNBs, NULL); + pthread_cond_init( &proc->cond_prach, NULL); + pthread_cond_init( &proc->cond_FH, NULL); + pthread_cond_init( &proc->cond_FH1, NULL); + pthread_cond_init( &proc->cond_emulateRF, NULL); + pthread_cond_init( &proc->cond_asynch_rxtx, NULL); + pthread_cond_init( &proc->cond_synch,NULL); + pthread_cond_init( &proc->cond_eNBs, NULL); + pthread_attr_init( &proc->attr_FH); + pthread_attr_init( &proc->attr_FH1); + pthread_attr_init( &proc->attr_emulateRF); + pthread_attr_init( &proc->attr_prach); + pthread_attr_init( &proc->attr_synch); + pthread_attr_init( &proc->attr_asynch_rxtx); + pthread_attr_init( &proc->attr_fep); + proc->instance_cnt_prach_br = -1; + pthread_mutex_init( &proc->mutex_prach_br, NULL); + pthread_cond_init( &proc->cond_prach_br, NULL); + attr_FH = &proc->attr_FH; + pthread_create( &proc->pthread_FH, attr_FH, ru_thread, (void *)ru ); +} + +void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { + L1_proc_t *proc = &eNB->proc; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + + // check if we have to detect PRACH first + if (is_prach_subframe(fp,frame,subframe)>0) { + // set timing for prach thread + proc->frame_prach = frame; + proc->subframe_prach = subframe; + prach_procedures(eNB + ,0 + ); + } +} + +void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { + L1_proc_t *proc = &eNB->proc; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + + // check if we have to detect PRACH first + if (is_prach_subframe(fp,frame,subframe)>0) { + LOG_D(PHY,"Triggering prach br processing, frame %d, subframe %d\n",frame,subframe); + // set timing for prach thread + proc->frame_prach_br = frame; + proc->subframe_prach_br = subframe; + prach_procedures(eNB,1); + } +} + +static inline int wakeup_prach_ru(RU_t *ru) { + struct timespec wait; + wait.tv_sec=0; + wait.tv_nsec=5000000L; + + if (pthread_mutex_timedlock(&ru->proc.mutex_prach,&wait) !=0) { + LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for RU prach thread (IC %d)\n", ru->proc.instance_cnt_prach); + exit_fun( "error locking mutex_rxtx" ); + return(-1); + } + + if (ru->proc.instance_cnt_prach==-1) { + ++ru->proc.instance_cnt_prach; + ru->proc.frame_prach = ru->proc.frame_rx; + ru->proc.subframe_prach = ru->proc.subframe_rx; + + // DJP - think prach_procedures() is looking at eNB frame_prach + if (ru->eNB_list[0]) { + ru->eNB_list[0]->proc.frame_prach = ru->proc.frame_rx; + ru->eNB_list[0]->proc.subframe_prach = ru->proc.subframe_rx; + } + + LOG_D(PHY,"RU %d: waking up PRACH thread\n",ru->idx); + // the thread can now be woken up + AssertFatal(pthread_cond_signal(&ru->proc.cond_prach) == 0, "ERROR pthread_cond_signal for RU prach thread\n"); + } else LOG_W(PHY,"RU prach thread busy, skipping\n"); + + pthread_mutex_unlock( &ru->proc.mutex_prach ); + return(0); +} + +static inline int wakeup_prach_ru_br(RU_t *ru) { + struct timespec wait; + wait.tv_sec=0; + wait.tv_nsec=5000000L; + + if (pthread_mutex_timedlock(&ru->proc.mutex_prach_br,&wait) !=0) { + LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for RU prach thread BR (IC %d)\n", ru->proc.instance_cnt_prach_br); + exit_fun( "error locking mutex_rxtx" ); + return(-1); + } + + if (ru->proc.instance_cnt_prach_br==-1) { + ++ru->proc.instance_cnt_prach_br; + ru->proc.frame_prach_br = ru->proc.frame_rx; + ru->proc.subframe_prach_br = ru->proc.subframe_rx; + LOG_D(PHY,"RU %d: waking up PRACH thread\n",ru->idx); + // the thread can now be woken up + AssertFatal(pthread_cond_signal(&ru->proc.cond_prach_br) == 0, "ERROR pthread_cond_signal for RU prach thread BR\n"); + } else LOG_W(PHY,"RU prach thread busy, skipping\n"); + + pthread_mutex_unlock( &ru->proc.mutex_prach_br ); + return(0); +} + +static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name) { + //L1_rxtx_proc_t *L1_proc_tx = &eNB->proc.L1_proc_tx; + // ******************************************************************* + AssertFatal( eNB !=NULL, ""); + + if (NFAPI_MODE==NFAPI_MODE_PNF) { + // I am a PNF and I need to let nFAPI know that we have a (sub)frame tick + uint16_t frame = proc->frame_rx; + uint16_t subframe = proc->subframe_rx; + //add_subframe(&frame, &subframe, 4); + //oai_subframe_ind(proc->frame_tx, proc->subframe_tx); + //LOG_D(PHY, "oai_subframe_ind(frame:%u, subframe:%d) - NOT CALLED ********\n", frame, subframe); + oai_subframe_ind(frame, subframe); + } + + AssertFatal( !(NFAPI_MODE==NFAPI_MODE_PNF && eNB->pdcch_vars[proc->subframe_tx&1].num_pdcch_symbols == 0), ""); + wakeup_prach_eNB(eNB,NULL,proc->frame_rx,proc->subframe_rx); + wakeup_prach_eNB_br(eNB,NULL,proc->frame_rx,proc->subframe_rx); + release_UE_in_freeList(eNB->Mod_id); + + // UE-specific RX processing for subframe n + if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { + phy_procedures_eNB_uespec_RX(eNB, proc); + } + + pthread_mutex_lock(&eNB->UL_INFO_mutex); + eNB->UL_INFO.frame = proc->frame_rx; + eNB->UL_INFO.subframe = proc->subframe_rx; + eNB->UL_INFO.module_id = eNB->Mod_id; + eNB->UL_INFO.CC_id = eNB->CC_id; + eNB->if_inst->UL_indication(&eNB->UL_INFO); + pthread_mutex_unlock(&eNB->UL_INFO_mutex); + phy_procedures_eNB_TX(eNB, proc, 1); + return(0); +} + +void eNB_top(PHY_VARS_eNB *eNB, int frame_rx, int subframe_rx, char *string,RU_t *ru) { + L1_proc_t *proc = &eNB->proc; + L1_rxtx_proc_t *L1_proc = &proc->L1_proc; + LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; + RU_proc_t *ru_proc=&ru->proc; + proc->frame_rx = frame_rx; + 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)); + 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; + L1_proc->frame_tx = (L1_proc->subframe_rx > (9-sf_ahead)) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx; + L1_proc->subframe_tx = (L1_proc->subframe_rx + sf_ahead)%10; + + if (rxtx(eNB,L1_proc,string) < 0) LOG_E(PHY,"eNB %d CC_id %d failed during execution\n",eNB->Mod_id,eNB->CC_id); + + ru_proc->timestamp_tx = L1_proc->timestamp_tx; + ru_proc->subframe_tx = L1_proc->subframe_tx; + ru_proc->frame_tx = L1_proc->frame_tx; + } +} +void init_transport(PHY_VARS_eNB *eNB) { + int i; + int j; + LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; + LOG_I(PHY, "Initialise transport\n"); + + for (i=0; idlsch[i][j] = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL,0,fp); + + if (!eNB->dlsch[i][j]) { + LOG_E(PHY,"Can't get eNB dlsch structures for UE %d \n", i); + exit(-1); + } else { + eNB->dlsch[i][j]->rnti=0; + LOG_D(PHY,"dlsch[%d][%d] => %p rnti:%d\n",i,j,eNB->dlsch[i][j], eNB->dlsch[i][j]->rnti); + } + } + + LOG_D(PHY,"Allocating Transport Channel Buffer for ULSCH, UE %d\n",i); + eNB->ulsch[1+i] = new_eNB_ulsch(MAX_TURBO_ITERATIONS,fp->N_RB_UL, 0); + + if (!eNB->ulsch[1+i]) { + LOG_E(PHY,"Can't get eNB ulsch structures\n"); + exit(-1); + } + + // this is the transmission mode for the signalling channels + // this will be overwritten with the real transmission mode by the RRC once the UE is connected + eNB->transmission_mode[i] = fp->nb_antenna_ports_eNB==1 ? 1 : 2; + } + + // ULSCH for RA + eNB->ulsch[0] = new_eNB_ulsch(MAX_TURBO_ITERATIONS, fp->N_RB_UL, 0); + + if (!eNB->ulsch[0]) { + LOG_E(PHY,"Can't get eNB ulsch structures\n"); + exit(-1); + } + + eNB->dlsch_SI = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL, 0, fp); + LOG_D(PHY,"eNB %d.%d : SI %p\n",eNB->Mod_id,eNB->CC_id,eNB->dlsch_SI); + eNB->dlsch_ra = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL, 0, fp); + LOG_D(PHY,"eNB %d.%d : RA %p\n",eNB->Mod_id,eNB->CC_id,eNB->dlsch_ra); + eNB->dlsch_MCH = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL, 0, fp); + LOG_D(PHY,"eNB %d.%d : MCH %p\n",eNB->Mod_id,eNB->CC_id,eNB->dlsch_MCH); + eNB->rx_total_gain_dB=130; + + for(i=0; imu_mimo_mode[i].dl_pow_off = 2; + + eNB->check_for_total_transmissions = 0; + eNB->check_for_MUMIMO_transmissions = 0; + eNB->FULL_MUMIMO_transmissions = 0; + eNB->check_for_SUMIMO_transmissions = 0; + fp->pucch_config_common.deltaPUCCH_Shift = 1; +} + +void init_eNB_afterRU(void) { + int inst,CC_id,ru_id,i,aa; + PHY_VARS_eNB *eNB; + + for (inst=0; instframe_parms.nb_antennas_rx = 0; + eNB->prach_vars.rxsigF[0] = (int16_t **)malloc16(64*sizeof(int16_t *)); + + for (int ce_level=0; ce_level<4; ce_level++) { + LOG_I(PHY,"Overwriting eNB->prach_vars_br.rxsigF.rxsigF[0]:%p\n", eNB->prach_vars_br.rxsigF[ce_level]); + eNB->prach_vars_br.rxsigF[ce_level] = (int16_t **)malloc16(64*sizeof(int16_t *)); + } + + for (ru_id=0,aa=0; ru_idnum_RU; ru_id++) { + eNB->frame_parms.nb_antennas_rx += eNB->RU_list[ru_id]->nb_rx; + AssertFatal(eNB->RU_list[ru_id]->common.rxdataF!=NULL, + "RU %d : common.rxdataF is NULL\n", + eNB->RU_list[ru_id]->idx); + AssertFatal(eNB->RU_list[ru_id]->prach_rxsigF!=NULL, + "RU %d : prach_rxsigF is NULL\n", + eNB->RU_list[ru_id]->idx); + + for (i=0; iRU_list[ru_id]->nb_rx; aa++,i++) { + LOG_I(PHY,"Attaching RU %d antenna %d to eNB antenna %d\n",eNB->RU_list[ru_id]->idx,i,aa); + eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[ru_id]->prach_rxsigF[i]; + + for (int ce_level=0; ce_level<4; ce_level++) + eNB->prach_vars_br.rxsigF[ce_level][aa] = eNB->RU_list[ru_id]->prach_rxsigF_br[ce_level][i]; + + eNB->common_vars.rxdataF[aa] = eNB->RU_list[ru_id]->common.rxdataF[i]; + } + } + + /* TODO: review this code, there is something wrong. + * In monolithic mode, we come here with nb_antennas_rx == 0 + * (not tested in other modes). + */ + if (eNB->frame_parms.nb_antennas_rx < 1) { + LOG_I(PHY, "%s() ************* DJP ***** eNB->frame_parms.nb_antennas_rx:%d - GOING TO HARD CODE TO 1", __FUNCTION__, eNB->frame_parms.nb_antennas_rx); + eNB->frame_parms.nb_antennas_rx = 1; + } else { + //LOG_I(PHY," Delete code\n"); + } + + if (eNB->frame_parms.nb_antennas_tx < 1) { + LOG_I(PHY, "%s() ************* DJP ***** eNB->frame_parms.nb_antennas_tx:%d - GOING TO HARD CODE TO 1", __FUNCTION__, eNB->frame_parms.nb_antennas_tx); + eNB->frame_parms.nb_antennas_tx = 1; + } else { + //LOG_I(PHY," Delete code\n"); + } + + AssertFatal(eNB->frame_parms.nb_antennas_rx >0, + "inst %d, CC_id %d : nb_antennas_rx %d\n",inst,CC_id,eNB->frame_parms.nb_antennas_rx); + LOG_I(PHY,"inst %d, CC_id %d : nb_antennas_rx %d\n",inst,CC_id,eNB->frame_parms.nb_antennas_rx); + init_transport(eNB); + //init_precoding_weights(RC.eNB[inst][CC_id]); + } + + init_eNB_proc(inst); + } +} + +void init_eNB(int single_thread_flag,int wait_for_sync) { + int CC_id; + int inst; + PHY_VARS_eNB *eNB; + + if (RC.eNB == NULL) RC.eNB = (PHY_VARS_eNB ** *) malloc(RC.nb_L1_inst*sizeof(PHY_VARS_eNB **)); + + for (inst=0; instabstraction_flag = 0; + eNB->single_thread_flag = single_thread_flag; + AssertFatal((eNB->if_inst = IF_Module_init(inst))!=NULL,"Cannot register interface"); + eNB->if_inst->schedule_response = schedule_response; + eNB->if_inst->PHY_config_req = phy_config_request; + memset((void *)&eNB->UL_INFO,0,sizeof(eNB->UL_INFO)); + memset((void *)&eNB->Sched_INFO,0,sizeof(eNB->Sched_INFO)); + LOG_I(PHY,"Setting indication lists\n"); + eNB->UL_INFO.rx_ind.rx_indication_body.rx_pdu_list = eNB->rx_pdu_list; + eNB->UL_INFO.crc_ind.crc_indication_body.crc_pdu_list = eNB->crc_pdu_list; + eNB->UL_INFO.sr_ind.sr_indication_body.sr_pdu_list = eNB->sr_pdu_list; + eNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list = eNB->harq_pdu_list; + eNB->UL_INFO.cqi_ind.cqi_pdu_list = eNB->cqi_pdu_list; + eNB->UL_INFO.cqi_ind.cqi_raw_pdu_list = eNB->cqi_raw_pdu_list; + eNB->prach_energy_counter = 0; + } + } +} + +void stop_eNB(int nb_inst) { + for (int inst=0; instproc; + LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; + void *rxp[ru->nb_rx]; + unsigned int rxs; + int i; + openair0_timestamp ts=0,old_ts=0; + + for (i=0; inb_rx; i++) + rxp[i] = (void *)&ru->common.rxdata[i][*subframe*fp->samples_per_tti]; + + old_ts = proc->timestamp_rx; + rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, + &ts, + rxp, + fp->samples_per_tti, + ru->nb_rx); + proc->timestamp_rx = ts-ru->ts_offset; + + // AssertFatal(rxs == fp->samples_per_tti, + // "rx_rf: Asked for %d samples, got %d from SDR\n",fp->samples_per_tti,rxs); + if(rxs != fp->samples_per_tti) { + LOG_E(PHY,"rx_rf: Asked for %d samples, got %d from SDR\n",fp->samples_per_tti,rxs); + } + + if (proc->first_rx == 1) { + ru->ts_offset = proc->timestamp_rx; + proc->timestamp_rx = 0; + } else { + if (proc->timestamp_rx - old_ts != fp->samples_per_tti) { + //LOG_I(PHY,"rx_rf: rfdevice timing drift of %"PRId64" samples (ts_off %"PRId64")\n",proc->timestamp_rx - old_ts - fp->samples_per_tti,ru->ts_offset); + ru->ts_offset += (proc->timestamp_rx - old_ts - fp->samples_per_tti); + proc->timestamp_rx = ts-ru->ts_offset; + } + } + + proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; + proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; + // synchronize first reception to frame 0 subframe 0 + proc->timestamp_tx = proc->timestamp_rx+(sf_ahead*fp->samples_per_tti); + proc->subframe_tx = (proc->subframe_rx+sf_ahead)%10; + proc->frame_tx = (proc->subframe_rx>(9-sf_ahead)) ? (proc->frame_rx+1)&1023 : proc->frame_rx; + + if (proc->first_rx == 0) { + if (proc->subframe_rx != *subframe) { + LOG_E(PHY,"Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",(long long unsigned int)proc->timestamp_rx,proc->subframe_rx,*subframe); + exit_fun("Exiting"); + } + + if (proc->frame_rx != *frame) { + LOG_E(PHY,"Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",(long long unsigned int)proc->timestamp_rx,proc->frame_rx,*frame); + exit_fun("Exiting"); + } + } else { + proc->first_rx = 0; + *frame = proc->frame_rx; + *subframe = proc->subframe_rx; + } + + //printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",ru->timestamp_rx,proc->frame_rx,frame,proc->subframe_rx,subframe); + + if (rxs != fp->samples_per_tti) { +#if defined(USRP_REC_PLAY) + exit_fun("Exiting IQ record/playback"); +#else + //exit_fun( "problem receiving samples" ); + LOG_E(PHY, "problem receiving samples"); +#endif + } +} + + +void tx_rf(RU_t *ru) { + RU_proc_t *proc = &ru->proc; + LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; + void *txp[ru->nb_tx]; + int i; + lte_subframe_t SF_type = subframe_select(fp,proc->subframe_tx%10); + lte_subframe_t prevSF_type = subframe_select(fp,(proc->subframe_tx+9)%10); + int sf_extension = 0; + + if ((SF_type == SF_DL) || + (SF_type == SF_S)) { + int siglen=fp->samples_per_tti,flags=1; + + if (SF_type == SF_S) { + /* end_of_burst_delay is used to stop TX only "after a while". + * If we stop right after effective signal, with USRP B210 and + * B200mini, we observe a high EVM on the S subframe (on the + * PSS). + * A value of 400 (for 30.72MHz) solves this issue. This is + * the default. + */ + siglen = (fp->ofdm_symbol_size + fp->nb_prefix_samples0) + + (fp->dl_symbols_in_S_subframe - 1) * (fp->ofdm_symbol_size + fp->nb_prefix_samples) + + ru->end_of_burst_delay; + flags=3; // end of burst + } + + if (fp->frame_type == TDD && + SF_type == SF_DL && + prevSF_type == SF_UL) { + flags = 2; // start of burst + sf_extension = ru->sf_extension; + } + +#if defined(__x86_64) || defined(__i386__) +#ifdef __AVX2__ + sf_extension = (sf_extension)&0xfffffff8; +#else + sf_extension = (sf_extension)&0xfffffffc; +#endif +#elif defined(__arm__) + sf_extension = (sf_extension)&0xfffffffc; +#endif + + for (i=0; inb_tx; i++) + txp[i] = (void *)&ru->common.txdata[i][(proc->subframe_tx*fp->samples_per_tti)-sf_extension]; + + /* add fail safe for late command end */ + // prepare tx buffer pointers + ru->rfdevice.trx_write_func(&ru->rfdevice, + proc->timestamp_tx+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension, + txp, + siglen+sf_extension, + ru->nb_tx, + flags); + LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, subframe %d\n",ru->idx, + (long long unsigned int)proc->timestamp_tx,proc->frame_tx,proc->frame_tx_unwrap,proc->subframe_tx); + } +} +// this is for RU with local RF unit +void fill_rf_config(RU_t *ru, char *rf_config_file) { + int i; + LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; + openair0_config_t *cfg = &ru->openair0_cfg; + //printf("////////////////numerology in config = %d\n",numerology); + int numerology = get_softmodem_params()->numerology; + + if(fp->N_RB_DL == 100) { + if(numerology == 0) { + if (fp->threequarter_fs) { + cfg->sample_rate=23.04e6; + cfg->samples_per_frame = 230400; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } else { + cfg->sample_rate=30.72e6; + cfg->samples_per_frame = 307200; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } + } else if(numerology == 1) { + cfg->sample_rate=61.44e6; + cfg->samples_per_frame = 307200; + cfg->tx_bw = 20e6; + cfg->rx_bw = 20e6; + } else if(numerology == 2) { + cfg->sample_rate=122.88e6; + cfg->samples_per_frame = 307200; + cfg->tx_bw = 40e6; + cfg->rx_bw = 40e6; + } else { + printf("Wrong input for numerology %d\n setting to 20MHz normal CP configuration",numerology); + cfg->sample_rate=30.72e6; + cfg->samples_per_frame = 307200; + cfg->tx_bw = 10e6; + cfg->rx_bw = 10e6; + } + } else if(fp->N_RB_DL == 50) { + cfg->sample_rate=15.36e6; + cfg->samples_per_frame = 153600; + cfg->tx_bw = 5e6; + cfg->rx_bw = 5e6; + } else if (fp->N_RB_DL == 25) { + cfg->sample_rate=7.68e6; + cfg->samples_per_frame = 76800; + cfg->tx_bw = 2.5e6; + cfg->rx_bw = 2.5e6; + } else if (fp->N_RB_DL == 6) { + cfg->sample_rate=1.92e6; + cfg->samples_per_frame = 19200; + cfg->tx_bw = 1.5e6; + cfg->rx_bw = 1.5e6; + } else AssertFatal(1==0,"Unknown N_RB_DL %d\n",fp->N_RB_DL); + + if (fp->frame_type==TDD) + cfg->duplex_mode = duplex_mode_TDD; + else //FDD + cfg->duplex_mode = duplex_mode_FDD; + + cfg->Mod_id = 0; + cfg->num_rb_dl=fp->N_RB_DL; + cfg->tx_num_channels=ru->nb_tx; + cfg->rx_num_channels=ru->nb_rx; + cfg->clock_source=get_softmodem_params()->clock_source; + + for (i=0; inb_tx; i++) { + cfg->tx_freq[i] = (double)fp->dl_CarrierFreq; + cfg->rx_freq[i] = (double)fp->ul_CarrierFreq; + cfg->tx_gain[i] = (double)ru->att_tx; + cfg->rx_gain[i] = ru->max_rxgain-(double)ru->att_rx; + cfg->configFilename = rf_config_file; + printf("channel %d, Setting tx_gain offset %f, rx_gain offset %f, tx_freq %f, rx_freq %f\n", + i, cfg->tx_gain[i], + cfg->rx_gain[i], + cfg->tx_freq[i], + cfg->rx_freq[i]); + } +} + +/* this function maps the RU tx and rx buffers to the available rf chains. + Each rf chain is is addressed by the card number and the chain on the card. The + rf_map specifies for each antenna port, on which rf chain the mapping should start. Multiple + antennas are mapped to successive RF chains on the same card. */ +int setup_RU_buffers(RU_t *ru) { + int i,j; + int card,ant; + //uint16_t N_TA_offset = 0; + LTE_DL_FRAME_PARMS *frame_parms; + + if (ru) { + frame_parms = &ru->frame_parms; + printf("setup_RU_buffers: frame_parms = %p\n",frame_parms); + } else { + printf("RU not initialized (NULL pointer)\n"); + return(-1); + } + + if (frame_parms->frame_type == TDD) { + if (frame_parms->N_RB_DL == 100) ru->N_TA_offset = 624; + else if (frame_parms->N_RB_DL == 50) ru->N_TA_offset = 624/2; + else if (frame_parms->N_RB_DL == 25) ru->N_TA_offset = 624/4; + + if(IS_SOFTMODEM_BASICSIM) + /* this is required for the basic simulator in TDD mode + * TODO: find a proper cleaner solution + */ + ru->N_TA_offset = 0; + + if (frame_parms->N_RB_DL == 100) /* no scaling to do */; + else if (frame_parms->N_RB_DL == 50) { + ru->sf_extension /= 2; + ru->end_of_burst_delay /= 2; + } else if (frame_parms->N_RB_DL == 25) { + ru->sf_extension /= 4; + ru->end_of_burst_delay /= 4; + } else { + printf("not handled, todo\n"); + exit(1); + } + } else { + ru->N_TA_offset = 0; + ru->sf_extension = 0; + ru->end_of_burst_delay = 0; + } + + if (ru->openair0_cfg.mmapped_dma == 1) { + // replace RX signal buffers with mmaped HW versions + for (i=0; inb_rx; i++) { + card = i/4; + ant = i%4; + printf("Mapping RU id %d, rx_ant %d, on card %d, chain %d\n",ru->idx,i,ru->rf_map.card+card, ru->rf_map.chain+ant); + free(ru->common.rxdata[i]); + ru->common.rxdata[i] = ru->openair0_cfg.rxbase[ru->rf_map.chain+ant]; + printf("rxdata[%d] @ %p\n",i,ru->common.rxdata[i]); + + for (j=0; j<16; j++) { + printf("rxbuffer %d: %x\n",j,ru->common.rxdata[i][j]); + ru->common.rxdata[i][j] = 16-j; + } + } + + for (i=0; inb_tx; i++) { + card = i/4; + ant = i%4; + printf("Mapping RU id %d, tx_ant %d, on card %d, chain %d\n",ru->idx,i,ru->rf_map.card+card, ru->rf_map.chain+ant); + free(ru->common.txdata[i]); + ru->common.txdata[i] = ru->openair0_cfg.txbase[ru->rf_map.chain+ant]; + printf("txdata[%d] @ %p\n",i,ru->common.txdata[i]); + + for (j=0; j<16; j++) { + printf("txbuffer %d: %x\n",j,ru->common.txdata[i][j]); + ru->common.txdata[i][j] = 16-j; + } + } + } else { // not memory-mapped DMA + //nothing to do, everything already allocated in lte_init + } + + return(0); +} +static void *ru_thread( void *param ) { + static int ru_thread_status; + RU_t *ru = (RU_t *)param; + RU_proc_t *proc = &ru->proc; + int subframe =9; + int frame =1023; + // set default return value + ru_thread_status = 0; + + if (ru->if_south == LOCAL_RF) { // configure RF parameters only + fill_rf_config(ru,ru->rf_config_file); + init_frame_parms(&ru->frame_parms,1); + phy_init_RU(ru); + openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); + } + + if (setup_RU_buffers(ru)!=0) { + printf("Exiting, cannot initialize RU Buffers\n"); + exit(-1); + } + + LOG_I(PHY, "Signaling main thread that RU %d is ready\n",ru->idx); + pthread_mutex_lock(&RC.ru_mutex); + RC.ru_mask &= ~(1<idx); + pthread_cond_signal(&RC.ru_cond); + pthread_mutex_unlock(&RC.ru_mutex); + pthread_mutex_lock(&proc->mutex_FH1); + proc->instance_cnt_FH1 = 0; + pthread_mutex_unlock(&proc->mutex_FH1); + pthread_cond_signal(&proc->cond_FH1); + wait_sync("ru_thread"); + + // Start RF device if any + if (ru->start_rf) { + if (ru->start_rf(ru) != 0) + LOG_E(HW,"Could not start the RF device\n"); + else LOG_I(PHY,"RU %d rf device ready\n",ru->idx); + } else LOG_I(PHY,"RU %d no rf device\n",ru->idx); + + // if an asnych_rxtx thread exists + // wakeup the thread because the devices are ready at this point + + if ((ru->fh_south_asynch_in)||(ru->fh_north_asynch_in)) { + pthread_mutex_lock(&proc->mutex_asynch_rxtx); + proc->instance_cnt_asynch_rxtx=0; + pthread_mutex_unlock(&proc->mutex_asynch_rxtx); + pthread_cond_signal(&proc->cond_asynch_rxtx); + } else LOG_I(PHY,"RU %d no asynch_south interface\n",ru->idx); + + // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices + while (!oai_exit) { + // these are local subframe/frame counters to check that we are in synch with the fronthaul timing. + // They are set on the first rx/tx in the underly FH routines. + if (subframe==9) { + subframe=0; + frame++; + frame&=1023; + } else { + subframe++; + } + + // synchronization on input FH interface, acquire signals/data and block + AssertFatal(ru->fh_south_in, "No fronthaul interface at south port"); + ru->fh_south_in(ru,&frame,&subframe); + + // adjust for timing offset between RU + if (ru->idx!=0) proc->frame_tx = (proc->frame_tx+proc->frame_offset)&1023; + + // do RX front-end processing (frequency-shift, dft) if needed + if (ru->feprx) ru->feprx(ru); + + // At this point, all information for subframe has been received on FH interface + // If this proc is to provide synchronization, do so + // Fixme: not used + // wakeup_slaves(proc); + for (int i=0; inum_eNB; i++) { + char string[20]; + sprintf(string,"Incoming RU %d",ru->idx); + ru->eNB_top(ru->eNB_list[i],ru->proc.frame_rx,ru->proc.subframe_rx,string,ru); + } + + // do TX front-end processing if needed (precoding and/or IDFTs) + if (ru->feptx_prec) ru->feptx_prec(ru); + + // do OFDM if needed + if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru); + + // do outgoing fronthaul (south) if needed + if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru); + + if (ru->fh_north_out) ru->fh_north_out(ru); + } + + printf( "Exiting ru_thread \n"); + + if (ru->stop_rf != NULL) { + if (ru->stop_rf(ru) != 0) + LOG_E(HW,"Could not stop the RF device\n"); + else LOG_I(PHY,"RU %d rf device stopped\n",ru->idx); + } + + ru_thread_status = 0; + return &ru_thread_status; +} +int start_if(struct RU_t_s *ru,struct PHY_VARS_eNB_s *eNB) { + return(ru->ifdevice.trx_start_func(&ru->ifdevice)); +} + +int start_rf(RU_t *ru) { + return(ru->rfdevice.trx_start_func(&ru->rfdevice)); +} + +int stop_rf(RU_t *ru) { + ru->rfdevice.trx_end_func(&ru->rfdevice); + return 0; +} +void init_precoding_weights(PHY_VARS_eNB *eNB) { + int layer,ru_id,aa,re,ue,tb; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + RU_t *ru; + LTE_eNB_DLSCH_t *dlsch; + + // init precoding weigths + for (ue=0; uedlsch[ue][tb]; + + for (layer=0; layer<4; layer++) { + int nb_tx=0; + + for (ru_id=0; ru_idnb_tx; + } + + dlsch->ue_spec_bf_weights[layer] = (int32_t **)malloc16(nb_tx*sizeof(int32_t *)); + + for (aa=0; aaue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(fp->ofdm_symbol_size*sizeof(int32_t)); + + for (re=0; reofdm_symbol_size; re++) { + dlsch->ue_spec_bf_weights[layer][aa][re] = 0x00007fff; + } + } + } + } + } +} + +void set_function_spec_param(RU_t *ru) { + + switch (ru->if_south) { + case LOCAL_RF: { // this is an RU with integrated RF (RRU, eNB) + ru->do_prach = 0; // no prach processing in RU + ru->feprx = fep_full; + ru->feptx_ofdm = feptx_ofdm; + ru->feptx_prec = feptx_prec; // this is fep with idft and precoding + ru->fh_north_in = NULL; // no incoming fronthaul from north + ru->fh_north_out = NULL; // no outgoing fronthaul to north + ru->start_if = NULL; // no if interface + ru->rfdevice.host_type = RAU_HOST; + } + + ru->fh_south_in = rx_rf; // local synchronous RF RX + ru->fh_south_out = tx_rf; // local synchronous RF TX + ru->start_rf = start_rf; // need to start the local RF interface + ru->stop_rf = stop_rf; + ru->eNB_top=eNB_top; + printf("configuring ru_id %d (start_rf %p)\n", ru->idx, start_rf); + /* + if (ru->function == eNodeB_3GPP) { // configure RF parameters only for 3GPP eNodeB, we need to get them from RAU otherwise + fill_rf_config(ru,rf_config_file); + init_frame_parms(&ru->frame_parms,1); + phy_init_RU(ru); + } + + ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); + if (setup_RU_buffers(ru)!=0) { + printf("Exiting, cannot initialize RU Buffers\n"); + exit(-1); + }*/ + break; + + default: + LOG_E(PHY,"RU with invalid or unknown southbound interface type %d\n",ru->if_south); + break; + } // switch on interface type +} + +//extern void RCconfig_RU(void); + +void init_RU(char *rf_config_file) { + int ru_id; + RU_t *ru; + PHY_VARS_eNB *eNB0= (PHY_VARS_eNB *)NULL; + int i; + int CC_id; + // create status mask + RC.ru_mask = 0; + pthread_mutex_init(&RC.ru_mutex,NULL); + pthread_cond_init(&RC.ru_cond,NULL); + // read in configuration file) + printf("configuring RU from file\n"); + RCconfig_RU(); + LOG_I(PHY,"number of L1 instances %d, number of RU %d, number of CPU cores %d\n",RC.nb_L1_inst,RC.nb_RU,get_nprocs()); + + if (RC.nb_CC != 0) + for (i=0; inum_RU=0; + + LOG_D(PHY,"Process RUs RC.nb_RU:%d\n",RC.nb_RU); + + for (ru_id=0; ru_idrf_config_file = rf_config_file; + ru->idx = ru_id; + ru->ts_offset = 0; + // use eNB_list[0] as a reference for RU frame parameters + // NOTE: multiple CC_id are not handled here yet! + + if (ru->num_eNB > 0) { + LOG_D(PHY, "%s() RC.ru[%d].num_eNB:%d ru->eNB_list[0]:%p RC.eNB[0][0]:%p rf_config_file:%s\n", __FUNCTION__, ru_id, ru->num_eNB, ru->eNB_list[0], RC.eNB[0][0], ru->rf_config_file); + + if (ru->eNB_list[0] == 0) { + LOG_E(PHY,"%s() DJP - ru->eNB_list ru->num_eNB are not initialized - so do it manually\n", __FUNCTION__); + ru->eNB_list[0] = RC.eNB[0][0]; + ru->num_eNB=1; + // + // DJP - feptx_prec() / feptx_ofdm() parses the eNB_list (based on num_eNB) and copies the txdata_F to txdata in RU + // + } else { + LOG_E(PHY,"DJP - delete code above this %s:%d\n", __FILE__, __LINE__); + } + } + + eNB0 = ru->eNB_list[0]; + LOG_D(PHY, "RU FUnction:%d ru->if_south:%d\n", ru->function, ru->if_south); + LOG_D(PHY, "eNB0:%p\n", eNB0); + + if (eNB0) { + if ((ru->function != NGFI_RRU_IF5) && (ru->function != NGFI_RRU_IF4p5)) + AssertFatal(eNB0!=NULL,"eNB0 is null!\n"); + + if (eNB0) { + LOG_I(PHY,"Copying frame parms from eNB %d to ru %d\n",eNB0->Mod_id,ru->idx); + memcpy((void *)&ru->frame_parms,(void *)&eNB0->frame_parms,sizeof(LTE_DL_FRAME_PARMS)); + // attach all RU to all eNBs in its list/ + LOG_D(PHY,"ru->num_eNB:%d eNB0->num_RU:%d\n", ru->num_eNB, eNB0->num_RU); + + for (i=0; inum_eNB; i++) { + eNB0 = ru->eNB_list[i]; + eNB0->RU_list[eNB0->num_RU++] = ru; + } + } + } + + LOG_I(PHY,"Initializing RRU descriptor %d : (%s,%s,%d)\n",ru_id,ru_if_types[ru->if_south],eNB_timing[ru->if_timing],ru->function); + set_function_spec_param(ru); + LOG_I(PHY,"Starting ru_thread %d\n",ru_id); + init_RU_proc(ru); + } // for ru_id + + // sleep(1); + LOG_D(HW,"[lte-softmodem.c] RU threads created\n"); +} + +void stop_RU(int nb_ru) { + for (int inst = 0; inst < nb_ru; inst++) { + LOG_I(PHY, "Stopping RU %d processing threads\n", inst); + kill_RU_proc(RC.ru[inst]); + } +} +/* --------------------------------------------------------*/ +/* from here function to use configuration module */ +void RCconfig_RU(void) { + int j = 0; + int i = 0; + paramdef_t RUParams[] = RUPARAMS_DESC; + paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0}; + config_getlist( &RUParamList,RUParams,sizeof(RUParams)/sizeof(paramdef_t), NULL); + + if ( RUParamList.numelt > 0) { + RC.ru = (RU_t **)malloc(RC.nb_RU*sizeof(RU_t *)); + RC.ru_mask=(1<idx = j; + printf("Creating RC.ru[%d]:%p\n", j, RC.ru[j]); + RC.ru[j]->if_timing = synch_to_ext_device; + + if (RC.nb_L1_inst >0) + RC.ru[j]->num_eNB = RUParamList.paramarray[j][RU_ENB_LIST_IDX].numelt; + else + RC.ru[j]->num_eNB = 0; + + for (i=0; inum_eNB; i++) RC.ru[j]->eNB_list[i] = RC.eNB[RUParamList.paramarray[j][RU_ENB_LIST_IDX].iptr[i]][0]; + + if (config_isparamset(RUParamList.paramarray[j], RU_SDR_ADDRS)) { + RC.ru[j]->openair0_cfg.sdr_addrs = strdup(*(RUParamList.paramarray[j][RU_SDR_ADDRS].strptr)); + } + + if (config_isparamset(RUParamList.paramarray[j], RU_SDR_CLK_SRC)) { + if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "internal") == 0) { + RC.ru[j]->openair0_cfg.clock_source = internal; + LOG_D(PHY, "RU clock source set as internal\n"); + } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "external") == 0) { + RC.ru[j]->openair0_cfg.clock_source = external; + LOG_D(PHY, "RU clock source set as external\n"); + } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "gpsdo") == 0) { + RC.ru[j]->openair0_cfg.clock_source = gpsdo; + LOG_D(PHY, "RU clock source set as gpsdo\n"); + } else { + LOG_E(PHY, "Erroneous RU clock source in the provided configuration file: '%s'\n", *(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr)); + } + } + + if (strcmp(*(RUParamList.paramarray[j][RU_LOCAL_RF_IDX].strptr), "yes") == 0) { + if ( !(config_isparamset(RUParamList.paramarray[j],RU_LOCAL_IF_NAME_IDX)) ) { + RC.ru[j]->if_south = LOCAL_RF; + RC.ru[j]->function = eNodeB_3GPP; + printf("Setting function for RU %d to eNodeB_3GPP\n",j); + } else { + RC.ru[j]->eth_params.local_if_name = strdup(*(RUParamList.paramarray[j][RU_LOCAL_IF_NAME_IDX].strptr)); + RC.ru[j]->eth_params.my_addr = strdup(*(RUParamList.paramarray[j][RU_LOCAL_ADDRESS_IDX].strptr)); + RC.ru[j]->eth_params.remote_addr = strdup(*(RUParamList.paramarray[j][RU_REMOTE_ADDRESS_IDX].strptr)); + RC.ru[j]->eth_params.my_portc = *(RUParamList.paramarray[j][RU_LOCAL_PORTC_IDX].uptr); + RC.ru[j]->eth_params.remote_portc = *(RUParamList.paramarray[j][RU_REMOTE_PORTC_IDX].uptr); + RC.ru[j]->eth_params.my_portd = *(RUParamList.paramarray[j][RU_LOCAL_PORTD_IDX].uptr); + RC.ru[j]->eth_params.remote_portd = *(RUParamList.paramarray[j][RU_REMOTE_PORTD_IDX].uptr); + } + + RC.ru[j]->max_pdschReferenceSignalPower = *(RUParamList.paramarray[j][RU_MAX_RS_EPRE_IDX].uptr);; + RC.ru[j]->max_rxgain = *(RUParamList.paramarray[j][RU_MAX_RXGAIN_IDX].uptr); + RC.ru[j]->num_bands = RUParamList.paramarray[j][RU_BAND_LIST_IDX].numelt; + /* sf_extension is in unit of samples for 30.72MHz here, has to be scaled later */ + RC.ru[j]->sf_extension = *(RUParamList.paramarray[j][RU_SF_EXTENSION_IDX].uptr); + RC.ru[j]->end_of_burst_delay = *(RUParamList.paramarray[j][RU_END_OF_BURST_DELAY_IDX].uptr); + + for (i=0; inum_bands; i++) RC.ru[j]->band[i] = RUParamList.paramarray[j][RU_BAND_LIST_IDX].iptr[i]; + } //strcmp(local_rf, "yes") == 0 + else { + printf("RU %d: Transport %s\n",j,*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr)); + RC.ru[j]->eth_params.local_if_name = strdup(*(RUParamList.paramarray[j][RU_LOCAL_IF_NAME_IDX].strptr)); + RC.ru[j]->eth_params.my_addr = strdup(*(RUParamList.paramarray[j][RU_LOCAL_ADDRESS_IDX].strptr)); + RC.ru[j]->eth_params.remote_addr = strdup(*(RUParamList.paramarray[j][RU_REMOTE_ADDRESS_IDX].strptr)); + RC.ru[j]->eth_params.my_portc = *(RUParamList.paramarray[j][RU_LOCAL_PORTC_IDX].uptr); + RC.ru[j]->eth_params.remote_portc = *(RUParamList.paramarray[j][RU_REMOTE_PORTC_IDX].uptr); + RC.ru[j]->eth_params.my_portd = *(RUParamList.paramarray[j][RU_LOCAL_PORTD_IDX].uptr); + RC.ru[j]->eth_params.remote_portd = *(RUParamList.paramarray[j][RU_REMOTE_PORTD_IDX].uptr); + } /* strcmp(local_rf, "yes") != 0 */ + + RC.ru[j]->nb_tx = *(RUParamList.paramarray[j][RU_NB_TX_IDX].uptr); + RC.ru[j]->nb_rx = *(RUParamList.paramarray[j][RU_NB_RX_IDX].uptr); + RC.ru[j]->att_tx = *(RUParamList.paramarray[j][RU_ATT_TX_IDX].uptr); + RC.ru[j]->att_rx = *(RUParamList.paramarray[j][RU_ATT_RX_IDX].uptr); + }// j=0..num_rus + } else { + RC.nb_RU = 0; + } // setting != NULL + + return; +} diff --git a/executables/transport_split.c b/executables/transport_split.c index a1e0738458..fe9e1a419c 100644 --- a/executables/transport_split.c +++ b/executables/transport_split.c @@ -3,63 +3,70 @@ int createListner (port) { int sock; AssertFatal((sock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) >= 0, ""); - struct sockaddr_in addr = { + struct sockaddr_in addr = { sin_family: AF_INET, sin_port: -htons(port), + htons(port), sin_addr: { s_addr: INADDR_ANY } - }; - int enable=1; - AssertFatal(setsockopt(eth->sockfdc, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable))==0,""); - AssertFatal(bind(sock, const struct sockaddr *addr, socklen_t addrlen)==0,""); - struct timeval tv={0,UDP_TIMEOUT}; - AssertFatal(setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(tv)) ==0,""); - // Make a send/recv buffer larger than a a couple of subframe - // so the kernel will store for us in and out paquets - int buff=1000*1000*10; - AssertFatal ( setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &buff, sizeof(buff)) == 0, ""); - AssertFatal ( setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &buff, sizeof(buff)) == 0, ""); + }; + int enable=1; + AssertFatal(setsockopt(eth->sockfdc, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable))==0,""); + AssertFatal(bind(sock, const struct sockaddr *addr, socklen_t addrlen)==0,""); + struct timeval tv= {0,UDP_TIMEOUT}; + AssertFatal(setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(tv)) ==0,""); + // Make a send/recv buffer larger than a a couple of subframe + // so the kernel will store for us in and out paquets + int buff=1000*1000*10; + AssertFatal ( setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &buff, sizeof(buff)) == 0, ""); + AssertFatal ( setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &buff, sizeof(buff)) == 0, ""); } // sock: udp socket // expectedTS: the expected timestamp, 0 if unknown // bufferZone: a reception area of bufferSize -int receiveSubFrame(int sock, uint64_t expectedTS, void* bufferZone, int bufferSize) { +int receiveSubFrame(int sock, uint64_t expectedTS, void *bufferZone, int bufferSize) { int rcved=0; + do { //read all subframe data from the control unit int ret=recv(sock, bufferZone, bufferSize, 0); + if ( ret==-1) { if ( errno == EWOULDBLOCK || errno== EINTR ) { - return rcved; // Timeout, subframe incomplete + return rcved; // Timeout, subframe incomplete } else { - LOG_E(HW,"Critical issue in socket: %s\n", strerror(errno)); - return -1; + LOG_E(HW,"Critical issue in socket: %s\n", strerror(errno)); + return -1; } } else { - commonUDP_t * tmp=(commonUDP_t *)bufferZone; + commonUDP_t *tmp=(commonUDP_t *)bufferZone; + if ( expectedTS && tmp->timestamp != expectedTS) { - LOG_W(HW,"Received a paquet in mixed subframes, dropping it\n"); + LOG_W(HW,"Received a paquet in mixed subframes, dropping it\n"); } else { - rcved++; - bufferZone+=ret; + rcved++; + bufferZone+=ret; } } } while ( !recved || recved < tmp->nbBlocks); + return recv; } -int sendSubFrame(int sock, void* bufferZone, int nbBlocks) { +int sendSubFrame(int sock, void *bufferZone, int nbBlocks) { do { int sz=alignedSize(bufferZone); int ret=send(sock, bufferZone, sz, 0); + if ( ret != sz ) LOG_W(HW,"Wrote socket doesn't return size %d (val: %d, errno:%d)\n", - sz, ret, errno); + sz, ret, errno); + bufferZone+=sz; nbBlocks--; } while (nbBlocks); + return 0; } diff --git a/targets/ARCH/rfsimulator/simulator.c b/targets/ARCH/rfsimulator/simulator.c index e81e958184..1bb424d115 100644 --- a/targets/ARCH/rfsimulator/simulator.c +++ b/targets/ARCH/rfsimulator/simulator.c @@ -135,9 +135,6 @@ void rxAddInput( struct complex16 *input_sig, struct complex16 *after_channel_si } 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++; } diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 8ae3d8956c..b9c6b19f11 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -1146,7 +1146,7 @@ void init_eNB_afterRU(void) { for (CC_id=0; CC_idmutex_FH,&wait) != 0) { - LOG_E( PHY, "ERROR pthread_mutex_lock for RU %d slave %d (IC %d)\n",proc->ru->idx,slave_proc->ru->idx,slave_proc->instance_cnt_FH); - exit_fun( "error locking mutex_rxtx" ); - break; - } + AssertFatal(pthread_mutex_timedlock(&slave_proc->mutex_FH,&wait) == 0, + "ERROR pthread_mutex_lock for RU %d slave %d (IC %d)\n", + proc->ru->idx,slave_proc->ru->idx,slave_proc->instance_cnt_FH); int cnt_slave = ++slave_proc->instance_cnt_FH; slave_proc->frame_rx = proc->frame_rx; @@ -1628,7 +1626,6 @@ static void *ru_thread( void *param ) { pthread_cond_signal(&proc->cond_FH1); wait_sync("ru_thread"); - if(!(get_softmodem_params()->emulate_rf)) { // Start RF device if any if (ru->start_rf) { if (ru->start_rf(ru) != 0) @@ -1648,12 +1645,9 @@ static void *ru_thread( void *param ) { // if this is a slave RRU, try to synchronize on the DL frequency if ((ru->is_slave) && (ru->if_south == LOCAL_RF)) do_ru_synch(ru); - } // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices while (!oai_exit) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_CPUID_RU_THREAD,sched_getcpu()); - LOG_ENTER(PHY); // these are local subframe/frame counters to check that we are in synch with the fronthaul timing. // They are set on the first rx/tx in the underly FH routines. if (subframe==9) { @@ -1665,37 +1659,9 @@ static void *ru_thread( void *param ) { } // synchronization on input FH interface, acquire signals/data and block - if (ru->fh_south_in) ru->fh_south_in(ru,&frame,&subframe); - else AssertFatal(1==0, "No fronthaul interface at south port"); + AssertFatal(ru->fh_south_in, "No fronthaul interface at south port"); + ru->fh_south_in(ru,&frame,&subframe); -#ifdef PHY_TX_THREAD - - if(first_phy_tx == 0) { - phy_tx_end = 0; - phy_tx_txdataF_end = 0; - - if(pthread_mutex_lock(&ru->proc.mutex_phy_tx) != 0) { - LOG_E( PHY, "[RU] ERROR pthread_mutex_lock for phy tx thread (IC %d)\n", ru->proc.instance_cnt_phy_tx); - exit_fun( "error locking mutex_rxtx" ); - } - - if (ru->proc.instance_cnt_phy_tx==-1) { - ++ru->proc.instance_cnt_phy_tx; - // the thread can now be woken up - AssertFatal(pthread_cond_signal(&ru->proc.cond_phy_tx) == 0, "ERROR pthread_cond_signal for phy_tx thread\n"); - } else { - LOG_E(PHY,"phy tx thread busy, skipping\n"); - ++ru->proc.instance_cnt_phy_tx; - } - - pthread_mutex_unlock( &ru->proc.mutex_phy_tx ); - } else { - phy_tx_end = 1; - phy_tx_txdataF_end = 1; - } - - first_phy_tx = 0; -#endif LOG_D(PHY,"RU thread (do_prach %d, is_prach_subframe %d), received frame %d, subframe %d\n", ru->do_prach, is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx), @@ -1720,72 +1686,26 @@ static void *ru_thread( void *param ) { // At this point, all information for subframe has been received on FH interface // If this proc is to provide synchronization, do so - wakeup_slaves(proc); -#if defined(PRE_SCD_THREAD) - new_dlsch_ue_select_tbl_in_use = dlsch_ue_select_tbl_in_use; - dlsch_ue_select_tbl_in_use = !dlsch_ue_select_tbl_in_use; - memcpy(&pre_scd_eNB_UE_stats,&RC.mac[ru->eNB_list[0]->Mod_id]->UE_list.eNB_UE_stats, sizeof(eNB_UE_STATS)*MAX_NUM_CCs*NUMBER_OF_UE_MAX); - memcpy(&pre_scd_activeUE, &RC.mac[ru->eNB_list[0]->Mod_id]->UE_list.active, sizeof(boolean_t)*NUMBER_OF_UE_MAX); - - if (pthread_mutex_lock(&ru->proc.mutex_pre_scd)!= 0) { - LOG_E( PHY, "[eNB] error locking proc mutex for eNB pre scd\n"); - exit_fun("error locking mutex_time"); + // Fixme: not used + // wakeup_slaves(proc); + for (int i=0; inum_eNB; i++) { + char string[20]; + sprintf(string,"Incoming RU %d",ru->idx); + ru->eNB_top(ru->eNB_list[i],ru->proc.frame_rx,ru->proc.subframe_rx,string,ru); } - - ru->proc.instance_pre_scd++; - - if (ru->proc.instance_pre_scd == 0) { - if (pthread_cond_signal(&ru->proc.cond_pre_scd) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB pre scd\n" ); - exit_fun( "ERROR pthread_cond_signal cond_pre_scd" ); - } - } else { - LOG_E( PHY, "[eNB] frame %d subframe %d rxtx busy instance_pre_scd %d\n", - frame,subframe,ru->proc.instance_pre_scd ); - } - - if (pthread_mutex_unlock(&ru->proc.mutex_pre_scd)!= 0) { - LOG_E( PHY, "[eNB] error unlocking mutex_pre_scd mutex for eNB pre scd\n"); - exit_fun("error unlocking mutex_pre_scd"); - } - -#endif - - // wakeup all eNB processes waiting for this RU - if (ru->num_eNB>0) wakeup_L1s(ru); - -#ifndef PHY_TX_THREAD - - if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD || ru->num_eNB==0) { - // do TX front-end processing if needed (precoding and/or IDFTs) - if (ru->feptx_prec) ru->feptx_prec(ru); - - // do OFDM if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru); - - if(!(get_softmodem_params()->emulate_rf)) { - // do outgoing fronthaul (south) if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru); - - if (ru->fh_north_out) ru->fh_north_out(ru); - } - - proc->emulate_rf_busy = 0; - } - -#else - struct timespec time_req, time_rem; - time_req.tv_sec = 0; - time_req.tv_nsec = 10000; - - while((!oai_exit)&&(phy_tx_end == 0)) { - nanosleep(&time_req,&time_rem); - continue; - } - -#endif + + // do TX front-end processing if needed (precoding and/or IDFTs) + if (ru->feptx_prec) ru->feptx_prec(ru); + + // do OFDM if needed + if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru); + // do outgoing fronthaul (south) if needed + if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru); + + if (ru->fh_north_out) ru->fh_north_out(ru); + } - + printf( "Exiting ru_thread \n"); if (!(get_softmodem_params()->emulate_rf)) { diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 50e866358b..f8a42de069 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -505,9 +505,7 @@ int main( int argc, char **argv ) { } for (int enb_id = 0; enb_id < RC.nb_inst; enb_id++) { - MessageDef *msg_p = itti_alloc_new_message (TASK_ENB_APP, RRC_CONFIGURATION_REQ); - RRC_CONFIGURATION_REQ(msg_p) = RC.rrc[enb_id]->configuration; - itti_send_msg_to_task (TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p); + openair_rrc_eNB_configuration(enb_id, &RC.rrc[enb_id]->configuration); } } else { printf("RC.nb_inst = 0, Initializing L1\n"); @@ -530,12 +528,9 @@ int main( int argc, char **argv ) { // init UE_PF_PO and mutex lock pthread_mutex_init(&ue_pf_po_mutex, NULL); memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*MAX_MOBILES_PER_ENB*MAX_NUM_CCs); - mlockall(MCL_CURRENT | MCL_FUTURE); pthread_cond_init(&sync_cond,NULL); pthread_mutex_init(&sync_mutex, NULL); - - rt_sleep_ns(10*100000000ULL); if (NFAPI_MODE!=NFAPI_MONOLITHIC) { @@ -563,9 +558,10 @@ int main( int argc, char **argv ) { // for (CC_id=0;CC_idinit_SI()->rrc_mac_config_req_eNB ()->phy_config_request () sets the wait_eNBs() tested flag + // wait_eNBs(); + // printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU); // RU thread and some L1 procedure aren't necessary in VNF or L2 FAPI simulator. // but RU thread deals with pre_scd and this is necessary in VNF and simulator. @@ -588,6 +584,9 @@ int main( int argc, char **argv ) { printf("wait RUs\n"); // end of CI modifications + // fixme: very weird usage of bitmask + // lack of mutex in: ru_thread_prach(),... + // wait_RUs() is wrong and over complex! wait_RUs(); LOG_I(ENB_APP,"RC.nb_RU:%d\n", RC.nb_RU); // once all RUs are ready intiailize the rest of the eNBs ((dependence on final RU parameters after configuration) From 217491cbbfe2a1f18a67c67a386300a63949395c Mon Sep 17 00:00:00 2001 From: laurent Date: Mon, 1 Jul 2019 15:46:38 +0200 Subject: [PATCH 004/240] progress in main cleanup coding --- cmake_targets/CMakeLists.txt | 10 +- executables/{simple_main.c => main-ocp.c} | 528 +++++++++++----------- executables/split_headers.h | 5 +- targets/ARCH/rfsimulator/simulator.c | 64 ++- targets/RT/USER/lte-softmodem.c | 158 +++++-- 5 files changed, 443 insertions(+), 322 deletions(-) rename executables/{simple_main.c => main-ocp.c} (95%) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index c9741ce488..10f263100b 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -2090,9 +2090,9 @@ target_link_libraries (lte-softmodem -Wl,--end-group z dl) -add_executable(simple-softmodem +add_executable(ocp-softmodem ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c - ${OPENAIR_DIR}/executables/simple_main.c + ${OPENAIR_DIR}/executables/main-ocp.c ${OPENAIR_TARGETS}/RT/USER/lte-softmodem.c ${OPENAIR_TARGETS}/RT/USER/lte-softmodem-common.c ${OPENAIR2_DIR}/ENB_APP/NB_IoT_interface.c @@ -2113,15 +2113,15 @@ add_executable(simple-softmodem ${CONFIG_SOURCES} ${SHLIB_LOADER_SOURCES} ) -add_dependencies(simple-softmodem rrc_flag s1ap_flag x2_flag) +add_dependencies(ocp-softmodem rrc_flag s1ap_flag x2_flag) -target_link_libraries (simple-softmodem +target_link_libraries (ocp-softmodem -Wl,--start-group RRC_LIB S1AP_LIB S1AP_ENB F1AP_LIB F1AP X2AP_LIB X2AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB SCHED_RU_LIB PHY_COMMON PHY PHY_RU LFDS L2 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} ${FSPT_MSG_LIB} ${PROTO_AGENT_LIB} LFDS7 NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB -Wl,--end-group z dl) -target_link_libraries (simple-softmodem ${LIBXML2_LIBRARIES} pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES} ${LIB_LMS_LIBRARIES} ${T_LIB}) +target_link_libraries (ocp-softmodem ${LIBXML2_LIBRARIES} pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES} ${LIB_LMS_LIBRARIES} ${T_LIB}) add_executable(cu_test ${OPENAIR2_DIR}/LAYER2/PROTO_AGENT/cu_test.c diff --git a/executables/simple_main.c b/executables/main-ocp.c similarity index 95% rename from executables/simple_main.c rename to executables/main-ocp.c index 7a15f6df3c..b3472f17cb 100644 --- a/executables/simple_main.c +++ b/executables/main-ocp.c @@ -50,9 +50,6 @@ void init_eNB_proc(int inst) { proc->CC_id = CC_id; proc->first_rx =1; proc->first_tx =1; - proc->RU_mask_tx = (1<num_RU)-1; - proc->RU_mask =0; - proc->RU_mask_prach =0; pthread_mutex_init( &eNB->UL_INFO_mutex, NULL); pthread_mutex_init( &L1_proc->mutex, NULL); pthread_cond_init( &L1_proc->cond, NULL); @@ -94,102 +91,12 @@ void init_RU_proc(RU_t *ru) { for (i=0; i<10; i++) proc->symbol_mask[i]=0; pthread_mutex_init( &proc->mutex_synch,NULL); - pthread_cond_init( &proc->cond_synch,NULL); pthread_cond_init( &proc->cond_eNBs, NULL); - pthread_t t; threadCreate(&t, ru_thread, (void *)ru, "MainRu", -1, OAI_PRIORITY_RT_MAX); } -void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { - L1_proc_t *proc = &eNB->proc; - LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - - // check if we have to detect PRACH first - if (is_prach_subframe(fp,frame,subframe)>0) { - // set timing for prach thread - proc->frame_prach = frame; - proc->subframe_prach = subframe; - prach_procedures(eNB,0); - } -} - -void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { - L1_proc_t *proc = &eNB->proc; - LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - - // check if we have to detect PRACH first - if (is_prach_subframe(fp,frame,subframe)>0) { - LOG_D(PHY,"Triggering prach br processing, frame %d, subframe %d\n",frame,subframe); - // set timing for prach thread - proc->frame_prach_br = frame; - proc->subframe_prach_br = subframe; - prach_procedures(eNB,1); - } -} - -static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name) { - - AssertFatal( eNB !=NULL, ""); - - if (NFAPI_MODE==NFAPI_MODE_PNF) { - // I am a PNF and I need to let nFAPI know that we have a (sub)frame tick - //add_subframe(&frame, &subframe, 4); - //oai_subframe_ind(proc->frame_tx, proc->subframe_tx); - oai_subframe_ind(proc->frame_rx, proc->subframe_rx); - } - - AssertFatal( !(NFAPI_MODE==NFAPI_MODE_PNF && - eNB->pdcch_vars[proc->subframe_tx&1].num_pdcch_symbols == 0), ""); - - wakeup_prach_eNB(eNB,NULL,proc->frame_rx,proc->subframe_rx); - wakeup_prach_eNB_br(eNB,NULL,proc->frame_rx,proc->subframe_rx); - release_UE_in_freeList(eNB->Mod_id); - - // UE-specific RX processing for subframe n - if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { - phy_procedures_eNB_uespec_RX(eNB, proc); - } - - pthread_mutex_lock(&eNB->UL_INFO_mutex); - eNB->UL_INFO.frame = proc->frame_rx; - eNB->UL_INFO.subframe = proc->subframe_rx; - eNB->UL_INFO.module_id = eNB->Mod_id; - eNB->UL_INFO.CC_id = eNB->CC_id; - eNB->if_inst->UL_indication(&eNB->UL_INFO); - pthread_mutex_unlock(&eNB->UL_INFO_mutex); - phy_procedures_eNB_TX(eNB, proc, 1); - - return(0); -} - -void eNB_top(PHY_VARS_eNB *eNB, int frame_rx, int subframe_rx, char *string,RU_t *ru) { - L1_proc_t *proc = &eNB->proc; - L1_rxtx_proc_t *L1_proc = &proc->L1_proc; - LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; - RU_proc_t *ru_proc=&ru->proc; - proc->frame_rx = frame_rx; - proc->subframe_rx = subframe_rx; - - if (!oai_exit) { - 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; - L1_proc->frame_tx = (L1_proc->subframe_rx > (9-sf_ahead)) ? - (L1_proc->frame_rx+1)&1023 : - L1_proc->frame_rx; - L1_proc->subframe_tx = (L1_proc->subframe_rx + sf_ahead)%10; - - if (rxtx(eNB,L1_proc,string) < 0) - LOG_E(PHY,"eNB %d CC_id %d failed during execution\n",eNB->Mod_id,eNB->CC_id); - - ru_proc->timestamp_tx = L1_proc->timestamp_tx; - ru_proc->subframe_tx = L1_proc->subframe_tx; - ru_proc->frame_tx = L1_proc->frame_tx; - } -} - void init_transport(PHY_VARS_eNB *eNB) { int i; int j; @@ -354,129 +261,6 @@ void stop_eNB(int nb_inst) { kill_eNB_proc(inst); } } - -void rx_rf(RU_t *ru,int *frame,int *subframe) { - RU_proc_t *proc = &ru->proc; - LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; - void *rxp[ru->nb_rx]; - unsigned int rxs; - int i; - openair0_timestamp ts=0,old_ts=0; - - for (i=0; inb_rx; i++) - rxp[i] = (void *)&ru->common.rxdata[i][*subframe*fp->samples_per_tti]; - - old_ts = proc->timestamp_rx; - rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, - &ts, - rxp, - fp->samples_per_tti, - ru->nb_rx); - proc->timestamp_rx = ts-ru->ts_offset; - - // AssertFatal(rxs == fp->samples_per_tti, - // "rx_rf: Asked for %d samples, got %d from SDR\n",fp->samples_per_tti,rxs); - if(rxs != fp->samples_per_tti) { - LOG_E(PHY,"rx_rf: Asked for %d samples, got %d from SDR\n",fp->samples_per_tti,rxs); - } - - if (proc->first_rx == 1) { - ru->ts_offset = proc->timestamp_rx; - proc->timestamp_rx = 0; - } else { - if (proc->timestamp_rx - old_ts != fp->samples_per_tti) { - ru->ts_offset += (proc->timestamp_rx - old_ts - fp->samples_per_tti); - proc->timestamp_rx = ts-ru->ts_offset; - } - } - - proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; - proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; - // synchronize first reception to frame 0 subframe 0 - proc->timestamp_tx = proc->timestamp_rx+(sf_ahead*fp->samples_per_tti); - proc->subframe_tx = (proc->subframe_rx+sf_ahead)%10; - proc->frame_tx = (proc->subframe_rx>(9-sf_ahead)) ? (proc->frame_rx+1)&1023 : proc->frame_rx; - - if (proc->first_rx == 0) { - AssertFatal( proc->subframe_rx == *subframe && proc->frame_rx == *frame , - "Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d) (proc->frame_rx %d frame %d)\n", - (long long unsigned int)proc->timestamp_rx,proc->subframe_rx,*subframe, proc->frame_rx,*frame); - } else { - proc->first_rx = 0; - *frame = proc->frame_rx; - *subframe = proc->subframe_rx; - } - - if (rxs != fp->samples_per_tti) { -#if defined(USRP_REC_PLAY) - exit_fun("Exiting IQ record/playback"); -#else - //exit_fun( "problem receiving samples" ); - LOG_E(PHY, "problem receiving samples"); -#endif - } -} - -void tx_rf(RU_t *ru) { - RU_proc_t *proc = &ru->proc; - LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; - void *txp[ru->nb_tx]; - int i; - lte_subframe_t SF_type = subframe_select(fp,proc->subframe_tx%10); - lte_subframe_t prevSF_type = subframe_select(fp,(proc->subframe_tx+9)%10); - int sf_extension = 0; - - if ((SF_type == SF_DL) || - (SF_type == SF_S)) { - int siglen=fp->samples_per_tti,flags=1; - - if (SF_type == SF_S) { - /* end_of_burst_delay is used to stop TX only "after a while". - * If we stop right after effective signal, with USRP B210 and - * B200mini, we observe a high EVM on the S subframe (on the - * PSS). - * A value of 400 (for 30.72MHz) solves this issue. This is - * the default. - */ - siglen = (fp->ofdm_symbol_size + fp->nb_prefix_samples0) - + (fp->dl_symbols_in_S_subframe - 1) * (fp->ofdm_symbol_size + fp->nb_prefix_samples) - + ru->end_of_burst_delay; - flags=3; // end of burst - } - - if (fp->frame_type == TDD && - SF_type == SF_DL && - prevSF_type == SF_UL) { - flags = 2; // start of burst - sf_extension = ru->sf_extension; - } - -#if defined(__x86_64) || defined(__i386__) -#ifdef __AVX2__ - sf_extension = (sf_extension)&0xfffffff8; -#else - sf_extension = (sf_extension)&0xfffffffc; -#endif -#elif defined(__arm__) - sf_extension = (sf_extension)&0xfffffffc; -#endif - - for (i=0; inb_tx; i++) - txp[i] = (void *)&ru->common.txdata[i][(proc->subframe_tx*fp->samples_per_tti)-sf_extension]; - - /* add fail safe for late command end */ - // prepare tx buffer pointers - ru->rfdevice.trx_write_func(&ru->rfdevice, - proc->timestamp_tx+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension, - txp, - siglen+sf_extension, - ru->nb_tx, - flags); - LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, subframe %d\n",ru->idx, - (long long unsigned int)proc->timestamp_tx,proc->frame_tx,proc->frame_tx_unwrap,proc->subframe_tx); - } -} - // this is for RU with local RF unit void fill_rf_config(RU_t *ru, char *rf_config_file) { int i; @@ -642,6 +426,247 @@ int setup_RU_buffers(RU_t *ru) { return(0); } + +void init_precoding_weights(PHY_VARS_eNB *eNB) { + int layer,ru_id,aa,re,ue,tb; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + RU_t *ru; + LTE_eNB_DLSCH_t *dlsch; + + // init precoding weigths + for (ue=0; uedlsch[ue][tb]; + + for (layer=0; layer<4; layer++) { + int nb_tx=0; + + for (ru_id=0; ru_idnb_tx; + } + + dlsch->ue_spec_bf_weights[layer] = (int32_t **)malloc16(nb_tx*sizeof(int32_t *)); + + for (aa=0; aaue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(fp->ofdm_symbol_size*sizeof(int32_t)); + + for (re=0; reofdm_symbol_size; re++) { + dlsch->ue_spec_bf_weights[layer][aa][re] = 0x00007fff; + } + } + } + } + } +} + +void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { + L1_proc_t *proc = &eNB->proc; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + + // check if we have to detect PRACH first + if (is_prach_subframe(fp,frame,subframe)>0) { + // set timing for prach thread + proc->frame_prach = frame; + proc->subframe_prach = subframe; + prach_procedures(eNB,0); + } +} + +void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { + L1_proc_t *proc = &eNB->proc; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + + // check if we have to detect PRACH first + if (is_prach_subframe(fp,frame,subframe)>0) { + LOG_D(PHY,"Triggering prach br processing, frame %d, subframe %d\n",frame,subframe); + // set timing for prach thread + proc->frame_prach_br = frame; + proc->subframe_prach_br = subframe; + prach_procedures(eNB,1); + } +} + +static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name) { + AssertFatal( eNB !=NULL, ""); + + if (NFAPI_MODE==NFAPI_MODE_PNF) { + // I am a PNF and I need to let nFAPI know that we have a (sub)frame tick + //add_subframe(&frame, &subframe, 4); + //oai_subframe_ind(proc->frame_tx, proc->subframe_tx); + oai_subframe_ind(proc->frame_rx, proc->subframe_rx); + } + + AssertFatal( !(NFAPI_MODE==NFAPI_MODE_PNF && + eNB->pdcch_vars[proc->subframe_tx&1].num_pdcch_symbols == 0), ""); + wakeup_prach_eNB(eNB,NULL,proc->frame_rx,proc->subframe_rx); + wakeup_prach_eNB_br(eNB,NULL,proc->frame_rx,proc->subframe_rx); + release_UE_in_freeList(eNB->Mod_id); + + // UE-specific RX processing for subframe n + if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { + phy_procedures_eNB_uespec_RX(eNB, proc); + } + + pthread_mutex_lock(&eNB->UL_INFO_mutex); + eNB->UL_INFO.frame = proc->frame_rx; + eNB->UL_INFO.subframe = proc->subframe_rx; + eNB->UL_INFO.module_id = eNB->Mod_id; + eNB->UL_INFO.CC_id = eNB->CC_id; + eNB->if_inst->UL_indication(&eNB->UL_INFO); + pthread_mutex_unlock(&eNB->UL_INFO_mutex); + phy_procedures_eNB_TX(eNB, proc, 1); + return(0); +} + +void eNB_top(PHY_VARS_eNB *eNB, int frame_rx, int subframe_rx, char *string,RU_t *ru) { + L1_proc_t *proc = &eNB->proc; + L1_rxtx_proc_t *L1_proc = &proc->L1_proc; + LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; + RU_proc_t *ru_proc=&ru->proc; + proc->frame_rx = frame_rx; + proc->subframe_rx = subframe_rx; + + if (!oai_exit) { + 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; + L1_proc->frame_tx = (L1_proc->subframe_rx > (9-sf_ahead)) ? + (L1_proc->frame_rx+1)&1023 : + L1_proc->frame_rx; + L1_proc->subframe_tx = (L1_proc->subframe_rx + sf_ahead)%10; + + if (rxtx(eNB,L1_proc,string) < 0) + LOG_E(PHY,"eNB %d CC_id %d failed during execution\n",eNB->Mod_id,eNB->CC_id); + + ru_proc->timestamp_tx = L1_proc->timestamp_tx; + ru_proc->subframe_tx = L1_proc->subframe_tx; + ru_proc->frame_tx = L1_proc->frame_tx; + } +} + +void rx_rf(RU_t *ru,int *frame,int *subframe) { + RU_proc_t *proc = &ru->proc; + LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; + void *rxp[ru->nb_rx]; + unsigned int rxs; + int i; + openair0_timestamp ts=0,old_ts=0; + + for (i=0; inb_rx; i++) + rxp[i] = (void *)&ru->common.rxdata[i][*subframe*fp->samples_per_tti]; + + old_ts = proc->timestamp_rx; + rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, + &ts, + rxp, + fp->samples_per_tti, + ru->nb_rx); + proc->timestamp_rx = ts-ru->ts_offset; + + // AssertFatal(rxs == fp->samples_per_tti, + // "rx_rf: Asked for %d samples, got %d from SDR\n",fp->samples_per_tti,rxs); + if(rxs != fp->samples_per_tti) { + LOG_E(PHY,"rx_rf: Asked for %d samples, got %d from SDR\n",fp->samples_per_tti,rxs); + } + + if (proc->first_rx == 1) { + ru->ts_offset = proc->timestamp_rx; + proc->timestamp_rx = 0; + } else { + if (proc->timestamp_rx - old_ts != fp->samples_per_tti) { + ru->ts_offset += (proc->timestamp_rx - old_ts - fp->samples_per_tti); + proc->timestamp_rx = ts-ru->ts_offset; + } + } + + proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; + proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; + // synchronize first reception to frame 0 subframe 0 + proc->timestamp_tx = proc->timestamp_rx+(sf_ahead*fp->samples_per_tti); + proc->subframe_tx = (proc->subframe_rx+sf_ahead)%10; + proc->frame_tx = (proc->subframe_rx>(9-sf_ahead)) ? (proc->frame_rx+1)&1023 : proc->frame_rx; + + if (proc->first_rx == 0) { + AssertFatal( proc->subframe_rx == *subframe && proc->frame_rx == *frame, + "Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d) (proc->frame_rx %d frame %d)\n", + (long long unsigned int)proc->timestamp_rx,proc->subframe_rx,*subframe, proc->frame_rx,*frame); + } else { + proc->first_rx = 0; + *frame = proc->frame_rx; + *subframe = proc->subframe_rx; + } + + if (rxs != fp->samples_per_tti) { +#if defined(USRP_REC_PLAY) + exit_fun("Exiting IQ record/playback"); +#else + //exit_fun( "problem receiving samples" ); + LOG_E(PHY, "problem receiving samples"); +#endif + } +} + +void tx_rf(RU_t *ru) { + RU_proc_t *proc = &ru->proc; + LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; + void *txp[ru->nb_tx]; + int i; + lte_subframe_t SF_type = subframe_select(fp,proc->subframe_tx%10); + lte_subframe_t prevSF_type = subframe_select(fp,(proc->subframe_tx+9)%10); + int sf_extension = 0; + + if ((SF_type == SF_DL) || + (SF_type == SF_S)) { + int siglen=fp->samples_per_tti,flags=1; + + if (SF_type == SF_S) { + /* end_of_burst_delay is used to stop TX only "after a while". + * If we stop right after effective signal, with USRP B210 and + * B200mini, we observe a high EVM on the S subframe (on the + * PSS). + * A value of 400 (for 30.72MHz) solves this issue. This is + * the default. + */ + siglen = (fp->ofdm_symbol_size + fp->nb_prefix_samples0) + + (fp->dl_symbols_in_S_subframe - 1) * (fp->ofdm_symbol_size + fp->nb_prefix_samples) + + ru->end_of_burst_delay; + flags=3; // end of burst + } + + if (fp->frame_type == TDD && + SF_type == SF_DL && + prevSF_type == SF_UL) { + flags = 2; // start of burst + sf_extension = ru->sf_extension; + } + +#if defined(__x86_64) || defined(__i386__) +#ifdef __AVX2__ + sf_extension = (sf_extension)&0xfffffff8; +#else + sf_extension = (sf_extension)&0xfffffffc; +#endif +#elif defined(__arm__) + sf_extension = (sf_extension)&0xfffffffc; +#endif + + for (i=0; inb_tx; i++) + txp[i] = (void *)&ru->common.txdata[i][(proc->subframe_tx*fp->samples_per_tti)-sf_extension]; + + /* add fail safe for late command end */ + // prepare tx buffer pointers + ru->rfdevice.trx_write_func(&ru->rfdevice, + proc->timestamp_tx+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension, + txp, + siglen+sf_extension, + ru->nb_tx, + flags); + LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, subframe %d\n",ru->idx, + (long long unsigned int)proc->timestamp_tx,proc->frame_tx,proc->frame_tx_unwrap,proc->subframe_tx); + } +} + static void *ru_thread( void *param ) { static int ru_thread_status; RU_t *ru = (RU_t *)param; @@ -664,10 +689,6 @@ static void *ru_thread( void *param ) { } LOG_I(PHY, "Signaling main thread that RU %d is ready\n",ru->idx); - pthread_mutex_lock(&RC.ru_mutex); - RC.ru_mask &= ~(1<idx); - pthread_cond_signal(&RC.ru_cond); - pthread_mutex_unlock(&RC.ru_mutex); wait_sync("ru_thread"); // Start RF device if any @@ -745,41 +766,7 @@ int stop_rf(RU_t *ru) { return 0; } -void init_precoding_weights(PHY_VARS_eNB *eNB) { - int layer,ru_id,aa,re,ue,tb; - LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - RU_t *ru; - LTE_eNB_DLSCH_t *dlsch; - - // init precoding weigths - for (ue=0; uedlsch[ue][tb]; - - for (layer=0; layer<4; layer++) { - int nb_tx=0; - - for (ru_id=0; ru_idnb_tx; - } - - dlsch->ue_spec_bf_weights[layer] = (int32_t **)malloc16(nb_tx*sizeof(int32_t *)); - - for (aa=0; aaue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(fp->ofdm_symbol_size*sizeof(int32_t)); - - for (re=0; reofdm_symbol_size; re++) { - dlsch->ue_spec_bf_weights[layer][aa][re] = 0x00007fff; - } - } - } - } - } -} - void set_function_spec_param(RU_t *ru) { - switch (ru->if_south) { case LOCAL_RF: { // this is an RU with integrated RF (RRU, eNB) ru->do_prach = 0; // no prach processing in RU @@ -819,21 +806,20 @@ void set_function_spec_param(RU_t *ru) { //extern void RCconfig_RU(void); -void init_RU(char *rf_config_file) { +void init_RU(char *rf_config_file, clock_source_t clock_source,clock_source_t time_source,int send_dmrssync) { int ru_id; RU_t *ru; PHY_VARS_eNB *eNB0= (PHY_VARS_eNB *)NULL; int i; int CC_id; // create status mask - RC.ru_mask = 0; pthread_mutex_init(&RC.ru_mutex,NULL); pthread_cond_init(&RC.ru_cond,NULL); // read in configuration file) printf("configuring RU from file\n"); RCconfig_RU(); LOG_I(PHY,"number of L1 instances %d, number of RU %d, number of CPU cores %d\n", - RC.nb_L1_inst,RC.nb_RU,get_nprocs()); + RC.nb_L1_inst,RC.nb_RU,get_nprocs()); if (RC.nb_CC != 0) for (i=0; irf_config_file = rf_config_file; ru->idx = ru_id; ru->ts_offset = 0; + + if (ru->is_slave == 1) { + ru->in_synch = 0; + ru->generate_dmrs_sync = 0; + } else { + ru->in_synch = 1; + ru->generate_dmrs_sync=send_dmrssync; + } + + ru->cmd = EMPTY; + ru->south_out_cnt= 0; // use eNB_list[0] as a reference for RU frame parameters // NOTE: multiple CC_id are not handled here yet! + ru->openair0_cfg.clock_source = clock_source; + ru->openair0_cfg.time_source = time_source; + + // ru->generate_dmrs_sync = (ru->is_slave == 0) ? 1 : 0; + if (ru->generate_dmrs_sync == 1) { + generate_ul_ref_sigs(); + ru->dmrssync = (int16_t *)malloc16_clear(ru->frame_parms.ofdm_symbol_size*2*sizeof(int16_t)); + } + + ru->wakeup_L1_sleeptime = 2000; + ru->wakeup_L1_sleep_cnt_max = 3; if (ru->num_eNB > 0) { LOG_D(PHY, "%s() RC.ru[%d].num_eNB:%d ru->eNB_list[0]:%p RC.eNB[0][0]:%p rf_config_file:%s\n", - __FUNCTION__, ru_id, ru->num_eNB, ru->eNB_list[0], RC.eNB[0][0], ru->rf_config_file); + __FUNCTION__, ru_id, ru->num_eNB, ru->eNB_list[0], RC.eNB[0][0], ru->rf_config_file); if (ru->eNB_list[0] == 0) { LOG_E(PHY,"%s() DJP - ru->eNB_list ru->num_eNB are not initialized - so do it manually\n", - __FUNCTION__); + __FUNCTION__); ru->eNB_list[0] = RC.eNB[0][0]; ru->num_eNB=1; // @@ -916,8 +924,6 @@ void RCconfig_RU(void) { if ( RUParamList.numelt > 0) { RC.ru = (RU_t **)malloc(RC.nb_RU*sizeof(RU_t *)); - RC.ru_mask=(1<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->lastWroteTS=0; ptr->headerMode=true; ptr->transferPtr=(char *)&ptr->th; ptr->remainToTransfer=sizeof(samplesBlockHeader_t); @@ -319,21 +319,22 @@ sin_addr: setblocking(sock, notBlocking); allocCirBuf(t, sock); - t->buf[sock].alreadyRead=true; // UE will start blocking on read 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 ) { + for (int i=0; ibuf[i]; + + if (b->conn_sock >= 0 ) { + if ( abs((double)b->lastWroteTS-timestamp) > (double)CirSize) + LOG_E(HW,"Tx/Rx shift too large Tx:%lu, Rx:%lu\n", b->lastWroteTS, b->lastReceivedTS); samplesBlockHeader_t header= {t->typeStamp, nsamps, nbAnt, timestamp}; - fullwrite(ptr->conn_sock,&header, sizeof(header), t); + fullwrite(b->conn_sock,&header, sizeof(header), t); sample_t tmpSamples[nsamps][nbAnt]; for(int a=0; aconn_sock >= 0 ) - fullwrite(ptr->conn_sock, (void *)tmpSamples, sampleToByte(nsamps,nbAnt), t); + if (b->conn_sock >= 0 ) { + fullwrite(b->conn_sock, (void *)tmpSamples, sampleToByte(nsamps,nbAnt), t); + b->lastWroteTS=timestamp+nsamps; + } } } - 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; @@ -425,7 +426,6 @@ static bool flushInput(rfsimulator_state_t *t, int timeout) { 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; @@ -441,8 +441,8 @@ static bool flushInput(rfsimulator_state_t *t, int timeout) { } 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); + AssertFatal(b->lastWroteTS == 0 || ( abs((double)b->lastWroteTS-b->lastReceivedTS) < (double)CirSize), + "Tx/Rx shift too large Tx:%lu, Rx:%lu\n", b->lastWroteTS, b->lastReceivedTS); b->transferPtr=(char *)&b->circularBuf[b->lastReceivedTS%CirSize]; b->remainToTransfer=sampleToByte(b->th.size, b->th.nbAnt); } @@ -498,15 +498,33 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo return nsamps; } } else { + bool have_to_wait; do { have_to_wait=false; for ( int sock=0; sockbuf[sock].circularBuf && t->buf[sock].alreadyRead ) - if ( t->buf[sock].lastReceivedTS == 0 || - (t->nextTimestamp+nsamps) > t->buf[sock].lastReceivedTS ) { + buffer_t *b=&t->buf[sock]; + if ( b->circularBuf) { + LOG_D(HW,"sock: %d, lastWroteTS: %lu, lastRecvTS: %lu, TS must be avail: %lu\n", + sock, b->lastWroteTS, + b->lastReceivedTS, + t->nextTimestamp+nsamps); + if ( b->lastReceivedTS > b->lastWroteTS ) { + // The caller momdem (NB, UE, ...) must send Tx in advance, so we fill TX if Rx is in advance + // This occurs for example when UE is in sync mode: it doesn't transmit + // with USRP, it seems ok: if "tx stream" is off, we may consider it actually cuts the Tx power + struct complex16 v={0}; + void *samplesVoid[b->th.nbAnt]; + for ( int i=0; i th.nbAnt; i++) + samplesVoid[i]=(void*)&v; + rfsimulator_write(device, b->lastReceivedTS, samplesVoid, 1, b->th.nbAnt, 0); + } + } + + if ( b->circularBuf ) + if ( t->nextTimestamp+nsamps > b->lastReceivedTS ) { have_to_wait=true; break; } @@ -529,7 +547,7 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo for (int sock=0; sockbuf[sock]; - if ( ptr->circularBuf && ptr->alreadyRead ) { + if ( ptr->circularBuf ) { bool reGenerateChannel=false; //fixme: when do we regenerate diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index dcd7966874..37e94de2b6 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -80,7 +80,7 @@ unsigned short config_frames[4] = {2,9,11,13}; //#include "PHY/TOOLS/time_meas.h" #ifndef OPENAIR2 -#include "UTIL/OTG/otg_vars.h" + #include "UTIL/OTG/otg_vars.h" #endif @@ -91,6 +91,7 @@ unsigned short config_frames[4] = {2,9,11,13}; #include "system.h" + #include "lte-softmodem.h" #include "NB_IoT_interface.h" @@ -107,6 +108,10 @@ pthread_mutex_t sync_mutex; int sync_var=-1; //!< protected by mutex \ref sync_mutex. int config_sync_var=-1; +uint16_t runtime_phy_rx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100] +uint16_t runtime_phy_tx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100] + + volatile int oai_exit = 0; uint32_t downlink_frequency[MAX_NUM_CCs][4]; @@ -145,10 +150,18 @@ char ref[128] = "internal"; char channels[128] = "0"; int rx_input_level_dBm; + int otg_enabled; + + uint8_t exit_missed_slots=1; uint64_t num_missed_slots=0; // counter for the number of missed slots + +extern void reset_opp_meas(void); +extern void print_opp_meas(void); + + extern void init_eNB_afterRU(void); extern void phy_free_RU(RU_t *); @@ -159,11 +172,73 @@ int numerology = 0; THREAD_STRUCT thread_struct; /* struct for ethernet specific parameters given in eNB conf file */ eth_params_t *eth_params; + double cpuf; +/* forward declarations */ + /* forward declarations */ void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]); +/*---------------------BMC: timespec helpers -----------------------------*/ + +struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 }; +struct timespec max_diff_time = { .tv_sec = 0, .tv_nsec = 0 }; + +struct timespec clock_difftime(struct timespec start, struct timespec end) { + struct timespec temp; + + if ((end.tv_nsec-start.tv_nsec)<0) { + temp.tv_sec = end.tv_sec-start.tv_sec-1; + temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec; + } else { + temp.tv_sec = end.tv_sec-start.tv_sec; + temp.tv_nsec = end.tv_nsec-start.tv_nsec; + } + + return temp; +} + +void print_difftimes(void) { +#ifdef DEBUG + printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec); +#else + LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec); +#endif +} + +void update_difftimes(struct timespec start, struct timespec end) { + struct timespec diff_time = { .tv_sec = 0, .tv_nsec = 0 }; + int changed = 0; + diff_time = clock_difftime(start, end); + + if ((min_diff_time.tv_nsec == 0) || (diff_time.tv_nsec < min_diff_time.tv_nsec)) { + min_diff_time.tv_nsec = diff_time.tv_nsec; + changed = 1; + } + + if ((max_diff_time.tv_nsec == 0) || (diff_time.tv_nsec > max_diff_time.tv_nsec)) { + max_diff_time.tv_nsec = diff_time.tv_nsec; + changed = 1; + } + +#if 1 + + if (changed) print_difftimes(); + +#endif +} + +/*------------------------------------------------------------------------*/ + +unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) { + return (txi + (txq<<6) + (rxi<<12) + (rxq<<18)); +} +unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe) { + return (dcoff_i_rxfe + (dcoff_q_rxfe<<8)); +} + + void signal_handler(int sig) { void *array[10]; size_t size; @@ -181,6 +256,7 @@ void signal_handler(int sig) { } } + void exit_function(const char *file, const char *function, const int line, const char *s) { int ru_id; @@ -209,6 +285,7 @@ void exit_function(const char *file, const char *function, const int line, const exit(1); } + static void get_options(void) { CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP); get_common_options(); @@ -232,6 +309,10 @@ static void get_options(void) { } } + + + + void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) { int CC_id; @@ -446,11 +527,14 @@ int main( int argc, char **argv ) { int CC_id = 0; int ru_id; - AssertFatal(load_configmodule(argc,argv,0) != NULL, - "[SOFTMODEM] Error, configuration module init failed\n"); + if ( load_configmodule(argc,argv,0) == NULL) { + exit_fun("[SOFTMODEM] Error, configuration module init failed\n"); + } + mode = normal_txrx; logInit(); + printf("Reading in command-line options\n"); get_options (); AssertFatal(!CONFIG_ISFLAGSET(CONFIG_ABORT),"Getting configuration failed\n"); @@ -472,14 +556,21 @@ int main( int argc, char **argv ) { EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1; + if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) { + fprintf(stderr,"Getting configuration failed\n"); + exit(-1); + } + #if T_TRACER T_Config_Init(); #endif //randominit (0); set_taus_seed (0); + printf("configuring for RAU/RRU\n"); - if (opp_enabled ==1) + if (opp_enabled ==1) { reset_opp_meas(); + } itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info); // allows to forward in wireshark L2 protocol for decoding @@ -491,8 +582,9 @@ int main( int argc, char **argv ) { /* Start the agent. If it is turned off in the configuration, it won't start */ RCconfig_flexran(); - for (i = 0; i < RC.nb_inst; i++) + for (i = 0; i < RC.nb_inst; i++) { flexran_agent_start(i); + } /* initializes PDCP and sets correct RLC Request/PDCP Indication callbacks * for monolithic/F1 modes */ @@ -521,7 +613,7 @@ int main( int argc, char **argv ) { ctxt.subframe = 0; pdcp_run(&ctxt); } - + /* start threads if only L1 or not a CU */ if (RC.nb_inst == 0 || !NODE_IS_CU(RC.rrc[0]->node_type)) { // init UE_PF_PO and mutex lock @@ -531,53 +623,56 @@ int main( int argc, char **argv ) { pthread_mutex_init(&sync_mutex, NULL); rt_sleep_ns(10*100000000ULL); - + if (NFAPI_MODE!=NFAPI_MONOLITHIC) { LOG_I(ENB_APP,"NFAPI*** - mutex and cond created - will block shortly for completion of PNF connection\n"); pthread_cond_init(&sync_cond,NULL); pthread_mutex_init(&sync_mutex, NULL); } - + if (NFAPI_MODE==NFAPI_MODE_VNF) {// VNF #if defined(PRE_SCD_THREAD) init_ru_vnf(); // ru pointer is necessary for pre_scd. #endif wait_nfapi_init("main?"); } - + LOG_I(ENB_APP,"START MAIN THREADS\n"); // start the main threads number_of_cards = 1; printf("RC.nb_L1_inst:%d\n", RC.nb_L1_inst); - + if (RC.nb_L1_inst > 0) { printf("Initializing eNB threads single_thread_flag:%d wait_for_sync:%d\n", get_softmodem_params()->single_thread_flag,get_softmodem_params()->wait_for_sync); init_eNB(get_softmodem_params()->single_thread_flag,get_softmodem_params()->wait_for_sync); // for (inst=0;inst0 && NFAPI_MODE!=NFAPI_MODE_VNF) { - printf("Initializing RU threads\n"); + + // no need to wait: openair_rrc_eNB_configuration() is called earlier from this thread + // openair_rrc_eNB_configuration()->init_SI()->rrc_mac_config_req_eNB ()->phy_config_request () sets the wait_eNBs() tested flag + // wait_eNBs(); + // printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU); + + // RU thread and some L1 procedure aren't necessary in VNF or L2 FAPI simulator. + // but RU thread deals with pre_scd and this is necessary in VNF and simulator. + // some initialization is necessary and init_ru_vnf do this. + if (RC.nb_RU >0 && NFAPI_MODE!=NFAPI_MODE_VNF) { + printf("Initializing RU threads\n"); init_RU(get_softmodem_params()->rf_config_file,get_softmodem_params()->clock_source,get_softmodem_params()->timing_source,get_softmodem_params()->send_dmrs_sync); - - for (ru_id=0; ru_idrf_map.card=0; - RC.ru[ru_id]->rf_map.chain=CC_id+(get_softmodem_params()->chain_offset); + + for (ru_id=0; ru_idrf_map.card=0; + RC.ru[ru_id]->rf_map.chain=CC_id+(get_softmodem_params()->chain_offset); + } } - + config_sync_var=0; - + if (NFAPI_MODE==NFAPI_MODE_PNF) { // PNF wait_nfapi_init("main?"); } - + printf("wait RUs\n"); // end of CI modifications // fixme: very weird usage of bitmask @@ -604,6 +699,7 @@ int main( int argc, char **argv ) { pthread_mutex_unlock(&sync_mutex); config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS); } + // wait for end of program LOG_UI(ENB_APP,"TYPE TO TERMINATE\n"); // CI -- Flushing the std outputs for the previous marker to show on the eNB / DU / CU log file @@ -648,17 +744,17 @@ int main( int argc, char **argv ) { for(ru_id=0; ru_idrfdevice.trx_end_func) { - RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice); - RC.ru[ru_id]->rfdevice.trx_end_func = NULL; + RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice); + RC.ru[ru_id]->rfdevice.trx_end_func = NULL; } if (RC.ru[ru_id]->ifdevice.trx_end_func) { - RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice); - RC.ru[ru_id]->ifdevice.trx_end_func = NULL; + RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice); + RC.ru[ru_id]->ifdevice.trx_end_func = NULL; } } } - + terminate_opt(); logClean(); printf("Bye.\n"); From 92442cece206ea48645c4aa3534076e041a92206 Mon Sep 17 00:00:00 2001 From: laurent Date: Mon, 1 Jul 2019 16:43:47 +0200 Subject: [PATCH 005/240] progress in main cleanup coding --- executables/main-ocp.c | 60 +++++++++---------------------- targets/RT/USER/lte-softmodem.c | 63 ++++++++++++++++++--------------- 2 files changed, 51 insertions(+), 72 deletions(-) diff --git a/executables/main-ocp.c b/executables/main-ocp.c index b3472f17cb..cbd18c6541 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -15,6 +15,7 @@ static int DEFENBS[] = {0}; #include #include #include +#include extern uint16_t sf_ahead; extern void oai_subframe_ind(uint16_t sfn, uint16_t sf); extern void fep_full(RU_t *ru); @@ -89,10 +90,6 @@ void init_RU_proc(RU_t *ru) { proc->frame_tx_unwrap = 0; for (i=0; i<10; i++) proc->symbol_mask[i]=0; - - pthread_mutex_init( &proc->mutex_synch,NULL); - pthread_cond_init( &proc->cond_synch,NULL); - pthread_cond_init( &proc->cond_eNBs, NULL); pthread_t t; threadCreate(&t, ru_thread, (void *)ru, "MainRu", -1, OAI_PRIORITY_RT_MAX); } @@ -166,6 +163,7 @@ void init_eNB_afterRU(void) { eNB = RC.eNB[inst][CC_id]; phy_init_lte_eNB(eNB,0,0); eNB->frame_parms.nb_antennas_rx = 0; + eNB->frame_parms.nb_antennas_tx = 0; eNB->prach_vars.rxsigF[0] = (int16_t **)malloc16(64*sizeof(int16_t *)); for (int ce_level=0; ce_level<4; ce_level++) { @@ -175,6 +173,7 @@ void init_eNB_afterRU(void) { for (ru_id=0,aa=0; ru_idnum_RU; ru_id++) { eNB->frame_parms.nb_antennas_rx += eNB->RU_list[ru_id]->nb_rx; + eNB->frame_parms.nb_antennas_tx += eNB->RU_list[ru_id]->nb_tx; AssertFatal(eNB->RU_list[ru_id]->common.rxdataF!=NULL, "RU %d : common.rxdataF is NULL\n", eNB->RU_list[ru_id]->idx); @@ -197,22 +196,9 @@ void init_eNB_afterRU(void) { * In monolithic mode, we come here with nb_antennas_rx == 0 * (not tested in other modes). */ - if (eNB->frame_parms.nb_antennas_rx < 1) { - LOG_I(PHY, "%s() ************* DJP ***** eNB->frame_parms.nb_antennas_rx:%d - GOING TO HARD CODE TO 1", __FUNCTION__, eNB->frame_parms.nb_antennas_rx); - eNB->frame_parms.nb_antennas_rx = 1; - } else { - //LOG_I(PHY," Delete code\n"); - } + AssertFatal( eNB->frame_parms.nb_antennas_rx > 0 && eNB->frame_parms.nb_antennas_rx < 4, ""); + AssertFatal( eNB->frame_parms.nb_antennas_tx > 0 && eNB->frame_parms.nb_antennas_rx < 4, ""); - if (eNB->frame_parms.nb_antennas_tx < 1) { - LOG_I(PHY, "%s() ************* DJP ***** eNB->frame_parms.nb_antennas_tx:%d - GOING TO HARD CODE TO 1", __FUNCTION__, eNB->frame_parms.nb_antennas_tx); - eNB->frame_parms.nb_antennas_tx = 1; - } else { - //LOG_I(PHY," Delete code\n"); - } - - AssertFatal(eNB->frame_parms.nb_antennas_rx >0, - "inst %d, CC_id %d : nb_antennas_rx %d\n",inst,CC_id,eNB->frame_parms.nb_antennas_rx); LOG_I(PHY,"inst %d, CC_id %d : nb_antennas_rx %d\n",inst,CC_id,eNB->frame_parms.nb_antennas_rx); init_transport(eNB); //init_precoding_weights(RC.eNB[inst][CC_id]); @@ -261,6 +247,7 @@ void stop_eNB(int nb_inst) { kill_eNB_proc(inst); } } + // this is for RU with local RF unit void fill_rf_config(RU_t *ru, char *rf_config_file) { int i; @@ -768,7 +755,7 @@ int stop_rf(RU_t *ru) { void set_function_spec_param(RU_t *ru) { switch (ru->if_south) { - case LOCAL_RF: { // this is an RU with integrated RF (RRU, eNB) + case LOCAL_RF: // this is an RU with integrated RF (RRU, eNB) ru->do_prach = 0; // no prach processing in RU ru->feprx = fep_full; ru->feptx_ofdm = feptx_ofdm; @@ -776,31 +763,16 @@ void set_function_spec_param(RU_t *ru) { ru->fh_north_in = NULL; // no incoming fronthaul from north ru->start_if = NULL; // no if interface ru->rfdevice.host_type = RAU_HOST; - } - - ru->fh_south_in = rx_rf; // local synchronous RF RX - ru->fh_south_out = tx_rf; // local synchronous RF TX - ru->start_rf = start_rf; // need to start the local RF interface - ru->stop_rf = stop_rf; - ru->eNB_top=eNB_top; - printf("configuring ru_id %d (start_rf %p)\n", ru->idx, start_rf); - /* - if (ru->function == eNodeB_3GPP) { // configure RF parameters only for 3GPP eNodeB, we need to get them from RAU otherwise - fill_rf_config(ru,rf_config_file); - init_frame_parms(&ru->frame_parms,1); - phy_init_RU(ru); - } - - ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); - if (setup_RU_buffers(ru)!=0) { - printf("Exiting, cannot initialize RU Buffers\n"); - exit(-1); - }*/ - break; - - default: - LOG_E(PHY,"RU with invalid or unknown southbound interface type %d\n",ru->if_south); + ru->fh_south_in = rx_rf; // local synchronous RF RX + ru->fh_south_out = tx_rf; // local synchronous RF TX + ru->start_rf = start_rf; // need to start the local RF interface + ru->stop_rf = stop_rf; + ru->eNB_top=eNB_top; break; + + default: + LOG_E(PHY,"RU with invalid or unknown southbound interface type %d\n",ru->if_south); + break; } // switch on interface type } diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 37e94de2b6..de211376b2 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -91,7 +91,6 @@ unsigned short config_frames[4] = {2,9,11,13}; #include "system.h" - #include "lte-softmodem.h" #include "NB_IoT_interface.h" @@ -163,7 +162,6 @@ extern void print_opp_meas(void); extern void init_eNB_afterRU(void); -extern void phy_free_RU(RU_t *); int transmission_mode=1; int emulate_rf = 0; @@ -296,11 +294,11 @@ static void get_options(void) { /* Read RC configuration file */ RCConfig(); NB_eNB_INST = RC.nb_inst; - LOG_I(ENB_APP,"Configuration: nb_rrc_inst %d, nb_L1_inst %d, nb_ru %d\n",NB_eNB_INST,RC.nb_L1_inst,RC.nb_RU); + printf("Configuration: nb_rrc_inst %d, nb_L1_inst %d, nb_ru %d\n",NB_eNB_INST,RC.nb_L1_inst,RC.nb_RU); if (!IS_SOFTMODEM_NONBIOT) { load_NB_IoT(); - LOG_I(ENB_APP," nb_nbiot_rrc_inst %d, nb_nbiot_L1_inst %d, nb_nbiot_macrlc_inst %d\n", + printf(" nb_nbiot_rrc_inst %d, nb_nbiot_L1_inst %d, nb_nbiot_macrlc_inst %d\n", RC.nb_nb_iot_rrc_inst, RC.nb_nb_iot_L1_inst, RC.nb_nb_iot_macrlc_inst); } else { printf("All Nb-IoT instances disabled\n"); @@ -532,25 +530,11 @@ int main( int argc, char **argv ) { } mode = normal_txrx; - + set_latency_target(); logInit(); printf("Reading in command-line options\n"); get_options (); - AssertFatal(!CONFIG_ISFLAGSET(CONFIG_ABORT),"Getting configuration failed\n"); - configure_linux(); - // to make a graceful exit when ctrl-c is pressed - signal(SIGSEGV, signal_handler); - signal(SIGINT, signal_handler); - signal(SIGTERM, signal_handler); - signal(SIGABRT, signal_handler); - cpuf=get_cpu_freq_GHz(); - - #ifndef PACKAGE_VERSION -# define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL" -#endif - LOG_I(HW, "OAI Version: %s\n", PACKAGE_VERSION); - if (is_nos1exec(argv[0]) ) set_softmodem_optmask(SOFTMODEM_NOS1_BIT); @@ -572,10 +556,30 @@ int main( int argc, char **argv ) { reset_opp_meas(); } + cpuf=get_cpu_freq_GHz(); + printf("ITTI init, useMME: %i\n",EPC_MODE_ENABLED); itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info); // allows to forward in wireshark L2 protocol for decoding + // initialize mscgen log after ITTI + if (get_softmodem_params()->start_msc) { + load_module_shlib("msc",NULL,0,&msc_interface); + } + + MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX); init_opt(); + signal(SIGSEGV, signal_handler); + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); + signal(SIGABRT, signal_handler); + check_clock(); +#ifndef PACKAGE_VERSION +# define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL" +#endif + LOG_I(HW, "Version: %s\n", PACKAGE_VERSION); + printf("Runtime table\n"); + fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx); + /* Read configuration */ if (RC.nb_inst > 0) { read_config_and_init(); @@ -596,7 +600,9 @@ int main( int argc, char **argv ) { } for (int enb_id = 0; enb_id < RC.nb_inst; enb_id++) { - openair_rrc_eNB_configuration(enb_id, &RC.rrc[enb_id]->configuration); + MessageDef *msg_p = itti_alloc_new_message (TASK_ENB_APP, RRC_CONFIGURATION_REQ); + RRC_CONFIGURATION_REQ(msg_p) = RC.rrc[enb_id]->configuration; + itti_send_msg_to_task (TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p); } } else { printf("RC.nb_inst = 0, Initializing L1\n"); @@ -619,6 +625,7 @@ int main( int argc, char **argv ) { // init UE_PF_PO and mutex lock pthread_mutex_init(&ue_pf_po_mutex, NULL); memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*MAX_MOBILES_PER_ENB*MAX_NUM_CCs); + mlockall(MCL_CURRENT | MCL_FUTURE); pthread_cond_init(&sync_cond,NULL); pthread_mutex_init(&sync_mutex, NULL); @@ -648,11 +655,11 @@ int main( int argc, char **argv ) { // for (inst=0;instinit_SI()->rrc_mac_config_req_eNB ()->phy_config_request () sets the wait_eNBs() tested flag - // wait_eNBs(); - // printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU); + printf("wait_eNBs()\n"); + wait_eNBs(); + printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU); // RU thread and some L1 procedure aren't necessary in VNF or L2 FAPI simulator. // but RU thread deals with pre_scd and this is necessary in VNF and simulator. @@ -664,7 +671,6 @@ int main( int argc, char **argv ) { for (ru_id=0; ru_idrf_map.card=0; RC.ru[ru_id]->rf_map.chain=CC_id+(get_softmodem_params()->chain_offset); - } } config_sync_var=0; @@ -675,12 +681,13 @@ int main( int argc, char **argv ) { printf("wait RUs\n"); // end of CI modifications - // fixme: very weird usage of bitmask - // lack of mutex in: ru_thread_prach(),... + fflush(stdout); + fflush(stderr); // wait_RUs() is wrong and over complex! wait_RUs(); LOG_I(ENB_APP,"RC.nb_RU:%d\n", RC.nb_RU); // once all RUs are ready intiailize the rest of the eNBs ((dependence on final RU parameters after configuration) + printf("ALL RUs ready - init eNBs\n"); if (NFAPI_MODE!=NFAPI_MODE_PNF && NFAPI_MODE!=NFAPI_MODE_VNF) { LOG_I(ENB_APP,"Not NFAPI mode - call init_eNB_afterRU()\n"); @@ -700,7 +707,6 @@ int main( int argc, char **argv ) { config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS); } - // wait for end of program LOG_UI(ENB_APP,"TYPE TO TERMINATE\n"); // CI -- Flushing the std outputs for the previous marker to show on the eNB / DU / CU log file fflush(stdout); @@ -726,6 +732,7 @@ int main( int argc, char **argv ) { * threads have been stopped (they partially use the same memory) */ for (int inst = 0; inst < NB_eNB_INST; inst++) { for (int cc_id = 0; cc_id < RC.nb_CC[inst]; cc_id++) { + free_transport(RC.eNB[inst][cc_id]); phy_free_lte_eNB(RC.eNB[inst][cc_id]); } } From db85b231221eadee1d616e937c681e993e43610a Mon Sep 17 00:00:00 2001 From: laurent Date: Fri, 5 Jul 2019 16:27:28 +0200 Subject: [PATCH 006/240] continue ocp-main.c --- executables/main-ocp.c | 427 +++++++++++++++++++++++------------------ 1 file changed, 241 insertions(+), 186 deletions(-) diff --git a/executables/main-ocp.c b/executables/main-ocp.c index cbd18c6541..93bf7d3daf 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -3,6 +3,15 @@ * Copyright: Open Cells Project company */ +/* + * This file replaces + * targets/RT/USER/lte-ru.c + * targets/RT/USER/lte-enb.c + * openair1/SCHED/prach_procedures.c + * The merger of OpenAir central code to this branch + * should check if these 3 files are modified and analyze if code code has to be copied in here + */ + #include #include static int DEFBANDS[] = {7}; @@ -16,6 +25,8 @@ static int DEFENBS[] = {0}; #include #include #include +#include + extern uint16_t sf_ahead; extern void oai_subframe_ind(uint16_t sfn, uint16_t sf); extern void fep_full(RU_t *ru); @@ -90,6 +101,7 @@ void init_RU_proc(RU_t *ru) { proc->frame_tx_unwrap = 0; for (i=0; i<10; i++) proc->symbol_mask[i]=0; + pthread_t t; threadCreate(&t, ru_thread, (void *)ru, "MainRu", -1, OAI_PRIORITY_RT_MAX); } @@ -198,7 +210,6 @@ void init_eNB_afterRU(void) { */ AssertFatal( eNB->frame_parms.nb_antennas_rx > 0 && eNB->frame_parms.nb_antennas_rx < 4, ""); AssertFatal( eNB->frame_parms.nb_antennas_tx > 0 && eNB->frame_parms.nb_antennas_rx < 4, ""); - LOG_I(PHY,"inst %d, CC_id %d : nb_antennas_rx %d\n",inst,CC_id,eNB->frame_parms.nb_antennas_rx); init_transport(eNB); //init_precoding_weights(RC.eNB[inst][CC_id]); @@ -280,7 +291,7 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) { cfg->tx_bw = 40e6; cfg->rx_bw = 40e6; } else { - printf("Wrong input for numerology %d\n setting to 20MHz normal CP configuration",numerology); + LOG_E(PHY,"Wrong input for numerology %d\n setting to 20MHz normal CP configuration",numerology); cfg->sample_rate=30.72e6; cfg->samples_per_frame = 307200; cfg->tx_bw = 10e6; @@ -320,11 +331,11 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) { cfg->tx_gain[i] = (double)ru->att_tx; cfg->rx_gain[i] = ru->max_rxgain-(double)ru->att_rx; cfg->configFilename = rf_config_file; - printf("channel %d, Setting tx_gain offset %f, rx_gain offset %f, tx_freq %f, rx_freq %f\n", - i, cfg->tx_gain[i], - cfg->rx_gain[i], - cfg->tx_freq[i], - cfg->rx_freq[i]); + LOG_I(PHY,"channel %d, Setting tx_gain offset %f, rx_gain offset %f, tx_freq %f, rx_freq %f\n", + i, cfg->tx_gain[i], + cfg->rx_gain[i], + cfg->tx_freq[i], + cfg->rx_freq[i]); } } @@ -333,42 +344,25 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) { rf_map specifies for each antenna port, on which rf chain the mapping should start. Multiple antennas are mapped to successive RF chains on the same card. */ int setup_RU_buffers(RU_t *ru) { - int i,j; - int card,ant; //uint16_t N_TA_offset = 0; LTE_DL_FRAME_PARMS *frame_parms; - - if (ru) { - frame_parms = &ru->frame_parms; - printf("setup_RU_buffers: frame_parms = %p\n",frame_parms); - } else { - printf("RU not initialized (NULL pointer)\n"); - return(-1); - } + AssertFatal(ru, "ru is NULL"); + frame_parms = &ru->frame_parms; + LOG_I(PHY,"setup_RU_buffers: frame_parms = %p\n",frame_parms); if (frame_parms->frame_type == TDD) { - if (frame_parms->N_RB_DL == 100) + if (frame_parms->N_RB_DL == 100) { ru->N_TA_offset = 624; - else if (frame_parms->N_RB_DL == 50) + } else if (frame_parms->N_RB_DL == 50) { ru->N_TA_offset = 624/2; - else if (frame_parms->N_RB_DL == 25) - ru->N_TA_offset = 624/4; - - if(IS_SOFTMODEM_BASICSIM) - /* this is required for the basic simulator in TDD mode - * TODO: find a proper cleaner solution - */ - ru->N_TA_offset = 0; - - if (frame_parms->N_RB_DL == 100) /* no scaling to do */; - else if (frame_parms->N_RB_DL == 50) { ru->sf_extension /= 2; ru->end_of_burst_delay /= 2; } else if (frame_parms->N_RB_DL == 25) { + ru->N_TA_offset = 624/4; ru->sf_extension /= 4; ru->end_of_burst_delay /= 4; } else { - printf("not handled, todo\n"); + LOG_E(PHY,"not handled, todo\n"); exit(1); } } else { @@ -377,39 +371,6 @@ int setup_RU_buffers(RU_t *ru) { ru->end_of_burst_delay = 0; } - if (ru->openair0_cfg.mmapped_dma == 1) { - // replace RX signal buffers with mmaped HW versions - for (i=0; inb_rx; i++) { - card = i/4; - ant = i%4; - printf("Mapping RU id %d, rx_ant %d, on card %d, chain %d\n",ru->idx,i,ru->rf_map.card+card, ru->rf_map.chain+ant); - free(ru->common.rxdata[i]); - ru->common.rxdata[i] = ru->openair0_cfg.rxbase[ru->rf_map.chain+ant]; - printf("rxdata[%d] @ %p\n",i,ru->common.rxdata[i]); - - for (j=0; j<16; j++) { - printf("rxbuffer %d: %x\n",j,ru->common.rxdata[i][j]); - ru->common.rxdata[i][j] = 16-j; - } - } - - for (i=0; inb_tx; i++) { - card = i/4; - ant = i%4; - printf("Mapping RU id %d, tx_ant %d, on card %d, chain %d\n",ru->idx,i,ru->rf_map.card+card, ru->rf_map.chain+ant); - free(ru->common.txdata[i]); - ru->common.txdata[i] = ru->openair0_cfg.txbase[ru->rf_map.chain+ant]; - printf("txdata[%d] @ %p\n",i,ru->common.txdata[i]); - - for (j=0; j<16; j++) { - printf("txbuffer %d: %x\n",j,ru->common.txdata[i][j]); - ru->common.txdata[i][j] = 16-j; - } - } - } else { // not memory-mapped DMA - //nothing to do, everything already allocated in lte_init - } - return(0); } @@ -447,30 +408,134 @@ void init_precoding_weights(PHY_VARS_eNB *eNB) { } } -void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { - L1_proc_t *proc = &eNB->proc; - LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; +void prach_procedures_ocp(PHY_VARS_eNB *eNB, int br_flag, int frame, int subframe) { + uint16_t max_preamble[4],max_preamble_energy[4],max_preamble_delay[4],avg_preamble_energy[4]; - // check if we have to detect PRACH first - if (is_prach_subframe(fp,frame,subframe)>0) { - // set timing for prach thread - proc->frame_prach = frame; - proc->subframe_prach = subframe; - prach_procedures(eNB,0); + if (br_flag==0) { + eNB->proc.frame_prach = frame; + eNB->proc.subframe_prach = subframe; + } else { + eNB->proc.frame_prach_br = frame; + eNB->proc.subframe_prach_br = subframe; } -} -void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { - L1_proc_t *proc = &eNB->proc; - LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + RU_t *ru; + int aa=0; + int ru_aa; + for (int i=0; inum_RU; i++) { + ru=eNB->RU_list[i]; + + for (ru_aa=0,aa=0; ru_aanb_rx; ru_aa++,aa++) { + eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[i]->prach_rxsigF[ru_aa]; + int ce_level; + + if (br_flag==1) + for (ce_level=0; ce_level<4; ce_level++) + eNB->prach_vars_br.rxsigF[ce_level][aa] = eNB->RU_list[i]->prach_rxsigF_br[ce_level][ru_aa]; + } + } + + // run PRACH detection for CE-level 0 only for now when br_flag is set + rx_prach(eNB, + eNB->RU_list[0], + &max_preamble[0], + &max_preamble_energy[0], + &max_preamble_delay[0], + &avg_preamble_energy[0], + frame, + 0 + ,br_flag + ); + + if (br_flag==1) { + int prach_mask; + prach_mask = is_prach_subframe (&eNB->frame_parms, eNB->proc.frame_prach_br, eNB->proc.subframe_prach_br); + eNB->UL_INFO.rach_ind_br.rach_indication_body.preamble_list = eNB->preamble_list_br; + int ind = 0; + int ce_level = 0; + /* Save for later, it doesn't work + for (int ind=0,ce_level=0;ce_level<4;ce_level++) { + + if ((eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[ce_level]==1)&& + (prach_mask&(1<<(1+ce_level)) > 0) && // prach is active and CE level has finished its repetitions + (eNB->prach_vars_br.repetition_number[ce_level]== + eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_numRepetitionPerPreambleAttempt[ce_level])) { + + */ + + if (eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[0] == 1) { + if ((eNB->prach_energy_counter == 100) && (max_preamble_energy[0] > eNB->measurements.prach_I0 + eNB->prach_DTX_threshold_emtc[0])) { + eNB->UL_INFO.rach_ind_br.rach_indication_body.number_of_preambles++; + eNB->preamble_list_br[ind].preamble_rel8.timing_advance = max_preamble_delay[ind]; // + eNB->preamble_list_br[ind].preamble_rel8.preamble = max_preamble[ind]; + // note: fid is implicitly 0 here, this is the rule for eMTC RA-RNTI from 36.321, Section 5.1.4 + eNB->preamble_list_br[ind].preamble_rel8.rnti = 1 + subframe + (60*(eNB->prach_vars_br.first_frame[ce_level] % 40)); + eNB->preamble_list_br[ind].instance_length = 0; //don't know exactly what this is + eNB->preamble_list_br[ind].preamble_rel13.rach_resource_type = 1 + ce_level; // CE Level + LOG_I (PHY, "Filling NFAPI indication for RACH %d CELevel %d (mask %x) : TA %d, Preamble %d, rnti %x, rach_resource_type %d\n", + ind, + ce_level, + prach_mask, + eNB->preamble_list_br[ind].preamble_rel8.timing_advance, + eNB->preamble_list_br[ind].preamble_rel8.preamble, eNB->preamble_list_br[ind].preamble_rel8.rnti, eNB->preamble_list_br[ind].preamble_rel13.rach_resource_type); + } + } + + /* + ind++; + } + } */// ce_level + } else if ((eNB->prach_energy_counter == 100) && + (max_preamble_energy[0] > eNB->measurements.prach_I0+eNB->prach_DTX_threshold)) { + LOG_I(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure with preamble %d, energy %d.%d dB, delay %d\n", + eNB->Mod_id, + eNB->CC_id, + frame, + subframe, + max_preamble[0], + max_preamble_energy[0]/10, + max_preamble_energy[0]%10, + max_preamble_delay[0]); + pthread_mutex_lock(&eNB->UL_INFO_mutex); + eNB->UL_INFO.rach_ind.rach_indication_body.number_of_preambles = 1; + eNB->UL_INFO.rach_ind.rach_indication_body.preamble_list = &eNB->preamble_list[0]; + eNB->UL_INFO.rach_ind.rach_indication_body.tl.tag = NFAPI_RACH_INDICATION_BODY_TAG; + eNB->UL_INFO.rach_ind.header.message_id = NFAPI_RACH_INDICATION; + eNB->UL_INFO.rach_ind.sfn_sf = frame<<4 | subframe; + eNB->preamble_list[0].preamble_rel8.tl.tag = NFAPI_PREAMBLE_REL8_TAG; + eNB->preamble_list[0].preamble_rel8.timing_advance = max_preamble_delay[0]; + eNB->preamble_list[0].preamble_rel8.preamble = max_preamble[0]; + eNB->preamble_list[0].preamble_rel8.rnti = 1+subframe; // note: fid is implicitly 0 here + eNB->preamble_list[0].preamble_rel13.rach_resource_type = 0; + eNB->preamble_list[0].instance_length = 0; //don't know exactly what this is + + if (NFAPI_MODE==NFAPI_MODE_PNF) { // If NFAPI PNF then we need to send the message to the VNF + LOG_D(PHY,"Filling NFAPI indication for RACH : SFN_SF:%d TA %d, Preamble %d, rnti %x, rach_resource_type %d\n", + NFAPI_SFNSF2DEC(eNB->UL_INFO.rach_ind.sfn_sf), + eNB->preamble_list[0].preamble_rel8.timing_advance, + eNB->preamble_list[0].preamble_rel8.preamble, + eNB->preamble_list[0].preamble_rel8.rnti, + eNB->preamble_list[0].preamble_rel13.rach_resource_type); + oai_nfapi_rach_ind(&eNB->UL_INFO.rach_ind); + eNB->UL_INFO.rach_ind.rach_indication_body.number_of_preambles = 0; + } + + pthread_mutex_unlock(&eNB->UL_INFO_mutex); + } // max_preamble_energy > prach_I0 + 100 + else { + eNB->measurements.prach_I0 = ((eNB->measurements.prach_I0*900)>>10) + ((avg_preamble_energy[0]*124)>>10); + + if (eNB->prach_energy_counter < 100) + eNB->prach_energy_counter++; + } +} // else br_flag + +void prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { // check if we have to detect PRACH first - if (is_prach_subframe(fp,frame,subframe)>0) { - LOG_D(PHY,"Triggering prach br processing, frame %d, subframe %d\n",frame,subframe); - // set timing for prach thread - proc->frame_prach_br = frame; - proc->subframe_prach_br = subframe; - prach_procedures(eNB,1); + if (is_prach_subframe(&eNB->frame_parms, frame,subframe)>0) { + prach_procedures_ocp(eNB, 0, frame, subframe); + prach_procedures_ocp(eNB, 1, frame, subframe); } } @@ -486,8 +551,7 @@ static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name AssertFatal( !(NFAPI_MODE==NFAPI_MODE_PNF && eNB->pdcch_vars[proc->subframe_tx&1].num_pdcch_symbols == 0), ""); - wakeup_prach_eNB(eNB,NULL,proc->frame_rx,proc->subframe_rx); - wakeup_prach_eNB_br(eNB,NULL,proc->frame_rx,proc->subframe_rx); + prach_eNB(eNB,NULL,proc->frame_rx,proc->subframe_rx); release_UE_in_freeList(eNB->Mod_id); // UE-specific RX processing for subframe n @@ -670,11 +734,7 @@ static void *ru_thread( void *param ) { openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); } - if (setup_RU_buffers(ru)!=0) { - printf("Exiting, cannot initialize RU Buffers\n"); - exit(-1); - } - + AssertFatal(setup_RU_buffers(ru)==0, "Exiting, cannot initialize RU Buffers\n"); LOG_I(PHY, "Signaling main thread that RU %d is ready\n",ru->idx); wait_sync("ru_thread"); @@ -732,7 +792,7 @@ static void *ru_thread( void *param ) { ru->fh_south_out(ru); } - printf( "Exiting ru_thread \n"); + LOG_W(PHY,"Exiting ru_thread \n"); if (ru->stop_rf != NULL) { if (ru->stop_rf(ru) != 0) @@ -769,10 +829,10 @@ void set_function_spec_param(RU_t *ru) { ru->stop_rf = stop_rf; ru->eNB_top=eNB_top; break; - - default: - LOG_E(PHY,"RU with invalid or unknown southbound interface type %d\n",ru->if_south); - break; + + default: + LOG_E(PHY,"RU with invalid or unknown southbound interface type %d\n",ru->if_south); + break; } // switch on interface type } @@ -788,7 +848,7 @@ void init_RU(char *rf_config_file, clock_source_t clock_source,clock_source_t ti pthread_mutex_init(&RC.ru_mutex,NULL); pthread_cond_init(&RC.ru_cond,NULL); // read in configuration file) - printf("configuring RU from file\n"); + LOG_I(PHY,"configuring RU from file\n"); RCconfig_RU(); LOG_I(PHY,"number of L1 instances %d, number of RU %d, number of CPU cores %d\n", RC.nb_L1_inst,RC.nb_RU,get_nprocs()); @@ -852,23 +912,17 @@ void init_RU(char *rf_config_file, clock_source_t clock_source,clock_source_t ti LOG_D(PHY, "eNB0:%p\n", eNB0); if (eNB0) { - if ((ru->function != NGFI_RRU_IF5) && (ru->function != NGFI_RRU_IF4p5)) - AssertFatal(eNB0!=NULL,"eNB0 is null!\n"); + LOG_I(PHY,"Copying frame parms from eNB %d to ru %d\n",eNB0->Mod_id,ru->idx); + memcpy((void *)&ru->frame_parms,(void *)&eNB0->frame_parms,sizeof(LTE_DL_FRAME_PARMS)); - if (eNB0) { - LOG_I(PHY,"Copying frame parms from eNB %d to ru %d\n",eNB0->Mod_id,ru->idx); - memcpy((void *)&ru->frame_parms,(void *)&eNB0->frame_parms,sizeof(LTE_DL_FRAME_PARMS)); - // attach all RU to all eNBs in its list/ - LOG_D(PHY,"ru->num_eNB:%d eNB0->num_RU:%d\n", ru->num_eNB, eNB0->num_RU); - - for (i=0; inum_eNB; i++) { - eNB0 = ru->eNB_list[i]; - eNB0->RU_list[eNB0->num_RU++] = ru; - } + for (i=0; inum_eNB; i++) { + eNB0 = ru->eNB_list[i]; + eNB0->RU_list[eNB0->num_RU++] = ru; } } - LOG_I(PHY,"Initializing RRU descriptor %d : (%s,%s,%d)\n",ru_id,ru_if_types[ru->if_south],eNB_timing[ru->if_timing],ru->function); + LOG_I(PHY,"Initializing RRU descriptor %d : (%s,%s,%d)\n", + ru_id,ru_if_types[ru->if_south],eNB_timing[ru->if_timing],ru->function); set_function_spec_param(ru); LOG_I(PHY,"Starting ru_thread %d\n",ru_id); init_RU_proc(ru); @@ -894,85 +948,86 @@ void RCconfig_RU(void) { paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0}; config_getlist( &RUParamList,RUParams,sizeof(RUParams)/sizeof(paramdef_t), NULL); - if ( RUParamList.numelt > 0) { - RC.ru = (RU_t **)malloc(RC.nb_RU*sizeof(RU_t *)); - - for (j = 0; j < RC.nb_RU; j++) { - RC.ru[j] = (RU_t *)malloc(sizeof(RU_t)); - memset((void *)RC.ru[j],0,sizeof(RU_t)); - RC.ru[j]->idx = j; - printf("Creating RC.ru[%d]:%p\n", j, RC.ru[j]); - RC.ru[j]->if_timing = synch_to_ext_device; - - if (RC.nb_L1_inst >0) - RC.ru[j]->num_eNB = RUParamList.paramarray[j][RU_ENB_LIST_IDX].numelt; - else - RC.ru[j]->num_eNB = 0; - - for (i=0; inum_eNB; i++) RC.ru[j]->eNB_list[i] = RC.eNB[RUParamList.paramarray[j][RU_ENB_LIST_IDX].iptr[i]][0]; - - if (config_isparamset(RUParamList.paramarray[j], RU_SDR_ADDRS)) { - RC.ru[j]->openair0_cfg.sdr_addrs = strdup(*(RUParamList.paramarray[j][RU_SDR_ADDRS].strptr)); - } - - if (config_isparamset(RUParamList.paramarray[j], RU_SDR_CLK_SRC)) { - if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "internal") == 0) { - RC.ru[j]->openair0_cfg.clock_source = internal; - LOG_D(PHY, "RU clock source set as internal\n"); - } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "external") == 0) { - RC.ru[j]->openair0_cfg.clock_source = external; - LOG_D(PHY, "RU clock source set as external\n"); - } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr), "gpsdo") == 0) { - RC.ru[j]->openair0_cfg.clock_source = gpsdo; - LOG_D(PHY, "RU clock source set as gpsdo\n"); - } else { - LOG_E(PHY, "Erroneous RU clock source in the provided configuration file: '%s'\n", *(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr)); - } - } - - if (strcmp(*(RUParamList.paramarray[j][RU_LOCAL_RF_IDX].strptr), "yes") == 0) { - if ( !(config_isparamset(RUParamList.paramarray[j],RU_LOCAL_IF_NAME_IDX)) ) { - RC.ru[j]->if_south = LOCAL_RF; - RC.ru[j]->function = eNodeB_3GPP; - printf("Setting function for RU %d to eNodeB_3GPP\n",j); - } else { - RC.ru[j]->eth_params.local_if_name = strdup(*(RUParamList.paramarray[j][RU_LOCAL_IF_NAME_IDX].strptr)); - RC.ru[j]->eth_params.my_addr = strdup(*(RUParamList.paramarray[j][RU_LOCAL_ADDRESS_IDX].strptr)); - RC.ru[j]->eth_params.remote_addr = strdup(*(RUParamList.paramarray[j][RU_REMOTE_ADDRESS_IDX].strptr)); - RC.ru[j]->eth_params.my_portc = *(RUParamList.paramarray[j][RU_LOCAL_PORTC_IDX].uptr); - RC.ru[j]->eth_params.remote_portc = *(RUParamList.paramarray[j][RU_REMOTE_PORTC_IDX].uptr); - RC.ru[j]->eth_params.my_portd = *(RUParamList.paramarray[j][RU_LOCAL_PORTD_IDX].uptr); - RC.ru[j]->eth_params.remote_portd = *(RUParamList.paramarray[j][RU_REMOTE_PORTD_IDX].uptr); - } - - RC.ru[j]->max_pdschReferenceSignalPower = *(RUParamList.paramarray[j][RU_MAX_RS_EPRE_IDX].uptr);; - RC.ru[j]->max_rxgain = *(RUParamList.paramarray[j][RU_MAX_RXGAIN_IDX].uptr); - RC.ru[j]->num_bands = RUParamList.paramarray[j][RU_BAND_LIST_IDX].numelt; - /* sf_extension is in unit of samples for 30.72MHz here, has to be scaled later */ - RC.ru[j]->sf_extension = *(RUParamList.paramarray[j][RU_SF_EXTENSION_IDX].uptr); - RC.ru[j]->end_of_burst_delay = *(RUParamList.paramarray[j][RU_END_OF_BURST_DELAY_IDX].uptr); - - for (i=0; inum_bands; i++) RC.ru[j]->band[i] = RUParamList.paramarray[j][RU_BAND_LIST_IDX].iptr[i]; - } //strcmp(local_rf, "yes") == 0 - else { - printf("RU %d: Transport %s\n",j,*(RUParamList.paramarray[j][RU_TRANSPORT_PREFERENCE_IDX].strptr)); - RC.ru[j]->eth_params.local_if_name = strdup(*(RUParamList.paramarray[j][RU_LOCAL_IF_NAME_IDX].strptr)); - RC.ru[j]->eth_params.my_addr = strdup(*(RUParamList.paramarray[j][RU_LOCAL_ADDRESS_IDX].strptr)); - RC.ru[j]->eth_params.remote_addr = strdup(*(RUParamList.paramarray[j][RU_REMOTE_ADDRESS_IDX].strptr)); - RC.ru[j]->eth_params.my_portc = *(RUParamList.paramarray[j][RU_LOCAL_PORTC_IDX].uptr); - RC.ru[j]->eth_params.remote_portc = *(RUParamList.paramarray[j][RU_REMOTE_PORTC_IDX].uptr); - RC.ru[j]->eth_params.my_portd = *(RUParamList.paramarray[j][RU_LOCAL_PORTD_IDX].uptr); - RC.ru[j]->eth_params.remote_portd = *(RUParamList.paramarray[j][RU_REMOTE_PORTD_IDX].uptr); - } /* strcmp(local_rf, "yes") != 0 */ - - RC.ru[j]->nb_tx = *(RUParamList.paramarray[j][RU_NB_TX_IDX].uptr); - RC.ru[j]->nb_rx = *(RUParamList.paramarray[j][RU_NB_RX_IDX].uptr); - RC.ru[j]->att_tx = *(RUParamList.paramarray[j][RU_ATT_TX_IDX].uptr); - RC.ru[j]->att_rx = *(RUParamList.paramarray[j][RU_ATT_RX_IDX].uptr); - }// j=0..num_rus - } else { + if ( RUParamList.numelt == 0 ) { RC.nb_RU = 0; + return; } // setting != NULL + RC.ru = (RU_t **)malloc(RC.nb_RU*sizeof(RU_t *)); + + for (j = 0; j < RC.nb_RU; j++) { + RC.ru[j] = (RU_t *)calloc(sizeof(RU_t), 1); + RC.ru[j]->idx = j; + LOG_I(PHY,"Creating RC.ru[%d]:%p\n", j, RC.ru[j]); + RC.ru[j]->if_timing = synch_to_ext_device; + paramdef_t *vals=RUParamList.paramarray[j]; + + if (RC.nb_L1_inst >0) + RC.ru[j]->num_eNB = vals[RU_ENB_LIST_IDX].numelt; + else + RC.ru[j]->num_eNB = 0; + + for (i=0; inum_eNB; i++) + RC.ru[j]->eNB_list[i] = RC.eNB[vals[RU_ENB_LIST_IDX].iptr[i]][0]; + + if (config_isparamset(vals, RU_SDR_ADDRS)) { + RC.ru[j]->openair0_cfg.sdr_addrs = strdup(*(vals[RU_SDR_ADDRS].strptr)); + } + + if (config_isparamset(vals, RU_SDR_CLK_SRC)) { + char *paramVal=*(vals[RU_SDR_CLK_SRC].strptr); + LOG_D(PHY, "RU clock source set as %s\n", paramVal); + + if (strcmp(paramVal, "internal") == 0) { + RC.ru[j]->openair0_cfg.clock_source = internal; + } else if (strcmp(paramVal, "external") == 0) { + RC.ru[j]->openair0_cfg.clock_source = external; + } else if (strcmp(paramVal, "gpsdo") == 0) { + RC.ru[j]->openair0_cfg.clock_source = gpsdo; + } else { + LOG_E(PHY, "Erroneous RU clock source in the provided configuration file: '%s'\n", paramVal); + } + } + + if (strcmp(*(vals[RU_LOCAL_RF_IDX].strptr), "yes") == 0) { + if ( !(config_isparamset(vals,RU_LOCAL_IF_NAME_IDX)) ) { + RC.ru[j]->if_south = LOCAL_RF; + RC.ru[j]->function = eNodeB_3GPP; + LOG_I(PHY, "Setting function for RU %d to eNodeB_3GPP\n",j); + } else { + RC.ru[j]->eth_params.local_if_name = strdup(*(vals[RU_LOCAL_IF_NAME_IDX].strptr)); + RC.ru[j]->eth_params.my_addr = strdup(*(vals[RU_LOCAL_ADDRESS_IDX].strptr)); + RC.ru[j]->eth_params.remote_addr = strdup(*(vals[RU_REMOTE_ADDRESS_IDX].strptr)); + RC.ru[j]->eth_params.my_portc = *(vals[RU_LOCAL_PORTC_IDX].uptr); + RC.ru[j]->eth_params.remote_portc = *(vals[RU_REMOTE_PORTC_IDX].uptr); + RC.ru[j]->eth_params.my_portd = *(vals[RU_LOCAL_PORTD_IDX].uptr); + RC.ru[j]->eth_params.remote_portd = *(vals[RU_REMOTE_PORTD_IDX].uptr); + } + + RC.ru[j]->max_pdschReferenceSignalPower = *(vals[RU_MAX_RS_EPRE_IDX].uptr);; + RC.ru[j]->max_rxgain = *(vals[RU_MAX_RXGAIN_IDX].uptr); + RC.ru[j]->num_bands = vals[RU_BAND_LIST_IDX].numelt; + /* sf_extension is in unit of samples for 30.72MHz here, has to be scaled later */ + RC.ru[j]->sf_extension = *(vals[RU_SF_EXTENSION_IDX].uptr); + RC.ru[j]->end_of_burst_delay = *(vals[RU_END_OF_BURST_DELAY_IDX].uptr); + + for (i=0; inum_bands; i++) RC.ru[j]->band[i] = vals[RU_BAND_LIST_IDX].iptr[i]; + } else { + LOG_I(PHY,"RU %d: Transport %s\n",j,*(vals[RU_TRANSPORT_PREFERENCE_IDX].strptr)); + RC.ru[j]->eth_params.local_if_name = strdup(*(vals[RU_LOCAL_IF_NAME_IDX].strptr)); + RC.ru[j]->eth_params.my_addr = strdup(*(vals[RU_LOCAL_ADDRESS_IDX].strptr)); + RC.ru[j]->eth_params.remote_addr = strdup(*(vals[RU_REMOTE_ADDRESS_IDX].strptr)); + RC.ru[j]->eth_params.my_portc = *(vals[RU_LOCAL_PORTC_IDX].uptr); + RC.ru[j]->eth_params.remote_portc = *(vals[RU_REMOTE_PORTC_IDX].uptr); + RC.ru[j]->eth_params.my_portd = *(vals[RU_LOCAL_PORTD_IDX].uptr); + RC.ru[j]->eth_params.remote_portd = *(vals[RU_REMOTE_PORTD_IDX].uptr); + } /* strcmp(local_rf, "yes") != 0 */ + + RC.ru[j]->nb_tx = *(vals[RU_NB_TX_IDX].uptr); + RC.ru[j]->nb_rx = *(vals[RU_NB_RX_IDX].uptr); + RC.ru[j]->att_tx = *(vals[RU_ATT_TX_IDX].uptr); + RC.ru[j]->att_rx = *(vals[RU_ATT_RX_IDX].uptr); + }// j=0..num_rus + return; } From 6b662a3ed9a2742871c5418332b65a3123565673 Mon Sep 17 00:00:00 2001 From: laurent Date: Fri, 12 Jul 2019 17:25:52 +0200 Subject: [PATCH 007/240] compiles --- cmake_targets/CMakeLists.txt | 2 + executables/dl_fs6.c | 157 +++++++++++++++++++++++++++++++--- executables/main-ocp.c | 32 ++++--- executables/split_headers.h | 21 ++++- executables/transport_split.c | 19 ++-- 5 files changed, 195 insertions(+), 36 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 552c5179b4..177de04a2d 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -2094,6 +2094,8 @@ target_link_libraries (lte-softmodem add_executable(ocp-softmodem ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c ${OPENAIR_DIR}/executables/main-ocp.c + ${OPENAIR_DIR}/executables/dl_fs6.c + ${OPENAIR_DIR}/executables/transport_split.c ${OPENAIR_TARGETS}/RT/USER/lte-softmodem.c ${OPENAIR_TARGETS}/RT/USER/lte-softmodem-common.c ${OPENAIR2_DIR}/ENB_APP/NB_IoT_interface.c diff --git a/executables/dl_fs6.c b/executables/dl_fs6.c index c583a4bc45..5ad6ddfd3b 100644 --- a/executables/dl_fs6.c +++ b/executables/dl_fs6.c @@ -1,5 +1,11 @@ -#include +#include +#include +#include +#include +#define FS6_BUF_SIZE 100*1000 +static int sockFS6; +#if 0 void pdsch_procedures(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, @@ -61,14 +67,15 @@ void pdsch_procedures(PHY_VARS_eNB *eNB, dlsch_harq->round++; } -phy_procedures_eNB_TX_fs6() { - receiveSubFrame(); +phy_procedures_eNB_TX_fs6(int sockFS6, uint64_t TS) { + uint8_t bufferZone[FS6_BUF_SIZE]; + receiveSubFrame(sockFS6, TS, bufferZone, sizeof(bufferZone) ); // We got // subframe number // - for (aa = 0; aa < fp->nb_antenna_ports_eNB; aa++) { + for (int aa = 0; aa < fp->nb_antenna_ports_eNB; aa++) { memset (&eNB->common_vars.txdataF[aa][subframe * fp->ofdm_symbol_size * fp->symbols_per_tti], 0, fp->ofdm_symbol_size * (fp->symbols_per_tti) * sizeof (int32_t)); @@ -178,17 +185,141 @@ phy_procedures_eNB_TX_fs6() { proc, AMP); } +#endif -DL_thread_fs6() { - receiveSubFrame(); - phy_procedures_eNB_TX_fs6(); - ru->feptx_prec(ru); - ru->feptx_ofdm(ru); - ru->fh_south_out(ru); +void prach_eNB_extract(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { } +void prach_eNB_process(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { +} +void phy_procedures_eNB_uespec_RX_extract(PHY_VARS_eNB *phy_vars_eNB,L1_rxtx_proc_t *proc) { +} -DL_thread_frequency() { - frequency_t header; - full_read(&header, \ No newline at end of file +void phy_procedures_eNB_uespec_RX_process(PHY_VARS_eNB *phy_vars_eNB,L1_rxtx_proc_t *proc) { +} + +void phy_procedures_eNB_TX_fs6() { +} + +void DL_du_fs6(RU_t *ru, int frame, int subframe, uint64_t TS) { + RU_proc_t *ru_proc=&ru->proc; + + for (int i=0; inum_eNB; i++) { + uint8_t bufferZone[FS6_BUF_SIZE]; + receiveSubFrame(sockFS6, TS, bufferZone, sizeof(bufferZone) ); + } + + phy_procedures_eNB_TX_fs6(); + /* Fixme: datamodel issue: a ru is supposed to be connected to several eNB + L1_rxtx_proc_t * L1_proc = &proc->L1_proc; + ru_proc->timestamp_tx = L1_proc->timestamp_tx; + ru_proc->subframe_tx = L1_proc->subframe_tx; + ru_proc->frame_tx = L1_proc->frame_tx; + */ + feptx_prec(ru); + feptx_ofdm(ru); + tx_rf(ru); +} + +void UL_du_fs6(RU_t *ru, int frame, int subframe) { + RU_proc_t *ru_proc=&ru->proc; + int tmpf=frame, tmpsf=subframe; + rx_rf(ru,&tmpf,&tmpsf); + AssertFatal(tmpf==frame && tmpsf==subframe, "lost synchronization\n"); + ru_proc->frame_tx = (ru_proc->frame_tx+ru_proc->frame_offset)&1023; + // Fixme: datamodel issue + PHY_VARS_eNB *eNB = RC.eNB[0][0]; + L1_proc_t *proc = &eNB->proc; + L1_rxtx_proc_t *L1_proc = &proc->L1_proc; + LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; + proc->frame_rx = frame; + proc->subframe_rx = subframe; + + if (NFAPI_MODE==NFAPI_MODE_PNF) { + // I am a PNF and I need to let nFAPI know that we have a (sub)frame tick + //add_subframe(&frame, &subframe, 4); + //oai_subframe_ind(proc->frame_tx, proc->subframe_tx); + oai_subframe_ind(proc->frame_rx, proc->subframe_rx); + } + + uint8_t bufferZone[FS6_BUF_SIZE]; + prach_eNB_extract(eNB,NULL,proc->frame_rx,proc->subframe_rx); + + if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { + phy_procedures_eNB_uespec_RX_extract(eNB, &proc->L1_proc); + } + + for (int i=0; inum_eNB; i++) { + sendSubFrame(sockFS6,bufferZone, sizeof(bufferZone) ); + } +} + +void DL_cu_fs6(RU_t *ru,int frame, int subframe) { + // Fixme: datamodel issue + PHY_VARS_eNB *eNB = RC.eNB[0][0]; + L1_proc_t *proc = &eNB->proc; + pthread_mutex_lock(&eNB->UL_INFO_mutex); + eNB->UL_INFO.frame = proc->frame_rx; + eNB->UL_INFO.subframe = proc->subframe_rx; + eNB->UL_INFO.module_id = eNB->Mod_id; + eNB->UL_INFO.CC_id = eNB->CC_id; + eNB->if_inst->UL_indication(&eNB->UL_INFO); + pthread_mutex_unlock(&eNB->UL_INFO_mutex); + uint8_t bufferZone[FS6_BUF_SIZE]; + phy_procedures_eNB_TX(eNB, &proc->L1_proc, 1); + sendSubFrame(sockFS6, bufferZone, sizeof(bufferZone) ); +} + +void UL_cu_fs6(RU_t *ru,int frame, int subframe, uint64_t TS) { + uint8_t bufferZone[FS6_BUF_SIZE]; + receiveSubFrame(sockFS6, TS, bufferZone, sizeof(bufferZone) ); + // Fixme: datamodel issue + PHY_VARS_eNB *eNB = RC.eNB[0][0]; + L1_proc_t *proc = &eNB->proc; + prach_eNB_process(eNB,NULL,proc->frame_rx,proc->subframe_rx); + release_UE_in_freeList(eNB->Mod_id); + + if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { + phy_procedures_eNB_uespec_RX_process(eNB, &proc->L1_proc); + } +} + +void *cu_fs6(void *arg) { + RU_t *ru = (RU_t *)arg; + RU_proc_t *proc = &ru->proc; + int64_t AbsoluteSubframe=-1; + init_frame_parms(&ru->frame_parms,1); + wait_sync("ru_thread"); + + while(1) { + AbsoluteSubframe++; + int subframe=AbsoluteSubframe%10; + int frame=(AbsoluteSubframe/10)%1024; + UL_cu_fs6(ru, frame,subframe, AbsoluteSubframe); + DL_cu_fs6(ru, frame,subframe); + } + + return NULL; +} + +void *du_fs6(void *arg) { + RU_t *ru = (RU_t *)arg; + RU_proc_t *proc = &ru->proc; + int64_t AbsoluteSubframe=-1; + fill_rf_config(ru,ru->rf_config_file); + init_frame_parms(&ru->frame_parms,1); + phy_init_RU(ru); + openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); + wait_sync("ru_thread"); + + while(1) { + AbsoluteSubframe++; + int subframe=AbsoluteSubframe%10; + int frame=(AbsoluteSubframe/10)%1024; + UL_du_fs6(ru, frame,subframe); + DL_du_fs6(ru, frame,subframe, AbsoluteSubframe); + } + + return NULL; +} diff --git a/executables/main-ocp.c b/executables/main-ocp.c index 93bf7d3daf..db64e47732 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -26,6 +26,7 @@ static int DEFENBS[] = {0}; #include #include #include +#include extern uint16_t sf_ahead; extern void oai_subframe_ind(uint16_t sfn, uint16_t sf); @@ -103,7 +104,17 @@ void init_RU_proc(RU_t *ru) { for (i=0; i<10; i++) proc->symbol_mask[i]=0; pthread_t t; - threadCreate(&t, ru_thread, (void *)ru, "MainRu", -1, OAI_PRIORITY_RT_MAX); + char *fs6=getenv("fs6"); + + if (fs6) { + if ( strncasecmp(fs6,"cu", 2) ) + threadCreate(&t, cu_fs6, (void *)ru, "MainCu", -1, OAI_PRIORITY_RT_MAX); + else if ( strncasecmp(fs6,"du", 2) ) + threadCreate(&t, du_fs6, (void *)ru, "MainDu", -1, OAI_PRIORITY_RT_MAX); + else + AssertFatal(false, "environement variable fs6 is not cu or du"); + } else + threadCreate(&t, ru_thread, (void *)ru, "MainRu", -1, OAI_PRIORITY_RT_MAX); } void init_transport(PHY_VARS_eNB *eNB) { @@ -719,13 +730,10 @@ void tx_rf(RU_t *ru) { } static void *ru_thread( void *param ) { - static int ru_thread_status; RU_t *ru = (RU_t *)param; RU_proc_t *proc = &ru->proc; int subframe =9; int frame =1023; - // set default return value - ru_thread_status = 0; if (ru->if_south == LOCAL_RF) { // configure RF parameters only fill_rf_config(ru,ru->rf_config_file); @@ -800,8 +808,7 @@ static void *ru_thread( void *param ) { else LOG_I(PHY,"RU %d rf device stopped\n",ru->idx); } - ru_thread_status = 0; - return &ru_thread_status; + return NULL; } int start_rf(RU_t *ru) { @@ -816,18 +823,15 @@ int stop_rf(RU_t *ru) { void set_function_spec_param(RU_t *ru) { switch (ru->if_south) { case LOCAL_RF: // this is an RU with integrated RF (RRU, eNB) - ru->do_prach = 0; // no prach processing in RU ru->feprx = fep_full; ru->feptx_ofdm = feptx_ofdm; ru->feptx_prec = feptx_prec; // this is fep with idft and precoding - ru->fh_north_in = NULL; // no incoming fronthaul from north - ru->start_if = NULL; // no if interface ru->rfdevice.host_type = RAU_HOST; - ru->fh_south_in = rx_rf; // local synchronous RF RX - ru->fh_south_out = tx_rf; // local synchronous RF TX - ru->start_rf = start_rf; // need to start the local RF interface - ru->stop_rf = stop_rf; - ru->eNB_top=eNB_top; + ru->fh_south_in = rx_rf; // local synchronous RF RX + ru->fh_south_out = tx_rf; // local synchronous RF TX + ru->start_rf = start_rf; // need to start the local RF interface + ru->stop_rf = stop_rf; + ru->eNB_top = eNB_top; break; default: diff --git a/executables/split_headers.h b/executables/split_headers.h index 3d59f3c199..68bb3925d7 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -1,6 +1,8 @@ #ifndef __SPLIT_HEADERS_H #define __SPLIT_HEADERS_H +#include +#include #define MTU 65536 #define UDP_TIMEOUT 100000L // in nano second #define MAX_BLOCKS 16 @@ -18,12 +20,27 @@ typedef struct frequency_s { int frame; int subframe; int sampleSize; - int nbAnt + int nbAnt; int nbSamples; } frequency_t; -int createListner (port); +int createListner (int port); int receiveSubFrame(int sock, uint64_t expectedTS, void *bufferZone, int bufferSize); int sendSubFrame(int sock, void *bufferZone, int nbBlocks); +inline size_t alignedSize(void *ptr) { + commonUDP_t *header=(commonUDP_t *) ptr; + return ((header->contentBytes+sizeof(commonUDP_t)+blockAlign-1)/blockAlign)*blockAlign; } + +void *cu_fs6(void *arg); +void *du_fs6(void *arg); +void fill_rf_config(RU_t *ru, char *rf_config_file); +void rx_rf(RU_t *ru,int *frame,int *subframe); +void tx_rf(RU_t *ru); + +// mistakes in main OAI +void phy_init_RU(RU_t *); +void feptx_prec(RU_t *); +void feptx_ofdm(RU_t *); +void oai_subframe_ind(uint16_t sfn, uint16_t sf); #endif diff --git a/executables/transport_split.c b/executables/transport_split.c index fe9e1a419c..c3819d665e 100644 --- a/executables/transport_split.c +++ b/executables/transport_split.c @@ -1,6 +1,10 @@ -#include +#include +#include /* See NOTES */ +#include +#include +#include -int createListner (port) { +int createListner (int port) { int sock; AssertFatal((sock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) >= 0, ""); struct sockaddr_in addr = { @@ -12,8 +16,8 @@ sin_addr: { s_addr: INADDR_ANY } }; int enable=1; - AssertFatal(setsockopt(eth->sockfdc, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable))==0,""); - AssertFatal(bind(sock, const struct sockaddr *addr, socklen_t addrlen)==0,""); + AssertFatal(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable))==0,""); + AssertFatal(bind(sock, (const struct sockaddr *) &addr, sizeof(addr))==0,""); struct timeval tv= {0,UDP_TIMEOUT}; AssertFatal(setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(tv)) ==0,""); // Make a send/recv buffer larger than a a couple of subframe @@ -28,6 +32,7 @@ sin_addr: // bufferZone: a reception area of bufferSize int receiveSubFrame(int sock, uint64_t expectedTS, void *bufferZone, int bufferSize) { int rcved=0; + commonUDP_t *tmp=NULL; do { //read all subframe data from the control unit @@ -41,7 +46,7 @@ int receiveSubFrame(int sock, uint64_t expectedTS, void *bufferZone, int buffer return -1; } } else { - commonUDP_t *tmp=(commonUDP_t *)bufferZone; + tmp=(commonUDP_t *)bufferZone; if ( expectedTS && tmp->timestamp != expectedTS) { LOG_W(HW,"Received a paquet in mixed subframes, dropping it\n"); @@ -50,9 +55,9 @@ int receiveSubFrame(int sock, uint64_t expectedTS, void *bufferZone, int buffer bufferZone+=ret; } } - } while ( !recved || recved < tmp->nbBlocks); + } while ( !rcved || rcved < tmp->nbBlocks); - return recv; + return rcved; } int sendSubFrame(int sock, void *bufferZone, int nbBlocks) { From 50aa4dcc584649e93db1fe825814e9619dcb742a Mon Sep 17 00:00:00 2001 From: ferrieux Date: Sat, 13 Jul 2019 22:06:34 +0200 Subject: [PATCH 008/240] test commit - just whitespace --- executables/transport_split.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/executables/transport_split.c b/executables/transport_split.c index c3819d665e..8f0ac5108c 100644 --- a/executables/transport_split.c +++ b/executables/transport_split.c @@ -55,7 +55,7 @@ int receiveSubFrame(int sock, uint64_t expectedTS, void *bufferZone, int buffer bufferZone+=ret; } } - } while ( !rcved || rcved < tmp->nbBlocks); + } while ( !rcved || rcved < tmp->nbBlocks ); return rcved; } From b8005ed09a07fc5142668a0ec19a5c80232810ee Mon Sep 17 00:00:00 2001 From: laurent Date: Mon, 15 Jul 2019 20:09:56 +0200 Subject: [PATCH 009/240] more code --- executables/dl_fs6.c | 77 ++++++++++++++++++++---------- executables/main-ocp.c | 4 +- executables/split_headers.h | 18 +++++-- executables/transport_split.c | 88 ++++++++++++++++++++++++++--------- 4 files changed, 136 insertions(+), 51 deletions(-) diff --git a/executables/dl_fs6.c b/executables/dl_fs6.c index 5ad6ddfd3b..2dcdca2365 100644 --- a/executables/dl_fs6.c +++ b/executables/dl_fs6.c @@ -4,7 +4,7 @@ #include #define FS6_BUF_SIZE 100*1000 -static int sockFS6; +static UDPsock_t sockFS6; #if 0 void pdsch_procedures(PHY_VARS_eNB *eNB, @@ -66,14 +66,26 @@ void pdsch_procedures(PHY_VARS_eNB *eNB, dlsch->active = 0; dlsch_harq->round++; } +#endif -phy_procedures_eNB_TX_fs6(int sockFS6, uint64_t TS) { - uint8_t bufferZone[FS6_BUF_SIZE]; - receiveSubFrame(sockFS6, TS, bufferZone, sizeof(bufferZone) ); - +void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas ) { // We got // subframe number // + int frame=proc->frame_tx; + int subframe=proc->subframe_tx; + uint32_t i,aa; + uint8_t harq_pid; + int16_t UE_id=0; + uint8_t num_pdcch_symbols=0; + uint8_t num_dci=0; +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + uint8_t num_mdci = 0; +#endif + uint8_t ul_subframe; + uint32_t ul_frame; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + LTE_UL_eNB_HARQ_t *ulsch_harq; for (int aa = 0; aa < fp->nb_antenna_ports_eNB; aa++) { memset (&eNB->common_vars.txdataF[aa][subframe * fp->ofdm_symbol_size * fp->symbols_per_tti], @@ -165,13 +177,15 @@ phy_procedures_eNB_TX_fs6(int sockFS6, uint64_t TS) { harq_pid,UE_id,frame,subframe,dlsch0->rnti); } else { // generate pdsch - pdsch_procedures_fs6(eNB, - proc, - harq_pid, - dlsch0, - dlsch1, - &eNB->UE_stats[(uint32_t)UE_id], - 0); + /* + pdsch_procedures_fs6(eNB, + proc, + harq_pid, + dlsch0, + dlsch1, + &eNB->UE_stats[(uint32_t)UE_id], + 0); + */ } } else if ((dlsch0)&&(dlsch0->rnti>0)&& (dlsch0->active == 0) @@ -185,21 +199,32 @@ phy_procedures_eNB_TX_fs6(int sockFS6, uint64_t TS) { proc, AMP); } -#endif -void prach_eNB_extract(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { +void prach_eNB_extract(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe, uint8_t *buf, int bufSize) { + commonUDP_t *header=(commonUDP_t *) buf; + header->contentBytes=1000; + header->nbBlocks=1; + return; } void prach_eNB_process(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { } -void phy_procedures_eNB_uespec_RX_extract(PHY_VARS_eNB *phy_vars_eNB,L1_rxtx_proc_t *proc) { +void phy_procedures_eNB_uespec_RX_extract(PHY_VARS_eNB *phy_vars_eNB,L1_rxtx_proc_t *proc, uint8_t *buf, int bufSize) { + commonUDP_t *header=(commonUDP_t *) buf; + header->contentBytes=1000; + header->nbBlocks=1; + return; } void phy_procedures_eNB_uespec_RX_process(PHY_VARS_eNB *phy_vars_eNB,L1_rxtx_proc_t *proc) { } -void phy_procedures_eNB_TX_fs6() { +void phy_procedures_eNB_TX_extract(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas, uint8_t *buf, int bufSize) { + commonUDP_t *header=(commonUDP_t *) buf; + header->contentBytes=1000; + header->nbBlocks=1; + return; } void DL_du_fs6(RU_t *ru, int frame, int subframe, uint64_t TS) { @@ -207,10 +232,10 @@ void DL_du_fs6(RU_t *ru, int frame, int subframe, uint64_t TS) { for (int i=0; inum_eNB; i++) { uint8_t bufferZone[FS6_BUF_SIZE]; - receiveSubFrame(sockFS6, TS, bufferZone, sizeof(bufferZone) ); + receiveSubFrame(&sockFS6, TS, bufferZone, sizeof(bufferZone) ); + phy_procedures_eNB_TX_process( bufferZone, sizeof(bufferZone), ru->eNB_list[i], &ru->eNB_list[i]->proc.L1_proc, 1); } - phy_procedures_eNB_TX_fs6(); /* Fixme: datamodel issue: a ru is supposed to be connected to several eNB L1_rxtx_proc_t * L1_proc = &proc->L1_proc; ru_proc->timestamp_tx = L1_proc->timestamp_tx; @@ -244,14 +269,14 @@ void UL_du_fs6(RU_t *ru, int frame, int subframe) { } uint8_t bufferZone[FS6_BUF_SIZE]; - prach_eNB_extract(eNB,NULL,proc->frame_rx,proc->subframe_rx); + prach_eNB_extract(eNB,NULL,proc->frame_rx,proc->subframe_rx, bufferZone, FS6_BUF_SIZE); if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { - phy_procedures_eNB_uespec_RX_extract(eNB, &proc->L1_proc); + phy_procedures_eNB_uespec_RX_extract(eNB, &proc->L1_proc, bufferZone, FS6_BUF_SIZE); } for (int i=0; inum_eNB; i++) { - sendSubFrame(sockFS6,bufferZone, sizeof(bufferZone) ); + sendSubFrame(&sockFS6,bufferZone); } } @@ -267,13 +292,13 @@ void DL_cu_fs6(RU_t *ru,int frame, int subframe) { eNB->if_inst->UL_indication(&eNB->UL_INFO); pthread_mutex_unlock(&eNB->UL_INFO_mutex); uint8_t bufferZone[FS6_BUF_SIZE]; - phy_procedures_eNB_TX(eNB, &proc->L1_proc, 1); - sendSubFrame(sockFS6, bufferZone, sizeof(bufferZone) ); + phy_procedures_eNB_TX_extract(eNB, &proc->L1_proc, 1, bufferZone, FS6_BUF_SIZE); + sendSubFrame(&sockFS6, bufferZone ); } void UL_cu_fs6(RU_t *ru,int frame, int subframe, uint64_t TS) { uint8_t bufferZone[FS6_BUF_SIZE]; - receiveSubFrame(sockFS6, TS, bufferZone, sizeof(bufferZone) ); + receiveSubFrame(&sockFS6, TS, bufferZone, sizeof(bufferZone) ); // Fixme: datamodel issue PHY_VARS_eNB *eNB = RC.eNB[0][0]; L1_proc_t *proc = &eNB->proc; @@ -289,8 +314,11 @@ void *cu_fs6(void *arg) { RU_t *ru = (RU_t *)arg; RU_proc_t *proc = &ru->proc; int64_t AbsoluteSubframe=-1; + fill_rf_config(ru,ru->rf_config_file); init_frame_parms(&ru->frame_parms,1); + phy_init_RU(ru); wait_sync("ru_thread"); + AssertFatal(createUDPsock(NULL, "8888", "127.0.0.1", "7777", &sockFS6), ""); while(1) { AbsoluteSubframe++; @@ -312,6 +340,7 @@ void *du_fs6(void *arg) { phy_init_RU(ru); openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); wait_sync("ru_thread"); + AssertFatal(createUDPsock(NULL, "7777", "127.0.0.1", "8888", &sockFS6),""); while(1) { AbsoluteSubframe++; diff --git a/executables/main-ocp.c b/executables/main-ocp.c index db64e47732..13464ed166 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -107,9 +107,9 @@ void init_RU_proc(RU_t *ru) { char *fs6=getenv("fs6"); if (fs6) { - if ( strncasecmp(fs6,"cu", 2) ) + if ( strncasecmp(fs6,"cu", 2) == 0 ) threadCreate(&t, cu_fs6, (void *)ru, "MainCu", -1, OAI_PRIORITY_RT_MAX); - else if ( strncasecmp(fs6,"du", 2) ) + else if ( strncasecmp(fs6,"du", 2) == 0 ) threadCreate(&t, du_fs6, (void *)ru, "MainDu", -1, OAI_PRIORITY_RT_MAX); else AssertFatal(false, "environement variable fs6 is not cu or du"); diff --git a/executables/split_headers.h b/executables/split_headers.h index 68bb3925d7..064615284f 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -2,12 +2,22 @@ #define __SPLIT_HEADERS_H #include +#include #include #define MTU 65536 #define UDP_TIMEOUT 100000L // in nano second #define MAX_BLOCKS 16 #define blockAlign 32 //bytes +typedef struct { + char *sourceIP; + char *sourcePort; + char *destIP; + char *destPort; + struct addrinfo *destAddr; + int sockHandler; +} UDPsock_t; + typedef struct commonUDP_s { uint64_t timestamp; // id of the group (subframe for LTE) uint16_t nbBlocks; // total number of blocks for this timestamp @@ -24,9 +34,9 @@ typedef struct frequency_s { int nbSamples; } frequency_t; -int createListner (int port); -int receiveSubFrame(int sock, uint64_t expectedTS, void *bufferZone, int bufferSize); -int sendSubFrame(int sock, void *bufferZone, int nbBlocks); +bool createUDPsock (char *sourceIP, char *sourcePort, char *destIP, char *destPort, UDPsock_t *result); +int receiveSubFrame(UDPsock_t *sock, uint64_t expectedTS, void *bufferZone, int bufferSize); +int sendSubFrame(UDPsock_t *sock, void *bufferZone); inline size_t alignedSize(void *ptr) { commonUDP_t *header=(commonUDP_t *) ptr; return ((header->contentBytes+sizeof(commonUDP_t)+blockAlign-1)/blockAlign)*blockAlign; @@ -37,6 +47,8 @@ void *du_fs6(void *arg); void fill_rf_config(RU_t *ru, char *rf_config_file); void rx_rf(RU_t *ru,int *frame,int *subframe); void tx_rf(RU_t *ru); +void common_signal_procedures (PHY_VARS_eNB *eNB,int frame, int subframe); +void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc); // mistakes in main OAI void phy_init_RU(RU_t *); diff --git a/executables/transport_split.c b/executables/transport_split.c index 8f0ac5108c..00de32a156 100644 --- a/executables/transport_split.c +++ b/executables/transport_split.c @@ -3,40 +3,79 @@ #include #include #include +#include + +bool createUDPsock (char *sourceIP, char *sourcePort, char *destIP, char *destPort, UDPsock_t *result) { + struct addrinfo hints= {0}, *servinfo, *p; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_flags = AI_PASSIVE; + int status; + + if ((status = getaddrinfo(sourceIP, sourcePort, &hints, &servinfo)) != 0) { + LOG_E(GTPU,"getaddrinfo error: %s\n", gai_strerror(status)); + return false; + } + + // loop through all the results and bind to the first we can + for(p = servinfo; p != NULL; p = p->ai_next) { + if ((result->sockHandler = socket(p->ai_family, p->ai_socktype, + p->ai_protocol)) == -1) { + LOG_W(GTPU,"socket: %s\n", strerror(errno)); + continue; + } + + if (bind(result->sockHandler, p->ai_addr, p->ai_addrlen) == -1) { + close(result->sockHandler); + LOG_W(GTPU,"bind: %s\n", strerror(errno)); + continue; + } + + break; // if we get here, we must have connected successfully + } + + if (p == NULL) { + // looped off the end of the list with no successful bind + LOG_E(GTPU,"failed to bind socket: %s %s \n",sourceIP,sourcePort); + return false; + } + + freeaddrinfo(servinfo); // all done with this structure + + if ((status = getaddrinfo(destIP, destPort, &hints, &servinfo)) != 0) { + LOG_E(GTPU,"getaddrinfo error: %s\n", gai_strerror(status)); + return false; + } + + if (servinfo) { + result->destAddr=servinfo; + } else { + LOG_E(PHY,"No valid UDP addr: %s:%s\n",destIP, destPort); + return false; + } -int createListner (int port) { - int sock; - AssertFatal((sock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) >= 0, ""); - struct sockaddr_in addr = { -sin_family: - AF_INET, -sin_port: - htons(port), -sin_addr: - { s_addr: INADDR_ANY } - }; int enable=1; - AssertFatal(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable))==0,""); - AssertFatal(bind(sock, (const struct sockaddr *) &addr, sizeof(addr))==0,""); + AssertFatal(setsockopt(result->sockHandler, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable))==0,""); struct timeval tv= {0,UDP_TIMEOUT}; - AssertFatal(setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(tv)) ==0,""); + AssertFatal(setsockopt(result->sockHandler, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(tv)) ==0,""); // Make a send/recv buffer larger than a a couple of subframe // so the kernel will store for us in and out paquets int buff=1000*1000*10; - AssertFatal ( setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &buff, sizeof(buff)) == 0, ""); - AssertFatal ( setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &buff, sizeof(buff)) == 0, ""); + AssertFatal ( setsockopt(result->sockHandler, SOL_SOCKET, SO_SNDBUF, &buff, sizeof(buff)) == 0, ""); + AssertFatal ( setsockopt(result->sockHandler, SOL_SOCKET, SO_RCVBUF, &buff, sizeof(buff)) == 0, ""); + return true; } // sock: udp socket // expectedTS: the expected timestamp, 0 if unknown // bufferZone: a reception area of bufferSize -int receiveSubFrame(int sock, uint64_t expectedTS, void *bufferZone, int bufferSize) { +int receiveSubFrame(UDPsock_t *sock, uint64_t expectedTS, void *bufferZone, int bufferSize) { int rcved=0; commonUDP_t *tmp=NULL; do { //read all subframe data from the control unit - int ret=recv(sock, bufferZone, bufferSize, 0); + int ret=recv(sock->sockHandler, bufferZone, bufferSize, 0); if ( ret==-1) { if ( errno == EWOULDBLOCK || errno== EINTR ) { @@ -60,14 +99,19 @@ int receiveSubFrame(int sock, uint64_t expectedTS, void *bufferZone, int buffer return rcved; } -int sendSubFrame(int sock, void *bufferZone, int nbBlocks) { +int sendSubFrame(UDPsock_t *sock, void *bufferZone) { + commonUDP_t *header=(commonUDP_t *)bufferZone ; + int nbBlocks=header->nbBlocks; + do { int sz=alignedSize(bufferZone); - int ret=send(sock, bufferZone, sz, 0); + // Let's use the first address returned by getaddrinfo() + int ret=sendto(sock->sockHandler, bufferZone, sz, 0, + sock->destAddr->ai_addr, sock->destAddr->ai_addrlen); if ( ret != sz ) - LOG_W(HW,"Wrote socket doesn't return size %d (val: %d, errno:%d)\n", - sz, ret, errno); + LOG_W(HW,"Wrote socket doesn't return size %d (val: %d, errno:%d, %s)\n", + sz, ret, errno, strerror(errno)); bufferZone+=sz; nbBlocks--; From 8f3a5d455c921b41089c0969cbb6a0b06a6e11e0 Mon Sep 17 00:00:00 2001 From: laurent Date: Tue, 16 Jul 2019 20:50:31 +0200 Subject: [PATCH 010/240] continue coding DL --- executables/dl_fs6.c | 355 +++++++++++++++++++++++++++---------------- 1 file changed, 224 insertions(+), 131 deletions(-) diff --git a/executables/dl_fs6.c b/executables/dl_fs6.c index 2dcdca2365..6b80369895 100644 --- a/executables/dl_fs6.c +++ b/executables/dl_fs6.c @@ -5,6 +5,7 @@ #define FS6_BUF_SIZE 100*1000 static UDPsock_t sockFS6; + #if 0 void pdsch_procedures(PHY_VARS_eNB *eNB, @@ -68,137 +69,6 @@ void pdsch_procedures(PHY_VARS_eNB *eNB, } #endif -void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas ) { - // We got - // subframe number - // - int frame=proc->frame_tx; - int subframe=proc->subframe_tx; - uint32_t i,aa; - uint8_t harq_pid; - int16_t UE_id=0; - uint8_t num_pdcch_symbols=0; - uint8_t num_dci=0; -#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) - uint8_t num_mdci = 0; -#endif - uint8_t ul_subframe; - uint32_t ul_frame; - LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - LTE_UL_eNB_HARQ_t *ulsch_harq; - - for (int aa = 0; aa < fp->nb_antenna_ports_eNB; aa++) { - memset (&eNB->common_vars.txdataF[aa][subframe * fp->ofdm_symbol_size * fp->symbols_per_tti], - 0, - fp->ofdm_symbol_size * (fp->symbols_per_tti) * sizeof (int32_t)); - } - - if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { - if (is_pmch_subframe(frame,subframe,fp)) { - pmch_procedures(eNB,proc); - } else { - // this is not a pmch subframe, so generate PSS/SSS/PBCH - common_signal_procedures(eNB,proc->frame_tx, proc->subframe_tx); - } - } - - if (ul_subframe < 10)if (ul_subframe < 10) { // This means that there is a potential UL subframe that will be scheduled here - for (i=0; i= MAKE_VERSION(14, 0, 0)) - - if (eNB->ulsch[i] && eNB->ulsch[i]->ue_type >0) harq_pid = 0; - else -#endif - harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe); - - if (eNB->ulsch[i]) { - ulsch_harq = eNB->ulsch[i]->harq_processes[harq_pid]; - /* Store first_rb and n_DMRS for correct PHICH generation below. - * For PHICH generation we need "old" values of last scheduling - * for this HARQ process. 'generate_eNB_dlsch_params' below will - * overwrite first_rb and n_DMRS and 'generate_phich_top', done - * after 'generate_eNB_dlsch_params', would use the "new" values - * instead of the "old" ones. - * - * This has been tested for FDD only, may be wrong for TDD. - * - * TODO: maybe we should restructure the code to be sure it - * is done correctly. The main concern is if the code - * changes and first_rb and n_DMRS are modified before - * we reach here, then the PHICH processing will be wrong, - * using wrong first_rb and n_DMRS values to compute - * ngroup_PHICH and nseq_PHICH. - * - * TODO: check if that works with TDD. - */ - ulsch_harq->previous_first_rb = ulsch_harq->first_rb; - ulsch_harq->previous_n_DMRS = ulsch_harq->n_DMRS; - } - } - } - - num_pdcch_symbols = eNB->pdcch_vars[subframe&1].num_pdcch_symbols; - num_dci = eNB->pdcch_vars[subframe&1].num_dci; - - if (num_dci > 0) - if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { - generate_dci_top(num_pdcch_symbols, - num_dci, - &eNB->pdcch_vars[subframe&1].dci_alloc[0], - 0, - AMP, - fp, - eNB->common_vars.txdataF, - subframe); - num_mdci = eNB->mpdcch_vars[subframe &1].num_dci; - - if (num_mdci > 0) { - generate_mdci_top (eNB, frame, subframe, AMP, eNB->common_vars.txdataF); - } - } - - // Now scan UE specific DLSCH - LTE_eNB_DLSCH_t *dlsch0,*dlsch1; - - for (UE_id=0; UE_iddlsch[(uint8_t)UE_id][0]; - dlsch1 = eNB->dlsch[(uint8_t)UE_id][1]; - - if ((dlsch0)&&(dlsch0->rnti>0)&& - (dlsch0->active == 1) - ) { - // get harq_pid - harq_pid = dlsch0->harq_ids[frame%2][subframe]; - AssertFatal(harq_pid>=0,"harq_pid is negative\n"); - - if (harq_pid>=8) { - if (dlsch0->ue_type==0) - LOG_E(PHY,"harq_pid:%d corrupt must be 0-7 UE_id:%d frame:%d subframe:%d rnti:%x \n", - harq_pid,UE_id,frame,subframe,dlsch0->rnti); - } else { - // generate pdsch - /* - pdsch_procedures_fs6(eNB, - proc, - harq_pid, - dlsch0, - dlsch1, - &eNB->UE_stats[(uint32_t)UE_id], - 0); - */ - } - } else if ((dlsch0)&&(dlsch0->rnti>0)&& - (dlsch0->active == 0) - ) { - // clear subframe TX flag since UE is not scheduled for PDSCH in this subframe (so that we don't look for PUCCH later) - dlsch0->subframe_tx[subframe]=0; - } - } - - generate_phich_top(eNB, - proc, - AMP); -} void prach_eNB_extract(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe, uint8_t *buf, int bufSize) { commonUDP_t *header=(commonUDP_t *) buf; @@ -220,7 +90,230 @@ void phy_procedures_eNB_uespec_RX_extract(PHY_VARS_eNB *phy_vars_eNB,L1_rxtx_pro void phy_procedures_eNB_uespec_RX_process(PHY_VARS_eNB *phy_vars_eNB,L1_rxtx_proc_t *proc) { } +typedef struct { + int frame; + int subframe; + int num_pdcch_symbols; + int num_dci; + int amp; + bool UE_active[NUMBER_OF_UE_MAX]; + LTE_eNB_PHICH phich_vars; +} fs6_dl_t; + +void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas ) { + // TBD: read frame&subframe from received data + int frame=proc->frame_tx; + int subframe=proc->subframe_tx; + uint32_t i,aa; + uint8_t harq_pid; + uint8_t num_pdcch_symbols=0; + uint8_t num_dci=0; + uint8_t num_mdci = 0; + uint8_t ul_subframe; + uint32_t ul_frame; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + LTE_UL_eNB_HARQ_t *ulsch_harq; + + if (do_meas==1) { + start_meas(&eNB->phy_proc_tx); + start_meas(&eNB->dlsch_common_and_dci); + } + + // clear the transmit data array for the current subframe + for (aa = 0; aa < fp->nb_antenna_ports_eNB; aa++) { + memset (&eNB->common_vars.txdataF[aa][subframe * fp->ofdm_symbol_size * (fp->symbols_per_tti)], + 0, fp->ofdm_symbol_size * (fp->symbols_per_tti) * sizeof (int32_t)); + } + + if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { + if (is_pmch_subframe(frame,subframe,fp)) { + pmch_procedures(eNB,proc); + } else { + // this is not a pmch subframe, so generate PSS/SSS/PBCH + common_signal_procedures(eNB,proc->frame_tx, proc->subframe_tx); + } + } + + // clear existing ulsch dci allocations before applying info from MAC (this is table + ul_subframe = pdcch_alloc2ul_subframe (fp, subframe); + ul_frame = pdcch_alloc2ul_frame (fp, frame, subframe); + + // clear previous allocation information for all UEs + for (i = 0; i < NUMBER_OF_UE_MAX; i++) { + if (eNB->dlsch[i][0]) + eNB->dlsch[i][0]->subframe_tx[subframe] = 0; + } + + if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { + generate_dci_top(header->num_pdcch_symbols, + header->num_dci, + &eNB->pdcch_vars[subframe&1].dci_alloc[0], + 0, + headerAMP, + fp, + eNB->common_vars.txdataF, + header->subframe); + num_mdci = eNB->mpdcch_vars[subframe &1].num_dci; + + if (num_mdci > 0) { + LOG_D (PHY, "[eNB %" PRIu8 "] Frame %d, subframe %d: Calling generate_mdci_top (mpdcch) (num_dci %" PRIu8 ")\n", eNB->Mod_id, frame, subframe, num_mdci); + generate_mdci_top (eNB, frame, subframe, AMP, eNB->common_vars.txdataF); + } + } + + for (int UE_id=0; UE_iddlsch[UE_id][0]; + dlsch1 = eNB->dlsch[UE_id][1]; + pdsch_procedures(eNB, + proc, + harq_pid, + dlsch0, + dlsch1); + } + } + + eNB->phich_vars[subframe&1]=header.phich_vars; + generate_phich_top(eNB, + proc, + AMP); +} + void phy_procedures_eNB_TX_extract(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas, uint8_t *buf, int bufSize) { + int frame=proc->frame_tx; + int subframe=proc->subframe_tx; + uint32_t i,aa; + uint8_t harq_pid; + uint8_t num_pdcch_symbols=0; + uint8_t num_dci=0; + uint8_t num_mdci = 0; + uint8_t ul_subframe; + uint32_t ul_frame; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + LTE_UL_eNB_HARQ_t *ulsch_harq; + + if ((fp->frame_type == TDD) && (subframe_select (fp, subframe) == SF_UL)) + return; + + header.frame=frame; + header.subframe=subframe; + // clear existing ulsch dci allocations before applying info from MAC (this is table + ul_subframe = pdcch_alloc2ul_subframe (fp, subframe); + ul_frame = pdcch_alloc2ul_frame (fp, frame, subframe); + + // clear previous allocation information for all UEs + for (i = 0; i < NUMBER_OF_UE_MAX; i++) { + if (eNB->dlsch[i][0]) + eNB->dlsch[i][0]->subframe_tx[subframe] = 0; + } + + /* TODO: check the following test - in the meantime it is put back as it was before */ + //if ((ul_subframe < 10)&& + // (subframe_select(fp,ul_subframe)==SF_UL)) { // This means that there is a potential UL subframe that will be scheduled here + if (ul_subframe < 10) { // This means that there is a potential UL subframe that will be scheduled here + for (i=0; iulsch[i] && eNB->ulsch[i]->ue_type >0) harq_pid = 0; + else + harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe); + + if (eNB->ulsch[i]) { + ulsch_harq = eNB->ulsch[i]->harq_processes[harq_pid]; + /* Store first_rb and n_DMRS for correct PHICH generation below. + * For PHICH generation we need "old" values of last scheduling + * for this HARQ process. 'generate_eNB_dlsch_params' below will + * overwrite first_rb and n_DMRS and 'generate_phich_top', done + * after 'generate_eNB_dlsch_params', would use the "new" values + * instead of the "old" ones. + * + * This has been tested for FDD only, may be wrong for TDD. + * + * TODO: maybe we should restructure the code to be sure it + * is done correctly. The main concern is if the code + * changes and first_rb and n_DMRS are modified before + * we reach here, then the PHICH processing will be wrong, + * using wrong first_rb and n_DMRS values to compute + * ngroup_PHICH and nseq_PHICH. + * + * TODO: check if that works with TDD. + */ + ulsch_harq->previous_first_rb = ulsch_harq->first_rb; + ulsch_harq->previous_n_DMRS = ulsch_harq->n_DMRS; + } + } + } + + num_pdcch_symbols = eNB->pdcch_vars[subframe&1].num_pdcch_symbols; + num_dci = eNB->pdcch_vars[subframe&1].num_dci; + LOG_D(PHY,"num_pdcch_symbols %"PRIu8",number dci %"PRIu8"\n",num_pdcch_symbols, num_dci); + + if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { + header.num_pdcch_symbols=num_pdcch_symbols; + header.num_dci=num_dci; + header.amp=AMP; + } + + if (do_meas==1) stop_meas(&eNB->dlsch_common_and_dci); + + if (do_meas==1) start_meas(&eNB->dlsch_ue_specific); + + // Now scan UE specific DLSCH + LTE_eNB_DLSCH_t *dlsch0,*dlsch1; + + for (int UE_id=0; UE_iddlsch[UE_id][0]; + dlsch1 = eNB->dlsch[UE_id][1]; + + if ((dlsch0)&&(dlsch0->rnti>0)&& +#ifdef PHY_TX_THREAD + (dlsch0->active[subframe] == 1) +#else + (dlsch0->active == 1) +#endif + ) { + // get harq_pid + harq_pid = dlsch0->harq_ids[frame%2][subframe]; + AssertFatal(harq_pid>=0,"harq_pid is negative\n"); + + if (harq_pid>=8) { + if (dlsch0->ue_type==0) + LOG_E(PHY,"harq_pid:%d corrupt must be 0-7 UE_id:%d frame:%d subframe:%d rnti:%x [ %1d.%1d.%1d.%1d.%1d.%1d.%1d.%1d\n", harq_pid,UE_id,frame,subframe,dlsch0->rnti, + dlsch0->harq_ids[frame%2][0], + dlsch0->harq_ids[frame%2][1], + dlsch0->harq_ids[frame%2][2], + dlsch0->harq_ids[frame%2][3], + dlsch0->harq_ids[frame%2][4], + dlsch0->harq_ids[frame%2][5], + dlsch0->harq_ids[frame%2][6], + dlsch0->harq_ids[frame%2][7]); + } else { + header.UE_active[UE_id]=true; + + if (dlsch_procedures(eNB, + proc, + harq_pid, + dlsch0, + &eNB->UE_stats[(uint32_t)UE_id])) { + append(UEdata); + } + } + } else if ((dlsch0)&&(dlsch0->rnti>0)&& +#ifdef PHY_TX_THREAD + (dlsch0->active[subframe] == 0) +#else + (dlsch0->active == 0) +#endif + ) { + // clear subframe TX flag since UE is not scheduled for PDSCH in this subframe (so that we don't look for PUCCH later) + dlsch0->subframe_tx[subframe]=0; + } + } + + header.phich_vars=eNB->phich_vars[subframe&1]; + + if (do_meas==1) stop_meas(&eNB->dlsch_ue_specific); + + if (do_meas==1) stop_meas(&eNB->phy_proc_tx); + commonUDP_t *header=(commonUDP_t *) buf; header->contentBytes=1000; header->nbBlocks=1; From c48609f9af649f0255b324b44f6ed51a86de5a0d Mon Sep 17 00:00:00 2001 From: laurent Date: Thu, 18 Jul 2019 15:10:20 +0200 Subject: [PATCH 011/240] merge develop (split pdsch/dlsch) --- executables/dl_fs6.c | 64 +++++++++++++++++++++---------------- executables/split_headers.h | 5 +++ 2 files changed, 42 insertions(+), 27 deletions(-) diff --git a/executables/dl_fs6.c b/executables/dl_fs6.c index 6b80369895..5cdb6a0444 100644 --- a/executables/dl_fs6.c +++ b/executables/dl_fs6.c @@ -6,6 +6,23 @@ #define FS6_BUF_SIZE 100*1000 static UDPsock_t sockFS6; +typedef struct { + int frame; + int subframe; +} fs6_ul_t; + + +typedef struct { + int frame; + int subframe; + int num_pdcch_symbols; + int num_dci; + int amp; + bool UE_active[NUMBER_OF_UE_MAX]; + LTE_eNB_PHICH phich_vars; +} fs6_dl_t; + + #if 0 void pdsch_procedures(PHY_VARS_eNB *eNB, @@ -90,17 +107,11 @@ void phy_procedures_eNB_uespec_RX_extract(PHY_VARS_eNB *phy_vars_eNB,L1_rxtx_pro void phy_procedures_eNB_uespec_RX_process(PHY_VARS_eNB *phy_vars_eNB,L1_rxtx_proc_t *proc) { } -typedef struct { - int frame; - int subframe; - int num_pdcch_symbols; - int num_dci; - int amp; - bool UE_active[NUMBER_OF_UE_MAX]; - LTE_eNB_PHICH phich_vars; -} fs6_dl_t; - void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas ) { + commonUDP_t *UDPheader=(commonUDP_t *) bufferZone; + UDPheader->contentBytes=1000; + UDPheader->nbBlocks=1; + fs6_dl_t *header=(fs6_dl_t *) commonUDPdata(bufferZone); // TBD: read frame&subframe from received data int frame=proc->frame_tx; int subframe=proc->subframe_tx; @@ -113,6 +124,7 @@ void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eN uint32_t ul_frame; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; LTE_UL_eNB_HARQ_t *ulsch_harq; + if (do_meas==1) { start_meas(&eNB->phy_proc_tx); @@ -149,7 +161,7 @@ void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eN header->num_dci, &eNB->pdcch_vars[subframe&1].dci_alloc[0], 0, - headerAMP, + header->amp, fp, eNB->common_vars.txdataF, header->subframe); @@ -162,9 +174,9 @@ void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eN } for (int UE_id=0; UE_iddlsch[UE_id][0]; - dlsch1 = eNB->dlsch[UE_id][1]; + if (header->UE_active[UE_id]) { // if we generate dlsch, we must generate pdsch + LTE_eNB_DLSCH_t *dlsch0 = eNB->dlsch[UE_id][0]; + LTE_eNB_DLSCH_t *dlsch1 = eNB->dlsch[UE_id][1]; pdsch_procedures(eNB, proc, harq_pid, @@ -173,13 +185,14 @@ void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eN } } - eNB->phich_vars[subframe&1]=header.phich_vars; + eNB->phich_vars[subframe&1]=header->phich_vars; generate_phich_top(eNB, proc, AMP); } -void phy_procedures_eNB_TX_extract(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas, uint8_t *buf, int bufSize) { +void phy_procedures_eNB_TX_extract(uint8_t bufferZone, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas, uint8_t *buf, int bufSize) { + fs6_dl_t *header=(fs6_dl_t *) commonUDPdata(bufferZone); int frame=proc->frame_tx; int subframe=proc->subframe_tx; uint32_t i,aa; @@ -195,8 +208,8 @@ void phy_procedures_eNB_TX_extract(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int if ((fp->frame_type == TDD) && (subframe_select (fp, subframe) == SF_UL)) return; - header.frame=frame; - header.subframe=subframe; + header->frame=frame; + header->subframe=subframe; // clear existing ulsch dci allocations before applying info from MAC (this is table ul_subframe = pdcch_alloc2ul_subframe (fp, subframe); ul_frame = pdcch_alloc2ul_frame (fp, frame, subframe); @@ -247,9 +260,9 @@ void phy_procedures_eNB_TX_extract(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int LOG_D(PHY,"num_pdcch_symbols %"PRIu8",number dci %"PRIu8"\n",num_pdcch_symbols, num_dci); if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { - header.num_pdcch_symbols=num_pdcch_symbols; - header.num_dci=num_dci; - header.amp=AMP; + header->num_pdcch_symbols=num_pdcch_symbols; + header->num_dci=num_dci; + header->amp=AMP; } if (do_meas==1) stop_meas(&eNB->dlsch_common_and_dci); @@ -286,7 +299,7 @@ void phy_procedures_eNB_TX_extract(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int dlsch0->harq_ids[frame%2][6], dlsch0->harq_ids[frame%2][7]); } else { - header.UE_active[UE_id]=true; + header->UE_active[UE_id]=true; if (dlsch_procedures(eNB, proc, @@ -308,15 +321,12 @@ void phy_procedures_eNB_TX_extract(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int } } - header.phich_vars=eNB->phich_vars[subframe&1]; + header->phich_vars=eNB->phich_vars[subframe&1]; if (do_meas==1) stop_meas(&eNB->dlsch_ue_specific); if (do_meas==1) stop_meas(&eNB->phy_proc_tx); - commonUDP_t *header=(commonUDP_t *) buf; - header->contentBytes=1000; - header->nbBlocks=1; return; } @@ -385,7 +395,7 @@ void DL_cu_fs6(RU_t *ru,int frame, int subframe) { eNB->if_inst->UL_indication(&eNB->UL_INFO); pthread_mutex_unlock(&eNB->UL_INFO_mutex); uint8_t bufferZone[FS6_BUF_SIZE]; - phy_procedures_eNB_TX_extract(eNB, &proc->L1_proc, 1, bufferZone, FS6_BUF_SIZE); + phy_procedures_eNB_TX_extract(bufferZone, eNB, &proc->L1_proc, 1, bufferZone, FS6_BUF_SIZE); sendSubFrame(&sockFS6, bufferZone ); } diff --git a/executables/split_headers.h b/executables/split_headers.h index 064615284f..6480680693 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -37,11 +37,16 @@ typedef struct frequency_s { bool createUDPsock (char *sourceIP, char *sourcePort, char *destIP, char *destPort, UDPsock_t *result); int receiveSubFrame(UDPsock_t *sock, uint64_t expectedTS, void *bufferZone, int bufferSize); int sendSubFrame(UDPsock_t *sock, void *bufferZone); + inline size_t alignedSize(void *ptr) { commonUDP_t *header=(commonUDP_t *) ptr; return ((header->contentBytes+sizeof(commonUDP_t)+blockAlign-1)/blockAlign)*blockAlign; } +inline void * commonUDPdata(void* ptr) { + return (void*) (((commonUDP_t*)ptr)+1); +} + void *cu_fs6(void *arg); void *du_fs6(void *arg); void fill_rf_config(RU_t *ru, char *rf_config_file); From 94831547c779c4fa2e541b5b7b9a78e780778ec1 Mon Sep 17 00:00:00 2001 From: laurent Date: Tue, 23 Jul 2019 18:24:27 +0200 Subject: [PATCH 012/240] add prach --- executables/dl_fs6.c | 424 +++++++++++++++++++++++----------- executables/split_headers.h | 46 +++- executables/transport_split.c | 15 +- 3 files changed, 344 insertions(+), 141 deletions(-) diff --git a/executables/dl_fs6.c b/executables/dl_fs6.c index 5cdb6a0444..7dacf08b51 100644 --- a/executables/dl_fs6.c +++ b/executables/dl_fs6.c @@ -1,4 +1,17 @@ #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -6,125 +19,214 @@ #define FS6_BUF_SIZE 100*1000 static UDPsock_t sockFS6; -typedef struct { - int frame; - int subframe; -} fs6_ul_t; +void prach_eNB_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, int frame,int subframe) { + commonUDP_t *UDPheader=(commonUDP_t *) bufferZone; + fs6_ul_t *header=(fs6_ul_t *) commonUDPdata(bufferZone); + if (is_prach_subframe(&eNB->frame_parms, frame,subframe)<=0) + return; -typedef struct { - int frame; - int subframe; - int num_pdcch_symbols; - int num_dci; - int amp; - bool UE_active[NUMBER_OF_UE_MAX]; - LTE_eNB_PHICH phich_vars; -} fs6_dl_t; + eNB->proc.frame_prach = frame; + eNB->proc.subframe_prach = subframe; + eNB->proc.frame_prach_br = frame; + eNB->proc.subframe_prach_br = subframe; + RU_t *ru; + int aa=0; + int ru_aa; + for (int i=0; inum_RU; i++) { + ru=eNB->RU_list[i]; -#if 0 + for (ru_aa=0,aa=0; ru_aanb_rx; ru_aa++,aa++) { + eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[i]->prach_rxsigF[ru_aa]; + int ce_level; -void pdsch_procedures(PHY_VARS_eNB *eNB, - L1_rxtx_proc_t *proc, - int harq_pid, - LTE_eNB_DLSCH_t *dlsch, - LTE_eNB_DLSCH_t *dlsch1, - LTE_eNB_UE_stats *ue_stats, - int ra_flag) { - int frame=proc->frame_tx; - int subframe=proc->subframe_tx; - LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch->harq_processes[harq_pid]; - LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - - // 36-212 - if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { // monolthic OR PNF - do not need turbo encoding on VNF - // Replace dlsch_encoding - // data is in - // dlsch->harq_processes[harq_pid]->e - feedDlschBuffers(eNB, - dlsch_harq->pdu, - dlsch_harq->pdsch_start, - dlsch, - frame, - subframe, - &eNB->dlsch_rate_matching_stats, - &eNB->dlsch_turbo_encoding_stats, - &eNB->dlsch_turbo_encoding_waiting_stats, - &eNB->dlsch_turbo_encoding_main_stats, - &eNB->dlsch_turbo_encoding_wakeup_stats0, - &eNB->dlsch_turbo_encoding_wakeup_stats1, - &eNB->dlsch_interleaving_stats); - // 36-211 - dlsch_scrambling(fp, - 0, - dlsch, - harq_pid, - get_G(fp, - dlsch_harq->nb_rb, - dlsch_harq->rb_alloc, - dlsch_harq->Qm, - dlsch_harq->Nl, - dlsch_harq->pdsch_start, - frame,subframe, - 0), - 0, - frame, - subframe<<1); - dlsch_modulation(eNB, - eNB->common_vars.txdataF, - AMP, - frame, - subframe, - dlsch_harq->pdsch_start, - dlsch, - dlsch->ue_type==0 ? dlsch1 : (LTE_eNB_DLSCH_t *)NULL); + for (ce_level=0; ce_level<4; ce_level++) + eNB->prach_vars_br.rxsigF[ce_level][aa] = eNB->RU_list[i]->prach_rxsigF_br[ce_level][ru_aa]; + } } - dlsch->active = 0; - dlsch_harq->round++; -} -#endif - - -void prach_eNB_extract(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe, uint8_t *buf, int bufSize) { - commonUDP_t *header=(commonUDP_t *) buf; - header->contentBytes=1000; - header->nbBlocks=1; + /* Fixme: the orgin code calls the two funtiosn, so one overwrite the second? + rx_prach(eNB, + eNB->RU_list[0], + header->max_preamble, + header->max_preamble_energy, + header->max_preamble_delay, + header->avg_preamble_energy, + frame, + 0, + false + ); + */ + // run PRACH detection for CE-level 0 only for now when br_flag is set + rx_prach(eNB, + eNB->RU_list[0], + header->max_preamble, + header->max_preamble_energy, + header->max_preamble_delay, + header->avg_preamble_energy, + frame, + 0, + true + ); return; } -void prach_eNB_process(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { +void prach_eNB_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { + commonUDP_t *UDPheader=(commonUDP_t *) bufferZone; + fs6_ul_t *header=(fs6_ul_t *) commonUDPdata(bufferZone); + uint16_t *max_preamble=header->max_preamble; + uint16_t *max_preamble_energy=header->max_preamble_energy; + uint16_t *max_preamble_delay=header->max_preamble_delay; + uint16_t *avg_preamble_energy=header->avg_preamble_energy; + // Fixme: not clear why we call twice with "br" and without + int br_flag=1; + + if (br_flag==1) { + int prach_mask; + prach_mask = is_prach_subframe (&eNB->frame_parms, eNB->proc.frame_prach_br, eNB->proc.subframe_prach_br); + eNB->UL_INFO.rach_ind_br.rach_indication_body.preamble_list = eNB->preamble_list_br; + int ind = 0; + int ce_level = 0; + /* Save for later, it doesn't work + for (int ind=0,ce_level=0;ce_level<4;ce_level++) { + + if ((eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[ce_level]==1)&& + (prach_mask&(1<<(1+ce_level)) > 0) && // prach is active and CE level has finished its repetitions + (eNB->prach_vars_br.repetition_number[ce_level]== + eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_numRepetitionPerPreambleAttempt[ce_level])) { + + */ + + if (eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[0] == 1) { + if ((eNB->prach_energy_counter == 100) && (max_preamble_energy[0] > eNB->measurements.prach_I0 + eNB->prach_DTX_threshold_emtc[0])) { + eNB->UL_INFO.rach_ind_br.rach_indication_body.number_of_preambles++; + eNB->preamble_list_br[ind].preamble_rel8.timing_advance = max_preamble_delay[ind]; // + eNB->preamble_list_br[ind].preamble_rel8.preamble = max_preamble[ind]; + // note: fid is implicitly 0 here, this is the rule for eMTC RA-RNTI from 36.321, Section 5.1.4 + eNB->preamble_list_br[ind].preamble_rel8.rnti = 1 + subframe + (60*(eNB->prach_vars_br.first_frame[ce_level] % 40)); + eNB->preamble_list_br[ind].instance_length = 0; //don't know exactly what this is + eNB->preamble_list_br[ind].preamble_rel13.rach_resource_type = 1 + ce_level; // CE Level + LOG_I (PHY, "Filling NFAPI indication for RACH %d CELevel %d (mask %x) : TA %d, Preamble %d, rnti %x, rach_resource_type %d\n", + ind, + ce_level, + prach_mask, + eNB->preamble_list_br[ind].preamble_rel8.timing_advance, + eNB->preamble_list_br[ind].preamble_rel8.preamble, eNB->preamble_list_br[ind].preamble_rel8.rnti, eNB->preamble_list_br[ind].preamble_rel13.rach_resource_type); + } + } + + /* + ind++; + } + } */// ce_level + } else if ((eNB->prach_energy_counter == 100) && + (max_preamble_energy[0] > eNB->measurements.prach_I0+eNB->prach_DTX_threshold)) { + LOG_I(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure with preamble %d, energy %d.%d dB, delay %d\n", + eNB->Mod_id, + eNB->CC_id, + frame, + subframe, + max_preamble[0], + max_preamble_energy[0]/10, + max_preamble_energy[0]%10, + max_preamble_delay[0]); + pthread_mutex_lock(&eNB->UL_INFO_mutex); + eNB->UL_INFO.rach_ind.rach_indication_body.number_of_preambles = 1; + eNB->UL_INFO.rach_ind.rach_indication_body.preamble_list = &eNB->preamble_list[0]; + eNB->UL_INFO.rach_ind.rach_indication_body.tl.tag = NFAPI_RACH_INDICATION_BODY_TAG; + eNB->UL_INFO.rach_ind.header.message_id = NFAPI_RACH_INDICATION; + eNB->UL_INFO.rach_ind.sfn_sf = frame<<4 | subframe; + eNB->preamble_list[0].preamble_rel8.tl.tag = NFAPI_PREAMBLE_REL8_TAG; + eNB->preamble_list[0].preamble_rel8.timing_advance = max_preamble_delay[0]; + eNB->preamble_list[0].preamble_rel8.preamble = max_preamble[0]; + eNB->preamble_list[0].preamble_rel8.rnti = 1+subframe; // note: fid is implicitly 0 here + eNB->preamble_list[0].preamble_rel13.rach_resource_type = 0; + eNB->preamble_list[0].instance_length = 0; //don't know exactly what this is + + if (NFAPI_MODE==NFAPI_MODE_PNF) { // If NFAPI PNF then we need to send the message to the VNF + LOG_D(PHY,"Filling NFAPI indication for RACH : SFN_SF:%d TA %d, Preamble %d, rnti %x, rach_resource_type %d\n", + NFAPI_SFNSF2DEC(eNB->UL_INFO.rach_ind.sfn_sf), + eNB->preamble_list[0].preamble_rel8.timing_advance, + eNB->preamble_list[0].preamble_rel8.preamble, + eNB->preamble_list[0].preamble_rel8.rnti, + eNB->preamble_list[0].preamble_rel13.rach_resource_type); + oai_nfapi_rach_ind(&eNB->UL_INFO.rach_ind); + eNB->UL_INFO.rach_ind.rach_indication_body.number_of_preambles = 0; + } + + pthread_mutex_unlock(&eNB->UL_INFO_mutex); + } // max_preamble_energy > prach_I0 + 100 + else { + eNB->measurements.prach_I0 = ((eNB->measurements.prach_I0*900)>>10) + ((avg_preamble_energy[0]*124)>>10); + + if (eNB->prach_energy_counter < 100) + eNB->prach_energy_counter++; + } } + +void phy_procedures_eNB_uespec_RX_extract(uint8_t *buf, int bufSize, PHY_VARS_eNB *phy_vars_eNB,L1_rxtx_proc_t *proc) { + //RX processing for ue-specific resources (i + LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; + const int subframe = proc->subframe_rx; + const int frame = proc->frame_rx; + /* TODO: use correct rxdata */ + T (T_ENB_PHY_INPUT_SIGNAL, T_INT (eNB->Mod_id), T_INT (frame), T_INT (subframe), T_INT (0), + T_BUFFER (&eNB->RU_list[0]->common.rxdata[0][subframe * eNB->frame_parms.samples_per_tti], eNB->frame_parms.samples_per_tti * 4)); + + if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) return; + + T(T_ENB_PHY_UL_TICK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe)); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 1 ); + LOG_D (PHY, "[eNB %d] Frame %d: Doing phy_procedures_eNB_uespec_RX(%d)\n", eNB->Mod_id, frame, subframe); + eNB->rb_mask_ul[0] = 0; + eNB->rb_mask_ul[1] = 0; + eNB->rb_mask_ul[2] = 0; + eNB->rb_mask_ul[3] = 0; + // Fix me here, these should be locked + eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus = 0; + eNB->UL_INFO.crc_ind.crc_indication_body.number_of_crcs = 0; + // Call SRS first since all others depend on presence of SRS or lack thereof + srs_procedures (eNB, proc); + eNB->first_run_I0_measurements = 0; + uci_procedures (eNB, proc); + lte_eNB_I0_measurements (eNB, subframe, 0, eNB->first_run_I0_measurements); + int min_I0=1000,max_I0=0; + + if ((frame==0) && (subframe==4)) { + for (int i=0; iframe_parms.N_RB_UL; i++) { + if (i==(eNB->frame_parms.N_RB_UL>>1) - 1) i+=2; + + if (eNB->measurements.n0_subband_power_tot_dB[i]measurements.n0_subband_power_tot_dB[i]; + + if (eNB->measurements.n0_subband_power_tot_dB[i]>max_I0) + max_I0 = eNB->measurements.n0_subband_power_tot_dB[i]; + } + + LOG_I (PHY, "max_I0 %d, min_I0 %d\n", max_I0, min_I0); + } -void phy_procedures_eNB_uespec_RX_extract(PHY_VARS_eNB *phy_vars_eNB,L1_rxtx_proc_t *proc, uint8_t *buf, int bufSize) { commonUDP_t *header=(commonUDP_t *) buf; header->contentBytes=1000; header->nbBlocks=1; return; } -void phy_procedures_eNB_uespec_RX_process(PHY_VARS_eNB *phy_vars_eNB,L1_rxtx_proc_t *proc) { +void phy_procedures_eNB_uespec_RX_process(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *phy_vars_eNB,L1_rxtx_proc_t *proc) { } -void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas ) { +void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas ) { commonUDP_t *UDPheader=(commonUDP_t *) bufferZone; - UDPheader->contentBytes=1000; - UDPheader->nbBlocks=1; fs6_dl_t *header=(fs6_dl_t *) commonUDPdata(bufferZone); // TBD: read frame&subframe from received data - int frame=proc->frame_tx; - int subframe=proc->subframe_tx; - uint32_t i,aa; - uint8_t harq_pid; - uint8_t num_pdcch_symbols=0; - uint8_t num_dci=0; - uint8_t num_mdci = 0; - uint8_t ul_subframe; - uint32_t ul_frame; + int frame=proc->frame_tx=header->frame; + int subframe=proc->subframe_tx=header->subframe; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; LTE_UL_eNB_HARQ_t *ulsch_harq; - + eNB->pdcch_vars[subframe&1].num_pdcch_symbols=header->num_pdcch_symbols; + eNB->pdcch_vars[subframe&1].num_dci=header->num_dci; + uint8_t num_mdci = eNB->mpdcch_vars[subframe&1].num_dci = header->num_mdci; if (do_meas==1) { start_meas(&eNB->phy_proc_tx); @@ -132,7 +234,7 @@ void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eN } // clear the transmit data array for the current subframe - for (aa = 0; aa < fp->nb_antenna_ports_eNB; aa++) { + for (int aa = 0; aa < fp->nb_antenna_ports_eNB; aa++) { memset (&eNB->common_vars.txdataF[aa][subframe * fp->ofdm_symbol_size * (fp->symbols_per_tti)], 0, fp->ofdm_symbol_size * (fp->symbols_per_tti) * sizeof (int32_t)); } @@ -142,21 +244,20 @@ void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eN pmch_procedures(eNB,proc); } else { // this is not a pmch subframe, so generate PSS/SSS/PBCH - common_signal_procedures(eNB,proc->frame_tx, proc->subframe_tx); + common_signal_procedures(eNB,frame, subframe); } } - // clear existing ulsch dci allocations before applying info from MAC (this is table - ul_subframe = pdcch_alloc2ul_subframe (fp, subframe); - ul_frame = pdcch_alloc2ul_frame (fp, frame, subframe); - // clear previous allocation information for all UEs - for (i = 0; i < NUMBER_OF_UE_MAX; i++) { + for (int i = 0; i < NUMBER_OF_UE_MAX; i++) { if (eNB->dlsch[i][0]) eNB->dlsch[i][0]->subframe_tx[subframe] = 0; } if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { + for (int i=0; i< header->num_dci; i++) + eNB->pdcch_vars[subframe&1].dci_alloc[i]=header->dci_alloc[i]; + generate_dci_top(header->num_pdcch_symbols, header->num_dci, &eNB->pdcch_vars[subframe&1].dci_alloc[0], @@ -165,7 +266,6 @@ void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eN fp, eNB->common_vars.txdataF, header->subframe); - num_mdci = eNB->mpdcch_vars[subframe &1].num_dci; if (num_mdci > 0) { LOG_D (PHY, "[eNB %" PRIu8 "] Frame %d, subframe %d: Calling generate_mdci_top (mpdcch) (num_dci %" PRIu8 ")\n", eNB->Mod_id, frame, subframe, num_mdci); @@ -177,6 +277,7 @@ void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eN if (header->UE_active[UE_id]) { // if we generate dlsch, we must generate pdsch LTE_eNB_DLSCH_t *dlsch0 = eNB->dlsch[UE_id][0]; LTE_eNB_DLSCH_t *dlsch1 = eNB->dlsch[UE_id][1]; + int harq_pid=dlsch0->harq_ids[frame%2][subframe]=header->UE_active[UE_id]; pdsch_procedures(eNB, proc, harq_pid, @@ -191,15 +292,32 @@ void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eN AMP); } -void phy_procedures_eNB_TX_extract(uint8_t bufferZone, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas, uint8_t *buf, int bufSize) { +void appendFs6DLUE(uint8_t *bufferZone, uint8_t *UEdata, int UEdataLen) { + commonUDP_t *FirstUDPheader=(commonUDP_t *) bufferZone; + // move to the end + uint8_t *firstFreeByte=bufferZone; + int curBlock=0; + + for (int i=0; i < FirstUDPheader->nbBlocks; i++) { + AssertFatal( ((commonUDP_t *) firstFreeByte)->blockID==curBlock,""); + firstFreeByte+=alignedSize(firstFreeByte); + curBlock++; + } + + AssertFatal(firstFreeByte+UEdataLen+sizeof(fs6_dl_t) <= bufferZone+FS6_BUF_SIZE, ""); + commonUDP_t *newUDPheader=(commonUDP_t *) firstFreeByte; + FirstUDPheader->nbBlocks++; + newUDPheader->blockID=curBlock; + newUDPheader->contentBytes=sizeof(fs6_dl_t)+UEdataLen; + // We skip the fs6 DL header, that is populated by caller + // This header will be duplicated during sending + memcpy(commonUDPdata(firstFreeByte+sizeof(fs6_dl_t)), UEdata, UEdataLen); +} + +void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas, uint8_t *buf, int bufSize) { fs6_dl_t *header=(fs6_dl_t *) commonUDPdata(bufferZone); int frame=proc->frame_tx; int subframe=proc->subframe_tx; - uint32_t i,aa; - uint8_t harq_pid; - uint8_t num_pdcch_symbols=0; - uint8_t num_dci=0; - uint8_t num_mdci = 0; uint8_t ul_subframe; uint32_t ul_frame; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; @@ -215,7 +333,7 @@ void phy_procedures_eNB_TX_extract(uint8_t bufferZone, PHY_VARS_eNB *eNB, L1_rxt ul_frame = pdcch_alloc2ul_frame (fp, frame, subframe); // clear previous allocation information for all UEs - for (i = 0; i < NUMBER_OF_UE_MAX; i++) { + for (int i = 0; i < NUMBER_OF_UE_MAX; i++) { if (eNB->dlsch[i][0]) eNB->dlsch[i][0]->subframe_tx[subframe] = 0; } @@ -224,8 +342,11 @@ void phy_procedures_eNB_TX_extract(uint8_t bufferZone, PHY_VARS_eNB *eNB, L1_rxt //if ((ul_subframe < 10)&& // (subframe_select(fp,ul_subframe)==SF_UL)) { // This means that there is a potential UL subframe that will be scheduled here if (ul_subframe < 10) { // This means that there is a potential UL subframe that will be scheduled here - for (i=0; iulsch[i] && eNB->ulsch[i]->ue_type >0) harq_pid = 0; + for (int i=0; iulsch[i] && eNB->ulsch[i]->ue_type >0) + harq_pid = 0; else harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe); @@ -255,13 +376,15 @@ void phy_procedures_eNB_TX_extract(uint8_t bufferZone, PHY_VARS_eNB *eNB, L1_rxt } } - num_pdcch_symbols = eNB->pdcch_vars[subframe&1].num_pdcch_symbols; - num_dci = eNB->pdcch_vars[subframe&1].num_dci; + uint8_t num_pdcch_symbols = eNB->pdcch_vars[subframe&1].num_pdcch_symbols; + uint8_t num_dci = eNB->pdcch_vars[subframe&1].num_dci; + uint8_t num_mdci = eNB->mpdcch_vars[subframe&1].num_dci; LOG_D(PHY,"num_pdcch_symbols %"PRIu8",number dci %"PRIu8"\n",num_pdcch_symbols, num_dci); if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { header->num_pdcch_symbols=num_pdcch_symbols; header->num_dci=num_dci; + header->num_mdci=num_mdci; header->amp=AMP; } @@ -270,11 +393,11 @@ void phy_procedures_eNB_TX_extract(uint8_t bufferZone, PHY_VARS_eNB *eNB, L1_rxt if (do_meas==1) start_meas(&eNB->dlsch_ue_specific); // Now scan UE specific DLSCH - LTE_eNB_DLSCH_t *dlsch0,*dlsch1; + LTE_eNB_DLSCH_t *dlsch0; for (int UE_id=0; UE_iddlsch[UE_id][0]; - dlsch1 = eNB->dlsch[UE_id][1]; + header->UE_active[UE_id]=-1; if ((dlsch0)&&(dlsch0->rnti>0)&& #ifdef PHY_TX_THREAD @@ -284,7 +407,7 @@ void phy_procedures_eNB_TX_extract(uint8_t bufferZone, PHY_VARS_eNB *eNB, L1_rxt #endif ) { // get harq_pid - harq_pid = dlsch0->harq_ids[frame%2][subframe]; + int harq_pid = dlsch0->harq_ids[frame%2][subframe]; AssertFatal(harq_pid>=0,"harq_pid is negative\n"); if (harq_pid>=8) { @@ -299,14 +422,37 @@ void phy_procedures_eNB_TX_extract(uint8_t bufferZone, PHY_VARS_eNB *eNB, L1_rxt dlsch0->harq_ids[frame%2][6], dlsch0->harq_ids[frame%2][7]); } else { - header->UE_active[UE_id]=true; + header->UE_active[UE_id]=harq_pid; if (dlsch_procedures(eNB, proc, harq_pid, dlsch0, &eNB->UE_stats[(uint32_t)UE_id])) { - append(UEdata); + // data in: dlsch0 harq_processes[harq_pid]->e + /* length + get_G(fp, + dlsch_harq->nb_rb, + dlsch_harq->rb_alloc, + dlsch_harq->Qm, + dlsch_harq->Nl, + dlsch_harq->pdsch_start, + frame,subframe, + 0) + need harq_pid + */ + LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch0->harq_processes[harq_pid]; + appendFs6DLUE(bufferZone, + dlsch0->harq_processes[harq_pid]->e, + get_G(fp, + dlsch_harq->nb_rb, + dlsch_harq->rb_alloc, + dlsch_harq->Qm, + dlsch_harq->Nl, + dlsch_harq->pdsch_start, + frame,subframe, + 0) + ); } } } else if ((dlsch0)&&(dlsch0->rnti>0)&& @@ -334,9 +480,13 @@ void DL_du_fs6(RU_t *ru, int frame, int subframe, uint64_t TS) { RU_proc_t *ru_proc=&ru->proc; for (int i=0; inum_eNB; i++) { - uint8_t bufferZone[FS6_BUF_SIZE]; - receiveSubFrame(&sockFS6, TS, bufferZone, sizeof(bufferZone) ); - phy_procedures_eNB_TX_process( bufferZone, sizeof(bufferZone), ru->eNB_list[i], &ru->eNB_list[i]->proc.L1_proc, 1); + initBufferZone(bufferZone); + int nb_blocks=receiveSubFrame(&sockFS6, TS, bufferZone, sizeof(bufferZone) ); + + if (nb_blocks>0) + phy_procedures_eNB_TX_process( bufferZone, nb_blocks, ru->eNB_list[i], &ru->eNB_list[i]->proc.L1_proc, 1); + else + LOG_E(PHY,"DL not received for subframe: %d\n", subframe); } /* Fixme: datamodel issue: a ru is supposed to be connected to several eNB @@ -371,15 +521,15 @@ void UL_du_fs6(RU_t *ru, int frame, int subframe) { oai_subframe_ind(proc->frame_rx, proc->subframe_rx); } - uint8_t bufferZone[FS6_BUF_SIZE]; - prach_eNB_extract(eNB,NULL,proc->frame_rx,proc->subframe_rx, bufferZone, FS6_BUF_SIZE); + initBufferZone(bufferZone); + prach_eNB_extract(bufferZone, FS6_BUF_SIZE, eNB, proc->frame_rx,proc->subframe_rx ); if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { - phy_procedures_eNB_uespec_RX_extract(eNB, &proc->L1_proc, bufferZone, FS6_BUF_SIZE); + phy_procedures_eNB_uespec_RX_extract(bufferZone, FS6_BUF_SIZE, eNB, &proc->L1_proc ); } for (int i=0; inum_eNB; i++) { - sendSubFrame(&sockFS6,bufferZone); + sendSubFrame(&sockFS6,bufferZone, sizeof(fs6_ul_t)); } } @@ -394,28 +544,36 @@ void DL_cu_fs6(RU_t *ru,int frame, int subframe) { eNB->UL_INFO.CC_id = eNB->CC_id; eNB->if_inst->UL_indication(&eNB->UL_INFO); pthread_mutex_unlock(&eNB->UL_INFO_mutex); - uint8_t bufferZone[FS6_BUF_SIZE]; + initBufferZone(bufferZone); phy_procedures_eNB_TX_extract(bufferZone, eNB, &proc->L1_proc, 1, bufferZone, FS6_BUF_SIZE); - sendSubFrame(&sockFS6, bufferZone ); + commonUDP_t *firstHeader=(commonUDP_t *) bufferZone; + + if (firstHeader->nbBlocks==0) { + firstHeader->nbBlocks=1; // We have to send the signaling, even is there is no user plan data (no UE) + firstHeader->blockID=0; + firstHeader->contentBytes=sizeof(fs6_dl_t); + } + + sendSubFrame(&sockFS6, bufferZone, sizeof(fs6_dl_t) ); } void UL_cu_fs6(RU_t *ru,int frame, int subframe, uint64_t TS) { - uint8_t bufferZone[FS6_BUF_SIZE]; - receiveSubFrame(&sockFS6, TS, bufferZone, sizeof(bufferZone) ); + initBufferZone(bufferZone); + int nb_blocks=receiveSubFrame(&sockFS6, TS, bufferZone, sizeof(bufferZone) ); // Fixme: datamodel issue PHY_VARS_eNB *eNB = RC.eNB[0][0]; L1_proc_t *proc = &eNB->proc; - prach_eNB_process(eNB,NULL,proc->frame_rx,proc->subframe_rx); + prach_eNB_process(bufferZone, sizeof(bufferZone), eNB,NULL,proc->frame_rx,proc->subframe_rx); release_UE_in_freeList(eNB->Mod_id); if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { - phy_procedures_eNB_uespec_RX_process(eNB, &proc->L1_proc); + phy_procedures_eNB_uespec_RX_process(bufferZone, sizeof(bufferZone), eNB, &proc->L1_proc); } } void *cu_fs6(void *arg) { RU_t *ru = (RU_t *)arg; - RU_proc_t *proc = &ru->proc; + //RU_proc_t *proc = &ru->proc; int64_t AbsoluteSubframe=-1; fill_rf_config(ru,ru->rf_config_file); init_frame_parms(&ru->frame_parms,1); @@ -436,7 +594,7 @@ void *cu_fs6(void *arg) { void *du_fs6(void *arg) { RU_t *ru = (RU_t *)arg; - RU_proc_t *proc = &ru->proc; + //RU_proc_t *proc = &ru->proc; int64_t AbsoluteSubframe=-1; fill_rf_config(ru,ru->rf_config_file); init_frame_parms(&ru->frame_parms,1); diff --git a/executables/split_headers.h b/executables/split_headers.h index 6480680693..f4bc2ba3db 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -34,17 +34,44 @@ typedef struct frequency_s { int nbSamples; } frequency_t; +typedef struct { + int frame; + int subframe; + uint16_t max_preamble[4]; + uint16_t max_preamble_energy[4]; + uint16_t max_preamble_delay[4]; + uint16_t avg_preamble_energy[4]; +} fs6_ul_t; + + +typedef struct { + int frame; + int subframe; + int num_pdcch_symbols; + int num_dci; + DCI_ALLOC_t dci_alloc[32]; + int num_mdci; + int amp; + bool UE_active[NUMBER_OF_UE_MAX]; + LTE_eNB_PHICH phich_vars; +} fs6_dl_t; + bool createUDPsock (char *sourceIP, char *sourcePort, char *destIP, char *destPort, UDPsock_t *result); int receiveSubFrame(UDPsock_t *sock, uint64_t expectedTS, void *bufferZone, int bufferSize); -int sendSubFrame(UDPsock_t *sock, void *bufferZone); +int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize); -inline size_t alignedSize(void *ptr) { +#define initBufferZone(xBuf) \ + uint8_t xBuf[FS6_BUF_SIZE];\ + ((commonUDP_t *)xBuf)->nbBlocks=0; + + +inline size_t alignedSize(uint8_t *ptr) { commonUDP_t *header=(commonUDP_t *) ptr; return ((header->contentBytes+sizeof(commonUDP_t)+blockAlign-1)/blockAlign)*blockAlign; } -inline void * commonUDPdata(void* ptr) { - return (void*) (((commonUDP_t*)ptr)+1); +inline void *commonUDPdata(uint8_t *ptr) { + return (void *) (((commonUDP_t *)ptr)+1); } void *cu_fs6(void *arg); @@ -54,7 +81,16 @@ void rx_rf(RU_t *ru,int *frame,int *subframe); void tx_rf(RU_t *ru); void common_signal_procedures (PHY_VARS_eNB *eNB,int frame, int subframe); void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc); - +bool dlsch_procedures(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, + int harq_pid, + LTE_eNB_DLSCH_t *dlsch, + LTE_eNB_UE_stats *ue_stats) ; +void pdsch_procedures(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, + int harq_pid, + LTE_eNB_DLSCH_t *dlsch, + LTE_eNB_DLSCH_t *dlsch1); // mistakes in main OAI void phy_init_RU(RU_t *); void feptx_prec(RU_t *); diff --git a/executables/transport_split.c b/executables/transport_split.c index 00de32a156..8a43a63833 100644 --- a/executables/transport_split.c +++ b/executables/transport_split.c @@ -99,11 +99,20 @@ int receiveSubFrame(UDPsock_t *sock, uint64_t expectedTS, void *bufferZone, int return rcved; } -int sendSubFrame(UDPsock_t *sock, void *bufferZone) { - commonUDP_t *header=(commonUDP_t *)bufferZone ; - int nbBlocks=header->nbBlocks; +int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize) { + commonUDP_t *UDPheader=(commonUDP_t *)bufferZone ; + int nbBlocks=UDPheader->nbBlocks; + int blockId=0; do { + if (blockId > 0 ) { + commonUDP_t *currentHeader=(commonUDP_t *)bufferZone; + *currentHeader=*UDPheader; + currentHeader->blockID=blockId; + memcpy(commonUDPdata((void *)currentHeader), commonUDPdata(bufferZone), secondHeaderSize); + blockId++; + } + int sz=alignedSize(bufferZone); // Let's use the first address returned by getaddrinfo() int ret=sendto(sock->sockHandler, bufferZone, sz, 0, From a9122624a178e13105362d86cdc766616b333fbf Mon Sep 17 00:00:00 2001 From: laurent Date: Fri, 26 Jul 2019 11:24:51 +0200 Subject: [PATCH 013/240] progress fs6 uplink --- executables/dl_fs6.c | 313 +++++++++++++++++++++++++++++++----- executables/split_headers.h | 12 +- 2 files changed, 282 insertions(+), 43 deletions(-) diff --git a/executables/dl_fs6.c b/executables/dl_fs6.c index 7dacf08b51..3e72eb8c37 100644 --- a/executables/dl_fs6.c +++ b/executables/dl_fs6.c @@ -14,13 +14,14 @@ #include #include #include +#include #include #define FS6_BUF_SIZE 100*1000 static UDPsock_t sockFS6; void prach_eNB_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, int frame,int subframe) { - commonUDP_t *UDPheader=(commonUDP_t *) bufferZone; + //commonUDP_t *UDPheader=(commonUDP_t *) bufferZone; fs6_ul_t *header=(fs6_ul_t *) commonUDPdata(bufferZone); if (is_prach_subframe(&eNB->frame_parms, frame,subframe)<=0) @@ -47,7 +48,7 @@ void prach_eNB_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, int } /* Fixme: the orgin code calls the two funtiosn, so one overwrite the second? - rx_prach(eNB, + rx_prach(eNB, eNB->RU_list[0], header->max_preamble, header->max_preamble_energy, @@ -73,7 +74,7 @@ void prach_eNB_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, int } void prach_eNB_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { - commonUDP_t *UDPheader=(commonUDP_t *) bufferZone; + //commonUDP_t *UDPheader=(commonUDP_t *) bufferZone; fs6_ul_t *header=(fs6_ul_t *) commonUDPdata(bufferZone); uint16_t *max_preamble=header->max_preamble; uint16_t *max_preamble_energy=header->max_preamble_energy; @@ -119,7 +120,7 @@ void prach_eNB_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB,RU_t /* ind++; } - } */// ce_level + } */// ce_level } else if ((eNB->prach_energy_counter == 100) && (max_preamble_energy[0] > eNB->measurements.prach_I0+eNB->prach_DTX_threshold)) { LOG_I(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure with preamble %d, energy %d.%d dB, delay %d\n", @@ -165,7 +166,72 @@ void prach_eNB_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB,RU_t } } -void phy_procedures_eNB_uespec_RX_extract(uint8_t *buf, int bufSize, PHY_VARS_eNB *phy_vars_eNB,L1_rxtx_proc_t *proc) { +void pusch_procedures_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { + uint32_t harq_pid; + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + const int subframe = proc->subframe_rx; + const int frame = proc->frame_rx; + uint32_t harq_pid0 = subframe2harq_pid(&eNB->frame_parms,frame,subframe); + + for (int i = 0; i < NUMBER_OF_UE_MAX; i++) { + LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[i]; + + if (ulsch->ue_type > 0) harq_pid = 0; + else harq_pid=harq_pid0; + + LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; + + if (ulsch->rnti>0) + LOG_D(PHY,"eNB->ulsch[%d]->harq_processes[harq_pid:%d] SFN/SF:%04d%d: PUSCH procedures, UE %d/%x ulsch_harq[status:%d SFN/SF:%04d%d handled:%d]\n", + i, harq_pid, frame,subframe,i,ulsch->rnti, + ulsch_harq->status, ulsch_harq->frame, ulsch_harq->subframe, ulsch_harq->handled); + + if ((ulsch) && + (ulsch->rnti>0) && + (ulsch_harq->status == ACTIVE) && + (ulsch_harq->frame == frame) && + (ulsch_harq->subframe == subframe) && + (ulsch_harq->handled == 0)) { + // UE has ULSCH scheduling + for (int rb=0; + rb<=ulsch_harq->nb_rb; + rb++) { + int rb2 = rb+ulsch_harq->first_rb; + eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31)); + } + + LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for UE %d \n", + eNB->Mod_id, frame, subframe, i); + uint8_t nPRS= fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1]; + ulsch->cyclicShift = (ulsch_harq->n_DMRS2 + + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift + + nPRS)%12; + AssertFatal(ulsch_harq->TBS>0,"illegal TBS %d\n",ulsch_harq->TBS); + LOG_D(PHY, + "[eNB %d][PUSCH %d] Frame %d Subframe %d Demodulating PUSCH: dci_alloc %d, rar_alloc %d, round %d, first_rb %d, nb_rb %d, Qm %d, TBS %d, rv %d, cyclic_shift %d (n_DMRS2 %d, cyclicShift_common %d, ), O_ACK %d, beta_cqi %d \n", + eNB->Mod_id,harq_pid,frame,subframe, + ulsch_harq->dci_alloc, + ulsch_harq->rar_alloc, + ulsch_harq->round, + ulsch_harq->first_rb, + ulsch_harq->nb_rb, + ulsch_harq->Qm, + ulsch_harq->TBS, + ulsch_harq->rvidx, + ulsch->cyclicShift, + ulsch_harq->n_DMRS2, + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift, + ulsch_harq->O_ACK, + ulsch->beta_offset_cqi_times8); + start_meas(&eNB->ulsch_demodulation_stats); + rx_ulsch(eNB,proc, i); + stop_meas(&eNB->ulsch_demodulation_stats); + // TBD: add datablock for transmission + } + } +} + +void phy_procedures_eNB_uespec_RX_extract(uint8_t *buf, int bufSize, PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { //RX processing for ue-specific resources (i LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; const int subframe = proc->subframe_rx; @@ -176,8 +242,6 @@ void phy_procedures_eNB_uespec_RX_extract(uint8_t *buf, int bufSize, PHY_VARS_eN if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) return; - T(T_ENB_PHY_UL_TICK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe)); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 1 ); LOG_D (PHY, "[eNB %d] Frame %d: Doing phy_procedures_eNB_uespec_RX(%d)\n", eNB->Mod_id, frame, subframe); eNB->rb_mask_ul[0] = 0; eNB->rb_mask_ul[1] = 0; @@ -190,6 +254,11 @@ void phy_procedures_eNB_uespec_RX_extract(uint8_t *buf, int bufSize, PHY_VARS_eN srs_procedures (eNB, proc); eNB->first_run_I0_measurements = 0; uci_procedures (eNB, proc); + + if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { // If PNF or monolithic + pusch_procedures_extract(buf, bufSize, eNB,proc); + } + lte_eNB_I0_measurements (eNB, subframe, 0, eNB->first_run_I0_measurements); int min_I0=1000,max_I0=0; @@ -213,17 +282,172 @@ void phy_procedures_eNB_uespec_RX_extract(uint8_t *buf, int bufSize, PHY_VARS_eN return; } +void pusch_procedures_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { + //LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + const int subframe = proc->subframe_rx; + const int frame = proc->frame_rx; + uint32_t harq_pid; + uint32_t harq_pid0 = subframe2harq_pid(&eNB->frame_parms,frame,subframe); + + for (int i = 0; i < NUMBER_OF_UE_MAX; i++) { + LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[i]; + + if (ulsch->ue_type > 0) harq_pid = 0; + else harq_pid=harq_pid0; + + LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; + + if (ulsch->rnti>0) LOG_D(PHY,"eNB->ulsch[%d]->harq_processes[harq_pid:%d] SFN/SF:%04d%d: PUSCH procedures, UE %d/%x ulsch_harq[status:%d SFN/SF:%04d%d handled:%d]\n", + i, harq_pid, frame,subframe,i,ulsch->rnti, + ulsch_harq->status, ulsch_harq->frame, ulsch_harq->subframe, ulsch_harq->handled); + + if ((ulsch) && + (ulsch->rnti>0) && + (ulsch_harq->status == ACTIVE) && + (ulsch_harq->frame == frame) && + (ulsch_harq->subframe == subframe) && + (ulsch_harq->handled == 0)) { + // UE has ULSCH scheduling + for (int rb=0; + rb<=ulsch_harq->nb_rb; + rb++) { + int rb2 = rb+ulsch_harq->first_rb; + eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31)); + } + + start_meas(&eNB->ulsch_decoding_stats); + int ret = ulsch_decoding(eNB,proc, + i, + 0, // control_only_flag + ulsch_harq->V_UL_DAI, + ulsch_harq->nb_rb>20 ? 1 : 0); + stop_meas(&eNB->ulsch_decoding_stats); + LOG_D(PHY, + "[eNB %d][PUSCH %d] frame %d subframe %d RNTI %x RX power (%d,%d) N0 (%d,%d) dB ACK (%d,%d), decoding iter %d ulsch_harq->cqi_crc_status:%d ackBits:%d ulsch_decoding_stats[t:%lld max:%lld]\n", + eNB->Mod_id,harq_pid, + frame,subframe, + ulsch->rnti, + dB_fixed(eNB->pusch_vars[i]->ulsch_power[0]), + dB_fixed(eNB->pusch_vars[i]->ulsch_power[1]), + 30,//eNB->measurements.n0_power_dB[0], + 30,//eNB->measurements.n0_power_dB[1], + ulsch_harq->o_ACK[0], + ulsch_harq->o_ACK[1], + ret, + ulsch_harq->cqi_crc_status, + ulsch_harq->O_ACK, + eNB->ulsch_decoding_stats.p_time, eNB->ulsch_decoding_stats.max); + //compute the expected ULSCH RX power (for the stats) + ulsch_harq->delta_TF = get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 0); // 0 means bw_factor is not considered + + if (RC.mac != NULL) { /* ulsim does not use RC.mac context. */ + if (ulsch_harq->cqi_crc_status == 1) { +#ifdef DEBUG_PHY_PROC + //if (((frame%10) == 0) || (frame < 50)) + print_CQI(ulsch_harq->o,ulsch_harq->uci_format,0,fp->N_RB_DL); +#endif + fill_ulsch_cqi_indication(eNB,frame,subframe,ulsch_harq,ulsch->rnti); + RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_flag &= (~(1 << subframe)); + } else { + if(RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_flag & (1 << subframe) ) { + RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_flag &= (~(1 << subframe)); + RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_timer=30; + LOG_D(PHY,"Frame %d,Subframe %d, We're supposed to get a cqi here. Set cqi_req_timer to 30.\n",frame,subframe); + } + } + } + + if (ret == (1+MAX_TURBO_ITERATIONS)) { + T(T_ENB_PHY_ULSCH_UE_NACK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(ulsch->rnti), + T_INT(harq_pid)); + fill_crc_indication(eNB,i,frame,subframe,1); // indicate NAK to MAC + fill_rx_indication(eNB,i,frame,subframe); // indicate SDU to MAC + LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d Error receiving ULSCH, round %d/%d (ACK %d,%d)\n", + eNB->Mod_id,harq_pid, + frame,subframe, i, + ulsch_harq->round, + ulsch->Mlimit, + ulsch_harq->o_ACK[0], + ulsch_harq->o_ACK[1]); + + if (ulsch_harq->round >= 3) { + ulsch_harq->status = SCH_IDLE; + ulsch_harq->handled = 0; + ulsch->harq_mask &= ~(1 << harq_pid); + ulsch_harq->round = 0; + } + + MSC_LOG_RX_DISCARDED_MESSAGE( + MSC_PHY_ENB,MSC_PHY_UE, + NULL,0, + "%05u:%02u ULSCH received rnti %x harq id %u round %d", + frame,subframe, + ulsch->rnti,harq_pid, + ulsch_harq->round-1 + ); + /* Mark the HARQ process to release it later if max transmission reached + * (see below). + * MAC does not send the max transmission count, we have to deal with it + * locally in PHY. + */ + ulsch_harq->handled = 1; + } // ulsch in error + else { + fill_crc_indication(eNB,i,frame,subframe,0); // indicate ACK to MAC + fill_rx_indication(eNB,i,frame,subframe); // indicate SDU to MAC + ulsch_harq->status = SCH_IDLE; + ulsch->harq_mask &= ~(1 << harq_pid); + T (T_ENB_PHY_ULSCH_UE_ACK, T_INT (eNB->Mod_id), T_INT (frame), T_INT (subframe), T_INT (ulsch->rnti), T_INT (harq_pid)); + MSC_LOG_RX_MESSAGE( + MSC_PHY_ENB,MSC_PHY_UE, + NULL,0, + "%05u:%02u ULSCH received rnti %x harq id %u", + frame,subframe, + ulsch->rnti,harq_pid + ); + } // ulsch not in error + + if (ulsch_harq->O_ACK>0) fill_ulsch_harq_indication(eNB,ulsch_harq,ulsch->rnti,frame,subframe,ulsch->bundling); + + LOG_D(PHY,"[eNB %d] Frame %d subframe %d: received ULSCH harq_pid %d for UE %d, ret = %d, CQI CRC Status %d, ACK %d,%d, ulsch_errors %d/%d\n", + eNB->Mod_id,frame,subframe, + harq_pid, + i, + ret, + ulsch_harq->cqi_crc_status, + ulsch_harq->o_ACK[0], + ulsch_harq->o_ACK[1], + eNB->UE_stats[i].ulsch_errors[harq_pid], + eNB->UE_stats[i].ulsch_decoding_attempts[harq_pid][0]); + } // if ((ulsch) && + // (ulsch->rnti>0) && + // (ulsch_harq->status == ACTIVE)) + else if ((ulsch) && + (ulsch->rnti>0) && + (ulsch_harq->status == ACTIVE) && + (ulsch_harq->frame == frame) && + (ulsch_harq->subframe == subframe) && + (ulsch_harq->handled == 1)) { + // this harq process is stale, kill it, this 1024 frames later (10s), consider reducing that + ulsch_harq->status = SCH_IDLE; + ulsch_harq->handled = 0; + ulsch->harq_mask &= ~(1 << harq_pid); + LOG_W (PHY, "Removing stale ULSCH config for UE %x harq_pid %d (harq_mask is now 0x%2.2x)\n", ulsch->rnti, harq_pid, ulsch->harq_mask); + } + } // for (i=0; iframe_tx=header->frame; int subframe=proc->subframe_tx=header->subframe; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - LTE_UL_eNB_HARQ_t *ulsch_harq; + //LTE_UL_eNB_HARQ_t *ulsch_harq; eNB->pdcch_vars[subframe&1].num_pdcch_symbols=header->num_pdcch_symbols; eNB->pdcch_vars[subframe&1].num_dci=header->num_dci; uint8_t num_mdci = eNB->mpdcch_vars[subframe&1].num_dci = header->num_mdci; @@ -274,10 +498,10 @@ void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int nbBlocks, PHY_VARS_e } for (int UE_id=0; UE_idUE_active[UE_id]) { // if we generate dlsch, we must generate pdsch + if (header->UE_dl_active[UE_id]) { // if we generate dlsch, we must generate pdsch LTE_eNB_DLSCH_t *dlsch0 = eNB->dlsch[UE_id][0]; LTE_eNB_DLSCH_t *dlsch1 = eNB->dlsch[UE_id][1]; - int harq_pid=dlsch0->harq_ids[frame%2][subframe]=header->UE_active[UE_id]; + int harq_pid=dlsch0->harq_ids[frame%2][subframe]=header->UE_dl_active[UE_id]; pdsch_procedures(eNB, proc, harq_pid, @@ -318,10 +542,7 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx fs6_dl_t *header=(fs6_dl_t *) commonUDPdata(bufferZone); int frame=proc->frame_tx; int subframe=proc->subframe_tx; - uint8_t ul_subframe; - uint32_t ul_frame; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - LTE_UL_eNB_HARQ_t *ulsch_harq; if ((fp->frame_type == TDD) && (subframe_select (fp, subframe) == SF_UL)) return; @@ -329,8 +550,8 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx header->frame=frame; header->subframe=subframe; // clear existing ulsch dci allocations before applying info from MAC (this is table - ul_subframe = pdcch_alloc2ul_subframe (fp, subframe); - ul_frame = pdcch_alloc2ul_frame (fp, frame, subframe); + header->ul_subframe = pdcch_alloc2ul_subframe (fp, subframe); + header->ul_frame = pdcch_alloc2ul_frame (fp, frame, subframe); // clear previous allocation information for all UEs for (int i = 0; i < NUMBER_OF_UE_MAX; i++) { @@ -341,17 +562,17 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx /* TODO: check the following test - in the meantime it is put back as it was before */ //if ((ul_subframe < 10)&& // (subframe_select(fp,ul_subframe)==SF_UL)) { // This means that there is a potential UL subframe that will be scheduled here - if (ul_subframe < 10) { // This means that there is a potential UL subframe that will be scheduled here + if (header->ul_subframe < 10) { // This means that there is a potential UL subframe that will be scheduled here for (int i=0; iulsch[i] && eNB->ulsch[i]->ue_type >0) harq_pid = 0; else - harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe); + header->UE_ul_active[i] = harq_pid = subframe2harq_pid(fp,header->ul_frame,header->ul_subframe); if (eNB->ulsch[i]) { - ulsch_harq = eNB->ulsch[i]->harq_processes[harq_pid]; + //LTE_UL_eNB_HARQ_t *ulsch_harq = eNB->ulsch[i]->harq_processes[harq_pid]; /* Store first_rb and n_DMRS for correct PHICH generation below. * For PHICH generation we need "old" values of last scheduling * for this HARQ process. 'generate_eNB_dlsch_params' below will @@ -370,9 +591,15 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx * * TODO: check if that works with TDD. */ - ulsch_harq->previous_first_rb = ulsch_harq->first_rb; - ulsch_harq->previous_n_DMRS = ulsch_harq->n_DMRS; - } + /* seems useless: unused variables + header->previous_first_rb= + ulsch_harq->previous_first_rb = ulsch_harq->first_rb; + header->previous_n_DMRS = + ulsch_harq->previous_n_DMRS = ulsch_harq->n_DMRS; + */ + header->UE_ul_active[i] = harq_pid; + } else + header->UE_ul_active[i] = -1; } } @@ -397,7 +624,7 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx for (int UE_id=0; UE_iddlsch[UE_id][0]; - header->UE_active[UE_id]=-1; + header->UE_dl_active[UE_id]=-1; if ((dlsch0)&&(dlsch0->rnti>0)&& #ifdef PHY_TX_THREAD @@ -422,7 +649,7 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx dlsch0->harq_ids[frame%2][6], dlsch0->harq_ids[frame%2][7]); } else { - header->UE_active[UE_id]=harq_pid; + header->UE_dl_active[UE_id]=harq_pid; if (dlsch_procedures(eNB, proc, @@ -431,15 +658,15 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx &eNB->UE_stats[(uint32_t)UE_id])) { // data in: dlsch0 harq_processes[harq_pid]->e /* length - get_G(fp, - dlsch_harq->nb_rb, - dlsch_harq->rb_alloc, - dlsch_harq->Qm, - dlsch_harq->Nl, - dlsch_harq->pdsch_start, - frame,subframe, - 0) - need harq_pid + get_G(fp, + dlsch_harq->nb_rb, + dlsch_harq->rb_alloc, + dlsch_harq->Qm, + dlsch_harq->Nl, + dlsch_harq->pdsch_start, + frame,subframe, + 0) + need harq_pid */ LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch0->harq_processes[harq_pid]; appendFs6DLUE(bufferZone, @@ -477,8 +704,7 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx } void DL_du_fs6(RU_t *ru, int frame, int subframe, uint64_t TS) { - RU_proc_t *ru_proc=&ru->proc; - + //RU_proc_t *ru_proc=&ru->proc; for (int i=0; inum_eNB; i++) { initBufferZone(bufferZone); int nb_blocks=receiveSubFrame(&sockFS6, TS, bufferZone, sizeof(bufferZone) ); @@ -490,10 +716,10 @@ void DL_du_fs6(RU_t *ru, int frame, int subframe, uint64_t TS) { } /* Fixme: datamodel issue: a ru is supposed to be connected to several eNB - L1_rxtx_proc_t * L1_proc = &proc->L1_proc; - ru_proc->timestamp_tx = L1_proc->timestamp_tx; - ru_proc->subframe_tx = L1_proc->subframe_tx; - ru_proc->frame_tx = L1_proc->frame_tx; + L1_rxtx_proc_t * L1_proc = &proc->L1_proc; + ru_proc->timestamp_tx = L1_proc->timestamp_tx; + ru_proc->subframe_tx = L1_proc->subframe_tx; + ru_proc->frame_tx = L1_proc->frame_tx; */ feptx_prec(ru); feptx_ofdm(ru); @@ -509,8 +735,8 @@ void UL_du_fs6(RU_t *ru, int frame, int subframe) { // Fixme: datamodel issue PHY_VARS_eNB *eNB = RC.eNB[0][0]; L1_proc_t *proc = &eNB->proc; - L1_rxtx_proc_t *L1_proc = &proc->L1_proc; - LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; + //L1_rxtx_proc_t *L1_proc = &proc->L1_proc; + //LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; proc->frame_rx = frame; proc->subframe_rx = subframe; @@ -559,7 +785,12 @@ void DL_cu_fs6(RU_t *ru,int frame, int subframe) { void UL_cu_fs6(RU_t *ru,int frame, int subframe, uint64_t TS) { initBufferZone(bufferZone); + commonUDP_t *UDPheader=(commonUDP_t *) bufferZone; int nb_blocks=receiveSubFrame(&sockFS6, TS, bufferZone, sizeof(bufferZone) ); + + if (nb_blocks != UDPheader->nbBlocks ) + LOG_W(PHY, "received %d blocks for %d expected\n", nb_blocks, UDPheader->nbBlocks); + // Fixme: datamodel issue PHY_VARS_eNB *eNB = RC.eNB[0][0]; L1_proc_t *proc = &eNB->proc; diff --git a/executables/split_headers.h b/executables/split_headers.h index f4bc2ba3db..4cb2f4a5c4 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -43,16 +43,20 @@ typedef struct { uint16_t avg_preamble_energy[4]; } fs6_ul_t; - typedef struct { int frame; int subframe; + int ul_frame; + int ul_subframe; int num_pdcch_symbols; int num_dci; DCI_ALLOC_t dci_alloc[32]; int num_mdci; int amp; - bool UE_active[NUMBER_OF_UE_MAX]; + int8_t UE_dl_active[NUMBER_OF_UE_MAX]; // the HARQ id for this UE (-1: disabled) + int8_t UE_ul_active[NUMBER_OF_UE_MAX]; + int8_t UE_ul_first_rb[NUMBER_OF_UE_MAX]; // + int8_t UE_ul_last_rb[NUMBER_OF_UE_MAX]; // LTE_eNB_PHICH phich_vars; } fs6_dl_t; @@ -91,6 +95,10 @@ void pdsch_procedures(PHY_VARS_eNB *eNB, int harq_pid, LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t *dlsch1); +void srs_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc); +void uci_procedures(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc); + // mistakes in main OAI void phy_init_RU(RU_t *); void feptx_prec(RU_t *); From 9e4f59f8e5c2c1042d668ecc620f26a5d81df3e8 Mon Sep 17 00:00:00 2001 From: laurent Date: Mon, 29 Jul 2019 08:58:40 +0200 Subject: [PATCH 014/240] add SystemX documentation --- SystemX-tutorial-design.odt | Bin 0 -> 54430 bytes executables/dl_fs6.c | 15 +++++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) create mode 100644 SystemX-tutorial-design.odt diff --git a/SystemX-tutorial-design.odt b/SystemX-tutorial-design.odt new file mode 100644 index 0000000000000000000000000000000000000000..788f9de955d3891f294a4efd08686925c6834e61 GIT binary patch literal 54430 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 literal 0 HcmV?d00001 diff --git a/executables/dl_fs6.c b/executables/dl_fs6.c index 3e72eb8c37..3b20ac9c7a 100644 --- a/executables/dl_fs6.c +++ b/executables/dl_fs6.c @@ -171,13 +171,14 @@ void pusch_procedures_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eN LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; const int subframe = proc->subframe_rx; const int frame = proc->frame_rx; - uint32_t harq_pid0 = subframe2harq_pid(&eNB->frame_parms,frame,subframe); for (int i = 0; i < NUMBER_OF_UE_MAX; i++) { LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[i]; - if (ulsch->ue_type > 0) harq_pid = 0; - else harq_pid=harq_pid0; + if (ulsch->ue_type > 0) + harq_pid = 0; + else + harq_pid= subframe2harq_pid(&eNB->frame_parms,frame,subframe); LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; @@ -297,9 +298,10 @@ void pusch_procedures_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eN LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; - if (ulsch->rnti>0) LOG_D(PHY,"eNB->ulsch[%d]->harq_processes[harq_pid:%d] SFN/SF:%04d%d: PUSCH procedures, UE %d/%x ulsch_harq[status:%d SFN/SF:%04d%d handled:%d]\n", - i, harq_pid, frame,subframe,i,ulsch->rnti, - ulsch_harq->status, ulsch_harq->frame, ulsch_harq->subframe, ulsch_harq->handled); + if (ulsch->rnti>0) + LOG_D(PHY,"eNB->ulsch[%d]->harq_processes[harq_pid:%d] SFN/SF:%04d%d: PUSCH procedures, UE %d/%x ulsch_harq[status:%d SFN/SF:%04d%d handled:%d]\n", + i, harq_pid, frame,subframe,i,ulsch->rnti, + ulsch_harq->status, ulsch_harq->frame, ulsch_harq->subframe, ulsch_harq->handled); if ((ulsch) && (ulsch->rnti>0) && @@ -550,6 +552,7 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx header->frame=frame; header->subframe=subframe; // clear existing ulsch dci allocations before applying info from MAC (this is table + // returns -1 (or 255) if there is no ul (tdd cases) header->ul_subframe = pdcch_alloc2ul_subframe (fp, subframe); header->ul_frame = pdcch_alloc2ul_frame (fp, frame, subframe); From 2af75f48f20ccd1c0cababda2e05a8a20bf5fd8d Mon Sep 17 00:00:00 2001 From: laurent Date: Mon, 29 Jul 2019 09:12:24 +0200 Subject: [PATCH 015/240] merge develop --- executables/main-ocp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/executables/main-ocp.c b/executables/main-ocp.c index 13464ed166..3fc3b00e89 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -256,8 +256,8 @@ void init_eNB(int single_thread_flag,int wait_for_sync) { eNB->UL_INFO.crc_ind.crc_indication_body.crc_pdu_list = eNB->crc_pdu_list; eNB->UL_INFO.sr_ind.sr_indication_body.sr_pdu_list = eNB->sr_pdu_list; eNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list = eNB->harq_pdu_list; - eNB->UL_INFO.cqi_ind.cqi_pdu_list = eNB->cqi_pdu_list; - eNB->UL_INFO.cqi_ind.cqi_raw_pdu_list = eNB->cqi_raw_pdu_list; + eNB->UL_INFO.cqi_ind.cqi_indication_body.cqi_pdu_list = eNB->cqi_pdu_list; + eNB->UL_INFO.cqi_ind.cqi_indication_body.cqi_raw_pdu_list = eNB->cqi_raw_pdu_list; eNB->prach_energy_counter = 0; } } From 75665ad0fc1247b598eb4b6db98b78920baa5cd2 Mon Sep 17 00:00:00 2001 From: laurent Date: Thu, 1 Aug 2019 10:45:25 +0200 Subject: [PATCH 016/240] Create DL sub header --- SystemX-tutorial-design.odt | Bin 54430 -> 55501 bytes cmake_targets/CMakeLists.txt | 2 +- executables/{dl_fs6.c => main-fs6.c} | 99 +++++++++++++++------ executables/split_headers.h | 8 +- openair1/PHY/LTE_TRANSPORT/dci_tools.c | 12 +-- openair1/PHY/LTE_TRANSPORT/transport_eNB.h | 6 +- openair1/SCHED/phy_procedures_lte_eNb.c | 6 +- 7 files changed, 90 insertions(+), 43 deletions(-) rename executables/{dl_fs6.c => main-fs6.c} (92%) diff --git a/SystemX-tutorial-design.odt b/SystemX-tutorial-design.odt index 788f9de955d3891f294a4efd08686925c6834e61..42e195ac112b370ff7d48cfbb5e083d9cfaecf6e 100644 GIT binary patch delta 21677 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�e+QF_zHp1N4uo9b0i5eK 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 delta 20589 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

)QR!~2=}W7u<&nt14zsWr3);Rp^>DYefC0$* zaidVpUyerMa)9giJ=CB>Uc@8W-6Udtf9{vbLJG*x$Wtrrdih-S zMVF0+?+eU__^P5liMa|D723)0yL}CY`~s={+x>mMU90arYfYfV+P?Q?lpN=eVFsD+ zw+)25K2Vj?N}yDq(HD*Sd+Y-9fB7VBYuHk``uJd>rz^m!VaLiMfAVd;x^HzSCYqlb zLA;Ly*)3X)D_?H6oCbG4-r?@mT)HlRY@Rjq*K)=u;;}^kMt* z5C?PebD?a_jXeT*tL8r$F*tw2*Bo9XvOx`nHhT(wywg%lyw@UAU)xQlC-YCs?M6q# zC2iTX=%bwz_TFz2blD47ZRCrq+l3}x&u0xidN2xX#z3`bW^+D`DrMUtPiOjzV$j=> z?A%xs)(vrRuX9{;ql2m1ZSfg03@OD)`UZ$=_9n6qY(+wxB3RsXJx@U@{oOpcL0S@J ziiaI?y=xcRH6`x~uec25v#0cSH^_xo>qA{$Z2%wop`NtyR3c#=gma>JE8c-SgJ4Gv zB484|Rpmydfe+i6Vy{I z>JZ5&P%3P+FVjekJPAWw-lSKffus=|q-6(Nmtv^c>DXkJrEglksM8RoE7N8TzFGi( zI9sPad>?_y^@eRKI!UcRP*ySxpyo+WDL?sO=}6kYg->569#v zLCe<};LP$@R_MfNuJ3&QbF>H60vrrBeAcd@MVmv4pV$_tYOv5&CW(YkZ9tq$EPSUi zDU0KQDU<_Sy0!MkGGmR1l+Tq2*ZA`2(m{c&or}H&@ON33mW~KbD;L6d1oio_D#o+~ z@WR?x`Fbdb-BCq_K73^)Lnr0!zZ7`dn>kdFF~t1waDW;@kD!tpRmKadlru~ucwUQ!vI@ zDj-2en|rOi*jP(8y||qy+9odCrk6)C(d2e2Mz75uLUX>e~$wC28mhweQ8ZQUo8TuRrZ9_6Dm_GpBX- z5xfTn^MB3qC^aR_7?OOj2zMJRJ6_zFIY``jqXg;AC1Wd7YyB#{R$gbi--~~n=3%)k zl38#qdGJBr-J~ye&M{7YSJ?^o~ zAKh8`ZLQHQX5!s#ja;WQ8ke@8P|KMg39vL?19n-@3CFI=CnDxE`l%=QlW+XpP^cA~ zRbS9+4g#Go@iUsC<7DfFhQJ6d&f5jiG<7xLADjMqP6mST9Q2p>kHKJ3l;;>fqi>(- z^eaXXXp@lOta%YkKn40|ejMucnCR7W67$ahIn=i?N!Ig|-&-EfY0WROKp1bDulsch[i]; - if (ulsch->ue_type > 0) + if (ulsch->ue_type > NOCE) harq_pid = 0; else harq_pid= subframe2harq_pid(&eNB->frame_parms,frame,subframe); @@ -232,14 +232,12 @@ void pusch_procedures_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eN } } -void phy_procedures_eNB_uespec_RX_extract(uint8_t *buf, int bufSize, PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { +void phy_procedures_eNB_uespec_RX_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { //RX processing for ue-specific resources (i LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; const int subframe = proc->subframe_rx; const int frame = proc->frame_rx; /* TODO: use correct rxdata */ - T (T_ENB_PHY_INPUT_SIGNAL, T_INT (eNB->Mod_id), T_INT (frame), T_INT (subframe), T_INT (0), - T_BUFFER (&eNB->RU_list[0]->common.rxdata[0][subframe * eNB->frame_parms.samples_per_tti], eNB->frame_parms.samples_per_tti * 4)); if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) return; @@ -257,7 +255,7 @@ void phy_procedures_eNB_uespec_RX_extract(uint8_t *buf, int bufSize, PHY_VARS_eN uci_procedures (eNB, proc); if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { // If PNF or monolithic - pusch_procedures_extract(buf, bufSize, eNB,proc); + pusch_procedures_extract(bufferZone, bufSize, eNB,proc); } lte_eNB_I0_measurements (eNB, subframe, 0, eNB->first_run_I0_measurements); @@ -277,9 +275,6 @@ void phy_procedures_eNB_uespec_RX_extract(uint8_t *buf, int bufSize, PHY_VARS_eN LOG_I (PHY, "max_I0 %d, min_I0 %d\n", max_I0, min_I0); } - commonUDP_t *header=(commonUDP_t *) buf; - header->contentBytes=1000; - header->nbBlocks=1; return; } @@ -293,7 +288,7 @@ void pusch_procedures_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eN for (int i = 0; i < NUMBER_OF_UE_MAX; i++) { LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[i]; - if (ulsch->ue_type > 0) harq_pid = 0; + if (ulsch->ue_type > NOCE) harq_pid = 0; else harq_pid=harq_pid0; LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; @@ -454,6 +449,35 @@ void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int nbBlocks, PHY_VARS_e eNB->pdcch_vars[subframe&1].num_dci=header->num_dci; uint8_t num_mdci = eNB->mpdcch_vars[subframe&1].num_dci = header->num_mdci; + // Remove all scheduled DL, we will populate from the CU sending + for (int UE_id=0; UE_iddlsch[UE_id][0]; + + if ( dlsch0 && dlsch0->rnti>0 ) { +#ifdef PHY_TX_THREAD + dlsch0->active[subframe] = 0; +#else + dlsch0->active = 0; +#endif + } + } + + void *bufPtr=bufferZone; + + for (int i=0; i < nbBlocks; i++) { //nbBlocks is the actual received blocks + fs6_dl_uespec_t *dlPtr=(fs6_dl_uespec_t *)(commonUDPdata(bufPtr)+sizeof(fs6_dl_t)); +#ifdef PHY_TX_THREAD + eNB->dlsch[dlPtr->UE_id][0]->active[subframe] = 1; +#else + eNB->dlsch[dlPtr->UE_id][0]->active = 1; +#endif + eNB->dlsch[dlPtr->UE_id][0]->harq_ids[frame%2][subframe]=dlPtr->harq_pid; + eNB->dlsch[dlPtr->UE_id][0]->rnti=dlPtr->rnti; + memcpy(eNB->dlsch[dlPtr->UE_id][0]->harq_processes[dlPtr->harq_pid]->e, + commonUDPdata(((uint8_t *)dlPtr)+sizeof(fs6_dl_t)), dlPtr->dataLen); + bufPtr+=alignedSize(bufPtr); + } + if (do_meas==1) { start_meas(&eNB->phy_proc_tx); start_meas(&eNB->dlsch_common_and_dci); @@ -476,8 +500,8 @@ void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int nbBlocks, PHY_VARS_e // clear previous allocation information for all UEs for (int i = 0; i < NUMBER_OF_UE_MAX; i++) { - if (eNB->dlsch[i][0]) - eNB->dlsch[i][0]->subframe_tx[subframe] = 0; + //if (eNB->dlsch[i][0]) + //eNB->dlsch[i][0]->subframe_tx[subframe] = 0; } if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { @@ -500,10 +524,17 @@ void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int nbBlocks, PHY_VARS_e } for (int UE_id=0; UE_idUE_dl_active[UE_id]) { // if we generate dlsch, we must generate pdsch - LTE_eNB_DLSCH_t *dlsch0 = eNB->dlsch[UE_id][0]; - LTE_eNB_DLSCH_t *dlsch1 = eNB->dlsch[UE_id][1]; - int harq_pid=dlsch0->harq_ids[frame%2][subframe]=header->UE_dl_active[UE_id]; + LTE_eNB_DLSCH_t *dlsch0 = eNB->dlsch[UE_id][0]; + LTE_eNB_DLSCH_t *dlsch1 = eNB->dlsch[UE_id][1]; + + if ((dlsch0)&&(dlsch0->rnti>0)&& +#ifdef PHY_TX_THREAD + (dlsch0->active[subframe] == 1) +#else + (dlsch0->active == 1) +#endif + ) { + int harq_pid=dlsch0->harq_ids[frame%2][subframe]; pdsch_procedures(eNB, proc, harq_pid, @@ -518,7 +549,7 @@ void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int nbBlocks, PHY_VARS_e AMP); } -void appendFs6DLUE(uint8_t *bufferZone, uint8_t *UEdata, int UEdataLen) { +void appendFs6DLUE(uint8_t *bufferZone, int UE_id, int8_t harq_pid, uint16_t rnti, uint8_t *UEdata, int UEdataLen) { commonUDP_t *FirstUDPheader=(commonUDP_t *) bufferZone; // move to the end uint8_t *firstFreeByte=bufferZone; @@ -534,10 +565,14 @@ void appendFs6DLUE(uint8_t *bufferZone, uint8_t *UEdata, int UEdataLen) { commonUDP_t *newUDPheader=(commonUDP_t *) firstFreeByte; FirstUDPheader->nbBlocks++; newUDPheader->blockID=curBlock; - newUDPheader->contentBytes=sizeof(fs6_dl_t)+UEdataLen; + newUDPheader->contentBytes=sizeof(fs6_dl_t)+sizeof(fs6_dl_uespec_t) + UEdataLen; // We skip the fs6 DL header, that is populated by caller // This header will be duplicated during sending - memcpy(commonUDPdata(firstFreeByte+sizeof(fs6_dl_t)), UEdata, UEdataLen); + fs6_dl_uespec_t *tmp=(fs6_dl_uespec_t *) firstFreeByte+sizeof(fs6_dl_t); + tmp->UE_id=UE_id; + tmp->harq_pid=harq_pid; + tmp->rnti=rnti; + memcpy(commonUDPdata(((uint8_t *)tmp)+sizeof(fs6_dl_uespec_t)), UEdata, UEdataLen); } void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas, uint8_t *buf, int bufSize) { @@ -558,8 +593,8 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx // clear previous allocation information for all UEs for (int i = 0; i < NUMBER_OF_UE_MAX; i++) { - if (eNB->dlsch[i][0]) - eNB->dlsch[i][0]->subframe_tx[subframe] = 0; + //if (eNB->dlsch[i][0]) + //eNB->dlsch[i][0]->subframe_tx[subframe] = 0; } /* TODO: check the following test - in the meantime it is put back as it was before */ @@ -569,7 +604,8 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx for (int i=0; iulsch[i] && eNB->ulsch[i]->ue_type >0) + if (eNB->ulsch[i] && eNB->ulsch[i]->ue_type > NOCE) + // LTE-M case harq_pid = 0; else header->UE_ul_active[i] = harq_pid = subframe2harq_pid(fp,header->ul_frame,header->ul_subframe); @@ -608,7 +644,7 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx uint8_t num_pdcch_symbols = eNB->pdcch_vars[subframe&1].num_pdcch_symbols; uint8_t num_dci = eNB->pdcch_vars[subframe&1].num_dci; - uint8_t num_mdci = eNB->mpdcch_vars[subframe&1].num_dci; + uint8_t num_mdci = eNB->mpdcch_vars[subframe&1].num_dci; LOG_D(PHY,"num_pdcch_symbols %"PRIu8",number dci %"PRIu8"\n",num_pdcch_symbols, num_dci); if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { @@ -626,8 +662,7 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx LTE_eNB_DLSCH_t *dlsch0; for (int UE_id=0; UE_iddlsch[UE_id][0]; - header->UE_dl_active[UE_id]=-1; + LTE_eNB_DLSCH_t *dlsch0 = eNB->dlsch[UE_id][0]; if ((dlsch0)&&(dlsch0->rnti>0)&& #ifdef PHY_TX_THREAD @@ -641,7 +676,7 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx AssertFatal(harq_pid>=0,"harq_pid is negative\n"); if (harq_pid>=8) { - if (dlsch0->ue_type==0) + if (dlsch0->ue_type == NOCE) LOG_E(PHY,"harq_pid:%d corrupt must be 0-7 UE_id:%d frame:%d subframe:%d rnti:%x [ %1d.%1d.%1d.%1d.%1d.%1d.%1d.%1d\n", harq_pid,UE_id,frame,subframe,dlsch0->rnti, dlsch0->harq_ids[frame%2][0], dlsch0->harq_ids[frame%2][1], @@ -652,8 +687,6 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx dlsch0->harq_ids[frame%2][6], dlsch0->harq_ids[frame%2][7]); } else { - header->UE_dl_active[UE_id]=harq_pid; - if (dlsch_procedures(eNB, proc, harq_pid, @@ -673,6 +706,9 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx */ LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch0->harq_processes[harq_pid]; appendFs6DLUE(bufferZone, + UE_id, + harq_pid, + dlsch0->rnti, dlsch0->harq_processes[harq_pid]->e, get_G(fp, dlsch_harq->nb_rb, @@ -693,7 +729,7 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx #endif ) { // clear subframe TX flag since UE is not scheduled for PDSCH in this subframe (so that we don't look for PUCCH later) - dlsch0->subframe_tx[subframe]=0; + //dlsch0->subframe_tx[subframe]=0; } } @@ -791,12 +827,17 @@ void UL_cu_fs6(RU_t *ru,int frame, int subframe, uint64_t TS) { commonUDP_t *UDPheader=(commonUDP_t *) bufferZone; int nb_blocks=receiveSubFrame(&sockFS6, TS, bufferZone, sizeof(bufferZone) ); + if (nb_blocks ==0) { + LOG_W(PHY, "CU lost a subframe\n"); + return; + } + if (nb_blocks != UDPheader->nbBlocks ) LOG_W(PHY, "received %d blocks for %d expected\n", nb_blocks, UDPheader->nbBlocks); // Fixme: datamodel issue PHY_VARS_eNB *eNB = RC.eNB[0][0]; - L1_proc_t *proc = &eNB->proc; + L1_proc_t *proc = &eNB->proc; prach_eNB_process(bufferZone, sizeof(bufferZone), eNB,NULL,proc->frame_rx,proc->subframe_rx); release_UE_in_freeList(eNB->Mod_id); diff --git a/executables/split_headers.h b/executables/split_headers.h index 4cb2f4a5c4..35e2e78d3a 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -53,13 +53,19 @@ typedef struct { DCI_ALLOC_t dci_alloc[32]; int num_mdci; int amp; - int8_t UE_dl_active[NUMBER_OF_UE_MAX]; // the HARQ id for this UE (-1: disabled) int8_t UE_ul_active[NUMBER_OF_UE_MAX]; int8_t UE_ul_first_rb[NUMBER_OF_UE_MAX]; // int8_t UE_ul_last_rb[NUMBER_OF_UE_MAX]; // LTE_eNB_PHICH phich_vars; } fs6_dl_t; +typedef struct { + int UE_id; + int8_t harq_pid; + uint16_t rnti; + int dataLen; +} fs6_dl_uespec_t; + bool createUDPsock (char *sourceIP, char *sourcePort, char *destIP, char *destPort, UDPsock_t *result); int receiveSubFrame(UDPsock_t *sock, uint64_t expectedTS, void *bufferZone, int bufferSize); int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize); diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c index 29bbd774a1..476e255fef 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c @@ -307,7 +307,7 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t dlsch0_harq->codeword = 0; dlsch1_harq = dlsch1->harq_processes[rel8->harq_process]; dlsch1_harq->codeword = 1; - dlsch0->subframe_tx[subframe] = 1; + //dlsch0->subframe_tx[subframe] = 1; LOG_D(PHY,"NFAPI: SFN/SF:%04d%d proc:TX:SFN/SF:%04d%d dlsch0[rnti:%x harq_mask:%04x] dci_pdu[rnti:%x rnti_type:%d harq_process:%d ndi1:%d] dlsch0_harq[round:%d harq_mask:%x ndi:%d]\n", frame,subframe, @@ -658,7 +658,7 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t dlsch0_harq->codeword = 0; // printf("DCI: Setting subframe_tx for subframe %d\n",subframe); - dlsch0->subframe_tx[subframe] = 1; + //dlsch0->subframe_tx[subframe] = 1; conv_rballoc (rel8->resource_allocation_type, rel8->resource_block_coding, fp->N_RB_DL, dlsch0_harq->rb_alloc); @@ -868,7 +868,7 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t dlsch0_harq = dlsch0->harq_processes[rel8->harq_process]; dlsch1_harq = dlsch1->harq_processes[rel8->harq_process]; - dlsch0->subframe_tx[subframe] = 1; + //dlsch0->subframe_tx[subframe] = 1; dlsch0->harq_ids[frame%2][subframe] = rel8->harq_process; dlsch1->harq_ids[frame%2][subframe] = rel8->harq_process; @@ -1316,7 +1316,7 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t } if (dlsch0 != NULL) { - dlsch0->subframe_tx[subframe] = 1; + //dlsch0->subframe_tx[subframe] = 1; dlsch0->harq_ids[frame%2][subframe] = rel8->harq_process; } @@ -1723,7 +1723,7 @@ void fill_mdci_and_dlsch(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,mDCI_ALLOC_t *dc dlsch0_harq->codeword = 0; // printf("DCI: Setting subframe_tx for subframe %d\n",subframe); - dlsch0->subframe_tx[(subframe + 2) % 10] = 1; + //dlsch0->subframe_tx[(subframe + 2) % 10] = 1; LOG_D(PHY,"PDSCH : resource_block_coding %x\n",rel13->resource_block_coding); conv_eMTC_rballoc (rel13->resource_block_coding, @@ -1746,7 +1746,7 @@ void fill_mdci_and_dlsch(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,mDCI_ALLOC_t *dc dlsch0_harq->dl_power_off = 1; - dlsch0->subframe_tx[subframe] = 1; + //dlsch0->subframe_tx[subframe] = 1; if (dlsch0->rnti != rel13->rnti) { // if rnti of dlsch is not the same as in the config, this is a new entry dlsch0_harq->round = 0; dlsch0->harq_mask =0; diff --git a/openair1/PHY/LTE_TRANSPORT/transport_eNB.h b/openair1/PHY/LTE_TRANSPORT/transport_eNB.h index 9e8685732f..196bfcaafb 100644 --- a/openair1/PHY/LTE_TRANSPORT/transport_eNB.h +++ b/openair1/PHY/LTE_TRANSPORT/transport_eNB.h @@ -154,11 +154,11 @@ typedef struct { uint8_t active; #endif /// indicator of UE type (0 = LTE, 1,2 = Cat-M) - int ue_type; + UE_type_t ue_type; /// HARQ process mask, indicates which processes are currently active uint16_t harq_mask; /// Indicator of TX activation per subframe. Used during PUCCH detection for ACK/NAK. - uint8_t subframe_tx[10]; + //uint8_t subframe_tx[10]; /// First CCE of last PDSCH scheduling per subframe. Again used during PUCCH detection for ACK/NAK. uint8_t nCCE[10]; /// Process ID's per subframe. Used to associate received ACKs on PUSCH/PUCCH to DLSCH harq process ids @@ -450,7 +450,7 @@ typedef struct { typedef struct { #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) /// UE type (normal, CEModeA, CEModeB) - uint8_t ue_type; + UE_type_t ue_type; #endif /// HARQ process mask, indicates which processes are currently active uint16_t harq_mask; diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index c4e162ec66..261e092737 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -410,8 +410,8 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, // clear previous allocation information for all UEs for (i = 0; i < NUMBER_OF_UE_MAX; i++) { - if (eNB->dlsch[i][0]) - eNB->dlsch[i][0]->subframe_tx[subframe] = 0; + //if (eNB->dlsch[i][0]) + //eNB->dlsch[i][0]->subframe_tx[subframe] = 0; } /* TODO: check the following test - in the meantime it is put back as it was before */ @@ -548,7 +548,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, #endif ) { // clear subframe TX flag since UE is not scheduled for PDSCH in this subframe (so that we don't look for PUCCH later) - dlsch0->subframe_tx[subframe]=0; + //dlsch0->subframe_tx[subframe]=0; } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,0); From cd920b09eb54a4d6b9fb87541fa069c406631cb8 Mon Sep 17 00:00:00 2001 From: laurent Date: Thu, 1 Aug 2019 10:18:16 +0000 Subject: [PATCH 017/240] test mail --- executables/main-fs6.c | 1 + 1 file changed, 1 insertion(+) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index 16a0cd305c..f54f0b9136 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -20,6 +20,7 @@ #define FS6_BUF_SIZE 100*1000 static UDPsock_t sockFS6; + void prach_eNB_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, int frame,int subframe) { //commonUDP_t *UDPheader=(commonUDP_t *) bufferZone; fs6_ul_t *header=(fs6_ul_t *) commonUDPdata(bufferZone); From 5a7cbde584e03113561d4d244cf834615d5c31fc Mon Sep 17 00:00:00 2001 From: laurent Date: Thu, 1 Aug 2019 12:23:38 +0200 Subject: [PATCH 018/240] test mail --- executables/main-fs6.c | 1 - 1 file changed, 1 deletion(-) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index f54f0b9136..16a0cd305c 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -20,7 +20,6 @@ #define FS6_BUF_SIZE 100*1000 static UDPsock_t sockFS6; - void prach_eNB_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, int frame,int subframe) { //commonUDP_t *UDPheader=(commonUDP_t *) bufferZone; fs6_ul_t *header=(fs6_ul_t *) commonUDPdata(bufferZone); From 02c8b38b18bd568178507912a11e1d24a7340cd5 Mon Sep 17 00:00:00 2001 From: laurent Date: Fri, 2 Aug 2019 11:08:09 +0200 Subject: [PATCH 019/240] adding timestamp management --- executables/main-fs6.c | 112 +++++++++++++++++--------------- executables/split_headers.h | 2 + executables/transport_split.c | 5 ++ targets/RT/USER/lte-softmodem.c | 3 +- 4 files changed, 69 insertions(+), 53 deletions(-) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index 16a0cd305c..c04290fef9 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -21,7 +21,6 @@ static UDPsock_t sockFS6; void prach_eNB_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, int frame,int subframe) { - //commonUDP_t *UDPheader=(commonUDP_t *) bufferZone; fs6_ul_t *header=(fs6_ul_t *) commonUDPdata(bufferZone); if (is_prach_subframe(&eNB->frame_parms, frame,subframe)<=0) @@ -74,7 +73,6 @@ void prach_eNB_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, int } void prach_eNB_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { - //commonUDP_t *UDPheader=(commonUDP_t *) bufferZone; fs6_ul_t *header=(fs6_ul_t *) commonUDPdata(bufferZone); uint16_t *max_preamble=header->max_preamble; uint16_t *max_preamble_energy=header->max_preamble_energy; @@ -438,16 +436,14 @@ void phy_procedures_eNB_uespec_RX_process(uint8_t *bufferZone, int nbBlocks, PHY } void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas ) { - //commonUDP_t *UDPheader=(commonUDP_t *) bufferZone; - fs6_dl_t *header=(fs6_dl_t *) commonUDPdata(bufferZone); // TBD: read frame&subframe from received data - int frame=proc->frame_tx=header->frame; - int subframe=proc->subframe_tx=header->subframe; + int frame=proc->frame_tx=hDL(bufferZone)->frame; + int subframe=proc->subframe_tx=hDL(bufferZone)->subframe; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; //LTE_UL_eNB_HARQ_t *ulsch_harq; - eNB->pdcch_vars[subframe&1].num_pdcch_symbols=header->num_pdcch_symbols; - eNB->pdcch_vars[subframe&1].num_dci=header->num_dci; - uint8_t num_mdci = eNB->mpdcch_vars[subframe&1].num_dci = header->num_mdci; + eNB->pdcch_vars[subframe&1].num_pdcch_symbols=hDL(bufferZone)->num_pdcch_symbols; + eNB->pdcch_vars[subframe&1].num_dci=hDL(bufferZone)->num_dci; + uint8_t num_mdci = eNB->mpdcch_vars[subframe&1].num_dci = hDL(bufferZone)->num_mdci; // Remove all scheduled DL, we will populate from the CU sending for (int UE_id=0; UE_idcontentBytes >= sizeof(fs6_dl_t)+sizeof(fs6_dl_uespec_t) ) { + fs6_dl_uespec_t *dlPtr=(fs6_dl_uespec_t *)(commonUDPdata(bufPtr)+sizeof(fs6_dl_t)); #ifdef PHY_TX_THREAD - eNB->dlsch[dlPtr->UE_id][0]->active[subframe] = 1; + eNB->dlsch[dlPtr->UE_id][0]->active[subframe] = 1; #else - eNB->dlsch[dlPtr->UE_id][0]->active = 1; + eNB->dlsch[dlPtr->UE_id][0]->active = 1; #endif - eNB->dlsch[dlPtr->UE_id][0]->harq_ids[frame%2][subframe]=dlPtr->harq_pid; - eNB->dlsch[dlPtr->UE_id][0]->rnti=dlPtr->rnti; - memcpy(eNB->dlsch[dlPtr->UE_id][0]->harq_processes[dlPtr->harq_pid]->e, - commonUDPdata(((uint8_t *)dlPtr)+sizeof(fs6_dl_t)), dlPtr->dataLen); + eNB->dlsch[dlPtr->UE_id][0]->harq_ids[frame%2][subframe]=dlPtr->harq_pid; + eNB->dlsch[dlPtr->UE_id][0]->rnti=dlPtr->rnti; + memcpy(eNB->dlsch[dlPtr->UE_id][0]->harq_processes[dlPtr->harq_pid]->e, + commonUDPdata(((uint8_t *)dlPtr)+sizeof(fs6_dl_t)), dlPtr->dataLen); + } + bufPtr+=alignedSize(bufPtr); } @@ -505,17 +504,17 @@ void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int nbBlocks, PHY_VARS_e } if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { - for (int i=0; i< header->num_dci; i++) - eNB->pdcch_vars[subframe&1].dci_alloc[i]=header->dci_alloc[i]; + for (int i=0; i< hDL(bufferZone)->num_dci; i++) + eNB->pdcch_vars[subframe&1].dci_alloc[i]=hDL(bufferZone)->dci_alloc[i]; - generate_dci_top(header->num_pdcch_symbols, - header->num_dci, + generate_dci_top(hDL(bufferZone)->num_pdcch_symbols, + hDL(bufferZone)->num_dci, &eNB->pdcch_vars[subframe&1].dci_alloc[0], 0, - header->amp, + hDL(bufferZone)->amp, fp, eNB->common_vars.txdataF, - header->subframe); + hDL(bufferZone)->subframe); if (num_mdci > 0) { LOG_D (PHY, "[eNB %" PRIu8 "] Frame %d, subframe %d: Calling generate_mdci_top (mpdcch) (num_dci %" PRIu8 ")\n", eNB->Mod_id, frame, subframe, num_mdci); @@ -543,7 +542,7 @@ void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int nbBlocks, PHY_VARS_e } } - eNB->phich_vars[subframe&1]=header->phich_vars; + eNB->phich_vars[subframe&1]=hDL(bufferZone)->phich_vars; generate_phich_top(eNB, proc, AMP); @@ -576,7 +575,6 @@ void appendFs6DLUE(uint8_t *bufferZone, int UE_id, int8_t harq_pid, uint16_t rnt } void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas, uint8_t *buf, int bufSize) { - fs6_dl_t *header=(fs6_dl_t *) commonUDPdata(bufferZone); int frame=proc->frame_tx; int subframe=proc->subframe_tx; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; @@ -584,12 +582,12 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx if ((fp->frame_type == TDD) && (subframe_select (fp, subframe) == SF_UL)) return; - header->frame=frame; - header->subframe=subframe; + hDL(bufferZone)->frame=frame; + hDL(bufferZone)->subframe=subframe; // clear existing ulsch dci allocations before applying info from MAC (this is table // returns -1 (or 255) if there is no ul (tdd cases) - header->ul_subframe = pdcch_alloc2ul_subframe (fp, subframe); - header->ul_frame = pdcch_alloc2ul_frame (fp, frame, subframe); + hDL(bufferZone)->ul_subframe = pdcch_alloc2ul_subframe (fp, subframe); + hDL(bufferZone)->ul_frame = pdcch_alloc2ul_frame (fp, frame, subframe); // clear previous allocation information for all UEs for (int i = 0; i < NUMBER_OF_UE_MAX; i++) { @@ -600,7 +598,7 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx /* TODO: check the following test - in the meantime it is put back as it was before */ //if ((ul_subframe < 10)&& // (subframe_select(fp,ul_subframe)==SF_UL)) { // This means that there is a potential UL subframe that will be scheduled here - if (header->ul_subframe < 10) { // This means that there is a potential UL subframe that will be scheduled here + if (hDL(bufferZone)->ul_subframe < 10) { // This means that there is a potential UL subframe that will be schedulyed here for (int i=0; iUE_ul_active[i] = harq_pid = subframe2harq_pid(fp,header->ul_frame,header->ul_subframe); + hDL(bufferZone)->UE_ul_active[i] = harq_pid = subframe2harq_pid(fp, hDL(bufferZone)->ul_frame, + hDL(bufferZone)->ul_subframe); if (eNB->ulsch[i]) { //LTE_UL_eNB_HARQ_t *ulsch_harq = eNB->ulsch[i]->harq_processes[harq_pid]; @@ -636,9 +635,9 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx header->previous_n_DMRS = ulsch_harq->previous_n_DMRS = ulsch_harq->n_DMRS; */ - header->UE_ul_active[i] = harq_pid; + hDL(bufferZone)->UE_ul_active[i] = harq_pid; } else - header->UE_ul_active[i] = -1; + hDL(bufferZone)->UE_ul_active[i] = -1; } } @@ -648,10 +647,10 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx LOG_D(PHY,"num_pdcch_symbols %"PRIu8",number dci %"PRIu8"\n",num_pdcch_symbols, num_dci); if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { - header->num_pdcch_symbols=num_pdcch_symbols; - header->num_dci=num_dci; - header->num_mdci=num_mdci; - header->amp=AMP; + hDL(bufferZone)->num_pdcch_symbols=num_pdcch_symbols; + hDL(bufferZone)->num_dci=num_dci; + hDL(bufferZone)->num_mdci=num_mdci; + hDL(bufferZone)->amp=AMP; } if (do_meas==1) stop_meas(&eNB->dlsch_common_and_dci); @@ -733,7 +732,7 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx } } - header->phich_vars=eNB->phich_vars[subframe&1]; + hDL(bufferZone)->phich_vars=eNB->phich_vars[subframe&1]; if (do_meas==1) stop_meas(&eNB->dlsch_ue_specific); @@ -743,10 +742,15 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx } void DL_du_fs6(RU_t *ru, int frame, int subframe, uint64_t TS) { - //RU_proc_t *ru_proc=&ru->proc; + RU_proc_t *ru_proc=&ru->proc; + for (int i=0; inum_eNB; i++) { initBufferZone(bufferZone); int nb_blocks=receiveSubFrame(&sockFS6, TS, bufferZone, sizeof(bufferZone) ); + L1_rxtx_proc_t *L1_proc = &ru->eNB_list[i]->proc.L1_proc_tx; + L1_proc->timestamp_tx=hUDP(bufferZone)->timestamp; + L1_proc->frame_tx=hDL(bufferZone)->frame; + L1_proc->subframe_tx=hDL(bufferZone)->subframe; if (nb_blocks>0) phy_procedures_eNB_TX_process( bufferZone, nb_blocks, ru->eNB_list[i], &ru->eNB_list[i]->proc.L1_proc, 1); @@ -754,12 +758,11 @@ void DL_du_fs6(RU_t *ru, int frame, int subframe, uint64_t TS) { LOG_E(PHY,"DL not received for subframe: %d\n", subframe); } - /* Fixme: datamodel issue: a ru is supposed to be connected to several eNB - L1_rxtx_proc_t * L1_proc = &proc->L1_proc; - ru_proc->timestamp_tx = L1_proc->timestamp_tx; - ru_proc->subframe_tx = L1_proc->subframe_tx; - ru_proc->frame_tx = L1_proc->frame_tx; - */ + /* OAI data model is wrong: hardcode link ru to enb index 0*/ + L1_rxtx_proc_t *L1_proc = &ru->eNB_list[0]->proc.L1_proc_tx; + ru_proc->timestamp_tx = L1_proc->timestamp_tx; + ru_proc->subframe_tx = L1_proc->subframe_tx; + ru_proc->frame_tx = L1_proc->frame_tx; feptx_prec(ru); feptx_ofdm(ru); tx_rf(ru); @@ -787,6 +790,9 @@ void UL_du_fs6(RU_t *ru, int frame, int subframe) { } initBufferZone(bufferZone); + hDL(bufferZone)->frame=frame; + hDL(bufferZone)->subframe=subframe; + hUDP(bufferZone)->timestamp=ru->proc.timestamp_rx; prach_eNB_extract(bufferZone, FS6_BUF_SIZE, eNB, proc->frame_rx,proc->subframe_rx ); if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { @@ -811,12 +817,14 @@ void DL_cu_fs6(RU_t *ru,int frame, int subframe) { pthread_mutex_unlock(&eNB->UL_INFO_mutex); initBufferZone(bufferZone); phy_procedures_eNB_TX_extract(bufferZone, eNB, &proc->L1_proc, 1, bufferZone, FS6_BUF_SIZE); - commonUDP_t *firstHeader=(commonUDP_t *) bufferZone; + hUDP(bufferZone)->timestamp=proc->L1_proc.timestamp_tx; + hDL(bufferZone)->frame=frame; + hDL(bufferZone)->subframe=subframe; - if (firstHeader->nbBlocks==0) { - firstHeader->nbBlocks=1; // We have to send the signaling, even is there is no user plan data (no UE) - firstHeader->blockID=0; - firstHeader->contentBytes=sizeof(fs6_dl_t); + if (hUDP(bufferZone)->nbBlocks==0) { + hUDP(bufferZone)->nbBlocks=1; // We have to send the signaling, even is there is no user plan data (no UE) + hUDP(bufferZone)->blockID=0; + hUDP(bufferZone)->contentBytes=sizeof(fs6_dl_t); } sendSubFrame(&sockFS6, bufferZone, sizeof(fs6_dl_t) ); @@ -824,7 +832,6 @@ void DL_cu_fs6(RU_t *ru,int frame, int subframe) { void UL_cu_fs6(RU_t *ru,int frame, int subframe, uint64_t TS) { initBufferZone(bufferZone); - commonUDP_t *UDPheader=(commonUDP_t *) bufferZone; int nb_blocks=receiveSubFrame(&sockFS6, TS, bufferZone, sizeof(bufferZone) ); if (nb_blocks ==0) { @@ -832,12 +839,13 @@ void UL_cu_fs6(RU_t *ru,int frame, int subframe, uint64_t TS) { return; } - if (nb_blocks != UDPheader->nbBlocks ) - LOG_W(PHY, "received %d blocks for %d expected\n", nb_blocks, UDPheader->nbBlocks); + if (nb_blocks != hUDP(bufferZone)->nbBlocks ) + LOG_W(PHY, "received %d blocks for %d expected\n", nb_blocks, hUDP(bufferZone)->nbBlocks); // Fixme: datamodel issue PHY_VARS_eNB *eNB = RC.eNB[0][0]; L1_proc_t *proc = &eNB->proc; + proc->timestamp_rx=hUDP(bufferZone)->timestamp; prach_eNB_process(bufferZone, sizeof(bufferZone), eNB,NULL,proc->frame_rx,proc->subframe_rx); release_UE_in_freeList(eNB->Mod_id); diff --git a/executables/split_headers.h b/executables/split_headers.h index 35e2e78d3a..0b9104fc20 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -74,6 +74,8 @@ int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize); uint8_t xBuf[FS6_BUF_SIZE];\ ((commonUDP_t *)xBuf)->nbBlocks=0; +#define hUDP(xBuf) ((commonUDP_t *)xBuf) +#define hDL(xBuf) (((fs6_dl_t*)((commonUDP_t *)xBuf)+1)) inline size_t alignedSize(uint8_t *ptr) { commonUDP_t *header=(commonUDP_t *) ptr; diff --git a/executables/transport_split.c b/executables/transport_split.c index 8a43a63833..6b13036d11 100644 --- a/executables/transport_split.c +++ b/executables/transport_split.c @@ -104,6 +104,11 @@ int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize) { int nbBlocks=UDPheader->nbBlocks; int blockId=0; + if (nbBlocks <= 0 ) { + LOG_E(PHY,"FS6: can't send blocks: %d\n", nbBlocks); + return 0; + } + do { if (blockId > 0 ) { commonUDP_t *currentHeader=(commonUDP_t *)bufferZone; diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index dc429f0288..109c0afdd4 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -593,7 +593,8 @@ int main( int argc, char **argv ) { /* initializes PDCP and sets correct RLC Request/PDCP Indication callbacks * for monolithic/F1 modes */ - init_pdcp(); + if ( getenv("fs6") == NULL || strncasecmp( getenv("fs6"), "du", 2) != 0 ) + init_pdcp(); if (create_tasks(1) < 0) { printf("cannot create ITTI tasks\n"); From 9b8e103329c0b86876646ee47953dd25b5db4f6b Mon Sep 17 00:00:00 2001 From: ferrieux Date: Fri, 2 Aug 2019 21:49:09 +0200 Subject: [PATCH 020/240] test mail --- executables/main-fs6.c | 1 + 1 file changed, 1 insertion(+) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index c04290fef9..e68327084a 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -18,6 +18,7 @@ #include #define FS6_BUF_SIZE 100*1000 + static UDPsock_t sockFS6; void prach_eNB_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, int frame,int subframe) { From 0d582559053c33f4333e71d6865d1c0ea26ec710 Mon Sep 17 00:00:00 2001 From: laurent Date: Sat, 3 Aug 2019 11:51:11 +0200 Subject: [PATCH 021/240] test --- executables/main-ocp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/executables/main-ocp.c b/executables/main-ocp.c index 3fc3b00e89..3e9e7bdf64 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -14,6 +14,7 @@ #include #include + static int DEFBANDS[] = {7}; static int DEFENBS[] = {0}; #include From ebb52e388bc6f2342f54b4311c83bd8242ef3099 Mon Sep 17 00:00:00 2001 From: ferrieux Date: Sat, 3 Aug 2019 15:50:50 +0200 Subject: [PATCH 022/240] test mail, qui marche \! --- executables/main-fs6.c | 1 - 1 file changed, 1 deletion(-) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index e68327084a..c04290fef9 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -18,7 +18,6 @@ #include #define FS6_BUF_SIZE 100*1000 - static UDPsock_t sockFS6; void prach_eNB_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, int frame,int subframe) { From 88d5739040ce656858f710a71e04e0d41d569b58 Mon Sep 17 00:00:00 2001 From: laurent Date: Mon, 5 Aug 2019 21:19:27 +0200 Subject: [PATCH 023/240] continue timestamp --- SystemX-tutorial-design.md | 264 ++++++++++++++++++++++++ cmake_targets/CMakeLists.txt | 4 +- executables/main-fs6.c | 41 ++-- executables/main-ocp.c | 14 +- executables/split_headers.h | 11 +- executables/transport_split.c | 34 ++- openair1/SCHED/phy_procedures_lte_eNb.c | 4 +- 7 files changed, 325 insertions(+), 47 deletions(-) create mode 100644 SystemX-tutorial-design.md diff --git a/SystemX-tutorial-design.md b/SystemX-tutorial-design.md new file mode 100644 index 0000000000..6371c81050 --- /dev/null +++ b/SystemX-tutorial-design.md @@ -0,0 +1,264 @@ +# OpenAirInterface for SystemX + +#Terminology + +****This document use the 5G terminology**** + +**Central Unit (CU): **It is a logical node that includes the gNB +functions like Transfer of user data, Mobility control, Radio access +network sharing, Positioning, Session Management etc., except those +functions allocated exclusively to the DU. CU controls the operation of +DUs over front-haul (Fs) interface. A central unit (CU) may also be +known as BBU/REC/RCC/C-RAN/V-RAN/VNF + +**Distributed Unit (DU):** This logical node includes a subset of the +gNB functions, depending on the functional split option. Its operation +is controlled by the CU. Distributed Unit (DU) also known with other +names like RRH/RRU/RE/RU/PNF. + +In OpenAir code, the terminology is often RU and BBU. + +#Usage +##EPC and general environment +### OAI EPC + +Use the stable OAI EPC, that can run in one machine (VM or standalone) + +Draft description: + + +##Standalone 4G + +EPC+eNB on one machine, the UE can be commercial or OAI UE. +### USRP B210 + +Main current issue: traffic is good only on coaxial link between UE and +eNB (probably power management issue). + +### Simulated RF + +Running eNB+UE both OAI can be done over a virtual RF link. + +The UE current status is that threads synchronization is implicit in +some cases. As the RF simulator is very quick, a “sleep()” is required +in the UE main loop + +(line 1744, targets/RT/USER/lte-ue.c). + +Running also the UE in the same machine is possible with simulated RF. + +Running in same machine is simpler, offers about infinite speed for +virtual RF samples transmission. + +A specific configuration is required because the EPC Sgi interface has +the same IP tunnel end point as the UE. + +So, we have to create a network namespace for the UE and to route data +in/out of the namespace. +``` bash +ip netns delete aNameSpace 2> /dev/null + +ip link delete v-eth1 2> /dev/null + +ip netns add aNameSpace + +ip link add v-eth1 type veth peer name v-peer1 + +ip link set v-peer1 netns aNameSpace + +ip addr add 10.200.1.1/24 dev v-eth1 + +ip link set v-eth1 up + +iptables -t nat -A POSTROUTING -s 10.200.1.0/255.255.255.0 -o enp0s31f6 +-j MASQUERADE + +iptables -A FORWARD -i enp0s31f6 -o v-eth1 -j ACCEPT + +iptables -A FORWARD -o enp0s31f6 -i v-eth1 -j ACCEPT + +ip netns exec aNameSpace ip link set dev lo up + +ip netns exec aNameSpace ip addr add 10.200.1.2/24 dev v-peer1 + +ip netns exec aNameSpace ip link set v-peer1 up + +ip netns exec aNameSpace bash +``` + +After the last command, the Linux shell is in the new namespace, ready +to run the UE. + +To make user plan traffic, the traffic generator has to run in the same +namespace + +`ip netns exec aNameSpace bash +` + +The traffic genenrator has to specify the interface: + +`route add default oaitun_ue1 +` + +or specify the outgoing route in the traffic generator (like option “-I” +in ping command). + +## Split 6 DL 4G + +The contract describes to reuse the uplink existing if4p5 and to develop +is this work the downlink “functional split 6”. + +The customer required after signature to develop also the uplink +functional split 6. This is accepted, as long as the whole work is +research with no delivery completeness warranty. +### Simulation + +To be able to verify the new features and to help in all future +developments, Open Cells added and improved the Rf board simulator +during this contract. + +We added the channel modeling simulation, that offer to simulate various +3GPP defined channels. +### Main loop + +The main log is in RF simulator is in + + targets/RT/USER/lte-ru.c and targets/RT/USER/lte-enb.c + +As this piece of SW is very complex and doesn’t meet our goals +(functional split 6), a cleaned version replaces these 2 files in +executables/ocp-main.c (openair1/SCHED/prach\_procedures.c is also +replaced by this new file as it only launching the RACH actual work in a +way not compatible with our FS6). + +The main loop cadences the I/Q samples reception, signal processing and +I/Q samples sending. + +The main loop uses extensively function pointers to call the right +processing function depending on the split case. + +This is enough for RF board dialog, but the FS6 is higher in SW layers, +we need to cut higher functions inside downlink and uplink procedures. + +### DownLink + +The main procedure is phy\_procedures\_eNB\_TX + +This is building the common channels (beacon, multi-UE signaling). + +The FS6 split breaks this function into pieces: + +- The multi-UE signals, built by common\_signal\_procedures(), + subframe2harq\_pid(), generate\_dci\_top(), subframe2harq\_pid() + + - These functions will be executed in the DU, nevertheless all + context has to be sent (it is also needed partially for + UL spitting) + - IT should be in the DU also to meet the requirement of pushing + in DU the data encoded with large redundancy (>3 redundancy) +- the per UE data: pdsch\_procedures() that needs further splitting: + + - dlsch\_encoding\_all() that makes the encoding: turbo code + and lte\_rate\_matching\_turbo() that will be in the DU (some + unlikely cases can reach redundancy up to x3, when MCS is very + low (negative SINR cases)). + + - dlsch\_encoding() output needs to be transmitted between the + DU and the CU for functional split 6. + - dlsch\_scrambling() that will go in the DU + - dlsch\_modulation() that will go in the DU + +### Uplink + +The uplink require configuration that is part of the DL transmission. + +It interprets the signalling to extract the RACH and the per UE data +channels. + +Ocp-main.c:rxtx() calls directly the entry procedure +phy\_procedures\_eNB\_uespec\_RX() calls: + +- rx\_ulsch() that demodulate and extract soft bits per UE. + + - This function runs in the DU + - the output data will be processes in the DU, so it needs to be + transmitted to the DU +- ulsch\_decoding() that do lte\_rate\_matching\_turbo\_rx() + sub\_block\_deinterleaving\_turbo() then turbo decode + + - it runs +- fill\_ulsch\_cqi\_indication() + + - TBD: either runs in DU or output needs to be transmitted to DU +- fill\_crc\_indication() , fill\_rx\_indication() results need also + to be transmitted or made in the DU + +### UDP transport layer + +A general UDP transport layer is in executables/transport\_split.c + +Linux offers a UDP socket builtin timeout, that we use. + +In and out buffers are memory zones that contains compacted +(concatenated) UDP chunks. + +For output, sendSubFrame() sends each UDP chunk + +For input, receiveSubFrame() collects all UDP chunks for a group (a +subframe in OAI LTE case). It returns in the following cases: + +- all chunks are received +- a timeout expired +- a chunk from the next subframe already arrived + +### Functional split 6 usage + +The ocp cleaned main hale to be used: run ocp-softmodem instead of +lte-softmodem. + +The functionality and parameters is the same, enhanced with FS6 mode. + +The environment variable “fs6” enables the fs6 mode and decided to be cu +or du from the fs6 variable content. + +Example: + +`fs6=cu ./ocp-softmodem -O … (regular lte-softmodem paramters) +` + +Run the CU init of the split 6 eNB. + +CU and DU IP address and port are configurable in the eNB configuration +file (as X2, GTP, … interfaces). + +##5G and F1 + +Today 5G achievement is limited to physical layer. + +The available modulation is 40MHz, that require one X310 or N300 for the +gNB and a X310 or N300 for the nrUE. + +### Usage with X310 + +Linux configuration: + + +We included most of this configuration included in OAI source code. + +Remain to set the NIC (network interface card) MTU to 9000 (jumbo +frames). + +### Running 5G + +Usage with RFsimulator: + +gNB + +`sudo RFSIMULATOR=server ./nr-softmodem -O +../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf +--parallel-config PARALLEL\_SINGLE\_THREAD` + +nrUE + +`sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --numerology 1 -r 106 -C +3510000000 -d` diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 62b592673f..76be8cf250 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -183,8 +183,8 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath -Wl,${CMAKE_CU ######################### # set a flag for changes in the source code # these changes are related to hardcoded path to include .h files -set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -g -DMALLOC_CHECK_=3") -set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS} -g -DMALLOC_CHECK_=3 -O2") +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -g3 -DMALLOC_CHECK_=3") +set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS} -g3 -DMALLOC_CHECK_=3 -O0") set(GIT_BRANCH "UNKNOWN") diff --git a/executables/main-fs6.c b/executables/main-fs6.c index c04290fef9..4e4d7dd54d 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -653,6 +653,8 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx hDL(bufferZone)->amp=AMP; } + if (num_mdci) abort(); + if (do_meas==1) stop_meas(&eNB->dlsch_common_and_dci); if (do_meas==1) start_meas(&eNB->dlsch_ue_specific); @@ -741,21 +743,21 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx return; } -void DL_du_fs6(RU_t *ru, int frame, int subframe, uint64_t TS) { +void DL_du_fs6(RU_t *ru) { RU_proc_t *ru_proc=&ru->proc; for (int i=0; inum_eNB; i++) { initBufferZone(bufferZone); - int nb_blocks=receiveSubFrame(&sockFS6, TS, bufferZone, sizeof(bufferZone) ); - L1_rxtx_proc_t *L1_proc = &ru->eNB_list[i]->proc.L1_proc_tx; - L1_proc->timestamp_tx=hUDP(bufferZone)->timestamp; - L1_proc->frame_tx=hDL(bufferZone)->frame; - L1_proc->subframe_tx=hDL(bufferZone)->subframe; + int nb_blocks=receiveSubFrame(&sockFS6, ru_proc->timestamp_tx, bufferZone, sizeof(bufferZone), CTsentCUv0 ); - if (nb_blocks>0) + if (nb_blocks > 0) { + L1_rxtx_proc_t *L1_proc = &ru->eNB_list[i]->proc.L1_proc_tx; + L1_proc->timestamp_tx=hUDP(bufferZone)->timestamp; + L1_proc->frame_tx=hDL(bufferZone)->frame; + L1_proc->subframe_tx=hDL(bufferZone)->subframe; phy_procedures_eNB_TX_process( bufferZone, nb_blocks, ru->eNB_list[i], &ru->eNB_list[i]->proc.L1_proc, 1); - else - LOG_E(PHY,"DL not received for subframe: %d\n", subframe); + } else + LOG_E(PHY,"DL not received for subframe\n"); } /* OAI data model is wrong: hardcode link ru to enb index 0*/ @@ -799,8 +801,14 @@ void UL_du_fs6(RU_t *ru, int frame, int subframe) { phy_procedures_eNB_uespec_RX_extract(bufferZone, FS6_BUF_SIZE, eNB, &proc->L1_proc ); } + if (hUDP(bufferZone)->nbBlocks==0) { + hUDP(bufferZone)->nbBlocks=1; // We have to send the signaling, even is there is no user plan data (no UE) + hUDP(bufferZone)->blockID=0; + hUDP(bufferZone)->contentBytes=sizeof(fs6_ul_t); + } + for (int i=0; inum_eNB; i++) { - sendSubFrame(&sockFS6,bufferZone, sizeof(fs6_ul_t)); + sendSubFrame(&sockFS6, bufferZone, sizeof(fs6_ul_t), CTsentDUv0); } } @@ -827,12 +835,12 @@ void DL_cu_fs6(RU_t *ru,int frame, int subframe) { hUDP(bufferZone)->contentBytes=sizeof(fs6_dl_t); } - sendSubFrame(&sockFS6, bufferZone, sizeof(fs6_dl_t) ); + sendSubFrame(&sockFS6, bufferZone, sizeof(fs6_dl_t), CTsentCUv0 ); } void UL_cu_fs6(RU_t *ru,int frame, int subframe, uint64_t TS) { initBufferZone(bufferZone); - int nb_blocks=receiveSubFrame(&sockFS6, TS, bufferZone, sizeof(bufferZone) ); + int nb_blocks=receiveSubFrame(&sockFS6, TS, bufferZone, sizeof(bufferZone), CTsentDUv0 ); if (nb_blocks ==0) { LOG_W(PHY, "CU lost a subframe\n"); @@ -878,7 +886,6 @@ void *cu_fs6(void *arg) { void *du_fs6(void *arg) { RU_t *ru = (RU_t *)arg; //RU_proc_t *proc = &ru->proc; - int64_t AbsoluteSubframe=-1; fill_rf_config(ru,ru->rf_config_file); init_frame_parms(&ru->frame_parms,1); phy_init_RU(ru); @@ -887,11 +894,9 @@ void *du_fs6(void *arg) { AssertFatal(createUDPsock(NULL, "7777", "127.0.0.1", "8888", &sockFS6),""); while(1) { - AbsoluteSubframe++; - int subframe=AbsoluteSubframe%10; - int frame=(AbsoluteSubframe/10)%1024; - UL_du_fs6(ru, frame,subframe); - DL_du_fs6(ru, frame,subframe, AbsoluteSubframe); + L1_rxtx_proc_t *proc = &ru->eNB_list[0]->proc; + UL_du_fs6(ru, proc->frame_rx,proc->subframe_rx); + DL_du_fs6(ru); } return NULL; diff --git a/executables/main-ocp.c b/executables/main-ocp.c index 3e9e7bdf64..92546eb018 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -582,13 +582,11 @@ static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name return(0); } -void eNB_top(PHY_VARS_eNB *eNB, int frame_rx, int subframe_rx, char *string,RU_t *ru) { +void eNB_top(PHY_VARS_eNB *eNB, int dummy1, int dummy2, char *string,RU_t *ru) { L1_proc_t *proc = &eNB->proc; L1_rxtx_proc_t *L1_proc = &proc->L1_proc; LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; RU_proc_t *ru_proc=&ru->proc; - proc->frame_rx = frame_rx; - proc->subframe_rx = subframe_rx; if (!oai_exit) { L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_tti); @@ -650,16 +648,6 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) { proc->subframe_tx = (proc->subframe_rx+sf_ahead)%10; proc->frame_tx = (proc->subframe_rx>(9-sf_ahead)) ? (proc->frame_rx+1)&1023 : proc->frame_rx; - if (proc->first_rx == 0) { - AssertFatal( proc->subframe_rx == *subframe && proc->frame_rx == *frame, - "Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d) (proc->frame_rx %d frame %d)\n", - (long long unsigned int)proc->timestamp_rx,proc->subframe_rx,*subframe, proc->frame_rx,*frame); - } else { - proc->first_rx = 0; - *frame = proc->frame_rx; - *subframe = proc->subframe_rx; - } - if (rxs != fp->samples_per_tti) { #if defined(USRP_REC_PLAY) exit_fun("Exiting IQ record/playback"); diff --git a/executables/split_headers.h b/executables/split_headers.h index 0b9104fc20..9674541628 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -18,6 +18,9 @@ typedef struct { int sockHandler; } UDPsock_t; +#define CTsentCUv0 0xA500 +#define CTsentDUv0 0x5A00 + typedef struct commonUDP_s { uint64_t timestamp; // id of the group (subframe for LTE) uint16_t nbBlocks; // total number of blocks for this timestamp @@ -67,8 +70,8 @@ typedef struct { } fs6_dl_uespec_t; bool createUDPsock (char *sourceIP, char *sourcePort, char *destIP, char *destPort, UDPsock_t *result); -int receiveSubFrame(UDPsock_t *sock, uint64_t expectedTS, void *bufferZone, int bufferSize); -int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize); +int receiveSubFrame(UDPsock_t *sock, uint64_t expectedTS, void *bufferZone, int bufferSize, uint16_t contentType); +int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize, uint16_t contentType); #define initBufferZone(xBuf) \ uint8_t xBuf[FS6_BUF_SIZE];\ @@ -77,12 +80,12 @@ int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize); #define hUDP(xBuf) ((commonUDP_t *)xBuf) #define hDL(xBuf) (((fs6_dl_t*)((commonUDP_t *)xBuf)+1)) -inline size_t alignedSize(uint8_t *ptr) { +static inline size_t alignedSize(uint8_t *ptr) { commonUDP_t *header=(commonUDP_t *) ptr; return ((header->contentBytes+sizeof(commonUDP_t)+blockAlign-1)/blockAlign)*blockAlign; } -inline void *commonUDPdata(uint8_t *ptr) { +static inline void *commonUDPdata(uint8_t *ptr) { return (void *) (((commonUDP_t *)ptr)+1); } diff --git a/executables/transport_split.c b/executables/transport_split.c index 6b13036d11..490f1259a3 100644 --- a/executables/transport_split.c +++ b/executables/transport_split.c @@ -56,7 +56,8 @@ bool createUDPsock (char *sourceIP, char *sourcePort, char *destIP, char *destPo int enable=1; AssertFatal(setsockopt(result->sockHandler, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable))==0,""); - struct timeval tv= {0,UDP_TIMEOUT}; + //struct timeval tv= {0,UDP_TIMEOUT}; + struct timeval tv= {2,UDP_TIMEOUT}; //debug: wait 2 seconds for human understanding AssertFatal(setsockopt(result->sockHandler, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(tv)) ==0,""); // Make a send/recv buffer larger than a a couple of subframe // so the kernel will store for us in and out paquets @@ -69,9 +70,9 @@ bool createUDPsock (char *sourceIP, char *sourcePort, char *destIP, char *destPo // sock: udp socket // expectedTS: the expected timestamp, 0 if unknown // bufferZone: a reception area of bufferSize -int receiveSubFrame(UDPsock_t *sock, uint64_t expectedTS, void *bufferZone, int bufferSize) { +int receiveSubFrame(UDPsock_t *sock, uint64_t expectedTS, void *bufferZone, int bufferSize, uint16_t contentType) { int rcved=0; - commonUDP_t *tmp=NULL; + commonUDP_t *bufOrigin=(commonUDP_t *)bufferZone; do { //read all subframe data from the control unit @@ -85,22 +86,37 @@ int receiveSubFrame(UDPsock_t *sock, uint64_t expectedTS, void *bufferZone, int return -1; } } else { - tmp=(commonUDP_t *)bufferZone; + if (hUDP(bufferZone)->contentType != contentType) + abort(); - if ( expectedTS && tmp->timestamp != expectedTS) { - LOG_W(HW,"Received a paquet in mixed subframes, dropping it\n"); + if ( hUDP(bufferZone)->timestamp != expectedTS) { + if ( hUDP(bufferZone)->timestamp < expectedTS) { + LOG_W(HW,"Received a paquet from past subframes, dropping it\n"); + } else { + LOG_W(HW,"Received a paquet in future subframes\n"); + + if ( rcved == 0 ) { + LOG_W(HW,"First paquet in the sub-frame, keeping it\n"); + rcved++; + bufferZone+=ret; + expectedTS=hUDP(bufferZone)->timestamp; + } + } } else { rcved++; bufferZone+=ret; } } - } while ( !rcved || rcved < tmp->nbBlocks ); + } while ( !rcved || rcved < hUDP(bufferZone)->nbBlocks ); + LOG_D(HW,"Received: nb_blocks: %d, TS: %lu, frame: %d, subframe: %d\n", + rcved, bufOrigin->timestamp, *(((int *)bufOrigin)+1), *(((int *)bufOrigin)+2)); return rcved; } -int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize) { +int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize, uint16_t contentType) { commonUDP_t *UDPheader=(commonUDP_t *)bufferZone ; + UDPheader->contentType=contentType; int nbBlocks=UDPheader->nbBlocks; int blockId=0; @@ -131,5 +147,7 @@ int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize) { nbBlocks--; } while (nbBlocks); + LOG_D(HW,"Sent: TS: %lu, frame: %d, subframe: %d\n", + UDPheader->timestamp, *(((int *)UDPheader)+1), *(((int *)UDPheader)+2)); return 0; } diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 261e092737..17d3001205 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -409,10 +409,10 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, ul_frame = pdcch_alloc2ul_frame (fp, frame, subframe); // clear previous allocation information for all UEs - for (i = 0; i < NUMBER_OF_UE_MAX; i++) { + //for (i = 0; i < NUMBER_OF_UE_MAX; i++) { //if (eNB->dlsch[i][0]) //eNB->dlsch[i][0]->subframe_tx[subframe] = 0; - } + //} /* TODO: check the following test - in the meantime it is put back as it was before */ //if ((ul_subframe < 10)&& From 32e19dbbb756ea7cbdc0b0e44fb1d65a64301f0b Mon Sep 17 00:00:00 2001 From: laurent Date: Fri, 9 Aug 2019 08:10:36 +0200 Subject: [PATCH 024/240] removed all frame/subframe copies distributed update, replace by a single function --- executables/main-fs6.c | 163 +++++++++++++++--------- executables/main-ocp.c | 6 +- executables/split_headers.h | 22 ++-- executables/transport_split.c | 50 +++++--- openair1/PHY/LTE_TRANSPORT/pbch.c | 2 +- openair1/SCHED/phy_procedures_lte_eNb.c | 2 +- 6 files changed, 150 insertions(+), 95 deletions(-) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index 4e4d7dd54d..ace3f7fd1d 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -20,6 +20,48 @@ #define FS6_BUF_SIZE 100*1000 static UDPsock_t sockFS6; +// Fixme: there are many mistakes in the datamodel and in redondant variables +// TDD is also mode complex +void setAllfromTS(uint64_t TS) { + for (int i=0; i frame_parms; + uint64_t TStx=TS+sf_ahead*fp->samples_per_tti; + RU_proc_t *proc =&RC.ru[i]->proc; + proc->timestamp_rx= TS; + proc->timestamp_tx= TStx; + proc->subframe_rx= (TS / fp->samples_per_tti)%10; + proc->subframe_tx= (TStx / fp->samples_per_tti)%10; + proc->subframe_prach=(TS / fp->samples_per_tti)%10; + proc->subframe_prach_br=(TS / fp->samples_per_tti)%10; + proc->frame_rx= (TS / (fp->samples_per_tti*10))&1023; + proc->frame_tx= (TStx / (fp->samples_per_tti*10))&1023; + } + + for (int i=0; i < RC.nb_inst; i++) { + for (int j=0; jframe_parms; + uint64_t TStx=TS+sf_ahead*fp->samples_per_tti; + L1_proc_t *proc =&RC.eNB[i][j]->proc; + L1_rxtx_proc_t *proc1=&RC.eNB[i][j]->proc.L1_proc; + proc->timestamp_rx= TS; + proc->timestamp_tx= TStx; + proc->subframe_rx= (TS / fp->samples_per_tti)%10; + proc->subframe_prach=(TS / fp->samples_per_tti)%10; + proc->subframe_prach_br=(TS / fp->samples_per_tti)%10; + proc->frame_rx= (TS / (fp->samples_per_tti*10))&1023; + proc->frame_tx= (TStx / (fp->samples_per_tti*10))&1023; + proc1->timestamp_tx= TStx; + proc1->subframe_rx= (TS / fp->samples_per_tti)%10; + proc1->subframe_tx= (TStx / fp->samples_per_tti)%10; + proc1->frame_rx= (TS / (fp->samples_per_tti*10))&1023; + proc1->frame_tx= (TStx / (fp->samples_per_tti*10))&1023; + } + } + + return; +} + + void prach_eNB_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, int frame,int subframe) { fs6_ul_t *header=(fs6_ul_t *) commonUDPdata(bufferZone); @@ -436,10 +478,9 @@ void phy_procedures_eNB_uespec_RX_process(uint8_t *bufferZone, int nbBlocks, PHY } void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas ) { - // TBD: read frame&subframe from received data - int frame=proc->frame_tx=hDL(bufferZone)->frame; - int subframe=proc->subframe_tx=hDL(bufferZone)->subframe; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + int subframe=proc->subframe_tx; + int frame=proc->frame_tx; //LTE_UL_eNB_HARQ_t *ulsch_harq; eNB->pdcch_vars[subframe&1].num_pdcch_symbols=hDL(bufferZone)->num_pdcch_symbols; eNB->pdcch_vars[subframe&1].num_dci=hDL(bufferZone)->num_dci; @@ -462,16 +503,16 @@ void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int nbBlocks, PHY_VARS_e for (int i=0; i < nbBlocks; i++) { //nbBlocks is the actual received blocks if ( ((commonUDP_t *)bufPtr)->contentBytes >= sizeof(fs6_dl_t)+sizeof(fs6_dl_uespec_t) ) { - fs6_dl_uespec_t *dlPtr=(fs6_dl_uespec_t *)(commonUDPdata(bufPtr)+sizeof(fs6_dl_t)); + int curUE=hDLUE(bufPtr)->UE_id; #ifdef PHY_TX_THREAD - eNB->dlsch[dlPtr->UE_id][0]->active[subframe] = 1; + eNB->dlsch[curUE][0]->active[subframe] = 1; #else - eNB->dlsch[dlPtr->UE_id][0]->active = 1; + eNB->dlsch[curUE][0]->active = 1; #endif - eNB->dlsch[dlPtr->UE_id][0]->harq_ids[frame%2][subframe]=dlPtr->harq_pid; - eNB->dlsch[dlPtr->UE_id][0]->rnti=dlPtr->rnti; - memcpy(eNB->dlsch[dlPtr->UE_id][0]->harq_processes[dlPtr->harq_pid]->e, - commonUDPdata(((uint8_t *)dlPtr)+sizeof(fs6_dl_t)), dlPtr->dataLen); + eNB->dlsch[curUE][0]->harq_ids[frame%2][subframe]=hDLUE(bufPtr)->harq_pid; + eNB->dlsch[curUE][0]->rnti=hDLUE(bufPtr)->rnti; + memcpy(eNB->dlsch[curUE][0]->harq_processes[hDLUE(bufPtr)->harq_pid]->e, + hDLUE(bufPtr)+1, hDLUE(bufPtr)->dataLen); } bufPtr+=alignedSize(bufPtr); @@ -514,7 +555,7 @@ void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int nbBlocks, PHY_VARS_e hDL(bufferZone)->amp, fp, eNB->common_vars.txdataF, - hDL(bufferZone)->subframe); + subframe); if (num_mdci > 0) { LOG_D (PHY, "[eNB %" PRIu8 "] Frame %d, subframe %d: Calling generate_mdci_top (mpdcch) (num_dci %" PRIu8 ")\n", eNB->Mod_id, frame, subframe, num_mdci); @@ -567,11 +608,11 @@ void appendFs6DLUE(uint8_t *bufferZone, int UE_id, int8_t harq_pid, uint16_t rnt newUDPheader->contentBytes=sizeof(fs6_dl_t)+sizeof(fs6_dl_uespec_t) + UEdataLen; // We skip the fs6 DL header, that is populated by caller // This header will be duplicated during sending - fs6_dl_uespec_t *tmp=(fs6_dl_uespec_t *) firstFreeByte+sizeof(fs6_dl_t); - tmp->UE_id=UE_id; - tmp->harq_pid=harq_pid; - tmp->rnti=rnti; - memcpy(commonUDPdata(((uint8_t *)tmp)+sizeof(fs6_dl_uespec_t)), UEdata, UEdataLen); + hDLUE(newUDPheader)->UE_id=UE_id; + hDLUE(newUDPheader)->harq_pid=harq_pid; + hDLUE(newUDPheader)->rnti=rnti; + hDLUE(newUDPheader)->dataLen=UEdataLen; + memcpy(hDLUE(newUDPheader)+1, UEdata, UEdataLen); } void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas, uint8_t *buf, int bufSize) { @@ -579,15 +620,15 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx int subframe=proc->subframe_tx; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - if ((fp->frame_type == TDD) && (subframe_select (fp, subframe) == SF_UL)) + if ((fp->frame_type == TDD) && (subframe_select (fp, subframe) == SF_UL)) { + LOG_W(HW,"no sending in eNB_TX\n"); return; + } - hDL(bufferZone)->frame=frame; - hDL(bufferZone)->subframe=subframe; // clear existing ulsch dci allocations before applying info from MAC (this is table // returns -1 (or 255) if there is no ul (tdd cases) - hDL(bufferZone)->ul_subframe = pdcch_alloc2ul_subframe (fp, subframe); - hDL(bufferZone)->ul_frame = pdcch_alloc2ul_frame (fp, frame, subframe); + int ul_subframe = pdcch_alloc2ul_subframe (fp, subframe); + int ul_frame = pdcch_alloc2ul_frame (fp, frame, subframe); // clear previous allocation information for all UEs for (int i = 0; i < NUMBER_OF_UE_MAX; i++) { @@ -598,7 +639,7 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx /* TODO: check the following test - in the meantime it is put back as it was before */ //if ((ul_subframe < 10)&& // (subframe_select(fp,ul_subframe)==SF_UL)) { // This means that there is a potential UL subframe that will be scheduled here - if (hDL(bufferZone)->ul_subframe < 10) { // This means that there is a potential UL subframe that will be schedulyed here + if (ul_subframe < 10) { // This means that there is a potential UL subframe that will be schedulyed here for (int i=0; iUE_ul_active[i] = harq_pid = subframe2harq_pid(fp, hDL(bufferZone)->ul_frame, - hDL(bufferZone)->ul_subframe); + hDL(bufferZone)->UE_ul_active[i] = harq_pid = subframe2harq_pid(fp, ul_frame, ul_subframe); if (eNB->ulsch[i]) { //LTE_UL_eNB_HARQ_t *ulsch_harq = eNB->ulsch[i]->harq_processes[harq_pid]; @@ -653,8 +693,6 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx hDL(bufferZone)->amp=AMP; } - if (num_mdci) abort(); - if (do_meas==1) stop_meas(&eNB->dlsch_common_and_dci); if (do_meas==1) start_meas(&eNB->dlsch_ue_specific); @@ -740,6 +778,9 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx if (do_meas==1) stop_meas(&eNB->phy_proc_tx); + // MBMS is not working in OAI + if (hDL(bufferZone)->num_mdci) abort(); + return; } @@ -748,23 +789,24 @@ void DL_du_fs6(RU_t *ru) { for (int i=0; inum_eNB; i++) { initBufferZone(bufferZone); - int nb_blocks=receiveSubFrame(&sockFS6, ru_proc->timestamp_tx, bufferZone, sizeof(bufferZone), CTsentCUv0 ); + int nb_blocks=receiveSubFrame(&sockFS6, bufferZone, sizeof(bufferZone), CTsentCUv0 ); if (nb_blocks > 0) { - L1_rxtx_proc_t *L1_proc = &ru->eNB_list[i]->proc.L1_proc_tx; - L1_proc->timestamp_tx=hUDP(bufferZone)->timestamp; - L1_proc->frame_tx=hDL(bufferZone)->frame; - L1_proc->subframe_tx=hDL(bufferZone)->subframe; + L1_proc_t *L1_proc = &ru->eNB_list[i]->proc; + + if ( L1_proc->timestamp_tx != hUDP(bufferZone)->timestamp) { + LOG_E(HW,"Missed a subframe: expecting: %lu, received %lu\n", + L1_proc->timestamp_tx, + hUDP(bufferZone)->timestamp); + } + + setAllfromTS(hUDP(bufferZone)->timestamp - + sf_ahead*ru->eNB_list[i]->frame_parms.samples_per_tti); phy_procedures_eNB_TX_process( bufferZone, nb_blocks, ru->eNB_list[i], &ru->eNB_list[i]->proc.L1_proc, 1); } else LOG_E(PHY,"DL not received for subframe\n"); } - /* OAI data model is wrong: hardcode link ru to enb index 0*/ - L1_rxtx_proc_t *L1_proc = &ru->eNB_list[0]->proc.L1_proc_tx; - ru_proc->timestamp_tx = L1_proc->timestamp_tx; - ru_proc->subframe_tx = L1_proc->subframe_tx; - ru_proc->frame_tx = L1_proc->frame_tx; feptx_prec(ru); feptx_ofdm(ru); tx_rf(ru); @@ -776,13 +818,10 @@ void UL_du_fs6(RU_t *ru, int frame, int subframe) { rx_rf(ru,&tmpf,&tmpsf); AssertFatal(tmpf==frame && tmpsf==subframe, "lost synchronization\n"); ru_proc->frame_tx = (ru_proc->frame_tx+ru_proc->frame_offset)&1023; + setAllfromTS(ru_proc->timestamp_rx); // Fixme: datamodel issue PHY_VARS_eNB *eNB = RC.eNB[0][0]; L1_proc_t *proc = &eNB->proc; - //L1_rxtx_proc_t *L1_proc = &proc->L1_proc; - //LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; - proc->frame_rx = frame; - proc->subframe_rx = subframe; if (NFAPI_MODE==NFAPI_MODE_PNF) { // I am a PNF and I need to let nFAPI know that we have a (sub)frame tick @@ -792,8 +831,6 @@ void UL_du_fs6(RU_t *ru, int frame, int subframe) { } initBufferZone(bufferZone); - hDL(bufferZone)->frame=frame; - hDL(bufferZone)->subframe=subframe; hUDP(bufferZone)->timestamp=ru->proc.timestamp_rx; prach_eNB_extract(bufferZone, FS6_BUF_SIZE, eNB, proc->frame_rx,proc->subframe_rx ); @@ -812,7 +849,7 @@ void UL_du_fs6(RU_t *ru, int frame, int subframe) { } } -void DL_cu_fs6(RU_t *ru,int frame, int subframe) { +void DL_cu_fs6(RU_t *ru, uint64_t TS) { // Fixme: datamodel issue PHY_VARS_eNB *eNB = RC.eNB[0][0]; L1_proc_t *proc = &eNB->proc; @@ -826,8 +863,6 @@ void DL_cu_fs6(RU_t *ru,int frame, int subframe) { initBufferZone(bufferZone); phy_procedures_eNB_TX_extract(bufferZone, eNB, &proc->L1_proc, 1, bufferZone, FS6_BUF_SIZE); hUDP(bufferZone)->timestamp=proc->L1_proc.timestamp_tx; - hDL(bufferZone)->frame=frame; - hDL(bufferZone)->subframe=subframe; if (hUDP(bufferZone)->nbBlocks==0) { hUDP(bufferZone)->nbBlocks=1; // We have to send the signaling, even is there is no user plan data (no UE) @@ -838,9 +873,9 @@ void DL_cu_fs6(RU_t *ru,int frame, int subframe) { sendSubFrame(&sockFS6, bufferZone, sizeof(fs6_dl_t), CTsentCUv0 ); } -void UL_cu_fs6(RU_t *ru,int frame, int subframe, uint64_t TS) { +void UL_cu_fs6(RU_t *ru, uint64_t *TS) { initBufferZone(bufferZone); - int nb_blocks=receiveSubFrame(&sockFS6, TS, bufferZone, sizeof(bufferZone), CTsentDUv0 ); + int nb_blocks=receiveSubFrame(&sockFS6, bufferZone, sizeof(bufferZone), CTsentDUv0 ); if (nb_blocks ==0) { LOG_W(PHY, "CU lost a subframe\n"); @@ -850,34 +885,34 @@ void UL_cu_fs6(RU_t *ru,int frame, int subframe, uint64_t TS) { if (nb_blocks != hUDP(bufferZone)->nbBlocks ) LOG_W(PHY, "received %d blocks for %d expected\n", nb_blocks, hUDP(bufferZone)->nbBlocks); - // Fixme: datamodel issue + if ( *TS != hUDP(bufferZone)->timestamp ) { + LOG_W(HW, "CU received time: %lu instead of %lu expected\n", hUDP(bufferZone)->timestamp, *TS); + *TS=hUDP(bufferZone)->timestamp; + } + + setAllfromTS(hUDP(bufferZone)->timestamp); PHY_VARS_eNB *eNB = RC.eNB[0][0]; - L1_proc_t *proc = &eNB->proc; - proc->timestamp_rx=hUDP(bufferZone)->timestamp; - prach_eNB_process(bufferZone, sizeof(bufferZone), eNB,NULL,proc->frame_rx,proc->subframe_rx); release_UE_in_freeList(eNB->Mod_id); if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { - phy_procedures_eNB_uespec_RX_process(bufferZone, sizeof(bufferZone), eNB, &proc->L1_proc); + phy_procedures_eNB_uespec_RX_process(bufferZone, sizeof(bufferZone), eNB, &eNB->proc.L1_proc); } } void *cu_fs6(void *arg) { RU_t *ru = (RU_t *)arg; //RU_proc_t *proc = &ru->proc; - int64_t AbsoluteSubframe=-1; fill_rf_config(ru,ru->rf_config_file); init_frame_parms(&ru->frame_parms,1); phy_init_RU(ru); wait_sync("ru_thread"); - AssertFatal(createUDPsock(NULL, "8888", "127.0.0.1", "7777", &sockFS6), ""); + AssertFatal(createUDPsock(NULL, CU_PORT, CU_IP, DU_PORT, &sockFS6), ""); + uint64_t timeStamp=0; while(1) { - AbsoluteSubframe++; - int subframe=AbsoluteSubframe%10; - int frame=(AbsoluteSubframe/10)%1024; - UL_cu_fs6(ru, frame,subframe, AbsoluteSubframe); - DL_cu_fs6(ru, frame,subframe); + timeStamp+=ru->frame_parms.samples_per_tti; + UL_cu_fs6(ru, &timeStamp); + DL_cu_fs6(ru, timeStamp); } return NULL; @@ -891,10 +926,16 @@ void *du_fs6(void *arg) { phy_init_RU(ru); openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); wait_sync("ru_thread"); - AssertFatal(createUDPsock(NULL, "7777", "127.0.0.1", "8888", &sockFS6),""); + AssertFatal(createUDPsock(NULL, DU_PORT, DU_IP, CU_PORT, &sockFS6),""); + + if (ru->start_rf) { + if (ru->start_rf(ru) != 0) + LOG_E(HW,"Could not start the RF device\n"); + else LOG_I(PHY,"RU %d rf device ready\n",ru->idx); + } else LOG_I(PHY,"RU %d no rf device\n",ru->idx); while(1) { - L1_rxtx_proc_t *proc = &ru->eNB_list[0]->proc; + L1_proc_t *proc = &ru->eNB_list[0]->proc; UL_du_fs6(ru, proc->frame_rx,proc->subframe_rx); DL_du_fs6(ru); } diff --git a/executables/main-ocp.c b/executables/main-ocp.c index 92546eb018..3f6d057d82 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -632,10 +632,12 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) { } if (proc->first_rx == 1) { - ru->ts_offset = proc->timestamp_rx; - proc->timestamp_rx = 0; + //ru->ts_offset = proc->timestamp_rx; + //proc->timestamp_rx = 0; + proc->first_rx = false; } else { if (proc->timestamp_rx - old_ts != fp->samples_per_tti) { + LOG_E(HW,"impossible shift in RFSIM\n"); ru->ts_offset += (proc->timestamp_rx - old_ts - fp->samples_per_tti); proc->timestamp_rx = ts-ru->ts_offset; } diff --git a/executables/split_headers.h b/executables/split_headers.h index 9674541628..59909e524e 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -4,11 +4,18 @@ #include #include #include + +#define CU_IP "127.0.0.1" +#define CU_PORT "7878" +#define DU_IP "127.0.0.1" +#define DU_PORT "8787" + #define MTU 65536 #define UDP_TIMEOUT 100000L // in nano second #define MAX_BLOCKS 16 #define blockAlign 32 //bytes + typedef struct { char *sourceIP; char *sourcePort; @@ -38,8 +45,6 @@ typedef struct frequency_s { } frequency_t; typedef struct { - int frame; - int subframe; uint16_t max_preamble[4]; uint16_t max_preamble_energy[4]; uint16_t max_preamble_delay[4]; @@ -47,10 +52,6 @@ typedef struct { } fs6_ul_t; typedef struct { - int frame; - int subframe; - int ul_frame; - int ul_subframe; int num_pdcch_symbols; int num_dci; DCI_ALLOC_t dci_alloc[32]; @@ -70,15 +71,17 @@ typedef struct { } fs6_dl_uespec_t; bool createUDPsock (char *sourceIP, char *sourcePort, char *destIP, char *destPort, UDPsock_t *result); -int receiveSubFrame(UDPsock_t *sock, uint64_t expectedTS, void *bufferZone, int bufferSize, uint16_t contentType); +int receiveSubFrame(UDPsock_t *sock, void *bufferZone, int bufferSize, uint16_t contentType); int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize, uint16_t contentType); #define initBufferZone(xBuf) \ - uint8_t xBuf[FS6_BUF_SIZE];\ + uint8_t xBuf[FS6_BUF_SIZE]; \ ((commonUDP_t *)xBuf)->nbBlocks=0; #define hUDP(xBuf) ((commonUDP_t *)xBuf) -#define hDL(xBuf) (((fs6_dl_t*)((commonUDP_t *)xBuf)+1)) +#define hDL(xBuf) ((fs6_dl_t*)(((commonUDP_t *)xBuf)+1)) +#define hUL(xBuf) ((fs6_ul_t*)(((commonUDP_t *)xBuf)+1)) +#define hDLUE(xBuf) ((fs6_dl_uespec_t*) (((fs6_dl_t*)(((commonUDP_t *)xBuf)+1))+1)) static inline size_t alignedSize(uint8_t *ptr) { commonUDP_t *header=(commonUDP_t *) ptr; @@ -115,4 +118,5 @@ void phy_init_RU(RU_t *); void feptx_prec(RU_t *); void feptx_ofdm(RU_t *); void oai_subframe_ind(uint16_t sfn, uint16_t sf); +extern uint16_t sf_ahead; #endif diff --git a/executables/transport_split.c b/executables/transport_split.c index 490f1259a3..38cd9c3438 100644 --- a/executables/transport_split.c +++ b/executables/transport_split.c @@ -68,11 +68,20 @@ bool createUDPsock (char *sourceIP, char *sourcePort, char *destIP, char *destPo } // sock: udp socket -// expectedTS: the expected timestamp, 0 if unknown // bufferZone: a reception area of bufferSize -int receiveSubFrame(UDPsock_t *sock, uint64_t expectedTS, void *bufferZone, int bufferSize, uint16_t contentType) { +int receiveSubFrame(UDPsock_t *sock, void *bufferZone, int bufferSize, uint16_t contentType) { int rcved=0; commonUDP_t *bufOrigin=(commonUDP_t *)bufferZone; + static uint8_t crossData[65536]; + static int crossDataSize=0; + + if (crossDataSize) { + LOG_D(HW,"copy a block received in previous subframe\n"); + memcpy(bufferZone, crossData, crossDataSize); + rcved=1; + bufferZone+=crossDataSize; + crossDataSize=0; + } do { //read all subframe data from the control unit @@ -80,7 +89,8 @@ int receiveSubFrame(UDPsock_t *sock, uint64_t expectedTS, void *bufferZone, int if ( ret==-1) { if ( errno == EWOULDBLOCK || errno== EINTR ) { - return rcved; // Timeout, subframe incomplete + LOG_I(HW,"Received: Timeout, subframe incomplete\n"); + return rcved; } else { LOG_E(HW,"Critical issue in socket: %s\n", strerror(errno)); return -1; @@ -89,28 +99,26 @@ int receiveSubFrame(UDPsock_t *sock, uint64_t expectedTS, void *bufferZone, int if (hUDP(bufferZone)->contentType != contentType) abort(); - if ( hUDP(bufferZone)->timestamp != expectedTS) { - if ( hUDP(bufferZone)->timestamp < expectedTS) { - LOG_W(HW,"Received a paquet from past subframes, dropping it\n"); + if (rcved && bufOrigin->timestamp != hUDP(bufferZone)->timestamp ) { + if ( hUDP(bufferZone)->timestamp > bufOrigin->timestamp ) { + LOG_W(HW,"Received data for TS: %lu before end of TS : %lu completion\n", + hUDP(bufferZone)->timestamp, + bufOrigin->timestamp); + memcpy(crossData, bufferZone, ret ); + crossDataSize=ret; + return rcved; } else { - LOG_W(HW,"Received a paquet in future subframes\n"); - - if ( rcved == 0 ) { - LOG_W(HW,"First paquet in the sub-frame, keeping it\n"); - rcved++; - bufferZone+=ret; - expectedTS=hUDP(bufferZone)->timestamp; - } + LOG_W(HW,"Dropping late packet\n"); + continue; } - } else { - rcved++; - bufferZone+=ret; } - } - } while ( !rcved || rcved < hUDP(bufferZone)->nbBlocks ); - LOG_D(HW,"Received: nb_blocks: %d, TS: %lu, frame: %d, subframe: %d\n", - rcved, bufOrigin->timestamp, *(((int *)bufOrigin)+1), *(((int *)bufOrigin)+2)); + rcved++; + bufferZone+=ret; + } + } while ( rcved == 0 || rcved < bufOrigin->nbBlocks ); + + LOG_D(HW,"Received: nb_blocks: %d, TS: %lu\n",rcved, bufOrigin->timestamp); return rcved; } diff --git a/openair1/PHY/LTE_TRANSPORT/pbch.c b/openair1/PHY/LTE_TRANSPORT/pbch.c index 37997c94b4..d852248b63 100644 --- a/openair1/PHY/LTE_TRANSPORT/pbch.c +++ b/openair1/PHY/LTE_TRANSPORT/pbch.c @@ -195,7 +195,7 @@ int generate_pbch(LTE_eNB_PBCH *eNB_pbch, pbch_E = (frame_parms->Ncp==NORMAL) ? 1920 : 1728; //RE/RB * #RB * bits/RB (QPSK) // pbch_E_bytes = pbch_coded_bits>>3; - LOG_D(PHY,"%s(eNB_pbch:%p txdataF:%p amp:%d frame_parms:%p pbch_pdu:%p frame_mod4:%d)\n", __FUNCTION__, eNB_pbch, txdataF, amp, frame_parms, pbch_pdu, frame_mod4==0); + LOG_D(PHY,"%s(eNB_pbch:%p txdataF:%p amp:%d frame_parms:%p pbch_pdu:%p frame_mod4:%d)\n", __FUNCTION__, eNB_pbch, txdataF, amp, frame_parms, pbch_pdu, frame_mod4); if (frame_mod4==0) { bzero(pbch_a,PBCH_A>>3); diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 17d3001205..533254ebc6 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -162,7 +162,7 @@ void common_signal_procedures (PHY_VARS_eNB *eNB,int frame, int subframe) { LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; int **txdataF = eNB->common_vars.txdataF; uint8_t *pbch_pdu=&eNB->pbch_pdu[0]; - //LOG_D(PHY,"common_signal_procedures: frame %d, subframe %d fdd:%s dir:%s\n",frame,subframe,fp->frame_type == FDD?"FDD":"TDD", subframe_select(fp,subframe) == SF_DL?"DL":"UL?"); + LOG_D(PHY,"common_signal_procedures: frame %d, subframe %d fdd:%s dir:%s\n",frame,subframe,fp->frame_type == FDD?"FDD":"TDD", subframe_select(fp,subframe) == SF_DL?"DL":"UL?"); // generate Cell-Specific Reference Signals for both slots VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,1); From 9fb9ac53876758482c69936fd84dfbaea61de5a7 Mon Sep 17 00:00:00 2001 From: laurent Date: Mon, 12 Aug 2019 21:32:46 +0200 Subject: [PATCH 025/240] UE primary sync ok, DU upper layers disabled, UE DCI decoding nok (partial) --- executables/main-fs6.c | 5 +++++ executables/main-ocp.c | 11 ++++++----- executables/split_headers.h | 1 + executables/transport_split.c | 3 +-- targets/COMMON/create_tasks.c | 5 ++++- targets/RT/USER/lte-softmodem.c | 6 ++++-- 6 files changed, 21 insertions(+), 10 deletions(-) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index ace3f7fd1d..cc94ea42fa 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -485,6 +485,8 @@ void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int nbBlocks, PHY_VARS_e eNB->pdcch_vars[subframe&1].num_pdcch_symbols=hDL(bufferZone)->num_pdcch_symbols; eNB->pdcch_vars[subframe&1].num_dci=hDL(bufferZone)->num_dci; uint8_t num_mdci = eNB->mpdcch_vars[subframe&1].num_dci = hDL(bufferZone)->num_mdci; + eNB->pbch_configured=true; + memcpy(eNB->pbch_pdu,hDL(bufferZone)->pbch_pdu, 4); // Remove all scheduled DL, we will populate from the CU sending for (int UE_id=0; UE_idpdcch_vars[subframe&1].num_pdcch_symbols; uint8_t num_dci = eNB->pdcch_vars[subframe&1].num_dci; uint8_t num_mdci = eNB->mpdcch_vars[subframe&1].num_dci; + memcpy(hDL(bufferZone)->pbch_pdu,eNB->pbch_pdu,4); + LOG_D(PHY,"num_pdcch_symbols %"PRIu8",number dci %"PRIu8"\n",num_pdcch_symbols, num_dci); if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { @@ -691,6 +695,7 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx hDL(bufferZone)->num_dci=num_dci; hDL(bufferZone)->num_mdci=num_mdci; hDL(bufferZone)->amp=AMP; + LOG_D(PHY, "pbch configured: %d\n", eNB->pbch_configured); } if (do_meas==1) stop_meas(&eNB->dlsch_common_and_dci); diff --git a/executables/main-ocp.c b/executables/main-ocp.c index 3f6d057d82..432ec6025a 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -109,9 +109,10 @@ void init_RU_proc(RU_t *ru) { if (fs6) { if ( strncasecmp(fs6,"cu", 2) == 0 ) - threadCreate(&t, cu_fs6, (void *)ru, "MainCu", -1, OAI_PRIORITY_RT_MAX); - else if ( strncasecmp(fs6,"du", 2) == 0 ) - threadCreate(&t, du_fs6, (void *)ru, "MainDu", -1, OAI_PRIORITY_RT_MAX); + threadCreate(&t, cu_fs6, (void *)ru, "MainCu", -1, OAI_PRIORITY_RT_MAX); + else if ( strncasecmp(fs6,"du", 2) == 0 ) { + threadCreate(&t, du_fs6, (void *)ru, "MainDu", -1, OAI_PRIORITY_RT_MAX); + } else AssertFatal(false, "environement variable fs6 is not cu or du"); } else @@ -638,8 +639,8 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) { } else { if (proc->timestamp_rx - old_ts != fp->samples_per_tti) { LOG_E(HW,"impossible shift in RFSIM\n"); - ru->ts_offset += (proc->timestamp_rx - old_ts - fp->samples_per_tti); - proc->timestamp_rx = ts-ru->ts_offset; + //ru->ts_offset += (proc->timestamp_rx - old_ts - fp->samples_per_tti); + //proc->timestamp_rx = ts-ru->ts_offset; } } diff --git a/executables/split_headers.h b/executables/split_headers.h index 59909e524e..42202d546b 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -52,6 +52,7 @@ typedef struct { } fs6_ul_t; typedef struct { + uint8_t pbch_pdu[4]; int num_pdcch_symbols; int num_dci; DCI_ALLOC_t dci_alloc[32]; diff --git a/executables/transport_split.c b/executables/transport_split.c index 38cd9c3438..c9d848ef19 100644 --- a/executables/transport_split.c +++ b/executables/transport_split.c @@ -155,7 +155,6 @@ int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize, ui nbBlocks--; } while (nbBlocks); - LOG_D(HW,"Sent: TS: %lu, frame: %d, subframe: %d\n", - UDPheader->timestamp, *(((int *)UDPheader)+1), *(((int *)UDPheader)+2)); + LOG_D(HW,"Sent: TS: %lu\n", UDPheader->timestamp); return 0; } diff --git a/targets/COMMON/create_tasks.c b/targets/COMMON/create_tasks.c index cfc2bc2215..58be63a848 100644 --- a/targets/COMMON/create_tasks.c +++ b/targets/COMMON/create_tasks.c @@ -49,6 +49,9 @@ int create_tasks(uint32_t enb_nb) { int rc; if (enb_nb == 0) return 0; + bool fs6Du=false; + if ( getenv("fs6") != NULL && strncasecmp( getenv("fs6"), "du", 2) == 0 ) + fs6Du=true; LOG_I(ENB_APP, "Creating ENB_APP eNB Task\n"); rc = itti_create_task (TASK_ENB_APP, eNB_app_task, NULL); @@ -64,7 +67,7 @@ int create_tasks(uint32_t enb_nb) { } - if (EPC_MODE_ENABLED && !NODE_IS_DU(type)) { + if (EPC_MODE_ENABLED && !NODE_IS_DU(type) && !fs6Du ) { rc = itti_create_task(TASK_S1AP, s1ap_eNB_task, NULL); AssertFatal(rc >= 0, "Create task for S1AP failed\n"); if (!(get_softmodem_params()->emulate_rf)){ diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 109c0afdd4..85862f9430 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -593,8 +593,10 @@ int main( int argc, char **argv ) { /* initializes PDCP and sets correct RLC Request/PDCP Indication callbacks * for monolithic/F1 modes */ - if ( getenv("fs6") == NULL || strncasecmp( getenv("fs6"), "du", 2) != 0 ) - init_pdcp(); + //if ( getenv("fs6") != NULL && strncasecmp( getenv("fs6"), "du", 2) == 0 ) + //RC.rrc[0]->node_type=ngran_eNB_DU; + + init_pdcp(); if (create_tasks(1) < 0) { printf("cannot create ITTI tasks\n"); From b907922014800ba44ef96efd40bdec13d1575df6 Mon Sep 17 00:00:00 2001 From: laurent Date: Tue, 13 Aug 2019 21:03:45 +0200 Subject: [PATCH 026/240] SIB ok for UE, UE send RACH --- executables/main-fs6.c | 86 +++++++++++++++++++++++++++++-------- executables/split_headers.h | 9 ++++ 2 files changed, 76 insertions(+), 19 deletions(-) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index cc94ea42fa..6aed32d132 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -506,14 +506,30 @@ void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int nbBlocks, PHY_VARS_e for (int i=0; i < nbBlocks; i++) { //nbBlocks is the actual received blocks if ( ((commonUDP_t *)bufPtr)->contentBytes >= sizeof(fs6_dl_t)+sizeof(fs6_dl_uespec_t) ) { int curUE=hDLUE(bufPtr)->UE_id; + LTE_eNB_DLSCH_t *dlsch0 = eNB->dlsch[curUE][0]; + LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch0->harq_processes[hDLUE(bufPtr)->harq_pid]; #ifdef PHY_TX_THREAD - eNB->dlsch[curUE][0]->active[subframe] = 1; + dlsch0->active[subframe] = 1; #else - eNB->dlsch[curUE][0]->active = 1; + dlsch0->active = 1; #endif - eNB->dlsch[curUE][0]->harq_ids[frame%2][subframe]=hDLUE(bufPtr)->harq_pid; - eNB->dlsch[curUE][0]->rnti=hDLUE(bufPtr)->rnti; - memcpy(eNB->dlsch[curUE][0]->harq_processes[hDLUE(bufPtr)->harq_pid]->e, + dlsch0->harq_ids[frame%2][subframe]=hDLUE(bufPtr)->harq_pid; + dlsch0->rnti=hDLUE(bufPtr)->rnti; + dlsch0->sqrt_rho_a=hDLUE(bufPtr)->sqrt_rho_a; + dlsch0->sqrt_rho_b=hDLUE(bufPtr)->sqrt_rho_b; + dlsch_harq->nb_rb=hDLUE(bufPtr)->nb_rb; + memcpy(dlsch_harq->rb_alloc, hDLUE(bufPtr)->rb_alloc, sizeof(hDLUE(bufPtr)->rb_alloc)); + dlsch_harq->Qm=hDLUE(bufPtr)->Qm; + dlsch_harq->Nl=hDLUE(bufPtr)->Nl; + dlsch_harq->pdsch_start=hDLUE(bufPtr)->pdsch_start; +#ifdef PHY_TX_THREAD + dlsch_harq->i0=hDLUE(bufPtr)->i0; + dlsch_harq->sib1_br_flag=hDLUE(bufPtr)->sib1_br_flag; +#else + dlsch0->i0=hDLUE(bufPtr)->i0; + dlsch0->sib1_br_flag=hDLUE(bufPtr)->sib1_br_flag; +#endif + memcpy(dlsch_harq->e, hDLUE(bufPtr)+1, hDLUE(bufPtr)->dataLen); } @@ -550,6 +566,7 @@ void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int nbBlocks, PHY_VARS_e for (int i=0; i< hDL(bufferZone)->num_dci; i++) eNB->pdcch_vars[subframe&1].dci_alloc[i]=hDL(bufferZone)->dci_alloc[i]; + LOG_D (PHY, "Frame %d, subframe %d: Calling generate_dci_top (pdcch) (num_dci %" PRIu8 ")\n", frame, subframe, hDL(bufferZone)->num_dci); generate_dci_top(hDL(bufferZone)->num_pdcch_symbols, hDL(bufferZone)->num_dci, &eNB->pdcch_vars[subframe&1].dci_alloc[0], @@ -576,6 +593,14 @@ void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int nbBlocks, PHY_VARS_e (dlsch0->active == 1) #endif ) { + uint64_t sum=0; + + for ( int i= subframe * fp->ofdm_symbol_size * (fp->symbols_per_tti); + i< (subframe+1) * fp->ofdm_symbol_size * (fp->symbols_per_tti); + i++) + sum+=((int32_t *)(eNB->common_vars.txdataF[0]))[i]; + + LOG_D(PHY,"frame: %d, subframe: %d, sum of dlsch mod v1: %lx\n", frame, subframe, sum); int harq_pid=dlsch0->harq_ids[frame%2][subframe]; pdsch_procedures(eNB, proc, @@ -591,7 +616,7 @@ void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int nbBlocks, PHY_VARS_e AMP); } -void appendFs6DLUE(uint8_t *bufferZone, int UE_id, int8_t harq_pid, uint16_t rnti, uint8_t *UEdata, int UEdataLen) { +void appendFs6DLUE(uint8_t *bufferZone, LTE_DL_FRAME_PARMS *fp, int UE_id, int8_t harq_pid, LTE_eNB_DLSCH_t *dlsch0, LTE_DL_eNB_HARQ_t *harqData, int frame, int subframe) { commonUDP_t *FirstUDPheader=(commonUDP_t *) bufferZone; // move to the end uint8_t *firstFreeByte=bufferZone; @@ -603,6 +628,14 @@ void appendFs6DLUE(uint8_t *bufferZone, int UE_id, int8_t harq_pid, uint16_t rnt curBlock++; } + int UEdataLen= get_G(fp, + harqData->nb_rb, + harqData->rb_alloc, + harqData->Qm, + harqData->Nl, + harqData->pdsch_start, + frame,subframe, + 0); AssertFatal(firstFreeByte+UEdataLen+sizeof(fs6_dl_t) <= bufferZone+FS6_BUF_SIZE, ""); commonUDP_t *newUDPheader=(commonUDP_t *) firstFreeByte; FirstUDPheader->nbBlocks++; @@ -612,9 +645,26 @@ void appendFs6DLUE(uint8_t *bufferZone, int UE_id, int8_t harq_pid, uint16_t rnt // This header will be duplicated during sending hDLUE(newUDPheader)->UE_id=UE_id; hDLUE(newUDPheader)->harq_pid=harq_pid; - hDLUE(newUDPheader)->rnti=rnti; + hDLUE(newUDPheader)->rnti=dlsch0->rnti; + hDLUE(newUDPheader)->sqrt_rho_a=dlsch0->sqrt_rho_a; + hDLUE(newUDPheader)->sqrt_rho_b=dlsch0->sqrt_rho_b; + hDLUE(newUDPheader)->nb_rb=harqData->nb_rb; + memcpy(hDLUE(newUDPheader)->rb_alloc, harqData->rb_alloc, sizeof(harqData->rb_alloc)); + hDLUE(newUDPheader)->Qm=harqData->Qm; + hDLUE(newUDPheader)->Nl=harqData->Nl; + hDLUE(newUDPheader)->pdsch_start=harqData->pdsch_start; +#ifdef PHY_TX_THREAD + hDLUE(newUDPheader)->i0=harqData->i0; + hDLUE(newUDPheader)->sib1_br_flag=harqData->sib1_br_flag; +#else + hDLUE(newUDPheader)->i0=dlsch0->i0; + hDLUE(newUDPheader)->sib1_br_flag=dlsch0->sib1_br_flag; +#endif hDLUE(newUDPheader)->dataLen=UEdataLen; - memcpy(hDLUE(newUDPheader)+1, UEdata, UEdataLen); + memcpy(hDLUE(newUDPheader)+1, harqData->e, UEdataLen); + + for (int i=0; i < UEdataLen; i++) + LOG_D(PHY,"buffer e:%hhx\n", ( (uint8_t *)(hDLUE(newUDPheader)+1) )[i]); } void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas, uint8_t *buf, int bufSize) { @@ -687,7 +737,6 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx uint8_t num_dci = eNB->pdcch_vars[subframe&1].num_dci; uint8_t num_mdci = eNB->mpdcch_vars[subframe&1].num_dci; memcpy(hDL(bufferZone)->pbch_pdu,eNB->pbch_pdu,4); - LOG_D(PHY,"num_pdcch_symbols %"PRIu8",number dci %"PRIu8"\n",num_pdcch_symbols, num_dci); if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { @@ -695,6 +744,10 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx hDL(bufferZone)->num_dci=num_dci; hDL(bufferZone)->num_mdci=num_mdci; hDL(bufferZone)->amp=AMP; + + for (int i=0; i< hDL(bufferZone)->num_dci; i++) + hDL(bufferZone)->dci_alloc[i]=eNB->pdcch_vars[subframe&1].dci_alloc[i]; + LOG_D(PHY, "pbch configured: %d\n", eNB->pbch_configured); } @@ -750,18 +803,13 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx */ LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch0->harq_processes[harq_pid]; appendFs6DLUE(bufferZone, + fp, UE_id, harq_pid, - dlsch0->rnti, - dlsch0->harq_processes[harq_pid]->e, - get_G(fp, - dlsch_harq->nb_rb, - dlsch_harq->rb_alloc, - dlsch_harq->Qm, - dlsch_harq->Nl, - dlsch_harq->pdsch_start, - frame,subframe, - 0) + dlsch0, + dlsch_harq, + frame, + subframe ); } } diff --git a/executables/split_headers.h b/executables/split_headers.h index 42202d546b..2e0df34c54 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -68,6 +68,15 @@ typedef struct { int UE_id; int8_t harq_pid; uint16_t rnti; + int16_t sqrt_rho_a; + int16_t sqrt_rho_b; + uint16_t nb_rb; + uint8_t Qm; + int8_t Nl; + uint8_t pdsch_start; + uint8_t sib1_br_flag; + uint16_t i0; + uint32_t rb_alloc[4]; int dataLen; } fs6_dl_uespec_t; From d28419cfca26ca6bd6a493b6359c572a02380702 Mon Sep 17 00:00:00 2001 From: laurent Date: Sat, 24 Aug 2019 16:28:55 +0200 Subject: [PATCH 027/240] usage of setAllfromTS in also monolitic version, RACH detected to the cu, several bugs fixed, still no attach complete --- executables/main-fs6.c | 508 ++++++++++++++------ executables/main-ocp.c | 151 +++--- executables/split_headers.h | 51 +- openair1/PHY/LTE_TRANSPORT/prach.c | 2 +- openair1/PHY/LTE_TRANSPORT/prach_common.c | 1 + openair1/PHY/LTE_TRANSPORT/transport_eNB.h | 6 +- openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c | 79 +-- openair1/PHY/defs_eNB.h | 1 + openair1/SCHED/phy_procedures_lte_eNb.c | 2 +- 9 files changed, 522 insertions(+), 279 deletions(-) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index 6aed32d132..1ebce9ef7d 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -16,62 +16,18 @@ #include #include #include +#include #define FS6_BUF_SIZE 100*1000 static UDPsock_t sockFS6; -// Fixme: there are many mistakes in the datamodel and in redondant variables -// TDD is also mode complex -void setAllfromTS(uint64_t TS) { - for (int i=0; i frame_parms; - uint64_t TStx=TS+sf_ahead*fp->samples_per_tti; - RU_proc_t *proc =&RC.ru[i]->proc; - proc->timestamp_rx= TS; - proc->timestamp_tx= TStx; - proc->subframe_rx= (TS / fp->samples_per_tti)%10; - proc->subframe_tx= (TStx / fp->samples_per_tti)%10; - proc->subframe_prach=(TS / fp->samples_per_tti)%10; - proc->subframe_prach_br=(TS / fp->samples_per_tti)%10; - proc->frame_rx= (TS / (fp->samples_per_tti*10))&1023; - proc->frame_tx= (TStx / (fp->samples_per_tti*10))&1023; - } - for (int i=0; i < RC.nb_inst; i++) { - for (int j=0; jframe_parms; - uint64_t TStx=TS+sf_ahead*fp->samples_per_tti; - L1_proc_t *proc =&RC.eNB[i][j]->proc; - L1_rxtx_proc_t *proc1=&RC.eNB[i][j]->proc.L1_proc; - proc->timestamp_rx= TS; - proc->timestamp_tx= TStx; - proc->subframe_rx= (TS / fp->samples_per_tti)%10; - proc->subframe_prach=(TS / fp->samples_per_tti)%10; - proc->subframe_prach_br=(TS / fp->samples_per_tti)%10; - proc->frame_rx= (TS / (fp->samples_per_tti*10))&1023; - proc->frame_tx= (TStx / (fp->samples_per_tti*10))&1023; - proc1->timestamp_tx= TStx; - proc1->subframe_rx= (TS / fp->samples_per_tti)%10; - proc1->subframe_tx= (TStx / fp->samples_per_tti)%10; - proc1->frame_rx= (TS / (fp->samples_per_tti*10))&1023; - proc1->frame_tx= (TStx / (fp->samples_per_tti*10))&1023; - } - } - - return; -} - - -void prach_eNB_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, int frame,int subframe) { +void prach_eNB_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB) { fs6_ul_t *header=(fs6_ul_t *) commonUDPdata(bufferZone); - if (is_prach_subframe(&eNB->frame_parms, frame,subframe)<=0) + if (is_prach_subframe(&eNB->frame_parms, eNB->proc.frame_prach,eNB->proc.subframe_prach)<=0) return; - eNB->proc.frame_prach = frame; - eNB->proc.subframe_prach = subframe; - eNB->proc.frame_prach_br = frame; - eNB->proc.subframe_prach_br = subframe; RU_t *ru; int aa=0; int ru_aa; @@ -88,19 +44,19 @@ void prach_eNB_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, int } } - /* Fixme: the orgin code calls the two funtiosn, so one overwrite the second? - rx_prach(eNB, - eNB->RU_list[0], - header->max_preamble, - header->max_preamble_energy, - header->max_preamble_delay, - header->avg_preamble_energy, - frame, - 0, - false - ); - */ + rx_prach(eNB, + eNB->RU_list[0], + header->max_preamble, + header->max_preamble_energy, + header->max_preamble_delay, + header->avg_preamble_energy, + eNB->proc.frame_prach, + 0, + false + ); // run PRACH detection for CE-level 0 only for now when br_flag is set + /* fixme: seems not operational and may overwrite regular LTE prach detection + * OAI code can call is sequence rx_prach(eNB, eNB->RU_list[0], header->max_preamble, @@ -111,17 +67,26 @@ void prach_eNB_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, int 0, true ); + */ + LOG_D(PHY,"RACH detection index 0: max preamble: %u, energy: %u, delay: %u, avg energy: %u\n", + header->max_preamble[0], + header->max_preamble_energy[0], + header->max_preamble_delay[0], + header->avg_preamble_energy[0] + ); return; } -void prach_eNB_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { +void prach_eNB_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB) { fs6_ul_t *header=(fs6_ul_t *) commonUDPdata(bufferZone); uint16_t *max_preamble=header->max_preamble; uint16_t *max_preamble_energy=header->max_preamble_energy; uint16_t *max_preamble_delay=header->max_preamble_delay; uint16_t *avg_preamble_energy=header->avg_preamble_energy; + int subframe=eNB->proc.subframe_prach; + int frame=eNB->proc.frame_prach; // Fixme: not clear why we call twice with "br" and without - int br_flag=1; + int br_flag=0; if (br_flag==1) { int prach_mask; @@ -206,6 +171,29 @@ void prach_eNB_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB,RU_t } } +void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen) { + uint8_t *bufferZone=eNB->FS6bufferZone; + commonUDP_t *FirstUDPheader=(commonUDP_t *) bufferZone; + // move to the end + uint8_t *firstFreeByte=bufferZone; + int curBlock=0; + + for (int i=0; i < FirstUDPheader->nbBlocks; i++) { + AssertFatal( ((commonUDP_t *) firstFreeByte)->blockID==curBlock,""); + firstFreeByte+=alignedSize(firstFreeByte); + curBlock++; + } + + commonUDP_t *newUDPheader=(commonUDP_t *) firstFreeByte; + FirstUDPheader->nbBlocks++; + newUDPheader->blockID=curBlock; + newUDPheader->contentBytes=sizeof(fs6_ul_t)+sizeof(fs6_ul_uespec_t) + dataLen; + hULUE(newUDPheader)->UE_id=UE_id; + hULUE(newUDPheader)->harq_id=harq_pid; + hULUE(newUDPheader)->segment=segmentID; + memcpy(hULUE(newUDPheader)+1, data, dataLen); +} + void pusch_procedures_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { uint32_t harq_pid; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; @@ -223,9 +211,14 @@ void pusch_procedures_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eN LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; if (ulsch->rnti>0) - LOG_D(PHY,"eNB->ulsch[%d]->harq_processes[harq_pid:%d] SFN/SF:%04d%d: PUSCH procedures, UE %d/%x ulsch_harq[status:%d SFN/SF:%04d%d handled:%d]\n", + LOG_D(PHY,"eNB->ulsch[%d]->harq_processes[harq_pid:%d] SFN/SF:%04d%d: PUSCH procedures, UE %d/%x ulsch_harq[status:%d SFN/SF:%04d%d active: %d handled:%d]\n", i, harq_pid, frame,subframe,i,ulsch->rnti, - ulsch_harq->status, ulsch_harq->frame, ulsch_harq->subframe, ulsch_harq->handled); + ulsch_harq->status, ulsch_harq->frame, ulsch_harq->subframe, ulsch_harq->status, ulsch_harq->handled); + + if ((ulsch) && + (ulsch->rnti>0) && + (ulsch_harq->status == ACTIVE)) + LOG_E(PHY,"active ulsch harq\n"); if ((ulsch) && (ulsch->rnti>0) && @@ -265,7 +258,8 @@ void pusch_procedures_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eN ulsch_harq->O_ACK, ulsch->beta_offset_cqi_times8); start_meas(&eNB->ulsch_demodulation_stats); - rx_ulsch(eNB,proc, i); + eNB->FS6bufferZone=bufferZone; + rx_ulsch(eNB, proc, i); stop_meas(&eNB->ulsch_demodulation_stats); // TBD: add datablock for transmission } @@ -318,13 +312,98 @@ void phy_procedures_eNB_uespec_RX_extract(uint8_t *bufferZone, int bufSize, PHY_ return; } -void pusch_procedures_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { +int ulsch_decoding_process(PHY_VARS_eNB *eNB, int UE_id, int llr8_flag) { + int harq_pid; + LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id]; + + if (ulsch->ue_type>0) + harq_pid = 0; + else + harq_pid = subframe2harq_pid(&eNB->frame_parms,eNB->proc.frame_rx,eNB->proc.subframe_rx); + + LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; + decoder_if_t *tc; + int offset, ret; + + if (llr8_flag == 0) + tc = *decoder16; + else + tc = *decoder8; + + for (int r=0; rC; r++) { + // printf("before subblock deinterleaving c[%d] = %p\n",r,ulsch_harq->c[r]); + // Get Turbo interleaver parameters + int Kr; + + if (rCminus) + Kr = ulsch_harq->Kminus; + else + Kr = ulsch_harq->Kplus; + + int Kr_bytes = Kr>>3; + int crc_type; + + if (ulsch_harq->C == 1) + crc_type = CRC24_A; + else + crc_type = CRC24_B; + + start_meas(&eNB->ulsch_turbo_decoding_stats); + ret = tc(&ulsch_harq->d[r][96], + NULL, + ulsch_harq->c[r], + NULL, + Kr, + ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS, + crc_type, + (r==0) ? ulsch_harq->F : 0, + &eNB->ulsch_tc_init_stats, + &eNB->ulsch_tc_alpha_stats, + &eNB->ulsch_tc_beta_stats, + &eNB->ulsch_tc_gamma_stats, + &eNB->ulsch_tc_ext_stats, + &eNB->ulsch_tc_intl1_stats, + &eNB->ulsch_tc_intl2_stats); + stop_meas(&eNB->ulsch_turbo_decoding_stats); + + // Reassembly of Transport block here + + if (ret != (1+ulsch->max_turbo_iterations)) { + if (rCminus) + Kr = ulsch_harq->Kminus; + else + Kr = ulsch_harq->Kplus; + + Kr_bytes = Kr>>3; + + if (r==0) { + memcpy(ulsch_harq->bb, + &ulsch_harq->c[0][(ulsch_harq->F>>3)], + Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0)); + offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0); + } else { + memcpy(ulsch_harq->bb+offset, + ulsch_harq->c[r], + Kr_bytes - ((ulsch_harq->C>1)?3:0)); + offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); + } + } else { + break; + } + } + + return(ret); +} + +void pusch_procedures_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB) { //LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - const int subframe = proc->subframe_rx; - const int frame = proc->frame_rx; + const int subframe = eNB->proc.subframe_rx; + const int frame = eNB->proc.frame_rx; uint32_t harq_pid; uint32_t harq_pid0 = subframe2harq_pid(&eNB->frame_parms,frame,subframe); + // TBD: read UL data + for (int i = 0; i < NUMBER_OF_UE_MAX; i++) { LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[i]; @@ -353,11 +432,16 @@ void pusch_procedures_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eN } start_meas(&eNB->ulsch_decoding_stats); - int ret = ulsch_decoding(eNB,proc, + /* + int ret = ulsch_decoding(eNB,&eNB->proc.L1_proc, i, 0, // control_only_flag ulsch_harq->V_UL_DAI, ulsch_harq->nb_rb>20 ? 1 : 0); + */ + int ret = ulsch_decoding_process(eNB, + i, + ulsch_harq->nb_rb>20 ? 1 : 0); stop_meas(&eNB->ulsch_decoding_stats); LOG_D(PHY, "[eNB %d][PUSCH %d] frame %d subframe %d RNTI %x RX power (%d,%d) N0 (%d,%d) dB ACK (%d,%d), decoding iter %d ulsch_harq->cqi_crc_status:%d ackBits:%d ulsch_decoding_stats[t:%lld max:%lld]\n", @@ -474,7 +558,26 @@ void pusch_procedures_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eN } // for (i=0; icontentBytes >= sizeof(fs6_ul_t)+sizeof(fs6_ul_uespec_t) ) { + LTE_eNB_ULSCH_t *ulsch =eNB->ulsch[hULUE(bufPtr)->UE_id]; + LTE_UL_eNB_HARQ_t *ulsch_harq=ulsch->harq_processes[hULUE(bufPtr)->harq_id]; + memcpy(&ulsch_harq->d[hULUE(bufPtr)->segment][96], + hULUE(bufPtr)+1, + hULUE(bufPtr)->segLen); + bufPtr+=alignedSize(bufPtr); + LOG_W(PHY,"Received ulsch data for: rnti:%d, fsf: %d/%d\n", ulsch->rnti, eNB->proc.frame_rx, eNB->proc.subframe_rx); + } + } +} + +void phy_procedures_eNB_uespec_RX_process(uint8_t *bufferZone, int nbBlocks,PHY_VARS_eNB *eNB) { + // The configuration arrived in Dl, so we can extract the UL data + recvFs6Ul(bufferZone, nbBlocks, eNB); + pusch_procedures_process(bufferZone, nbBlocks, eNB); } void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas ) { @@ -504,36 +607,75 @@ void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int nbBlocks, PHY_VARS_e void *bufPtr=bufferZone; for (int i=0; i < nbBlocks; i++) { //nbBlocks is the actual received blocks - if ( ((commonUDP_t *)bufPtr)->contentBytes >= sizeof(fs6_dl_t)+sizeof(fs6_dl_uespec_t) ) { - int curUE=hDLUE(bufPtr)->UE_id; - LTE_eNB_DLSCH_t *dlsch0 = eNB->dlsch[curUE][0]; - LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch0->harq_processes[hDLUE(bufPtr)->harq_pid]; -#ifdef PHY_TX_THREAD - dlsch0->active[subframe] = 1; -#else - dlsch0->active = 1; -#endif - dlsch0->harq_ids[frame%2][subframe]=hDLUE(bufPtr)->harq_pid; - dlsch0->rnti=hDLUE(bufPtr)->rnti; - dlsch0->sqrt_rho_a=hDLUE(bufPtr)->sqrt_rho_a; - dlsch0->sqrt_rho_b=hDLUE(bufPtr)->sqrt_rho_b; - dlsch_harq->nb_rb=hDLUE(bufPtr)->nb_rb; - memcpy(dlsch_harq->rb_alloc, hDLUE(bufPtr)->rb_alloc, sizeof(hDLUE(bufPtr)->rb_alloc)); - dlsch_harq->Qm=hDLUE(bufPtr)->Qm; - dlsch_harq->Nl=hDLUE(bufPtr)->Nl; - dlsch_harq->pdsch_start=hDLUE(bufPtr)->pdsch_start; -#ifdef PHY_TX_THREAD - dlsch_harq->i0=hDLUE(bufPtr)->i0; - dlsch_harq->sib1_br_flag=hDLUE(bufPtr)->sib1_br_flag; -#else - dlsch0->i0=hDLUE(bufPtr)->i0; - dlsch0->sib1_br_flag=hDLUE(bufPtr)->sib1_br_flag; -#endif - memcpy(dlsch_harq->e, - hDLUE(bufPtr)+1, hDLUE(bufPtr)->dataLen); - } + if ( ((commonUDP_t *)bufPtr)->contentBytes > sizeof(fs6_dl_t) ) { + int type=hDLUE(bufPtr)->type; - bufPtr+=alignedSize(bufPtr); + if ( type == fs6DlConfig) { + int curUE=hDLUE(bufPtr)->UE_id; + LTE_eNB_DLSCH_t *dlsch0 = eNB->dlsch[curUE][0]; + LTE_DL_eNB_HARQ_t *dlsch_harq=dlsch0->harq_processes[hDLUE(bufPtr)->harq_pid]; +#ifdef PHY_TX_THREAD + dlsch0->active[subframe] = 1; +#else + dlsch0->active = 1; +#endif + dlsch0->harq_ids[frame%2][subframe]=hDLUE(bufPtr)->harq_pid; + dlsch0->rnti=hDLUE(bufPtr)->rnti; + dlsch0->sqrt_rho_a=hDLUE(bufPtr)->sqrt_rho_a; + dlsch0->sqrt_rho_b=hDLUE(bufPtr)->sqrt_rho_b; + dlsch_harq->nb_rb=hDLUE(bufPtr)->nb_rb; + memcpy(dlsch_harq->rb_alloc, hDLUE(bufPtr)->rb_alloc, sizeof(hDLUE(bufPtr)->rb_alloc)); + dlsch_harq->Qm=hDLUE(bufPtr)->Qm; + dlsch_harq->Nl=hDLUE(bufPtr)->Nl; + dlsch_harq->pdsch_start=hDLUE(bufPtr)->pdsch_start; +#ifdef PHY_TX_THREAD + dlsch_harq->i0=hDLUE(bufPtr)->i0; + dlsch_harq->sib1_br_flag=hDLUE(bufPtr)->sib1_br_flag; +#else + dlsch0->i0=hDLUE(bufPtr)->i0; + dlsch0->sib1_br_flag=hDLUE(bufPtr)->sib1_br_flag; +#endif + memcpy(dlsch_harq->e, + hDLUE(bufPtr)+1, hDLUE(bufPtr)->dataLen); + } else if (type == fs6UlConfig) { + int nbUE=(((commonUDP_t *)bufPtr)->contentBytes - sizeof(fs6_dl_t)) / sizeof( fs6_dl_ulsched_t ) ; + + for ( int i=0; i < nbUE; i++ ) { + int curUE=hTxULUE(bufPtr)->UE_id; + LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[curUE]; + LTE_UL_eNB_HARQ_t *ulsch_harq=ulsch->harq_processes[hTxULUE(bufPtr)->harq_pid]; + ulsch->ue_type=hTxULUE(bufPtr)->ue_type; + ulsch->harq_mask=hTxULUE(bufPtr)->harq_mask; + ulsch->Mlimit=hTxULUE(bufPtr)->Mlimit; + ulsch->max_turbo_iterations=hTxULUE(bufPtr)->max_turbo_iterations; + ulsch->bundling=hTxULUE(bufPtr)->bundling; + ulsch->beta_offset_cqi_times8=hTxULUE(bufPtr)->beta_offset_cqi_times8; + ulsch->beta_offset_ri_times8=hTxULUE(bufPtr)->beta_offset_ri_times8; + ulsch->beta_offset_harqack_times8=hTxULUE(bufPtr)->beta_offset_harqack_times8; + ulsch->Msg3_active=hTxULUE(bufPtr)->Msg3_active; + ulsch->cyclicShift=hTxULUE(bufPtr)->cyclicShift; + ulsch->cooperation_flag=hTxULUE(bufPtr)->cooperation_flag; + ulsch->num_active_cba_groups=hTxULUE(bufPtr)->num_active_cba_groups; + memcpy(ulsch->cba_rnti,hTxULUE(bufPtr)->cba_rnti,sizeof(ulsch->cba_rnti));//NUM_MAX_CBA_GROUP]; + ulsch->rnti=hTxULUE(bufPtr)->rnti; + ulsch_harq->nb_rb=hTxULUE(bufPtr)->nb_rb; + ulsch_harq->handled=0; + ulsch_harq->status = ACTIVE; + ulsch_harq->frame = frame; + ulsch_harq->subframe = subframe; + ulsch_harq->first_rb=hTxULUE(bufPtr)->first_rb; + ulsch_harq->V_UL_DAI=hTxULUE(bufPtr)->V_UL_DAI; + ulsch_harq->Qm=hTxULUE(bufPtr)->Qm; + ulsch_harq->srs_active=hTxULUE(bufPtr)->srs_active; + ulsch_harq->TBS=hTxULUE(bufPtr)->TBS; + ulsch_harq->Nsymb_pusch=hTxULUE(bufPtr)->Nsymb_pusch; + LOG_W(PHY,"Received request to perform ulsch for: rnti:%d, fsf: %d/%d\n", ulsch->rnti, frame, subframe); + } + } else + LOG_E(PHY, "Impossible block in fs6 DL\n"); + + bufPtr+=alignedSize(bufPtr); + } } if (do_meas==1) { @@ -616,6 +758,63 @@ void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int nbBlocks, PHY_VARS_e AMP); } +#define cpyToDu(a) hTxULUE(newUDPheader)->a=ulsch->a +#define cpyToDuHarq(a) hTxULUE(newUDPheader)->a=ulsch_harq->a + +void appendFs6TxULUE(uint8_t *bufferZone, LTE_DL_FRAME_PARMS *fp, int curUE, LTE_eNB_ULSCH_t *ulsch, int frame, int subframe) { + commonUDP_t *FirstUDPheader=(commonUDP_t *) bufferZone; + // move to the end + uint8_t *firstFreeByte=bufferZone; + int curBlock=0; + + for (int i=0; i < FirstUDPheader->nbBlocks; i++) { + AssertFatal( ((commonUDP_t *) firstFreeByte)->blockID==curBlock,""); + firstFreeByte+=alignedSize(firstFreeByte); + curBlock++; + } + + commonUDP_t *newUDPheader=(commonUDP_t *) firstFreeByte; + FirstUDPheader->nbBlocks++; + newUDPheader->blockID=curBlock; + newUDPheader->contentBytes=sizeof(fs6_dl_t)+sizeof(fs6_dl_ulsched_t); + // We skip the fs6 DL header, that is populated by caller + // This header will be duplicated during sending + hTxULUE(newUDPheader)->type=fs6UlConfig; + hTxULUE(newUDPheader)->UE_id=curUE; + int harq_pid; + + if (ulsch->ue_type > NOCE) + // LTE-M case + harq_pid = 0; + else + harq_pid = subframe2harq_pid(fp, frame, subframe); + + LTE_UL_eNB_HARQ_t *ulsch_harq=ulsch->harq_processes[harq_pid]; + hTxULUE(newUDPheader)->harq_pid=harq_pid; + cpyToDu(ue_type); + cpyToDu(harq_mask); + cpyToDu(Mlimit); + cpyToDu(max_turbo_iterations); + cpyToDu(bundling); + cpyToDu(beta_offset_cqi_times8); + cpyToDu(beta_offset_ri_times8); + cpyToDu(beta_offset_harqack_times8); + cpyToDu(Msg3_active); + cpyToDu(cyclicShift); + cpyToDu(cooperation_flag); + cpyToDu(num_active_cba_groups); + memcpy(hTxULUE(newUDPheader)->cba_rnti,ulsch->cba_rnti,sizeof(ulsch->cba_rnti));//NUM_MAX_CBA_GROUP]; + cpyToDu(rnti); + cpyToDuHarq(nb_rb); + cpyToDuHarq(first_rb); + cpyToDuHarq(V_UL_DAI); + cpyToDuHarq(Qm); + cpyToDuHarq(srs_active); + cpyToDuHarq(TBS); + cpyToDuHarq(Nsymb_pusch); + LOG_W(PHY,"Added request to perform ulsch for: rnti:%d, fsf: %d/%d\n", ulsch->rnti, frame, subframe); +} + void appendFs6DLUE(uint8_t *bufferZone, LTE_DL_FRAME_PARMS *fp, int UE_id, int8_t harq_pid, LTE_eNB_DLSCH_t *dlsch0, LTE_DL_eNB_HARQ_t *harqData, int frame, int subframe) { commonUDP_t *FirstUDPheader=(commonUDP_t *) bufferZone; // move to the end @@ -643,6 +842,7 @@ void appendFs6DLUE(uint8_t *bufferZone, LTE_DL_FRAME_PARMS *fp, int UE_id, int8_ newUDPheader->contentBytes=sizeof(fs6_dl_t)+sizeof(fs6_dl_uespec_t) + UEdataLen; // We skip the fs6 DL header, that is populated by caller // This header will be duplicated during sending + hDLUE(newUDPheader)->type=fs6DlConfig; hDLUE(newUDPheader)->UE_id=UE_id; hDLUE(newUDPheader)->harq_pid=harq_pid; hDLUE(newUDPheader)->rnti=dlsch0->rnti; @@ -662,9 +862,8 @@ void appendFs6DLUE(uint8_t *bufferZone, LTE_DL_FRAME_PARMS *fp, int UE_id, int8_ #endif hDLUE(newUDPheader)->dataLen=UEdataLen; memcpy(hDLUE(newUDPheader)+1, harqData->e, UEdataLen); - - for (int i=0; i < UEdataLen; i++) - LOG_D(PHY,"buffer e:%hhx\n", ( (uint8_t *)(hDLUE(newUDPheader)+1) )[i]); + //for (int i=0; i < UEdataLen; i++) + //LOG_D(PHY,"buffer e:%hhx\n", ( (uint8_t *)(hDLUE(newUDPheader)+1) )[i]); } void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas, uint8_t *buf, int bufSize) { @@ -677,59 +876,51 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx return; } - // clear existing ulsch dci allocations before applying info from MAC (this is table - // returns -1 (or 255) if there is no ul (tdd cases) - int ul_subframe = pdcch_alloc2ul_subframe (fp, subframe); - int ul_frame = pdcch_alloc2ul_frame (fp, frame, subframe); - // clear previous allocation information for all UEs for (int i = 0; i < NUMBER_OF_UE_MAX; i++) { //if (eNB->dlsch[i][0]) //eNB->dlsch[i][0]->subframe_tx[subframe] = 0; } - /* TODO: check the following test - in the meantime it is put back as it was before */ - //if ((ul_subframe < 10)&& - // (subframe_select(fp,ul_subframe)==SF_UL)) { // This means that there is a potential UL subframe that will be scheduled here - if (ul_subframe < 10) { // This means that there is a potential UL subframe that will be schedulyed here - for (int i=0; iulsch[i]; - if (eNB->ulsch[i] && eNB->ulsch[i]->ue_type > NOCE) - // LTE-M case - harq_pid = 0; - else - hDL(bufferZone)->UE_ul_active[i] = harq_pid = subframe2harq_pid(fp, ul_frame, ul_subframe); + if (ulsch->ue_type > NOCE) + harq_pid = 0; + else + harq_pid= subframe2harq_pid(&eNB->frame_parms,frame,subframe); - if (eNB->ulsch[i]) { - //LTE_UL_eNB_HARQ_t *ulsch_harq = eNB->ulsch[i]->harq_processes[harq_pid]; - /* Store first_rb and n_DMRS for correct PHICH generation below. - * For PHICH generation we need "old" values of last scheduling - * for this HARQ process. 'generate_eNB_dlsch_params' below will - * overwrite first_rb and n_DMRS and 'generate_phich_top', done - * after 'generate_eNB_dlsch_params', would use the "new" values - * instead of the "old" ones. - * - * This has been tested for FDD only, may be wrong for TDD. - * - * TODO: maybe we should restructure the code to be sure it - * is done correctly. The main concern is if the code - * changes and first_rb and n_DMRS are modified before - * we reach here, then the PHICH processing will be wrong, - * using wrong first_rb and n_DMRS values to compute - * ngroup_PHICH and nseq_PHICH. - * - * TODO: check if that works with TDD. - */ - /* seems useless: unused variables - header->previous_first_rb= - ulsch_harq->previous_first_rb = ulsch_harq->first_rb; - header->previous_n_DMRS = - ulsch_harq->previous_n_DMRS = ulsch_harq->n_DMRS; - */ - hDL(bufferZone)->UE_ul_active[i] = harq_pid; - } else - hDL(bufferZone)->UE_ul_active[i] = -1; + LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; + + if (ulsch->rnti>0) { + LOG_I(PHY,"check in UL scheduled harq %d: rnti %d, tx frame %d/%d, ulsch: %d, %d/%d (handled: %d)\n", + harq_pid, ulsch->rnti, frame, subframe, ulsch_harq->status, ulsch_harq->frame, ulsch_harq->subframe, ulsch_harq->handled); + + for (int k=0; k<8; k++) + if ( ulsch->harq_processes[k]->status == ACTIVE) + LOG_I(PHY,"check in UL scheduledi (harq_pid %d): rnti %d, tx frame %d/%d, ulsch: %d, %d/%d (handled: %d)\n", k, + ulsch->rnti, frame, subframe, ulsch->harq_processes[k]->status, ulsch->harq_processes[k]->frame, ulsch->harq_processes[k]->subframe, ulsch->harq_processes[k]->handled); + } + + for (int k=0; k<8; k++) { + ulsch_harq = ulsch->harq_processes[k]; + + if (ulsch && + (ulsch->rnti>0) && + (ulsch_harq->status == ACTIVE) && + (ulsch_harq->frame == frame) && + (ulsch_harq->subframe == subframe) && + (ulsch_harq->handled == 0) + ) + appendFs6TxULUE(bufferZone, + fp, + i, + ulsch, + frame, + subframe + ); } } @@ -755,9 +946,6 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx if (do_meas==1) start_meas(&eNB->dlsch_ue_specific); - // Now scan UE specific DLSCH - LTE_eNB_DLSCH_t *dlsch0; - for (int UE_id=0; UE_iddlsch[UE_id][0]; @@ -838,8 +1026,6 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx } void DL_du_fs6(RU_t *ru) { - RU_proc_t *ru_proc=&ru->proc; - for (int i=0; inum_eNB; i++) { initBufferZone(bufferZone); int nb_blocks=receiveSubFrame(&sockFS6, bufferZone, sizeof(bufferZone), CTsentCUv0 ); @@ -853,8 +1039,7 @@ void DL_du_fs6(RU_t *ru) { hUDP(bufferZone)->timestamp); } - setAllfromTS(hUDP(bufferZone)->timestamp - - sf_ahead*ru->eNB_list[i]->frame_parms.samples_per_tti); + setAllfromTS(hUDP(bufferZone)->timestamp - sf_ahead*ru->eNB_list[i]->frame_parms.samples_per_tti); phy_procedures_eNB_TX_process( bufferZone, nb_blocks, ru->eNB_list[i], &ru->eNB_list[i]->proc.L1_proc, 1); } else LOG_E(PHY,"DL not received for subframe\n"); @@ -868,13 +1053,15 @@ void DL_du_fs6(RU_t *ru) { void UL_du_fs6(RU_t *ru, int frame, int subframe) { RU_proc_t *ru_proc=&ru->proc; int tmpf=frame, tmpsf=subframe; - rx_rf(ru,&tmpf,&tmpsf); + rx_rf(ru); AssertFatal(tmpf==frame && tmpsf==subframe, "lost synchronization\n"); - ru_proc->frame_tx = (ru_proc->frame_tx+ru_proc->frame_offset)&1023; setAllfromTS(ru_proc->timestamp_rx); + // front end processing: convert from time domain to frequency domain + // fills rxdataF buffer + fep_full(ru); // Fixme: datamodel issue PHY_VARS_eNB *eNB = RC.eNB[0][0]; - L1_proc_t *proc = &eNB->proc; + L1_proc_t *proc = &eNB->proc; if (NFAPI_MODE==NFAPI_MODE_PNF) { // I am a PNF and I need to let nFAPI know that we have a (sub)frame tick @@ -885,7 +1072,7 @@ void UL_du_fs6(RU_t *ru, int frame, int subframe) { initBufferZone(bufferZone); hUDP(bufferZone)->timestamp=ru->proc.timestamp_rx; - prach_eNB_extract(bufferZone, FS6_BUF_SIZE, eNB, proc->frame_rx,proc->subframe_rx ); + prach_eNB_extract(bufferZone, FS6_BUF_SIZE, eNB); if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { phy_procedures_eNB_uespec_RX_extract(bufferZone, FS6_BUF_SIZE, eNB, &proc->L1_proc ); @@ -902,7 +1089,7 @@ void UL_du_fs6(RU_t *ru, int frame, int subframe) { } } -void DL_cu_fs6(RU_t *ru, uint64_t TS) { +void DL_cu_fs6(RU_t *ru) { // Fixme: datamodel issue PHY_VARS_eNB *eNB = RC.eNB[0][0]; L1_proc_t *proc = &eNB->proc; @@ -945,10 +1132,11 @@ void UL_cu_fs6(RU_t *ru, uint64_t *TS) { setAllfromTS(hUDP(bufferZone)->timestamp); PHY_VARS_eNB *eNB = RC.eNB[0][0]; + prach_eNB_process(bufferZone, sizeof(bufferZone), eNB); release_UE_in_freeList(eNB->Mod_id); if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { - phy_procedures_eNB_uespec_RX_process(bufferZone, sizeof(bufferZone), eNB, &eNB->proc.L1_proc); + phy_procedures_eNB_uespec_RX_process(bufferZone, nb_blocks, eNB); } } @@ -965,7 +1153,7 @@ void *cu_fs6(void *arg) { while(1) { timeStamp+=ru->frame_parms.samples_per_tti; UL_cu_fs6(ru, &timeStamp); - DL_cu_fs6(ru, timeStamp); + DL_cu_fs6(ru); } return NULL; diff --git a/executables/main-ocp.c b/executables/main-ocp.c index 432ec6025a..b3983463e0 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -46,6 +46,54 @@ void free_transport(PHY_VARS_eNB *eNB) { void reset_opp_meas(void) { } +// Fixme: there are many mistakes in the datamodel and in redondant variables +// TDD is also mode complex +void setAllfromTS(uint64_t TS) { + for (int i=0; i frame_parms; + RU_proc_t *proc =&RC.ru[i]->proc; + uint64_t TStx=TS+(sf_ahead)*fp->samples_per_tti; + uint64_t TSrach=TS;//-fp->samples_per_tti; + proc->timestamp_rx= TS; + proc->timestamp_tx= TStx; + proc->subframe_rx= (TS / fp->samples_per_tti)%10; + proc->subframe_tx= (TStx / fp->samples_per_tti)%10; + proc->subframe_prach=(TSrach / fp->samples_per_tti)%10; + proc->subframe_prach_br=proc->subframe_prach; + proc->frame_rx= (TS / (fp->samples_per_tti*10))&1023; + proc->frame_prach= (TSrach / (fp->samples_per_tti*10))&1023; + proc->frame_prach_br=(TSrach / (fp->samples_per_tti*10))&1023; + proc->frame_tx= (TStx / (fp->samples_per_tti*10))&1023; + } + + for (int i=0; i < RC.nb_inst; i++) { + for (int j=0; jframe_parms; + L1_proc_t *proc =&RC.eNB[i][j]->proc; + L1_rxtx_proc_t *proc1=&RC.eNB[i][j]->proc.L1_proc; + uint64_t TStx=TS+(sf_ahead)*fp->samples_per_tti; + uint64_t TSrach=TS;//-fp->samples_per_tti; + proc->timestamp_rx= TS; + proc->timestamp_tx= TStx; + proc->subframe_rx= (TS / fp->samples_per_tti)%10; + proc->subframe_prach=(TSrach / fp->samples_per_tti)%10; + proc->subframe_prach_br=(TSrach / fp->samples_per_tti)%10; + proc->frame_rx= (TS / (fp->samples_per_tti*10))&1023; + proc->frame_prach= (TSrach / (fp->samples_per_tti*10))&1023; + proc->frame_prach_br=(TSrach / (fp->samples_per_tti*10))&1023; + proc->frame_tx= (TStx / (fp->samples_per_tti*10))&1023; + proc1->timestamp_tx= TStx; + proc1->subframe_rx= (TS / fp->samples_per_tti)%10; + proc1->subframe_tx= (TStx / fp->samples_per_tti)%10; + proc1->frame_rx= (TS / (fp->samples_per_tti*10))&1023; + proc1->frame_tx= (TStx / (fp->samples_per_tti*10))&1023; + } + } + + return; +} + + void init_eNB_proc(int inst) { /*int i=0;*/ int CC_id; @@ -98,7 +146,6 @@ void init_RU_proc(RU_t *ru) { proc->instance_cnt_eNBs = -1; proc->first_rx = 1; proc->first_tx = 1; - proc->frame_offset = 0; proc->num_slaves = 0; proc->frame_tx_unwrap = 0; @@ -112,8 +159,7 @@ void init_RU_proc(RU_t *ru) { threadCreate(&t, cu_fs6, (void *)ru, "MainCu", -1, OAI_PRIORITY_RT_MAX); else if ( strncasecmp(fs6,"du", 2) == 0 ) { threadCreate(&t, du_fs6, (void *)ru, "MainDu", -1, OAI_PRIORITY_RT_MAX); - } - else + } else AssertFatal(false, "environement variable fs6 is not cu or du"); } else threadCreate(&t, ru_thread, (void *)ru, "MainRu", -1, OAI_PRIORITY_RT_MAX); @@ -263,6 +309,8 @@ void init_eNB(int single_thread_flag,int wait_for_sync) { eNB->prach_energy_counter = 0; } } + + SET_LOG_DEBUG(PRACH); } void stop_eNB(int nb_inst) { @@ -421,17 +469,8 @@ void init_precoding_weights(PHY_VARS_eNB *eNB) { } } -void prach_procedures_ocp(PHY_VARS_eNB *eNB, int br_flag, int frame, int subframe) { +void prach_procedures_ocp(PHY_VARS_eNB *eNB, int br_flag) { uint16_t max_preamble[4],max_preamble_energy[4],max_preamble_delay[4],avg_preamble_energy[4]; - - if (br_flag==0) { - eNB->proc.frame_prach = frame; - eNB->proc.subframe_prach = subframe; - } else { - eNB->proc.frame_prach_br = frame; - eNB->proc.subframe_prach_br = subframe; - } - RU_t *ru; int aa=0; int ru_aa; @@ -456,10 +495,16 @@ void prach_procedures_ocp(PHY_VARS_eNB *eNB, int br_flag, int frame, int subfram &max_preamble_energy[0], &max_preamble_delay[0], &avg_preamble_energy[0], - frame, + eNB->proc.frame_prach, 0 ,br_flag ); + LOG_D(PHY,"RACH detection index 0: max preamble: %u, energy: %u, delay: %u, avg energy: %u\n", + max_preamble[0], + max_preamble_energy[0], + max_preamble_delay[0], + avg_preamble_energy[0] + ); if (br_flag==1) { int prach_mask; @@ -483,7 +528,7 @@ void prach_procedures_ocp(PHY_VARS_eNB *eNB, int br_flag, int frame, int subfram eNB->preamble_list_br[ind].preamble_rel8.timing_advance = max_preamble_delay[ind]; // eNB->preamble_list_br[ind].preamble_rel8.preamble = max_preamble[ind]; // note: fid is implicitly 0 here, this is the rule for eMTC RA-RNTI from 36.321, Section 5.1.4 - eNB->preamble_list_br[ind].preamble_rel8.rnti = 1 + subframe + (60*(eNB->prach_vars_br.first_frame[ce_level] % 40)); + eNB->preamble_list_br[ind].preamble_rel8.rnti = 1 + eNB->proc.subframe_prach + (60*(eNB->prach_vars_br.first_frame[ce_level] % 40)); eNB->preamble_list_br[ind].instance_length = 0; //don't know exactly what this is eNB->preamble_list_br[ind].preamble_rel13.rach_resource_type = 1 + ce_level; // CE Level LOG_I (PHY, "Filling NFAPI indication for RACH %d CELevel %d (mask %x) : TA %d, Preamble %d, rnti %x, rach_resource_type %d\n", @@ -504,8 +549,8 @@ void prach_procedures_ocp(PHY_VARS_eNB *eNB, int br_flag, int frame, int subfram LOG_I(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure with preamble %d, energy %d.%d dB, delay %d\n", eNB->Mod_id, eNB->CC_id, - frame, - subframe, + eNB->proc.frame_prach, + eNB->proc.subframe_prach, max_preamble[0], max_preamble_energy[0]/10, max_preamble_energy[0]%10, @@ -515,11 +560,11 @@ void prach_procedures_ocp(PHY_VARS_eNB *eNB, int br_flag, int frame, int subfram eNB->UL_INFO.rach_ind.rach_indication_body.preamble_list = &eNB->preamble_list[0]; eNB->UL_INFO.rach_ind.rach_indication_body.tl.tag = NFAPI_RACH_INDICATION_BODY_TAG; eNB->UL_INFO.rach_ind.header.message_id = NFAPI_RACH_INDICATION; - eNB->UL_INFO.rach_ind.sfn_sf = frame<<4 | subframe; + eNB->UL_INFO.rach_ind.sfn_sf = eNB->proc.frame_prach<<4 | eNB->proc.subframe_prach; eNB->preamble_list[0].preamble_rel8.tl.tag = NFAPI_PREAMBLE_REL8_TAG; eNB->preamble_list[0].preamble_rel8.timing_advance = max_preamble_delay[0]; eNB->preamble_list[0].preamble_rel8.preamble = max_preamble[0]; - eNB->preamble_list[0].preamble_rel8.rnti = 1+subframe; // note: fid is implicitly 0 here + eNB->preamble_list[0].preamble_rel8.rnti = 1+eNB->proc.subframe_prach; // note: fid is implicitly 0 here eNB->preamble_list[0].preamble_rel13.rach_resource_type = 0; eNB->preamble_list[0].instance_length = 0; //don't know exactly what this is @@ -547,8 +592,8 @@ void prach_procedures_ocp(PHY_VARS_eNB *eNB, int br_flag, int frame, int subfram void prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { // check if we have to detect PRACH first if (is_prach_subframe(&eNB->frame_parms, frame,subframe)>0) { - prach_procedures_ocp(eNB, 0, frame, subframe); - prach_procedures_ocp(eNB, 1, frame, subframe); + prach_procedures_ocp(eNB, 0); + prach_procedures_ocp(eNB, 1); } } @@ -586,28 +631,14 @@ static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name void eNB_top(PHY_VARS_eNB *eNB, int dummy1, int dummy2, char *string,RU_t *ru) { L1_proc_t *proc = &eNB->proc; L1_rxtx_proc_t *L1_proc = &proc->L1_proc; - LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; - RU_proc_t *ru_proc=&ru->proc; if (!oai_exit) { - 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; - L1_proc->frame_tx = (L1_proc->subframe_rx > (9-sf_ahead)) ? - (L1_proc->frame_rx+1)&1023 : - L1_proc->frame_rx; - L1_proc->subframe_tx = (L1_proc->subframe_rx + sf_ahead)%10; - if (rxtx(eNB,L1_proc,string) < 0) LOG_E(PHY,"eNB %d CC_id %d failed during execution\n",eNB->Mod_id,eNB->CC_id); - - ru_proc->timestamp_tx = L1_proc->timestamp_tx; - ru_proc->subframe_tx = L1_proc->subframe_tx; - ru_proc->frame_tx = L1_proc->frame_tx; } } -void rx_rf(RU_t *ru,int *frame,int *subframe) { +void rx_rf(RU_t *ru) { RU_proc_t *proc = &ru->proc; LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; void *rxp[ru->nb_rx]; @@ -616,7 +647,8 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) { openair0_timestamp ts=0,old_ts=0; for (i=0; inb_rx; i++) - rxp[i] = (void *)&ru->common.rxdata[i][*subframe*fp->samples_per_tti]; + //receive in the next slot + rxp[i] = (void *)&ru->common.rxdata[i][((ru->proc.subframe_rx+1)%10)*fp->samples_per_tti]; old_ts = proc->timestamp_rx; rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, @@ -630,6 +662,12 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) { // "rx_rf: Asked for %d samples, got %d from SDR\n",fp->samples_per_tti,rxs); if(rxs != fp->samples_per_tti) { LOG_E(PHY,"rx_rf: Asked for %d samples, got %d from SDR\n",fp->samples_per_tti,rxs); +#if defined(USRP_REC_PLAY) + exit_fun("Exiting IQ record/playback"); +#else + //exit_fun( "problem receiving samples" ); + LOG_E(PHY, "problem receiving samples"); +#endif } if (proc->first_rx == 1) { @@ -638,27 +676,13 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) { proc->first_rx = false; } else { if (proc->timestamp_rx - old_ts != fp->samples_per_tti) { - LOG_E(HW,"impossible shift in RFSIM\n"); + LOG_E(HW,"impossible shift in RFSIM, rx: %ld, previous rx distance: %ld\n", proc->timestamp_rx, proc->timestamp_rx - old_ts); //ru->ts_offset += (proc->timestamp_rx - old_ts - fp->samples_per_tti); //proc->timestamp_rx = ts-ru->ts_offset; } } - proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; - proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; - // synchronize first reception to frame 0 subframe 0 - proc->timestamp_tx = proc->timestamp_rx+(sf_ahead*fp->samples_per_tti); - proc->subframe_tx = (proc->subframe_rx+sf_ahead)%10; - proc->frame_tx = (proc->subframe_rx>(9-sf_ahead)) ? (proc->frame_rx+1)&1023 : proc->frame_rx; - - if (rxs != fp->samples_per_tti) { -#if defined(USRP_REC_PLAY) - exit_fun("Exiting IQ record/playback"); -#else - //exit_fun( "problem receiving samples" ); - LOG_E(PHY, "problem receiving samples"); -#endif - } + setAllfromTS(proc->timestamp_rx); } void tx_rf(RU_t *ru) { @@ -723,9 +747,6 @@ void tx_rf(RU_t *ru) { static void *ru_thread( void *param ) { RU_t *ru = (RU_t *)param; - RU_proc_t *proc = &ru->proc; - int subframe =9; - int frame =1023; if (ru->if_south == LOCAL_RF) { // configure RF parameters only fill_rf_config(ru,ru->rf_config_file); @@ -747,23 +768,8 @@ static void *ru_thread( void *param ) { // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices while (!oai_exit) { - // these are local subframe/frame counters to check that we are in synch with the fronthaul timing. - // They are set on the first rx/tx in the underly FH routines. - if (subframe==9) { - subframe=0; - frame++; - frame&=1023; - } else { - subframe++; - } - // synchronization on input FH interface, acquire signals/data and block - AssertFatal(ru->fh_south_in, "No fronthaul interface at south port"); - ru->fh_south_in(ru,&frame,&subframe); - - // adjust for timing offset between RU - if (ru->idx!=0) - proc->frame_tx = (proc->frame_tx+proc->frame_offset)&1023; + rx_rf(ru); // do RX front-end processing (frequency-shift, dft) if needed if (ru->feprx) @@ -819,7 +825,6 @@ void set_function_spec_param(RU_t *ru) { ru->feptx_ofdm = feptx_ofdm; ru->feptx_prec = feptx_prec; // this is fep with idft and precoding ru->rfdevice.host_type = RAU_HOST; - ru->fh_south_in = rx_rf; // local synchronous RF RX ru->fh_south_out = tx_rf; // local synchronous RF TX ru->start_rf = start_rf; // need to start the local RF interface ru->stop_rf = stop_rf; diff --git a/executables/split_headers.h b/executables/split_headers.h index 2e0df34c54..f3b17e4918 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -58,13 +58,43 @@ typedef struct { DCI_ALLOC_t dci_alloc[32]; int num_mdci; int amp; - int8_t UE_ul_active[NUMBER_OF_UE_MAX]; - int8_t UE_ul_first_rb[NUMBER_OF_UE_MAX]; // - int8_t UE_ul_last_rb[NUMBER_OF_UE_MAX]; // LTE_eNB_PHICH phich_vars; } fs6_dl_t; +enum pckType { + fs6UlConfig=25, + fs6DlConfig=26, +}; + typedef struct { + enum pckType type:8; + uint16_t UE_id; + int8_t harq_pid; + UE_type_t ue_type; + uint16_t harq_mask; + uint16_t nb_rb; + uint8_t Qm; + uint16_t first_rb; + uint8_t V_UL_DAI; + uint8_t srs_active; + uint32_t TBS; + uint8_t Nsymb_pusch; + uint8_t Mlimit; + uint8_t max_turbo_iterations; + uint8_t bundling; + uint16_t beta_offset_cqi_times8; + uint16_t beta_offset_ri_times8; + uint16_t beta_offset_harqack_times8; + uint8_t Msg3_active; + uint16_t rnti; + uint8_t cyclicShift; + uint8_t cooperation_flag; + uint8_t num_active_cba_groups; + uint16_t cba_rnti[4];//NUM_MAX_CBA_GROUP]; +} fs6_dl_ulsched_t; + +typedef struct { + enum pckType type:8; int UE_id; int8_t harq_pid; uint16_t rnti; @@ -76,10 +106,17 @@ typedef struct { uint8_t pdsch_start; uint8_t sib1_br_flag; uint16_t i0; - uint32_t rb_alloc[4]; + uint32_t rb_alloc[4];; int dataLen; } fs6_dl_uespec_t; +typedef struct { + short UE_id; + short harq_id; + short segment; + short segLen; +} fs6_ul_uespec_t; + bool createUDPsock (char *sourceIP, char *sourcePort, char *destIP, char *destPort, UDPsock_t *result); int receiveSubFrame(UDPsock_t *sock, void *bufferZone, int bufferSize, uint16_t contentType); int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize, uint16_t contentType); @@ -92,6 +129,8 @@ int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize, ui #define hDL(xBuf) ((fs6_dl_t*)(((commonUDP_t *)xBuf)+1)) #define hUL(xBuf) ((fs6_ul_t*)(((commonUDP_t *)xBuf)+1)) #define hDLUE(xBuf) ((fs6_dl_uespec_t*) (((fs6_dl_t*)(((commonUDP_t *)xBuf)+1))+1)) +#define hTxULUE(xBuf) ((fs6_dl_ulsched_t*) (((fs6_dl_t*)(((commonUDP_t *)xBuf)+1))+1)) +#define hULUE(xBuf) ((fs6_ul_uespec_t*) (((fs6_ul_t*)(((commonUDP_t *)xBuf)+1))+1)) static inline size_t alignedSize(uint8_t *ptr) { commonUDP_t *header=(commonUDP_t *) ptr; @@ -102,10 +141,11 @@ static inline void *commonUDPdata(uint8_t *ptr) { return (void *) (((commonUDP_t *)ptr)+1); } +void setAllfromTS(uint64_t TS); void *cu_fs6(void *arg); void *du_fs6(void *arg); void fill_rf_config(RU_t *ru, char *rf_config_file); -void rx_rf(RU_t *ru,int *frame,int *subframe); +void rx_rf(RU_t *ru); void tx_rf(RU_t *ru); void common_signal_procedures (PHY_VARS_eNB *eNB,int frame, int subframe); void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc); @@ -128,5 +168,6 @@ void phy_init_RU(RU_t *); void feptx_prec(RU_t *); void feptx_ofdm(RU_t *); void oai_subframe_ind(uint16_t sfn, uint16_t sf); +void fep_full(RU_t *ru); extern uint16_t sf_ahead; #endif diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c index f49005b5d7..6aca9ba904 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach.c +++ b/openair1/PHY/LTE_TRANSPORT/prach.c @@ -649,7 +649,7 @@ void rx_prach0(PHY_VARS_eNB *eNB, preamble_shift2 = ((preamble_shift==0) ? 0 : ((preamble_shift<harq_processes[i]) { - if (ulsch->harq_processes[i]->b) { - free16(ulsch->harq_processes[i]->b,MAX_ULSCH_PAYLOAD_BYTES); - ulsch->harq_processes[i]->b = NULL; + if (ulsch->harq_processes[i]->bb) { + free16(ulsch->harq_processes[i]->bb,MAX_ULSCH_PAYLOAD_BYTES); + ulsch->harq_processes[i]->bb = NULL; } for (r=0; rharq_processes[i]) { memset(ulsch->harq_processes[i],0,sizeof(LTE_UL_eNB_HARQ_t)); - ulsch->harq_processes[i]->b = (uint8_t *)malloc16(MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); + ulsch->harq_processes[i]->bb = (uint8_t *)malloc16(MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); - if (ulsch->harq_processes[i]->b) - memset(ulsch->harq_processes[i]->b,0,MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); + if (ulsch->harq_processes[i]->bb) + memset(ulsch->harq_processes[i]->bb,0,MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); else exit_flag=3; @@ -274,7 +274,7 @@ int ulsch_decoding_data_2thread0(td_params *tdp) { Kr_bytes = Kr>>3; memset(&dummy_w[r][0],0,3*(6144+64)*sizeof(short)); - ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8), + ulsch_harq->RTCC[r] = generate_dummy_w(4+(Kr_bytes*8), (uint8_t *)&dummy_w[r][0], (r==0) ? ulsch_harq->F : 0); #ifdef DEBUG_ULSCH_DECODING @@ -286,11 +286,11 @@ int ulsch_decoding_data_2thread0(td_params *tdp) { ulsch_harq->Nl); #endif - if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r], + if (lte_rate_matching_turbo_rx(ulsch_harq->RTCC[r], G, ulsch_harq->w[r], (uint8_t *) &dummy_w[r][0], - ulsch_harq->e+r_offset, + ulsch_harq->eE+r_offset, ulsch_harq->C, NSOFT, 0, //Uplink @@ -340,7 +340,7 @@ int ulsch_decoding_data_2thread0(td_params *tdp) { Kr = ulsch_harq->Kplus; Kr_bytes = Kr>>3; - memcpy(ulsch_harq->b+offset, + memcpy(ulsch_harq->bb+offset, ulsch_harq->c[r], Kr_bytes - ((ulsch_harq->C>1)?3:0)); offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); @@ -448,7 +448,7 @@ int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr Kr_bytes = Kr>>3; memset(&dummy_w[r][0],0,3*(6144+64)*sizeof(short)); - ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8), + ulsch_harq->RTCC[r] = generate_dummy_w(4+(Kr_bytes*8), (uint8_t *)&dummy_w[r][0], (r==0) ? ulsch_harq->F : 0); #ifdef DEBUG_ULSCH_DECODING @@ -461,11 +461,11 @@ int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr #endif start_meas(&eNB->ulsch_rate_unmatching_stats); - if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r], + if (lte_rate_matching_turbo_rx(ulsch_harq->RTCC[r], G, ulsch_harq->w[r], (uint8_t *) &dummy_w[r][0], - ulsch_harq->e+r_offset, + ulsch_harq->eE+r_offset, ulsch_harq->C, NSOFT, 0, //Uplink @@ -521,12 +521,12 @@ int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr Kr_bytes = Kr>>3; if (r==0) { - memcpy(ulsch_harq->b, + memcpy(ulsch_harq->bb, &ulsch_harq->c[0][(ulsch_harq->F>>3)], Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0)); offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0); } else { - memcpy(ulsch_harq->b+offset, + memcpy(ulsch_harq->bb+offset, ulsch_harq->c[r], Kr_bytes - ((ulsch_harq->C>1)?3:0)); offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); @@ -553,7 +553,7 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id]; LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; int G = ulsch_harq->G; - unsigned int E; + unsigned int EE; decoder_if_t *tc; if (llr8_flag == 0) @@ -571,7 +571,7 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) Kr_bytes = Kr>>3; memset(&dummy_w[r][0],0,3*(6144+64)*sizeof(short)); - ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8), + ulsch_harq->RTCC[r] = generate_dummy_w(4+(Kr_bytes*8), (uint8_t *)&dummy_w[r][0], (r==0) ? ulsch_harq->F : 0); #ifdef DEBUG_ULSCH_DECODING @@ -584,11 +584,11 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) #endif start_meas(&eNB->ulsch_rate_unmatching_stats); - if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r], + if (lte_rate_matching_turbo_rx(ulsch_harq->RTCC[r], G, ulsch_harq->w[r], (uint8_t *) &dummy_w[r][0], - ulsch_harq->e+r_offset, + ulsch_harq->eE+r_offset, ulsch_harq->C, NSOFT, 0, //Uplink @@ -598,13 +598,13 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) ulsch_harq->Qm, 1, r, - &E)==-1) { + &EE)==-1) { LOG_E(PHY,"ulsch_decoding.c: Problem in rate matching\n"); return(-1); } stop_meas(&eNB->ulsch_rate_unmatching_stats); - r_offset += E; + r_offset += EE; start_meas(&eNB->ulsch_deinterleaving_stats); sub_block_deinterleaving_turbo(4+Kr, &ulsch_harq->d[r][96], @@ -616,6 +616,13 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) else crc_type = CRC24_B; + if ( getenv("fs6") != NULL && strncasecmp( getenv("fs6"), "du", 2) == 0 ) { + // r is the segment id, + // Kr is the segment length in short + sendFs6Ul(eNB, UE_id, harq_pid, r, &ulsch_harq->d[r][96], Kr*sizeof(int16_t)); + return 0; + } + start_meas(&eNB->ulsch_turbo_decoding_stats); ret = tc(&ulsch_harq->d[r][96], NULL, @@ -645,12 +652,12 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) Kr_bytes = Kr>>3; if (r==0) { - memcpy(ulsch_harq->b, + memcpy(ulsch_harq->bb, &ulsch_harq->c[0][(ulsch_harq->F>>3)], Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0)); offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0); } else { - memcpy(ulsch_harq->b+offset, + memcpy(ulsch_harq->bb+offset, ulsch_harq->c[r], Kr_bytes - ((ulsch_harq->C>1)?3:0)); offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); @@ -1190,8 +1197,8 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, j2+=2; } - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; + ulsch_harq->eE[iprime++] = y[j2++]; + ulsch_harq->eE[iprime++] = y[j2++]; } break; @@ -1203,10 +1210,10 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, j2+=4; } - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; + ulsch_harq->eE[iprime++] = y[j2++]; + ulsch_harq->eE[iprime++] = y[j2++]; + ulsch_harq->eE[iprime++] = y[j2++]; + ulsch_harq->eE[iprime++] = y[j2++]; } break; @@ -1218,12 +1225,12 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, j2+=6; } - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; + ulsch_harq->eE[iprime++] = y[j2++]; + ulsch_harq->eE[iprime++] = y[j2++]; + ulsch_harq->eE[iprime++] = y[j2++]; + ulsch_harq->eE[iprime++] = y[j2++]; + ulsch_harq->eE[iprime++] = y[j2++]; + ulsch_harq->eE[iprime++] = y[j2++]; } break; @@ -1261,7 +1268,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, */ int16_t *yp,*ep; - for (iprime=0,yp=&y[j2],ep=&ulsch_harq->e[0]; + for (iprime=0,yp=&y[j2],ep=&ulsch_harq->eE[0]; iprimerx_indication_rel8.tl.tag = NFAPI_RX_INDICATION_REL8_TAG; pdu->rx_indication_rel8.length = eNB->ulsch[UE_id]->harq_processes[harq_pid]->TBS>>3; pdu->rx_indication_rel8.offset = 1; // DJP - I dont understand - but broken unless 1 ???? 0; // filled in at the end of the UL_INFO formation - pdu->data = eNB->ulsch[UE_id]->harq_processes[harq_pid]->b; + pdu->data = eNB->ulsch[UE_id]->harq_processes[harq_pid]->bb; // estimate timing advance for MAC sync_pos = lte_est_timing_advance_pusch(eNB,UE_id); timing_advance_update = sync_pos; // - eNB->frame_parms.nb_prefix_samples/4; //to check From cb41822b426b410753f7148049e6a4d7851fcc47 Mon Sep 17 00:00:00 2001 From: laurent Date: Sat, 24 Aug 2019 18:59:45 +0200 Subject: [PATCH 028/240] ulsch turbo decode success, fails after now --- executables/main-fs6.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index 1ebce9ef7d..6cc5f1be65 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -262,6 +262,13 @@ void pusch_procedures_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eN rx_ulsch(eNB, proc, i); stop_meas(&eNB->ulsch_demodulation_stats); // TBD: add datablock for transmission + start_meas(&eNB->ulsch_decoding_stats); + ulsch_decoding(eNB,proc, + i, + 0, // control_only_flag + ulsch_harq->V_UL_DAI, + ulsch_harq->nb_rb>20 ? 1 : 0); + stop_meas(&eNB->ulsch_decoding_stats); } } } @@ -323,14 +330,28 @@ int ulsch_decoding_process(PHY_VARS_eNB *eNB, int UE_id, int llr8_flag) { LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; decoder_if_t *tc; - int offset, ret; + int offset, ret=-1; if (llr8_flag == 0) tc = *decoder16; else tc = *decoder8; - for (int r=0; rC; r++) { + // This is a new packet, so compute quantities regarding segmentation + //Fixme: very dirty: all the variables produced by let_segmentation are only used localy + // Furthermore, variables as 1 letter and global is "time consuming" for everybody !!! + ulsch_harq->B = ulsch_harq->TBS+24; + lte_segmentation(NULL, + NULL, + ulsch_harq->B, + &ulsch_harq->C, + &ulsch_harq->Cplus, + &ulsch_harq->Cminus, + &ulsch_harq->Kplus, + &ulsch_harq->Kminus, + &ulsch_harq->F); + + for (int r=0; rCcC; r++) { // printf("before subblock deinterleaving c[%d] = %p\n",r,ulsch_harq->c[r]); // Get Turbo interleaver parameters int Kr; @@ -379,13 +400,13 @@ int ulsch_decoding_process(PHY_VARS_eNB *eNB, int UE_id, int llr8_flag) { if (r==0) { memcpy(ulsch_harq->bb, &ulsch_harq->c[0][(ulsch_harq->F>>3)], - Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0)); - offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0); + Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->CcC>1)?3:0)); + offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->CcC>1)?3:0); } else { memcpy(ulsch_harq->bb+offset, ulsch_harq->c[r], - Kr_bytes - ((ulsch_harq->C>1)?3:0)); - offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); + Kr_bytes - ((ulsch_harq->CcC>1)?3:0)); + offset += (Kr_bytes- ((ulsch_harq->CcC>1)?3:0)); } } else { break; @@ -666,6 +687,7 @@ void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int nbBlocks, PHY_VARS_e ulsch_harq->first_rb=hTxULUE(bufPtr)->first_rb; ulsch_harq->V_UL_DAI=hTxULUE(bufPtr)->V_UL_DAI; ulsch_harq->Qm=hTxULUE(bufPtr)->Qm; + ulsch_harq->CcC=hTxULUE(bufPtr)->CcC; ulsch_harq->srs_active=hTxULUE(bufPtr)->srs_active; ulsch_harq->TBS=hTxULUE(bufPtr)->TBS; ulsch_harq->Nsymb_pusch=hTxULUE(bufPtr)->Nsymb_pusch; @@ -809,6 +831,7 @@ void appendFs6TxULUE(uint8_t *bufferZone, LTE_DL_FRAME_PARMS *fp, int curUE, LTE cpyToDuHarq(first_rb); cpyToDuHarq(V_UL_DAI); cpyToDuHarq(Qm); + cpyToDuHarq(CcC); cpyToDuHarq(srs_active); cpyToDuHarq(TBS); cpyToDuHarq(Nsymb_pusch); @@ -1052,9 +1075,7 @@ void DL_du_fs6(RU_t *ru) { void UL_du_fs6(RU_t *ru, int frame, int subframe) { RU_proc_t *ru_proc=&ru->proc; - int tmpf=frame, tmpsf=subframe; rx_rf(ru); - AssertFatal(tmpf==frame && tmpsf==subframe, "lost synchronization\n"); setAllfromTS(ru_proc->timestamp_rx); // front end processing: convert from time domain to frequency domain // fills rxdataF buffer From 55660e87ca4442dd3ca0873289eef08ee727cc37 Mon Sep 17 00:00:00 2001 From: laurent Date: Sun, 25 Aug 2019 20:32:57 +0200 Subject: [PATCH 029/240] RACH working, fails later during MME authentication --- executables/main-fs6.c | 203 +++++++++++++++----- executables/split_headers.h | 32 +++ executables/transport_split.c | 5 +- openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c | 4 +- openair1/SCHED/fapi_l1.h | 2 +- openair1/SCHED/phy_procedures_lte_eNb.c | 20 +- 6 files changed, 212 insertions(+), 54 deletions(-) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index 6cc5f1be65..07a5fc2805 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -171,6 +171,49 @@ void prach_eNB_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB) { } } +void sendFs6Ulharq(int UEid, PHY_VARS_eNB *eNB, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask) { + static int current_fsf=-1; + int fsf=frame*16+subframe; + uint8_t *bufferZone=eNB->FS6bufferZone; + commonUDP_t *FirstUDPheader=(commonUDP_t *) bufferZone; + // move to the end + uint8_t *firstFreeByte=bufferZone; + int curBlock=0; + + if ( current_fsf != fsf ) { + for (int i=0; i < FirstUDPheader->nbBlocks; i++) { + AssertFatal( ((commonUDP_t *) firstFreeByte)->blockID==curBlock,""); + firstFreeByte+=alignedSize(firstFreeByte); + curBlock++; + } + + commonUDP_t *newUDPheader=(commonUDP_t *) firstFreeByte; + FirstUDPheader->nbBlocks++; + newUDPheader->blockID=curBlock; + newUDPheader->contentBytes=sizeof(fs6_ul_t)+sizeof(fs6_ul_uespec_uci_t); + hULUEuci(newUDPheader)->type=fs6ULcch; + hULUEuci(newUDPheader)->nb_active_ue=0; + } else + for (int i=0; i < FirstUDPheader->nbBlocks-1; i++) { + AssertFatal( ((commonUDP_t *) firstFreeByte)->blockID==curBlock,""); + firstFreeByte+=alignedSize(firstFreeByte); + curBlock++; + } + + commonUDP_t *newUDPheader=(commonUDP_t *) firstFreeByte; + fs6_ul_uespec_uci_element_t *tmp=(fs6_ul_uespec_uci_element_t *)(hULUEuci(newUDPheader)+1); + tmp+=hULUEuci(newUDPheader)->nb_active_ue; + tmp->UEid=UEid; + tmp->frame=frame; + tmp->subframe=subframe; + memcpy(tmp->harq_ack, harq_ack, 4); + tmp->tdd_mapping_mode=tdd_mapping_mode; + tmp->tdd_multiplexing_mask=tdd_multiplexing_mask; + tmp->n0_subband_power_dB=eNB->measurements.n0_subband_power_dB[0][0]; + hULUEuci(newUDPheader)->nb_active_ue++; + newUDPheader->contentBytes+=sizeof(fs6_ul_uespec_uci_element_t); +} + void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen) { uint8_t *bufferZone=eNB->FS6bufferZone; commonUDP_t *FirstUDPheader=(commonUDP_t *) bufferZone; @@ -188,10 +231,12 @@ void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_ FirstUDPheader->nbBlocks++; newUDPheader->blockID=curBlock; newUDPheader->contentBytes=sizeof(fs6_ul_t)+sizeof(fs6_ul_uespec_t) + dataLen; + hULUE(newUDPheader)->type=fs6ULsch; hULUE(newUDPheader)->UE_id=UE_id; hULUE(newUDPheader)->harq_id=harq_pid; hULUE(newUDPheader)->segment=segmentID; memcpy(hULUE(newUDPheader)+1, data, dataLen); + hULUE(newUDPheader)->segLen=dataLen; } void pusch_procedures_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { @@ -351,7 +396,7 @@ int ulsch_decoding_process(PHY_VARS_eNB *eNB, int UE_id, int llr8_flag) { &ulsch_harq->Kminus, &ulsch_harq->F); - for (int r=0; rCcC; r++) { + for (int r=0; rC; r++) { // printf("before subblock deinterleaving c[%d] = %p\n",r,ulsch_harq->c[r]); // Get Turbo interleaver parameters int Kr; @@ -400,13 +445,13 @@ int ulsch_decoding_process(PHY_VARS_eNB *eNB, int UE_id, int llr8_flag) { if (r==0) { memcpy(ulsch_harq->bb, &ulsch_harq->c[0][(ulsch_harq->F>>3)], - Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->CcC>1)?3:0)); - offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->CcC>1)?3:0); + Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0)); + offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0); } else { memcpy(ulsch_harq->bb+offset, ulsch_harq->c[r], - Kr_bytes - ((ulsch_harq->CcC>1)?3:0)); - offset += (Kr_bytes- ((ulsch_harq->CcC>1)?3:0)); + Kr_bytes - ((ulsch_harq->C>1)?3:0)); + offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); } } else { break; @@ -583,15 +628,32 @@ void recvFs6Ul(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB) { void *bufPtr=bufferZone; for (int i=0; i < nbBlocks; i++) { //nbBlocks is the actual received blocks - if ( ((commonUDP_t *)bufPtr)->contentBytes >= sizeof(fs6_ul_t)+sizeof(fs6_ul_uespec_t) ) { - LTE_eNB_ULSCH_t *ulsch =eNB->ulsch[hULUE(bufPtr)->UE_id]; - LTE_UL_eNB_HARQ_t *ulsch_harq=ulsch->harq_processes[hULUE(bufPtr)->harq_id]; - memcpy(&ulsch_harq->d[hULUE(bufPtr)->segment][96], - hULUE(bufPtr)+1, - hULUE(bufPtr)->segLen); - bufPtr+=alignedSize(bufPtr); - LOG_W(PHY,"Received ulsch data for: rnti:%d, fsf: %d/%d\n", ulsch->rnti, eNB->proc.frame_rx, eNB->proc.subframe_rx); + if ( ((commonUDP_t *)bufPtr)->contentBytes > sizeof(fs6_ul_t) ) { + int type=hULUE(bufPtr)->type; + + if ( type == fs6ULsch) { + LTE_eNB_ULSCH_t *ulsch =eNB->ulsch[hULUE(bufPtr)->UE_id]; + LTE_UL_eNB_HARQ_t *ulsch_harq=ulsch->harq_processes[hULUE(bufPtr)->harq_id]; + memcpy(&ulsch_harq->d[hULUE(bufPtr)->segment][96], + hULUE(bufPtr)+1, + hULUE(bufPtr)->segLen); + LOG_W(PHY,"Received ulsch data for: rnti:%d, fsf: %d/%d\n", ulsch->rnti, eNB->proc.frame_rx, eNB->proc.subframe_rx); + } else if ( type == fs6ULcch ) { + int nb_uci=hULUEuci(bufPtr)->nb_active_ue; + fs6_ul_uespec_uci_element_t *tmp=(fs6_ul_uespec_uci_element_t *)(hULUEuci(bufPtr)+1); + + for (int i=0; i < nb_uci ; i++) { + eNB->measurements.n0_subband_power_dB[0][0]=tmp->n0_subband_power_dB; + fill_uci_harq_indication (tmp->UEid, eNB, &eNB->uci_vars[tmp->UEid], + tmp->frame, tmp->subframe, tmp->harq_ack, + tmp->tdd_mapping_mode, tmp->tdd_multiplexing_mask); + tmp++; + } + } else + LOG_E(PHY, "FS6 ul packet type impossible\n" ); } + + bufPtr+=alignedSize(bufPtr); } } @@ -601,30 +663,7 @@ void phy_procedures_eNB_uespec_RX_process(uint8_t *bufferZone, int nbBlocks,PHY_ pusch_procedures_process(bufferZone, nbBlocks, eNB); } -void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas ) { - LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - int subframe=proc->subframe_tx; - int frame=proc->frame_tx; - //LTE_UL_eNB_HARQ_t *ulsch_harq; - eNB->pdcch_vars[subframe&1].num_pdcch_symbols=hDL(bufferZone)->num_pdcch_symbols; - eNB->pdcch_vars[subframe&1].num_dci=hDL(bufferZone)->num_dci; - uint8_t num_mdci = eNB->mpdcch_vars[subframe&1].num_dci = hDL(bufferZone)->num_mdci; - eNB->pbch_configured=true; - memcpy(eNB->pbch_pdu,hDL(bufferZone)->pbch_pdu, 4); - - // Remove all scheduled DL, we will populate from the CU sending - for (int UE_id=0; UE_iddlsch[UE_id][0]; - - if ( dlsch0 && dlsch0->rnti>0 ) { -#ifdef PHY_TX_THREAD - dlsch0->active[subframe] = 0; -#else - dlsch0->active = 0; -#endif - } - } - +void rcvFs6DL(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, int frame, int subframe) { void *bufPtr=bufferZone; for (int i=0; i < nbBlocks; i++) { //nbBlocks is the actual received blocks @@ -687,19 +726,50 @@ void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int nbBlocks, PHY_VARS_e ulsch_harq->first_rb=hTxULUE(bufPtr)->first_rb; ulsch_harq->V_UL_DAI=hTxULUE(bufPtr)->V_UL_DAI; ulsch_harq->Qm=hTxULUE(bufPtr)->Qm; - ulsch_harq->CcC=hTxULUE(bufPtr)->CcC; ulsch_harq->srs_active=hTxULUE(bufPtr)->srs_active; ulsch_harq->TBS=hTxULUE(bufPtr)->TBS; ulsch_harq->Nsymb_pusch=hTxULUE(bufPtr)->Nsymb_pusch; LOG_W(PHY,"Received request to perform ulsch for: rnti:%d, fsf: %d/%d\n", ulsch->rnti, frame, subframe); } - } else - LOG_E(PHY, "Impossible block in fs6 DL\n"); + } else if ( type == fs6ULConfigCCH ) { + fs6_dl_uespec_ulcch_element_t *tmp=(fs6_dl_uespec_ulcch_element_t *)(hTxULcch(bufPtr)+1); - bufPtr+=alignedSize(bufPtr); + for (int i=0; i< hTxULcch(bufPtr)->nb_active_ue; i++ ) + memcpy(&eNB->uci_vars[tmp->UE_id], &tmp->cch_vars, sizeof(tmp->cch_vars)); + } else + LOG_E(PHY, "Impossible block in fs6 DL\n"); + } + + bufPtr+=alignedSize(bufPtr); + } +} + +void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas ) { + LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; + int subframe=proc->subframe_tx; + int frame=proc->frame_tx; + //LTE_UL_eNB_HARQ_t *ulsch_harq; + eNB->pdcch_vars[subframe&1].num_pdcch_symbols=hDL(bufferZone)->num_pdcch_symbols; + eNB->pdcch_vars[subframe&1].num_dci=hDL(bufferZone)->num_dci; + uint8_t num_mdci = eNB->mpdcch_vars[subframe&1].num_dci = hDL(bufferZone)->num_mdci; + eNB->pbch_configured=true; + memcpy(eNB->pbch_pdu,hDL(bufferZone)->pbch_pdu, 4); + + // Remove all scheduled DL, we will populate from the CU sending + for (int UE_id=0; UE_iddlsch[UE_id][0]; + + if ( dlsch0 && dlsch0->rnti>0 ) { +#ifdef PHY_TX_THREAD + dlsch0->active[subframe] = 0; +#else + dlsch0->active = 0; +#endif } } + rcvFs6DL(bufferZone, nbBlocks, eNB, frame, subframe); + if (do_meas==1) { start_meas(&eNB->phy_proc_tx); start_meas(&eNB->dlsch_common_and_dci); @@ -831,13 +901,11 @@ void appendFs6TxULUE(uint8_t *bufferZone, LTE_DL_FRAME_PARMS *fp, int curUE, LTE cpyToDuHarq(first_rb); cpyToDuHarq(V_UL_DAI); cpyToDuHarq(Qm); - cpyToDuHarq(CcC); cpyToDuHarq(srs_active); cpyToDuHarq(TBS); cpyToDuHarq(Nsymb_pusch); LOG_W(PHY,"Added request to perform ulsch for: rnti:%d, fsf: %d/%d\n", ulsch->rnti, frame, subframe); } - void appendFs6DLUE(uint8_t *bufferZone, LTE_DL_FRAME_PARMS *fp, int UE_id, int8_t harq_pid, LTE_eNB_DLSCH_t *dlsch0, LTE_DL_eNB_HARQ_t *harqData, int frame, int subframe) { commonUDP_t *FirstUDPheader=(commonUDP_t *) bufferZone; // move to the end @@ -889,6 +957,50 @@ void appendFs6DLUE(uint8_t *bufferZone, LTE_DL_FRAME_PARMS *fp, int UE_id, int8_ //LOG_D(PHY,"buffer e:%hhx\n", ( (uint8_t *)(hDLUE(newUDPheader)+1) )[i]); } +void appendFs6DLUEcch(uint8_t *bufferZone, PHY_VARS_eNB *eNB, int frame, int subframe) { + commonUDP_t *FirstUDPheader=(commonUDP_t *) bufferZone; + // move to the end + uint8_t *firstFreeByte=bufferZone; + int curBlock=0; + + for (int i=0; i < FirstUDPheader->nbBlocks; i++) { + AssertFatal( ((commonUDP_t *) firstFreeByte)->blockID==curBlock,""); + firstFreeByte+=alignedSize(firstFreeByte); + curBlock++; + } + + commonUDP_t *newUDPheader=(commonUDP_t *) firstFreeByte; + bool first_UE=true; + + for (int i = 0; i < NUMBER_OF_UCI_VARS_MAX; i++) { + LTE_eNB_UCI *uci = &(eNB->uci_vars[i]); + + if ((uci->active == 1) && (uci->frame == frame) && (uci->subframe == subframe)) { + LOG_D(PHY,"Frame %d, subframe %d: adding uci procedures (type %d) for %d \n", + frame, + subframe, + uci->type, + i); + + if ( first_UE ) { + FirstUDPheader->nbBlocks++; + newUDPheader->blockID=curBlock; + newUDPheader->contentBytes=sizeof(fs6_dl_t)+sizeof(fs6_dl_uespec_ulcch_t); + hTxULcch(newUDPheader)->type=fs6ULConfigCCH; + hTxULcch(newUDPheader)->nb_active_ue=0; + first_UE=false; + } + + fs6_dl_uespec_ulcch_element_t *tmp=(fs6_dl_uespec_ulcch_element_t *)(hTxULcch(newUDPheader)+1); + tmp+=hTxULcch(newUDPheader)->nb_active_ue; + tmp->UE_id=i; + memcpy(&tmp->cch_vars,uci, sizeof(tmp->cch_vars)); + hTxULcch(newUDPheader)->nb_active_ue++; + newUDPheader->contentBytes+=sizeof(fs6_dl_uespec_ulcch_element_t); + } + } +} + void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas, uint8_t *buf, int bufSize) { int frame=proc->frame_tx; int subframe=proc->subframe_tx; @@ -947,6 +1059,11 @@ void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx } } + appendFs6DLUEcch(bufferZone, + eNB, + frame, + subframe + ); uint8_t num_pdcch_symbols = eNB->pdcch_vars[subframe&1].num_pdcch_symbols; uint8_t num_dci = eNB->pdcch_vars[subframe&1].num_dci; uint8_t num_mdci = eNB->mpdcch_vars[subframe&1].num_dci; diff --git a/executables/split_headers.h b/executables/split_headers.h index f3b17e4918..0fed9d63c8 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -64,6 +64,9 @@ typedef struct { enum pckType { fs6UlConfig=25, fs6DlConfig=26, + fs6ULConfigCCH=27, + fs6ULsch=28, + fs6ULcch=29, }; typedef struct { @@ -111,12 +114,39 @@ typedef struct { } fs6_dl_uespec_t; typedef struct { + int16_t UE_id; + LTE_eNB_UCI cch_vars; +} fs6_dl_uespec_ulcch_element_t; + +typedef struct { + enum pckType type:8; + int16_t nb_active_ue; +} fs6_dl_uespec_ulcch_t; + +typedef struct { + enum pckType type:8; short UE_id; short harq_id; short segment; short segLen; } fs6_ul_uespec_t; +typedef struct { + int UEid; + int frame; + int subframe; + uint8_t harq_ack[4]; + uint8_t tdd_mapping_mode; + uint16_t tdd_multiplexing_mask; + unsigned short n0_subband_power_dB; +} fs6_ul_uespec_uci_element_t; + +typedef struct { + enum pckType type:8; + int16_t nb_active_ue; +} fs6_ul_uespec_uci_t; + + bool createUDPsock (char *sourceIP, char *sourcePort, char *destIP, char *destPort, UDPsock_t *result); int receiveSubFrame(UDPsock_t *sock, void *bufferZone, int bufferSize, uint16_t contentType); int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize, uint16_t contentType); @@ -130,7 +160,9 @@ int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize, ui #define hUL(xBuf) ((fs6_ul_t*)(((commonUDP_t *)xBuf)+1)) #define hDLUE(xBuf) ((fs6_dl_uespec_t*) (((fs6_dl_t*)(((commonUDP_t *)xBuf)+1))+1)) #define hTxULUE(xBuf) ((fs6_dl_ulsched_t*) (((fs6_dl_t*)(((commonUDP_t *)xBuf)+1))+1)) +#define hTxULcch(xBuf) ((fs6_dl_uespec_ulcch_t*) (((fs6_dl_t*)(((commonUDP_t *)xBuf)+1))+1)) #define hULUE(xBuf) ((fs6_ul_uespec_t*) (((fs6_ul_t*)(((commonUDP_t *)xBuf)+1))+1)) +#define hULUEuci(xBuf) ((fs6_ul_uespec_uci_t*) (((fs6_ul_t*)(((commonUDP_t *)xBuf)+1))+1)) static inline size_t alignedSize(uint8_t *ptr) { commonUDP_t *header=(commonUDP_t *) ptr; diff --git a/executables/transport_split.c b/executables/transport_split.c index c9d848ef19..17e40e7e25 100644 --- a/executables/transport_split.c +++ b/executables/transport_split.c @@ -139,9 +139,9 @@ int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize, ui *currentHeader=*UDPheader; currentHeader->blockID=blockId; memcpy(commonUDPdata((void *)currentHeader), commonUDPdata(bufferZone), secondHeaderSize); - blockId++; } + blockId++; int sz=alignedSize(bufferZone); // Let's use the first address returned by getaddrinfo() int ret=sendto(sock->sockHandler, bufferZone, sz, 0, @@ -155,6 +155,7 @@ int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize, ui nbBlocks--; } while (nbBlocks); - LOG_D(HW,"Sent: TS: %lu\n", UDPheader->timestamp); + LOG_D(HW,"Sent: TS: %lu, nb blocks %d, size of first block: %lu \n", + UDPheader->timestamp, UDPheader->nbBlocks, alignedSize((void *)UDPheader)); return 0; } diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index 1fe65cd75e..59fd9b1378 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -46,6 +46,7 @@ #include "transport_proto.h" extern WORKER_CONF_t get_thread_worker_conf(void); +void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen); void free_eNB_ulsch(LTE_eNB_ULSCH_t *ulsch) { int i,r; @@ -619,7 +620,8 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) if ( getenv("fs6") != NULL && strncasecmp( getenv("fs6"), "du", 2) == 0 ) { // r is the segment id, // Kr is the segment length in short - sendFs6Ul(eNB, UE_id, harq_pid, r, &ulsch_harq->d[r][96], Kr*sizeof(int16_t)); +// *3 because LTE redudancy scheme + sendFs6Ul(eNB, UE_id, harq_pid, r, &ulsch_harq->d[r][96], Kr*sizeof(int16_t)*3); return 0; } diff --git a/openair1/SCHED/fapi_l1.h b/openair1/SCHED/fapi_l1.h index 3bd469b685..77c254b13f 100644 --- a/openair1/SCHED/fapi_l1.h +++ b/openair1/SCHED/fapi_l1.h @@ -37,7 +37,7 @@ #include "SCHED/sched_common.h" #include "nfapi_interface.h" -void fill_uci_harq_indication(PHY_VARS_eNB *eNB,LTE_eNB_UCI *uci,int frame,int subframe,uint8_t *harq_ack,uint8_t tdd_mapping_mode,uint16_t tdd_multiplexing_mask); +void fill_uci_harq_indication(int UEid, PHY_VARS_eNB *eNB,LTE_eNB_UCI *uci,int frame,int subframe,uint8_t *harq_ack,uint8_t tdd_mapping_mode,uint16_t tdd_multiplexing_mask); void fill_ulsch_harq_indication(PHY_VARS_eNB *eNB,LTE_UL_eNB_HARQ_t *ulsch_harq,uint16_t rnti, int frame,int subframe,int bundling); void fill_ulsch_cqi_indication(PHY_VARS_eNB *eNB,uint16_t frame,uint8_t subframe,LTE_UL_eNB_HARQ_t *ulsch_harq,uint16_t rnti); void fill_sr_indication(PHY_VARS_eNB *eNB,uint16_t rnti,int frame,int subframe,uint32_t stat); diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 52b0c93bcf..4764ede395 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -46,6 +46,7 @@ #include #include "intertask_interface.h" +void sendFs6Ulharq(int UEid, PHY_VARS_eNB *eNB, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask); nfapi_ue_release_request_body_t release_rntis; @@ -768,7 +769,7 @@ uci_procedures(PHY_VARS_eNB *eNB, frame,subframe, pucch_b0b1[0][0],metric[0]); uci->stat = metric[0]; - fill_uci_harq_indication(eNB,uci,frame,subframe,pucch_b0b1[0],0,0xffff); + fill_uci_harq_indication(i, eNB,uci,frame,subframe,pucch_b0b1[0],0,0xffff); } else { // frame_type == TDD LOG_D(PHY,"Frame %d Subframe %d Demodulating PUCCH (UCI %d) for ACK/NAK (uci->pucch_fmt %d,uci->type %d.uci->frame %d, uci->subframe %d): n1_pucch0 %d SR_payload %d\n", frame,subframe,i, @@ -881,7 +882,7 @@ uci_procedures(PHY_VARS_eNB *eNB, } uci->stat = metric[0]; - fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,2,0xffff); // special_bundling mode + fill_uci_harq_indication(i, eNB,uci,frame,subframe,harq_ack,2,0xffff); // special_bundling mode } else if ((uci->tdd_bundling == 0) && (uci->num_pucch_resources==2)) { // multiplexing + no SR, implement Table 10.1.3-5 (Rel14) for multiplexing with M=2 if (pucch_b0b1[0][0] == 4 || pucch_b0b1[1][0] == 4) { // there isn't a likely transmission @@ -917,7 +918,7 @@ uci_procedures(PHY_VARS_eNB *eNB, } uci->stat = max(metric[0],metric[1]); - fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode + fill_uci_harq_indication(i, eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode } //else if ((uci->tdd_bundling == 0) && (res==2)) else if ((uci->tdd_bundling == 0) && (uci->num_pucch_resources==3)) { // multiplexing + no SR, implement Table 10.1.3-6 (Rel14) for multiplexing with M=3 if (harq_ack[0] == 4 || @@ -988,7 +989,7 @@ uci_procedures(PHY_VARS_eNB *eNB, } uci->stat = max_metric; - fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode + fill_uci_harq_indication(i, eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode } } //else if ((uci->tdd_bundling == 0) && (res==3)) else if ((uci->tdd_bundling == 0) && (uci->num_pucch_resources==4)) { // multiplexing + no SR, implement Table 10.1.3-7 (Rel14) for multiplexing with M=4 @@ -1110,14 +1111,14 @@ uci_procedures(PHY_VARS_eNB *eNB, } uci->stat = max_metric; - fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode + fill_uci_harq_indication(i, eNB,uci,frame,subframe,harq_ack,1,tdd_multiplexing_mask); // multiplexing mode } // else if ((uci->tdd_bundling == 0) && (res==4)) else { // bundling harq_ack[0] = pucch_b0b1[0][0]; harq_ack[1] = pucch_b0b1[0][1]; uci->stat = metric[0]; LOG_D(PHY,"bundling: (%d,%d), metric %d\n",harq_ack[0],harq_ack[1],uci->stat); - fill_uci_harq_indication(eNB,uci,frame,subframe,harq_ack,0,0xffff); // special_bundling mode + fill_uci_harq_indication(i, eNB,uci,frame,subframe,harq_ack,0,0xffff); // special_bundling mode } #ifdef DEBUG_PHY_PROC @@ -1754,7 +1755,12 @@ void fill_ulsch_harq_indication (PHY_VARS_eNB *eNB, LTE_UL_eNB_HARQ_t *ulsch_har pthread_mutex_unlock(&eNB->UL_INFO_mutex); } -void fill_uci_harq_indication (PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask) { +void fill_uci_harq_indication (int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask) { + if ( getenv("fs6") != NULL && strncasecmp( getenv("fs6"), "du", 2) == 0 ) { + sendFs6Ulharq(UEid, eNB, frame, subframe, harq_ack, tdd_mapping_mode, tdd_multiplexing_mask); + return; + } + int UE_id=find_dlsch(uci->rnti,eNB,SEARCH_EXIST); //AssertFatal(UE_id>=0,"UE_id doesn't exist rnti:%x\n", uci->rnti); From 1fe5ed6f3a232378a47f00f19eb8226939b55d19 Mon Sep 17 00:00:00 2001 From: laurent Date: Sun, 25 Aug 2019 20:45:13 +0200 Subject: [PATCH 030/240] changed terminology from/to split --- executables/main-fs6.c | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index 07a5fc2805..845e5c6f5f 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -22,7 +22,7 @@ static UDPsock_t sockFS6; -void prach_eNB_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB) { +void prach_eNB_tosplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB) { fs6_ul_t *header=(fs6_ul_t *) commonUDPdata(bufferZone); if (is_prach_subframe(&eNB->frame_parms, eNB->proc.frame_prach,eNB->proc.subframe_prach)<=0) @@ -77,7 +77,7 @@ void prach_eNB_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB) { return; } -void prach_eNB_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB) { +void prach_eNB_fromsplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB) { fs6_ul_t *header=(fs6_ul_t *) commonUDPdata(bufferZone); uint16_t *max_preamble=header->max_preamble; uint16_t *max_preamble_energy=header->max_preamble_energy; @@ -239,7 +239,7 @@ void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_ hULUE(newUDPheader)->segLen=dataLen; } -void pusch_procedures_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { +void pusch_procedures_tosplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { uint32_t harq_pid; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; const int subframe = proc->subframe_rx; @@ -260,11 +260,6 @@ void pusch_procedures_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eN i, harq_pid, frame,subframe,i,ulsch->rnti, ulsch_harq->status, ulsch_harq->frame, ulsch_harq->subframe, ulsch_harq->status, ulsch_harq->handled); - if ((ulsch) && - (ulsch->rnti>0) && - (ulsch_harq->status == ACTIVE)) - LOG_E(PHY,"active ulsch harq\n"); - if ((ulsch) && (ulsch->rnti>0) && (ulsch_harq->status == ACTIVE) && @@ -318,7 +313,7 @@ void pusch_procedures_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eN } } -void phy_procedures_eNB_uespec_RX_extract(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { +void phy_procedures_eNB_uespec_RX_tosplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { //RX processing for ue-specific resources (i LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; const int subframe = proc->subframe_rx; @@ -341,7 +336,7 @@ void phy_procedures_eNB_uespec_RX_extract(uint8_t *bufferZone, int bufSize, PHY_ uci_procedures (eNB, proc); if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { // If PNF or monolithic - pusch_procedures_extract(bufferZone, bufSize, eNB,proc); + pusch_procedures_tosplit(bufferZone, bufSize, eNB,proc); } lte_eNB_I0_measurements (eNB, subframe, 0, eNB->first_run_I0_measurements); @@ -461,7 +456,7 @@ int ulsch_decoding_process(PHY_VARS_eNB *eNB, int UE_id, int llr8_flag) { return(ret); } -void pusch_procedures_process(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB) { +void pusch_procedures_fromsplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB) { //LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; const int subframe = eNB->proc.subframe_rx; const int frame = eNB->proc.frame_rx; @@ -657,10 +652,10 @@ void recvFs6Ul(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB) { } } -void phy_procedures_eNB_uespec_RX_process(uint8_t *bufferZone, int nbBlocks,PHY_VARS_eNB *eNB) { +void phy_procedures_eNB_uespec_RX_fromsplit(uint8_t *bufferZone, int nbBlocks,PHY_VARS_eNB *eNB) { // The configuration arrived in Dl, so we can extract the UL data recvFs6Ul(bufferZone, nbBlocks, eNB); - pusch_procedures_process(bufferZone, nbBlocks, eNB); + pusch_procedures_fromsplit(bufferZone, nbBlocks, eNB); } void rcvFs6DL(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, int frame, int subframe) { @@ -744,7 +739,7 @@ void rcvFs6DL(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, int frame, i } } -void phy_procedures_eNB_TX_process(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas ) { +void phy_procedures_eNB_TX_fromsplit(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas ) { LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; int subframe=proc->subframe_tx; int frame=proc->frame_tx; @@ -1001,7 +996,7 @@ void appendFs6DLUEcch(uint8_t *bufferZone, PHY_VARS_eNB *eNB, int frame, int sub } } -void phy_procedures_eNB_TX_extract(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas, uint8_t *buf, int bufSize) { +void phy_procedures_eNB_TX_tosplit(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int do_meas, uint8_t *buf, int bufSize) { int frame=proc->frame_tx; int subframe=proc->subframe_tx; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; @@ -1180,7 +1175,7 @@ void DL_du_fs6(RU_t *ru) { } setAllfromTS(hUDP(bufferZone)->timestamp - sf_ahead*ru->eNB_list[i]->frame_parms.samples_per_tti); - phy_procedures_eNB_TX_process( bufferZone, nb_blocks, ru->eNB_list[i], &ru->eNB_list[i]->proc.L1_proc, 1); + phy_procedures_eNB_TX_fromsplit( bufferZone, nb_blocks, ru->eNB_list[i], &ru->eNB_list[i]->proc.L1_proc, 1); } else LOG_E(PHY,"DL not received for subframe\n"); } @@ -1210,10 +1205,10 @@ void UL_du_fs6(RU_t *ru, int frame, int subframe) { initBufferZone(bufferZone); hUDP(bufferZone)->timestamp=ru->proc.timestamp_rx; - prach_eNB_extract(bufferZone, FS6_BUF_SIZE, eNB); + prach_eNB_tosplit(bufferZone, FS6_BUF_SIZE, eNB); if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { - phy_procedures_eNB_uespec_RX_extract(bufferZone, FS6_BUF_SIZE, eNB, &proc->L1_proc ); + phy_procedures_eNB_uespec_RX_tosplit(bufferZone, FS6_BUF_SIZE, eNB, &proc->L1_proc ); } if (hUDP(bufferZone)->nbBlocks==0) { @@ -1239,7 +1234,7 @@ void DL_cu_fs6(RU_t *ru) { eNB->if_inst->UL_indication(&eNB->UL_INFO); pthread_mutex_unlock(&eNB->UL_INFO_mutex); initBufferZone(bufferZone); - phy_procedures_eNB_TX_extract(bufferZone, eNB, &proc->L1_proc, 1, bufferZone, FS6_BUF_SIZE); + phy_procedures_eNB_TX_tosplit(bufferZone, eNB, &proc->L1_proc, 1, bufferZone, FS6_BUF_SIZE); hUDP(bufferZone)->timestamp=proc->L1_proc.timestamp_tx; if (hUDP(bufferZone)->nbBlocks==0) { @@ -1270,11 +1265,11 @@ void UL_cu_fs6(RU_t *ru, uint64_t *TS) { setAllfromTS(hUDP(bufferZone)->timestamp); PHY_VARS_eNB *eNB = RC.eNB[0][0]; - prach_eNB_process(bufferZone, sizeof(bufferZone), eNB); + prach_eNB_fromsplit(bufferZone, sizeof(bufferZone), eNB); release_UE_in_freeList(eNB->Mod_id); if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { - phy_procedures_eNB_uespec_RX_process(bufferZone, nb_blocks, eNB); + phy_procedures_eNB_uespec_RX_fromsplit(bufferZone, nb_blocks, eNB); } } From 43c07e401d3cdeddddb9620bcf1e9db004f9dd6e Mon Sep 17 00:00:00 2001 From: laurent Date: Mon, 26 Aug 2019 21:14:25 +0200 Subject: [PATCH 031/240] fix SR report from UE->DU->CU, remain later failure in PUSCH allocation --- executables/main-fs6.c | 41 ++++++++++++++------- executables/split_headers.h | 7 ++++ openair1/PHY/LTE_TRANSPORT/pbch.c | 2 +- openair1/PHY/LTE_TRANSPORT/prach_common.c | 1 - openair1/PHY/LTE_TRANSPORT/transport_eNB.h | 2 +- openair1/PHY/LTE_TRANSPORT/uci_tools.c | 4 +- openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c | 34 +++++++++++++---- openair1/SCHED/fapi_l1.c | 2 +- openair1/SCHED/fapi_l1.h | 2 +- openair1/SCHED/phy_procedures_lte_eNb.c | 16 +++++--- targets/ARCH/rfsimulator/simulator.c | 2 +- 11 files changed, 79 insertions(+), 34 deletions(-) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index 845e5c6f5f..bb88c1d61e 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -171,7 +171,7 @@ void prach_eNB_fromsplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB) { } } -void sendFs6Ulharq(int UEid, PHY_VARS_eNB *eNB, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask) { +void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, uint16_t rnti, int32_t stat) { static int current_fsf=-1; int fsf=frame*16+subframe; uint8_t *bufferZone=eNB->FS6bufferZone; @@ -200,16 +200,22 @@ void sendFs6Ulharq(int UEid, PHY_VARS_eNB *eNB, int frame, int subframe, uint8_ curBlock++; } + LOG_D(PHY,"FS6 du, block: %d: adding ul harq/sr: %d, rnti: %d, ueid: %d\n", + curBlock, type, rnti, UEid); commonUDP_t *newUDPheader=(commonUDP_t *) firstFreeByte; fs6_ul_uespec_uci_element_t *tmp=(fs6_ul_uespec_uci_element_t *)(hULUEuci(newUDPheader)+1); tmp+=hULUEuci(newUDPheader)->nb_active_ue; + tmp->type=type; tmp->UEid=UEid; tmp->frame=frame; tmp->subframe=subframe; - memcpy(tmp->harq_ack, harq_ack, 4); + if (harq_ack != NULL) + memcpy(tmp->harq_ack, harq_ack, 4); tmp->tdd_mapping_mode=tdd_mapping_mode; tmp->tdd_multiplexing_mask=tdd_multiplexing_mask; tmp->n0_subband_power_dB=eNB->measurements.n0_subband_power_dB[0][0]; + tmp->rnti=rnti; + tmp->stat=stat; hULUEuci(newUDPheader)->nb_active_ue++; newUDPheader->contentBytes+=sizeof(fs6_ul_uespec_uci_element_t); } @@ -636,12 +642,19 @@ void recvFs6Ul(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB) { } else if ( type == fs6ULcch ) { int nb_uci=hULUEuci(bufPtr)->nb_active_ue; fs6_ul_uespec_uci_element_t *tmp=(fs6_ul_uespec_uci_element_t *)(hULUEuci(bufPtr)+1); - - for (int i=0; i < nb_uci ; i++) { + for (int j=0; j < nb_uci ; j++) { + LOG_D(PHY,"FS6 cu, block: %d/%d: received ul harq/sr: %d, rnti: %d, ueid: %d\n", + i, j, type, tmp->rnti, tmp->UEid); eNB->measurements.n0_subband_power_dB[0][0]=tmp->n0_subband_power_dB; - fill_uci_harq_indication (tmp->UEid, eNB, &eNB->uci_vars[tmp->UEid], - tmp->frame, tmp->subframe, tmp->harq_ack, - tmp->tdd_mapping_mode, tmp->tdd_multiplexing_mask); + + if ( tmp->type == fs6ULindicationHarq ) + fill_uci_harq_indication (tmp->UEid, eNB, &eNB->uci_vars[tmp->UEid], + tmp->frame, tmp->subframe, tmp->harq_ack, + tmp->tdd_mapping_mode, tmp->tdd_multiplexing_mask); + else if ( tmp->type == fs6ULindicationSr ) + fill_sr_indication(tmp->UEid, eNB,tmp->rnti,tmp->frame,tmp->subframe,tmp->stat); + else + LOG_E(PHY, "Split FS6: impossible UL harq type\n"); tmp++; } } else @@ -655,6 +668,13 @@ void recvFs6Ul(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB) { void phy_procedures_eNB_uespec_RX_fromsplit(uint8_t *bufferZone, int nbBlocks,PHY_VARS_eNB *eNB) { // The configuration arrived in Dl, so we can extract the UL data recvFs6Ul(bufferZone, nbBlocks, eNB); + + // dirty memory allocation in OAI... + for (int i = 0; i < NUMBER_OF_UCI_VARS_MAX; i++) + if ( eNB->uci_vars[i].frame == eNB->proc.frame_rx && + eNB->uci_vars[i].subframe == eNB->proc.subframe_rx ) + eNB->uci_vars[i].active=0; + pusch_procedures_fromsplit(bufferZone, nbBlocks, eNB); } @@ -1025,13 +1045,8 @@ void phy_procedures_eNB_TX_tosplit(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; if (ulsch->rnti>0) { - LOG_I(PHY,"check in UL scheduled harq %d: rnti %d, tx frame %d/%d, ulsch: %d, %d/%d (handled: %d)\n", + LOG_D(PHY,"check in UL scheduled harq %d: rnti %d, tx frame %d/%d, ulsch: %d, %d/%d (handled: %d)\n", harq_pid, ulsch->rnti, frame, subframe, ulsch_harq->status, ulsch_harq->frame, ulsch_harq->subframe, ulsch_harq->handled); - - for (int k=0; k<8; k++) - if ( ulsch->harq_processes[k]->status == ACTIVE) - LOG_I(PHY,"check in UL scheduledi (harq_pid %d): rnti %d, tx frame %d/%d, ulsch: %d, %d/%d (handled: %d)\n", k, - ulsch->rnti, frame, subframe, ulsch->harq_processes[k]->status, ulsch->harq_processes[k]->frame, ulsch->harq_processes[k]->subframe, ulsch->harq_processes[k]->handled); } for (int k=0; k<8; k++) { diff --git a/executables/split_headers.h b/executables/split_headers.h index 0fed9d63c8..576a3854a1 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -67,6 +67,8 @@ enum pckType { fs6ULConfigCCH=27, fs6ULsch=28, fs6ULcch=29, + fs6ULindicationHarq=40, + fs6ULindicationSr=41, }; typedef struct { @@ -132,6 +134,7 @@ typedef struct { } fs6_ul_uespec_t; typedef struct { + enum pckType type:8; int UEid; int frame; int subframe; @@ -139,6 +142,8 @@ typedef struct { uint8_t tdd_mapping_mode; uint16_t tdd_multiplexing_mask; unsigned short n0_subband_power_dB; + uint16_t rnti; + int32_t stat; } fs6_ul_uespec_uci_element_t; typedef struct { @@ -174,6 +179,8 @@ static inline void *commonUDPdata(uint8_t *ptr) { } void setAllfromTS(uint64_t TS); +void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, uint16_t rnti, int32_t stat); +void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen); void *cu_fs6(void *arg); void *du_fs6(void *arg); void fill_rf_config(RU_t *ru, char *rf_config_file); diff --git a/openair1/PHY/LTE_TRANSPORT/pbch.c b/openair1/PHY/LTE_TRANSPORT/pbch.c index d852248b63..37997c94b4 100644 --- a/openair1/PHY/LTE_TRANSPORT/pbch.c +++ b/openair1/PHY/LTE_TRANSPORT/pbch.c @@ -195,7 +195,7 @@ int generate_pbch(LTE_eNB_PBCH *eNB_pbch, pbch_E = (frame_parms->Ncp==NORMAL) ? 1920 : 1728; //RE/RB * #RB * bits/RB (QPSK) // pbch_E_bytes = pbch_coded_bits>>3; - LOG_D(PHY,"%s(eNB_pbch:%p txdataF:%p amp:%d frame_parms:%p pbch_pdu:%p frame_mod4:%d)\n", __FUNCTION__, eNB_pbch, txdataF, amp, frame_parms, pbch_pdu, frame_mod4); + LOG_D(PHY,"%s(eNB_pbch:%p txdataF:%p amp:%d frame_parms:%p pbch_pdu:%p frame_mod4:%d)\n", __FUNCTION__, eNB_pbch, txdataF, amp, frame_parms, pbch_pdu, frame_mod4==0); if (frame_mod4==0) { bzero(pbch_a,PBCH_A>>3); diff --git a/openair1/PHY/LTE_TRANSPORT/prach_common.c b/openair1/PHY/LTE_TRANSPORT/prach_common.c index 32c37842b5..5f7a904db1 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach_common.c +++ b/openair1/PHY/LTE_TRANSPORT/prach_common.c @@ -36,7 +36,6 @@ #include "common/utils/LOG/vcd_signal_dumper.h" -#define PRACH_DEBUG uint16_t NCS_unrestricted[16] = {0,13,15,18,22,26,32,38,46,59,76,93,119,167,279,419}; uint16_t NCS_restricted[15] = {15,18,22,26,32,38,46,55,68,82,100,128,158,202,237}; // high-speed case uint16_t NCS_4[7] = {2,4,6,8,10,12,15}; diff --git a/openair1/PHY/LTE_TRANSPORT/transport_eNB.h b/openair1/PHY/LTE_TRANSPORT/transport_eNB.h index 4caca45acd..e1c68cc055 100644 --- a/openair1/PHY/LTE_TRANSPORT/transport_eNB.h +++ b/openair1/PHY/LTE_TRANSPORT/transport_eNB.h @@ -274,7 +274,7 @@ typedef struct { /// Pointers to transport block segments uint8_t *c[MAX_NUM_ULSCH_SEGMENTS]; /// RTC values for each segment (for definition see 36-212 V8.6 2009-03, p.15) - uint32_t RTCC[MAX_NUM_ULSCH_SEGMENTS]; + uint32_t RTC[MAX_NUM_ULSCH_SEGMENTS]; /// Current Number of Symbols uint8_t Nsymb_pusch; /// SRS active flag diff --git a/openair1/PHY/LTE_TRANSPORT/uci_tools.c b/openair1/PHY/LTE_TRANSPORT/uci_tools.c index c301c8510f..08addbb635 100644 --- a/openair1/PHY/LTE_TRANSPORT/uci_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/uci_tools.c @@ -49,7 +49,9 @@ int16_t find_uci(uint16_t rnti, int frame, int subframe, PHY_VARS_eNB *eNB,find_ else if ((eNB->uci_vars[i].active == 0) && (first_free_index==-1)) first_free_index=i; } if (type == SEARCH_EXIST) return(-1); - else return(first_free_index); + if (first_free_index==-1) + LOG_E(MAC,"UCI table is full\n"); + return(first_free_index); } diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index 59fd9b1378..fbbe9eadbe 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -44,9 +44,10 @@ //#define DEBUG_ULSCH_DECODING #include "targets/RT/USER/rt_wrapper.h" #include "transport_proto.h" +#include extern WORKER_CONF_t get_thread_worker_conf(void); -void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen); + void free_eNB_ulsch(LTE_eNB_ULSCH_t *ulsch) { int i,r; @@ -275,7 +276,7 @@ int ulsch_decoding_data_2thread0(td_params *tdp) { Kr_bytes = Kr>>3; memset(&dummy_w[r][0],0,3*(6144+64)*sizeof(short)); - ulsch_harq->RTCC[r] = generate_dummy_w(4+(Kr_bytes*8), + ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8), (uint8_t *)&dummy_w[r][0], (r==0) ? ulsch_harq->F : 0); #ifdef DEBUG_ULSCH_DECODING @@ -287,7 +288,7 @@ int ulsch_decoding_data_2thread0(td_params *tdp) { ulsch_harq->Nl); #endif - if (lte_rate_matching_turbo_rx(ulsch_harq->RTCC[r], + if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r], G, ulsch_harq->w[r], (uint8_t *) &dummy_w[r][0], @@ -449,7 +450,7 @@ int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr Kr_bytes = Kr>>3; memset(&dummy_w[r][0],0,3*(6144+64)*sizeof(short)); - ulsch_harq->RTCC[r] = generate_dummy_w(4+(Kr_bytes*8), + ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8), (uint8_t *)&dummy_w[r][0], (r==0) ? ulsch_harq->F : 0); #ifdef DEBUG_ULSCH_DECODING @@ -462,7 +463,7 @@ int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr #endif start_meas(&eNB->ulsch_rate_unmatching_stats); - if (lte_rate_matching_turbo_rx(ulsch_harq->RTCC[r], + if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r], G, ulsch_harq->w[r], (uint8_t *) &dummy_w[r][0], @@ -572,7 +573,7 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) Kr_bytes = Kr>>3; memset(&dummy_w[r][0],0,3*(6144+64)*sizeof(short)); - ulsch_harq->RTCC[r] = generate_dummy_w(4+(Kr_bytes*8), + ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8), (uint8_t *)&dummy_w[r][0], (r==0) ? ulsch_harq->F : 0); #ifdef DEBUG_ULSCH_DECODING @@ -585,7 +586,7 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) #endif start_meas(&eNB->ulsch_rate_unmatching_stats); - if (lte_rate_matching_turbo_rx(ulsch_harq->RTCC[r], + if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r], G, ulsch_harq->w[r], (uint8_t *) &dummy_w[r][0], @@ -620,8 +621,24 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) if ( getenv("fs6") != NULL && strncasecmp( getenv("fs6"), "du", 2) == 0 ) { // r is the segment id, // Kr is the segment length in short -// *3 because LTE redudancy scheme + // *3 because LTE redudancy scheme sendFs6Ul(eNB, UE_id, harq_pid, r, &ulsch_harq->d[r][96], Kr*sizeof(int16_t)*3); + LOG_D(PHY, "Cu should decode in %d iter\n",tc(&ulsch_harq->d[r][96], + NULL, + ulsch_harq->c[r], + NULL, + Kr, + ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS, + crc_type, + (r==0) ? ulsch_harq->F : 0, + &eNB->ulsch_tc_init_stats, + &eNB->ulsch_tc_alpha_stats, + &eNB->ulsch_tc_beta_stats, + &eNB->ulsch_tc_gamma_stats, + &eNB->ulsch_tc_ext_stats, + &eNB->ulsch_tc_intl1_stats, + &eNB->ulsch_tc_intl2_stats)); + return 0; } @@ -642,6 +659,7 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) &eNB->ulsch_tc_intl1_stats, &eNB->ulsch_tc_intl2_stats); stop_meas(&eNB->ulsch_turbo_decoding_stats); + LOG_D(PHY,"turbo decode in %d iter\n",ret); // Reassembly of Transport block here diff --git a/openair1/SCHED/fapi_l1.c b/openair1/SCHED/fapi_l1.c index 5f8b4ec3db..41c6554c8f 100644 --- a/openair1/SCHED/fapi_l1.c +++ b/openair1/SCHED/fapi_l1.c @@ -720,7 +720,7 @@ void handle_nfapi_ul_pdu(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, } else if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE) { AssertFatal(1==0,"NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE not handled yet\n"); } else if (ul_config_pdu->pdu_type == NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE) { - AssertFatal((UE_id = find_uci(ul_config_pdu->uci_sr_pdu.ue_information.ue_information_rel8.rnti, + AssertFatal((UE_id = find_uci(ul_config_pdu->uci_sr_pdu.ue_information.ue_information_rel8.rnti, proc->frame_tx,proc->subframe_tx,eNB,SEARCH_EXIST_OR_FREE))>=0, "No available UE UCI for rnti %x\n",ul_config_pdu->uci_sr_pdu.ue_information.ue_information_rel8.rnti); handle_uci_sr_pdu(eNB,UE_id,ul_config_pdu,frame,subframe,srs_present); diff --git a/openair1/SCHED/fapi_l1.h b/openair1/SCHED/fapi_l1.h index 77c254b13f..0314fcc322 100644 --- a/openair1/SCHED/fapi_l1.h +++ b/openair1/SCHED/fapi_l1.h @@ -40,7 +40,7 @@ void fill_uci_harq_indication(int UEid, PHY_VARS_eNB *eNB,LTE_eNB_UCI *uci,int frame,int subframe,uint8_t *harq_ack,uint8_t tdd_mapping_mode,uint16_t tdd_multiplexing_mask); void fill_ulsch_harq_indication(PHY_VARS_eNB *eNB,LTE_UL_eNB_HARQ_t *ulsch_harq,uint16_t rnti, int frame,int subframe,int bundling); void fill_ulsch_cqi_indication(PHY_VARS_eNB *eNB,uint16_t frame,uint8_t subframe,LTE_UL_eNB_HARQ_t *ulsch_harq,uint16_t rnti); -void fill_sr_indication(PHY_VARS_eNB *eNB,uint16_t rnti,int frame,int subframe,uint32_t stat); +void fill_sr_indication(int UEid, PHY_VARS_eNB *eNB,uint16_t rnti,int frame,int subframe,uint32_t stat); void fill_rx_indication(PHY_VARS_eNB *eNB,int UE_id,int frame,int subframe); void fill_crc_indication(PHY_VARS_eNB *eNB,int UE_id,int frame,int subframe,uint8_t crc_flag); void handle_nfapi_dci_dl_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t *proc,nfapi_dl_config_request_pdu_t *dl_config_pdu); diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 4764ede395..e139994514 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -46,7 +46,7 @@ #include #include "intertask_interface.h" -void sendFs6Ulharq(int UEid, PHY_VARS_eNB *eNB, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask); +#include nfapi_ue_release_request_body_t release_rntis; @@ -590,7 +590,11 @@ void srs_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { } } -void fill_sr_indication(PHY_VARS_eNB *eNB,uint16_t rnti,int frame,int subframe,uint32_t stat) { +void fill_sr_indication(int UEid, PHY_VARS_eNB *eNB,uint16_t rnti,int frame,int subframe,uint32_t stat) { + if ( getenv("fs6") != NULL && strncasecmp( getenv("fs6"), "du", 2) == 0 ) { + sendFs6Ulharq(fs6ULindicationSr, UEid, eNB, frame, subframe, NULL,0,0, rnti, stat); + return; + } pthread_mutex_lock(&eNB->UL_INFO_mutex); nfapi_sr_indication_t *sr_ind = &eNB->UL_INFO.sr_ind; nfapi_sr_indication_body_t *sr_ind_body = &sr_ind->sr_indication_body; @@ -706,7 +710,7 @@ uci_procedures(PHY_VARS_eNB *eNB, if (uci->type == SR) { if (SR_payload == 1) { - fill_sr_indication(eNB,uci->rnti,frame,subframe,metric_SR); + fill_sr_indication(i, eNB,uci->rnti,frame,subframe,metric_SR); break; } else { break; @@ -742,7 +746,7 @@ uci_procedures(PHY_VARS_eNB *eNB, /* cancel SR detection if reception on n1_pucch0 is better than on SR PUCCH resource index, otherwise send it up to MAC */ if (uci->type==HARQ_SR && metric[0] > metric_SR) SR_payload = 0; - else if (SR_payload == 1) fill_sr_indication(eNB,uci->rnti,frame,subframe,metric_SR); + else if (SR_payload == 1) fill_sr_indication(i, eNB,uci->rnti,frame,subframe,metric_SR); if (uci->type==HARQ_SR && metric[0] <= metric_SR) { /* when transmitting ACK/NACK on SR PUCCH resource index, SR payload is always 1 */ @@ -793,7 +797,7 @@ uci_procedures(PHY_VARS_eNB *eNB, ); if (uci->type==HARQ_SR && metric[0] > metric_SR) SR_payload = 0; - else if (SR_payload == 1) fill_sr_indication(eNB,uci->rnti,frame,subframe,metric_SR); + else if (SR_payload == 1) fill_sr_indication(i, eNB,uci->rnti,frame,subframe,metric_SR); if (uci->type==HARQ_SR && metric[0] <= metric_SR) { SR_payload = 1; @@ -1757,7 +1761,7 @@ void fill_ulsch_harq_indication (PHY_VARS_eNB *eNB, LTE_UL_eNB_HARQ_t *ulsch_har void fill_uci_harq_indication (int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask) { if ( getenv("fs6") != NULL && strncasecmp( getenv("fs6"), "du", 2) == 0 ) { - sendFs6Ulharq(UEid, eNB, frame, subframe, harq_ack, tdd_mapping_mode, tdd_multiplexing_mask); + sendFs6Ulharq(fs6ULindicationHarq, UEid, eNB, frame, subframe, harq_ack, tdd_mapping_mode, tdd_multiplexing_mask, 0, 0); return; } diff --git a/targets/ARCH/rfsimulator/simulator.c b/targets/ARCH/rfsimulator/simulator.c index d308486096..c8469adbb2 100644 --- a/targets/ARCH/rfsimulator/simulator.c +++ b/targets/ARCH/rfsimulator/simulator.c @@ -487,7 +487,7 @@ 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, 10)) { + if (!flushInput(t, 100)) { for (int x=0; x < nbAnt; x++) memset(samplesVoid[x],0,sampleToByte(nsamps,1)); From f1b677f849e2e72276ed86f617396620c044df42 Mon Sep 17 00:00:00 2001 From: laurent Date: Tue, 27 Aug 2019 18:47:12 +0200 Subject: [PATCH 032/240] Remove useless differences with regular OAI, enhance the build to be compatible with regular binaries --- cmake_targets/CMakeLists.txt | 10 +++++++++- openair1/PHY/LTE_TRANSPORT/dci_tools.c | 12 ++++++------ openair1/PHY/LTE_TRANSPORT/transport_eNB.h | 2 +- openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c | 17 ++++++++++++----- openair1/PHY/LTE_UE_TRANSPORT/ulsch_coding.c | 5 +++++ openair1/SCHED/phy_procedures_lte_eNb.c | 4 ++++ targets/RT/USER/lte-ru.c | 7 +++---- targets/RT/USER/lte-softmodem.c | 5 +---- 8 files changed, 41 insertions(+), 21 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 76be8cf250..fd3364dec8 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -1059,6 +1059,10 @@ set(SCHED_SRC add_library(SCHED_LIB ${SCHED_SRC}) add_dependencies(SCHED_LIB rrc_flag) +add_library(SCHED_LIB_FS6 ${SCHED_SRC}) +target_compile_definitions(SCHED_LIB_FS6 PRIVATE FS6=1) +add_dependencies(SCHED_LIB_FS6 rrc_flag) + set(SCHED_SRC_RU ${OPENAIR1_DIR}/SCHED/ru_procedures.c ${OPENAIR1_DIR}/SCHED/prach_procedures.c @@ -1290,6 +1294,9 @@ endif () add_library(PHY_COMMON ${PHY_SRC_COMMON}) add_dependencies(PHY_COMMON rrc_flag) add_library(PHY ${PHY_SRC}) +add_library(PHY_FS6 ${PHY_SRC}) +target_compile_definitions(PHY_FS6 PRIVATE FS6=1) + add_dependencies(PHY rrc_flag) add_library(PHY_UE ${PHY_SRC_UE}) add_dependencies(PHY_UE rrc_flag) @@ -2116,11 +2123,12 @@ add_executable(ocp-softmodem ${CONFIG_SOURCES} ${SHLIB_LOADER_SOURCES} ) +target_compile_definitions(ocp-softmodem PRIVATE FS6=1) add_dependencies(ocp-softmodem rrc_flag s1ap_flag x2_flag) target_link_libraries (ocp-softmodem -Wl,--start-group - RRC_LIB S1AP_LIB S1AP_ENB F1AP_LIB F1AP X2AP_LIB X2AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB SCHED_RU_LIB PHY_COMMON PHY PHY_RU LFDS L2 + RRC_LIB S1AP_LIB S1AP_ENB F1AP_LIB F1AP X2AP_LIB X2AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB_FS6 SCHED_RU_LIB PHY_COMMON PHY_FS6 PHY_RU LFDS L2 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} ${FSPT_MSG_LIB} ${PROTO_AGENT_LIB} LFDS7 NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB -Wl,--end-group z dl) diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c index 476e255fef..29bbd774a1 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c @@ -307,7 +307,7 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t dlsch0_harq->codeword = 0; dlsch1_harq = dlsch1->harq_processes[rel8->harq_process]; dlsch1_harq->codeword = 1; - //dlsch0->subframe_tx[subframe] = 1; + dlsch0->subframe_tx[subframe] = 1; LOG_D(PHY,"NFAPI: SFN/SF:%04d%d proc:TX:SFN/SF:%04d%d dlsch0[rnti:%x harq_mask:%04x] dci_pdu[rnti:%x rnti_type:%d harq_process:%d ndi1:%d] dlsch0_harq[round:%d harq_mask:%x ndi:%d]\n", frame,subframe, @@ -658,7 +658,7 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t dlsch0_harq->codeword = 0; // printf("DCI: Setting subframe_tx for subframe %d\n",subframe); - //dlsch0->subframe_tx[subframe] = 1; + dlsch0->subframe_tx[subframe] = 1; conv_rballoc (rel8->resource_allocation_type, rel8->resource_block_coding, fp->N_RB_DL, dlsch0_harq->rb_alloc); @@ -868,7 +868,7 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t dlsch0_harq = dlsch0->harq_processes[rel8->harq_process]; dlsch1_harq = dlsch1->harq_processes[rel8->harq_process]; - //dlsch0->subframe_tx[subframe] = 1; + dlsch0->subframe_tx[subframe] = 1; dlsch0->harq_ids[frame%2][subframe] = rel8->harq_process; dlsch1->harq_ids[frame%2][subframe] = rel8->harq_process; @@ -1316,7 +1316,7 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t } if (dlsch0 != NULL) { - //dlsch0->subframe_tx[subframe] = 1; + dlsch0->subframe_tx[subframe] = 1; dlsch0->harq_ids[frame%2][subframe] = rel8->harq_process; } @@ -1723,7 +1723,7 @@ void fill_mdci_and_dlsch(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,mDCI_ALLOC_t *dc dlsch0_harq->codeword = 0; // printf("DCI: Setting subframe_tx for subframe %d\n",subframe); - //dlsch0->subframe_tx[(subframe + 2) % 10] = 1; + dlsch0->subframe_tx[(subframe + 2) % 10] = 1; LOG_D(PHY,"PDSCH : resource_block_coding %x\n",rel13->resource_block_coding); conv_eMTC_rballoc (rel13->resource_block_coding, @@ -1746,7 +1746,7 @@ void fill_mdci_and_dlsch(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,mDCI_ALLOC_t *dc dlsch0_harq->dl_power_off = 1; - //dlsch0->subframe_tx[subframe] = 1; + dlsch0->subframe_tx[subframe] = 1; if (dlsch0->rnti != rel13->rnti) { // if rnti of dlsch is not the same as in the config, this is a new entry dlsch0_harq->round = 0; dlsch0->harq_mask =0; diff --git a/openair1/PHY/LTE_TRANSPORT/transport_eNB.h b/openair1/PHY/LTE_TRANSPORT/transport_eNB.h index e1c68cc055..e76939e8af 100644 --- a/openair1/PHY/LTE_TRANSPORT/transport_eNB.h +++ b/openair1/PHY/LTE_TRANSPORT/transport_eNB.h @@ -158,7 +158,7 @@ typedef struct { /// HARQ process mask, indicates which processes are currently active uint16_t harq_mask; /// Indicator of TX activation per subframe. Used during PUCCH detection for ACK/NAK. - //uint8_t subframe_tx[10]; + uint8_t subframe_tx[10]; /// First CCE of last PDSCH scheduling per subframe. Again used during PUCCH detection for ACK/NAK. uint8_t nCCE[10]; /// Process ID's per subframe. Used to associate received ACKs on PUSCH/PUCCH to DLSCH harq process ids diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index fbbe9eadbe..cbf1e887b5 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -617,13 +617,13 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) crc_type = CRC24_A; else crc_type = CRC24_B; - +#ifdef FS6 if ( getenv("fs6") != NULL && strncasecmp( getenv("fs6"), "du", 2) == 0 ) { // r is the segment id, // Kr is the segment length in short // *3 because LTE redudancy scheme sendFs6Ul(eNB, UE_id, harq_pid, r, &ulsch_harq->d[r][96], Kr*sizeof(int16_t)*3); - LOG_D(PHY, "Cu should decode in %d iter\n",tc(&ulsch_harq->d[r][96], + int iter=tc(&ulsch_harq->d[r][96], NULL, ulsch_harq->c[r], NULL, @@ -637,11 +637,18 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) &eNB->ulsch_tc_gamma_stats, &eNB->ulsch_tc_ext_stats, &eNB->ulsch_tc_intl1_stats, - &eNB->ulsch_tc_intl2_stats)); + &eNB->ulsch_tc_intl2_stats); + LOG_D(PHY, "Cu should decode in %d iter\n",iter); + if ( iter == 5 ) { + for (int i=0; i < Kr; i++ ) + printf("%hx:", ulsch_harq->d[r][96+i]); + printf("\n"); + } return 0; } - + + #endif start_meas(&eNB->ulsch_turbo_decoding_stats); ret = tc(&ulsch_harq->d[r][96], NULL, @@ -788,7 +795,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, Q_m = ulsch_harq->Qm; G = nb_rb * (12 * Q_m) * ulsch_harq->Nsymb_pusch; //#ifdef DEBUG_ULSCH_DECODING - LOG_D(PHY,"[PUSCH %d] Frame %d, Subframe %d: ulsch_decoding (Nid_cell %d, rnti %x, x2 %x): A %d, round %d, RV %d, O_r1 %d, O_RI %d, O_ACK %d, G %d, Q_m %d Nsymb_pusch %d nb_rb %d\n", + LOG_D(PHY,"[PUSCH harq %d] Frame %d, Subframe %d: ulsch_decoding (Nid_cell %d, rnti %x, x2 %x): TBS %d, round %d, RV %d, O_r1 %d, O_RI %d, O_ACK %d, G %d, Q_m %d Nsymb_pusch %d nb_rb %d\n", harq_pid, proc->frame_rx,subframe, frame_parms->Nid_cell,ulsch->rnti,x2, diff --git a/openair1/PHY/LTE_UE_TRANSPORT/ulsch_coding.c b/openair1/PHY/LTE_UE_TRANSPORT/ulsch_coding.c index cc1f762e70..53c45b2d2f 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/ulsch_coding.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/ulsch_coding.c @@ -353,6 +353,11 @@ uint32_t ulsch_encoding(uint8_t *a, (r==0) ? ulsch->harq_processes[harq_pid]->F : 0 ); stop_meas(te_stats); +/* + for (int i=0; i< Kr ; i++ ) + printf("%hx", ulsch->harq_processes[harq_pid]->d[r][96+i]); + printf ("\n"); +*/ #ifdef DEBUG_ULSCH_CODING if (r==0) diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index e139994514..13ec2de771 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -591,10 +591,12 @@ void srs_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { } void fill_sr_indication(int UEid, PHY_VARS_eNB *eNB,uint16_t rnti,int frame,int subframe,uint32_t stat) { + #ifdef FS6 if ( getenv("fs6") != NULL && strncasecmp( getenv("fs6"), "du", 2) == 0 ) { sendFs6Ulharq(fs6ULindicationSr, UEid, eNB, frame, subframe, NULL,0,0, rnti, stat); return; } + #endif pthread_mutex_lock(&eNB->UL_INFO_mutex); nfapi_sr_indication_t *sr_ind = &eNB->UL_INFO.sr_ind; nfapi_sr_indication_body_t *sr_ind_body = &sr_ind->sr_indication_body; @@ -1760,10 +1762,12 @@ void fill_ulsch_harq_indication (PHY_VARS_eNB *eNB, LTE_UL_eNB_HARQ_t *ulsch_har } void fill_uci_harq_indication (int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask) { + #ifdef FS6 if ( getenv("fs6") != NULL && strncasecmp( getenv("fs6"), "du", 2) == 0 ) { sendFs6Ulharq(fs6ULindicationHarq, UEid, eNB, frame, subframe, harq_ack, tdd_mapping_mode, tdd_multiplexing_mask, 0, 0); return; } + #endif int UE_id=find_dlsch(uci->rnti,eNB,SEARCH_EXIST); diff --git a/targets/RT/USER/lte-ru.c b/targets/RT/USER/lte-ru.c index 89abd12499..b1894be28f 100644 --- a/targets/RT/USER/lte-ru.c +++ b/targets/RT/USER/lte-ru.c @@ -1202,7 +1202,8 @@ void wakeup_L1s(RU_t *ru) { ru->proc.emulate_rf_busy = 0; } -inline int wakeup_prach_ru(RU_t *ru) { + +void wakeup_prach_ru(RU_t *ru) { int ret; struct timespec wait; int time_ns = 5000000L; @@ -1234,11 +1235,10 @@ inline int wakeup_prach_ru(RU_t *ru) { } else LOG_W(PHY,"RU prach thread busy, skipping\n"); AssertFatal((ret=pthread_mutex_unlock( &ru->proc.mutex_prach ))==0,"mutex_unlock returns %d\n",ret); - return(0); } #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) -inline int wakeup_prach_ru_br(RU_t *ru) { +void wakeup_prach_ru_br(RU_t *ru) { int ret; struct timespec wait; int time_ns = 5000000L; @@ -1264,7 +1264,6 @@ inline int wakeup_prach_ru_br(RU_t *ru) { } else LOG_W(PHY,"RU prach thread busy, skipping\n"); AssertFatal((ret=pthread_mutex_unlock( &ru->proc.mutex_prach_br ))==0,"mutex_unlock returns %d\n",ret); - return(0); } #endif diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 85862f9430..b1d2bd4e3f 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -593,10 +593,7 @@ int main( int argc, char **argv ) { /* initializes PDCP and sets correct RLC Request/PDCP Indication callbacks * for monolithic/F1 modes */ - //if ( getenv("fs6") != NULL && strncasecmp( getenv("fs6"), "du", 2) == 0 ) - //RC.rrc[0]->node_type=ngran_eNB_DU; - - init_pdcp(); + init_pdcp(); if (create_tasks(1) < 0) { printf("cannot create ITTI tasks\n"); From f112de54b1d7b4a56662a22ae0ae085ab45ee5d3 Mon Sep 17 00:00:00 2001 From: laurent Date: Wed, 28 Aug 2019 09:35:27 +0200 Subject: [PATCH 033/240] fix -O3 issue; add FS6_REMOTE_IP to set distant CU or DU --- cmake_targets/CMakeLists.txt | 2 +- executables/main-fs6.c | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index fd3364dec8..4897146918 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -184,7 +184,7 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath -Wl,${CMAKE_CU # set a flag for changes in the source code # these changes are related to hardcoded path to include .h files set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -g3 -DMALLOC_CHECK_=3") -set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS} -g3 -DMALLOC_CHECK_=3 -O0") +set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS} -g3 -DMALLOC_CHECK_=3 -O3") set(GIT_BRANCH "UNKNOWN") diff --git a/executables/main-fs6.c b/executables/main-fs6.c index bb88c1d61e..ff932d71ad 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -1280,7 +1280,8 @@ void UL_cu_fs6(RU_t *ru, uint64_t *TS) { setAllfromTS(hUDP(bufferZone)->timestamp); PHY_VARS_eNB *eNB = RC.eNB[0][0]; - prach_eNB_fromsplit(bufferZone, sizeof(bufferZone), eNB); + if (is_prach_subframe(&eNB->frame_parms, eNB->proc.frame_prach,eNB->proc.subframe_prach)>0) + prach_eNB_fromsplit(bufferZone, sizeof(bufferZone), eNB); release_UE_in_freeList(eNB->Mod_id); if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { @@ -1295,7 +1296,12 @@ void *cu_fs6(void *arg) { init_frame_parms(&ru->frame_parms,1); phy_init_RU(ru); wait_sync("ru_thread"); - AssertFatal(createUDPsock(NULL, CU_PORT, CU_IP, DU_PORT, &sockFS6), ""); + char * remoteIP; + if ( getenv("FS6_REMOTE_IP") ) + remoteIP=getenv("FS6_REMOTE_IP"); + else + remoteIP=DU_IP; + AssertFatal(createUDPsock(NULL, CU_PORT, remoteIP, DU_PORT, &sockFS6), ""); uint64_t timeStamp=0; while(1) { @@ -1315,7 +1321,12 @@ void *du_fs6(void *arg) { phy_init_RU(ru); openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); wait_sync("ru_thread"); - AssertFatal(createUDPsock(NULL, DU_PORT, DU_IP, CU_PORT, &sockFS6),""); + char * remoteIP; + if ( getenv("FS6_REMOTE_IP") ) + remoteIP=getenv("FS6_REMOTE_IP"); + else + remoteIP=CU_IP; + AssertFatal(createUDPsock(NULL, DU_PORT, remoteIP, CU_PORT, &sockFS6), ""); if (ru->start_rf) { if (ru->start_rf(ru) != 0) From 839a7997d18989428b0117458ecff4f6bd650d6b Mon Sep 17 00:00:00 2001 From: laurent Date: Thu, 29 Aug 2019 19:22:46 +0200 Subject: [PATCH 034/240] UE attach complete, added traces ulsch coding, remove temporary renaming --- executables/main-fs6.c | 63 ++++++++++++----- executables/split_headers.h | 5 ++ openair1/PHY/LTE_TRANSPORT/transport_eNB.h | 4 +- openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c | 73 +++++++++++--------- openair1/PHY/LTE_UE_TRANSPORT/ulsch_coding.c | 15 ++-- openair1/SCHED/phy_procedures_lte_eNb.c | 12 ++-- openair2/LAYER2/MAC/eNB_scheduler_fairRR.c | 2 +- 7 files changed, 107 insertions(+), 67 deletions(-) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index ff932d71ad..aa1b31d67f 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -171,7 +171,8 @@ void prach_eNB_fromsplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB) { } } -void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, uint16_t rnti, int32_t stat) { +void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, uint16_t rnti, + int32_t stat) { static int current_fsf=-1; int fsf=frame*16+subframe; uint8_t *bufferZone=eNB->FS6bufferZone; @@ -201,7 +202,7 @@ void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, int frame, in } LOG_D(PHY,"FS6 du, block: %d: adding ul harq/sr: %d, rnti: %d, ueid: %d\n", - curBlock, type, rnti, UEid); + curBlock, type, rnti, UEid); commonUDP_t *newUDPheader=(commonUDP_t *) firstFreeByte; fs6_ul_uespec_uci_element_t *tmp=(fs6_ul_uespec_uci_element_t *)(hULUEuci(newUDPheader)+1); tmp+=hULUEuci(newUDPheader)->nb_active_ue; @@ -209,8 +210,10 @@ void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, int frame, in tmp->UEid=UEid; tmp->frame=frame; tmp->subframe=subframe; + if (harq_ack != NULL) memcpy(tmp->harq_ack, harq_ack, 4); + tmp->tdd_mapping_mode=tdd_mapping_mode; tmp->tdd_multiplexing_mask=tdd_multiplexing_mask; tmp->n0_subband_power_dB=eNB->measurements.n0_subband_power_dB[0][0]; @@ -240,6 +243,9 @@ void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_ hULUE(newUDPheader)->type=fs6ULsch; hULUE(newUDPheader)->UE_id=UE_id; hULUE(newUDPheader)->harq_id=harq_pid; + memcpy(hULUE(newUDPheader)->ulsch_power, + eNB->pusch_vars[UE_id]->ulsch_power, + sizeof(int)*2); hULUE(newUDPheader)->segment=segmentID; memcpy(hULUE(newUDPheader)+1, data, dataLen); hULUE(newUDPheader)->segLen=dataLen; @@ -444,12 +450,12 @@ int ulsch_decoding_process(PHY_VARS_eNB *eNB, int UE_id, int llr8_flag) { Kr_bytes = Kr>>3; if (r==0) { - memcpy(ulsch_harq->bb, + memcpy(ulsch_harq->b, &ulsch_harq->c[0][(ulsch_harq->F>>3)], Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0)); offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0); } else { - memcpy(ulsch_harq->bb+offset, + memcpy(ulsch_harq->b+offset, ulsch_harq->c[r], Kr_bytes - ((ulsch_harq->C>1)?3:0)); offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); @@ -638,23 +644,28 @@ void recvFs6Ul(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB) { memcpy(&ulsch_harq->d[hULUE(bufPtr)->segment][96], hULUE(bufPtr)+1, hULUE(bufPtr)->segLen); + memcpy(eNB->pusch_vars[hULUE(bufPtr)->UE_id]->ulsch_power, + hULUE(bufPtr)->ulsch_power, + sizeof(int)*2); LOG_W(PHY,"Received ulsch data for: rnti:%d, fsf: %d/%d\n", ulsch->rnti, eNB->proc.frame_rx, eNB->proc.subframe_rx); } else if ( type == fs6ULcch ) { int nb_uci=hULUEuci(bufPtr)->nb_active_ue; fs6_ul_uespec_uci_element_t *tmp=(fs6_ul_uespec_uci_element_t *)(hULUEuci(bufPtr)+1); + for (int j=0; j < nb_uci ; j++) { - LOG_D(PHY,"FS6 cu, block: %d/%d: received ul harq/sr: %d, rnti: %d, ueid: %d\n", - i, j, type, tmp->rnti, tmp->UEid); + LOG_D(PHY,"FS6 cu, block: %d/%d: received ul harq/sr: %d, rnti: %d, ueid: %d\n", + i, j, type, tmp->rnti, tmp->UEid); eNB->measurements.n0_subband_power_dB[0][0]=tmp->n0_subband_power_dB; - - if ( tmp->type == fs6ULindicationHarq ) - fill_uci_harq_indication (tmp->UEid, eNB, &eNB->uci_vars[tmp->UEid], - tmp->frame, tmp->subframe, tmp->harq_ack, - tmp->tdd_mapping_mode, tmp->tdd_multiplexing_mask); - else if ( tmp->type == fs6ULindicationSr ) - fill_sr_indication(tmp->UEid, eNB,tmp->rnti,tmp->frame,tmp->subframe,tmp->stat); - else - LOG_E(PHY, "Split FS6: impossible UL harq type\n"); + + if ( tmp->type == fs6ULindicationHarq ) + fill_uci_harq_indication (tmp->UEid, eNB, &eNB->uci_vars[tmp->UEid], + tmp->frame, tmp->subframe, tmp->harq_ack, + tmp->tdd_mapping_mode, tmp->tdd_multiplexing_mask); + else if ( tmp->type == fs6ULindicationSr ) + fill_sr_indication(tmp->UEid, eNB,tmp->rnti,tmp->frame,tmp->subframe,tmp->stat); + else + LOG_E(PHY, "Split FS6: impossible UL harq type\n"); + tmp++; } } else @@ -668,11 +679,11 @@ void recvFs6Ul(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB) { void phy_procedures_eNB_uespec_RX_fromsplit(uint8_t *bufferZone, int nbBlocks,PHY_VARS_eNB *eNB) { // The configuration arrived in Dl, so we can extract the UL data recvFs6Ul(bufferZone, nbBlocks, eNB); - + // dirty memory allocation in OAI... for (int i = 0; i < NUMBER_OF_UCI_VARS_MAX; i++) if ( eNB->uci_vars[i].frame == eNB->proc.frame_rx && - eNB->uci_vars[i].subframe == eNB->proc.subframe_rx ) + eNB->uci_vars[i].subframe == eNB->proc.subframe_rx ) eNB->uci_vars[i].active=0; pusch_procedures_fromsplit(bufferZone, nbBlocks, eNB); @@ -739,6 +750,10 @@ void rcvFs6DL(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, int frame, i ulsch_harq->frame = frame; ulsch_harq->subframe = subframe; ulsch_harq->first_rb=hTxULUE(bufPtr)->first_rb; + ulsch_harq->O_RI=hTxULUE(bufPtr)->O_RI; + ulsch_harq->Or1=hTxULUE(bufPtr)->Or1; + ulsch_harq->Msc_initial=hTxULUE(bufPtr)->Msc_initial; + ulsch_harq->Nsymb_initial=hTxULUE(bufPtr)->Nsymb_initial; ulsch_harq->V_UL_DAI=hTxULUE(bufPtr)->V_UL_DAI; ulsch_harq->Qm=hTxULUE(bufPtr)->Qm; ulsch_harq->srs_active=hTxULUE(bufPtr)->srs_active; @@ -913,6 +928,10 @@ void appendFs6TxULUE(uint8_t *bufferZone, LTE_DL_FRAME_PARMS *fp, int curUE, LTE memcpy(hTxULUE(newUDPheader)->cba_rnti,ulsch->cba_rnti,sizeof(ulsch->cba_rnti));//NUM_MAX_CBA_GROUP]; cpyToDu(rnti); cpyToDuHarq(nb_rb); + cpyToDuHarq(Msc_initial); + cpyToDuHarq(Nsymb_initial); + cpyToDuHarq(O_RI); + cpyToDuHarq(Or1); cpyToDuHarq(first_rb); cpyToDuHarq(V_UL_DAI); cpyToDuHarq(Qm); @@ -1280,8 +1299,10 @@ void UL_cu_fs6(RU_t *ru, uint64_t *TS) { setAllfromTS(hUDP(bufferZone)->timestamp); PHY_VARS_eNB *eNB = RC.eNB[0][0]; + if (is_prach_subframe(&eNB->frame_parms, eNB->proc.frame_prach,eNB->proc.subframe_prach)>0) prach_eNB_fromsplit(bufferZone, sizeof(bufferZone), eNB); + release_UE_in_freeList(eNB->Mod_id); if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { @@ -1296,11 +1317,13 @@ void *cu_fs6(void *arg) { init_frame_parms(&ru->frame_parms,1); phy_init_RU(ru); wait_sync("ru_thread"); - char * remoteIP; + char *remoteIP; + if ( getenv("FS6_REMOTE_IP") ) remoteIP=getenv("FS6_REMOTE_IP"); else remoteIP=DU_IP; + AssertFatal(createUDPsock(NULL, CU_PORT, remoteIP, DU_PORT, &sockFS6), ""); uint64_t timeStamp=0; @@ -1321,11 +1344,13 @@ void *du_fs6(void *arg) { phy_init_RU(ru); openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); wait_sync("ru_thread"); - char * remoteIP; + char *remoteIP; + if ( getenv("FS6_REMOTE_IP") ) remoteIP=getenv("FS6_REMOTE_IP"); else remoteIP=CU_IP; + AssertFatal(createUDPsock(NULL, DU_PORT, remoteIP, CU_PORT, &sockFS6), ""); if (ru->start_rf) { diff --git a/executables/split_headers.h b/executables/split_headers.h index 576a3854a1..737358f51f 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -80,6 +80,10 @@ typedef struct { uint16_t nb_rb; uint8_t Qm; uint16_t first_rb; + uint8_t O_RI; + uint8_t Or1; + uint16_t Msc_initial; + uint8_t Nsymb_initial; uint8_t V_UL_DAI; uint8_t srs_active; uint32_t TBS; @@ -131,6 +135,7 @@ typedef struct { short harq_id; short segment; short segLen; + int ulsch_power[2]; } fs6_ul_uespec_t; typedef struct { diff --git a/openair1/PHY/LTE_TRANSPORT/transport_eNB.h b/openair1/PHY/LTE_TRANSPORT/transport_eNB.h index e76939e8af..dfa2a2f20b 100644 --- a/openair1/PHY/LTE_TRANSPORT/transport_eNB.h +++ b/openair1/PHY/LTE_TRANSPORT/transport_eNB.h @@ -266,11 +266,11 @@ typedef struct { /// coded RI bits int16_t q_RI[MAX_RI_PAYLOAD]; /// Concatenated "e"-sequences (for definition see 36-212 V8.6 2009-03, p.17-18) - int16_t eE[MAX_NUM_CHANNEL_BITS] __attribute__((aligned(32))); + int16_t e[MAX_NUM_CHANNEL_BITS] __attribute__((aligned(32))); /// Temporary h sequence to flag PUSCH_x/PUSCH_y symbols which are not scrambled uint8_t h[MAX_NUM_CHANNEL_BITS]; /// Pointer to the payload - uint8_t *bb; + uint8_t *b; /// Pointers to transport block segments uint8_t *c[MAX_NUM_ULSCH_SEGMENTS]; /// RTC values for each segment (for definition see 36-212 V8.6 2009-03, p.15) diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index cbf1e887b5..663b32b7fb 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -55,9 +55,9 @@ void free_eNB_ulsch(LTE_eNB_ULSCH_t *ulsch) { if (ulsch) { for (i=0; i<8; i++) { if (ulsch->harq_processes[i]) { - if (ulsch->harq_processes[i]->bb) { - free16(ulsch->harq_processes[i]->bb,MAX_ULSCH_PAYLOAD_BYTES); - ulsch->harq_processes[i]->bb = NULL; + if (ulsch->harq_processes[i]->b) { + free16(ulsch->harq_processes[i]->b,MAX_ULSCH_PAYLOAD_BYTES); + ulsch->harq_processes[i]->b = NULL; } for (r=0; rharq_processes[i]) { memset(ulsch->harq_processes[i],0,sizeof(LTE_UL_eNB_HARQ_t)); - ulsch->harq_processes[i]->bb = (uint8_t *)malloc16(MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); + ulsch->harq_processes[i]->b = (uint8_t *)malloc16(MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); - if (ulsch->harq_processes[i]->bb) - memset(ulsch->harq_processes[i]->bb,0,MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); + if (ulsch->harq_processes[i]->b) + memset(ulsch->harq_processes[i]->b,0,MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); else exit_flag=3; @@ -292,7 +292,7 @@ int ulsch_decoding_data_2thread0(td_params *tdp) { G, ulsch_harq->w[r], (uint8_t *) &dummy_w[r][0], - ulsch_harq->eE+r_offset, + ulsch_harq->e+r_offset, ulsch_harq->C, NSOFT, 0, //Uplink @@ -342,7 +342,7 @@ int ulsch_decoding_data_2thread0(td_params *tdp) { Kr = ulsch_harq->Kplus; Kr_bytes = Kr>>3; - memcpy(ulsch_harq->bb+offset, + memcpy(ulsch_harq->b+offset, ulsch_harq->c[r], Kr_bytes - ((ulsch_harq->C>1)?3:0)); offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); @@ -467,7 +467,7 @@ int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr G, ulsch_harq->w[r], (uint8_t *) &dummy_w[r][0], - ulsch_harq->eE+r_offset, + ulsch_harq->e+r_offset, ulsch_harq->C, NSOFT, 0, //Uplink @@ -523,12 +523,12 @@ int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr Kr_bytes = Kr>>3; if (r==0) { - memcpy(ulsch_harq->bb, + memcpy(ulsch_harq->b, &ulsch_harq->c[0][(ulsch_harq->F>>3)], Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0)); offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0); } else { - memcpy(ulsch_harq->bb+offset, + memcpy(ulsch_harq->b+offset, ulsch_harq->c[r], Kr_bytes - ((ulsch_harq->C>1)?3:0)); offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); @@ -555,7 +555,7 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id]; LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; int G = ulsch_harq->G; - unsigned int EE; + unsigned int E; decoder_if_t *tc; if (llr8_flag == 0) @@ -580,8 +580,7 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) printf("Rate Matching Segment %u (coded bits (G) %d,unpunctured/repeated bits %u, Q_m %d, nb_rb %d, Nl %d)...\n", r, G, Kr*3, - Q_m, - nb_rb, + ulsch_harq->Qm, ulsch_harq->Nl); #endif start_meas(&eNB->ulsch_rate_unmatching_stats); @@ -590,7 +589,7 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) G, ulsch_harq->w[r], (uint8_t *) &dummy_w[r][0], - ulsch_harq->eE+r_offset, + ulsch_harq->e+r_offset, ulsch_harq->C, NSOFT, 0, //Uplink @@ -600,13 +599,13 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) ulsch_harq->Qm, 1, r, - &EE)==-1) { + &E)==-1) { LOG_E(PHY,"ulsch_decoding.c: Problem in rate matching\n"); return(-1); } stop_meas(&eNB->ulsch_rate_unmatching_stats); - r_offset += EE; + r_offset += E; start_meas(&eNB->ulsch_deinterleaving_stats); sub_block_deinterleaving_turbo(4+Kr, &ulsch_harq->d[r][96], @@ -623,6 +622,7 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) // Kr is the segment length in short // *3 because LTE redudancy scheme sendFs6Ul(eNB, UE_id, harq_pid, r, &ulsch_harq->d[r][96], Kr*sizeof(int16_t)*3); +/* int iter=tc(&ulsch_harq->d[r][96], NULL, ulsch_harq->c[r], @@ -644,7 +644,7 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) printf("%hx:", ulsch_harq->d[r][96+i]); printf("\n"); } - +*/ return 0; } @@ -679,12 +679,12 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) Kr_bytes = Kr>>3; if (r==0) { - memcpy(ulsch_harq->bb, + memcpy(ulsch_harq->b, &ulsch_harq->c[0][(ulsch_harq->F>>3)], Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0)); offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0); } else { - memcpy(ulsch_harq->bb+offset, + memcpy(ulsch_harq->b+offset, ulsch_harq->c[r], Kr_bytes - ((ulsch_harq->C>1)?3:0)); offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); @@ -794,6 +794,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, A = ulsch_harq->TBS; Q_m = ulsch_harq->Qm; G = nb_rb * (12 * Q_m) * ulsch_harq->Nsymb_pusch; + LOG_D(PHY, "PUSCH nb_rb %d Q_m %d ulsch_harq->Nsymb_pusch %d\n",nb_rb, Q_m, ulsch_harq->Nsymb_pusch); //#ifdef DEBUG_ULSCH_DECODING LOG_D(PHY,"[PUSCH harq %d] Frame %d, Subframe %d: ulsch_decoding (Nid_cell %d, rnti %x, x2 %x): TBS %d, round %d, RV %d, O_r1 %d, O_RI %d, O_ACK %d, G %d, Q_m %d Nsymb_pusch %d nb_rb %d\n", harq_pid, @@ -848,6 +849,12 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, subframe); // Compute Q_ri Qprime = ulsch_harq->O_RI*ulsch_harq->Msc_initial*ulsch_harq->Nsymb_initial * ulsch->beta_offset_ri_times8; + LOG_D(PHY, "Qprime %d, O_RI %d, Msc %d, Nym %d beta %d\n", + Qprime, + ulsch_harq->O_RI, + ulsch_harq->Msc_initial, + ulsch_harq->Nsymb_initial, + ulsch->beta_offset_ri_times8); if (Qprime > 0 ) { if ((Qprime % (8*sumKr)) > 0) @@ -1224,8 +1231,8 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, j2+=2; } - ulsch_harq->eE[iprime++] = y[j2++]; - ulsch_harq->eE[iprime++] = y[j2++]; + ulsch_harq->e[iprime++] = y[j2++]; + ulsch_harq->e[iprime++] = y[j2++]; } break; @@ -1237,10 +1244,10 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, j2+=4; } - ulsch_harq->eE[iprime++] = y[j2++]; - ulsch_harq->eE[iprime++] = y[j2++]; - ulsch_harq->eE[iprime++] = y[j2++]; - ulsch_harq->eE[iprime++] = y[j2++]; + ulsch_harq->e[iprime++] = y[j2++]; + ulsch_harq->e[iprime++] = y[j2++]; + ulsch_harq->e[iprime++] = y[j2++]; + ulsch_harq->e[iprime++] = y[j2++]; } break; @@ -1252,12 +1259,12 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, j2+=6; } - ulsch_harq->eE[iprime++] = y[j2++]; - ulsch_harq->eE[iprime++] = y[j2++]; - ulsch_harq->eE[iprime++] = y[j2++]; - ulsch_harq->eE[iprime++] = y[j2++]; - ulsch_harq->eE[iprime++] = y[j2++]; - ulsch_harq->eE[iprime++] = y[j2++]; + ulsch_harq->e[iprime++] = y[j2++]; + ulsch_harq->e[iprime++] = y[j2++]; + ulsch_harq->e[iprime++] = y[j2++]; + ulsch_harq->e[iprime++] = y[j2++]; + ulsch_harq->e[iprime++] = y[j2++]; + ulsch_harq->e[iprime++] = y[j2++]; } break; @@ -1295,7 +1302,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, */ int16_t *yp,*ep; - for (iprime=0,yp=&y[j2],ep=&ulsch_harq->eE[0]; + for (iprime=0,yp=&y[j2],ep=&ulsch_harq->e[0]; iprimeharq_processes[harq_pid]->F : 0 ); stop_meas(te_stats); -/* - for (int i=0; i< Kr ; i++ ) - printf("%hx", ulsch->harq_processes[harq_pid]->d[r][96+i]); - printf ("\n"); -*/ #ifdef DEBUG_ULSCH_CODING if (r==0) @@ -451,6 +446,13 @@ uint32_t ulsch_encoding(uint8_t *a, Qprime = (ulsch->O + L) * ulsch->harq_processes[harq_pid]->Msc_initial*ulsch->harq_processes[harq_pid]->Nsymb_initial * ulsch->beta_offset_cqi_times8; else Qprime = 0; + LOG_D(PHY,"Qprime %d, O_RI %d + %d, Msc %d, Nym %d beta %d\n", + Qprime, + ulsch->O, L, + ulsch->harq_processes[harq_pid]->Msc_initial, + ulsch->harq_processes[harq_pid]->Nsymb_initial, + ulsch->beta_offset_cqi_times8); + if (Qprime > 0) { if ((Qprime % (8*sumKr)) > 0) @@ -460,7 +462,7 @@ uint32_t ulsch_encoding(uint8_t *a, } G = ulsch->harq_processes[harq_pid]->nb_rb * (12 * Q_m) * (ulsch->Nsymb_pusch); - + LOG_D(PHY,"G: rb %d * ( 12 * Qm %d ) * nsymb %d, Qprime %d, O_RI %d\n", ulsch->harq_processes[harq_pid]->nb_rb, Q_m, ulsch->Nsymb_pusch, Qprime, ulsch->O_RI); if (Qprime > (G - ulsch->O_RI)) Qprime = G - ulsch->O_RI; @@ -470,6 +472,7 @@ uint32_t ulsch_encoding(uint8_t *a, G = G - Q_RI - Q_CQI; + LOG_D(PHY,"new G: %d, Q_RI %d Q_CQI %d\n", G , Q_RI , Q_CQI); ulsch->harq_processes[harq_pid]->G = G; /* diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 13ec2de771..374cbb251a 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -410,10 +410,10 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, ul_frame = pdcch_alloc2ul_frame (fp, frame, subframe); // clear previous allocation information for all UEs - //for (i = 0; i < NUMBER_OF_UE_MAX; i++) { - //if (eNB->dlsch[i][0]) - //eNB->dlsch[i][0]->subframe_tx[subframe] = 0; - //} + for (i = 0; i < NUMBER_OF_UE_MAX; i++) { + if (eNB->dlsch[i][0]) + eNB->dlsch[i][0]->subframe_tx[subframe] = 0; + } /* TODO: check the following test - in the meantime it is put back as it was before */ //if ((ul_subframe < 10)&& @@ -549,7 +549,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, #endif ) { // clear subframe TX flag since UE is not scheduled for PDSCH in this subframe (so that we don't look for PUCCH later) - //dlsch0->subframe_tx[subframe]=0; + dlsch0->subframe_tx[subframe]=0; } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,0); @@ -1424,7 +1424,7 @@ void fill_rx_indication(PHY_VARS_eNB *eNB,int UE_id,int frame,int subframe) { pdu->rx_indication_rel8.tl.tag = NFAPI_RX_INDICATION_REL8_TAG; pdu->rx_indication_rel8.length = eNB->ulsch[UE_id]->harq_processes[harq_pid]->TBS>>3; pdu->rx_indication_rel8.offset = 1; // DJP - I dont understand - but broken unless 1 ???? 0; // filled in at the end of the UL_INFO formation - pdu->data = eNB->ulsch[UE_id]->harq_processes[harq_pid]->bb; + pdu->data = eNB->ulsch[UE_id]->harq_processes[harq_pid]->b; // estimate timing advance for MAC sync_pos = lte_est_timing_advance_pusch(eNB,UE_id); timing_advance_update = sync_pos; // - eNB->frame_parms.nb_prefix_samples/4; //to check diff --git a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c index c071c1f505..cc08f4f611 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c @@ -2836,7 +2836,7 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP, } if (tpc!=1) { - LOG_D(MAC,"[eNB %d] ULSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, snr/target snr %d/%d\n", + LOG_D(MAC,"[eNB %d] ULSCH schedulerRR: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, snr/target snr %d/%d\n", module_idP,frameP,subframeP,harq_pid,tpc, tpc_accumulated,snr,target_snr); } From 733d1292c6b11d4174049078bf04cac4b3c015dd Mon Sep 17 00:00:00 2001 From: laurent Date: Wed, 25 Sep 2019 08:28:02 +0200 Subject: [PATCH 035/240] small fixes --- executables/main-ocp.c | 2 +- openair1/PHY/LTE_TRANSPORT/transport_eNB.h | 4 ++-- openair2/LAYER2/MAC/pre_processor.c | 7 +++++-- targets/RT/USER/lte-ue.c | 1 + 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/executables/main-ocp.c b/executables/main-ocp.c index b3983463e0..cfec3b336c 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -676,7 +676,7 @@ void rx_rf(RU_t *ru) { proc->first_rx = false; } else { if (proc->timestamp_rx - old_ts != fp->samples_per_tti) { - LOG_E(HW,"impossible shift in RFSIM, rx: %ld, previous rx distance: %ld\n", proc->timestamp_rx, proc->timestamp_rx - old_ts); + LOG_E(HW,"impossible shift in rx stream, rx: %ld, previous rx distance: %ld, should be %d\n", proc->timestamp_rx, proc->timestamp_rx - old_ts, fp->samples_per_tti); //ru->ts_offset += (proc->timestamp_rx - old_ts - fp->samples_per_tti); //proc->timestamp_rx = ts-ru->ts_offset; } diff --git a/openair1/PHY/LTE_TRANSPORT/transport_eNB.h b/openair1/PHY/LTE_TRANSPORT/transport_eNB.h index 61a9d50b53..5feb1389be 100644 --- a/openair1/PHY/LTE_TRANSPORT/transport_eNB.h +++ b/openair1/PHY/LTE_TRANSPORT/transport_eNB.h @@ -154,7 +154,7 @@ typedef struct { uint8_t active; #endif /// indicator of UE type (0 = LTE, 1,2 = Cat-M) - UE_type_t ue_type; + int ue_type; /// HARQ process mask, indicates which processes are currently active uint16_t harq_mask; /// Indicator of TX activation per subframe. Used during PUCCH detection for ACK/NAK. @@ -456,7 +456,7 @@ typedef struct { typedef struct { #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) /// UE type (normal, CEModeA, CEModeB) - UE_type_t ue_type; + uint8_t ue_type; #endif /// HARQ process mask, indicates which processes are currently active uint16_t harq_mask; diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 0dc11b0e45..1e6b0148a8 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -1799,12 +1799,15 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, } total_allocated_rbs[CC_id] += nb_allocated_rbs[CC_id][UE_id]; - LOG_D(MAC, "In ulsch_preprocessor: assigning %d RBs for UE %d/%x CCid %d, harq_pid %d\n", + LOG_D(MAC, "In ulsch_preprocessor: assigning %d RBs for UE %d/%x CCid %d, harq_pid %d, nb_rb_ul %d, %d ,%d\n", nb_allocated_rbs[CC_id][UE_id], UE_id, rntiTable[UE_id], CC_id, - harq_pid); + harq_pid, + UE_list->UE_template[CC_id][UE_id].nb_rb_ul[harq_pid], + UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[slice_idx], + average_rbs_per_user[CC_id]); } } diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c index 42ec7d216d..6c4087d08f 100644 --- a/targets/RT/USER/lte-ue.c +++ b/targets/RT/USER/lte-ue.c @@ -1644,6 +1644,7 @@ void *UE_thread(void *arg) { pthread_mutex_unlock(&proc->mutex_rxtx); } + usleep(3000); } LOG_D(PHY,"Process Subframe %d thread Idx %d \n", sub_frame, UE->current_thread_id[sub_frame]); From 2aafa61712af1f9d85645262555d570ddc3e0993 Mon Sep 17 00:00:00 2001 From: laurent Date: Sun, 29 Sep 2019 18:00:07 +0200 Subject: [PATCH 036/240] fix multi blocks transport issue in fs6, and simulators related ul issue for rfsim --- executables/main-fs6.c | 21 +++++++++++++--- executables/split_headers.h | 1 + executables/transport_split.c | 15 +++++++---- openair1/PHY/LTE_UE_TRANSPORT/initial_sync.c | 4 +-- openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c | 4 +-- openair1/SCHED_UE/phy_procedures_lte_ue.c | 26 +++++++++++--------- targets/ARCH/rfsimulator/simulator.c | 4 +-- 7 files changed, 50 insertions(+), 25 deletions(-) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index aa1b31d67f..2b724ea163 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -21,6 +21,12 @@ #define FS6_BUF_SIZE 100*1000 static UDPsock_t sockFS6; +int sum(uint8_t * b, int s) { + int sum=0; + for (int i=0; i < s; i++) + sum+=b[i]; + return sum; +} void prach_eNB_tosplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB) { fs6_ul_t *header=(fs6_ul_t *) commonUDPdata(bufferZone); @@ -647,7 +653,8 @@ void recvFs6Ul(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB) { memcpy(eNB->pusch_vars[hULUE(bufPtr)->UE_id]->ulsch_power, hULUE(bufPtr)->ulsch_power, sizeof(int)*2); - LOG_W(PHY,"Received ulsch data for: rnti:%d, fsf: %d/%d\n", ulsch->rnti, eNB->proc.frame_rx, eNB->proc.subframe_rx); + LOG_I(PHY,"Received ulsch data for: rnti:%d, fsf: %d/%d\n", + ulsch->rnti, eNB->proc.frame_rx, eNB->proc.subframe_rx); } else if ( type == fs6ULcch ) { int nb_uci=hULUEuci(bufPtr)->nb_active_ue; fs6_ul_uespec_uci_element_t *tmp=(fs6_ul_uespec_uci_element_t *)(hULUEuci(bufPtr)+1); @@ -715,6 +722,7 @@ void rcvFs6DL(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, int frame, i dlsch_harq->Nl=hDLUE(bufPtr)->Nl; dlsch_harq->pdsch_start=hDLUE(bufPtr)->pdsch_start; #ifdef PHY_TX_THREAD + dlsch_harq->CEmode = hDLUE(bufPtr)->CEmode; dlsch_harq->i0=hDLUE(bufPtr)->i0; dlsch_harq->sib1_br_flag=hDLUE(bufPtr)->sib1_br_flag; #else @@ -723,6 +731,8 @@ void rcvFs6DL(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, int frame, i #endif memcpy(dlsch_harq->e, hDLUE(bufPtr)+1, hDLUE(bufPtr)->dataLen); + LOG_D(PHY,"received %d bits, in harq id: %di fsf: %d.%d, sum %d\n", + hDLUE(bufPtr)->dataLen, hDLUE(bufPtr)->harq_pid, frame, subframe, sum(dlsch_harq->e, hDLUE(bufPtr)->dataLen)); } else if (type == fs6UlConfig) { int nbUE=(((commonUDP_t *)bufPtr)->contentBytes - sizeof(fs6_dl_t)) / sizeof( fs6_dl_ulsched_t ) ; @@ -759,7 +769,8 @@ void rcvFs6DL(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, int frame, i ulsch_harq->srs_active=hTxULUE(bufPtr)->srs_active; ulsch_harq->TBS=hTxULUE(bufPtr)->TBS; ulsch_harq->Nsymb_pusch=hTxULUE(bufPtr)->Nsymb_pusch; - LOG_W(PHY,"Received request to perform ulsch for: rnti:%d, fsf: %d/%d\n", ulsch->rnti, frame, subframe); + LOG_I(PHY,"Received request to perform ulsch for: rnti:%d, fsf: %d/%d\n", + ulsch->rnti, frame, subframe); } } else if ( type == fs6ULConfigCCH ) { fs6_dl_uespec_ulcch_element_t *tmp=(fs6_dl_uespec_ulcch_element_t *)(hTxULcch(bufPtr)+1); @@ -979,6 +990,7 @@ void appendFs6DLUE(uint8_t *bufferZone, LTE_DL_FRAME_PARMS *fp, int UE_id, int8_ hDLUE(newUDPheader)->Nl=harqData->Nl; hDLUE(newUDPheader)->pdsch_start=harqData->pdsch_start; #ifdef PHY_TX_THREAD + hDLUE(newUDPheader)->CEmode=harqData->CEmode; hDLUE(newUDPheader)->i0=harqData->i0; hDLUE(newUDPheader)->sib1_br_flag=harqData->sib1_br_flag; #else @@ -987,8 +999,11 @@ void appendFs6DLUE(uint8_t *bufferZone, LTE_DL_FRAME_PARMS *fp, int UE_id, int8_ #endif hDLUE(newUDPheader)->dataLen=UEdataLen; memcpy(hDLUE(newUDPheader)+1, harqData->e, UEdataLen); + LOG_D(PHY,"sending %d bits, in harq id: %di fsf: %d.%d, sum %d\n", + UEdataLen , harq_pid, frame, subframe, sum(harqData->e, UEdataLen)); + //for (int i=0; i < UEdataLen; i++) - //LOG_D(PHY,"buffer e:%hhx\n", ( (uint8_t *)(hDLUE(newUDPheader)+1) )[i]); + //LOG_D(PHY,"buffer ei[%d]:%hhx\n", i, ( (uint8_t *)(hDLUE(newUDPheader)+1) )[i]); } void appendFs6DLUEcch(uint8_t *bufferZone, PHY_VARS_eNB *eNB, int frame, int subframe) { diff --git a/executables/split_headers.h b/executables/split_headers.h index 737358f51f..9b67cadd91 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -109,6 +109,7 @@ typedef struct { uint16_t rnti; int16_t sqrt_rho_a; int16_t sqrt_rho_b; + CEmode_t CEmode:8; uint16_t nb_rb; uint8_t Qm; int8_t Nl; diff --git a/executables/transport_split.c b/executables/transport_split.c index 17e40e7e25..07cb67b31a 100644 --- a/executables/transport_split.c +++ b/executables/transport_split.c @@ -116,9 +116,11 @@ int receiveSubFrame(UDPsock_t *sock, void *bufferZone, int bufferSize, uint16_t rcved++; bufferZone+=ret; } + LOG_D(HW,"Received: blocks: %d/%d, size %d, TS: %lu\n", + rcved, bufOrigin->nbBlocks, ret, bufOrigin->timestamp); + } while ( rcved == 0 || rcved < bufOrigin->nbBlocks ); - LOG_D(HW,"Received: nb_blocks: %d, TS: %lu\n",rcved, bufOrigin->timestamp); return rcved; } @@ -136,8 +138,10 @@ int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize, ui do { if (blockId > 0 ) { commonUDP_t *currentHeader=(commonUDP_t *)bufferZone; - *currentHeader=*UDPheader; + currentHeader->timestamp=UDPheader->timestamp; + currentHeader->nbBlocks=UDPheader->nbBlocks; currentHeader->blockID=blockId; + currentHeader->contentType=UDPheader->contentType; memcpy(commonUDPdata((void *)currentHeader), commonUDPdata(bufferZone), secondHeaderSize); } @@ -151,11 +155,12 @@ int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize, ui LOG_W(HW,"Wrote socket doesn't return size %d (val: %d, errno:%d, %s)\n", sz, ret, errno, strerror(errno)); + LOG_D(HW,"Sent: TS: %lu, blocks %d/%d, block size : %d \n", + UDPheader->timestamp, UDPheader->nbBlocks-nbBlocks, UDPheader->nbBlocks, sz); + bufferZone+=sz; nbBlocks--; } while (nbBlocks); - LOG_D(HW,"Sent: TS: %lu, nb blocks %d, size of first block: %lu \n", - UDPheader->timestamp, UDPheader->nbBlocks, alignedSize((void *)UDPheader)); - return 0; + return 0; } diff --git a/openair1/PHY/LTE_UE_TRANSPORT/initial_sync.c b/openair1/PHY/LTE_UE_TRANSPORT/initial_sync.c index 968597bfb8..100dd3b2f1 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/initial_sync.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/initial_sync.c @@ -590,10 +590,10 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode) { LOG_I(PHY,"[UE%d] Initial sync : Estimated power: %d dB\n",ue->Mod_id,ue->measurements.rx_power_avg_dB[0] ); - if (IS_SOFTMODEM_BASICSIM || IS_SOFTMODEM_RFSIM ) + if (IS_SOFTMODEM_BASICSIM ) phy_adjust_gain(ue,ue->measurements.rx_power_avg_dB[0],0); } else { - if (IS_SOFTMODEM_BASICSIM || IS_SOFTMODEM_RFSIM ) + if (IS_SOFTMODEM_BASICSIM ) phy_adjust_gain(ue,dB_fixed(ue->measurements.rssi),0); } diff --git a/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c b/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c index 8139c496ae..49fa484c26 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c @@ -80,7 +80,7 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1 int i, prach_len; uint16_t first_nonzero_root_idx=0; - if ( !(IS_SOFTMODEM_BASICSIM || IS_SOFTMODEM_RFSIM) ) { + if ( !(IS_SOFTMODEM_BASICSIM ) ) { prach_start = (ue->rx_offset+subframe*ue->frame_parms.samples_per_tti-ue->hw_timing_advance-ue->N_TA_offset); #ifdef PRACH_DEBUG LOG_I(PHY,"[UE %d] prach_start %d, rx_offset %d, hw_timing_advance %d, N_TA_offset %d\n", ue->Mod_id, @@ -473,7 +473,7 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1 AssertFatal(prach_fmt<4, "prach_fmt4 not fully implemented" ); - if (!(IS_SOFTMODEM_BASICSIM || IS_SOFTMODEM_RFSIM) ) { + if (!(IS_SOFTMODEM_BASICSIM ) ) { int j; int overflow = prach_start + prach_len - LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*ue->frame_parms.samples_per_tti; LOG_I( PHY, "prach_start=%d, overflow=%d\n", prach_start, overflow ); diff --git a/openair1/SCHED_UE/phy_procedures_lte_ue.c b/openair1/SCHED_UE/phy_procedures_lte_ue.c index 5da97b3a1a..cbcd72a9c1 100644 --- a/openair1/SCHED_UE/phy_procedures_lte_ue.c +++ b/openair1/SCHED_UE/phy_procedures_lte_ue.c @@ -166,13 +166,16 @@ unsigned int get_tx_amp(int power_dBm, int power_max_dBm, int N_RB_UL, int nb_rb int gain_dB; double gain_lin; - if (power_dBm<=power_max_dBm) + if ( (power_dBm<=power_max_dBm) && ! IS_SOFTMODEM_RFSIM) gain_dB = power_dBm - power_max_dBm; else gain_dB = 0; gain_lin = pow(10,.1*gain_dB); AssertFatal((nb_rb >0) && (nb_rb <= N_RB_UL),"Illegal nb_rb/N_RB_UL combination (%d/%d)\n",nb_rb,N_RB_UL); + LOG_D(PHY," tx gain: %d = %d * sqrt ( pow(10, 0.1*max(0,%d-%d)) * %d/%d ) (gain lin=%f (dB=%d))\n", + (int)(AMP*sqrt(gain_lin*N_RB_UL/(double)nb_rb)), + AMP, power_dBm, power_max_dBm, N_RB_UL, nb_rb, gain_lin, gain_dB); return((int)(AMP*sqrt(gain_lin*N_RB_UL/(double)nb_rb))); } @@ -1099,7 +1102,7 @@ void ulsch_common_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, uint8_t empt nsymb = (frame_parms->Ncp == 0) ? 14 : 12; - if (!(IS_SOFTMODEM_BASICSIM || IS_SOFTMODEM_RFSIM) ) { + if (!IS_SOFTMODEM_BASICSIM) { ulsch_start = (ue->rx_offset+subframe_tx*frame_parms->samples_per_tti- ue->hw_timing_advance- ue->timing_advance- @@ -1130,7 +1133,7 @@ void ulsch_common_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, uint8_t empt } for (aa=0; aanb_antennas_tx; aa++) { - int *Buff = (IS_SOFTMODEM_BASICSIM || IS_SOFTMODEM_RFSIM) ? &ue->common_vars.txdata[aa][ulsch_start] :dummy_tx_buffer; + int *Buff = IS_SOFTMODEM_BASICSIM ? &ue->common_vars.txdata[aa][ulsch_start] :dummy_tx_buffer; if (frame_parms->Ncp == 1) { PHY_ofdm_mod(&ue->common_vars.txdataF[aa][subframe_tx*nsymb*frame_parms->ofdm_symbol_size], @@ -1151,7 +1154,7 @@ void ulsch_common_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, uint8_t empt &ue->frame_parms); } - if (IS_SOFTMODEM_BASICSIM || IS_SOFTMODEM_RFSIM ) { + if (IS_SOFTMODEM_BASICSIM ) { apply_7_5_kHz(ue,&ue->common_vars.txdata[aa][ulsch_start],0); apply_7_5_kHz(ue,&ue->common_vars.txdata[aa][ulsch_start],1); } else { @@ -1159,7 +1162,7 @@ void ulsch_common_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, uint8_t empt apply_7_5_kHz(ue,dummy_tx_buffer,1); } - if (!(IS_SOFTMODEM_BASICSIM || IS_SOFTMODEM_RFSIM) ) { + if (!(IS_SOFTMODEM_BASICSIM ) ) { overflow = ulsch_start - 9*frame_parms->samples_per_tti; for (k=ulsch_start,l=0; ksamples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME,ulsch_start+frame_parms->samples_per_tti); k++,l++) { @@ -1259,7 +1262,7 @@ void ue_prach_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin ue->prach_resources[eNB_id]->ra_RNTI); ue->tx_total_RE[subframe_tx] = 96; - if (IS_SOFTMODEM_BASICSIM || IS_SOFTMODEM_RFSIM ) { + if (IS_SOFTMODEM_BASICSIM ) { ue->prach_vars[eNB_id]->amp = get_tx_amp(ue->tx_power_dBm[subframe_tx], ue->tx_power_max_dBm, ue->frame_parms.N_RB_UL, @@ -1630,7 +1633,7 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB ue->tx_total_RE[subframe_tx] = nb_rb*12; - if (IS_SOFTMODEM_BASICSIM || IS_SOFTMODEM_RFSIM ) { + if (IS_SOFTMODEM_BASICSIM ) { tx_amp = AMP; } else { tx_amp = get_tx_amp(ue->tx_power_dBm[subframe_tx], @@ -1704,7 +1707,7 @@ void ue_srs_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8 Po_SRS = ue->tx_power_max_dBm; } - if (IS_SOFTMODEM_BASICSIM || IS_SOFTMODEM_RFSIM ) { + if (IS_SOFTMODEM_BASICSIM) { tx_amp = AMP; } else { if (ue->mac_enabled==1) { @@ -1942,7 +1945,7 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin ue->tx_power_dBm[subframe_tx] = Po_PUCCH; ue->tx_total_RE[subframe_tx] = 12; - if (IS_SOFTMODEM_BASICSIM || IS_SOFTMODEM_RFSIM ) { + if (IS_SOFTMODEM_BASICSIM ) { tx_amp = AMP; } else { tx_amp = get_tx_amp(Po_PUCCH, @@ -2023,7 +2026,7 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin ue->tx_power_dBm[subframe_tx] = Po_PUCCH; ue->tx_total_RE[subframe_tx] = 12; - if (IS_SOFTMODEM_BASICSIM || IS_SOFTMODEM_RFSIM ) { + if (IS_SOFTMODEM_BASICSIM ) { tx_amp = AMP; } else { tx_amp = get_tx_amp(Po_PUCCH, @@ -2269,7 +2272,7 @@ void ue_measurement_procedures( // AGC VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL, VCD_FUNCTION_IN); - if (IS_SOFTMODEM_BASICSIM || IS_SOFTMODEM_RFSIM ) + if (IS_SOFTMODEM_BASICSIM ) phy_adjust_gain (ue,dB_fixed(ue->measurements.rssi),0); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL, VCD_FUNCTION_OUT); @@ -3325,6 +3328,7 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue, pdsch==PDSCH?1:0, dlsch0->harq_processes[harq_pid]->TBS>256?1:0); + LOG_D(PHY,"dlsch turbo decode in %d iter\n", ret); if (LOG_DEBUGFLAG(UE_TIMING)) { stop_meas(&ue->dlsch_decoding_stats[ue->current_thread_id[subframe_rx]]); LOG_I(PHY, " --> Unscrambling for CW0 %5.3f\n", diff --git a/targets/ARCH/rfsimulator/simulator.c b/targets/ARCH/rfsimulator/simulator.c index 76f2f3f0fb..36a90994cb 100644 --- a/targets/ARCH/rfsimulator/simulator.c +++ b/targets/ARCH/rfsimulator/simulator.c @@ -430,8 +430,8 @@ static bool flushInput(rfsimulator_state_t *t, int timeout) { b->circularBuf[(index*nbAnt+a)%CirSize].i=0; } } - - LOG_W(HW,"gap of: %ld in reception\n", b->th.timestamp-b->lastReceivedTS ); + if ( abs(b->th.timestamp-b->lastReceivedTS) > 50 ) + LOG_W(HW,"gap of: %ld in reception\n", b->th.timestamp-b->lastReceivedTS ); } b->lastReceivedTS=b->th.timestamp; From 3321a3510100fbf51de5f1ed1887cad478aa799e Mon Sep 17 00:00:00 2001 From: laurent Date: Wed, 2 Oct 2019 16:22:47 +0200 Subject: [PATCH 037/240] add DL packet compression --- executables/main-fs6.c | 68 +++++++++++++++++---- executables/split_headers.h | 8 +-- openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c | 4 +- openair1/SCHED_UE/phy_procedures_lte_ue.c | 1 - openair2/LAYER2/MAC/pre_processor.c | 11 +++- openair2/UTIL/OPT/probe.c | 8 ++- 6 files changed, 76 insertions(+), 24 deletions(-) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index 2b724ea163..1b060d3eef 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -17,17 +17,54 @@ #include #include #include +#include #define FS6_BUF_SIZE 100*1000 static UDPsock_t sockFS6; -int sum(uint8_t * b, int s) { +int sum(uint8_t *b, int s) { int sum=0; + for (int i=0; i < s; i++) sum+=b[i]; + return sum; } +#define ceil16_bytes(a) ((((a+15)/16)*16)/8) +static void fs6Dlunpack(void *out, void *in, int szUnpacked) { + static uint64_t *lut=NULL; + + if (!lut) { + lut=(uint64_t *) malloc(sizeof(*lut)*256); + + for (int i=0; i <256; i++) + for (int j=0; j<8; j++) + ((uint8_t *)(lut+i))[7-j]=(i>>j)&1; + } + + int64_t *out_64 = (int64_t *)out; + int sz=ceil16_bytes(szUnpacked); + + for (int i=0; ipusch_vars[hULUE(bufPtr)->UE_id]->ulsch_power, hULUE(bufPtr)->ulsch_power, sizeof(int)*2); - LOG_I(PHY,"Received ulsch data for: rnti:%d, fsf: %d/%d\n", + LOG_I(PHY,"Received ulsch data for: rnti:%d, fsf: %d/%d\n", ulsch->rnti, eNB->proc.frame_rx, eNB->proc.subframe_rx); } else if ( type == fs6ULcch ) { int nb_uci=hULUEuci(bufPtr)->nb_active_ue; @@ -722,16 +759,16 @@ void rcvFs6DL(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, int frame, i dlsch_harq->Nl=hDLUE(bufPtr)->Nl; dlsch_harq->pdsch_start=hDLUE(bufPtr)->pdsch_start; #ifdef PHY_TX_THREAD - dlsch_harq->CEmode = hDLUE(bufPtr)->CEmode; + dlsch_harq->CEmode = hDLUE(bufPtr)->CEmode; dlsch_harq->i0=hDLUE(bufPtr)->i0; dlsch_harq->sib1_br_flag=hDLUE(bufPtr)->sib1_br_flag; #else dlsch0->i0=hDLUE(bufPtr)->i0; dlsch0->sib1_br_flag=hDLUE(bufPtr)->sib1_br_flag; #endif - memcpy(dlsch_harq->e, - hDLUE(bufPtr)+1, hDLUE(bufPtr)->dataLen); - LOG_D(PHY,"received %d bits, in harq id: %di fsf: %d.%d, sum %d\n", + fs6Dlunpack(dlsch_harq->e, + hDLUE(bufPtr)+1, hDLUE(bufPtr)->dataLen); + LOG_D(PHY,"received %d bits, in harq id: %di fsf: %d.%d, sum %d\n", hDLUE(bufPtr)->dataLen, hDLUE(bufPtr)->harq_pid, frame, subframe, sum(dlsch_harq->e, hDLUE(bufPtr)->dataLen)); } else if (type == fs6UlConfig) { int nbUE=(((commonUDP_t *)bufPtr)->contentBytes - sizeof(fs6_dl_t)) / sizeof( fs6_dl_ulsched_t ) ; @@ -769,7 +806,7 @@ void rcvFs6DL(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, int frame, i ulsch_harq->srs_active=hTxULUE(bufPtr)->srs_active; ulsch_harq->TBS=hTxULUE(bufPtr)->TBS; ulsch_harq->Nsymb_pusch=hTxULUE(bufPtr)->Nsymb_pusch; - LOG_I(PHY,"Received request to perform ulsch for: rnti:%d, fsf: %d/%d\n", + LOG_I(PHY,"Received request to perform ulsch for: rnti:%d, fsf: %d/%d\n", ulsch->rnti, frame, subframe); } } else if ( type == fs6ULConfigCCH ) { @@ -971,11 +1008,11 @@ void appendFs6DLUE(uint8_t *bufferZone, LTE_DL_FRAME_PARMS *fp, int UE_id, int8_ harqData->pdsch_start, frame,subframe, 0); - AssertFatal(firstFreeByte+UEdataLen+sizeof(fs6_dl_t) <= bufferZone+FS6_BUF_SIZE, ""); + AssertFatal(firstFreeByte+ceil16_bytes(UEdataLen)+sizeof(fs6_dl_t) <= bufferZone+FS6_BUF_SIZE, ""); commonUDP_t *newUDPheader=(commonUDP_t *) firstFreeByte; FirstUDPheader->nbBlocks++; newUDPheader->blockID=curBlock; - newUDPheader->contentBytes=sizeof(fs6_dl_t)+sizeof(fs6_dl_uespec_t) + UEdataLen; + newUDPheader->contentBytes=sizeof(fs6_dl_t)+sizeof(fs6_dl_uespec_t) + ceil16_bytes(UEdataLen); // We skip the fs6 DL header, that is populated by caller // This header will be duplicated during sending hDLUE(newUDPheader)->type=fs6DlConfig; @@ -998,10 +1035,9 @@ void appendFs6DLUE(uint8_t *bufferZone, LTE_DL_FRAME_PARMS *fp, int UE_id, int8_ hDLUE(newUDPheader)->sib1_br_flag=dlsch0->sib1_br_flag; #endif hDLUE(newUDPheader)->dataLen=UEdataLen; - memcpy(hDLUE(newUDPheader)+1, harqData->e, UEdataLen); + fs6Dlpack(hDLUE(newUDPheader)+1, harqData->e, UEdataLen); LOG_D(PHY,"sending %d bits, in harq id: %di fsf: %d.%d, sum %d\n", - UEdataLen , harq_pid, frame, subframe, sum(harqData->e, UEdataLen)); - + UEdataLen, harq_pid, frame, subframe, sum(harqData->e, UEdataLen)); //for (int i=0; i < UEdataLen; i++) //LOG_D(PHY,"buffer ei[%d]:%hhx\n", i, ( (uint8_t *)(hDLUE(newUDPheader)+1) )[i]); } @@ -1112,7 +1148,13 @@ void phy_procedures_eNB_TX_tosplit(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx uint8_t num_dci = eNB->pdcch_vars[subframe&1].num_dci; uint8_t num_mdci = eNB->mpdcch_vars[subframe&1].num_dci; memcpy(hDL(bufferZone)->pbch_pdu,eNB->pbch_pdu,4); - LOG_D(PHY,"num_pdcch_symbols %"PRIu8",number dci %"PRIu8"\n",num_pdcch_symbols, num_dci); + + if ( num_dci <= 8 ) + LOG_D(PHY,"num_pdcch_symbols %"PRIu8",number dci %"PRIu8"\n",num_pdcch_symbols, num_dci); + else { + LOG_E(PHY, "Num dci too large for current FS6 implementation, reducing to 8 dci (was %d)\n", num_dci); + num_dci=8; + } if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { hDL(bufferZone)->num_pdcch_symbols=num_pdcch_symbols; diff --git a/executables/split_headers.h b/executables/split_headers.h index 9b67cadd91..12dd08beb4 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -55,7 +55,7 @@ typedef struct { uint8_t pbch_pdu[4]; int num_pdcch_symbols; int num_dci; - DCI_ALLOC_t dci_alloc[32]; + DCI_ALLOC_t dci_alloc[8]; int num_mdci; int amp; LTE_eNB_PHICH phich_vars; @@ -133,9 +133,9 @@ typedef struct { typedef struct { enum pckType type:8; short UE_id; - short harq_id; - short segment; - short segLen; + uint8_t harq_id; + uint8_t segment; + int segLen; int ulsch_power[2]; } fs6_ul_uespec_t; diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index c59e71607e..f51fc3035b 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -666,9 +666,9 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) &eNB->ulsch_tc_intl1_stats, &eNB->ulsch_tc_intl2_stats); LOG_D(PHY, "Cu should decode in %d iter\n",iter); - if ( iter == 5 ) { + if ( 1) { //iter == 5 ) { for (int i=0; i < Kr; i++ ) - printf("%hx:", ulsch_harq->d[r][96+i]); + printf("%hhx:", ulsch_harq->d[r][96+i]); printf("\n"); } */ diff --git a/openair1/SCHED_UE/phy_procedures_lte_ue.c b/openair1/SCHED_UE/phy_procedures_lte_ue.c index cbcd72a9c1..9e6644def9 100644 --- a/openair1/SCHED_UE/phy_procedures_lte_ue.c +++ b/openair1/SCHED_UE/phy_procedures_lte_ue.c @@ -3328,7 +3328,6 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue, pdsch==PDSCH?1:0, dlsch0->harq_processes[harq_pid]->TBS>256?1:0); - LOG_D(PHY,"dlsch turbo decode in %d iter\n", ret); if (LOG_DEBUGFLAG(UE_TIMING)) { stop_meas(&ue->dlsch_decoding_stats[ue->current_thread_id[subframe_rx]]); LOG_I(PHY, " --> Unscrambling for CW0 %5.3f\n", diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 1e6b0148a8..991c459c24 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -1799,7 +1799,7 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, } total_allocated_rbs[CC_id] += nb_allocated_rbs[CC_id][UE_id]; - LOG_D(MAC, "In ulsch_preprocessor: assigning %d RBs for UE %d/%x CCid %d, harq_pid %d, nb_rb_ul %d, %d ,%d\n", + LOG_D(MAC, "In ulsch_preprocessor: assigning %d RBs for UE %d/%x CCid %d, harq_pid %d, nb_rb_ul %d, %d ,%d, slice %d, round ul %d\n", nb_allocated_rbs[CC_id][UE_id], UE_id, rntiTable[UE_id], @@ -1807,7 +1807,9 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, harq_pid, UE_list->UE_template[CC_id][UE_id].nb_rb_ul[harq_pid], UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[slice_idx], - average_rbs_per_user[CC_id]); + average_rbs_per_user[CC_id], + slice_idx, + UE_list->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid]); } } @@ -1833,6 +1835,10 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, while (UE_template->pre_allocated_nb_rb_ul[slice_idx] > 0 && nb_allocated_rbs[CC_id][UE_id] < UE_template->pre_allocated_nb_rb_ul[slice_idx] && total_remaining_rbs[CC_id] > 0) { + LOG_D(PHY,"in ulsch alloc: prealloc: %d, nb_allocated %d, total remain%d\n", + UE_template->pre_allocated_nb_rb_ul[slice_idx], + nb_allocated_rbs[CC_id][UE_id], + total_remaining_rbs[CC_id]); nb_allocated_rbs[CC_id][UE_id] = cmin(nb_allocated_rbs[CC_id][UE_id] + 1, UE_template->pre_allocated_nb_rb_ul[slice_idx]); total_remaining_rbs[CC_id]--; total_allocated_rbs[CC_id]++; @@ -1902,6 +1908,7 @@ assign_max_mcs_min_rb(module_id_t module_idP, ue_sched_ctl->max_rbs_allowed_slice_uplink[CC_id][slice_idx] = nb_rbs_allowed_slice(sli->ul[slice_idx].pct, N_RB_UL); int bytes_to_schedule = UE_template->estimated_ul_buffer - UE_template->scheduled_ul_bytes; + LOG_D(MAC,"ul bytes to schedule: %d-%d\n",UE_template->estimated_ul_buffer, UE_template->scheduled_ul_bytes); if (bytes_to_schedule < 0) bytes_to_schedule = 0; int bits_to_schedule = bytes_to_schedule * 8; diff --git a/openair2/UTIL/OPT/probe.c b/openair2/UTIL/OPT/probe.c index b032784028..32facd6889 100644 --- a/openair2/UTIL/OPT/probe.c +++ b/openair2/UTIL/OPT/probe.c @@ -396,11 +396,15 @@ void trace_pdu(int direction, uint8_t *pdu_buffer, unsigned int pdu_buffer_size, MAC_Context_Info_t pdu_context; int radioType=FDD_RADIO; - if (RC.eNB[0][0]!=NULL) + if (RC.eNB && RC.eNB[0][0]!=NULL) radioType=RC.eNB[0][0]->frame_parms.frame_type== FDD ? FDD_RADIO:TDD_RADIO; - if (PHY_vars_UE_g[0][0] != NULL) + else if (PHY_vars_UE_g && PHY_vars_UE_g[0][0] != NULL) radioType=PHY_vars_UE_g[0][0]->frame_parms.frame_type== FDD ? FDD_RADIO:TDD_RADIO; + else { + LOG_E(OPT,"not a eNB neither a UE!!! \n"); + return; + } switch (opt_type) { case OPT_WIRESHARK : From 18fb589b7130ad7afd6b22b6a9add523950b5d43 Mon Sep 17 00:00:00 2001 From: laurent Date: Mon, 7 Oct 2019 13:21:01 +0200 Subject: [PATCH 038/240] fixes: improves throughput --- executables/main-fs6.c | 187 ++++++++++++++++-- executables/split_headers.h | 44 ++++- openair1/PHY/CODING/lte_segmentation.c | 2 +- openair1/SCHED/phy_procedures_lte_eNb.c | 5 +- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 2 +- .../LAYER2/MAC/eNB_scheduler_primitives.c | 7 +- openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c | 6 +- targets/ARCH/rfsimulator/stored_node.c | 36 +++- 8 files changed, 263 insertions(+), 26 deletions(-) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index 1b060d3eef..dbfa0a4cbb 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -214,7 +214,8 @@ void prach_eNB_fromsplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB) { } } -void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, uint16_t rnti, +void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, + uint16_t rnti, int32_t stat) { static int current_fsf=-1; int fsf=frame*16+subframe; @@ -254,6 +255,11 @@ void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, int frame, in tmp->frame=frame; tmp->subframe=subframe; + if (uci != NULL) + memcpy(&tmp->uci, uci, sizeof(*uci)); + else + tmp->uci.ue_id=0xFFFF; + if (harq_ack != NULL) memcpy(tmp->harq_ack, harq_ack, 4); @@ -289,7 +295,11 @@ void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_ memcpy(hULUE(newUDPheader)->ulsch_power, eNB->pusch_vars[UE_id]->ulsch_power, sizeof(int)*2); + hULUE(newUDPheader)->cqi_crc_status=eNB->ulsch[UE_id]->harq_processes[harq_pid]->cqi_crc_status; + hULUE(newUDPheader)->ta=lte_est_timing_advance_pusch(eNB, UE_id); hULUE(newUDPheader)->segment=segmentID; + memcpy(hULUE(newUDPheader)->o, eNB->ulsch[UE_id]->harq_processes[harq_pid]->o, + sizeof(eNB->ulsch[UE_id]->harq_processes[harq_pid]->o)); memcpy(hULUE(newUDPheader)+1, data, dataLen); hULUE(newUDPheader)->segLen=dataLen; } @@ -433,7 +443,7 @@ int ulsch_decoding_process(PHY_VARS_eNB *eNB, int UE_id, int llr8_flag) { tc = *decoder8; // This is a new packet, so compute quantities regarding segmentation - //Fixme: very dirty: all the variables produced by let_segmentation are only used localy + // Fixme: very dirty: all the variables produced by let_segmentation are only used localy // Furthermore, variables as 1 letter and global is "time consuming" for everybody !!! ulsch_harq->B = ulsch_harq->TBS+24; lte_segmentation(NULL, @@ -511,15 +521,99 @@ int ulsch_decoding_process(PHY_VARS_eNB *eNB, int UE_id, int llr8_flag) { return(ret); } -void pusch_procedures_fromsplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB) { +void fill_rx_indication_from_split(uint8_t *bufferZone, PHY_VARS_eNB *eNB,int UE_id,int frame,int subframe, ul_propagation_t *ul_propa) { + nfapi_rx_indication_pdu_t *pdu; + int timing_advance_update; + uint32_t harq_pid; +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + + if (eNB->ulsch[UE_id]->ue_type > 0) harq_pid = 0; + else +#endif + { + harq_pid = subframe2harq_pid (&eNB->frame_parms, + frame, subframe); + } + + pthread_mutex_lock(&eNB->UL_INFO_mutex); + eNB->UL_INFO.rx_ind.sfn_sf = frame<<4| subframe; + eNB->UL_INFO.rx_ind.rx_indication_body.tl.tag = NFAPI_RX_INDICATION_BODY_TAG; + pdu = &eNB->UL_INFO.rx_ind.rx_indication_body.rx_pdu_list[eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus]; + // pdu->rx_ue_information.handle = eNB->ulsch[UE_id]->handle; + pdu->rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG; + pdu->rx_ue_information.rnti = eNB->ulsch[UE_id]->rnti; + pdu->rx_indication_rel8.tl.tag = NFAPI_RX_INDICATION_REL8_TAG; + pdu->rx_indication_rel8.length = eNB->ulsch[UE_id]->harq_processes[harq_pid]->TBS>>3; + pdu->rx_indication_rel8.offset = 1; // DJP - I dont understand - but broken unless 1 ???? 0; // filled in at the end of the UL_INFO formation + pdu->data = eNB->ulsch[UE_id]->harq_processes[harq_pid]->b; + // estimate timing advance for MAC + timing_advance_update = ul_propa[UE_id].ta; + + // if (timing_advance_update > 10) { dump_ulsch(eNB,frame,subframe,UE_id); exit(-1);} + // if (timing_advance_update < -10) { dump_ulsch(eNB,frame,subframe,UE_id); exit(-1);} + switch (eNB->frame_parms.N_RB_DL) { + case 6: /* nothing to do */ + break; + + case 15: + timing_advance_update /= 2; + break; + + case 25: + timing_advance_update /= 4; + break; + + case 50: + timing_advance_update /= 8; + break; + + case 75: + timing_advance_update /= 12; + break; + + case 100: + timing_advance_update /= 16; + break; + + default: + abort (); + } + + // put timing advance command in 0..63 range + timing_advance_update += 31; + + if (timing_advance_update < 0) + timing_advance_update = 0; + + if (timing_advance_update > 63) + timing_advance_update = 63; + + pdu->rx_indication_rel8.timing_advance = timing_advance_update; + // estimate UL_CQI for MAC (from antenna port 0 only) + int SNRtimes10 = dB_fixed_times10(eNB->pusch_vars[UE_id]->ulsch_power[0]) - 10 * eNB->measurements.n0_subband_power_dB[0][0]; + + if (SNRtimes10 < -640) + pdu->rx_indication_rel8.ul_cqi = 0; + else if (SNRtimes10 > 635) + pdu->rx_indication_rel8.ul_cqi = 255; + else + pdu->rx_indication_rel8.ul_cqi = (640 + SNRtimes10) / 5; + + LOG_D(PHY,"[PUSCH %d] Frame %d Subframe %d Filling RX_indication with SNR %d (%d), timing_advance %d (update %d)\n", + harq_pid,frame,subframe,SNRtimes10,pdu->rx_indication_rel8.ul_cqi,pdu->rx_indication_rel8.timing_advance, + timing_advance_update); + eNB->UL_INFO.rx_ind.rx_indication_body.number_of_pdus++; + eNB->UL_INFO.rx_ind.sfn_sf = frame<<4 | subframe; + pthread_mutex_unlock(&eNB->UL_INFO_mutex); +} + +void pusch_procedures_fromsplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, ul_propagation_t *ul_propa) { //LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; const int subframe = eNB->proc.subframe_rx; const int frame = eNB->proc.frame_rx; uint32_t harq_pid; uint32_t harq_pid0 = subframe2harq_pid(&eNB->frame_parms,frame,subframe); - // TBD: read UL data - for (int i = 0; i < NUMBER_OF_UE_MAX; i++) { LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[i]; @@ -598,7 +692,7 @@ void pusch_procedures_fromsplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB * T(T_ENB_PHY_ULSCH_UE_NACK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(ulsch->rnti), T_INT(harq_pid)); fill_crc_indication(eNB,i,frame,subframe,1); // indicate NAK to MAC - fill_rx_indication(eNB,i,frame,subframe); // indicate SDU to MAC + fill_rx_indication_from_split(bufferZone, eNB,i,frame,subframe, ul_propa); // indicate SDU to MAC LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d Error receiving ULSCH, round %d/%d (ACK %d,%d)\n", eNB->Mod_id,harq_pid, frame,subframe, i, @@ -631,7 +725,7 @@ void pusch_procedures_fromsplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB * } // ulsch in error else { fill_crc_indication(eNB,i,frame,subframe,0); // indicate ACK to MAC - fill_rx_indication(eNB,i,frame,subframe); // indicate SDU to MAC + fill_rx_indication_from_split(bufferZone, eNB,i,frame,subframe, ul_propa); // indicate SDU to MAC ulsch_harq->status = SCH_IDLE; ulsch->harq_mask &= ~(1 << harq_pid); T (T_ENB_PHY_ULSCH_UE_ACK, T_INT (eNB->Mod_id), T_INT (frame), T_INT (subframe), T_INT (ulsch->rnti), T_INT (harq_pid)); @@ -674,7 +768,7 @@ void pusch_procedures_fromsplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB * } // for (i=0; ipusch_vars[hULUE(bufPtr)->UE_id]->ulsch_power, hULUE(bufPtr)->ulsch_power, sizeof(int)*2); - LOG_I(PHY,"Received ulsch data for: rnti:%d, fsf: %d/%d\n", - ulsch->rnti, eNB->proc.frame_rx, eNB->proc.subframe_rx); + ulsch_harq->cqi_crc_status=hULUE(bufPtr)->cqi_crc_status; + memcpy(ulsch_harq->o,hULUE(bufPtr)->o, sizeof(ulsch_harq->o)); + ul_propa[hULUE(bufPtr)->UE_id].ta=hULUE(bufPtr)->ta; + LOG_I(PHY,"Received ulsch data for: rnti:%d, fsf: %d/%d, cqi_crc_status %d \n", + ulsch->rnti, eNB->proc.frame_rx, eNB->proc.subframe_rx, ulsch_harq->cqi_crc_status); } else if ( type == fs6ULcch ) { int nb_uci=hULUEuci(bufPtr)->nb_active_ue; fs6_ul_uespec_uci_element_t *tmp=(fs6_ul_uespec_uci_element_t *)(hULUEuci(bufPtr)+1); @@ -701,6 +798,9 @@ void recvFs6Ul(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB) { i, j, type, tmp->rnti, tmp->UEid); eNB->measurements.n0_subband_power_dB[0][0]=tmp->n0_subband_power_dB; + if (tmp->uci.ue_id != 0xFFFF) + memcpy(&eNB->uci_vars[tmp->UEid],&tmp->uci, sizeof(tmp->uci)); + if ( tmp->type == fs6ULindicationHarq ) fill_uci_harq_indication (tmp->UEid, eNB, &eNB->uci_vars[tmp->UEid], tmp->frame, tmp->subframe, tmp->harq_ack, @@ -722,7 +822,8 @@ void recvFs6Ul(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB) { void phy_procedures_eNB_uespec_RX_fromsplit(uint8_t *bufferZone, int nbBlocks,PHY_VARS_eNB *eNB) { // The configuration arrived in Dl, so we can extract the UL data - recvFs6Ul(bufferZone, nbBlocks, eNB); + ul_propagation_t ul_propa[NUMBER_OF_UE_MAX]; + recvFs6Ul(bufferZone, nbBlocks, eNB, ul_propa); // dirty memory allocation in OAI... for (int i = 0; i < NUMBER_OF_UCI_VARS_MAX; i++) @@ -730,7 +831,7 @@ void phy_procedures_eNB_uespec_RX_fromsplit(uint8_t *bufferZone, int nbBlocks,PH eNB->uci_vars[i].subframe == eNB->proc.subframe_rx ) eNB->uci_vars[i].active=0; - pusch_procedures_fromsplit(bufferZone, nbBlocks, eNB); + pusch_procedures_fromsplit(bufferZone, nbBlocks, eNB, ul_propa); } void rcvFs6DL(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, int frame, int subframe) { @@ -772,6 +873,7 @@ void rcvFs6DL(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, int frame, i hDLUE(bufPtr)->dataLen, hDLUE(bufPtr)->harq_pid, frame, subframe, sum(dlsch_harq->e, hDLUE(bufPtr)->dataLen)); } else if (type == fs6UlConfig) { int nbUE=(((commonUDP_t *)bufPtr)->contentBytes - sizeof(fs6_dl_t)) / sizeof( fs6_dl_ulsched_t ) ; +#define cpyVal(a) memcpy(&ulsch_harq->a,&hTxULUE(bufPtr)->a, sizeof(ulsch_harq->a)) for ( int i=0; i < nbUE; i++ ) { int curUE=hTxULUE(bufPtr)->UE_id; @@ -806,6 +908,36 @@ void rcvFs6DL(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, int frame, i ulsch_harq->srs_active=hTxULUE(bufPtr)->srs_active; ulsch_harq->TBS=hTxULUE(bufPtr)->TBS; ulsch_harq->Nsymb_pusch=hTxULUE(bufPtr)->Nsymb_pusch; + cpyVal(dci_alloc); + cpyVal(rar_alloc); + cpyVal(status); + cpyVal(Msg3_flag); + cpyVal(phich_active); + cpyVal(phich_ACK); + cpyVal(previous_first_rb); + cpyVal(B); + cpyVal(G); + //cpyVal(o); + cpyVal(uci_format); + cpyVal(Or2); + cpyVal(o_RI); + cpyVal(o_ACK); + cpyVal(O_ACK); + //cpyVal(q); + cpyVal(o_RCC); + cpyVal(q_ACK); + cpyVal(q_RI); + cpyVal(RTC); + cpyVal(ndi); + cpyVal(round); + cpyVal(rvidx); + cpyVal(Nl); + cpyVal(n_DMRS); + cpyVal(previous_n_DMRS); + cpyVal(n_DMRS2); + cpyVal(delta_TF); + cpyVal(repetition_number ); + cpyVal(total_number_of_repetitions); LOG_I(PHY,"Received request to perform ulsch for: rnti:%d, fsf: %d/%d\n", ulsch->rnti, frame, subframe); } @@ -930,6 +1062,7 @@ void phy_procedures_eNB_TX_fromsplit(uint8_t *bufferZone, int nbBlocks, PHY_VARS #define cpyToDu(a) hTxULUE(newUDPheader)->a=ulsch->a #define cpyToDuHarq(a) hTxULUE(newUDPheader)->a=ulsch_harq->a +#define memcpyToDuHarq(a) memcpy(&hTxULUE(newUDPheader)->a,&ulsch_harq->a, sizeof(ulsch_harq->a)); void appendFs6TxULUE(uint8_t *bufferZone, LTE_DL_FRAME_PARMS *fp, int curUE, LTE_eNB_ULSCH_t *ulsch, int frame, int subframe) { commonUDP_t *FirstUDPheader=(commonUDP_t *) bufferZone; @@ -986,6 +1119,36 @@ void appendFs6TxULUE(uint8_t *bufferZone, LTE_DL_FRAME_PARMS *fp, int curUE, LTE cpyToDuHarq(srs_active); cpyToDuHarq(TBS); cpyToDuHarq(Nsymb_pusch); + memcpyToDuHarq(dci_alloc); + memcpyToDuHarq(rar_alloc); + memcpyToDuHarq(status); + memcpyToDuHarq(Msg3_flag); + memcpyToDuHarq(phich_active); + memcpyToDuHarq(phich_ACK); + memcpyToDuHarq(previous_first_rb); + memcpyToDuHarq(B); + memcpyToDuHarq(G); + //memcpyToDuHarq(o); + memcpyToDuHarq(uci_format); + memcpyToDuHarq(Or2); + memcpyToDuHarq(o_RI); + memcpyToDuHarq(o_ACK); + memcpyToDuHarq(O_ACK); + //memcpyToDuHarq(q); + memcpyToDuHarq(o_RCC); + memcpyToDuHarq(q_ACK); + memcpyToDuHarq(q_RI); + memcpyToDuHarq(RTC); + memcpyToDuHarq(ndi); + memcpyToDuHarq(round); + memcpyToDuHarq(rvidx); + memcpyToDuHarq(Nl); + memcpyToDuHarq(n_DMRS); + memcpyToDuHarq(previous_n_DMRS); + memcpyToDuHarq(n_DMRS2); + memcpyToDuHarq(delta_TF); + memcpyToDuHarq(repetition_number ); + memcpyToDuHarq(total_number_of_repetitions); LOG_W(PHY,"Added request to perform ulsch for: rnti:%d, fsf: %d/%d\n", ulsch->rnti, frame, subframe); } void appendFs6DLUE(uint8_t *bufferZone, LTE_DL_FRAME_PARMS *fp, int UE_id, int8_t harq_pid, LTE_eNB_DLSCH_t *dlsch0, LTE_DL_eNB_HARQ_t *harqData, int frame, int subframe) { diff --git a/executables/split_headers.h b/executables/split_headers.h index 12dd08beb4..87c8176b9a 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -76,6 +76,39 @@ typedef struct { uint16_t UE_id; int8_t harq_pid; UE_type_t ue_type; + + uint8_t dci_alloc; + uint8_t rar_alloc; + SCH_status_t status; + uint8_t Msg3_flag; + uint8_t subframe; + uint32_t frame; + uint8_t handled; + uint8_t phich_active; + uint8_t phich_ACK; + uint16_t previous_first_rb; + uint32_t B; + uint32_t G; + UCI_format_t uci_format; + uint8_t Or2; + uint8_t o_RI[2]; + uint8_t o_ACK[4]; + uint8_t O_ACK; + uint8_t o_RCC; + int16_t q_ACK[MAX_ACK_PAYLOAD]; + int16_t q_RI[MAX_RI_PAYLOAD]; + uint32_t RTC[MAX_NUM_ULSCH_SEGMENTS]; + uint8_t ndi; + uint8_t round; + uint8_t rvidx; + uint8_t Nl; + uint8_t n_DMRS; + uint8_t previous_n_DMRS; + uint8_t n_DMRS2; + int32_t delta_TF; + uint32_t repetition_number ; + uint32_t total_number_of_repetitions; + uint16_t harq_mask; uint16_t nb_rb; uint8_t Qm; @@ -130,6 +163,10 @@ typedef struct { int16_t nb_active_ue; } fs6_dl_uespec_ulcch_t; +typedef struct { + int ta; +} ul_propagation_t; + typedef struct { enum pckType type:8; short UE_id; @@ -137,6 +174,9 @@ typedef struct { uint8_t segment; int segLen; int ulsch_power[2]; + int ta; + uint8_t o[MAX_CQI_BYTES]; + uint8_t cqi_crc_status; } fs6_ul_uespec_t; typedef struct { @@ -144,6 +184,7 @@ typedef struct { int UEid; int frame; int subframe; + LTE_eNB_UCI uci; uint8_t harq_ack[4]; uint8_t tdd_mapping_mode; uint16_t tdd_multiplexing_mask; @@ -185,7 +226,8 @@ static inline void *commonUDPdata(uint8_t *ptr) { } void setAllfromTS(uint64_t TS); -void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, uint16_t rnti, int32_t stat); +void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB,LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, + uint16_t rnti, int32_t stat); void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen); void *cu_fs6(void *arg); void *du_fs6(void *arg); diff --git a/openair1/PHY/CODING/lte_segmentation.c b/openair1/PHY/CODING/lte_segmentation.c index 5116c765b8..6a38707580 100644 --- a/openair1/PHY/CODING/lte_segmentation.c +++ b/openair1/PHY/CODING/lte_segmentation.c @@ -105,7 +105,7 @@ int lte_segmentation(unsigned char *input_buffer, #endif *Kminus = (*Kplus - 64); } else { - printf("lte_segmentation.c: Illegal codeword size !!!\n"); + LOG_E(PHY,"lte_segmentation.c: Illegal codeword size !!!\n"); return(-1); } diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 0b35e98a0b..a6b546679a 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -593,7 +593,7 @@ void srs_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { void fill_sr_indication(int UEid, PHY_VARS_eNB *eNB,uint16_t rnti,int frame,int subframe,uint32_t stat) { #ifdef FS6 if ( getenv("fs6") != NULL && strncasecmp( getenv("fs6"), "du", 2) == 0 ) { - sendFs6Ulharq(fs6ULindicationSr, UEid, eNB, frame, subframe, NULL,0,0, rnti, stat); + sendFs6Ulharq(fs6ULindicationSr, UEid, eNB, NULL, frame, subframe, NULL,0,0, rnti, stat); return; } #endif @@ -609,6 +609,7 @@ void fill_sr_indication(int UEid, PHY_VARS_eNB *eNB,uint16_t rnti,int frame,int pdu->rx_ue_information.tl.tag = NFAPI_RX_UE_INFORMATION_TAG; pdu->rx_ue_information.rnti = rnti; int SNRtimes10 = dB_fixed_times10(stat) - 10 * eNB->measurements.n0_subband_power_dB[0][0]; + LOG_D(PHY,"stat %d subbandpower %d, SNRtimes10 %d\n", stat, eNB->measurements.n0_subband_power_dB[0][0], SNRtimes10); pdu->ul_cqi_information.tl.tag = NFAPI_UL_CQI_INFORMATION_TAG; if (SNRtimes10 < -640) pdu->ul_cqi_information.ul_cqi=0; @@ -1769,7 +1770,7 @@ void fill_ulsch_harq_indication (PHY_VARS_eNB *eNB, LTE_UL_eNB_HARQ_t *ulsch_har void fill_uci_harq_indication (int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask) { #ifdef FS6 if ( getenv("fs6") != NULL && strncasecmp( getenv("fs6"), "du", 2) == 0 ) { - sendFs6Ulharq(fs6ULindicationHarq, UEid, eNB, frame, subframe, harq_ack, tdd_mapping_mode, tdd_multiplexing_mask, 0, 0); + sendFs6Ulharq(fs6ULindicationHarq, UEid, eNB, uci, frame, subframe, harq_ack, tdd_mapping_mode, tdd_multiplexing_mask, 0, 0); return; } #endif diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 134089dbf4..2c317900bf 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -1506,7 +1506,7 @@ schedule_ue_spec(module_id_t module_idP, tpc = 1; //0 } - LOG_D(MAC, "[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, snr/target snr %d/%d\n", + LOG_D(MAC, "[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, snr/target snr %d/%d (normal case)\n", module_idP, frameP, subframeP, diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index 63f838f652..784e413f37 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -4990,7 +4990,12 @@ cqi_indication(module_id_t mod_idP, UE_id, ul_cqi_information->channel, ul_cqi_information->ul_cqi); - +/* + int sum=0; + for (int i=0; i length; i++) + sum+=pdu[i]; + LOG_D(MAC, "pdu for channel: %d, checksum: %d\n", ul_cqi_information->channel, sum); +*/ if (ul_cqi_information->channel == 0) { // PUCCH // extract pucch csi information before changing RI information extract_pucch_csi(mod_idP, diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c index dc1799ccb6..424e23c6da 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c @@ -127,14 +127,16 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t *const ctxt_pP) { } else if (UE_NAS_USE_TUN) { ret = write(nas_sock_fd[ctxt_pP->module_id], &(sdu_p->data[sizeof(pdcp_data_ind_header_t)]),sizeToWrite ); } else if (ENB_NAS_USE_TUN) { - ret = write(nas_sock_fd[0], &(sdu_p->data[sizeof(pdcp_data_ind_header_t)]),sizeToWrite ); + if ((ret = write(nas_sock_fd[0], &(sdu_p->data[sizeof(pdcp_data_ind_header_t)]),sizeToWrite )) != sizeToWrite) { + printf("ret: %d\n",ret); + } } else if (PDCP_USE_NETLINK) { memcpy(NLMSG_DATA(nas_nlh_tx), (uint8_t *) sdu_p->data, sizeToWrite); nas_nlh_tx->nlmsg_len = sizeToWrite; ret = sendmsg(nas_sock_fd[0],&nas_msg_tx,0); } // PDCP_USE_NETLINK - AssertFatal(ret >= 0,"[PDCP_FIFOS] pdcp_fifo_flush_sdus (errno: %d %s)\n", errno, strerror(errno)); + if(ret < 0) LOG_E(PDCP,"[PDCP_FIFOS] pdcp_fifo_flush_sdus (ret (instead of: %d) : %d, errno: %d %s)\n", ret, sizeToWrite, errno, strerror(errno)); list_remove_head (&pdcp_sdu_list); free_mem_block (sdu_p, __func__); pdcp_nb_sdu_sent ++; diff --git a/targets/ARCH/rfsimulator/stored_node.c b/targets/ARCH/rfsimulator/stored_node.c index 8cf3aa3bb2..07d6861d57 100644 --- a/targets/ARCH/rfsimulator/stored_node.c +++ b/targets/ARCH/rfsimulator/stored_node.c @@ -7,6 +7,21 @@ volatile int oai_exit = 0; +int fullread(int fd, void *_buf, int count) +{ + char *buf = _buf; + int ret = 0; + int l; + while (count) { + l = read(fd, buf, count); + if (l <= 0) return -1; + count -= l; + buf += l; + ret += l; + } + return ret; +} + void fullwrite(int fd, void *_buf, int count) { char *buf = _buf; int l; @@ -63,10 +78,10 @@ sin_addr: bool connected=false; while(!connected) { - LOG_I(HW,"rfsimulator: trying to connect to %s:%d\n", IP, port); + //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"); + //LOG_I(HW,"rfsimulator: connection established\n"); connected=true; } @@ -108,12 +123,13 @@ int main(int argc, char *argv[]) { if (strcmp(argv[2],"server")==0) { serviceSock=server_start(atoi(argv[3])); } else { - client_start(argv[2],atoi(argv[3])); + serviceSock=client_start(argv[2],atoi(argv[3])); } samplesBlockHeader_t header; int bufSize=100000; void *buff=malloc(bufSize); + uint64_t readTS=0; while (1) { //Rewind the file to loop on the samples @@ -125,6 +141,7 @@ int main(int argc, char *argv[]) { AssertFatal(read(fd,&header,sizeof(header)), ""); fullwrite(serviceSock, &header, sizeof(header)); int dataSize=sizeof(int32_t)*header.size*header.nbAnt; + uint64_t wroteTS=header.timestamp; if (dataSize>bufSize) { void * new_buff = realloc(buff, dataSize); @@ -139,9 +156,16 @@ int main(int argc, char *argv[]) { AssertFatal(read(fd,buff,dataSize) == dataSize, ""); fullwrite(serviceSock, buff, dataSize); // Purge incoming samples - setblocking(serviceSock, notBlocking); - - while(recv(serviceSock,buff, bufSize, MSG_DONTWAIT) > 0) { + setblocking(serviceSock, blocking); + while(readTS < wroteTS) { + if ( fullread(serviceSock, &header,sizeof(header)) != sizeof(header) || + fullread(serviceSock, buff, sizeof(int32_t)*header.size*header.nbAnt) != + sizeof(int32_t)*header.size*header.nbAnt + ) { + printf("error: %s\n", strerror(errno)); + exit(1); + } + readTS=header.timestamp; } } From 2fc638464233baf81b811ecbdd434b7ec583cbc2 Mon Sep 17 00:00:00 2001 From: laurent Date: Mon, 7 Oct 2019 17:56:46 +0200 Subject: [PATCH 039/240] first version with UL and DL traffic good throughput --- executables/main-fs6.c | 18 ++++++++++++------ executables/split_headers.h | 2 ++ openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c | 2 +- openair2/PHY_INTERFACE/IF_Module.c | 6 +++--- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index dbfa0a4cbb..edd3f24f05 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -19,7 +19,7 @@ #include #include -#define FS6_BUF_SIZE 100*1000 +#define FS6_BUF_SIZE 1000*1000 static UDPsock_t sockFS6; int sum(uint8_t *b, int s) { @@ -296,6 +296,9 @@ void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_ eNB->pusch_vars[UE_id]->ulsch_power, sizeof(int)*2); hULUE(newUDPheader)->cqi_crc_status=eNB->ulsch[UE_id]->harq_processes[harq_pid]->cqi_crc_status; + hULUE(newUDPheader)->O_ACK=eNB->ulsch[UE_id]->harq_processes[harq_pid]->O_ACK; + memcpy(hULUE(newUDPheader)->o_ACK, eNB->ulsch[UE_id]->harq_processes[harq_pid]->o_ACK, + sizeof(eNB->ulsch[UE_id]->harq_processes[harq_pid]->o_ACK)); hULUE(newUDPheader)->ta=lte_est_timing_advance_pusch(eNB, UE_id); hULUE(newUDPheader)->segment=segmentID; memcpy(hULUE(newUDPheader)->o, eNB->ulsch[UE_id]->harq_processes[harq_pid]->o, @@ -379,7 +382,7 @@ void pusch_procedures_tosplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eN } void phy_procedures_eNB_uespec_RX_tosplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { - //RX processing for ue-specific resources (i + //RX processing for ue-specific resources LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; const int subframe = proc->subframe_rx; const int frame = proc->frame_rx; @@ -785,10 +788,13 @@ void recvFs6Ul(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, ul_propagat hULUE(bufPtr)->ulsch_power, sizeof(int)*2); ulsch_harq->cqi_crc_status=hULUE(bufPtr)->cqi_crc_status; + //ulsch_harq->O_ACK= hULUE(bufPtr)->O_ACK; + memcpy(ulsch_harq->o_ACK, hULUE(bufPtr)->o_ACK, + sizeof(ulsch_harq->o_ACK)); memcpy(ulsch_harq->o,hULUE(bufPtr)->o, sizeof(ulsch_harq->o)); ul_propa[hULUE(bufPtr)->UE_id].ta=hULUE(bufPtr)->ta; - LOG_I(PHY,"Received ulsch data for: rnti:%d, fsf: %d/%d, cqi_crc_status %d \n", - ulsch->rnti, eNB->proc.frame_rx, eNB->proc.subframe_rx, ulsch_harq->cqi_crc_status); + LOG_D(PHY,"Received ulsch data for: rnti:%d, fsf: %d/%d, cqi_crc_status %d O_ACK: %di, segment: %di, seglen: %d \n", + ulsch->rnti, eNB->proc.frame_rx, eNB->proc.subframe_rx, ulsch_harq->cqi_crc_status, ulsch_harq->O_ACK,hULUE(bufPtr)->segment , hULUE(bufPtr)->segLen); } else if ( type == fs6ULcch ) { int nb_uci=hULUEuci(bufPtr)->nb_active_ue; fs6_ul_uespec_uci_element_t *tmp=(fs6_ul_uespec_uci_element_t *)(hULUEuci(bufPtr)+1); @@ -938,8 +944,8 @@ void rcvFs6DL(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, int frame, i cpyVal(delta_TF); cpyVal(repetition_number ); cpyVal(total_number_of_repetitions); - LOG_I(PHY,"Received request to perform ulsch for: rnti:%d, fsf: %d/%d\n", - ulsch->rnti, frame, subframe); + LOG_D(PHY,"Received request to perform ulsch for: rnti:%d, fsf: %d/%d, O_ACK: %d\n", + ulsch->rnti, frame, subframe, ulsch_harq->O_ACK); } } else if ( type == fs6ULConfigCCH ) { fs6_dl_uespec_ulcch_element_t *tmp=(fs6_dl_uespec_ulcch_element_t *)(hTxULcch(bufPtr)+1); diff --git a/executables/split_headers.h b/executables/split_headers.h index 87c8176b9a..04e70bb469 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -174,6 +174,8 @@ typedef struct { uint8_t segment; int segLen; int ulsch_power[2]; + uint8_t o_ACK[4]; + uint8_t O_ACK; int ta; uint8_t o[MAX_CQI_BYTES]; uint8_t cqi_crc_status; diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index f51fc3035b..c4b8dc7755 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -672,7 +672,7 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) printf("\n"); } */ - return 0; + continue; } #endif diff --git a/openair2/PHY_INTERFACE/IF_Module.c b/openair2/PHY_INTERFACE/IF_Module.c index 2cc43189c6..98d099add8 100644 --- a/openair2/PHY_INTERFACE/IF_Module.c +++ b/openair2/PHY_INTERFACE/IF_Module.c @@ -388,10 +388,10 @@ static void dump_ul(UL_IND_t *u) { A("XXXX crc_ind %d\n", u->crc_ind.crc_indication_body.number_of_crcs); A("XXXX sr_ind %d\n", u->sr_ind.sr_indication_body.number_of_srs); - A("XXXX cqi_ind %d\n", u->cqi_ind.number_of_cqis); + A("XXXX cqi_ind %d\n", u->cqi_ind.cqi_indication_body.number_of_cqis); - for (i = 0; i < u->cqi_ind.number_of_cqis; i++) { - nfapi_cqi_indication_pdu_t *v = &u->cqi_ind.cqi_pdu_list[i]; + for (i = 0; i < u->cqi_ind.cqi_indication_body.number_of_cqis; i++) { + nfapi_cqi_indication_pdu_t *v = &u->cqi_ind.cqi_indication_body.cqi_pdu_list[i]; A("XXXX cqi ind %d\n", i); A("XXXX cqi ul_cqi %d channel %d\n", v->ul_cqi_information.ul_cqi, v->ul_cqi_information.channel); From 93f6e2446b4a094f2d1f8653e67a61f716008a2a Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Wed, 16 Oct 2019 18:01:40 +0200 Subject: [PATCH 040/240] CI: increasing the repeat count since the 1st try will always fail Signed-off-by: Raphael Defosseux --- ci-scripts/xml_files/inria/enb_usrp210_band7_test_05mhz_tm1.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/xml_files/inria/enb_usrp210_band7_test_05mhz_tm1.xml b/ci-scripts/xml_files/inria/enb_usrp210_band7_test_05mhz_tm1.xml index 5843539f72..2d34439ef7 100644 --- a/ci-scripts/xml_files/inria/enb_usrp210_band7_test_05mhz_tm1.xml +++ b/ci-scripts/xml_files/inria/enb_usrp210_band7_test_05mhz_tm1.xml @@ -25,7 +25,7 @@ test-05-tm1 Test-05MHz-TM1 tasks - 2 + 4 030201 040101 030102 000002 040301 000002 040504 000001 040401 000002 030201 From 2e0890751307ab9353067285d0aa57a20e169148 Mon Sep 17 00:00:00 2001 From: Laurent Date: Thu, 17 Oct 2019 11:14:23 +0200 Subject: [PATCH 041/240] Move split 6 to do rate matching (puncturing) in CU --- enb.fs6.example.conf | 4 +- executables/main-fs6.c | 138 ++++---------------- executables/split_headers.h | 4 +- openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c | 69 +++------- 4 files changed, 48 insertions(+), 167 deletions(-) diff --git a/enb.fs6.example.conf b/enb.fs6.example.conf index 6102f91756..d5e5609dd0 100644 --- a/enb.fs6.example.conf +++ b/enb.fs6.example.conf @@ -276,9 +276,9 @@ rfsimulator : global_log_verbosity ="medium"; hw_log_level ="info"; hw_log_verbosity ="medium"; - phy_log_level ="info"; + phy_log_level ="debug"; phy_log_verbosity ="medium"; - mac_log_level ="info"; + mac_log_level ="debug"; mac_log_verbosity ="high"; rlc_log_level ="info"; rlc_log_verbosity ="medium"; diff --git a/executables/main-fs6.c b/executables/main-fs6.c index df1c2810cd..8e57e75c6a 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -272,7 +272,8 @@ void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI * newUDPheader->contentBytes+=sizeof(fs6_ul_uespec_uci_element_t); } -void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen) { + +void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset) { uint8_t *bufferZone=eNB->FS6bufferZone; commonUDP_t *FirstUDPheader=(commonUDP_t *) bufferZone; // move to the end @@ -298,13 +299,15 @@ void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_ hULUE(newUDPheader)->cqi_crc_status=eNB->ulsch[UE_id]->harq_processes[harq_pid]->cqi_crc_status; hULUE(newUDPheader)->O_ACK=eNB->ulsch[UE_id]->harq_processes[harq_pid]->O_ACK; memcpy(hULUE(newUDPheader)->o_ACK, eNB->ulsch[UE_id]->harq_processes[harq_pid]->o_ACK, - sizeof(eNB->ulsch[UE_id]->harq_processes[harq_pid]->o_ACK)); + sizeof(eNB->ulsch[UE_id]->harq_processes[harq_pid]->o_ACK)); hULUE(newUDPheader)->ta=lte_est_timing_advance_pusch(eNB, UE_id); hULUE(newUDPheader)->segment=segmentID; memcpy(hULUE(newUDPheader)->o, eNB->ulsch[UE_id]->harq_processes[harq_pid]->o, sizeof(eNB->ulsch[UE_id]->harq_processes[harq_pid]->o)); memcpy(hULUE(newUDPheader)+1, data, dataLen); hULUE(newUDPheader)->segLen=dataLen; + hULUE(newUDPheader)->r_offset=r_offset; + hULUE(newUDPheader)->G=eNB->ulsch[UE_id]->harq_processes[harq_pid]->G; } void pusch_procedures_tosplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { @@ -427,102 +430,6 @@ void phy_procedures_eNB_uespec_RX_tosplit(uint8_t *bufferZone, int bufSize, PHY_ return; } -int ulsch_decoding_process(PHY_VARS_eNB *eNB, int UE_id, int llr8_flag) { - int harq_pid; - LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id]; - - if (ulsch->ue_type>0) - harq_pid = 0; - else - harq_pid = subframe2harq_pid(&eNB->frame_parms,eNB->proc.frame_rx,eNB->proc.subframe_rx); - - LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; - decoder_if_t *tc; - int offset, ret=-1; - - if (llr8_flag == 0) - tc = *decoder16; - else - tc = *decoder8; - - // This is a new packet, so compute quantities regarding segmentation - // Fixme: very dirty: all the variables produced by let_segmentation are only used localy - // Furthermore, variables as 1 letter and global is "time consuming" for everybody !!! - ulsch_harq->B = ulsch_harq->TBS+24; - lte_segmentation(NULL, - NULL, - ulsch_harq->B, - &ulsch_harq->C, - &ulsch_harq->Cplus, - &ulsch_harq->Cminus, - &ulsch_harq->Kplus, - &ulsch_harq->Kminus, - &ulsch_harq->F); - - for (int r=0; rC; r++) { - // printf("before subblock deinterleaving c[%d] = %p\n",r,ulsch_harq->c[r]); - // Get Turbo interleaver parameters - int Kr; - - if (rCminus) - Kr = ulsch_harq->Kminus; - else - Kr = ulsch_harq->Kplus; - - int Kr_bytes = Kr>>3; - int crc_type; - - if (ulsch_harq->C == 1) - crc_type = CRC24_A; - else - crc_type = CRC24_B; - - start_meas(&eNB->ulsch_turbo_decoding_stats); - ret = tc(&ulsch_harq->d[r][96], - NULL, - ulsch_harq->c[r], - NULL, - Kr, - ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS, - crc_type, - (r==0) ? ulsch_harq->F : 0, - &eNB->ulsch_tc_init_stats, - &eNB->ulsch_tc_alpha_stats, - &eNB->ulsch_tc_beta_stats, - &eNB->ulsch_tc_gamma_stats, - &eNB->ulsch_tc_ext_stats, - &eNB->ulsch_tc_intl1_stats, - &eNB->ulsch_tc_intl2_stats); - stop_meas(&eNB->ulsch_turbo_decoding_stats); - - // Reassembly of Transport block here - - if (ret != (1+ulsch->max_turbo_iterations)) { - if (rCminus) - Kr = ulsch_harq->Kminus; - else - Kr = ulsch_harq->Kplus; - - Kr_bytes = Kr>>3; - - if (r==0) { - memcpy(ulsch_harq->b, - &ulsch_harq->c[0][(ulsch_harq->F>>3)], - Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0)); - offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0); - } else { - memcpy(ulsch_harq->b+offset, - ulsch_harq->c[r], - Kr_bytes - ((ulsch_harq->C>1)?3:0)); - offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); - } - } else { - break; - } - } - - return(ret); -} void fill_rx_indication_from_split(uint8_t *bufferZone, PHY_VARS_eNB *eNB,int UE_id,int frame,int subframe, ul_propagation_t *ul_propa) { nfapi_rx_indication_pdu_t *pdu; @@ -645,16 +552,19 @@ void pusch_procedures_fromsplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB * } start_meas(&eNB->ulsch_decoding_stats); - /* - int ret = ulsch_decoding(eNB,&eNB->proc.L1_proc, - i, - 0, // control_only_flag - ulsch_harq->V_UL_DAI, - ulsch_harq->nb_rb>20 ? 1 : 0); - */ - int ret = ulsch_decoding_process(eNB, - i, - ulsch_harq->nb_rb>20 ? 1 : 0); + // This is a new packet, so compute quantities regarding segmentation + ulsch_harq->B = ulsch_harq->TBS+24; + lte_segmentation(NULL, + NULL, + ulsch_harq->B, + &ulsch_harq->C, + &ulsch_harq->Cplus, + &ulsch_harq->Cminus, + &ulsch_harq->Kplus, + &ulsch_harq->Kminus, + &ulsch_harq->F); + int ret = ulsch_decoding_data(eNB, i, harq_pid, + ulsch_harq->nb_rb>20 ? 1 : 0); stop_meas(&eNB->ulsch_decoding_stats); LOG_D(PHY, "[eNB %d][PUSCH %d] frame %d subframe %d RNTI %x RX power (%d,%d) N0 (%d,%d) dB ACK (%d,%d), decoding iter %d ulsch_harq->cqi_crc_status:%d ackBits:%d ulsch_decoding_stats[t:%lld max:%lld]\n", @@ -781,20 +691,21 @@ void recvFs6Ul(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, ul_propagat if ( type == fs6ULsch) { LTE_eNB_ULSCH_t *ulsch =eNB->ulsch[hULUE(bufPtr)->UE_id]; LTE_UL_eNB_HARQ_t *ulsch_harq=ulsch->harq_processes[hULUE(bufPtr)->harq_id]; - memcpy(&ulsch_harq->d[hULUE(bufPtr)->segment][96], + memcpy(ulsch_harq->e+hULUE(bufPtr)->r_offset, hULUE(bufPtr)+1, hULUE(bufPtr)->segLen); memcpy(eNB->pusch_vars[hULUE(bufPtr)->UE_id]->ulsch_power, hULUE(bufPtr)->ulsch_power, sizeof(int)*2); + ulsch_harq->G=hULUE(bufPtr)->G; ulsch_harq->cqi_crc_status=hULUE(bufPtr)->cqi_crc_status; - //ulsch_harq->O_ACK= hULUE(bufPtr)->O_ACK; - memcpy(ulsch_harq->o_ACK, hULUE(bufPtr)->o_ACK, - sizeof(ulsch_harq->o_ACK)); + //ulsch_harq->O_ACK= hULUE(bufPtr)->O_ACK; + memcpy(ulsch_harq->o_ACK, hULUE(bufPtr)->o_ACK, + sizeof(ulsch_harq->o_ACK)); memcpy(ulsch_harq->o,hULUE(bufPtr)->o, sizeof(ulsch_harq->o)); ul_propa[hULUE(bufPtr)->UE_id].ta=hULUE(bufPtr)->ta; LOG_D(PHY,"Received ulsch data for: rnti:%x, fsf: %d/%d, cqi_crc_status %d O_ACK: %di, segment: %di, seglen: %d \n", - ulsch->rnti, eNB->proc.frame_rx, eNB->proc.subframe_rx, ulsch_harq->cqi_crc_status, ulsch_harq->O_ACK,hULUE(bufPtr)->segment , hULUE(bufPtr)->segLen); + ulsch->rnti, eNB->proc.frame_rx, eNB->proc.subframe_rx, ulsch_harq->cqi_crc_status, ulsch_harq->O_ACK,hULUE(bufPtr)->segment, hULUE(bufPtr)->segLen); } else if ( type == fs6ULcch ) { int nb_uci=hULUEuci(bufPtr)->nb_active_ue; fs6_ul_uespec_uci_element_t *tmp=(fs6_ul_uespec_uci_element_t *)(hULUEuci(bufPtr)+1); @@ -1157,6 +1068,7 @@ void appendFs6TxULUE(uint8_t *bufferZone, LTE_DL_FRAME_PARMS *fp, int curUE, LTE memcpyToDuHarq(total_number_of_repetitions); LOG_D(PHY,"Added request to perform ulsch for: rnti:%x, fsf: %d/%d\n", ulsch->rnti, frame, subframe); } + void appendFs6DLUE(uint8_t *bufferZone, LTE_DL_FRAME_PARMS *fp, int UE_id, int8_t harq_pid, LTE_eNB_DLSCH_t *dlsch0, LTE_DL_eNB_HARQ_t *harqData, int frame, int subframe) { commonUDP_t *FirstUDPheader=(commonUDP_t *) bufferZone; // move to the end diff --git a/executables/split_headers.h b/executables/split_headers.h index 673628b8e0..4a8afc9c85 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -173,6 +173,8 @@ typedef struct { uint8_t harq_id; uint8_t segment; int segLen; + int r_offset; + int G; int ulsch_power[2]; uint8_t o_ACK[4]; uint8_t O_ACK; @@ -230,7 +232,7 @@ static inline void *commonUDPdata(uint8_t *ptr) { void setAllfromTS(uint64_t TS); void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB,LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, uint16_t rnti, int32_t stat); -void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen); +void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset); void *cu_fs6(void *arg); void *du_fs6(void *arg); void fill_rf_config(RU_t *ru, char *rf_config_file); diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index 5d39076d08..f7bea46744 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -279,14 +279,6 @@ int ulsch_decoding_data_2thread0(td_params *tdp) { ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8), (uint8_t *)&dummy_w[r][0], (r==0) ? ulsch_harq->F : 0); -#ifdef DEBUG_ULSCH_DECODING - printf("Rate Matching Segment %u (coded bits (G) %d,unpunctured/repeated bits %u, Q_m %d, nb_rb %d, Nl %d)...\n", - r, G, - Kr*3, - Q_m, - nb_rb, - ulsch_harq->Nl); -#endif if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r], G, @@ -453,14 +445,6 @@ int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8), (uint8_t *)&dummy_w[r][0], (r==0) ? ulsch_harq->F : 0); -#ifdef DEBUG_ULSCH_DECODING - printf("Rate Matching Segment %u (coded bits (G) %d,unpunctured/repeated bits %u, Q_m %d, nb_rb %d, Nl %d)...\n", - r, G, - Kr*3, - Q_m, - nb_rb, - ulsch_harq->Nl); -#endif start_meas(&eNB->ulsch_rate_unmatching_stats); if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r], @@ -583,13 +567,29 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) (uint8_t *)&dummy_w[r][0], (r==0) ? ulsch_harq->F : 0); #ifdef DEBUG_ULSCH_DECODING - printf("Rate Matching Segment %u (coded bits (G) %d,unpunctured/repeated bits %u, Q_m %d, nb_rb %d, Nl %d)...\n", + printf("Rate Matching Segment %u (coded bits (G) %d,unpunctured/repeated bits %u, Q_m %d, Nl %d, r_offset %d)...\n", r, G, Kr*3, ulsch_harq->Qm, - ulsch_harq->Nl); + ulsch_harq->Nl, r_offset); #endif start_meas(&eNB->ulsch_rate_unmatching_stats); + #ifdef FS6 + if ( getenv("fs6") != NULL && strncasecmp( getenv("fs6"), "du", 2) == 0 ) { + int Gp=G/ulsch_harq->Qm; + int GpmodC = Gp%ulsch_harq->C; + + if (r < (ulsch_harq->C-(GpmodC))) + E = ulsch_harq->Qm * (Gp/ulsch_harq->C); + else + E = ulsch_harq->Qm * ((GpmodC==0?0:1) + (Gp/ulsch_harq->C)); + sendFs6Ul(eNB, UE_id, harq_pid, r, ulsch_harq->e+r_offset, E*sizeof(int16_t), r_offset); + + r_offset += E; + continue; + } + + #endif if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r], G, @@ -639,39 +639,6 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) crc_type = CRC24_A; else crc_type = CRC24_B; -#ifdef FS6 - if ( getenv("fs6") != NULL && strncasecmp( getenv("fs6"), "du", 2) == 0 ) { - // r is the segment id, - // Kr is the segment length in short - // *3 because LTE redudancy scheme - sendFs6Ul(eNB, UE_id, harq_pid, r, &ulsch_harq->d[r][96], Kr*sizeof(int16_t)*3); -/* - int iter=tc(&ulsch_harq->d[r][96], - NULL, - ulsch_harq->c[r], - NULL, - Kr, - ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS, - crc_type, - (r==0) ? ulsch_harq->F : 0, - &eNB->ulsch_tc_init_stats, - &eNB->ulsch_tc_alpha_stats, - &eNB->ulsch_tc_beta_stats, - &eNB->ulsch_tc_gamma_stats, - &eNB->ulsch_tc_ext_stats, - &eNB->ulsch_tc_intl1_stats, - &eNB->ulsch_tc_intl2_stats); - LOG_D(PHY, "Cu should decode in %d iter\n",iter); - if ( 1) { //iter == 5 ) { - for (int i=0; i < Kr; i++ ) - printf("%hhx:", ulsch_harq->d[r][96+i]); - printf("\n"); - } -*/ - continue; - } - - #endif start_meas(&eNB->ulsch_turbo_decoding_stats); ret = tc(&ulsch_harq->d[r][96], NULL, From 61041b4275a546cd94fdd33bd98925a22f353e06 Mon Sep 17 00:00:00 2001 From: Laurent Date: Thu, 17 Oct 2019 15:04:20 +0200 Subject: [PATCH 042/240] add du measurements --- enb.fs6.example.conf | 4 ++-- executables/main-fs6.c | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/enb.fs6.example.conf b/enb.fs6.example.conf index d5e5609dd0..6102f91756 100644 --- a/enb.fs6.example.conf +++ b/enb.fs6.example.conf @@ -276,9 +276,9 @@ rfsimulator : global_log_verbosity ="medium"; hw_log_level ="info"; hw_log_verbosity ="medium"; - phy_log_level ="debug"; + phy_log_level ="info"; phy_log_verbosity ="medium"; - mac_log_level ="debug"; + mac_log_level ="info"; mac_log_verbosity ="high"; rlc_log_level ="info"; rlc_log_verbosity ="medium"; diff --git a/executables/main-fs6.c b/executables/main-fs6.c index 8e57e75c6a..074b4c8770 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -1497,10 +1497,18 @@ void *du_fs6(void *arg) { else LOG_I(PHY,"RU %d rf device ready\n",ru->idx); } else LOG_I(PHY,"RU %d no rf device\n",ru->idx); + initStaticTime(begingWait); + initRefTimes(waitRxAndProcessingUL); + initRefTimes(makeSendDL); + while(1) { L1_proc_t *proc = &ru->eNB_list[0]->proc; + pickStaticTime(begingWait); UL_du_fs6(ru, proc->frame_rx,proc->subframe_rx); + updateTimes(begingWait, &waitRxAndProcessingUL, 1000, "DU Time in wait Rx + Ul processing"); + pickStaticTime(begingWait); DL_du_fs6(ru); + updateTimes(begingWait, &makeSendDL, 1000, "DU Time in build and send Tx"); } return NULL; From 80b89510b7d41673cef6783bca87a358f6399754 Mon Sep 17 00:00:00 2001 From: Laurent Date: Thu, 17 Oct 2019 15:15:19 +0200 Subject: [PATCH 043/240] add cu and full loop measurements --- executables/main-fs6.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index 074b4c8770..42b016919c 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -1464,11 +1464,22 @@ void *cu_fs6(void *arg) { AssertFatal(createUDPsock(NULL, CU_PORT, remoteIP, DU_PORT, &sockFS6), ""); uint64_t timeStamp=0; + initStaticTime(begingWait); + initStaticTime(begingWait2); + initRefTimes(waitDUAndProcessingUL); + initRefTimes(makeSendDL); + initRefTimes(fullLoop); while(1) { timeStamp+=ru->frame_parms.samples_per_tti; + updateTimes(begingWait, &fullLoop, 1000, "CU for full SubFrame (must be less 1ms)"); + pickStaticTime(begingWait); + updateTimes(begingWait, &waitDUAndProcessingUL, 1000, "CU Time in wait Rx + Ul processing"); UL_cu_fs6(ru, &timeStamp); + pickStaticTime(begingWait2); DL_cu_fs6(ru); + updateTimes(begingWait2, &makeSendDL, 1000, "CU Time in DL build+send"); + } return NULL; @@ -1498,17 +1509,20 @@ void *du_fs6(void *arg) { } else LOG_I(PHY,"RU %d no rf device\n",ru->idx); initStaticTime(begingWait); - initRefTimes(waitRxAndProcessingUL); + initStaticTime(begingWait2); + initRefTimes(waitRxAndProcessingUL); initRefTimes(makeSendDL); + initRefTimes(fullLoop); while(1) { L1_proc_t *proc = &ru->eNB_list[0]->proc; + updateTimes(begingWait, &fullLoop, 1000, "DU for full SubFrame (must be less 1ms)"); pickStaticTime(begingWait); UL_du_fs6(ru, proc->frame_rx,proc->subframe_rx); updateTimes(begingWait, &waitRxAndProcessingUL, 1000, "DU Time in wait Rx + Ul processing"); - pickStaticTime(begingWait); + pickStaticTime(begingWait2); DL_du_fs6(ru); - updateTimes(begingWait, &makeSendDL, 1000, "DU Time in build and send Tx"); + updateTimes(begingWait2, &makeSendDL, 1000, "DU Time in build and send Tx"); } return NULL; From 282a60fd561e93c96931802a063f3d5b098f1bc1 Mon Sep 17 00:00:00 2001 From: Laurent Date: Thu, 17 Oct 2019 15:29:20 +0200 Subject: [PATCH 044/240] reset measurements after print --- executables/main-fs6.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index 42b016919c..fb8fc9ada4 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -31,6 +31,20 @@ int sum(uint8_t *b, int s) { return sum; } +static inline void updateTimesReset(uint64_t start, Meas *M, int period, char *txt) { + if (start!=0) { + uint64_t end=rdtsc(); + long long diff=(end-start)/(cpuf*1000); + M->maxArray[0]=diff; + M->sum+=diff; + M->iterations++; + qsort(M->maxArray, 11, sizeof(uint64_t), cmpint); + printMeas(txt,M,period); + if (M->iterations%period == 0 ) + bzero(M,sizeof(*M)); + } +} + #define ceil16_bytes(a) ((((a+15)/16)*16)/8) static void fs6Dlunpack(void *out, void *in, int szUnpacked) { static uint64_t *lut=NULL; @@ -1472,13 +1486,13 @@ void *cu_fs6(void *arg) { while(1) { timeStamp+=ru->frame_parms.samples_per_tti; - updateTimes(begingWait, &fullLoop, 1000, "CU for full SubFrame (must be less 1ms)"); + updateTimesReset(begingWait, &fullLoop, 1000, "CU for full SubFrame (must be less 1ms)"); pickStaticTime(begingWait); - updateTimes(begingWait, &waitDUAndProcessingUL, 1000, "CU Time in wait Rx + Ul processing"); + updateTimesReset(begingWait, &waitDUAndProcessingUL, 1000, "CU Time in wait Rx + Ul processing"); UL_cu_fs6(ru, &timeStamp); pickStaticTime(begingWait2); DL_cu_fs6(ru); - updateTimes(begingWait2, &makeSendDL, 1000, "CU Time in DL build+send"); + updateTimesReset(begingWait2, &makeSendDL, 1000, "CU Time in DL build+send"); } @@ -1509,20 +1523,20 @@ void *du_fs6(void *arg) { } else LOG_I(PHY,"RU %d no rf device\n",ru->idx); initStaticTime(begingWait); - initStaticTime(begingWait2); - initRefTimes(waitRxAndProcessingUL); + initStaticTime(begingWait2); + initRefTimes(waitRxAndProcessingUL); initRefTimes(makeSendDL); initRefTimes(fullLoop); while(1) { L1_proc_t *proc = &ru->eNB_list[0]->proc; - updateTimes(begingWait, &fullLoop, 1000, "DU for full SubFrame (must be less 1ms)"); + updateTimesReset(begingWait, &fullLoop, 1000, "DU for full SubFrame (must be less 1ms)"); pickStaticTime(begingWait); UL_du_fs6(ru, proc->frame_rx,proc->subframe_rx); - updateTimes(begingWait, &waitRxAndProcessingUL, 1000, "DU Time in wait Rx + Ul processing"); + updateTimesReset(begingWait, &waitRxAndProcessingUL, 1000, "DU Time in wait Rx + Ul processing"); pickStaticTime(begingWait2); DL_du_fs6(ru); - updateTimes(begingWait2, &makeSendDL, 1000, "DU Time in build and send Tx"); + updateTimesReset(begingWait2, &makeSendDL, 1000, "DU Time in build and send Tx"); } return NULL; From 63f04fe72c8cb3faa7fcdf142b006830ff9f370a Mon Sep 17 00:00:00 2001 From: Laurent Date: Thu, 17 Oct 2019 15:52:41 +0200 Subject: [PATCH 045/240] flush traces --- executables/main-fs6.c | 9 +++++++++ executables/main-ocp.c | 1 + 2 files changed, 10 insertions(+) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index fb8fc9ada4..12904d378d 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -1373,7 +1373,12 @@ void DL_du_fs6(RU_t *ru) { void UL_du_fs6(RU_t *ru, int frame, int subframe) { RU_proc_t *ru_proc=&ru->proc; + initStaticTime(begingWait); + initRefTimes(fullLoop); + pickStaticTime(begingWait); rx_rf(ru); + updateTimesReset(begingWait, &fullLoop, 1000, "DU wait USRP"); + setAllfromTS(ru_proc->timestamp_rx); // front end processing: convert from time domain to frequency domain // fills rxdataF buffer @@ -1434,7 +1439,11 @@ void DL_cu_fs6(RU_t *ru) { void UL_cu_fs6(RU_t *ru, uint64_t *TS) { initBufferZone(bufferZone); + initStaticTime(begingWait); + initRefTimes(fullLoop); + pickStaticTime(begingWait); int nb_blocks=receiveSubFrame(&sockFS6, bufferZone, sizeof(bufferZone), CTsentDUv0 ); + updateTimesReset(begingWait, &fullLoop, 1000, "CU wait DU"); if (nb_blocks ==0) { LOG_W(PHY, "CU lost a subframe\n"); diff --git a/executables/main-ocp.c b/executables/main-ocp.c index cfec3b336c..afcc1a2363 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -746,6 +746,7 @@ void tx_rf(RU_t *ru) { } static void *ru_thread( void *param ) { + setbuf(stdout, NULL); RU_t *ru = (RU_t *)param; if (ru->if_south == LOCAL_RF) { // configure RF parameters only From 24de1caad6ca01d71048bf962a1b38308384a548 Mon Sep 17 00:00:00 2001 From: Laurent Date: Thu, 17 Oct 2019 16:01:30 +0200 Subject: [PATCH 046/240] flush traces --- executables/main-ocp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/executables/main-ocp.c b/executables/main-ocp.c index afcc1a2363..e1c3c94d4d 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -747,6 +747,7 @@ void tx_rf(RU_t *ru) { static void *ru_thread( void *param ) { setbuf(stdout, NULL); + setbuf(stderr, NULL); RU_t *ru = (RU_t *)param; if (ru->if_south == LOCAL_RF) { // configure RF parameters only From 280e12ba4f425fb0a158821d109d270249955c53 Mon Sep 17 00:00:00 2001 From: Laurent Date: Thu, 17 Oct 2019 16:03:39 +0200 Subject: [PATCH 047/240] flush traces --- executables/main-fs6.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index 12904d378d..966a198654 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -1472,6 +1472,9 @@ void UL_cu_fs6(RU_t *ru, uint64_t *TS) { } void *cu_fs6(void *arg) { + setbuf(stdout, NULL); + setbuf(stderr, NULL); + RU_t *ru = (RU_t *)arg; //RU_proc_t *proc = &ru->proc; fill_rf_config(ru,ru->rf_config_file); @@ -1509,6 +1512,9 @@ void *cu_fs6(void *arg) { } void *du_fs6(void *arg) { + setbuf(stdout, NULL); + setbuf(stderr, NULL); + RU_t *ru = (RU_t *)arg; //RU_proc_t *proc = &ru->proc; fill_rf_config(ru,ru->rf_config_file); From 03dda0d890f72c6f6792f3ee47aee8a4434421ee Mon Sep 17 00:00:00 2001 From: Laurent Date: Thu, 17 Oct 2019 16:30:45 +0200 Subject: [PATCH 048/240] flush traces --- executables/main-fs6.c | 58 ++++++++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index 966a198654..42cd146ee2 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -31,17 +31,49 @@ int sum(uint8_t *b, int s) { return sum; } -static inline void updateTimesReset(uint64_t start, Meas *M, int period, char *txt) { +static inline int cmpintRev(const void *a, const void *b) { + uint64_t *aa=(uint64_t *)a; + uint64_t *bb=(uint64_t *)b; + return (int)(*bb-*aa); +} + +static inline void printMeas2(char *txt, Meas *M, int period, bool MaxMin) { + if (M->iterations%period == 0 ) { + char txt2[512]; + sprintf(txt2,"%s avg=%" PRIu64 " iterations=%" PRIu64 " %s=%" + PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 "\n", + txt, + M->sum/M->iterations, + M->iterations, + MaxMin?"max":"min", + M->maxArray[1],M->maxArray[2], M->maxArray[3],M->maxArray[4], M->maxArray[5], + M->maxArray[6],M->maxArray[7], M->maxArray[8],M->maxArray[9],M->maxArray[10]); +#if T_TRACER + LOG_W(PHY,"%s",txt2); +#else + printf("%s",txt2); +#endif + } +} + +static inline void updateTimesReset(uint64_t start, Meas *M, int period, bool MaxMin, char *txt) { if (start!=0) { uint64_t end=rdtsc(); long long diff=(end-start)/(cpuf*1000); M->maxArray[0]=diff; M->sum+=diff; M->iterations++; - qsort(M->maxArray, 11, sizeof(uint64_t), cmpint); - printMeas(txt,M,period); - if (M->iterations%period == 0 ) - bzero(M,sizeof(*M)); + if ( MaxMin) + qsort(M->maxArray, 11, sizeof(uint64_t), cmpint); + else + qsort(M->maxArray, 11, sizeof(uint64_t), cmpintRev); + printMeas2(txt,M,period, MaxMin); + if (M->iterations%period == 0 ) { + bzero(M,sizeof(*M)); + if (!MaxMin) + for (int i=0;i<11;i++) + M->maxArray[i]=INT_MAX; + } } } @@ -1377,7 +1409,7 @@ void UL_du_fs6(RU_t *ru, int frame, int subframe) { initRefTimes(fullLoop); pickStaticTime(begingWait); rx_rf(ru); - updateTimesReset(begingWait, &fullLoop, 1000, "DU wait USRP"); + updateTimesReset(begingWait, &fullLoop, 1000, false, "DU wait USRP"); setAllfromTS(ru_proc->timestamp_rx); // front end processing: convert from time domain to frequency domain @@ -1443,7 +1475,7 @@ void UL_cu_fs6(RU_t *ru, uint64_t *TS) { initRefTimes(fullLoop); pickStaticTime(begingWait); int nb_blocks=receiveSubFrame(&sockFS6, bufferZone, sizeof(bufferZone), CTsentDUv0 ); - updateTimesReset(begingWait, &fullLoop, 1000, "CU wait DU"); + updateTimesReset(begingWait, &fullLoop, 1000, false, "CU wait DU"); if (nb_blocks ==0) { LOG_W(PHY, "CU lost a subframe\n"); @@ -1498,13 +1530,13 @@ void *cu_fs6(void *arg) { while(1) { timeStamp+=ru->frame_parms.samples_per_tti; - updateTimesReset(begingWait, &fullLoop, 1000, "CU for full SubFrame (must be less 1ms)"); + updateTimesReset(begingWait, &fullLoop, 1000, true, "CU for full SubFrame (must be less 1ms)"); pickStaticTime(begingWait); - updateTimesReset(begingWait, &waitDUAndProcessingUL, 1000, "CU Time in wait Rx + Ul processing"); + updateTimesReset(begingWait, &waitDUAndProcessingUL, 1000, true,"CU Time in wait Rx + Ul processing"); UL_cu_fs6(ru, &timeStamp); pickStaticTime(begingWait2); DL_cu_fs6(ru); - updateTimesReset(begingWait2, &makeSendDL, 1000, "CU Time in DL build+send"); + updateTimesReset(begingWait2, &makeSendDL, 1000, true,"CU Time in DL build+send"); } @@ -1545,13 +1577,13 @@ void *du_fs6(void *arg) { while(1) { L1_proc_t *proc = &ru->eNB_list[0]->proc; - updateTimesReset(begingWait, &fullLoop, 1000, "DU for full SubFrame (must be less 1ms)"); + updateTimesReset(begingWait, &fullLoop, 1000, true,"DU for full SubFrame (must be less 1ms)"); pickStaticTime(begingWait); UL_du_fs6(ru, proc->frame_rx,proc->subframe_rx); - updateTimesReset(begingWait, &waitRxAndProcessingUL, 1000, "DU Time in wait Rx + Ul processing"); + updateTimesReset(begingWait, &waitRxAndProcessingUL, 1000, true,"DU Time in wait Rx + Ul processing"); pickStaticTime(begingWait2); DL_du_fs6(ru); - updateTimesReset(begingWait2, &makeSendDL, 1000, "DU Time in build and send Tx"); + updateTimesReset(begingWait2, &makeSendDL, 1000, true, "DU Time in build and send Tx"); } return NULL; From ae25c88372d609115afad1c23e573583a814ee1d Mon Sep 17 00:00:00 2001 From: Laurent Date: Thu, 17 Oct 2019 16:38:08 +0200 Subject: [PATCH 049/240] flush traces --- executables/main-fs6.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index 42cd146ee2..60dbf0014a 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -1381,8 +1381,12 @@ void phy_procedures_eNB_TX_tosplit(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx void DL_du_fs6(RU_t *ru) { for (int i=0; inum_eNB; i++) { initBufferZone(bufferZone); + initStaticTime(begingWait); + initRefTimes(fullLoop); + pickStaticTime(begingWait); int nb_blocks=receiveSubFrame(&sockFS6, bufferZone, sizeof(bufferZone), CTsentCUv0 ); - + updateTimesReset(begingWait, &fullLoop, 1000, false, "DU wait CU"); + if (nb_blocks > 0) { L1_proc_t *L1_proc = &ru->eNB_list[i]->proc; From 6b52ac7d584ff0c948e23279eb09207adf090b1f Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Thu, 17 Oct 2019 16:51:15 +0200 Subject: [PATCH 050/240] CI: looping on attach/ping/detach sequences Signed-off-by: Raphael Defosseux --- .../enb_usrp210_band7_test_05mhz_tm1.xml | 286 +++++++++++++++++- 1 file changed, 284 insertions(+), 2 deletions(-) diff --git a/ci-scripts/xml_files/inria/enb_usrp210_band7_test_05mhz_tm1.xml b/ci-scripts/xml_files/inria/enb_usrp210_band7_test_05mhz_tm1.xml index 2d34439ef7..f5e095ba8a 100644 --- a/ci-scripts/xml_files/inria/enb_usrp210_band7_test_05mhz_tm1.xml +++ b/ci-scripts/xml_files/inria/enb_usrp210_band7_test_05mhz_tm1.xml @@ -19,7 +19,7 @@ For more information about the OpenAirInterface (OAI) Software Alliance: contact@openairinterface.org - 030102 000002 040301 000002 040504 040605 040606 040645 040646 000001 040401 000002 030201 + 030103 000002 040301 000002 040504 040605 040606 040645 040646 000001 040401 000002 030201 --> test-05-tm1 @@ -28,7 +28,44 @@ 4 030201 040101 - 030102 000002 040301 000002 040504 000001 040401 000002 030201 + 030103 000002 040301 + 000002 040504 000001 + 000002 040505 000001 + 000002 040506 000001 + 000002 040507 000001 + 000002 040508 000001 + 000002 040509 000001 + 000002 040510 000001 + 000002 040511 000001 + 000002 040512 000001 + 000002 040513 000001 + 000002 040514 000001 + 000002 040515 000001 + 000002 040516 000001 + 000002 040517 000001 + 000002 040518 000001 + 000002 040519 000001 + 000002 040520 000001 + 000002 040521 000001 + 000002 040522 000001 + 000002 040523 000001 + 000002 040524 000001 + 000002 040525 000001 + 000002 040526 000001 + 000002 040527 000001 + 000002 040528 000001 + 000002 040529 000001 + 000002 040530 000001 + 000002 040531 000001 + 000002 040532 000001 + 000002 040533 000001 + 000002 040534 000001 + 000002 040535 000001 + 000002 040536 000001 + 000002 040537 000001 + 000002 040538 000001 + 000002 040539 000001 + 040401 000002 030201 @@ -77,6 +114,251 @@ 5 + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -I 192.168.248.159 -c 20 + 5 + + Iperf iperf (5MHz - DL/1Mbps/UDP)(30 sec) From 90b9cbb81df0934129c63c0f2ba54926bf54bfc3 Mon Sep 17 00:00:00 2001 From: Laurent Date: Fri, 18 Oct 2019 16:35:33 +0200 Subject: [PATCH 051/240] remove global for frame/subframe, noS1 attach+ traffic ok, UE do not compile --- executables/main-fs6.c | 135 +++--- executables/main-ocp.c | 143 ++---- executables/split_headers.h | 12 +- nfapi/oai_integration/nfapi_pnf.c | 11 +- nfapi/oai_integration/nfapi_vnf.c | 9 +- .../PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c | 2 +- .../lte_ul_channel_estimation.c | 2 +- openair1/PHY/LTE_TRANSPORT/dlsch_coding.c | 287 ------------ openair1/PHY/LTE_TRANSPORT/if5_tools.c | 7 +- openair1/PHY/LTE_TRANSPORT/if5_tools.h | 3 +- openair1/PHY/LTE_TRANSPORT/prach.c | 52 +-- openair1/PHY/LTE_TRANSPORT/transport_proto.h | 4 +- openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c | 317 ------------- openair1/PHY/defs_eNB.h | 416 +----------------- openair1/SCHED/fapi_l1.c | 4 +- openair1/SCHED/fapi_l1.h | 2 +- openair1/SCHED/phy_procedures_lte_eNb.c | 43 -- openair1/SCHED/prach_procedures.c | 14 +- openair1/SCHED/ru_procedures.c | 397 +---------------- openair1/SCHED/sched_common.h | 2 +- openair1/SCHED/sched_eNB.h | 4 +- openair1/SCHED_UE/phy_procedures_lte_ue.c | 2 +- openair2/PHY_INTERFACE/IF_Module.c | 4 +- openair2/PHY_INTERFACE/IF_Module.h | 48 +- 24 files changed, 242 insertions(+), 1678 deletions(-) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index 60dbf0014a..b7f4c62293 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -45,7 +45,7 @@ static inline void printMeas2(char *txt, Meas *M, int period, bool MaxMin) { txt, M->sum/M->iterations, M->iterations, - MaxMin?"max":"min", + MaxMin?"max":"min", M->maxArray[1],M->maxArray[2], M->maxArray[3],M->maxArray[4], M->maxArray[5], M->maxArray[6],M->maxArray[7], M->maxArray[8],M->maxArray[9],M->maxArray[10]); #if T_TRACER @@ -63,16 +63,20 @@ static inline void updateTimesReset(uint64_t start, Meas *M, int period, bool Ma M->maxArray[0]=diff; M->sum+=diff; M->iterations++; + if ( MaxMin) qsort(M->maxArray, 11, sizeof(uint64_t), cmpint); else qsort(M->maxArray, 11, sizeof(uint64_t), cmpintRev); + printMeas2(txt,M,period, MaxMin); + if (M->iterations%period == 0 ) { - bzero(M,sizeof(*M)); - if (!MaxMin) - for (int i=0;i<11;i++) - M->maxArray[i]=INT_MAX; + bzero(M,sizeof(*M)); + + if (!MaxMin) + for (int i=0; i<11; i++) + M->maxArray[i]=INT_MAX; } } } @@ -111,10 +115,10 @@ static void fs6Dlpack(void *out, void *in, int szUnpacked) { } } -void prach_eNB_tosplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB) { +void prach_eNB_tosplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc) { fs6_ul_t *header=(fs6_ul_t *) commonUDPdata(bufferZone); - if (is_prach_subframe(&eNB->frame_parms, eNB->proc.frame_prach,eNB->proc.subframe_prach)<=0) + if (is_prach_subframe(&eNB->frame_parms, proc->frame_prach,proc->subframe_prach)<=0) return; RU_t *ru; @@ -134,12 +138,13 @@ void prach_eNB_tosplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB) { } rx_prach(eNB, + proc, eNB->RU_list[0], header->max_preamble, header->max_preamble_energy, header->max_preamble_delay, header->avg_preamble_energy, - eNB->proc.frame_prach, + proc->frame_prach, 0, false ); @@ -166,20 +171,20 @@ void prach_eNB_tosplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB) { return; } -void prach_eNB_fromsplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB) { +void prach_eNB_fromsplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc) { fs6_ul_t *header=(fs6_ul_t *) commonUDPdata(bufferZone); uint16_t *max_preamble=header->max_preamble; uint16_t *max_preamble_energy=header->max_preamble_energy; uint16_t *max_preamble_delay=header->max_preamble_delay; uint16_t *avg_preamble_energy=header->avg_preamble_energy; - int subframe=eNB->proc.subframe_prach; - int frame=eNB->proc.frame_prach; + int subframe=proc->subframe_prach; + int frame=proc->frame_prach; // Fixme: not clear why we call twice with "br" and without int br_flag=0; if (br_flag==1) { int prach_mask; - prach_mask = is_prach_subframe (&eNB->frame_parms, eNB->proc.frame_prach_br, eNB->proc.subframe_prach_br); + prach_mask = is_prach_subframe (&eNB->frame_parms, proc->frame_prach_br, proc->subframe_prach_br); eNB->UL_INFO.rach_ind_br.rach_indication_body.preamble_list = eNB->preamble_list_br; int ind = 0; int ce_level = 0; @@ -563,10 +568,10 @@ void fill_rx_indication_from_split(uint8_t *bufferZone, PHY_VARS_eNB *eNB,int UE pthread_mutex_unlock(&eNB->UL_INFO_mutex); } -void pusch_procedures_fromsplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, ul_propagation_t *ul_propa) { +void pusch_procedures_fromsplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, ul_propagation_t *ul_propa) { //LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - const int subframe = eNB->proc.subframe_rx; - const int frame = eNB->proc.frame_rx; + const int subframe = proc->subframe_rx; + const int frame = proc->frame_rx; uint32_t harq_pid; uint32_t harq_pid0 = subframe2harq_pid(&eNB->frame_parms,frame,subframe); @@ -750,8 +755,8 @@ void recvFs6Ul(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, ul_propagat sizeof(ulsch_harq->o_ACK)); memcpy(ulsch_harq->o,hULUE(bufPtr)->o, sizeof(ulsch_harq->o)); ul_propa[hULUE(bufPtr)->UE_id].ta=hULUE(bufPtr)->ta; - LOG_D(PHY,"Received ulsch data for: rnti:%x, fsf: %d/%d, cqi_crc_status %d O_ACK: %di, segment: %di, seglen: %d \n", - ulsch->rnti, eNB->proc.frame_rx, eNB->proc.subframe_rx, ulsch_harq->cqi_crc_status, ulsch_harq->O_ACK,hULUE(bufPtr)->segment, hULUE(bufPtr)->segLen); + LOG_D(PHY,"Received ulsch data for: rnti:%x, cqi_crc_status %d O_ACK: %di, segment: %di, seglen: %d \n", + ulsch->rnti, ulsch_harq->cqi_crc_status, ulsch_harq->O_ACK,hULUE(bufPtr)->segment, hULUE(bufPtr)->segLen); } else if ( type == fs6ULcch ) { int nb_uci=hULUEuci(bufPtr)->nb_active_ue; fs6_ul_uespec_uci_element_t *tmp=(fs6_ul_uespec_uci_element_t *)(hULUEuci(bufPtr)+1); @@ -783,18 +788,18 @@ void recvFs6Ul(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, ul_propagat } } -void phy_procedures_eNB_uespec_RX_fromsplit(uint8_t *bufferZone, int nbBlocks,PHY_VARS_eNB *eNB) { +void phy_procedures_eNB_uespec_RX_fromsplit(uint8_t *bufferZone, int nbBlocks,PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc) { // The configuration arrived in Dl, so we can extract the UL data ul_propagation_t ul_propa[NUMBER_OF_UE_MAX]; recvFs6Ul(bufferZone, nbBlocks, eNB, ul_propa); // dirty memory allocation in OAI... for (int i = 0; i < NUMBER_OF_UCI_VARS_MAX; i++) - if ( eNB->uci_vars[i].frame == eNB->proc.frame_rx && - eNB->uci_vars[i].subframe == eNB->proc.subframe_rx ) + if ( eNB->uci_vars[i].frame == proc->frame_rx && + eNB->uci_vars[i].subframe == proc->subframe_rx ) eNB->uci_vars[i].active=0; - pusch_procedures_fromsplit(bufferZone, nbBlocks, eNB, ul_propa); + pusch_procedures_fromsplit(bufferZone, nbBlocks, eNB, proc, ul_propa); } void rcvFs6DL(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, int frame, int subframe) { @@ -1379,6 +1384,9 @@ void phy_procedures_eNB_TX_tosplit(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx } void DL_du_fs6(RU_t *ru) { + static uint64_t lastTS; + L1_rxtx_proc_t L1_proc; + for (int i=0; inum_eNB; i++) { initBufferZone(bufferZone); initStaticTime(begingWait); @@ -1386,42 +1394,38 @@ void DL_du_fs6(RU_t *ru) { pickStaticTime(begingWait); int nb_blocks=receiveSubFrame(&sockFS6, bufferZone, sizeof(bufferZone), CTsentCUv0 ); updateTimesReset(begingWait, &fullLoop, 1000, false, "DU wait CU"); - - if (nb_blocks > 0) { - L1_proc_t *L1_proc = &ru->eNB_list[i]->proc; - if ( L1_proc->timestamp_tx != hUDP(bufferZone)->timestamp) { + if (nb_blocks > 0) { + if ( lastTS+ru->eNB_list[i]->frame_parms.samples_per_tti != hUDP(bufferZone)->timestamp) { LOG_E(HW,"Missed a subframe: expecting: %lu, received %lu\n", - L1_proc->timestamp_tx, + lastTS+ru->eNB_list[i]->frame_parms.samples_per_tti, hUDP(bufferZone)->timestamp); } - setAllfromTS(hUDP(bufferZone)->timestamp - sf_ahead*ru->eNB_list[i]->frame_parms.samples_per_tti); - phy_procedures_eNB_TX_fromsplit( bufferZone, nb_blocks, ru->eNB_list[i], &ru->eNB_list[i]->proc.L1_proc, 1); + lastTS=hUDP(bufferZone)->timestamp; + setAllfromTS(hUDP(bufferZone)->timestamp - sf_ahead*ru->eNB_list[i]->frame_parms.samples_per_tti, &L1_proc); + phy_procedures_eNB_TX_fromsplit( bufferZone, nb_blocks, ru->eNB_list[i], &L1_proc, 1); } else LOG_E(PHY,"DL not received for subframe\n"); } - feptx_prec(ru); - feptx_ofdm(ru); - tx_rf(ru); + feptx_prec(ru, &L1_proc); + feptx_ofdm(ru, &L1_proc); + tx_rf(ru, &L1_proc); } -void UL_du_fs6(RU_t *ru, int frame, int subframe) { - RU_proc_t *ru_proc=&ru->proc; +void UL_du_fs6(RU_t *ru, L1_rxtx_proc_t *proc, int frame, int subframe) { initStaticTime(begingWait); initRefTimes(fullLoop); pickStaticTime(begingWait); - rx_rf(ru); + rx_rf(ru, proc); updateTimesReset(begingWait, &fullLoop, 1000, false, "DU wait USRP"); - - setAllfromTS(ru_proc->timestamp_rx); + setAllfromTS(proc->timestamp_rx, proc); // front end processing: convert from time domain to frequency domain // fills rxdataF buffer - fep_full(ru); + fep_full(ru, proc); // Fixme: datamodel issue PHY_VARS_eNB *eNB = RC.eNB[0][0]; - L1_proc_t *proc = &eNB->proc; if (NFAPI_MODE==NFAPI_MODE_PNF) { // I am a PNF and I need to let nFAPI know that we have a (sub)frame tick @@ -1431,11 +1435,11 @@ void UL_du_fs6(RU_t *ru, int frame, int subframe) { } initBufferZone(bufferZone); - hUDP(bufferZone)->timestamp=ru->proc.timestamp_rx; - prach_eNB_tosplit(bufferZone, FS6_BUF_SIZE, eNB); + hUDP(bufferZone)->timestamp=proc->timestamp_rx; + prach_eNB_tosplit(bufferZone, FS6_BUF_SIZE, eNB, proc ); if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { - phy_procedures_eNB_uespec_RX_tosplit(bufferZone, FS6_BUF_SIZE, eNB, &proc->L1_proc ); + phy_procedures_eNB_uespec_RX_tosplit(bufferZone, FS6_BUF_SIZE, eNB, proc ); } if (hUDP(bufferZone)->nbBlocks==0) { @@ -1449,20 +1453,19 @@ void UL_du_fs6(RU_t *ru, int frame, int subframe) { } } -void DL_cu_fs6(RU_t *ru) { +void DL_cu_fs6(RU_t *ru, L1_rxtx_proc_t *proc) { // Fixme: datamodel issue PHY_VARS_eNB *eNB = RC.eNB[0][0]; - L1_proc_t *proc = &eNB->proc; pthread_mutex_lock(&eNB->UL_INFO_mutex); eNB->UL_INFO.frame = proc->frame_rx; eNB->UL_INFO.subframe = proc->subframe_rx; eNB->UL_INFO.module_id = eNB->Mod_id; eNB->UL_INFO.CC_id = eNB->CC_id; - eNB->if_inst->UL_indication(&eNB->UL_INFO); + eNB->if_inst->UL_indication(&eNB->UL_INFO, proc); pthread_mutex_unlock(&eNB->UL_INFO_mutex); initBufferZone(bufferZone); - phy_procedures_eNB_TX_tosplit(bufferZone, eNB, &proc->L1_proc, 1, bufferZone, FS6_BUF_SIZE); - hUDP(bufferZone)->timestamp=proc->L1_proc.timestamp_tx; + phy_procedures_eNB_TX_tosplit(bufferZone, eNB, proc, 1, bufferZone, FS6_BUF_SIZE); + hUDP(bufferZone)->timestamp=proc->timestamp_tx; if (hUDP(bufferZone)->nbBlocks==0) { hUDP(bufferZone)->nbBlocks=1; // We have to send the signaling, even is there is no user plan data (no UE) @@ -1473,7 +1476,7 @@ void DL_cu_fs6(RU_t *ru) { sendSubFrame(&sockFS6, bufferZone, sizeof(fs6_dl_t), CTsentCUv0 ); } -void UL_cu_fs6(RU_t *ru, uint64_t *TS) { +void UL_cu_fs6(RU_t *ru, L1_rxtx_proc_t *proc, uint64_t *TS) { initBufferZone(bufferZone); initStaticTime(begingWait); initRefTimes(fullLoop); @@ -1494,23 +1497,22 @@ void UL_cu_fs6(RU_t *ru, uint64_t *TS) { *TS=hUDP(bufferZone)->timestamp; } - setAllfromTS(hUDP(bufferZone)->timestamp); + setAllfromTS(hUDP(bufferZone)->timestamp, proc); PHY_VARS_eNB *eNB = RC.eNB[0][0]; - if (is_prach_subframe(&eNB->frame_parms, eNB->proc.frame_prach,eNB->proc.subframe_prach)>0) - prach_eNB_fromsplit(bufferZone, sizeof(bufferZone), eNB); + if (is_prach_subframe(&eNB->frame_parms, proc->frame_prach,proc->subframe_prach)>0) + prach_eNB_fromsplit(bufferZone, sizeof(bufferZone), eNB, proc); release_UE_in_freeList(eNB->Mod_id); if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { - phy_procedures_eNB_uespec_RX_fromsplit(bufferZone, nb_blocks, eNB); + phy_procedures_eNB_uespec_RX_fromsplit(bufferZone, nb_blocks, eNB, proc); } } void *cu_fs6(void *arg) { - setbuf(stdout, NULL); - setbuf(stderr, NULL); - + setbuf(stdout, NULL); + setbuf(stderr, NULL); RU_t *ru = (RU_t *)arg; //RU_proc_t *proc = &ru->proc; fill_rf_config(ru,ru->rf_config_file); @@ -1530,27 +1532,30 @@ void *cu_fs6(void *arg) { initStaticTime(begingWait2); initRefTimes(waitDUAndProcessingUL); initRefTimes(makeSendDL); - initRefTimes(fullLoop); + initRefTimes(fullLoop); + L1_rxtx_proc_t L1proc; while(1) { timeStamp+=ru->frame_parms.samples_per_tti; updateTimesReset(begingWait, &fullLoop, 1000, true, "CU for full SubFrame (must be less 1ms)"); pickStaticTime(begingWait); updateTimesReset(begingWait, &waitDUAndProcessingUL, 1000, true,"CU Time in wait Rx + Ul processing"); - UL_cu_fs6(ru, &timeStamp); + UL_cu_fs6(ru, &L1proc, &timeStamp); pickStaticTime(begingWait2); - DL_cu_fs6(ru); + DL_cu_fs6(ru, &L1proc); updateTimesReset(begingWait2, &makeSendDL, 1000, true,"CU Time in DL build+send"); - } return NULL; } -void *du_fs6(void *arg) { - setbuf(stdout, NULL); - setbuf(stderr, NULL); +void *DlDu(void *arg) { + return NULL; +} +void *du_fs6(void *arg) { + setbuf(stdout, NULL); + setbuf(stderr, NULL); RU_t *ru = (RU_t *)arg; //RU_proc_t *proc = &ru->proc; fill_rf_config(ru,ru->rf_config_file); @@ -1573,17 +1578,19 @@ void *du_fs6(void *arg) { else LOG_I(PHY,"RU %d rf device ready\n",ru->idx); } else LOG_I(PHY,"RU %d no rf device\n",ru->idx); + //threadCreate(&t, dutxfs6, (void *)ru, "DlDu", -1, OAI_PRIORITY_RT_MAX); initStaticTime(begingWait); initStaticTime(begingWait2); initRefTimes(waitRxAndProcessingUL); initRefTimes(makeSendDL); initRefTimes(fullLoop); - + L1_rxtx_proc_t L1proc; + while(1) { - L1_proc_t *proc = &ru->eNB_list[0]->proc; + L1_rxtx_proc_t *proc = &L1proc; updateTimesReset(begingWait, &fullLoop, 1000, true,"DU for full SubFrame (must be less 1ms)"); pickStaticTime(begingWait); - UL_du_fs6(ru, proc->frame_rx,proc->subframe_rx); + UL_du_fs6(ru, proc, proc->frame_rx,proc->subframe_rx); updateTimesReset(begingWait, &waitRxAndProcessingUL, 1000, true,"DU Time in wait Rx + Ul processing"); pickStaticTime(begingWait2); DL_du_fs6(ru); diff --git a/executables/main-ocp.c b/executables/main-ocp.c index e1c3c94d4d..9a4743a295 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -30,11 +30,6 @@ static int DEFENBS[] = {0}; #include extern uint16_t sf_ahead; -extern void oai_subframe_ind(uint16_t sfn, uint16_t sf); -extern void fep_full(RU_t *ru); -extern void feptx_ofdm(RU_t *ru); -extern void feptx_prec(RU_t *ru); -extern void phy_init_RU(RU_t *); static void *ru_thread( void *param ); void kill_RU_proc(RU_t *ru) { @@ -48,29 +43,11 @@ void reset_opp_meas(void) { // Fixme: there are many mistakes in the datamodel and in redondant variables // TDD is also mode complex -void setAllfromTS(uint64_t TS) { - for (int i=0; i frame_parms; - RU_proc_t *proc =&RC.ru[i]->proc; - uint64_t TStx=TS+(sf_ahead)*fp->samples_per_tti; - uint64_t TSrach=TS;//-fp->samples_per_tti; - proc->timestamp_rx= TS; - proc->timestamp_tx= TStx; - proc->subframe_rx= (TS / fp->samples_per_tti)%10; - proc->subframe_tx= (TStx / fp->samples_per_tti)%10; - proc->subframe_prach=(TSrach / fp->samples_per_tti)%10; - proc->subframe_prach_br=proc->subframe_prach; - proc->frame_rx= (TS / (fp->samples_per_tti*10))&1023; - proc->frame_prach= (TSrach / (fp->samples_per_tti*10))&1023; - proc->frame_prach_br=(TSrach / (fp->samples_per_tti*10))&1023; - proc->frame_tx= (TStx / (fp->samples_per_tti*10))&1023; - } +void setAllfromTS(uint64_t TS, L1_rxtx_proc_t *proc) { for (int i=0; i < RC.nb_inst; i++) { for (int j=0; jframe_parms; - L1_proc_t *proc =&RC.eNB[i][j]->proc; - L1_rxtx_proc_t *proc1=&RC.eNB[i][j]->proc.L1_proc; uint64_t TStx=TS+(sf_ahead)*fp->samples_per_tti; uint64_t TSrach=TS;//-fp->samples_per_tti; proc->timestamp_rx= TS; @@ -82,11 +59,7 @@ void setAllfromTS(uint64_t TS) { proc->frame_prach= (TSrach / (fp->samples_per_tti*10))&1023; proc->frame_prach_br=(TSrach / (fp->samples_per_tti*10))&1023; proc->frame_tx= (TStx / (fp->samples_per_tti*10))&1023; - proc1->timestamp_tx= TStx; - proc1->subframe_rx= (TS / fp->samples_per_tti)%10; - proc1->subframe_tx= (TStx / fp->samples_per_tti)%10; - proc1->frame_rx= (TS / (fp->samples_per_tti*10))&1023; - proc1->frame_tx= (TStx / (fp->samples_per_tti*10))&1023; + proc->subframe_tx= (TStx / fp->samples_per_tti)%10; } } @@ -98,24 +71,10 @@ void init_eNB_proc(int inst) { /*int i=0;*/ int CC_id; PHY_VARS_eNB *eNB; - L1_proc_t *proc; - L1_rxtx_proc_t *L1_proc; for (CC_id=0; CC_idproc; - L1_proc = &proc->L1_proc; - L1_proc->instance_cnt = -1; - L1_proc->instance_cnt_RUs = 0; - proc->instance_cnt_prach = -1; - proc->instance_cnt_synch = -1; - proc->CC_id = CC_id; - proc->first_rx =1; - proc->first_tx =1; pthread_mutex_init( &eNB->UL_INFO_mutex, NULL); - pthread_mutex_init( &L1_proc->mutex, NULL); - pthread_cond_init( &L1_proc->cond, NULL); - pthread_mutex_init( &proc->mutex_RU,NULL); } //for multiple CCs: setup master and slaves @@ -124,8 +83,8 @@ void init_eNB_proc(int inst) { eNB = PHY_vars_eNB_g[inst][CC_id]; if (eNB->node_timing == synch_to_ext_device) { //master - eNB->proc.num_slaves = MAX_NUM_CCs-1; - eNB->proc.slave_proc = (L1_proc_t**)malloc(eNB->proc.num_slaves*sizeof(L1_proc_t*)); + proc->num_slaves = MAX_NUM_CCs-1; + proc->slave_proc = (L1_proc_t**)malloc(proc->num_slaves*sizeof(L1_proc_t*)); for (i=0; i< eNB->proc.num_slaves; i++) { if (i < CC_id) eNB->proc.slave_proc[i] = &(PHY_vars_eNB_g[inst][i]->proc); @@ -137,19 +96,6 @@ void init_eNB_proc(int inst) { } void init_RU_proc(RU_t *ru) { - int i=0; - RU_proc_t *proc; - proc = &ru->proc; - memset((void *)proc,0,sizeof(RU_proc_t)); - proc->ru = ru; - proc->instance_cnt_synch = -1; - proc->instance_cnt_eNBs = -1; - proc->first_rx = 1; - proc->first_tx = 1; - proc->num_slaves = 0; - proc->frame_tx_unwrap = 0; - - for (i=0; i<10; i++) proc->symbol_mask[i]=0; pthread_t t; char *fs6=getenv("fs6"); @@ -469,7 +415,7 @@ void init_precoding_weights(PHY_VARS_eNB *eNB) { } } -void prach_procedures_ocp(PHY_VARS_eNB *eNB, int br_flag) { +void prach_procedures_ocp(PHY_VARS_eNB *eNB, L1_rxtx_proc_t * proc, int br_flag) { uint16_t max_preamble[4],max_preamble_energy[4],max_preamble_delay[4],avg_preamble_energy[4]; RU_t *ru; int aa=0; @@ -490,12 +436,13 @@ void prach_procedures_ocp(PHY_VARS_eNB *eNB, int br_flag) { // run PRACH detection for CE-level 0 only for now when br_flag is set rx_prach(eNB, + proc, eNB->RU_list[0], &max_preamble[0], &max_preamble_energy[0], &max_preamble_delay[0], &avg_preamble_energy[0], - eNB->proc.frame_prach, + proc->frame_prach, 0 ,br_flag ); @@ -508,7 +455,7 @@ void prach_procedures_ocp(PHY_VARS_eNB *eNB, int br_flag) { if (br_flag==1) { int prach_mask; - prach_mask = is_prach_subframe (&eNB->frame_parms, eNB->proc.frame_prach_br, eNB->proc.subframe_prach_br); + prach_mask = is_prach_subframe (&eNB->frame_parms, proc->frame_prach_br, proc->subframe_prach_br); eNB->UL_INFO.rach_ind_br.rach_indication_body.preamble_list = eNB->preamble_list_br; int ind = 0; int ce_level = 0; @@ -528,7 +475,7 @@ void prach_procedures_ocp(PHY_VARS_eNB *eNB, int br_flag) { eNB->preamble_list_br[ind].preamble_rel8.timing_advance = max_preamble_delay[ind]; // eNB->preamble_list_br[ind].preamble_rel8.preamble = max_preamble[ind]; // note: fid is implicitly 0 here, this is the rule for eMTC RA-RNTI from 36.321, Section 5.1.4 - eNB->preamble_list_br[ind].preamble_rel8.rnti = 1 + eNB->proc.subframe_prach + (60*(eNB->prach_vars_br.first_frame[ce_level] % 40)); + eNB->preamble_list_br[ind].preamble_rel8.rnti = 1 + proc->subframe_prach + (60*(eNB->prach_vars_br.first_frame[ce_level] % 40)); eNB->preamble_list_br[ind].instance_length = 0; //don't know exactly what this is eNB->preamble_list_br[ind].preamble_rel13.rach_resource_type = 1 + ce_level; // CE Level LOG_I (PHY, "Filling NFAPI indication for RACH %d CELevel %d (mask %x) : TA %d, Preamble %d, rnti %x, rach_resource_type %d\n", @@ -549,8 +496,8 @@ void prach_procedures_ocp(PHY_VARS_eNB *eNB, int br_flag) { LOG_I(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure with preamble %d, energy %d.%d dB, delay %d\n", eNB->Mod_id, eNB->CC_id, - eNB->proc.frame_prach, - eNB->proc.subframe_prach, + proc->frame_prach, + proc->subframe_prach, max_preamble[0], max_preamble_energy[0]/10, max_preamble_energy[0]%10, @@ -560,11 +507,11 @@ void prach_procedures_ocp(PHY_VARS_eNB *eNB, int br_flag) { eNB->UL_INFO.rach_ind.rach_indication_body.preamble_list = &eNB->preamble_list[0]; eNB->UL_INFO.rach_ind.rach_indication_body.tl.tag = NFAPI_RACH_INDICATION_BODY_TAG; eNB->UL_INFO.rach_ind.header.message_id = NFAPI_RACH_INDICATION; - eNB->UL_INFO.rach_ind.sfn_sf = eNB->proc.frame_prach<<4 | eNB->proc.subframe_prach; + eNB->UL_INFO.rach_ind.sfn_sf = proc->frame_prach<<4 | proc->subframe_prach; eNB->preamble_list[0].preamble_rel8.tl.tag = NFAPI_PREAMBLE_REL8_TAG; eNB->preamble_list[0].preamble_rel8.timing_advance = max_preamble_delay[0]; eNB->preamble_list[0].preamble_rel8.preamble = max_preamble[0]; - eNB->preamble_list[0].preamble_rel8.rnti = 1+eNB->proc.subframe_prach; // note: fid is implicitly 0 here + eNB->preamble_list[0].preamble_rel8.rnti = 1+proc->subframe_prach; // note: fid is implicitly 0 here eNB->preamble_list[0].preamble_rel13.rach_resource_type = 0; eNB->preamble_list[0].instance_length = 0; //don't know exactly what this is @@ -589,11 +536,11 @@ void prach_procedures_ocp(PHY_VARS_eNB *eNB, int br_flag) { } } // else br_flag -void prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { +void prach_eNB(PHY_VARS_eNB *eNB, L1_rxtx_proc_t * proc, int frame,int subframe) { // check if we have to detect PRACH first if (is_prach_subframe(&eNB->frame_parms, frame,subframe)>0) { - prach_procedures_ocp(eNB, 0); - prach_procedures_ocp(eNB, 1); + prach_procedures_ocp(eNB, proc, 0); + prach_procedures_ocp(eNB, proc, 1); } } @@ -609,7 +556,7 @@ static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name AssertFatal( !(NFAPI_MODE==NFAPI_MODE_PNF && eNB->pdcch_vars[proc->subframe_tx&1].num_pdcch_symbols == 0), ""); - prach_eNB(eNB,NULL,proc->frame_rx,proc->subframe_rx); + prach_eNB(eNB,proc,proc->frame_rx,proc->subframe_rx); release_UE_in_freeList(eNB->Mod_id); // UE-specific RX processing for subframe n @@ -622,41 +569,38 @@ static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name eNB->UL_INFO.subframe = proc->subframe_rx; eNB->UL_INFO.module_id = eNB->Mod_id; eNB->UL_INFO.CC_id = eNB->CC_id; - eNB->if_inst->UL_indication(&eNB->UL_INFO); + eNB->if_inst->UL_indication(&eNB->UL_INFO, proc); pthread_mutex_unlock(&eNB->UL_INFO_mutex); phy_procedures_eNB_TX(eNB, proc, 1); return(0); } -void eNB_top(PHY_VARS_eNB *eNB, int dummy1, int dummy2, char *string,RU_t *ru) { - L1_proc_t *proc = &eNB->proc; - L1_rxtx_proc_t *L1_proc = &proc->L1_proc; +void eNB_top(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int dummy1, int dummy2, char *string,RU_t *ru) { if (!oai_exit) { - if (rxtx(eNB,L1_proc,string) < 0) + if (rxtx(eNB,proc,string) < 0) LOG_E(PHY,"eNB %d CC_id %d failed during execution\n",eNB->Mod_id,eNB->CC_id); } } -void rx_rf(RU_t *ru) { - RU_proc_t *proc = &ru->proc; +void rx_rf(RU_t *ru, L1_rxtx_proc_t *proc) { LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; void *rxp[ru->nb_rx]; unsigned int rxs; int i; - openair0_timestamp ts=0,old_ts=0; - + openair0_timestamp ts=0, timestamp_rx; + static openair0_timestamp old_ts=0; + for (i=0; inb_rx; i++) //receive in the next slot - rxp[i] = (void *)&ru->common.rxdata[i][((ru->proc.subframe_rx+1)%10)*fp->samples_per_tti]; + rxp[i] = (void *)&ru->common.rxdata[i][((proc->subframe_rx+1)%10)*fp->samples_per_tti]; - old_ts = proc->timestamp_rx; rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, &ts, rxp, fp->samples_per_tti, ru->nb_rx); - proc->timestamp_rx = ts-ru->ts_offset; + timestamp_rx = ts-ru->ts_offset; // AssertFatal(rxs == fp->samples_per_tti, // "rx_rf: Asked for %d samples, got %d from SDR\n",fp->samples_per_tti,rxs); @@ -670,23 +614,16 @@ void rx_rf(RU_t *ru) { #endif } - if (proc->first_rx == 1) { - //ru->ts_offset = proc->timestamp_rx; - //proc->timestamp_rx = 0; - proc->first_rx = false; - } else { - if (proc->timestamp_rx - old_ts != fp->samples_per_tti) { - LOG_E(HW,"impossible shift in rx stream, rx: %ld, previous rx distance: %ld, should be %d\n", proc->timestamp_rx, proc->timestamp_rx - old_ts, fp->samples_per_tti); + if (timestamp_rx - old_ts != fp->samples_per_tti) { + LOG_E(HW,"impossible shift in rx stream, rx: %ld, previous rx distance: %ld, should be %d\n", timestamp_rx, proc->timestamp_rx - old_ts, fp->samples_per_tti); //ru->ts_offset += (proc->timestamp_rx - old_ts - fp->samples_per_tti); //proc->timestamp_rx = ts-ru->ts_offset; - } } - - setAllfromTS(proc->timestamp_rx); + old_ts=timestamp_rx; + setAllfromTS(timestamp_rx, proc); } -void tx_rf(RU_t *ru) { - RU_proc_t *proc = &ru->proc; +void tx_rf(RU_t *ru, L1_rxtx_proc_t *proc) { LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; void *txp[ru->nb_tx]; int i; @@ -740,8 +677,8 @@ void tx_rf(RU_t *ru) { siglen+sf_extension, ru->nb_tx, flags); - LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, subframe %d\n",ru->idx, - (long long unsigned int)proc->timestamp_tx,proc->frame_tx,proc->frame_tx_unwrap,proc->subframe_tx); + LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, subframe %d\n",ru->idx, + (long long unsigned int)proc->timestamp_tx,proc->frame_tx,proc->subframe_tx); } } @@ -749,6 +686,8 @@ static void *ru_thread( void *param ) { setbuf(stdout, NULL); setbuf(stderr, NULL); RU_t *ru = (RU_t *)param; + L1_rxtx_proc_t L1proc; + L1_rxtx_proc_t * proc=&L1proc; if (ru->if_south == LOCAL_RF) { // configure RF parameters only fill_rf_config(ru,ru->rf_config_file); @@ -771,11 +710,11 @@ static void *ru_thread( void *param ) { // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices while (!oai_exit) { // synchronization on input FH interface, acquire signals/data and block - rx_rf(ru); + rx_rf(ru, proc); // do RX front-end processing (frequency-shift, dft) if needed if (ru->feprx) - ru->feprx(ru); + ru->feprx(ru, proc); // At this point, all information for subframe has been received on FH interface // If this proc is to provide synchronization, do so @@ -784,20 +723,20 @@ static void *ru_thread( void *param ) { for (int i=0; inum_eNB; i++) { char string[20]; sprintf(string,"Incoming RU %d",ru->idx); - ru->eNB_top(ru->eNB_list[i],ru->proc.frame_rx,ru->proc.subframe_rx,string,ru); + ru->eNB_top(ru->eNB_list[i],proc, proc->frame_rx,proc->subframe_rx,string,ru); } // do TX front-end processing if needed (precoding and/or IDFTs) if (ru->feptx_prec) - ru->feptx_prec(ru); + ru->feptx_prec(ru, proc); // do OFDM if needed if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) - ru->feptx_ofdm(ru); + ru->feptx_ofdm(ru, proc); // do outgoing fronthaul (south) if needed if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) - ru->fh_south_out(ru); + ru->fh_south_out(ru, proc); } LOG_W(PHY,"Exiting ru_thread \n"); diff --git a/executables/split_headers.h b/executables/split_headers.h index 4a8afc9c85..1f9443c00c 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -229,15 +229,15 @@ static inline void *commonUDPdata(uint8_t *ptr) { return (void *) (((commonUDP_t *)ptr)+1); } -void setAllfromTS(uint64_t TS); +void setAllfromTS(uint64_t TS, L1_rxtx_proc_t *proc); void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB,LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, uint16_t rnti, int32_t stat); void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset); void *cu_fs6(void *arg); void *du_fs6(void *arg); void fill_rf_config(RU_t *ru, char *rf_config_file); -void rx_rf(RU_t *ru); -void tx_rf(RU_t *ru); +void rx_rf(RU_t *ru, L1_rxtx_proc_t *proc); +void tx_rf(RU_t *ru, L1_rxtx_proc_t *proc); void common_signal_procedures (PHY_VARS_eNB *eNB,int frame, int subframe); void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc); bool dlsch_procedures(PHY_VARS_eNB *eNB, @@ -256,9 +256,9 @@ void uci_procedures(PHY_VARS_eNB *eNB, // mistakes in main OAI void phy_init_RU(RU_t *); -void feptx_prec(RU_t *); -void feptx_ofdm(RU_t *); +void feptx_prec(RU_t *, L1_rxtx_proc_t *proc); +void feptx_ofdm(RU_t *, L1_rxtx_proc_t *proc); void oai_subframe_ind(uint16_t sfn, uint16_t sf); -void fep_full(RU_t *ru); +void fep_full(RU_t *ru, L1_rxtx_proc_t *proc); extern uint16_t sf_ahead; #endif diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index f07fb1ad23..ed3d708992 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -692,13 +692,12 @@ void pnf_phy_deallocate_p7_vendor_ext(nfapi_p7_message_header_t *header) { free(header); } -int pnf_phy_hi_dci0_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_hi_dci0_request_t *req) { +int pnf_phy_hi_dci0_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_hi_dci0_request_t *req) { if (req->hi_dci0_request_body.number_of_dci == 0 && req->hi_dci0_request_body.number_of_hi == 0) LOG_D(PHY,"[PNF] HI_DCI0_REQUEST SFN/SF:%05d dci:%d hi:%d\n", NFAPI_SFNSF2DEC(req->sfn_sf), req->hi_dci0_request_body.number_of_dci, req->hi_dci0_request_body.number_of_hi); //phy_info* phy = (phy_info*)(pnf_p7->user_data); struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0]; - L1_rxtx_proc_t *proc = &eNB->proc.L1_proc; for (int i=0; ihi_dci0_request_body.number_of_dci + req->hi_dci0_request_body.number_of_hi; i++) { //LOG_D(PHY,"[PNF] HI_DCI0_REQ sfn_sf:%d PDU[%d]\n", NFAPI_SFNSF2DEC(req->sfn_sf), i); @@ -719,7 +718,7 @@ int pnf_phy_hi_dci0_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_hi_dci0_request_t * return 0; } -int pnf_phy_dl_config_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_dl_config_request_t *req) { +int pnf_phy_dl_config_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_dl_config_request_t *req) { if (RC.ru == 0) { return -1; } @@ -740,7 +739,6 @@ int pnf_phy_dl_config_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_dl_config_request int sfn = NFAPI_SFNSF2SFN(req->sfn_sf); int sf = NFAPI_SFNSF2SF(req->sfn_sf); struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0]; - L1_rxtx_proc_t *proc = &eNB->proc.L1_proc; nfapi_dl_config_request_pdu_t *dl_config_pdu_list = req->dl_config_request_body.dl_config_pdu_list; LTE_eNB_PDCCH *pdcch_vars = &eNB->pdcch_vars[sf&1]; pdcch_vars->num_pdcch_symbols = req->dl_config_request_body.number_pdcch_ofdm_symbols; @@ -797,7 +795,7 @@ int pnf_phy_dl_config_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_dl_config_request uint8_t *dlsch_sdu = tx_pdus[UE_id][harq_pid]; memcpy(dlsch_sdu, tx_pdu->segments[0].segment_data, tx_pdu->segments[0].segment_length); //NFAPI_TRACE(NFAPI_TRACE_INFO, "%s() DLSCH:pdu_index:%d handle_nfapi_dlsch_pdu(eNB, proc_rxtx, dlsch_pdu, transport_blocks:%d sdu:%p) eNB->pdcch_vars[proc->subframe_tx & 1].num_pdcch_symbols:%d\n", __FUNCTION__, rel8_pdu->pdu_index, rel8_pdu->transport_blocks, dlsch_sdu, eNB->pdcch_vars[proc->subframe_tx & 1].num_pdcch_symbols); - handle_nfapi_dlsch_pdu( eNB, sfn,sf, &eNB->proc.L1_proc, &dl_config_pdu_list[i], rel8_pdu->transport_blocks-1, dlsch_sdu); + handle_nfapi_dlsch_pdu( eNB, sfn,sf, proc, &dl_config_pdu_list[i], rel8_pdu->transport_blocks-1, dlsch_sdu); } else { NFAPI_TRACE(NFAPI_TRACE_ERROR, "%s() DLSCH NULL TX PDU SFN/SF:%d PDU_INDEX:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), rel8_pdu->pdu_index); } @@ -837,7 +835,7 @@ int pnf_phy_tx_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_tx_request_t *req) { return 0; } -int pnf_phy_ul_config_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_ul_config_request_t *req) { +int pnf_phy_ul_config_req(L1_rxtx_proc_t *proc, nfapi_pnf_p7_config_t *pnf_p7, nfapi_ul_config_request_t *req) { if (0)LOG_D(PHY,"[PNF] UL_CONFIG_REQ %s() sfn_sf:%d pdu:%d rach_prach_frequency_resources:%d srs_present:%u\n", __FUNCTION__, NFAPI_SFNSF2DEC(req->sfn_sf), @@ -866,7 +864,6 @@ int pnf_phy_ul_config_req(nfapi_pnf_p7_config_t *pnf_p7, nfapi_ul_config_request uint16_t curr_sfn = NFAPI_SFNSF2SFN(req->sfn_sf); uint16_t curr_sf = NFAPI_SFNSF2SF(req->sfn_sf); struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0]; - L1_rxtx_proc_t *proc = &eNB->proc.L1_proc; nfapi_ul_config_request_pdu_t *ul_config_pdu_list = req->ul_config_request_body.ul_config_pdu_list; for (int i=0; iul_config_request_body.number_of_pdus; i++) { diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index 6b68a29658..729ce5e78d 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -321,9 +321,8 @@ int pnf_config_resp_cb(nfapi_vnf_config_t *config, int p5_idx, nfapi_pnf_config_ return 0; } -int wake_eNB_rxtx(PHY_VARS_eNB *eNB, uint16_t sfn, uint16_t sf) { - L1_proc_t *proc=&eNB->proc; - L1_rxtx_proc_t *L1_proc= (sf&1)? &proc->L1_proc : &proc->L1_proc_tx; +int wake_eNB_rxtx(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, uint16_t sfn, uint16_t sf) { + L1_rxtx_proc_t *L1_proc= proc; LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; //printf("%s(eNB:%p, sfn:%d, sf:%d)\n", __FUNCTION__, eNB, sfn, sf); //int i; @@ -398,7 +397,7 @@ int phy_sync_indication(struct nfapi_vnf_p7_config *config, uint8_t sync) { return(0); } -int phy_subframe_indication(struct nfapi_vnf_p7_config *config, uint16_t phy_id, uint16_t sfn_sf) { +int phy_subframe_indication(L1_rxtx_proc_t * proc, struct nfapi_vnf_p7_config *config, uint16_t phy_id, uint16_t sfn_sf) { static uint8_t first_time = 1; if (first_time) { @@ -410,7 +409,7 @@ int phy_subframe_indication(struct nfapi_vnf_p7_config *config, uint16_t phy_id, uint16_t sfn = NFAPI_SFNSF2SFN(sfn_sf); uint16_t sf = NFAPI_SFNSF2SF(sfn_sf); //LOG_D(PHY,"[VNF] subframe indication sfn_sf:%d sfn:%d sf:%d\n", sfn_sf, sfn, sf); - wake_eNB_rxtx(RC.eNB[0][0], sfn, sf); + wake_eNB_rxtx(RC.eNB[0][0], proc, sfn, sf); } else { printf("[VNF] %s() RC.eNB:%p\n", __FUNCTION__, RC.eNB); diff --git a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c index 960ad10667..ee80dff7b9 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c @@ -148,7 +148,7 @@ int lte_est_timing_advance_pusch(PHY_VARS_eNB *eNB,module_id_t UE_id) max_pos = max_pos-frame_parms->ofdm_symbol_size; //#ifdef DEBUG_PHY - LOG_D(PHY,"frame %d: max_pos = %d, sync_pos=%d\n",eNB->proc.frame_rx,max_pos,sync_pos); + LOG_D(PHY,"max_pos = %d, sync_pos=%d\n",max_pos,sync_pos); //#endif //DEBUG_PHY return max_pos - sync_pos; diff --git a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c index eaed019a4f..26d800fa5d 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c @@ -54,7 +54,7 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB, int32_t **rxdataF_ext = (eNB!=NULL) ? pusch_vars->rxdataF_ext : calibration->rxdataF_ext; - int subframe = (eNB!=NULL) ? proc->subframe_rx : ru->proc.subframe_rx; + int subframe = proc->subframe_rx; uint8_t harq_pid; int16_t delta_phase = 0; diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c index 327b0cf57c..b494f7bd6c 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c @@ -328,231 +328,7 @@ int dlsch_encoding_2threads0(te_params *tep) { extern int oai_exit; -void *te_thread(void *param) { - cpu_set_t cpuset; - CPU_ZERO(&cpuset); - thread_top_init("te_thread",1,200000,250000,500000); - pthread_setname_np( pthread_self(),"te processing"); - LOG_I(PHY,"thread te created id=%ld\n", syscall(__NR_gettid)); - te_params *tep = (te_params *)param; - //wait_sync("te_thread"); - - while (!oai_exit) { - if (wait_on_condition(&tep->mutex_te,&tep->cond_te,&tep->instance_cnt_te,"te thread")<0) break; - - if(oai_exit) break; - - dlsch_encoding_2threads0(tep); - - if (release_thread(&tep->mutex_te,&tep->instance_cnt_te,"te thread")<0) break; - - if (pthread_cond_signal(&tep->cond_te) != 0) { - printf("[eNB] ERROR pthread_cond_signal for te thread exit\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return(NULL); - } - - /*if(opp_enabled == 1 && te_wakeup_stats0->p_time>50*3000){ - print_meas_now(te_wakeup_stats0,"coding_wakeup",stderr); - printf("te_thread0 delay for waking up in frame_rx: %d subframe_rx: %d \n",proc->frame_rx,proc->subframe_rx); - }*/ - } - - return(NULL); -} - - - -int dlsch_encoding_2threads(PHY_VARS_eNB *eNB, - unsigned char *a, - uint8_t num_pdcch_symbols, - LTE_eNB_DLSCH_t *dlsch, - int frame, - uint8_t subframe, - time_stats_t *rm_stats, - time_stats_t *te_stats, - time_stats_t *te_wait_stats, - time_stats_t *te_main_stats, - time_stats_t *te_wakeup_stats0, - time_stats_t *te_wakeup_stats1, - time_stats_t *i_stats, - int worker_num) { - //start_meas(&eNB->dlsch_turbo_encoding_preperation_stats); - LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; - L1_proc_t *proc = &eNB->proc; - unsigned int G; - unsigned int crc=1; - unsigned char harq_pid = dlsch->harq_ids[frame%2][subframe]; - if((harq_pid < 0) || (harq_pid >= dlsch->Mdlharq)) { - LOG_E(PHY,"dlsch_encoding_2threads illegal harq_pid %d %s:%d\n", harq_pid, __FILE__, __LINE__); - return(-1); - } - - unsigned short nb_rb = dlsch->harq_processes[harq_pid]->nb_rb; - unsigned int A; - unsigned char mod_order; - unsigned int Kr=0,Kr_bytes,r,r_offset=0; - // unsigned short m=dlsch->harq_processes[harq_pid]->mcs; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN); - A = dlsch->harq_processes[harq_pid]->TBS; //6228 - mod_order = dlsch->harq_processes[harq_pid]->Qm; - G = get_G(frame_parms,nb_rb,dlsch->harq_processes[harq_pid]->rb_alloc,mod_order,dlsch->harq_processes[harq_pid]->Nl,num_pdcch_symbols,frame,subframe, - dlsch->harq_processes[harq_pid]->mimo_mode==TM7?7:0); - - if (dlsch->harq_processes[harq_pid]->round == 0) { // this is a new packet - start_meas(&eNB->dlsch_turbo_encoding_preperation_stats); - // Add 24-bit crc (polynomial A) to payload - crc = crc24a(a, - A)>>8; - stop_meas(&eNB->dlsch_turbo_encoding_preperation_stats); - a[A>>3] = ((uint8_t *)&crc)[2]; - a[1+(A>>3)] = ((uint8_t *)&crc)[1]; - a[2+(A>>3)] = ((uint8_t *)&crc)[0]; - dlsch->harq_processes[harq_pid]->B = A+24; - memcpy(dlsch->harq_processes[harq_pid]->b,a,(A/8)+4); - //stop_meas(&eNB->dlsch_turbo_encoding_preperation_stats); - start_meas(&eNB->dlsch_turbo_encoding_segmentation_stats); - - if (lte_segmentation(dlsch->harq_processes[harq_pid]->b, - dlsch->harq_processes[harq_pid]->c, - dlsch->harq_processes[harq_pid]->B, - &dlsch->harq_processes[harq_pid]->C, - &dlsch->harq_processes[harq_pid]->Cplus, - &dlsch->harq_processes[harq_pid]->Cminus, - &dlsch->harq_processes[harq_pid]->Kplus, - &dlsch->harq_processes[harq_pid]->Kminus, - &dlsch->harq_processes[harq_pid]->F)<0) - return(-1); - - stop_meas(&eNB->dlsch_turbo_encoding_segmentation_stats); - start_meas(&eNB->dlsch_turbo_encoding_signal_stats); - - for(int i=0; itep[i].eNB = eNB; - proc->tep[i].dlsch = dlsch; - proc->tep[i].G = G; - proc->tep[i].harq_pid = harq_pid; - proc->tep[i].total_worker = worker_num; - proc->tep[i].current_worker = i; - pthread_mutex_lock( &proc->tep[i].mutex_te ); - - if (proc->tep[i].instance_cnt_te==0) { - printf("[eNB] TE thread busy\n"); - exit_fun("TE thread busy"); - pthread_mutex_unlock( &proc->tep[i].mutex_te ); - return(-1); - } - - ++proc->tep[i].instance_cnt_te; - - // wakeup worker to do segments - if (pthread_cond_signal(&proc->tep[i].cond_te) != 0) { - printf("[eNB] ERROR pthread_cond_signal for te thread %d exit\n",i); - exit_fun( "ERROR pthread_cond_signal" ); - return (-1); - } - - pthread_mutex_unlock( &proc->tep[i].mutex_te ); - } - - stop_meas(&eNB->dlsch_turbo_encoding_signal_stats); - start_meas(te_main_stats); - - for (r=(dlsch->harq_processes[harq_pid]->C/(worker_num+1))*worker_num; rharq_processes[harq_pid]->C; r++) { - if (rharq_processes[harq_pid]->Cminus) - Kr = dlsch->harq_processes[harq_pid]->Kminus; - else - Kr = dlsch->harq_processes[harq_pid]->Kplus; - - Kr_bytes = Kr>>3; - start_meas(te_stats); - encoder(dlsch->harq_processes[harq_pid]->c[r], - Kr>>3, - &dlsch->harq_processes[harq_pid]->d[r][96], - (r==0) ? dlsch->harq_processes[harq_pid]->F : 0 - ); - stop_meas(te_stats); - start_meas(i_stats); - dlsch->harq_processes[harq_pid]->RTC[r] = - sub_block_interleaving_turbo(4+(Kr_bytes*8), - &dlsch->harq_processes[harq_pid]->d[r][96], - dlsch->harq_processes[harq_pid]->w[r]); - stop_meas(i_stats); - } - } else { - for(int i=0; itep[i].eNB = eNB; - proc->tep[i].dlsch = dlsch; - proc->tep[i].G = G; - proc->tep[i].total_worker = worker_num; - proc->tep[i].current_worker = i; - - if (pthread_cond_signal(&proc->tep[i].cond_te) != 0) { - printf("[eNB] ERROR pthread_cond_signal for te thread exit\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return (-1); - } - } - } - - // Fill in the "e"-sequence from 36-212, V8.6 2009-03, p. 16-17 (for each "e") and concatenate the - // outputs for each code segment, see Section 5.1.5 p.20 - for (r=0,r_offset=0; rharq_processes[harq_pid]->C; r++) { - // get information for E for the segments that are handled by the worker thread - if (r<(dlsch->harq_processes[harq_pid]->C/(worker_num+1))*worker_num) { - int Nl=dlsch->harq_processes[harq_pid]->Nl; - int Qm=dlsch->harq_processes[harq_pid]->Qm; - int C = dlsch->harq_processes[harq_pid]->C; - int Gp = G/Nl/Qm; - int GpmodC = Gp%C; - - if (r < (C-(GpmodC))) - r_offset += Nl*Qm * (Gp/C); - else - r_offset += Nl*Qm * ((GpmodC==0?0:1) + (Gp/C)); - } else { - start_meas(rm_stats); - r_offset += lte_rate_matching_turbo(dlsch->harq_processes[harq_pid]->RTC[r], - G, //G - dlsch->harq_processes[harq_pid]->w[r], - dlsch->harq_processes[harq_pid]->e+r_offset, - dlsch->harq_processes[harq_pid]->C, // C - dlsch->Nsoft, // Nsoft, - dlsch->Mdlharq, - dlsch->Kmimo, - dlsch->harq_processes[harq_pid]->rvidx, - dlsch->harq_processes[harq_pid]->Qm, - dlsch->harq_processes[harq_pid]->Nl, - r, - nb_rb); - // m); // r - stop_meas(rm_stats); - } - } - - stop_meas(te_main_stats); - start_meas(te_wait_stats); - - if(worker_num == 1) { - wait_on_busy_condition(&proc->tep[0].mutex_te,&proc->tep[0].cond_te,&proc->tep[0].instance_cnt_te,"te thread 0"); - } else if(worker_num == 2) { - wait_on_busy_condition(&proc->tep[0].mutex_te,&proc->tep[0].cond_te,&proc->tep[0].instance_cnt_te,"te thread 0"); - wait_on_busy_condition(&proc->tep[1].mutex_te,&proc->tep[1].cond_te,&proc->tep[1].instance_cnt_te,"te thread 1"); - } else { - wait_on_busy_condition(&proc->tep[0].mutex_te,&proc->tep[0].cond_te,&proc->tep[0].instance_cnt_te,"te thread 0"); - wait_on_busy_condition(&proc->tep[1].mutex_te,&proc->tep[1].cond_te,&proc->tep[1].instance_cnt_te,"te thread 1"); - wait_on_busy_condition(&proc->tep[2].mutex_te,&proc->tep[2].cond_te,&proc->tep[2].instance_cnt_te,"te thread 2"); - } - - stop_meas(te_wait_stats); - /*if(opp_enabled == 1 && te_wait_stats->p_time>100*3000){ - print_meas_now(te_wait_stats,"coding_wait",stderr); - printf("coding delay in wait on codition in frame_rx: %d \n",proc->frame_rx); - }*/ - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT); - return(0); -} int dlsch_encoding_all(PHY_VARS_eNB *eNB, unsigned char *a, uint8_t num_pdcch_symbols, @@ -589,68 +365,6 @@ int dlsch_encoding_all(PHY_VARS_eNB *eNB, } } - if(get_thread_worker_conf() == WORKER_ENABLE) { - if(C >= 8) { //one main three worker - encoding_return = - dlsch_encoding_2threads(eNB, - a, - num_pdcch_symbols, - dlsch, - frame, - subframe, - rm_stats, - te_stats, - te_wait_stats, - te_main_stats, - te_wakeup_stats0, - te_wakeup_stats1, - i_stats, - 3); - } else if(C >= 6) { //one main two worker - encoding_return = - dlsch_encoding_2threads(eNB, - a, - num_pdcch_symbols, - dlsch, - frame, - subframe, - rm_stats, - te_stats, - te_wait_stats, - te_main_stats, - te_wakeup_stats0, - te_wakeup_stats1, - i_stats, - 2); - } else if(C >= 4) { //one main one worker - encoding_return = - dlsch_encoding_2threads(eNB, - a, - num_pdcch_symbols, - dlsch, - frame, - subframe, - rm_stats, - te_stats, - te_wait_stats, - te_main_stats, - te_wakeup_stats0, - te_wakeup_stats1, - i_stats, - 1); - } else { - encoding_return = - dlsch_encoding(eNB, - a, - num_pdcch_symbols, - dlsch, - frame, - subframe, - rm_stats, - te_stats, - i_stats); - } - } else { encoding_return = dlsch_encoding(eNB, a, @@ -661,7 +375,6 @@ int dlsch_encoding_all(PHY_VARS_eNB *eNB, rm_stats, te_stats, i_stats); - } return encoding_return; } diff --git a/openair1/PHY/LTE_TRANSPORT/if5_tools.c b/openair1/PHY/LTE_TRANSPORT/if5_tools.c index 9e31735f81..5882ab50d3 100644 --- a/openair1/PHY/LTE_TRANSPORT/if5_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if5_tools.c @@ -308,7 +308,7 @@ void send_IF5(RU_t *ru, openair0_timestamp proc_timestamp, int subframe, uint8_t } -void recv_IF5(RU_t *ru, openair0_timestamp *proc_timestamp, int subframe, uint16_t packet_type) { +void recv_IF5(RU_t *ru, L1_rxtx_proc_t *proc, openair0_timestamp *proc_timestamp, int subframe, uint16_t packet_type) { LTE_DL_FRAME_PARMS *fp=&ru->frame_parms; int32_t *txp[fp->nb_antennas_tx], *rxp[fp->nb_antennas_rx]; @@ -505,7 +505,6 @@ void recv_IF5(RU_t *ru, openair0_timestamp *proc_timestamp, int subframe, uint16 rxp[0] = (void*)&ru->common.rxdata[0][subframe*ru->frame_parms.samples_per_tti]; rxp128 = (__m128i *) (rxp[0]); - RU_proc_t *proc = &ru->proc; /* // while(packet_idsamples_per_tti/db_fulllength) { data_block = data_block_head; @@ -569,13 +568,13 @@ void recv_IF5(RU_t *ru, openair0_timestamp *proc_timestamp, int subframe, uint16 subframe_skip++; offset_cnt = header->seqno; } else { - if ((offset_cnt != header->seqno) && (start_flag == 0) && (proc->first_rx > 3)){ + if ((offset_cnt != header->seqno) && (start_flag == 0) ){ #ifdef DEBUG_UL_MOBIPASS LOG_D(PHY,"[Mobipass] Reset sequence number, offset_cnt:%d, header->seqno:%d, packet_id:%d\n", offset_cnt, header->seqno, packet_id); #endif reset_flag=1; } - if ((reset_flag == 1) && (proc->first_rx > 3 ) && (start_flag == 0) && (packet_id == 0)) { + if ((reset_flag == 1) && (start_flag == 0) && (packet_id == 0)) { packet_id = 1; reset_flag = 0; } diff --git a/openair1/PHY/LTE_TRANSPORT/if5_tools.h b/openair1/PHY/LTE_TRANSPORT/if5_tools.h index 0f24f7bece..445accd899 100644 --- a/openair1/PHY/LTE_TRANSPORT/if5_tools.h +++ b/openair1/PHY/LTE_TRANSPORT/if5_tools.h @@ -61,7 +61,8 @@ typedef struct IF5_mobipass_header IF5_mobipass_header_t; void send_IF5(RU_t *, openair0_timestamp, int, uint8_t*, uint16_t); -void recv_IF5(RU_t *, openair0_timestamp*, int, uint16_t); +void recv_IF5(RU_t *ru, L1_rxtx_proc_t *proc, openair0_timestamp *proc_timestamp, int subframe, uint16_t packet_type); + void malloc_IF5_buffer(RU_t *ru); diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c index 6aca9ba904..94c5ede32f 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach.c +++ b/openair1/PHY/LTE_TRANSPORT/prach.c @@ -38,12 +38,15 @@ #include "SCHED/sched_eNB.h" #include "common/utils/LOG/vcd_signal_dumper.h" #include "prach_extern.h" +#include +#include #if (LTE_RRC_VERSION < MAKE_VERSION(14, 0, 0)) #define rx_prach0 rx_prach #endif void rx_prach0(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, RU_t *ru, uint16_t *max_preamble, uint16_t *max_preamble_energy, @@ -147,13 +150,13 @@ void rx_prach0(PHY_VARS_eNB *eNB, if (br_flag == 1) { prach_ifftp = eNB->prach_vars_br.prach_ifft[ce_level]; - subframe = eNB->proc.subframe_prach_br; + subframe = proc->subframe_prach_br; prachF = eNB->prach_vars_br.prachF; rxsigF = eNB->prach_vars_br.rxsigF[ce_level]; if (LOG_DEBUGFLAG(PRACH)){ - if (((eNB->proc.frame_prach)&1023) < 20) LOG_I(PHY,"PRACH (eNB) : running rx_prach (br_flag %d, ce_level %d) for frame %d subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d, rootSequenceIndex %d, repetition number %d,numRepetitionsPrePreambleAttempt %d\n", - br_flag,ce_level,eNB->proc.frame_prach,subframe, + if (((proc->frame_prach)&1023) < 20) LOG_I(PHY,"PRACH (eNB) : running rx_prach (br_flag %d, ce_level %d) for frame %d subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d, rootSequenceIndex %d, repetition number %d,numRepetitionsPrePreambleAttempt %d\n", + br_flag,ce_level,proc->frame_prach,subframe, fp->prach_emtc_config_common.prach_ConfigInfo.prach_FreqOffset[ce_level], prach_ConfigIndex,rootSequenceIndex, eNB->prach_vars_br.repetition_number[ce_level], @@ -163,34 +166,30 @@ void rx_prach0(PHY_VARS_eNB *eNB, #endif { prach_ifftp = eNB->prach_vars.prach_ifft[0]; - subframe = eNB->proc.subframe_prach; + subframe = proc->subframe_prach; prachF = eNB->prach_vars.prachF; rxsigF = eNB->prach_vars.rxsigF[0]; if (LOG_DEBUGFLAG(PRACH)){ - if (((eNB->proc.frame_prach)&1023) < 20) LOG_I(PHY,"PRACH (eNB) : running rx_prach for subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d , rootSequenceIndex %d\n", subframe,fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset,prach_ConfigIndex,rootSequenceIndex); + if (((proc->frame_prach)&1023) < 20) LOG_I(PHY,"PRACH (eNB) : running rx_prach for subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d , rootSequenceIndex %d\n", subframe,fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset,prach_ConfigIndex,rootSequenceIndex); } } } else { #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) if (br_flag == 1) { - subframe = ru->proc.subframe_prach_br; + subframe = proc->subframe_prach_br; rxsigF = ru->prach_rxsigF_br[ce_level]; if (LOG_DEBUGFLAG(PRACH)) { - if (((ru->proc.frame_prach)&1023) < 20) LOG_I(PHY,"PRACH (RU) : running rx_prach (br_flag %d, ce_level %d) for frame %d subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d\n", - br_flag,ce_level,ru->proc.frame_prach,subframe,fp->prach_emtc_config_common.prach_ConfigInfo.prach_FreqOffset[ce_level],prach_ConfigIndex); + if (((proc->frame_prach)&1023) < 20) LOG_I(PHY,"PRACH (RU) : running rx_prach (br_flag %d, ce_level %d) for frame %d subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d\n", + br_flag,ce_level,proc->frame_prach,subframe,fp->prach_emtc_config_common.prach_ConfigInfo.prach_FreqOffset[ce_level],prach_ConfigIndex); } } else #endif { - subframe = ru->proc.subframe_prach; + subframe = proc->subframe_prach; rxsigF = ru->prach_rxsigF; - if (LOG_DEBUGFLAG(PRACH)) { - if (((ru->proc.frame_prach)&1023) < 20) LOG_I(PHY,"PRACH (RU) : running rx_prach for subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d\n", - subframe,fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset,prach_ConfigIndex); - } } } @@ -218,8 +217,8 @@ void rx_prach0(PHY_VARS_eNB *eNB, if (prach[0]!= NULL) LOG_M("prach_rx","prach_rx",prach[0],fp->samples_per_tti,1,1); - LOG_I(PHY,"RU %d, br_flag %d ce_level %d frame %d subframe %d per_tti:%d prach:%p (energy %d) TA:%d %s rxdata:%p index:%d\n", - ru->idx,br_flag,ce_level,ru->proc.frame_prach,subframe,fp->samples_per_tti, + LOG_I(PHY,"RU %d, br_flag %d ce_level %d subframe %d per_tti:%d prach:%p (energy %d) TA:%d %s rxdata:%p index:%d\n", + ru->idx,br_flag,ce_level,subframe,fp->samples_per_tti, prach[aa],dbEn0,ru->N_TA_offset,buffer,ru->common.rxdata[aa], (subframe*fp->samples_per_tti)-ru->N_TA_offset); } @@ -424,16 +423,16 @@ void rx_prach0(PHY_VARS_eNB *eNB, if ((eNB==NULL) && ru->function == NGFI_RRU_IF4p5) { /// **** send_IF4 of rxsigF to RAU **** /// #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) - if (br_flag == 1) send_IF4p5(ru, ru->proc.frame_prach, ru->proc.subframe_prach, IF4p5_PRACH+1+ce_level); + if (br_flag == 1) send_IF4p5(ru, proc->frame_prach, proc->subframe_prach, IF4p5_PRACH+1+ce_level); else #endif - send_IF4p5(ru, ru->proc.frame_prach, ru->proc.subframe_prach, IF4p5_PRACH); + send_IF4p5(ru, proc->frame_prach, proc->subframe_prach, IF4p5_PRACH); return; } else if (eNB!=NULL) { if ( LOG_DEBUGFLAG(PRACH)) { int en = dB_fixed(signal_energy((int32_t *)&rxsigF[0][0],840)); - if ((en > 60)&&(br_flag==1)) LOG_I(PHY,"PRACH (br_flag %d,ce_level %d, n_ra_prb %d, k %d): Frame %d, Subframe %d => %d dB\n",br_flag,ce_level,n_ra_prb,k,eNB->proc.frame_rx,eNB->proc.subframe_rx,en); + if ((en > 60)&&(br_flag==1)) LOG_I(PHY,"PRACH (br_flag %d,ce_level %d, n_ra_prb %d, k %d): Frame %d, Subframe %d => %d dB\n",br_flag,ce_level,n_ra_prb,k,proc->frame_rx,proc->subframe_rx,en); } } @@ -475,7 +474,7 @@ void rx_prach0(PHY_VARS_eNB *eNB, if (LOG_DEBUGFLAG(PRACH)) { int en = dB_fixed(signal_energy((int32_t *)&rxsigF[0][0],840)); - if (en>60) LOG_I(PHY,"frame %d, subframe %d : Trying preamble %d (br_flag %d)\n",ru->proc.frame_prach,subframe,preamble_index,br_flag); + if (en>60) LOG_I(PHY,"frame %d, subframe %d : Trying preamble %d (br_flag %d)\n",proc->frame_prach,subframe,preamble_index,br_flag); } if (restricted_set == 0) { @@ -561,7 +560,7 @@ void rx_prach0(PHY_VARS_eNB *eNB, int en = dB_fixed(signal_energy((int32_t *)&rxsigF[0][0],840)); if (en>60) LOG_I(PHY,"frame %d, subframe %d : preamble index %d: offset %d, preamble shift %d (br_flag %d, en %d)\n", - ru->proc.frame_prach,subframe,preamble_index,preamble_offset,preamble_shift,br_flag,en); + proc->frame_prach,subframe,preamble_index,preamble_offset,preamble_shift,br_flag,en); } log2_ifft_size = 10; @@ -643,7 +642,7 @@ void rx_prach0(PHY_VARS_eNB *eNB, if (LOG_DEBUGFLAG(PRACH)) { int en = dB_fixed(signal_energy((int32_t *)&rxsigF[0][0],840)); - if (en>60) LOG_I(PHY,"frame %d, subframe %d: Checking for peak in time-domain (br_flag %d, en %d)\n",ru->proc.frame_prach,subframe,br_flag,en); + if (en>60) LOG_I(PHY,"frame %d, subframe %d: Checking for peak in time-domain (br_flag %d, en %d)\n",proc->frame_prach,subframe,br_flag,en); } preamble_shift2 = ((preamble_shift==0) ? 0 : ((preamble_shift<60) && (br_flag==1)) LOG_D(PHY,"frame %d, subframe %d : max_preamble_energy %d, max_preamble_delay %d, max_preamble %d (br_flag %d,ce_level %d, levdB %d, lev %d)\n", - ru->proc.frame_prach,subframe, + proc->frame_prach,subframe, *max_preamble_energy,*max_preamble_delay, *max_preamble,br_flag,ce_level,levdB,lev); } @@ -707,6 +706,7 @@ void rx_prach0(PHY_VARS_eNB *eNB, #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) void rx_prach(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, RU_t *ru, uint16_t *max_preamble, uint16_t *max_preamble_energy, @@ -719,21 +719,21 @@ void rx_prach(PHY_VARS_eNB *eNB, int prach_mask=0; if (br_flag == 0) { - rx_prach0(eNB,ru,max_preamble,max_preamble_energy,max_preamble_delay,avg_preamble_energy,Nf,tdd_mapindex,0,0); + rx_prach0(eNB,proc, ru,max_preamble,max_preamble_energy,max_preamble_delay,avg_preamble_energy,Nf,tdd_mapindex,0,0); } else { // This is procedure for eMTC, basically handling the repetitions - prach_mask = is_prach_subframe(&eNB->frame_parms,eNB->proc.frame_prach_br,eNB->proc.subframe_prach_br); + prach_mask = is_prach_subframe(&eNB->frame_parms,proc->frame_prach_br,proc->subframe_prach_br); for (i=0; i<4; i++) { if ((eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_CElevel_enable[i]==1) && ((prach_mask&(1<<(i+1))) > 0)) { // check that prach CE level is active now // if first reception in group of repetitions store frame for later (in RA-RNTI for Msg2) - if (eNB->prach_vars_br.repetition_number[i]==0) eNB->prach_vars_br.first_frame[i]=eNB->proc.frame_prach_br; + if (eNB->prach_vars_br.repetition_number[i]==0) eNB->prach_vars_br.first_frame[i]=proc->frame_prach_br; // increment repetition number eNB->prach_vars_br.repetition_number[i]++; // do basic PRACH reception - rx_prach0(eNB,ru,max_preamble,max_preamble_energy,max_preamble_delay,avg_preamble_energy,Nf,tdd_mapindex,1,i); + rx_prach0(eNB,proc, ru,max_preamble,max_preamble_energy,max_preamble_delay,avg_preamble_energy,Nf,tdd_mapindex,1,i); // if last repetition, clear counter if (eNB->prach_vars_br.repetition_number[i] == eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_numRepetitionPerPreambleAttempt[i]) { diff --git a/openair1/PHY/LTE_TRANSPORT/transport_proto.h b/openair1/PHY/LTE_TRANSPORT/transport_proto.h index 90555eb2a8..a795ca79a0 100644 --- a/openair1/PHY/LTE_TRANSPORT/transport_proto.h +++ b/openair1/PHY/LTE_TRANSPORT/transport_proto.h @@ -573,7 +573,9 @@ uint32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, @returns 0 on success */ -void rx_prach(PHY_VARS_eNB *phy_vars_eNB,RU_t *ru, +void rx_prach(PHY_VARS_eNB *phy_vars_eNB, + L1_rxtx_proc_t *proc, + RU_t *ru, uint16_t *max_preamble, uint16_t *max_preamble_energy, uint16_t *max_preamble_delay, diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index f7bea46744..1f8afe2609 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -211,324 +211,7 @@ uint8_t extract_cqi_crc(uint8_t *cqi,uint8_t CQI_LENGTH) { return(crc); } - - - -int ulsch_decoding_data_2thread0(td_params *tdp) { - PHY_VARS_eNB *eNB = tdp->eNB; - int UE_id = tdp->UE_id; - int harq_pid = tdp->harq_pid; - int llr8_flag = tdp->llr8_flag; - unsigned int r,r_offset=0,Kr,Kr_bytes; - uint8_t crc_type; - int offset = 0; - int ret = 1; - int16_t dummy_w[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)]; - LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id]; - LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; - int Q_m = ulsch_harq->Qm; - int G = ulsch_harq->G; - uint32_t E=0; - uint32_t Gp,GpmodC,Nl=1; - uint32_t C = ulsch_harq->C; - decoder_if_t *tc; - - if (llr8_flag == 0) - tc = decoder16; - else - tc = decoder8; - - // go through first half of segments to get r_offset - for (r=0; r<(ulsch_harq->C/2); r++) { - // Get Turbo interleaver parameters - if (rCminus) - Kr = ulsch_harq->Kminus; - else - Kr = ulsch_harq->Kplus; - - Kr_bytes = Kr>>3; - // This is stolen from rate-matching algorithm to get the value of E - Gp = G/Nl/Q_m; - GpmodC = Gp%C; - - if (r < (C-(GpmodC))) - E = Nl*Q_m * (Gp/C); - else - E = Nl*Q_m * ((GpmodC==0?0:1) + (Gp/C)); - - r_offset += E; - - if (r==0) { - offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0); - } else { - offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); - } - } - - // go through second half of segments - for (; r<(ulsch_harq->C); r++) { - // printf("before subblock deinterleaving c[%d] = %p\n",r,ulsch_harq->c[r]); - // Get Turbo interleaver parameters - if (rCminus) - Kr = ulsch_harq->Kminus; - else - Kr = ulsch_harq->Kplus; - - Kr_bytes = Kr>>3; - memset(&dummy_w[r][0],0,3*(6144+64)*sizeof(short)); - ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8), - (uint8_t *)&dummy_w[r][0], - (r==0) ? ulsch_harq->F : 0); - - if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r], - G, - ulsch_harq->w[r], - (uint8_t *) &dummy_w[r][0], - ulsch_harq->e+r_offset, - ulsch_harq->C, - NSOFT, - 0, //Uplink - 1, - ulsch_harq->rvidx, - (ulsch_harq->round==0)?1:0, // clear - ulsch_harq->Qm, - 1, - r, - &E)==-1) { - LOG_E(PHY,"ulsch_decoding.c: Problem in rate matching\n"); - return(-1); - } - - r_offset += E; - sub_block_deinterleaving_turbo(4+Kr, - &ulsch_harq->d[r][96], - ulsch_harq->w[r]); - - if (ulsch_harq->C == 1) - crc_type = CRC24_A; - else - crc_type = CRC24_B; - - ret = tc(&ulsch_harq->d[r][96], - NULL, - ulsch_harq->c[r], - NULL, - Kr, - ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS, - crc_type, - (r==0) ? ulsch_harq->F : 0, - &eNB->ulsch_tc_init_stats, - &eNB->ulsch_tc_alpha_stats, - &eNB->ulsch_tc_beta_stats, - &eNB->ulsch_tc_gamma_stats, - &eNB->ulsch_tc_ext_stats, - &eNB->ulsch_tc_intl1_stats, - &eNB->ulsch_tc_intl2_stats); - - // Reassembly of Transport block here - - if (ret != (1+ulsch->max_turbo_iterations)) { - if (rCminus) - Kr = ulsch_harq->Kminus; - else - Kr = ulsch_harq->Kplus; - - Kr_bytes = Kr>>3; - memcpy(ulsch_harq->b+offset, - ulsch_harq->c[r], - Kr_bytes - ((ulsch_harq->C>1)?3:0)); - offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); - } else { - break; - } - } - - return(ret); -} - extern int oai_exit; -void *td_thread(void *param) { - PHY_VARS_eNB *eNB = ((td_params *)param)->eNB; - L1_proc_t *proc = &eNB->proc; - cpu_set_t cpuset; - CPU_ZERO(&cpuset); - thread_top_init("td_thread",1,200000,250000,500000); - pthread_setname_np( pthread_self(),"td processing"); - LOG_I(PHY,"thread td created id=%ld\n", syscall(__NR_gettid)); - //wait_sync("td_thread"); - - while (!oai_exit) { - if (wait_on_condition(&proc->mutex_td,&proc->cond_td,&proc->instance_cnt_td,"td thread")<0) break; - - if(oai_exit) break; - - ((td_params *)param)->ret = ulsch_decoding_data_2thread0((td_params *)param); - - if (release_thread(&proc->mutex_td,&proc->instance_cnt_td,"td thread")<0) break; - - if (pthread_cond_signal(&proc->cond_td) != 0) { - printf("[eNB] ERROR pthread_cond_signal for td thread exit\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return(NULL); - } - } - - return(NULL); -} - -int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) { - L1_proc_t *proc = &eNB->proc; - unsigned int r,r_offset=0,Kr,Kr_bytes; - uint8_t crc_type; - int offset = 0; - int ret = 1; - int16_t dummy_w[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)]; - LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id]; - LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; - int G = ulsch_harq->G; - unsigned int E; - int Cby2; - decoder_if_t *tc; - struct timespec wait; - wait.tv_sec=0; - wait.tv_nsec=5000000L; - - if (llr8_flag == 0) - tc = decoder16; - else - tc = decoder8; - - if (ulsch_harq->C>1) { // wakeup worker if more than 1 segment - if (pthread_mutex_timedlock(&proc->mutex_td,&wait) != 0) { - printf("[eNB] ERROR pthread_mutex_lock for TD thread (IC %d)\n", proc->instance_cnt_td); - exit_fun( "error locking mutex_fep" ); - return -1; - } - - if (proc->instance_cnt_td==0) { - printf("[eNB] TD thread busy\n"); - exit_fun("TD thread busy"); - pthread_mutex_unlock( &proc->mutex_td ); - return -1; - } - - ++proc->instance_cnt_td; - proc->tdp.eNB = eNB; - proc->tdp.UE_id = UE_id; - proc->tdp.harq_pid = harq_pid; - proc->tdp.llr8_flag = llr8_flag; - - // wakeup worker to do second half segments - if (pthread_cond_signal(&proc->cond_td) != 0) { - printf("[eNB] ERROR pthread_cond_signal for td thread exit\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return (1+ulsch->max_turbo_iterations); - } - - pthread_mutex_unlock( &proc->mutex_td ); - Cby2 = ulsch_harq->C/2; - } else { - Cby2 = 1; - } - - // go through first half of segments in main thread - for (r=0; rc[r]); - // Get Turbo interleaver parameters - if (rCminus) - Kr = ulsch_harq->Kminus; - else - Kr = ulsch_harq->Kplus; - - Kr_bytes = Kr>>3; - memset(&dummy_w[r][0],0,3*(6144+64)*sizeof(short)); - ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8), - (uint8_t *)&dummy_w[r][0], - (r==0) ? ulsch_harq->F : 0); - start_meas(&eNB->ulsch_rate_unmatching_stats); - - if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r], - G, - ulsch_harq->w[r], - (uint8_t *) &dummy_w[r][0], - ulsch_harq->e+r_offset, - ulsch_harq->C, - NSOFT, - 0, //Uplink - 1, - ulsch_harq->rvidx, - (ulsch_harq->round==0)?1:0, // clear - ulsch_harq->Qm, - 1, - r, - &E)==-1) { - LOG_E(PHY,"ulsch_decoding.c: Problem in rate matching\n"); - return(-1); - } - - stop_meas(&eNB->ulsch_rate_unmatching_stats); - r_offset += E; - start_meas(&eNB->ulsch_deinterleaving_stats); - sub_block_deinterleaving_turbo(4+Kr, - &ulsch_harq->d[r][96], - ulsch_harq->w[r]); - stop_meas(&eNB->ulsch_deinterleaving_stats); - - if (ulsch_harq->C == 1) - crc_type = CRC24_A; - else - crc_type = CRC24_B; - - start_meas(&eNB->ulsch_turbo_decoding_stats); - ret = tc(&ulsch_harq->d[r][96], - NULL, - ulsch_harq->c[r], - NULL, - Kr, - ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS, - crc_type, - (r==0) ? ulsch_harq->F : 0, - &eNB->ulsch_tc_init_stats, - &eNB->ulsch_tc_alpha_stats, - &eNB->ulsch_tc_beta_stats, - &eNB->ulsch_tc_gamma_stats, - &eNB->ulsch_tc_ext_stats, - &eNB->ulsch_tc_intl1_stats, - &eNB->ulsch_tc_intl2_stats); - - // Reassembly of Transport block here - - if (ret != (1+ulsch->max_turbo_iterations)) { - if (rCminus) - Kr = ulsch_harq->Kminus; - else - Kr = ulsch_harq->Kplus; - - Kr_bytes = Kr>>3; - - if (r==0) { - memcpy(ulsch_harq->b, - &ulsch_harq->c[0][(ulsch_harq->F>>3)], - Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0)); - offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0); - } else { - memcpy(ulsch_harq->b+offset, - ulsch_harq->c[r], - Kr_bytes - ((ulsch_harq->C>1)?3:0)); - offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); - } - } else { - break; - } - - stop_meas(&eNB->ulsch_turbo_decoding_stats); - //printf("/////////////////////////////////////////**************************loop for %d time in ulsch_decoding main\n",r); - } - - // wait for worker to finish - wait_on_busy_condition(&proc->mutex_td,&proc->cond_td,&proc->instance_cnt_td,"td thread"); - return( (ret>proc->tdp.ret) ? ret : proc->tdp.ret ); -} int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) { unsigned int r,r_offset=0,Kr,Kr_bytes; diff --git a/openair1/PHY/defs_eNB.h b/openair1/PHY/defs_eNB.h index c6e348cb70..1ae3515cd8 100644 --- a/openair1/PHY/defs_eNB.h +++ b/openair1/PHY/defs_eNB.h @@ -71,220 +71,8 @@ #include -#include "openair2/PHY_INTERFACE/IF_Module.h" -typedef struct RU_proc_t_s { - /// Pointer to associated RU descriptor - struct RU_t_s *ru; - /// timestamp received from HW - openair0_timestamp timestamp_rx; - /// timestamp to send to "slave rru" - openair0_timestamp timestamp_tx; - /// subframe to act upon for reception - int subframe_rx; - /// subframe to act upon for transmission - int subframe_tx; - /// subframe to act upon for reception of prach - int subframe_prach; -#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) - /// subframe to act upon for reception of prach BL/CE UEs - int subframe_prach_br; -#endif - /// frame to act upon for reception - int frame_rx; - /// frame to act upon for transmission - int frame_tx; - /// unwrapped frame count - int frame_tx_unwrap; - /// frame to act upon for reception of prach - int frame_prach; -#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) - /// frame to act upon for reception of prach - int frame_prach_br; -#endif - /// frame offset for slave RUs (to correct for frame asynchronism at startup) - int frame_offset; - /// \brief Instance count for FH processing thread. - /// \internal This variable is protected by \ref mutex_FH. - int instance_cnt_FH; - int instance_cnt_FH1; - /// \internal This variable is protected by \ref mutex_prach. - int instance_cnt_prach; -#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) - /// \internal This variable is protected by \ref mutex_prach. - int instance_cnt_prach_br; -#endif - /// \internal This variable is protected by \ref mutex_synch. - int instance_cnt_synch; - /// \internal This variable is protected by \ref mutex_eNBs. - int instance_cnt_eNBs; - /// \brief Instance count for rx processing thread. - /// \internal This variable is protected by \ref mutex_asynch_rxtx. - int instance_cnt_asynch_rxtx; - /// \internal This variable is protected by \ref mutex_fep - int instance_cnt_fep; - /// \internal This variable is protected by \ref mutex_feptx - int instance_cnt_feptx; - - /// \internal This variable is protected by \ref mutex_ru_thread - int instance_cnt_ru; - /// pthread structure for RU FH processing thread - pthread_t pthread_FH; - /// pthread structure for RU control thread - pthread_t pthread_ctrl; - - /// This varible is protected by \ref mutex_emulatedRF - int instance_cnt_emulateRF; - /// pthread structure for RU FH processing thread - - pthread_t pthread_FH1; - - /// pthread structure for RU prach processing thread - pthread_t pthread_prach; -#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) - /// pthread structure for RU prach processing thread BL/CE UEs - pthread_t pthread_prach_br; -#endif - /// pthread struct for RU synch thread - pthread_t pthread_synch; - /// pthread struct for RU RX FEP worker thread - pthread_t pthread_fep; - /// pthread struct for RU TX FEP worker thread - pthread_t pthread_feptx; - /// pthread struct for emulated RF - pthread_t pthread_emulateRF; - /// pthread structure for asychronous RX/TX processing thread - pthread_t pthread_asynch_rxtx; - /// flag to indicate first RX acquisition - int first_rx; - /// flag to indicate first TX transmission - int first_tx; - /// pthread attributes for RU FH processing thread - pthread_attr_t attr_FH; - - /// pthread attributes for RU control thread - pthread_attr_t attr_ctrl; - - pthread_attr_t attr_FH1; - - /// pthread attributes for RU prach - pthread_attr_t attr_prach; -#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) - /// pthread attributes for RU prach BL/CE UEs - pthread_attr_t attr_prach_br; -#endif - /// pthread attributes for RU synch thread - pthread_attr_t attr_synch; - /// pthread attributes for asynchronous RX thread - pthread_attr_t attr_asynch_rxtx; - /// pthread attributes for worker fep thread - pthread_attr_t attr_fep; - /// pthread attributes for worker feptx thread - pthread_attr_t attr_feptx; - /// pthread attributes for emulated RF - pthread_attr_t attr_emulateRF; - /// scheduling parameters for RU FH thread - struct sched_param sched_param_FH; - struct sched_param sched_param_FH1; - /// scheduling parameters for RU prach thread - struct sched_param sched_param_prach; -#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) - /// scheduling parameters for RU prach thread BL/CE UEs - struct sched_param sched_param_prach_br; -#endif - /// scheduling parameters for RU synch thread - struct sched_param sched_param_synch; - /// scheduling parameters for asynch_rxtx thread - struct sched_param sched_param_asynch_rxtx; - /// condition variable for RU FH thread - pthread_cond_t cond_FH; - pthread_cond_t cond_FH1; - /// condition variable for RU prach thread - pthread_cond_t cond_prach; -#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) - /// condition variable for RU prach thread BL/CE UEs - pthread_cond_t cond_prach_br; -#endif - /// condition variable for RU synch thread - pthread_cond_t cond_synch; - /// condition variable for asynch RX/TX thread - pthread_cond_t cond_asynch_rxtx; - /// condition variable for RU RX FEP thread - pthread_cond_t cond_fep; - /// condition variable for RU TX FEP thread - pthread_cond_t cond_feptx; - /// condition variable for emulated RF - pthread_cond_t cond_emulateRF; - /// condition variable for eNB signal - pthread_cond_t cond_eNBs; - /// condition variable for ru_thread - pthread_cond_t cond_ru_thread; - /// mutex for RU FH - pthread_mutex_t mutex_FH; - pthread_mutex_t mutex_FH1; - /// mutex for RU prach - pthread_mutex_t mutex_prach; -#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) - /// mutex for RU prach BL/CE UEs - pthread_mutex_t mutex_prach_br; -#endif - /// mutex for RU synch - pthread_mutex_t mutex_synch; - /// mutex for eNB signal - pthread_mutex_t mutex_eNBs; - /// mutex for asynch RX/TX thread - pthread_mutex_t mutex_asynch_rxtx; - /// mutex for fep RX worker thread - pthread_mutex_t mutex_fep; - /// mutex for fep TX worker thread - pthread_mutex_t mutex_feptx; - - /// mutex for ru_thread - pthread_mutex_t mutex_ru; - - /// mutex for emulated RF thread - pthread_mutex_t mutex_emulateRF; - - /// symbol mask for IF4p5 reception per subframe - uint32_t symbol_mask[10]; - /// time measurements for each subframe - struct timespec t[10]; - /// number of slave threads - int num_slaves; - /// array of pointers to slaves - struct RU_proc_t_s **slave_proc; -#ifdef PHY_TX_THREAD - /// pthread structure for PRACH thread - pthread_t pthread_phy_tx; - pthread_mutex_t mutex_phy_tx; - pthread_cond_t cond_phy_tx; - /// \internal This variable is protected by \ref mutex_phy_tx. - int instance_cnt_phy_tx; - /// frame to act upon for transmission - int frame_phy_tx; - /// subframe to act upon for transmission - int subframe_phy_tx; - /// timestamp to send to "slave rru" - openair0_timestamp timestamp_phy_tx; - /// pthread structure for RF TX thread - pthread_t pthread_rf_tx; - pthread_mutex_t mutex_rf_tx; - pthread_cond_t cond_rf_tx; - /// \internal This variable is protected by \ref mutex_rf_tx. - int instance_cnt_rf_tx; -#endif -#if defined(PRE_SCD_THREAD) - pthread_t pthread_pre_scd; - /// condition variable for time processing thread - pthread_cond_t cond_pre_scd; - /// mutex for time thread - pthread_mutex_t mutex_pre_scd; - int instance_pre_scd; -#endif - int emulate_rf_busy; -} RU_proc_t; - typedef enum { LOCAL_RF =0, REMOTE_IF5 =1, @@ -312,6 +100,7 @@ typedef enum { WAIT_RESYNCH = 3 } rru_cmd_t; +#include "openair2/PHY_INTERFACE/IF_Module.h" typedef struct RU_t_s{ /// index of this ru uint32_t idx; @@ -396,7 +185,7 @@ typedef struct RU_t_s{ /// function pointer to synchronous RX fronthaul function (RRU,3GPP_eNB) void (*fh_south_in)(struct RU_t_s *ru,int *frame, int *subframe); /// function pointer to synchronous TX fronthaul function - void (*fh_south_out)(struct RU_t_s *ru); + void (*fh_south_out)(struct RU_t_s *ru, L1_rxtx_proc_t * proc); /// function pointer to synchronous RX fronthaul function (RRU) void (*fh_north_in)(struct RU_t_s *ru,int *frame, int *subframe); /// function pointer to synchronous RX fronthaul function (RRU) @@ -412,11 +201,11 @@ typedef struct RU_t_s{ /// function pointer to initialization function for radio interface int (*start_if)(struct RU_t_s *ru,struct PHY_VARS_eNB_s *eNB); /// function pointer to RX front-end processing routine (DFTs/prefix removal or NULL) - void (*feprx)(struct RU_t_s *ru); + void (*feprx)(struct RU_t_s *ru, L1_rxtx_proc_t * proc); /// function pointer to TX front-end processing routine (IDFTs and prefix removal or NULL) - void (*feptx_ofdm)(struct RU_t_s *ru); + void (*feptx_ofdm)(struct RU_t_s *ru, L1_rxtx_proc_t * proc); /// function pointer to TX front-end processing routine (PRECODING) - void (*feptx_prec)(struct RU_t_s *ru); + void (*feptx_prec)(struct RU_t_s *ru, L1_rxtx_proc_t * proc); /// function pointer to wakeup routine in lte-enb. int (*wakeup_rxtx)(struct PHY_VARS_eNB_s *eNB, struct RU_t_s *ru); /// function pointer to wakeup routine in lte-enb. @@ -426,7 +215,7 @@ typedef struct RU_t_s{ void (*wakeup_prach_eNB_br)(struct PHY_VARS_eNB_s *eNB,struct RU_t_s *ru,int frame,int subframe); #endif /// function pointer to eNB entry routine - void (*eNB_top)(struct PHY_VARS_eNB_s *eNB, int frame_rx, int subframe_rx, char *string, struct RU_t_s *ru); + void (*eNB_top)(struct PHY_VARS_eNB_s *eNB, L1_rxtx_proc_t * proc, int frame_rx, int subframe_rx, char *string, struct RU_t_s *ru); /// Timing statistics time_stats_t ofdm_demod_stats; /// Timing statistics (TX) @@ -468,7 +257,7 @@ typedef struct RU_t_s{ /// value to be passed using command uint16_t cmdval; /// process scheduling variables - RU_proc_t proc; + //RU_proc_t proc; /// stats thread pthread descriptor pthread_t ru_stats_thread; /// OTA synchronization signal @@ -728,41 +517,6 @@ typedef struct { #include "PHY/TOOLS/tools_defs.h" #include "PHY/LTE_TRANSPORT/transport_eNB.h" -/// Context data structure for RX/TX portion of subframe processing -typedef struct { - /// Component Carrier index - uint8_t CC_id; - /// timestamp transmitted to HW - openair0_timestamp timestamp_tx; - /// subframe to act upon for transmission - int subframe_tx; - /// subframe to act upon for reception - int subframe_rx; - /// frame to act upon for transmission - int frame_tx; - /// frame to act upon for reception - int frame_rx; - /// \brief Instance count for RXn-TXnp4 processing thread. - /// \internal This variable is protected by \ref mutex_rxtx. - int instance_cnt; - /// pthread structure for RXn-TXnp4 processing thread - pthread_t pthread; - /// pthread attributes for RXn-TXnp4 processing thread - pthread_attr_t attr; - /// condition variable for tx processing thread - pthread_cond_t cond; - /// mutex for RXn-TXnp4 processing thread - pthread_mutex_t mutex; - /// scheduling parameters for RXn-TXnp4 thread - struct sched_param sched_param_rxtx; - - /// \internal This variable is protected by \ref mutex_RUs. - int instance_cnt_RUs; - /// condition variable for tx processing thread - pthread_cond_t cond_RUs; - /// mutex for RXn-TXnp4 processing thread - pthread_mutex_t mutex_RUs; -} L1_rxtx_proc_t; typedef struct { struct PHY_VARS_eNB_s *eNB; @@ -793,159 +547,6 @@ typedef struct { pthread_mutex_t mutex_te; } te_params; -/// Context data structure for eNB subframe processing -typedef struct L1_proc_t_s { - /// Component Carrier index - uint8_t CC_id; - /// thread index - int thread_index; - /// timestamp received from HW - openair0_timestamp timestamp_rx; - /// timestamp to send to "slave rru" - openair0_timestamp timestamp_tx; - /// subframe to act upon for reception - int subframe_rx; - /// subframe to act upon for PRACH - int subframe_prach; -#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) - /// subframe to act upon for reception of prach BL/CE UEs - int subframe_prach_br; -#endif - /// frame to act upon for reception - int frame_rx; - /// frame to act upon for transmission - int frame_tx; - /// frame to act upon for PRACH - int frame_prach; -#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) - /// frame to act upon for PRACH BL/CE UEs - int frame_prach_br; -#endif - /// \internal This variable is protected by \ref mutex_td. - int instance_cnt_td; - /// \internal This variable is protected by \ref mutex_te. - int instance_cnt_te; - /// \internal This variable is protected by \ref mutex_prach. - int instance_cnt_prach; -#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) - /// \internal This variable is protected by \ref mutex_prach for BL/CE UEs. - int instance_cnt_prach_br; -#endif - // instance count for over-the-air eNB synchronization - int instance_cnt_synch; - - - /// \internal This variable is protected by \ref mutex_asynch_rxtx. - int instance_cnt_asynch_rxtx; - /// pthread structure for asychronous RX/TX processing thread - pthread_t pthread_asynch_rxtx; - /// flag to indicate first RX acquisition - int first_rx; - /// flag to indicate first TX transmission - int first_tx; - /// pthread attributes for parallel turbo-decoder thread - pthread_attr_t attr_td; - /// pthread attributes for parallel turbo-encoder thread - pthread_attr_t attr_te; - /// pthread attributes for single eNB processing thread - pthread_attr_t attr_single; - /// pthread attributes for prach processing thread - pthread_attr_t attr_prach; -#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) - /// pthread attributes for prach processing thread BL/CE UEs - pthread_attr_t attr_prach_br; -#endif - /// pthread attributes for asynchronous RX thread - pthread_attr_t attr_asynch_rxtx; - /// scheduling parameters for parallel turbo-decoder thread - struct sched_param sched_param_td; - /// scheduling parameters for parallel turbo-encoder thread - struct sched_param sched_param_te; - /// scheduling parameters for single eNB thread - struct sched_param sched_param_single; - /// scheduling parameters for prach thread - struct sched_param sched_param_prach; -#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) - /// scheduling parameters for prach thread - struct sched_param sched_param_prach_br; -#endif - /// scheduling parameters for asynch_rxtx thread - struct sched_param sched_param_asynch_rxtx; - /// pthread structure for parallel turbo-decoder thread - pthread_t pthread_td; - /// pthread structure for parallel turbo-encoder thread - pthread_t pthread_te; - /// pthread structure for PRACH thread - pthread_t pthread_prach; -#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) - /// pthread structure for PRACH thread BL/CE UEs - pthread_t pthread_prach_br; -#endif - /// condition variable for parallel turbo-decoder thread - pthread_cond_t cond_td; - /// condition variable for parallel turbo-encoder thread - pthread_cond_t cond_te; - /// condition variable for PRACH processing thread; - pthread_cond_t cond_prach; -#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) - /// condition variable for PRACH processing thread BL/CE UEs; - pthread_cond_t cond_prach_br; -#endif - - /// condition variable for asynch RX/TX thread - pthread_cond_t cond_asynch_rxtx; - /// mutex for parallel turbo-decoder thread - pthread_mutex_t mutex_td; - /// mutex for parallel turbo-encoder thread - pthread_mutex_t mutex_te; - /// mutex for PRACH thread - pthread_mutex_t mutex_prach; -#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) - /// mutex for PRACH thread for BL/CE UEs - pthread_mutex_t mutex_prach_br; -#endif - /// mutex for asynch RX/TX thread - pthread_mutex_t mutex_asynch_rxtx; - /// mutex for RU access to eNB processing (PDSCH/PUSCH) - pthread_mutex_t mutex_RU; - /// mutex for eNB processing to access RU TX (PDSCH/PUSCH) - pthread_mutex_t mutex_RU_tx; - /// mutex for RU access to eNB processing (PRACH) - pthread_mutex_t mutex_RU_PRACH; - /// mutex for RU access to eNB processing (PRACH BR) - pthread_mutex_t mutex_RU_PRACH_br; - /// mask for RUs serving eNB (PDSCH/PUSCH) - int RU_mask[10]; - /// mask for RUs serving eNB (PDSCH/PUSCH) - int RU_mask_tx; - /// time measurements for RU arrivals - struct timespec t[10]; - /// Timing statistics (RU_arrivals) - time_stats_t ru_arrival_time; - /// mask for RUs serving eNB (PRACH) - int RU_mask_prach; -#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) - /// mask for RUs serving eNB (PRACH) - int RU_mask_prach_br; -#endif - /// parameters for turbo-decoding worker thread - td_params tdp; - /// parameters for turbo-encoding worker thread - te_params tep[3]; - /// set of scheduling variables RXn-TXnp4 threads - L1_rxtx_proc_t L1_proc,L1_proc_tx; - /// stats thread pthread descriptor - pthread_t process_stats_thread; - /// for waking up tx procedure - RU_proc_t *ru_proc; -} L1_proc_t; - - - - - - - typedef struct { //unsigned int rx_power[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX]; //! estimated received signal power (linear) //unsigned short rx_power_dB[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX]; //! estimated received signal power (dB) @@ -1007,7 +608,7 @@ typedef struct PHY_VARS_eNB_s { module_id_t Mod_id; uint8_t CC_id; uint8_t configured; - L1_proc_t proc; + //L1_proc_t proc; int single_thread_flag; int abstraction_flag; int num_RU; @@ -1257,5 +858,6 @@ typedef struct PHY_VARS_eNB_s { } PHY_VARS_eNB; + #endif /* __PHY_DEFS_ENB__H__ */ diff --git a/openair1/SCHED/fapi_l1.c b/openair1/SCHED/fapi_l1.c index 5113502fcc..b52a2eb22c 100644 --- a/openair1/SCHED/fapi_l1.c +++ b/openair1/SCHED/fapi_l1.c @@ -730,9 +730,8 @@ void handle_nfapi_ul_pdu(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, } } -void schedule_response(Sched_Rsp_t *Sched_INFO) { +void schedule_response(Sched_Rsp_t *Sched_INFO, L1_rxtx_proc_t *proc) { PHY_VARS_eNB *eNB; - L1_rxtx_proc_t *proc; // copy data from L2 interface into L1 structures module_id_t Mod_id = Sched_INFO->module_id; uint8_t CC_id = Sched_INFO->CC_id; @@ -752,7 +751,6 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) { AssertFatal(RC.eNB[Mod_id][CC_id]!=NULL,"RC.eNB[%d][%d] is null\n",Mod_id,CC_id); eNB = RC.eNB[Mod_id][CC_id]; fp = &eNB->frame_parms; - proc = &eNB->proc.L1_proc; /* TODO: check that following line is correct - in the meantime it is disabled */ //if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)==SF_UL)) return; ul_subframe = pdcch_alloc2ul_subframe(fp,subframe); diff --git a/openair1/SCHED/fapi_l1.h b/openair1/SCHED/fapi_l1.h index 0314fcc322..9c5c314334 100644 --- a/openair1/SCHED/fapi_l1.h +++ b/openair1/SCHED/fapi_l1.h @@ -76,4 +76,4 @@ void handle_uci_harq_pdu(PHY_VARS_eNB *eNB,int UE_id,nfapi_ul_config_request_pdu void handle_srs_pdu(PHY_VARS_eNB *eNB,nfapi_ul_config_request_pdu_t *ul_config_pdu,uint16_t frame,uint8_t subframe); -void schedule_response(Sched_Rsp_t *Sched_INFO); +void schedule_response(Sched_Rsp_t *Sched_INFO, L1_rxtx_proc_t *proc); diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index a6b546679a..e5c767361d 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -1360,51 +1360,8 @@ extern int oai_exit; extern void *td_thread (void *); -void init_td_thread(PHY_VARS_eNB *eNB) { - L1_proc_t *proc = &eNB->proc; - proc->tdp.eNB = eNB; - proc->instance_cnt_td = -1; - pthread_attr_init( &proc->attr_td); - pthread_mutex_init( &proc->mutex_td, NULL); - pthread_cond_init( &proc->cond_td, NULL); - pthread_create(&proc->pthread_td, &proc->attr_td, td_thread, (void *)&proc->tdp); -} -void kill_td_thread(PHY_VARS_eNB *eNB) { - L1_proc_t *proc = &eNB->proc; - proc->instance_cnt_td = 0; - pthread_cond_signal(&proc->cond_td); - pthread_join(proc->pthread_td, NULL); - pthread_mutex_destroy( &proc->mutex_td ); - pthread_cond_destroy( &proc->cond_td ); -} - extern void *te_thread (void *); -void init_te_thread(PHY_VARS_eNB *eNB) { - L1_proc_t *proc = &eNB->proc; - - for(int i=0; i<3 ; i++) { - proc->tep[i].eNB = eNB; - proc->tep[i].instance_cnt_te = -1; - pthread_mutex_init( &proc->tep[i].mutex_te, NULL); - pthread_cond_init( &proc->tep[i].cond_te, NULL); - pthread_attr_init( &proc->tep[i].attr_te); - LOG_I(PHY,"Creating te_thread %d\n",i); - pthread_create(&proc->tep[i].pthread_te, &proc->tep[i].attr_te, te_thread, (void *)&proc->tep[i]); - } -} -void kill_te_thread(PHY_VARS_eNB *eNB) { - L1_proc_t *proc = &eNB->proc; - - for(int i=0; i<3 ; i++) { - proc->tep[i].instance_cnt_te = 0; - pthread_cond_signal(&proc->tep[i].cond_te); - pthread_join(proc->tep[i].pthread_te, NULL); - pthread_mutex_destroy( &proc->tep[i].mutex_te); - pthread_cond_destroy( &proc->tep[i].cond_te); - } -} - void fill_rx_indication(PHY_VARS_eNB *eNB,int UE_id,int frame,int subframe) { nfapi_rx_indication_pdu_t *pdu; int timing_advance_update; diff --git a/openair1/SCHED/prach_procedures.c b/openair1/SCHED/prach_procedures.c index 15d2c4fafc..6223be1a91 100644 --- a/openair1/SCHED/prach_procedures.c +++ b/openair1/SCHED/prach_procedures.c @@ -53,7 +53,8 @@ extern int oai_nfapi_rach_ind(nfapi_rach_indication_t *rach_ind); -void prach_procedures(PHY_VARS_eNB *eNB +void prach_procedures(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) , int br_flag @@ -65,8 +66,8 @@ void prach_procedures(PHY_VARS_eNB *eNB #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) if (br_flag==1) { - subframe = eNB->proc.subframe_prach_br; - frame = eNB->proc.frame_prach_br; + subframe = proc->subframe_prach_br; + frame = proc->frame_prach_br; pthread_mutex_lock(&eNB->UL_INFO_mutex); eNB->UL_INFO.rach_ind_br.rach_indication_body.number_of_preambles=0; pthread_mutex_unlock(&eNB->UL_INFO_mutex); @@ -76,8 +77,8 @@ void prach_procedures(PHY_VARS_eNB *eNB pthread_mutex_lock(&eNB->UL_INFO_mutex); eNB->UL_INFO.rach_ind.rach_indication_body.number_of_preambles=0; pthread_mutex_unlock(&eNB->UL_INFO_mutex); - subframe = eNB->proc.subframe_prach; - frame = eNB->proc.frame_prach; + subframe = proc->subframe_prach; + frame = proc->frame_prach; } RU_t *ru; @@ -102,6 +103,7 @@ void prach_procedures(PHY_VARS_eNB *eNB // run PRACH detection for CE-level 0 only for now when br_flag is set rx_prach(eNB, + proc, eNB->RU_list[0], &max_preamble[0], &max_preamble_energy[0], @@ -125,7 +127,7 @@ void prach_procedures(PHY_VARS_eNB *eNB if (br_flag==1) { int prach_mask; - prach_mask = is_prach_subframe (&eNB->frame_parms, eNB->proc.frame_prach_br, eNB->proc.subframe_prach_br); + prach_mask = is_prach_subframe (&eNB->frame_parms, proc->frame_prach_br, proc->subframe_prach_br); eNB->UL_INFO.rach_ind_br.rach_indication_body.preamble_list = eNB->preamble_list_br; int ind = 0; int ce_level = 0; diff --git a/openair1/SCHED/ru_procedures.c b/openair1/SCHED/ru_procedures.c index 1f1a36b238..52103ef878 100644 --- a/openair1/SCHED/ru_procedures.c +++ b/openair1/SCHED/ru_procedures.c @@ -69,7 +69,7 @@ extern int oai_exit; -void feptx0(RU_t *ru,int slot) { +void feptx0(RU_t *ru, L1_rxtx_proc_t *proc, int slot) { LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; //int dummy_tx_b[7680*2] __attribute__((aligned(32))); @@ -77,7 +77,7 @@ void feptx0(RU_t *ru,int slot) { unsigned int aa,slot_offset; int slot_sizeF = (fp->ofdm_symbol_size)* ((fp->Ncp==1) ? 6 : 7); - int subframe = ru->proc.subframe_tx; + int subframe = proc->subframe_tx; //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+slot , 1 ); @@ -169,108 +169,7 @@ void feptx0(RU_t *ru,int slot) { //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+slot , 0); } -static void *feptx_thread(void *param) { - - RU_t *ru = (RU_t *)param; - RU_proc_t *proc = &ru->proc; - cpu_set_t cpuset; - CPU_ZERO(&cpuset); - - thread_top_init("feptx_thread",1,85000,120000,500000); - pthread_setname_np( pthread_self(),"feptx processing"); - LOG_I(PHY,"thread feptx created id=%ld\n", syscall(__NR_gettid)); - //CPU_SET(6, &cpuset); - //pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - //wait_sync("feptx_thread"); - - - - while (!oai_exit) { - - if (wait_on_condition(&proc->mutex_feptx,&proc->cond_feptx,&proc->instance_cnt_feptx,"feptx thread")<0) break; - if (oai_exit) break; - //stop_meas(&ru->ofdm_mod_wakeup_stats); - feptx0(ru,1); - if (release_thread(&proc->mutex_feptx,&proc->instance_cnt_feptx,"feptx thread")<0) break; - - if (pthread_cond_signal(&proc->cond_feptx) != 0) { - printf("[eNB] ERROR pthread_cond_signal for feptx thread exit\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return NULL; - } - /*if(opp_enabled == 1 && ru->ofdm_mod_wakeup_stats.p_time>30*3000){ - print_meas_now(&ru->ofdm_mod_wakeup_stats,"fep wakeup",stderr); - printf("delay in fep wakeup in frame_tx: %d subframe_rx: %d \n",proc->frame_tx,proc->subframe_tx); - }*/ - } - - - - return(NULL); -} - -void feptx_ofdm_2thread(RU_t *ru) { - - LTE_DL_FRAME_PARMS *fp=&ru->frame_parms; - RU_proc_t *proc = &ru->proc; - struct timespec wait; - int subframe = ru->proc.subframe_tx; - - wait.tv_sec=0; - wait.tv_nsec=5000000L; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+ru->idx , 1 ); - start_meas(&ru->ofdm_mod_stats); - - if (subframe_select(fp,subframe) == SF_UL) return; - - //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM , 1 ); - - if (subframe_select(fp,subframe)==SF_DL) { - // If this is not an S-subframe - if (pthread_mutex_timedlock(&proc->mutex_feptx,&wait) != 0) { - printf("[RU] ERROR pthread_mutex_lock for feptx thread (IC %d)\n", proc->instance_cnt_feptx); - exit_fun( "error locking mutex_feptx" ); - return; - } - - if (proc->instance_cnt_feptx==0) { - printf("[RU] FEPtx thread busy\n"); - exit_fun("FEPtx thread busy"); - pthread_mutex_unlock( &proc->mutex_feptx ); - return; - } - - ++proc->instance_cnt_feptx; - - - if (pthread_cond_signal(&proc->cond_feptx) != 0) { - printf("[RU] ERROR pthread_cond_signal for feptx thread\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return; - } - //start_meas(&ru->ofdm_mod_wakeup_stats); - - pthread_mutex_unlock( &proc->mutex_feptx ); - } - - // call first slot in this thread - feptx0(ru,0); - start_meas(&ru->ofdm_mod_wait_stats); - wait_on_busy_condition(&proc->mutex_feptx,&proc->cond_feptx,&proc->instance_cnt_feptx,"feptx thread"); - stop_meas(&ru->ofdm_mod_wait_stats); - /*if(opp_enabled == 1 && ru->ofdm_mod_wait_stats.p_time>30*3000){ - print_meas_now(&ru->ofdm_mod_wait_stats,"fep wakeup",stderr); - printf("delay in feptx wait on codition in frame_rx: %d subframe_rx: %d \n",proc->frame_tx,proc->subframe_tx); - }*/ - - //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM , 0 ); - - stop_meas(&ru->ofdm_mod_stats); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+ru->idx , 0 ); - -} - -void feptx_ofdm(RU_t *ru) { +void feptx_ofdm(RU_t *ru, L1_rxtx_proc_t* proc) { LTE_DL_FRAME_PARMS *fp=&ru->frame_parms; @@ -281,7 +180,7 @@ void feptx_ofdm(RU_t *ru) { ((fp->Ncp==1) ? 6 : 7); int len,len2; int16_t *txdata; - int subframe = ru->proc.subframe_tx; + int subframe = proc->subframe_tx; // int CC_id = ru->proc.CC_id; @@ -402,18 +301,18 @@ void feptx_ofdm(RU_t *ru) { // } stop_meas(&ru->ofdm_mod_stats); - LOG_D(PHY,"feptx_ofdm (TXPATH): frame %d, subframe %d: txp (time %p) %d dB, txp (freq) %d dB\n", - ru->proc.frame_tx,subframe,txdata,dB_fixed(signal_energy((int32_t*)txdata,fp->samples_per_tti)), + LOG_D(PHY,"feptx_ofdm (TXPATH): subframe %d: txp (time %p) %d dB, txp (freq) %d dB\n", + subframe,txdata,dB_fixed(signal_energy((int32_t*)txdata,fp->samples_per_tti)), dB_fixed(signal_energy_nodc(ru->common.txdataF_BF[aa],2*slot_sizeF))); } } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+ru->idx , 0 ); } -void feptx_prec(RU_t *ru) { +void feptx_prec(RU_t *ru, L1_rxtx_proc_t * proc) { int l,i,aa,p; - int subframe = ru->proc.subframe_tx; + int subframe = proc->subframe_tx; PHY_VARS_eNB **eNB_list = ru->eNB_list,*eNB; LTE_DL_FRAME_PARMS *fp; @@ -504,9 +403,8 @@ void feptx_prec(RU_t *ru) { } } -void fep0(RU_t *ru,int slot) { +void fep0(RU_t *ru,L1_rxtx_proc_t *proc, int slot) { - RU_proc_t *proc = &ru->proc; LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; int l; @@ -524,243 +422,8 @@ void fep0(RU_t *ru,int slot) { //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX+slot, 0); } +void fep_full(RU_t *ru, L1_rxtx_proc_t *proc) { - -static void *fep_thread(void *param) { - - RU_t *ru = (RU_t *)param; - RU_proc_t *proc = &ru->proc; - - thread_top_init("fep_thread",1,100000,120000,5000000); - pthread_setname_np( pthread_self(),"fep processing"); - LOG_I(PHY,"thread fep created id=%ld\n", syscall(__NR_gettid)); - - cpu_set_t cpuset; - CPU_ZERO(&cpuset); - //CPU_SET(2, &cpuset); - //pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - //wait_sync("fep_thread"); - - while (!oai_exit) { - - if (wait_on_condition(&proc->mutex_fep,&proc->cond_fep,&proc->instance_cnt_fep,"fep thread")<0) break; - if (oai_exit) break; - //stop_meas(&ru->ofdm_demod_wakeup_stats); - //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX1, 1 ); - fep0(ru,0); - //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX1, 0 ); - if (release_thread(&proc->mutex_fep,&proc->instance_cnt_fep,"fep thread")<0) break; - - if (pthread_cond_signal(&proc->cond_fep) != 0) { - printf("[eNB] ERROR pthread_cond_signal for fep thread exit\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return NULL; - } - /*if(opp_enabled == 1 && ru->ofdm_demod_wakeup_stats.p_time>30*3000){ - print_meas_now(&ru->ofdm_demod_wakeup_stats,"fep wakeup",stderr); - printf("delay in fep wakeup in frame_rx: %d subframe_rx: %d \n",proc->frame_rx,proc->subframe_rx); - }*/ - } - - - - return(NULL); -} - -void init_feptx_thread(RU_t *ru,pthread_attr_t *attr_feptx) { - - RU_proc_t *proc = &ru->proc; - - proc->instance_cnt_feptx = -1; - - pthread_mutex_init( &proc->mutex_feptx, NULL); - pthread_cond_init( &proc->cond_feptx, NULL); - - pthread_create(&proc->pthread_feptx, attr_feptx, feptx_thread, (void*)ru); - - -} - -void init_fep_thread(RU_t *ru,pthread_attr_t *attr_fep) { - - RU_proc_t *proc = &ru->proc; - - proc->instance_cnt_fep = -1; - - pthread_mutex_init( &proc->mutex_fep, NULL); - pthread_cond_init( &proc->cond_fep, NULL); - - pthread_create(&proc->pthread_fep, attr_fep, fep_thread, (void*)ru); - - -} - -extern void kill_fep_thread(RU_t *ru) -{ - RU_proc_t *proc = &ru->proc; - pthread_mutex_lock( &proc->mutex_fep ); - proc->instance_cnt_fep = 0; - pthread_cond_signal(&proc->cond_fep); - pthread_mutex_unlock( &proc->mutex_fep ); - LOG_D(PHY, "Joining pthread_fep\n"); - pthread_join(proc->pthread_fep, NULL); - pthread_mutex_destroy( &proc->mutex_fep ); - pthread_cond_destroy( &proc->cond_fep ); -} - -extern void kill_feptx_thread(RU_t *ru) -{ - RU_proc_t *proc = &ru->proc; - pthread_mutex_lock( &proc->mutex_feptx ); - proc->instance_cnt_feptx = 0; - pthread_cond_signal(&proc->cond_feptx); - pthread_mutex_unlock( &proc->mutex_feptx ); - LOG_D(PHY, "Joining pthread_feptx\n"); - pthread_join(proc->pthread_feptx, NULL); - pthread_mutex_destroy( &proc->mutex_feptx ); - pthread_cond_destroy( &proc->cond_feptx ); -} - -void ru_fep_full_2thread(RU_t *ru) { - - RU_proc_t *proc = &ru->proc; - //PHY_VARS_eNB *eNB = RC.eNB[0][0]; - LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; - RU_CALIBRATION *calibration = &ru->calibration; - RRU_CONFIG_msg_t rru_config_msg; - int check_sync_pos; - - struct timespec wait; - if (proc->subframe_rx==1){ - //LOG_I(PHY,"subframe type %d, RU %d\n",subframe_select(fp,proc->subframe_rx),ru->idx); - } - else if ((fp->frame_type == TDD) && (subframe_select(fp,proc->subframe_rx) != SF_UL)) { - return; - } - //if (ru->idx == 0) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX, 1 ); - - wait.tv_sec=0; - wait.tv_nsec=5000000L; - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX+ru->idx, 1 ); - start_meas(&ru->ofdm_demod_stats); - - if (pthread_mutex_timedlock(&proc->mutex_fep,&wait) != 0) { - printf("[RU] ERROR pthread_mutex_lock for fep thread (IC %d)\n", proc->instance_cnt_fep); - exit_fun( "error locking mutex_fep" ); - return; - } - - if (proc->instance_cnt_fep==0) { - printf("[RU] FEP thread busy\n"); - exit_fun("FEP thread busy"); - pthread_mutex_unlock( &proc->mutex_fep ); - return; - } - - ++proc->instance_cnt_fep; - - - if (pthread_cond_signal(&proc->cond_fep) != 0) { - printf("[RU] ERROR pthread_cond_signal for fep thread\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return; - } - //start_meas(&ru->ofdm_demod_wakeup_stats); - - pthread_mutex_unlock( &proc->mutex_fep ); - - // call second slot in this symbol - fep0(ru,1); - - start_meas(&ru->ofdm_demod_wait_stats); - wait_on_busy_condition(&proc->mutex_fep,&proc->cond_fep,&proc->instance_cnt_fep,"fep thread"); - stop_meas(&ru->ofdm_demod_wait_stats); - if(opp_enabled == 1 && ru->ofdm_demod_wakeup_stats.p_time>30*3000){ - print_meas_now(&ru->ofdm_demod_wakeup_stats,"fep wakeup",stderr); - printf("delay in fep wait on condition in frame_rx: %d subframe_rx: %d \n",proc->frame_rx,proc->subframe_rx); - } - - if (proc->subframe_rx==1 && ru->is_slave==1/* && ru->state == RU_CHECK_SYNC*/) { - - //LOG_I(PHY,"Running check synchronization procedure for frame %d\n", proc->frame_rx); - ulsch_extract_rbs_single(ru->common.rxdataF, - calibration->rxdataF_ext, - 0, - fp->N_RB_DL, - 3%(fp->symbols_per_tti/2),// l = symbol within slot - 3/(fp->symbols_per_tti/2),// Ns = slot number - fp); - - /*lte_ul_channel_estimation((PHY_VARS_eNB *)NULL, - proc, - ru->idx, - 3%(fp->symbols_per_tti/2), - 3/(fp->symbols_per_tti/2)); - */ - lte_ul_channel_estimation_RRU(fp, - calibration->drs_ch_estimates, - calibration->drs_ch_estimates_time, - calibration->rxdataF_ext, - fp->N_RB_DL, //N_rb_alloc, - proc->frame_rx, - proc->subframe_rx, - 0,//u = 0..29 - 0,//v = 0,1 - /*eNB->ulsch[ru->idx]->cyclicShift,cyclic_shift,0..7*/0, - 3,//l, - 0,//interpolate, - 0 /*eNB->ulsch[ru->idx]->rnti rnti or ru->ulsch[eNB_id]->rnti*/); - - - - check_sync_pos = lte_est_timing_advance_pusch((PHY_VARS_eNB *)NULL, - ru->idx); - if (ru->state == RU_CHECK_SYNC) { - if ((check_sync_pos >= 0 && check_sync_pos<8) || (check_sync_pos < 0 && check_sync_pos>-8)) { - LOG_I(PHY,"~~~~~~~~~~~ check_sync_pos %d, frame %d, cnt %d\n",check_sync_pos,proc->frame_rx,ru->wait_check); - ru->wait_check++; - } - - if (ru->wait_check==20) { - ru->state = RU_RUN; - ru->wait_check = 0; - // Send RRU_sync_ok - rru_config_msg.type = RRU_sync_ok; - rru_config_msg.len = sizeof(RRU_CONFIG_msg_t); // TODO: set to correct msg len - LOG_I(PHY,"Sending RRU_sync_ok to RAU\n"); - AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),"Failed to send msg to RAU %d\n",ru->idx); - //LOG_I(PHY,"~~~~~~~~~ RU_RUN\n"); - /*LOG_M("dmrs_time.m","dmrstime",calibration->drs_ch_estimates_time[0], (fp->ofdm_symbol_size),1,1); - LOG_M("rxdataF_ext.m","rxdataFext",&calibration->rxdataF_ext[0][36*fp->N_RB_DL], 12*(fp->N_RB_DL),1,1); - LOG_M("drs_seq0.m","drsseq0",ul_ref_sigs_rx[0][0][23],600,1,1); - LOG_M("rxdata.m","rxdata",&ru->common.rxdata[0][0], fp->samples_per_tti*2,1,1); - exit(-1);*/ - } - } - else if (ru->state == RU_RUN) { - // check for synchronization error - if (check_sync_pos >= 8 || check_sync_pos<=-8) { - LOG_E(PHY,"~~~~~~~~~~~~~~ check_sync_pos %d, frame %d ---> LOST SYNC-EXIT\n", check_sync_pos, proc->frame_rx); -LOG_M("rxdata.m","rxdata",&ru->common.rxdata[0][0], fp->samples_per_tti*2,1,1); -exit(-1); - } - } - - else { - AssertFatal(1==0,"Should not get here\n"); - } - } - - stop_meas(&ru->ofdm_demod_stats); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPRX+ru->idx, 0 ); -} - - - -void fep_full(RU_t *ru) { - - RU_proc_t *proc = &ru->proc; int l; LTE_DL_FRAME_PARMS *fp=&ru->frame_parms; @@ -791,43 +454,3 @@ void fep_full(RU_t *ru) { } - -void do_prach_ru(RU_t *ru) { - - RU_proc_t *proc = &ru->proc; - LTE_DL_FRAME_PARMS *fp=&ru->frame_parms; - - // check if we have to detect PRACH first - if (is_prach_subframe(fp,proc->frame_prach,proc->subframe_prach)>0) { - //accept some delay in processing - up to 5ms - int i; - for (i = 0; i < 10 && proc->instance_cnt_prach == 0; i++) { - LOG_W(PHY,"Frame %d Subframe %d, PRACH thread busy (IC %d)!!\n", proc->frame_prach,proc->subframe_prach, - proc->instance_cnt_prach); - usleep(500); - } - if (proc->instance_cnt_prach == 0) { - exit_fun( "PRACH thread busy" ); - return; - } - - // wake up thread for PRACH RX - if (pthread_mutex_lock(&proc->mutex_prach) != 0) { - LOG_E( PHY, "ERROR pthread_mutex_lock for PRACH thread (IC %d)\n", proc->instance_cnt_prach ); - exit_fun( "error locking mutex_prach" ); - return; - } - - ++proc->instance_cnt_prach; - - // the thread can now be woken up - if (pthread_cond_signal(&proc->cond_prach) != 0) { - LOG_E( PHY, "ERROR pthread_cond_signal for PRACH thread\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return; - } - - pthread_mutex_unlock( &proc->mutex_prach ); - } - -} diff --git a/openair1/SCHED/sched_common.h b/openair1/SCHED/sched_common.h index e9af869b05..f3e43d516e 100644 --- a/openair1/SCHED/sched_common.h +++ b/openair1/SCHED/sched_common.h @@ -311,7 +311,7 @@ void get_cqipmiri_params(PHY_VARS_UE *ue,uint8_t eNB_id); int8_t get_PHR(uint8_t Mod_id, uint8_t CC_id, uint8_t eNB_index); -void schedule_response(Sched_Rsp_t *Sched_INFO); +void schedule_response(Sched_Rsp_t *Sched_INFO, L1_rxtx_proc_t *proc); LTE_eNB_UE_stats* get_UE_stats(uint8_t Mod_id, uint8_t CC_id,uint16_t rnti); diff --git a/openair1/SCHED/sched_eNB.h b/openair1/SCHED/sched_eNB.h index 7fcabdc5dd..a38b594efe 100644 --- a/openair1/SCHED/sched_eNB.h +++ b/openair1/SCHED/sched_eNB.h @@ -128,7 +128,7 @@ void phy_procedures_eNB_S_RX(PHY_VARS_eNB *phy_vars_eNB,L1_rxtx_proc_t *proc); @param br_flag indicator for eMTC PRACH */ #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) -void prach_procedures(PHY_VARS_eNB *eNB, +void prach_procedures(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int br_flag); #else void prach_procedures(PHY_VARS_eNB *eNB); @@ -195,7 +195,7 @@ int8_t find_ue_ulsch(uint16_t rnti, PHY_VARS_eNB *phy_vars_eNB); -void schedule_response(Sched_Rsp_t *Sched_INFO); +void schedule_response(Sched_Rsp_t *Sched_INFO, L1_rxtx_proc_t *proc); LTE_eNB_UE_stats* get_UE_stats(uint8_t Mod_id, uint8_t CC_id,uint16_t rnti); diff --git a/openair1/SCHED_UE/phy_procedures_lte_ue.c b/openair1/SCHED_UE/phy_procedures_lte_ue.c index 84db43933a..438c7228f1 100644 --- a/openair1/SCHED_UE/phy_procedures_lte_ue.c +++ b/openair1/SCHED_UE/phy_procedures_lte_ue.c @@ -3399,7 +3399,7 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue, frame_rx%1024, subframe_rx,(ue->dlsch_decoding_stats[ue->current_thread_id[subframe_rx]].p_time)/(cpuf*1000.0)); } - LOG_D(PHY," ------ end turbo decoder for AbsSubframe %d.%d ------ \n", frame_rx, subframe_rx); + LOG_D(PHY," ------ end turbo decoder for AbsSubframe %d.%d ------ iter %d \n", frame_rx, subframe_rx,ret1); // Check CRC for CW 0 if (ret == (1+dlsch0->max_turbo_iterations)) { diff --git a/openair2/PHY_INTERFACE/IF_Module.c b/openair2/PHY_INTERFACE/IF_Module.c index 5b3b6d5da6..e12ddb897d 100644 --- a/openair2/PHY_INTERFACE/IF_Module.c +++ b/openair2/PHY_INTERFACE/IF_Module.c @@ -693,7 +693,7 @@ static void dump_dl(Sched_Rsp_t *d) { /* debug utility functions end */ /****************************************************************************/ -void UL_indication(UL_IND_t *UL_info) { +void UL_indication(UL_IND_t *UL_info, L1_rxtx_proc_t *proc) { AssertFatal(UL_info!=NULL,"UL_INFO is null\n"); #ifdef DUMP_FAPI dump_ul(UL_info); @@ -775,7 +775,7 @@ void UL_indication(UL_IND_t *UL_info) { "schedule_response is null (mod %d, cc %d)\n", module_id, CC_id); - ifi->schedule_response(sched_info); + ifi->schedule_response(sched_info, proc ); } LOG_D(PHY,"Schedule_response: SFN_SF:%d%d dl_pdus:%d\n",sched_info->frame,sched_info->subframe,sched_info->DL_req->dl_config_request_body.number_pdu); diff --git a/openair2/PHY_INTERFACE/IF_Module.h b/openair2/PHY_INTERFACE/IF_Module.h index c42ba992c9..0e8daf064f 100644 --- a/openair2/PHY_INTERFACE/IF_Module.h +++ b/openair2/PHY_INTERFACE/IF_Module.h @@ -34,6 +34,7 @@ #include +#include //#include "openair1/PHY/LTE_TRANSPORT/transport_eNB.h" #include "nfapi_interface.h" #include "platform_constants.h" @@ -138,11 +139,52 @@ typedef struct { int CC_id; nfapi_config_request_t *cfg; }PHY_Config_t; +#include +/// Context data structure for RX/TX portion of subframe processing +typedef struct { + /// Component Carrier index + uint8_t CC_id; + /// timestamp transmitted to HW + openair0_timestamp timestamp_tx; + openair0_timestamp timestamp_rx; + /// subframe to act upon for transmission + int subframe_tx; + /// subframe to act upon for reception + int subframe_rx; + /// frame to act upon for transmission + int frame_tx; + /// frame to act upon for reception + int frame_rx; + int frame_prach; + int subframe_prach; + int frame_prach_br; + int subframe_prach_br; + /// \brief Instance count for RXn-TXnp4 processing thread. + /// \internal This variable is protected by \ref mutex_rxtx. + int instance_cnt; + /// pthread structure for RXn-TXnp4 processing thread + pthread_t pthread; + /// pthread attributes for RXn-TXnp4 processing thread + pthread_attr_t attr; + /// condition variable for tx processing thread + pthread_cond_t cond; + /// mutex for RXn-TXnp4 processing thread + pthread_mutex_t mutex; + /// scheduling parameters for RXn-TXnp4 thread + struct sched_param sched_param_rxtx; + + /// \internal This variable is protected by \ref mutex_RUs. + int instance_cnt_RUs; + /// condition variable for tx processing thread + pthread_cond_t cond_RUs; + /// mutex for RXn-TXnp4 processing thread + pthread_mutex_t mutex_RUs; +} L1_rxtx_proc_t; typedef struct IF_Module_s{ //define the function pointer - void (*UL_indication)(UL_IND_t *UL_INFO); - void (*schedule_response)(Sched_Rsp_t *Sched_INFO); + void (*UL_indication)(UL_IND_t *UL_INFO, L1_rxtx_proc_t *proc); + void (*schedule_response)(Sched_Rsp_t *Sched_INFO, L1_rxtx_proc_t *proc); void (*PHY_config_req)(PHY_Config_t* config_INFO); uint32_t CC_mask; uint16_t current_frame; @@ -167,7 +209,7 @@ void IF_Module_kill(int Mod_id); /*Interface for uplink, transmitting the Preamble(list), ULSCH SDU, NAK, Tick (trigger scheduler) */ -void UL_indication(UL_IND_t *UL_INFO); +void UL_indication(UL_IND_t *UL_INFO, L1_rxtx_proc_t *proc); /*Interface for Downlink, transmitting the DLSCH SDU, DCI SDU*/ void Schedule_Response(Sched_Rsp_t *Sched_INFO); From b760012adf3eaa2c7e9a8e56d6530ed2e73f7730 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Fri, 18 Oct 2019 16:48:40 +0200 Subject: [PATCH 052/240] CI: fix in looping attach / ping / detach Signed-off-by: Raphael Defosseux --- ci-scripts/main.py | 24 ++++-- ...b_ue_usrp210_band7_test_05mhz_tm1_nos1.xml | 2 +- .../enb_usrp210_band7_test_05mhz_tm1.xml | 84 ++++++++++--------- 3 files changed, 60 insertions(+), 50 deletions(-) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index bb00d806dd..0909b42747 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -879,20 +879,26 @@ class SSHConnection(): self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) if not self.ADBCentralized: # Reboot UE - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesRebootCmd[idx], '\$', 60) + #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesRebootCmd[idx], '\$', 60) # Wait - time.sleep(60) + #time.sleep(60) # Put in LTE-Mode only - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode 11"\'', '\$', 60) - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode1 11"\'', '\$', 60) - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode2 11"\'', '\$', 60) - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode3 11"\'', '\$', 60) + #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode 11"\'', '\$', 60) + #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode1 11"\'', '\$', 60) + #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode2 11"\'', '\$', 60) + #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode3 11"\'', '\$', 60) # enable data service - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) + #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) # we need to do radio on/off cycle to make sure of above changes # airplane mode off // radio on - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) - time.sleep(10) + #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) + #time.sleep(10) + # airplane mode on // radio off + #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + + # normal procedure without reboot + # enable data service + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) # airplane mode on // radio off self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) self.close() diff --git a/ci-scripts/xml_files/inria/enb_ue_usrp210_band7_test_05mhz_tm1_nos1.xml b/ci-scripts/xml_files/inria/enb_ue_usrp210_band7_test_05mhz_tm1_nos1.xml index dff0761bd3..c2835d0461 100644 --- a/ci-scripts/xml_files/inria/enb_ue_usrp210_band7_test_05mhz_tm1_nos1.xml +++ b/ci-scripts/xml_files/inria/enb_ue_usrp210_band7_test_05mhz_tm1_nos1.xml @@ -24,7 +24,7 @@ test-05-tm1-nos1-tunnel Test-05MHz-TM1-noS1-tunnel tasks - 2 + 4 030201 090109 030101 000001 090101 000002 040501 040502 000001 040601 040602 040641 040642 000001 090109 030201 diff --git a/ci-scripts/xml_files/inria/enb_usrp210_band7_test_05mhz_tm1.xml b/ci-scripts/xml_files/inria/enb_usrp210_band7_test_05mhz_tm1.xml index f5e095ba8a..6bc52568c3 100644 --- a/ci-scripts/xml_files/inria/enb_usrp210_band7_test_05mhz_tm1.xml +++ b/ci-scripts/xml_files/inria/enb_usrp210_band7_test_05mhz_tm1.xml @@ -19,7 +19,6 @@ For more information about the OpenAirInterface (OAI) Software Alliance: contact@openairinterface.org - 030103 000002 040301 000002 040504 040605 040606 040645 040646 000001 040401 000002 030201 --> test-05-tm1 @@ -28,44 +27,44 @@ 4 030201 040101 - 030103 000002 040301 - 000002 040504 000001 - 000002 040505 000001 - 000002 040506 000001 - 000002 040507 000001 - 000002 040508 000001 - 000002 040509 000001 - 000002 040510 000001 - 000002 040511 000001 - 000002 040512 000001 - 000002 040513 000001 - 000002 040514 000001 - 000002 040515 000001 - 000002 040516 000001 - 000002 040517 000001 - 000002 040518 000001 - 000002 040519 000001 - 000002 040520 000001 - 000002 040521 000001 - 000002 040522 000001 - 000002 040523 000001 - 000002 040524 000001 - 000002 040525 000001 - 000002 040526 000001 - 000002 040527 000001 - 000002 040528 000001 - 000002 040529 000001 - 000002 040530 000001 - 000002 040531 000001 - 000002 040532 000001 - 000002 040533 000001 - 000002 040534 000001 - 000002 040535 000001 - 000002 040536 000001 - 000002 040537 000001 - 000002 040538 000001 - 000002 040539 000001 - 040401 000002 030201 + 030103 000002 + 040301 000002 040504 000001 040401 + 040301 000002 040505 000001 040401 + 040301 000002 040506 000001 040401 + 040301 000002 040507 000001 040401 + 040301 000002 040508 000001 040401 + 040301 000002 040509 000001 040401 + 040301 000002 040510 000001 040401 + 040301 000002 040511 000001 040401 + 040301 000002 040512 000001 040401 + 040301 000002 040513 000001 040401 + 040301 000002 040514 000001 040401 + 040301 000002 040515 000001 040401 + 040301 000002 040516 000001 040401 + 040301 000002 040517 000001 040401 + 040301 000002 040518 000001 040401 + 040301 000002 040519 000001 040401 + 040301 000002 040520 000001 040401 + 040301 000002 040521 000001 040401 + 040301 000002 040522 000001 040401 + 040301 000002 040523 000001 040401 + 040301 000002 040524 000001 040401 + 040301 000002 040525 000001 040401 + 040301 000002 040526 000001 040401 + 040301 000002 040527 000001 040401 + 040301 000002 040528 000001 040401 + 040301 000002 040529 000001 040401 + 040301 000002 040530 000001 040401 + 040301 000002 040531 000001 040401 + 040301 000002 040532 000001 040401 + 040301 000002 040533 000001 040401 + 040301 000002 040534 000001 040401 + 040301 000002 040535 000001 040401 + 040301 000002 040536 000001 040401 + 040301 000002 040537 000001 040401 + 040301 000002 040538 000001 040401 + 040301 000002 040539 000001 040401 + 040201 000002 030201 @@ -74,6 +73,11 @@ Initialize UE + + Terminate_UE + Terminate UE + + IdleSleep Sleep for 10 sec @@ -86,7 +90,7 @@ 3 - + Initialize_eNB Initialize eNB (FDD/Band7/5MHz) -O ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf --eNBs.[0].rrc_inactivity_threshold 0 --RUs.[0].max_rxgain 120 --eNBs.[0].component_carriers.[0].pusch_p0_Nominal -90 --eNBs.[0].component_carriers.[0].pucch_p0_Nominal -96 --eNBs.[0].tracking_area_code 600 --eNBs.[0].plmn_list.[0].mnc 95 --THREAD_STRUCT.[0].parallel_config PARALLEL_RU_L1_TRX_SPLIT From 4c646e8d57453bfc830371bdccf95d4d7907772a Mon Sep 17 00:00:00 2001 From: Laurent Date: Fri, 18 Oct 2019 18:04:00 +0200 Subject: [PATCH 053/240] try parallel du --- executables/main-fs6.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index b7f4c62293..c96e20e352 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -1385,7 +1385,7 @@ void phy_procedures_eNB_TX_tosplit(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx void DL_du_fs6(RU_t *ru) { static uint64_t lastTS; - L1_rxtx_proc_t L1_proc; + L1_rxtx_proc_t L1_proc={0}; for (int i=0; inum_eNB; i++) { initBufferZone(bufferZone); @@ -1533,7 +1533,7 @@ void *cu_fs6(void *arg) { initRefTimes(waitDUAndProcessingUL); initRefTimes(makeSendDL); initRefTimes(fullLoop); - L1_rxtx_proc_t L1proc; + L1_rxtx_proc_t L1proc={0}; while(1) { timeStamp+=ru->frame_parms.samples_per_tti; @@ -1549,7 +1549,16 @@ void *cu_fs6(void *arg) { return NULL; } -void *DlDu(void *arg) { +void *dutxfs6(void *arg) { + RU_t *ru = (RU_t *)arg; + initStaticTime(begingWait2); + initRefTimes(makeSendDL); + usleep(100); + while(1) { + pickStaticTime(begingWait2); + DL_du_fs6(ru); + updateTimesReset(begingWait2, &makeSendDL, 1000, true, "DU Time in build and send Tx"); + } return NULL; } @@ -1577,12 +1586,10 @@ void *du_fs6(void *arg) { LOG_E(HW,"Could not start the RF device\n"); else LOG_I(PHY,"RU %d rf device ready\n",ru->idx); } else LOG_I(PHY,"RU %d no rf device\n",ru->idx); - - //threadCreate(&t, dutxfs6, (void *)ru, "DlDu", -1, OAI_PRIORITY_RT_MAX); + pthread_t t; + threadCreate(&t, dutxfs6, (void *)ru, "DlDu", -1, OAI_PRIORITY_RT_MAX); initStaticTime(begingWait); - initStaticTime(begingWait2); initRefTimes(waitRxAndProcessingUL); - initRefTimes(makeSendDL); initRefTimes(fullLoop); L1_rxtx_proc_t L1proc; @@ -1592,9 +1599,7 @@ void *du_fs6(void *arg) { pickStaticTime(begingWait); UL_du_fs6(ru, proc, proc->frame_rx,proc->subframe_rx); updateTimesReset(begingWait, &waitRxAndProcessingUL, 1000, true,"DU Time in wait Rx + Ul processing"); - pickStaticTime(begingWait2); - DL_du_fs6(ru); - updateTimesReset(begingWait2, &makeSendDL, 1000, true, "DU Time in build and send Tx"); + } return NULL; From 283fed9c4ccab0fc62611547fc06eea5a7898517 Mon Sep 17 00:00:00 2001 From: laurent Date: Mon, 21 Oct 2019 14:59:16 +0200 Subject: [PATCH 054/240] du RX/Tx in parallel, controled by the thread pool --- cmake_targets/CMakeLists.txt | 1 + executables/main-fs6.c | 36 +++++++++++++++++------------------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 0615f91ae7..c1d4069915 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -2105,6 +2105,7 @@ target_link_libraries (lte-softmodem add_executable(ocp-softmodem ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c ${OPENAIR_DIR}/executables/main-ocp.c + ${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c ${OPENAIR_DIR}/executables/main-fs6.c ${OPENAIR_DIR}/executables/transport_split.c ${OPENAIR_TARGETS}/RT/USER/lte-softmodem.c diff --git a/executables/main-fs6.c b/executables/main-fs6.c index c96e20e352..ab3ba61734 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #define FS6_BUF_SIZE 1000*1000 @@ -1383,9 +1384,10 @@ void phy_procedures_eNB_TX_tosplit(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx return; } -void DL_du_fs6(RU_t *ru) { +void DL_du_fs6(void *arg) { + RU_t *ru = *(RU_t **)arg; static uint64_t lastTS; - L1_rxtx_proc_t L1_proc={0}; + L1_rxtx_proc_t L1_proc= {0}; for (int i=0; inum_eNB; i++) { initBufferZone(bufferZone); @@ -1474,6 +1476,7 @@ void DL_cu_fs6(RU_t *ru, L1_rxtx_proc_t *proc) { } sendSubFrame(&sockFS6, bufferZone, sizeof(fs6_dl_t), CTsentCUv0 ); + return; } void UL_cu_fs6(RU_t *ru, L1_rxtx_proc_t *proc, uint64_t *TS) { @@ -1533,7 +1536,7 @@ void *cu_fs6(void *arg) { initRefTimes(waitDUAndProcessingUL); initRefTimes(makeSendDL); initRefTimes(fullLoop); - L1_rxtx_proc_t L1proc={0}; + L1_rxtx_proc_t L1proc= {0}; while(1) { timeStamp+=ru->frame_parms.samples_per_tti; @@ -1549,19 +1552,6 @@ void *cu_fs6(void *arg) { return NULL; } -void *dutxfs6(void *arg) { - RU_t *ru = (RU_t *)arg; - initStaticTime(begingWait2); - initRefTimes(makeSendDL); - usleep(100); - while(1) { - pickStaticTime(begingWait2); - DL_du_fs6(ru); - updateTimesReset(begingWait2, &makeSendDL, 1000, true, "DU Time in build and send Tx"); - } - return NULL; -} - void *du_fs6(void *arg) { setbuf(stdout, NULL); setbuf(stderr, NULL); @@ -1580,26 +1570,34 @@ void *du_fs6(void *arg) { remoteIP=CU_IP; AssertFatal(createUDPsock(NULL, DU_PORT, remoteIP, CU_PORT, &sockFS6), ""); + tpool_t pool; + tpool_t *Tpool = &pool; + char params[]="-1,-1"; + initTpool(params, Tpool, false); if (ru->start_rf) { if (ru->start_rf(ru) != 0) LOG_E(HW,"Could not start the RF device\n"); else LOG_I(PHY,"RU %d rf device ready\n",ru->idx); } else LOG_I(PHY,"RU %d no rf device\n",ru->idx); - pthread_t t; - threadCreate(&t, dutxfs6, (void *)ru, "DlDu", -1, OAI_PRIORITY_RT_MAX); + initStaticTime(begingWait); initRefTimes(waitRxAndProcessingUL); initRefTimes(fullLoop); L1_rxtx_proc_t L1proc; + notifiedFIFO_t nf; + initNotifiedFIFO(&nf); while(1) { L1_rxtx_proc_t *proc = &L1proc; updateTimesReset(begingWait, &fullLoop, 1000, true,"DU for full SubFrame (must be less 1ms)"); pickStaticTime(begingWait); + notifiedFIFO_elt_t *Msg=newNotifiedFIFO_elt(sizeof(ru),0,&nf, DL_du_fs6); + *(RU_t **)NotifiedFifoData(Msg)=ru; + pushTpool(Tpool, Msg); UL_du_fs6(ru, proc, proc->frame_rx,proc->subframe_rx); + notifiedFIFO_elt_t *res=pullTpool(&nf, Tpool); updateTimesReset(begingWait, &waitRxAndProcessingUL, 1000, true,"DU Time in wait Rx + Ul processing"); - } return NULL; From 63c023029acc630288b4a50ffea46c623eb30b33 Mon Sep 17 00:00:00 2001 From: laurent Date: Sat, 26 Oct 2019 11:28:46 +0200 Subject: [PATCH 055/240] du in 2 threads, and fix UL in FS6 split --- common/utils/ocp_itti/intertask_interface.h | 2 +- executables/main-fs6.c | 77 ++++++++++----------- executables/main-ocp.c | 62 ++++++++++------- executables/split_headers.h | 6 +- openair2/RRC/LTE/rrc_eNB.c | 7 +- targets/COMMON/create_tasks.c | 2 +- 6 files changed, 84 insertions(+), 72 deletions(-) diff --git a/common/utils/ocp_itti/intertask_interface.h b/common/utils/ocp_itti/intertask_interface.h index 956d90072d..2290fbdbc4 100644 --- a/common/utils/ocp_itti/intertask_interface.h +++ b/common/utils/ocp_itti/intertask_interface.h @@ -285,7 +285,7 @@ typedef struct { TASK_DEF(TASK_PDCP_ENB, TASK_PRIORITY_MED, 200, NULL, NULL) \ TASK_DEF(TASK_DATA_FORWARDING, TASK_PRIORITY_MED, 200, NULL, NULL) \ TASK_DEF(TASK_END_MARKER, TASK_PRIORITY_MED, 200, NULL, NULL) \ - TASK_DEF(TASK_RRC_ENB, TASK_PRIORITY_MED, 200, NULL,NULL)\ + TASK_DEF(TASK_RRC_ENB, TASK_PRIORITY_MED, 200, rrc_enb_process_itti_msg,NULL)\ TASK_DEF(TASK_RAL_ENB, TASK_PRIORITY_MED, 200, NULL, NULL) \ TASK_DEF(TASK_S1AP, TASK_PRIORITY_MED, 200, NULL, NULL) \ TASK_DEF(TASK_X2AP, TASK_PRIORITY_MED, 200, NULL, NULL) \ diff --git a/executables/main-fs6.c b/executables/main-fs6.c index ab3ba61734..1416572d76 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -1384,39 +1384,43 @@ void phy_procedures_eNB_TX_tosplit(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx return; } -void DL_du_fs6(void *arg) { - RU_t *ru = *(RU_t **)arg; +void *DL_du_fs6(void *arg) { + RU_t *ru=(RU_t *)arg; static uint64_t lastTS; L1_rxtx_proc_t L1_proc= {0}; - for (int i=0; inum_eNB; i++) { - initBufferZone(bufferZone); - initStaticTime(begingWait); - initRefTimes(fullLoop); - pickStaticTime(begingWait); - int nb_blocks=receiveSubFrame(&sockFS6, bufferZone, sizeof(bufferZone), CTsentCUv0 ); - updateTimesReset(begingWait, &fullLoop, 1000, false, "DU wait CU"); + while (1) { + for (int i=0; inum_eNB; i++) { + initBufferZone(bufferZone); + initStaticTime(begingWait); + initRefTimes(fullLoop); + pickStaticTime(begingWait); + int nb_blocks=receiveSubFrame(&sockFS6, bufferZone, sizeof(bufferZone), CTsentCUv0 ); + updateTimesReset(begingWait, &fullLoop, 1000, false, "DU wait CU"); - if (nb_blocks > 0) { - if ( lastTS+ru->eNB_list[i]->frame_parms.samples_per_tti != hUDP(bufferZone)->timestamp) { - LOG_E(HW,"Missed a subframe: expecting: %lu, received %lu\n", - lastTS+ru->eNB_list[i]->frame_parms.samples_per_tti, - hUDP(bufferZone)->timestamp); - } + if (nb_blocks > 0) { + if ( lastTS+ru->eNB_list[i]->frame_parms.samples_per_tti != hUDP(bufferZone)->timestamp) { + LOG_E(HW,"Missed a subframe: expecting: %lu, received %lu\n", + lastTS+ru->eNB_list[i]->frame_parms.samples_per_tti, + hUDP(bufferZone)->timestamp); + } - lastTS=hUDP(bufferZone)->timestamp; - setAllfromTS(hUDP(bufferZone)->timestamp - sf_ahead*ru->eNB_list[i]->frame_parms.samples_per_tti, &L1_proc); - phy_procedures_eNB_TX_fromsplit( bufferZone, nb_blocks, ru->eNB_list[i], &L1_proc, 1); - } else - LOG_E(PHY,"DL not received for subframe\n"); + lastTS=hUDP(bufferZone)->timestamp; + setAllfromTS(hUDP(bufferZone)->timestamp - sf_ahead*ru->eNB_list[i]->frame_parms.samples_per_tti, &L1_proc); + phy_procedures_eNB_TX_fromsplit( bufferZone, nb_blocks, ru->eNB_list[i], &L1_proc, 1); + } else + LOG_E(PHY,"DL not received for subframe\n"); + } + + feptx_prec(ru, &L1_proc); + feptx_ofdm(ru, &L1_proc); + tx_rf(ru, &L1_proc); } - feptx_prec(ru, &L1_proc); - feptx_ofdm(ru, &L1_proc); - tx_rf(ru, &L1_proc); + return NULL; } -void UL_du_fs6(RU_t *ru, L1_rxtx_proc_t *proc, int frame, int subframe) { +void UL_du_fs6(RU_t *ru, L1_rxtx_proc_t *proc) { initStaticTime(begingWait); initRefTimes(fullLoop); pickStaticTime(begingWait); @@ -1560,7 +1564,7 @@ void *du_fs6(void *arg) { fill_rf_config(ru,ru->rf_config_file); init_frame_parms(&ru->frame_parms,1); phy_init_RU(ru); - openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); + init_rf(ru); wait_sync("ru_thread"); char *remoteIP; @@ -1570,33 +1574,26 @@ void *du_fs6(void *arg) { remoteIP=CU_IP; AssertFatal(createUDPsock(NULL, DU_PORT, remoteIP, CU_PORT, &sockFS6), ""); - tpool_t pool; - tpool_t *Tpool = &pool; - char params[]="-1,-1"; - initTpool(params, Tpool, false); if (ru->start_rf) { if (ru->start_rf(ru) != 0) LOG_E(HW,"Could not start the RF device\n"); - else LOG_I(PHY,"RU %d rf device ready\n",ru->idx); - } else LOG_I(PHY,"RU %d no rf device\n",ru->idx); + else + LOG_I(PHY,"RU %d rf device ready\n",ru->idx); + } else + LOG_I(PHY,"RU %d no rf device\n",ru->idx); initStaticTime(begingWait); initRefTimes(waitRxAndProcessingUL); initRefTimes(fullLoop); - L1_rxtx_proc_t L1proc; - notifiedFIFO_t nf; - initNotifiedFIFO(&nf); + pthread_t t; + threadCreate(&t, DL_du_fs6, (void *)ru, "MainDuTx", -1, OAI_PRIORITY_RT_MAX); while(1) { - L1_rxtx_proc_t *proc = &L1proc; + L1_rxtx_proc_t L1proc; updateTimesReset(begingWait, &fullLoop, 1000, true,"DU for full SubFrame (must be less 1ms)"); pickStaticTime(begingWait); - notifiedFIFO_elt_t *Msg=newNotifiedFIFO_elt(sizeof(ru),0,&nf, DL_du_fs6); - *(RU_t **)NotifiedFifoData(Msg)=ru; - pushTpool(Tpool, Msg); - UL_du_fs6(ru, proc, proc->frame_rx,proc->subframe_rx); - notifiedFIFO_elt_t *res=pullTpool(&nf, Tpool); + UL_du_fs6(ru, &L1proc); updateTimesReset(begingWait, &waitRxAndProcessingUL, 1000, true,"DU Time in wait Rx + Ul processing"); } diff --git a/executables/main-ocp.c b/executables/main-ocp.c index 9a4743a295..5ae15c8a29 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -11,10 +11,11 @@ * The merger of OpenAir central code to this branch * should check if these 3 files are modified and analyze if code code has to be copied in here */ +#define _GNU_SOURCE +#include #include #include - static int DEFBANDS[] = {7}; static int DEFENBS[] = {0}; #include @@ -44,7 +45,6 @@ void reset_opp_meas(void) { // Fixme: there are many mistakes in the datamodel and in redondant variables // TDD is also mode complex void setAllfromTS(uint64_t TS, L1_rxtx_proc_t *proc) { - for (int i=0; i < RC.nb_inst; i++) { for (int j=0; jframe_parms; @@ -96,7 +96,6 @@ void init_eNB_proc(int inst) { } void init_RU_proc(RU_t *ru) { - pthread_t t; char *fs6=getenv("fs6"); @@ -104,7 +103,7 @@ void init_RU_proc(RU_t *ru) { if ( strncasecmp(fs6,"cu", 2) == 0 ) threadCreate(&t, cu_fs6, (void *)ru, "MainCu", -1, OAI_PRIORITY_RT_MAX); else if ( strncasecmp(fs6,"du", 2) == 0 ) { - threadCreate(&t, du_fs6, (void *)ru, "MainDu", -1, OAI_PRIORITY_RT_MAX); + threadCreate(&t, du_fs6, (void *)ru, "MainDuRx", -1, OAI_PRIORITY_RT_MAX); } else AssertFatal(false, "environement variable fs6 is not cu or du"); } else @@ -415,7 +414,7 @@ void init_precoding_weights(PHY_VARS_eNB *eNB) { } } -void prach_procedures_ocp(PHY_VARS_eNB *eNB, L1_rxtx_proc_t * proc, int br_flag) { +void prach_procedures_ocp(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int br_flag) { uint16_t max_preamble[4],max_preamble_energy[4],max_preamble_delay[4],avg_preamble_energy[4]; RU_t *ru; int aa=0; @@ -436,7 +435,7 @@ void prach_procedures_ocp(PHY_VARS_eNB *eNB, L1_rxtx_proc_t * proc, int br_flag) // run PRACH detection for CE-level 0 only for now when br_flag is set rx_prach(eNB, - proc, + proc, eNB->RU_list[0], &max_preamble[0], &max_preamble_energy[0], @@ -536,7 +535,7 @@ void prach_procedures_ocp(PHY_VARS_eNB *eNB, L1_rxtx_proc_t * proc, int br_flag) } } // else br_flag -void prach_eNB(PHY_VARS_eNB *eNB, L1_rxtx_proc_t * proc, int frame,int subframe) { +void prach_eNB(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int frame,int subframe) { // check if we have to detect PRACH first if (is_prach_subframe(&eNB->frame_parms, frame,subframe)>0) { prach_procedures_ocp(eNB, proc, 0); @@ -576,7 +575,6 @@ static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name } void eNB_top(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int dummy1, int dummy2, char *string,RU_t *ru) { - if (!oai_exit) { if (rxtx(eNB,proc,string) < 0) LOG_E(PHY,"eNB %d CC_id %d failed during execution\n",eNB->Mod_id,eNB->CC_id); @@ -590,7 +588,7 @@ void rx_rf(RU_t *ru, L1_rxtx_proc_t *proc) { int i; openair0_timestamp ts=0, timestamp_rx; static openair0_timestamp old_ts=0; - + for (i=0; inb_rx; i++) //receive in the next slot rxp[i] = (void *)&ru->common.rxdata[i][((proc->subframe_rx+1)%10)*fp->samples_per_tti]; @@ -615,15 +613,17 @@ void rx_rf(RU_t *ru, L1_rxtx_proc_t *proc) { } if (timestamp_rx - old_ts != fp->samples_per_tti) { - LOG_E(HW,"impossible shift in rx stream, rx: %ld, previous rx distance: %ld, should be %d\n", timestamp_rx, proc->timestamp_rx - old_ts, fp->samples_per_tti); - //ru->ts_offset += (proc->timestamp_rx - old_ts - fp->samples_per_tti); - //proc->timestamp_rx = ts-ru->ts_offset; + LOG_E(HW,"impossible shift in rx stream, rx: %ld, previous rx distance: %ld, should be %d\n", timestamp_rx, proc->timestamp_rx - old_ts, fp->samples_per_tti); + //ru->ts_offset += (proc->timestamp_rx - old_ts - fp->samples_per_tti); + //proc->timestamp_rx = ts-ru->ts_offset; } + old_ts=timestamp_rx; setAllfromTS(timestamp_rx, proc); } -void tx_rf(RU_t *ru, L1_rxtx_proc_t *proc) { +int tx_rf(RU_t *ru, L1_rxtx_proc_t *proc) { + int ret=0; LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; void *txp[ru->nb_tx]; int i; @@ -671,29 +671,31 @@ void tx_rf(RU_t *ru, L1_rxtx_proc_t *proc) { /* add fail safe for late command end */ // prepare tx buffer pointers - ru->rfdevice.trx_write_func(&ru->rfdevice, - proc->timestamp_tx+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension, - txp, - siglen+sf_extension, - ru->nb_tx, - flags); + ret=ru->rfdevice.trx_write_func(&ru->rfdevice, + proc->timestamp_tx+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension, + txp, + siglen+sf_extension, + ru->nb_tx, + flags); LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, subframe %d\n",ru->idx, (long long unsigned int)proc->timestamp_tx,proc->frame_tx,proc->subframe_tx); } + + return ret; } static void *ru_thread( void *param ) { - setbuf(stdout, NULL); - setbuf(stderr, NULL); + setbuf(stdout, NULL); + setbuf(stderr, NULL); RU_t *ru = (RU_t *)param; L1_rxtx_proc_t L1proc; - L1_rxtx_proc_t * proc=&L1proc; + L1_rxtx_proc_t *proc=&L1proc; if (ru->if_south == LOCAL_RF) { // configure RF parameters only fill_rf_config(ru,ru->rf_config_file); init_frame_parms(&ru->frame_parms,1); phy_init_RU(ru); - openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); + init_rf(ru); } AssertFatal(setup_RU_buffers(ru)==0, "Exiting, cannot initialize RU Buffers\n"); @@ -714,7 +716,7 @@ static void *ru_thread( void *param ) { // do RX front-end processing (frequency-shift, dft) if needed if (ru->feprx) - ru->feprx(ru, proc); + ru->feprx(ru, proc); // At this point, all information for subframe has been received on FH interface // If this proc is to provide synchronization, do so @@ -750,8 +752,18 @@ static void *ru_thread( void *param ) { return NULL; } +int init_rf(RU_t *ru) { + char name[256]; + pthread_getname_np(pthread_self(),name, 255); + pthread_setname_np(pthread_self(),"UHD for OAI"); + int ret=openair0_device_load(&ru->rfdevice,&ru->openair0_cfg); + pthread_setname_np(pthread_self(),name); + return ret; +} + int start_rf(RU_t *ru) { - return(ru->rfdevice.trx_start_func(&ru->rfdevice)); + int ret=ru->rfdevice.trx_start_func(&ru->rfdevice); + return ret; } int stop_rf(RU_t *ru) { diff --git a/executables/split_headers.h b/executables/split_headers.h index 1f9443c00c..1849efffc7 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -11,7 +11,8 @@ #define DU_PORT "8787" #define MTU 65536 -#define UDP_TIMEOUT 1000L // in micro second (struct timeval, NOT struct timespec) +#define UDP_TIMEOUT 900000L // in micro second (struct timeval, NOT struct timespec) +// linux may timeout for a much longer time (up to 10ms) #define MAX_BLOCKS 16 #define blockAlign 32 //bytes @@ -236,8 +237,9 @@ void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_ void *cu_fs6(void *arg); void *du_fs6(void *arg); void fill_rf_config(RU_t *ru, char *rf_config_file); +int init_rf(RU_t *ru); void rx_rf(RU_t *ru, L1_rxtx_proc_t *proc); -void tx_rf(RU_t *ru, L1_rxtx_proc_t *proc); +int tx_rf(RU_t *ru, L1_rxtx_proc_t *proc); void common_signal_procedures (PHY_VARS_eNB *eNB,int frame, int subframe); void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc); bool dlsch_procedures(PHY_VARS_eNB *eNB, diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index d93510ac5d..8aefbf87aa 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -9124,9 +9124,10 @@ rrc_enb_task( itti_mark_task_ready(TASK_RRC_ENB); LOG_I(RRC,"Entering main loop of RRC message task\n"); - while (1) { - (void) rrc_enb_process_itti_msg(NULL); - } + //while (1) { + //(void) rrc_enb_process_itti_msg(NULL); + //} + return NULL; } /*------------------------------------------------------------------------------*/ diff --git a/targets/COMMON/create_tasks.c b/targets/COMMON/create_tasks.c index 58be63a848..80721a1c28 100644 --- a/targets/COMMON/create_tasks.c +++ b/targets/COMMON/create_tasks.c @@ -61,7 +61,7 @@ int create_tasks(uint32_t enb_nb) { rc = itti_create_task (TASK_RRC_ENB, rrc_enb_task, NULL); AssertFatal(rc >= 0, "Create task for RRC eNB failed\n"); - if (EPC_MODE_ENABLED) { + if (EPC_MODE_ENABLED && !fs6Du ) { rc = itti_create_task(TASK_SCTP, sctp_eNB_task, NULL); AssertFatal(rc >= 0, "Create task for SCTP failed\n"); } From f0759d6e615e30c4f58be3dbdc4aedc543e994a7 Mon Sep 17 00:00:00 2001 From: laurent Date: Wed, 30 Oct 2019 11:10:41 +0100 Subject: [PATCH 056/240] dl in threadpool ok --- executables/main-ocp.c | 8 + openair1/PHY/LTE_TRANSPORT/dci_tools.c | 42 +- openair1/PHY/LTE_TRANSPORT/dlsch_coding.c | 427 +++++++----------- openair1/PHY/LTE_TRANSPORT/pmch.c | 1 + openair1/PHY/LTE_TRANSPORT/transport_eNB.h | 8 +- openair1/PHY/LTE_TRANSPORT/transport_proto.h | 2 + openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c | 60 +++ .../PHY/LTE_TRANSPORT/ulsch_demodulation.c | 2 - openair1/PHY/defs_eNB.h | 48 ++ openair1/SCHED/fapi_l1.c | 16 +- openair1/SCHED/phy_procedures_lte_eNb.c | 155 ++++++- openair2/PHY_INTERFACE/IF_Module.h | 6 + targets/RT/USER/lte-softmodem.h | 3 + 13 files changed, 462 insertions(+), 316 deletions(-) diff --git a/executables/main-ocp.c b/executables/main-ocp.c index 5ae15c8a29..34cd950ce7 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -29,6 +29,7 @@ static int DEFENBS[] = {0}; #include #include #include +#include extern uint16_t sf_ahead; @@ -691,6 +692,13 @@ static void *ru_thread( void *param ) { L1_rxtx_proc_t L1proc; L1_rxtx_proc_t *proc=&L1proc; + if ( strlen(get_softmodem_params()->threadPoolConfig) > 0 ) { + initTpool(get_softmodem_params()->threadPoolConfig, &L1proc.threadPool, true); + initNotifiedFIFO(&L1proc.respEncode); + initNotifiedFIFO(&L1proc.respDecode); + } else + initTpool("n", &L1proc.threadPool, true); + if (ru->if_south == LOCAL_RF) { // configure RF parameters only fill_rf_config(ru,ru->rf_config_file); init_frame_parms(&ru->frame_parms,1); diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c index a8032b3368..fafc009e51 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c @@ -314,17 +314,17 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t proc->frame_tx,proc->subframe_tx, dlsch0->rnti,dlsch0->harq_mask, rel8->rnti, rel8->rnti_type, rel8->harq_process, rel8->new_data_indicator_1, - dlsch0_harq->round, dlsch0->harq_mask, dlsch0_harq->ndi); + dlsch0_harq->DLround, dlsch0->harq_mask, dlsch0_harq->ndi); if (dlsch0->rnti != rel8->rnti) { // if rnti of dlsch is not the same as in the config, this is a new entry - dlsch0_harq->round=0; + dlsch0_harq->DLround=0; dlsch0->harq_mask=0; } if ((dlsch0->harq_mask & (1 << rel8->harq_process)) > 0) { if (rel8->new_data_indicator_1 != dlsch0_harq->ndi) - dlsch0_harq->round = 0; + dlsch0_harq->DLround = 0; } else { // process is inactive, so activate and set round to 0 - dlsch0_harq->round = 0; + dlsch0_harq->DLround = 0; } dlsch0_harq->ndi = rel8->new_data_indicator_1; @@ -335,12 +335,12 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t dlsch0->active = 1; #endif if (rel8->rnti_type == 2) - dlsch0_harq->round = 0; + dlsch0_harq->DLround = 0; LOG_D(PHY,"NFAPI: rel8[rnti %x dci_format %d harq_process %d ndi1 %d rnti type %d] dlsch0[rnti %x harq_mask %x] dlsch0_harq[round %d ndi %d]\n", rel8->rnti,rel8->dci_format,rel8->harq_process, rel8->new_data_indicator_1, rel8->rnti_type, dlsch0->rnti,dlsch0->harq_mask, - dlsch0_harq->round,dlsch0_harq->ndi + dlsch0_harq->DLround,dlsch0_harq->ndi ); switch (rel8->dci_format) { @@ -503,7 +503,7 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t NPRB = dlsch0_harq->nb_rb; I_mcs = get_I_TBS(rel8->mcs_1); } - AssertFatal(NPRB>0,"DCI 1A: NPRB = 0 (rnti %x, rnti type %d, tpc %d, round %d, resource_block_coding %d, harq process %d)\n",rel8->rnti,rel8->rnti_type,rel8->tpc,dlsch0_harq->round,rel8->resource_block_coding,rel8->harq_process); + AssertFatal(NPRB>0,"DCI 1A: NPRB = 0 (rnti %x, rnti type %d, tpc %d, round %d, resource_block_coding %d, harq process %d)\n",rel8->rnti,rel8->rnti_type,rel8->tpc,dlsch0_harq->DLround,rel8->resource_block_coding,rel8->harq_process); dlsch0_harq->rvidx = rel8->redundancy_version_1; dlsch0_harq->Nl = 1; dlsch0_harq->mimo_mode = (fp->nb_antenna_ports_eNB == 1) ? SISO : ALAMOUTI; @@ -523,12 +523,12 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t dlsch0->rnti = rel8->rnti; //dlsch0->harq_ids[subframe] = rel8->harq_process; - if (dlsch0_harq->round == 0) + if (dlsch0_harq->DLround == 0) dlsch0_harq->status = ACTIVE; dlsch0->harq_mask |= (1 << rel8->harq_process); - if (rel8->rnti_type == 1) LOG_D(PHY,"DCI 1A: round %d, mcs %d, TBS %d, rballoc %x, rv %d, rnti %x, harq process %d\n",dlsch0_harq->round,rel8->mcs_1,dlsch0_harq->TBS,rel8->resource_block_coding,rel8->redundancy_version_1,rel8->rnti,rel8->harq_process); + if (rel8->rnti_type == 1) LOG_D(PHY,"DCI 1A: round %d, mcs %d, TBS %d, rballoc %x, rv %d, rnti %x, harq process %d\n",dlsch0_harq->DLround,rel8->mcs_1,dlsch0_harq->TBS,rel8->resource_block_coding,rel8->redundancy_version_1,rel8->rnti,rel8->harq_process); break; case NFAPI_DL_DCI_FORMAT_1: @@ -690,7 +690,7 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t - if (dlsch0_harq->round == 0) { + if (dlsch0_harq->DLround == 0) { dlsch0_harq->status = ACTIVE; // printf("Setting DLSCH process %d to ACTIVE\n",rel8->harq_process); @@ -1042,16 +1042,16 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t // reset HARQ process if this is the first transmission #ifdef PHY_TX_THREAD - if ((dlsch0->active[subframe]==1) && (dlsch0_harq->round == 0)) + if ((dlsch0->active[subframe]==1) && (dlsch0_harq->DLround == 0)) #else - if ((dlsch0->active==1) && (dlsch0_harq->round == 0)) + if ((dlsch0->active==1) && (dlsch0_harq->DLround == 0)) #endif dlsch0_harq->status = ACTIVE; #ifdef PHY_TX_THREAD - if ((dlsch1->active[subframe]==1) && (dlsch1_harq->round == 0)) + if ((dlsch1->active[subframe]==1) && (dlsch1_harq->DLround == 0)) #else - if ((dlsch1->active==1) && (dlsch1_harq->round == 0)) + if ((dlsch1->active==1) && (dlsch1_harq->DLround == 0)) #endif dlsch1_harq->status = ACTIVE; @@ -1479,7 +1479,7 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t printf ("dlsch0 eNB: NBRB %d\n", dlsch0_harq->nb_rb); printf ("dlsch0 eNB: rballoc %x\n", dlsch0_harq->rb_alloc[0]); printf ("dlsch0 eNB: harq_pid %d\n", harq_pid); - printf ("dlsch0 eNB: round %d\n", dlsch0_harq->round); + printf ("dlsch0 eNB: round %d\n", dlsch0_harq->DLround); printf ("dlsch0 eNB: rvidx %d\n", dlsch0_harq->rvidx); printf ("dlsch0 eNB: TBS %d (NPRB %d)\n", dlsch0_harq->TBS, NPRB); printf ("dlsch0 eNB: mcs %d\n", dlsch0_harq->mcs); @@ -1493,7 +1493,7 @@ void fill_dci_and_dlsch(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_proc_t printf ("dlsch1 eNB: NBRB %d\n", dlsch1_harq->nb_rb); printf ("dlsch1 eNB: rballoc %x\n", dlsch1_harq->rb_alloc[0]); printf ("dlsch1 eNB: harq_pid %d\n", harq_pid); - printf ("dlsch1 eNB: round %d\n", dlsch1_harq->round); + printf ("dlsch1 eNB: round %d\n", dlsch1_harq->DLround); printf ("dlsch1 eNB: rvidx %d\n", dlsch1_harq->rvidx); printf ("dlsch1 eNB: TBS %d (NPRB %d)\n", dlsch1_harq->TBS, NPRB); printf ("dlsch1 eNB: mcs %d\n", dlsch1_harq->mcs); @@ -1748,19 +1748,19 @@ void fill_mdci_and_dlsch(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,mDCI_ALLOC_t *dc dlsch0->subframe_tx[subframe] = 1; if (dlsch0->rnti != rel13->rnti) { // if rnti of dlsch is not the same as in the config, this is a new entry - dlsch0_harq->round = 0; + dlsch0_harq->DLround = 0; dlsch0->harq_mask =0; printf("*********************** rnti %x => %x, pos %d\n",rel13->rnti,dlsch0->rnti,UE_id); } if ((dlsch0->harq_mask & (1 << rel13->harq_process)) > 0) { if ((rel13->new_data_indicator != dlsch0_harq->ndi)||(dci_alloc->ra_flag==1)) - dlsch0_harq->round = 0; + dlsch0_harq->DLround = 0; } else { // process is inactive, so activate and set round to 0 - dlsch0_harq->round = 0; + dlsch0_harq->DLround = 0; } dlsch0_harq->ndi = rel13->new_data_indicator; - if (dlsch0_harq->round == 0) { + if (dlsch0_harq->DLround == 0) { dlsch0_harq->status = ACTIVE; dlsch0_harq->mcs = rel13->mcs; if (dci_alloc->ra_flag == 0) // get TBS from table using mcs and nb_rb @@ -1782,7 +1782,7 @@ void fill_mdci_and_dlsch(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,mDCI_ALLOC_t *dc dlsch0->harq_ids[dlsch0_harq->frame%2][dlsch0_harq->subframe] = rel13->harq_process; dlsch0_harq->pdsch_start = rel13->start_symbol; - LOG_D(PHY,"Setting DLSCH harq %d round %d to active for %d.%d\n",rel13->harq_process,dlsch0_harq->round,dlsch0_harq->frame,dlsch0_harq->subframe); + LOG_D(PHY,"Setting DLSCH harq %d round %d to active for %d.%d\n",rel13->harq_process,dlsch0_harq->DLround,dlsch0_harq->frame,dlsch0_harq->subframe); dlsch0->rnti = rel13->rnti; diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c index b494f7bd6c..ea6bf29ac7 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c @@ -20,15 +20,15 @@ */ /*! \file PHY/LTE_TRANSPORT/dlsch_coding.c -* \brief Top-level routines for implementing Turbo-coded (DLSCH) transport channels from 36-212, V8.6 2009-03 -* \author R. Knopp -* \date 2011 -* \version 0.1 -* \company Eurecom -* \email: knopp@eurecom.fr -* \note -* \warning -*/ + * \brief Top-level routines for implementing Turbo-coded (DLSCH) transport channels from 36-212, V8.6 2009-03 + * \author R. Knopp + * \date 2011 + * \version 0.1 + * \company Eurecom + * \email: knopp@eurecom.fr + * \note + * \warning + */ #include "PHY/defs_eNB.h" #include "PHY/phy_extern.h" @@ -42,21 +42,22 @@ #include "common/utils/LOG/log.h" #include #include "targets/RT/USER/rt_wrapper.h" +#include //#define DEBUG_DLSCH_CODING //#define DEBUG_DLSCH_FREE 1 /* -#define is_not_pilot(pilots,first_pilot,re) (pilots==0) || \ + #define is_not_pilot(pilots,first_pilot,re) (pilots==0) || \ ((pilots==1)&&(first_pilot==1)&&(((re>2)&&(re<6))||((re>8)&&(re<12)))) || \ ((pilots==1)&&(first_pilot==0)&&(((re<3))||((re>5)&&(re<9)))) \ */ #define is_not_pilot(pilots,first_pilot,re) (1) /*extern void thread_top_init(char *thread_name, - int affinity, - uint64_t runtime, - uint64_t deadline, - uint64_t period);*/ + int affinity, + uint64_t runtime, + uint64_t deadline, + uint64_t period);*/ extern WORKER_CONF_t get_thread_worker_conf(void); @@ -82,11 +83,6 @@ void free_eNB_dlsch(LTE_eNB_DLSCH_t *dlsch) { free16(dlsch->harq_processes[i]->c[r],((r==0)?8:0) + 3+768); dlsch->harq_processes[i]->c[r] = NULL; } - - if (dlsch->harq_processes[i]->d[r]) { - free16(dlsch->harq_processes[i]->d[r],(96+12+3+(3*6144))); - dlsch->harq_processes[i]->d[r] = NULL; - } } free16(dlsch->harq_processes[i],sizeof(LTE_DL_eNB_HARQ_t)); @@ -100,26 +96,26 @@ void free_eNB_dlsch(LTE_eNB_DLSCH_t *dlsch) { LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_t Nsoft,unsigned char N_RB_DL, uint8_t abstraction_flag, LTE_DL_FRAME_PARMS *frame_parms) { LTE_eNB_DLSCH_t *dlsch; - unsigned char exit_flag = 0,i,j,r,aa,layer; + unsigned char exit_flag = 0,i,r,aa,layer; int re; unsigned char bw_scaling =1; switch (N_RB_DL) { - case 6: - bw_scaling =16; - break; + case 6: + bw_scaling =16; + break; - case 25: - bw_scaling =4; - break; + case 25: + bw_scaling =4; + break; - case 50: - bw_scaling =2; - break; + case 50: + bw_scaling =2; + break; - default: - bw_scaling =1; - break; + default: + bw_scaling =1; + break; } dlsch = (LTE_eNB_DLSCH_t *)malloc16(sizeof(LTE_eNB_DLSCH_t)); @@ -145,11 +141,11 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_ // NOTE: THIS HAS TO BE REVISED FOR RU, commenting to remove memory leak !!!!! /* - dlsch->calib_dl_ch_estimates = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*)); - for (aa=0; aanb_antennas_tx; aa++) { - dlsch->calib_dl_ch_estimates[aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t)); + dlsch->calib_dl_ch_estimates = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*)); + for (aa=0; aanb_antennas_tx; aa++) { + dlsch->calib_dl_ch_estimates[aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t)); - }*/ + }*/ for (i=0; i<20; i++) dlsch->harq_ids[i/10][i%10] = Mdlharq; @@ -175,7 +171,6 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_ for (r=0; rharq_processes[i]->c[r] = (uint8_t *)malloc16(((r==0)?8:0) + 3+ 768); - dlsch->harq_processes[i]->d[r] = (uint8_t *)malloc16((96+12+3+(3*6144))); if (dlsch->harq_processes[i]->c[r]) { bzero(dlsch->harq_processes[i]->c[r],((r==0)?8:0) + 3+ 768); @@ -183,13 +178,6 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_ printf("Can't get c\n"); exit_flag=2; } - - if (dlsch->harq_processes[i]->d[r]) { - bzero(dlsch->harq_processes[i]->d[r],(96+12+3+(3*6144))); - } else { - printf("Can't get d\n"); - exit_flag=2; - } } } } else { @@ -200,14 +188,7 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_ if (exit_flag==0) { for (i=0; iharq_processes[i]->round=0; - - for (j=0; j<96; j++) - for (r=0; rharq_processes[%d]->d[%d] %p\n",i,r,dlsch->harq_processes[i]->d[r]); - if (dlsch->harq_processes[i]->d[r]) - dlsch->harq_processes[i]->d[r][j] = LTE_NULL; - } + dlsch->harq_processes[i]->DLround=0; } return(dlsch); @@ -222,7 +203,7 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_ void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch) { unsigned char Mdlharq; - unsigned char i,j,r; + unsigned char i; if (dlsch) { Mdlharq = dlsch->Mdlharq; @@ -244,92 +225,17 @@ void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch) { if (dlsch->harq_processes[i]) { // dlsch->harq_processes[i]->Ndi = 0; dlsch->harq_processes[i]->status = 0; - dlsch->harq_processes[i]->round = 0; + dlsch->harq_processes[i]->DLround = 0; - for (j=0; j<96; j++) - for (r=0; rharq_processes[i]->d[r]) - dlsch->harq_processes[i]->d[r][j] = LTE_NULL; } } } } - - - -int dlsch_encoding_2threads0(te_params *tep) { - LTE_eNB_DLSCH_t *dlsch = tep->dlsch; - unsigned int G = tep->G; - unsigned char harq_pid = tep->harq_pid; - unsigned int total_worker = tep->total_worker; - unsigned int current_worker = tep->current_worker; - unsigned short nb_rb = dlsch->harq_processes[harq_pid]->nb_rb; - unsigned int Kr=0,Kr_bytes,r,r_offset=0; - // unsigned short m=dlsch->harq_processes[harq_pid]->mcs; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING_W, VCD_FUNCTION_IN); - - if (dlsch->harq_processes[harq_pid]->round == 0) { // this is a new packet - for (r=(dlsch->harq_processes[harq_pid]->C/(total_worker+1))*current_worker; r<(dlsch->harq_processes[harq_pid]->C/(total_worker+1))*(current_worker+1); r++) { - if (rharq_processes[harq_pid]->Cminus) - Kr = dlsch->harq_processes[harq_pid]->Kminus; - else - Kr = dlsch->harq_processes[harq_pid]->Kplus; - - Kr_bytes = Kr>>3; - encoder(dlsch->harq_processes[harq_pid]->c[r], - Kr>>3, - &dlsch->harq_processes[harq_pid]->d[r][96], - (r==0) ? dlsch->harq_processes[harq_pid]->F : 0 - ); - dlsch->harq_processes[harq_pid]->RTC[r] = - sub_block_interleaving_turbo(4+(Kr_bytes*8), - &dlsch->harq_processes[harq_pid]->d[r][96], - dlsch->harq_processes[harq_pid]->w[r]); - } - } - - // Fill in the "e"-sequence from 36-212, V8.6 2009-03, p. 16-17 (for each "e") and concatenate the - // outputs for each code segment, see Section 5.1.5 p.20 - - for (r=0,r_offset=0; r<(dlsch->harq_processes[harq_pid]->C/(total_worker+1))*(current_worker+1); r++) { - if(r<(dlsch->harq_processes[harq_pid]->C/(total_worker+1))*(current_worker)) { - int Nl=dlsch->harq_processes[harq_pid]->Nl; - int Qm=dlsch->harq_processes[harq_pid]->Qm; - int C = dlsch->harq_processes[harq_pid]->C; - int Gp = G/Nl/Qm; - int GpmodC = Gp%C; - - if (r < (C-(GpmodC))) - r_offset += Nl*Qm * (Gp/C); - else - r_offset += Nl*Qm * ((GpmodC==0?0:1) + (Gp/C)); - } else { - r_offset += lte_rate_matching_turbo(dlsch->harq_processes[harq_pid]->RTC[r], - G, //G - dlsch->harq_processes[harq_pid]->w[r], - dlsch->harq_processes[harq_pid]->e+r_offset, - dlsch->harq_processes[harq_pid]->C, // C - dlsch->Nsoft, // Nsoft, - dlsch->Mdlharq, - dlsch->Kmimo, - dlsch->harq_processes[harq_pid]->rvidx, - dlsch->harq_processes[harq_pid]->Qm, - dlsch->harq_processes[harq_pid]->Nl, - r, - nb_rb); - // m); // r - } - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING_W, VCD_FUNCTION_OUT); - return(0); -} - - extern int oai_exit; int dlsch_encoding_all(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, unsigned char *a, uint8_t num_pdcch_symbols, LTE_eNB_DLSCH_t *dlsch, @@ -342,45 +248,72 @@ int dlsch_encoding_all(PHY_VARS_eNB *eNB, time_stats_t *te_wakeup_stats0, time_stats_t *te_wakeup_stats1, time_stats_t *i_stats) { - int encoding_return = 0; - unsigned int L,C,B; uint8_t harq_pid = dlsch->harq_ids[frame%2][subframe]; if(harq_pid >= dlsch->Mdlharq) { LOG_E(PHY,"dlsch_encoding_all illegal harq_pid %d\n", harq_pid); return(-1); } - B = dlsch->harq_processes[harq_pid]->B; + + LOG_D(PHY,"B %d, harq_pid %d\n", + dlsch->harq_processes[harq_pid]->B, + dlsch->harq_ids[frame%2][subframe]); - LOG_D(PHY,"B %d, harq_pid %d\n",B,dlsch->harq_ids[frame%2][subframe]); + return dlsch_encoding(eNB, + proc, + a, + num_pdcch_symbols, + dlsch, + frame, + subframe, + rm_stats, + te_stats, + i_stats); - if(B<=6144) { - L=0; - C=1; - } else { - L=24; - C = B/(6144-L); - - if((6144-L)*C < B) { - C = C+1; - } - } - - encoding_return = - dlsch_encoding(eNB, - a, - num_pdcch_symbols, - dlsch, - frame, - subframe, - rm_stats, - te_stats, - i_stats); - - return encoding_return; } +static void TPencode(void * arg) { + turboEncode_t * rdata=(turboEncode_t *) arg; + unsigned char harq_pid = rdata->harq_pid; + LTE_DL_eNB_HARQ_t *hadlsch=rdata->dlsch->harq_processes[harq_pid]; + + if ( rdata-> round == 0) { + uint8_t tmp[96+12+3+3*6144]; + memset(tmp,LTE_NULL, TURBO_SIMD_SOFTBITS); + start_meas(rdata->te_stats); + encoder(rdata->input, + rdata->Kr_bytes, + tmp+96,//&dlsch->harq_processes[harq_pid]->d[r][96], + rdata->filler); + stop_meas(rdata->te_stats); + start_meas(rdata->i_stats); + hadlsch->RTC[rdata->r] = + sub_block_interleaving_turbo(4+(rdata->Kr_bytes*8), + tmp+96, + hadlsch->w[rdata->r]); + stop_meas(rdata->i_stats); + } + + // Fill in the "e"-sequence from 36-212, V8.6 2009-03, p. 16-17 (for each "e") and concatenate the + // outputs for each code segment, see Section 5.1.5 p.20 + start_meas(rdata->rm_stats); + lte_rate_matching_turbo(hadlsch->RTC[rdata->r], + rdata->G, //G + hadlsch->w[rdata->r], + hadlsch->e+rdata->r_offset, + hadlsch->C, // C + rdata->dlsch->Nsoft, // Nsoft, + rdata->dlsch->Mdlharq, + rdata->dlsch->Kmimo, + hadlsch->rvidx, + hadlsch->Qm, + hadlsch->Nl, + rdata->r, + hadlsch->nb_rb); + stop_meas(rdata->rm_stats); +} int dlsch_encoding(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, unsigned char *a, uint8_t num_pdcch_symbols, LTE_eNB_DLSCH_t *dlsch, @@ -389,8 +322,6 @@ int dlsch_encoding(PHY_VARS_eNB *eNB, time_stats_t *rm_stats, time_stats_t *te_stats, time_stats_t *i_stats) { - unsigned int G; - unsigned int crc=1; LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms; unsigned char harq_pid = dlsch->harq_ids[frame%2][subframe]; if((harq_pid < 0) || (harq_pid >= dlsch->Mdlharq)) { @@ -398,136 +329,88 @@ int dlsch_encoding(PHY_VARS_eNB *eNB, return(-1); } - unsigned short nb_rb = dlsch->harq_processes[harq_pid]->nb_rb; - unsigned int A; - unsigned char mod_order; - unsigned int Kr=0,Kr_bytes,r,r_offset=0; - // unsigned short m=dlsch->harq_processes[harq_pid]->mcs; + LTE_DL_eNB_HARQ_t *hadlsch=dlsch->harq_processes[harq_pid]; uint8_t beamforming_mode=0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN); - A = dlsch->harq_processes[harq_pid]->TBS; //6228 - // printf("Encoder: A: %d\n",A); - mod_order = dlsch->harq_processes[harq_pid]->Qm; - if(dlsch->harq_processes[harq_pid]->mimo_mode == TM7) + if(hadlsch->mimo_mode == TM7) beamforming_mode = 7; - else if(dlsch->harq_processes[harq_pid]->mimo_mode == TM8) + else if(hadlsch->mimo_mode == TM8) beamforming_mode = 8; - else if(dlsch->harq_processes[harq_pid]->mimo_mode == TM9_10) + else if(hadlsch->mimo_mode == TM9_10) beamforming_mode = 9; - G = get_G(frame_parms,nb_rb,dlsch->harq_processes[harq_pid]->rb_alloc,mod_order,dlsch->harq_processes[harq_pid]->Nl,num_pdcch_symbols,frame,subframe,beamforming_mode); + unsigned int G = get_G(frame_parms,hadlsch->nb_rb, + hadlsch->rb_alloc, + hadlsch->Qm, // mod order + hadlsch->Nl, + num_pdcch_symbols, + frame,subframe,beamforming_mode); - // if (dlsch->harq_processes[harq_pid]->Ndi == 1) { // this is a new packet - if (dlsch->harq_processes[harq_pid]->round == 0) { // this is a new packet -#ifdef DEBUG_DLSCH_CODING - printf("encoding thinks this is a new packet for harq_pid %d (%p), A %u \n",harq_pid,dlsch,A); -#endif - /* - int i; - printf("dlsch (tx): \n"); - for (i=0;i<(A>>3);i++) - printf("%02x.",a[i]); - printf("\n"); - */ + proc->nbEncode=0; + + // if (hadlsch->Ndi == 1) { // this is a new packet + if (hadlsch->DLround == 0) { // this is a new packet // Add 24-bit crc (polynomial A) to payload - crc = crc24a(a, + unsigned int A=hadlsch->TBS; //6228; + unsigned int crc = crc24a(a, A)>>8; a[A>>3] = ((uint8_t *)&crc)[2]; a[1+(A>>3)] = ((uint8_t *)&crc)[1]; a[2+(A>>3)] = ((uint8_t *)&crc)[0]; // printf("CRC %x (A %d)\n",crc,A); - dlsch->harq_processes[harq_pid]->B = A+24; - // dlsch->harq_processes[harq_pid]->b = a; - memcpy(dlsch->harq_processes[harq_pid]->b,a,(A/8)+4); - - if (lte_segmentation(dlsch->harq_processes[harq_pid]->b, - dlsch->harq_processes[harq_pid]->c, - dlsch->harq_processes[harq_pid]->B, - &dlsch->harq_processes[harq_pid]->C, - &dlsch->harq_processes[harq_pid]->Cplus, - &dlsch->harq_processes[harq_pid]->Cminus, - &dlsch->harq_processes[harq_pid]->Kplus, - &dlsch->harq_processes[harq_pid]->Kminus, - &dlsch->harq_processes[harq_pid]->F)<0) + hadlsch->B = A+24; + // hadlsch->b = a; + memcpy(hadlsch->b,a,(A/8)+4); + + if (lte_segmentation(hadlsch->b, + hadlsch->c, + hadlsch->B, + &hadlsch->C, + &hadlsch->Cplus, + &hadlsch->Cminus, + &hadlsch->Kplus, + &hadlsch->Kminus, + &hadlsch->F)<0) return(-1); - - for (r=0; rharq_processes[harq_pid]->C; r++) { - if (rharq_processes[harq_pid]->Cminus) - Kr = dlsch->harq_processes[harq_pid]->Kminus; - else - Kr = dlsch->harq_processes[harq_pid]->Kplus; - - Kr_bytes = Kr>>3; -#ifdef DEBUG_DLSCH_CODING - printf("Generating Code Segment %u (%u bits)\n",r,Kr); - // generate codewords - printf("bits_per_codeword (Kr)= %u, A %u\n",Kr,A); - printf("N_RB = %d\n",nb_rb); - printf("Ncp %d\n",frame_parms->Ncp); - printf("mod_order %d\n",mod_order); -#endif - start_meas(te_stats); - encoder(dlsch->harq_processes[harq_pid]->c[r], - Kr>>3, - &dlsch->harq_processes[harq_pid]->d[r][96], - (r==0) ? dlsch->harq_processes[harq_pid]->F : 0 - ); - stop_meas(te_stats); -#ifdef DEBUG_DLSCH_CODING - - if (r==0) - LOG_M("enc_output0.m","enc0",&dlsch->harq_processes[harq_pid]->d[r][96],(3*8*Kr_bytes)+12,1,4); - -#endif - start_meas(i_stats); - dlsch->harq_processes[harq_pid]->RTC[r] = - sub_block_interleaving_turbo(4+(Kr_bytes*8), - &dlsch->harq_processes[harq_pid]->d[r][96], - dlsch->harq_processes[harq_pid]->w[r]); - stop_meas(i_stats); + } + + for (int r=0, r_offset=0; rC; r++) { + + union turboReqUnion id= {.s={dlsch->rnti,frame,subframe,r,0}}; + notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(turboEncode_t), id.p, &proc->respEncode, TPencode); + turboEncode_t * rdata=(turboEncode_t *) NotifiedFifoData(req); + rdata->input=hadlsch->c[r]; + rdata->Kr_bytes= ( rCminus ? hadlsch->Kminus : hadlsch->Kplus) >>3; + rdata->filler=(r==0) ? hadlsch->F : 0; + rdata->r=r; + rdata->harq_pid=harq_pid; + rdata->dlsch=dlsch; + rdata->rm_stats=rm_stats; + rdata->te_stats=te_stats; + rdata->i_stats=i_stats; + rdata->round=hadlsch->DLround; + rdata->r_offset=r_offset; + rdata->G=G; + + if ( proc->threadPool.activated) { + pushTpool(&proc->threadPool,req); + proc->nbEncode++; + } else { + TPencode(rdata); } + + int Qm=hadlsch->Qm; + int C=hadlsch->C; + int Nl=hadlsch->Nl; + int Gp = G/Nl/Qm; + int GpmodC = Gp%C; + if (r < (C-(GpmodC))) + r_offset += Nl*Qm * (Gp/C); + else + r_offset += Nl*Qm * ((GpmodC==0?0:1) + (Gp/C)); } - // Fill in the "e"-sequence from 36-212, V8.6 2009-03, p. 16-17 (for each "e") and concatenate the - // outputs for each code segment, see Section 5.1.5 p.20 - - for (r=0; rharq_processes[harq_pid]->C; r++) { -#ifdef DEBUG_DLSCH_CODING - printf("Rate Matching, Code segment %u (coded bits (G) %u,unpunctured/repeated bits per code segment %u,mod_order %d, nb_rb %d)...\n", - r, - G, - Kr*3, - mod_order,nb_rb); -#endif - start_meas(rm_stats); -#ifdef DEBUG_DLSCH_CODING - printf("rvidx in encoding = %d\n", dlsch->harq_processes[harq_pid]->rvidx); -#endif - r_offset += lte_rate_matching_turbo(dlsch->harq_processes[harq_pid]->RTC[r], - G, //G - dlsch->harq_processes[harq_pid]->w[r], - dlsch->harq_processes[harq_pid]->e+r_offset, - dlsch->harq_processes[harq_pid]->C, // C - dlsch->Nsoft, // Nsoft, - dlsch->Mdlharq, - dlsch->Kmimo, - dlsch->harq_processes[harq_pid]->rvidx, - dlsch->harq_processes[harq_pid]->Qm, - dlsch->harq_processes[harq_pid]->Nl, - r, - nb_rb); - // m); // r - stop_meas(rm_stats); -#ifdef DEBUG_DLSCH_CODING - - if (r==dlsch->harq_processes[harq_pid]->C-1) - LOG_M("enc_output.m","enc",dlsch->harq_processes[harq_pid]->e,r_offset,1,4); - -#endif - } - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT); return(0); } diff --git a/openair1/PHY/LTE_TRANSPORT/pmch.c b/openair1/PHY/LTE_TRANSPORT/pmch.c index 6fab3dc59b..965ac66eef 100644 --- a/openair1/PHY/LTE_TRANSPORT/pmch.c +++ b/openair1/PHY/LTE_TRANSPORT/pmch.c @@ -102,6 +102,7 @@ void generate_mch(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc,uint8_t *a) AssertFatal(dlsch_encoding(eNB, + proc, a, 1, eNB->dlsch_MCH, diff --git a/openair1/PHY/LTE_TRANSPORT/transport_eNB.h b/openair1/PHY/LTE_TRANSPORT/transport_eNB.h index 5feb1389be..9e78eb75a0 100644 --- a/openair1/PHY/LTE_TRANSPORT/transport_eNB.h +++ b/openair1/PHY/LTE_TRANSPORT/transport_eNB.h @@ -71,7 +71,7 @@ typedef struct { /// Subframe where current HARQ round was sent uint32_t subframe; /// Index of current HARQ round for this DLSCH - uint8_t round; + uint8_t DLround; /// Modulation order uint8_t Qm; /// MCS @@ -103,7 +103,7 @@ typedef struct { /// Concatenated "e"-sequences (for definition see 36-212 V8.6 2009-03, p.17-18) uint8_t e[MAX_NUM_CHANNEL_BITS] __attribute__((aligned(32))); /// Turbo-code outputs (36-212 V8.6 2009-03, p.12 - uint8_t *d[MAX_NUM_DLSCH_SEGMENTS];//[(96+3+(3*6144))]; + //uint8_t *d[MAX_NUM_DLSCH_SEGMENTS];//[(96+3+(3*6144))]; /// Sub-block interleaver outputs (36-212 V8.6 2009-03, p.16-17) uint8_t w[MAX_NUM_DLSCH_SEGMENTS][3*6144]; /// Number of code segments (for definition see 36-212 V8.6 2009-03, p.9) @@ -272,6 +272,7 @@ typedef struct { /// Pointer to the payload uint8_t *b; /// Pointers to transport block segments + //TBD uint8_t *c[MAX_NUM_ULSCH_SEGMENTS]; /// RTC values for each segment (for definition see 36-212 V8.6 2009-03, p.15) uint32_t RTC[MAX_NUM_ULSCH_SEGMENTS]; @@ -288,7 +289,10 @@ typedef struct { /// soft bits for each received segment ("w"-sequence)(for definition see 36-212 V8.6 2009-03, p.15) int16_t w[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)]; /// soft bits for each received segment ("d"-sequence)(for definition see 36-212 V8.6 2009-03, p.15) + //TBD int16_t *d[MAX_NUM_ULSCH_SEGMENTS]; + uint32_t processedSegments; + uint32_t processedBadSegment; /// Number of code segments (for definition see 36-212 V8.6 2009-03, p.9) uint32_t C; /// Number of "small" code segments (for definition see 36-212 V8.6 2009-03, p.10) diff --git a/openair1/PHY/LTE_TRANSPORT/transport_proto.h b/openair1/PHY/LTE_TRANSPORT/transport_proto.h index a795ca79a0..a358df3ff3 100644 --- a/openair1/PHY/LTE_TRANSPORT/transport_proto.h +++ b/openair1/PHY/LTE_TRANSPORT/transport_proto.h @@ -73,6 +73,7 @@ void free_eNB_ulsch(LTE_eNB_ULSCH_t *ulsch); LTE_eNB_ULSCH_t *new_eNB_ulsch(uint8_t max_turbo_iterations,uint8_t N_RB_UL, uint8_t abstraction_flag); int dlsch_encoding_all(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, unsigned char *a, uint8_t num_pdcch_symbols, LTE_eNB_DLSCH_t *dlsch, @@ -112,6 +113,7 @@ int dlsch_encoding_all(PHY_VARS_eNB *eNB, @returns status */ int32_t dlsch_encoding(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, uint8_t *a, uint8_t num_pdcch_symbols, LTE_eNB_DLSCH_t *dlsch, diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index 1f8afe2609..64b83c524a 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -313,6 +313,14 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) r_offset += E; start_meas(&eNB->ulsch_deinterleaving_stats); + #if 0 + start_meas(&eNB->ulsch_deinterleaving_stats); + req=createRequest(DECODE,sizeof(turboDecode_t)); + req->startUELoop=eNB->proc.threadPool.startProcessingUE; + union turboReqUnion id= {.s={eNB->ulsch[UE_id]->rnti,frame,subframe,r,0}}; + req->id= id.p; + turboDecode_t * rdata=(turboDecode_t *) req->data; + #endif sub_block_deinterleaving_turbo(4+Kr, &ulsch_harq->d[r][96], ulsch_harq->w[r]); @@ -322,6 +330,58 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) crc_type = CRC24_A; else crc_type = CRC24_B; + #if 0 + rdata->frame=frame; + rdata->subframe=subframe; + rdata->UEid=UE_id; + rdata->harq_pid=harq_pid; + rdata->Kr=Kr; + rdata->maxIterations=eNB->ulsch[UE_id]->max_turbo_iterations; + rdata->ulsch_harq=ulsch_harq; + rdata->eNB=eNB; + rdata->nbSegments=ulsch_harq->C; + rdata->segment_r=r; + rdata->Fbits=(r==0) ? ulsch_harq->F : 0; + rdata->offset=offset; + rdata->function=td; + int Fbytes=rdata->Fbits>>3; + int blockSize=Kr_bytes - Fbytes - (rdata->nbSegments>1?3:0); + if ( eNB->proc.threadPool.activated) { + add_request(req, &eNB->proc.threadPool); + req=NULL; + } else { + req->startProcessingTime=rdtsc(); + rdata->decodeIterations = td( rdata->soft_bits+96, + rdata->decoded_bytes, + rdata->Kr, + f1f2mat_old[rdata->iind*2], + f1f2mat_old[(rdata->iind*2)+1], + rdata->maxIterations, + rdata->nbSegments == 1 ? CRC24_A: CRC24_B, + rdata->Fbits, + &eNB->ulsch_tc_init_stats, + &eNB->ulsch_tc_alpha_stats, + &eNB->ulsch_tc_beta_stats, + &eNB->ulsch_tc_gamma_stats, + &eNB->ulsch_tc_ext_stats, + &eNB->ulsch_tc_intl1_stats, + &eNB->ulsch_tc_intl2_stats); + + stop_meas(&eNB->ulsch_turbo_decoding_stats); + req->returnTime=req->endProcessingTime=rdtsc(); + req->decodeIterations=rdata->decodeIterations; + req->coreId=0; + req->processedBy[0]=0; + req->next=eNB->proc.threadPool.doneRequests; + eNB->proc.threadPool.doneRequests=req; + + if (rdata->decodeIterations > eNB->ulsch[UE_id]->max_turbo_iterations ) + // Entire TPU need retransmission + break; + } +offset += blockSize; + eNB->proc.threadPool.startProcessingUE=rdtsc(); + #endif start_meas(&eNB->ulsch_turbo_decoding_stats); ret = tc(&ulsch_harq->d[r][96], NULL, diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c index da213c3919..0b9fd57d19 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c @@ -1332,8 +1332,6 @@ void rx_ulsch_emul(PHY_VARS_eNB *eNB, eNB->ulsch[UE_id]->harq_processes[harq_pid]->Nsymb_pusch); sprintf(fname,"/tmp/ulsch_r%d_d",round); sprintf(vname,"/tmp/ulsch_r%d_dseq",round); - LOG_UM(fname,vname,&eNB->ulsch[UE_id]->harq_processes[harq_pid]->d[0][96], - eNB->ulsch[UE_id]->harq_processes[harq_pid]->Kplus*3,1,0); if (eNB->common_vars.rxdata) { sprintf(fname,"/tmp/rxsig0_r%d.m",round); sprintf(vname,"rxs0_r%d",round); diff --git a/openair1/PHY/defs_eNB.h b/openair1/PHY/defs_eNB.h index 1ae3515cd8..718ede5715 100644 --- a/openair1/PHY/defs_eNB.h +++ b/openair1/PHY/defs_eNB.h @@ -857,6 +857,54 @@ typedef struct PHY_VARS_eNB_s { uint8_t *FS6bufferZone; } PHY_VARS_eNB; +struct turboReqId { + uint16_t rnti; + uint16_t frame; + uint8_t subframe; + uint8_t codeblock; + uint16_t spare; +} __attribute__((packed)); + +union turboReqUnion { + struct turboReqId s; + uint64_t p; +}; + +typedef struct TurboDecode_s { + decoder_if_t *function; + int16_t soft_bits[3*8*6144+12+96] __attribute__((aligned(32))); + uint8_t decoded_bytes[3+768] __attribute__((aligned(32))); + int UEid; + int harq_pid; + int frame; + int subframe; + int iind; + int Fbits; + int Kr; + LTE_UL_eNB_HARQ_t *ulsch_harq; + PHY_VARS_eNB *eNB; + int nbSegments; + int segment_r; + int offset; + int maxIterations; + int decodeIterations; +} turboDecode_t; + +#define TURBO_SIMD_SOFTBITS 96+12+3+3*6144 +typedef struct turboEncode_s { + uint8_t * input; + int Kr_bytes; + int filler; + unsigned int G; + int r; + int harq_pid; + int round; + int r_offset; + LTE_eNB_DLSCH_t *dlsch; + time_stats_t *rm_stats; + time_stats_t *te_stats; + time_stats_t *i_stats; +} turboEncode_t; #endif /* __PHY_DEFS_ENB__H__ */ diff --git a/openair1/SCHED/fapi_l1.c b/openair1/SCHED/fapi_l1.c index b52a2eb22c..1a088563f0 100644 --- a/openair1/SCHED/fapi_l1.c +++ b/openair1/SCHED/fapi_l1.c @@ -220,13 +220,13 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_pro dlsch0_harq->pdsch_start = eNB->pdcch_vars[proc->subframe_tx & 1].num_pdcch_symbols; - if (dlsch0_harq->round==0) { //get pointer to SDU if this a new SDU + if (dlsch0_harq->DLround==0) { //get pointer to SDU if this a new SDU if(sdu == NULL) { LOG_E(PHY, "NFAPI: SFN/SF:%04d%d proc:TX:[frame %d subframe %d]: programming dlsch for round 0, rnti %x, UE_id %d, harq_pid %d : sdu is null for pdu_index %d dlsch0_harq[round:%d SFN/SF:%d%d pdu:%p mcs:%d ndi:%d pdschstart:%d]\n", frame,subframe, proc->frame_tx,proc->subframe_tx,rel8->rnti,UE_id,harq_pid, - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index,dlsch0_harq->round,dlsch0_harq->frame,dlsch0_harq->subframe,dlsch0_harq->pdu,dlsch0_harq->mcs,dlsch0_harq->ndi,dlsch0_harq->pdsch_start); + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index,dlsch0_harq->DLround,dlsch0_harq->frame,dlsch0_harq->subframe,dlsch0_harq->pdu,dlsch0_harq->mcs,dlsch0_harq->ndi,dlsch0_harq->pdsch_start); return; } @@ -241,7 +241,7 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_pro else dlsch1_harq->pdu = sdu; } else { if (rel8->rnti != 0xFFFF) LOG_D(PHY,"NFAPI: SFN/SF:%04d%d proc:TX:[frame %d, subframe %d]: programming dlsch for round %d, rnti %x, UE_id %d, harq_pid %d\n", - frame,subframe,proc->frame_tx,proc->subframe_tx,dlsch0_harq->round, + frame,subframe,proc->frame_tx,proc->subframe_tx,dlsch0_harq->DLround, rel8->rnti,UE_id,harq_pid); } @@ -321,7 +321,7 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_pro dlsch0_harq->Nl = 1; dlsch0_harq->mimo_mode = (eNB->frame_parms.nb_antenna_ports_eNB == 1) ? SISO : ALAMOUTI; dlsch0_harq->dl_power_off = 1; - dlsch0_harq->round = 0; + dlsch0_harq->DLround = 0; dlsch0_harq->status = ACTIVE; dlsch0_harq->TBS = rel8->length<<3; dlsch0_harq->Qm = rel8->modulation; @@ -346,13 +346,13 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_pro #else dlsch0->i0, #endif - dlsch0_harq->pdsch_start, dlsch0_harq->nb_rb, dlsch0_harq->vrb_type, dlsch0_harq->rvidx, dlsch0_harq->Nl, dlsch0_harq->mimo_mode, dlsch0_harq->dl_power_off, dlsch0_harq->round, dlsch0_harq->status, + dlsch0_harq->pdsch_start, dlsch0_harq->nb_rb, dlsch0_harq->vrb_type, dlsch0_harq->rvidx, dlsch0_harq->Nl, dlsch0_harq->mimo_mode, dlsch0_harq->dl_power_off, dlsch0_harq->DLround, dlsch0_harq->status, dlsch0_harq->TBS, dlsch0_harq->Qm, dlsch0_harq->codeword, dlsch0_harq->rb_alloc[0], rel8->length ); #else LOG_D(PHY,"dlsch0_harq[pdsch_start:%d nb_rb:%d vrb_type:%d rvidx:%d Nl:%d mimo_mode:%d dl_power_off:%d round:%d status:%d TBS:%d Qm:%d codeword:%d rb_alloc:%d] rel8[length:%d]\n", - dlsch0_harq->pdsch_start, dlsch0_harq->nb_rb, dlsch0_harq->vrb_type, dlsch0_harq->rvidx, dlsch0_harq->Nl, dlsch0_harq->mimo_mode, dlsch0_harq->dl_power_off, dlsch0_harq->round, dlsch0_harq->status, + dlsch0_harq->pdsch_start, dlsch0_harq->nb_rb, dlsch0_harq->vrb_type, dlsch0_harq->rvidx, dlsch0_harq->Nl, dlsch0_harq->mimo_mode, dlsch0_harq->dl_power_off, dlsch0_harq->DLround, dlsch0_harq->status, dlsch0_harq->TBS, dlsch0_harq->Qm, dlsch0_harq->codeword, dlsch0_harq->rb_alloc[0], rel8->length ); @@ -385,7 +385,7 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_pro #endif dlsch0_harq->pdsch_start = eNB->pdcch_vars[proc->subframe_tx & 1].num_pdcch_symbols; - if (dlsch0_harq->round==0) { //get pointer to SDU if this a new SDU + if (dlsch0_harq->DLround==0) { //get pointer to SDU if this a new SDU AssertFatal(sdu!=NULL,"NFAPI: frame %d, subframe %d: programming dlsch for round 0, rnti %x, UE_id %d, harq_pid %d : sdu is null for pdu_index %d\n", proc->frame_tx,proc->subframe_tx,rel8->rnti,UE_id,harq_pid, dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index); @@ -397,7 +397,7 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_pro else dlsch1_harq->pdu = sdu; } else { if (rel8->rnti != 0xFFFF) LOG_D(PHY,"NFAPI: frame %d, subframe %d: programming dlsch for round %d, rnti %x, UE_id %d, harq_pid %d\n", - proc->frame_tx,proc->subframe_tx,dlsch0_harq->round, + proc->frame_tx,proc->subframe_tx,dlsch0_harq->DLround, rel8->rnti,UE_id,harq_pid); } } diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index e5c767361d..94689ed246 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -260,16 +260,16 @@ bool dlsch_procedures(PHY_VARS_eNB *eNB, dlsch_harq->TBS, pmi2hex_2Ar1(dlsch_harq->pmi_alloc), dlsch_harq->rvidx, - dlsch_harq->round); + dlsch_harq->DLround); } if (ue_stats) ue_stats->dlsch_sliding_cnt++; - if (dlsch_harq->round == 0) { + if (dlsch_harq->DLround == 0) { if (ue_stats) ue_stats->dlsch_trials[harq_pid][0]++; } else { - ue_stats->dlsch_trials[harq_pid][dlsch_harq->round]++; + ue_stats->dlsch_trials[harq_pid][dlsch_harq->DLround]++; #ifdef DEBUG_PHY_PROC #ifdef DEBUG_DLSCH LOG_D (PHY, "[eNB] This DLSCH is a retransmission\n"); @@ -280,18 +280,19 @@ bool dlsch_procedures(PHY_VARS_eNB *eNB, if (dlsch->rnti!=0xffff) LOG_D(PHY,"Generating DLSCH/PDSCH pdu:%p pdsch_start:%d frame:%d subframe:%d nb_rb:%d rb_alloc:%d Qm:%d Nl:%d round:%d\n", dlsch_harq->pdu,dlsch_harq->pdsch_start,frame,subframe,dlsch_harq->nb_rb,dlsch_harq->rb_alloc[0], - dlsch_harq->Qm,dlsch_harq->Nl,dlsch_harq->round); + dlsch_harq->Qm,dlsch_harq->Nl,dlsch_harq->DLround); // 36-212 if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) { // monolthic OR PNF - do not need turbo encoding on VNF if (dlsch_harq->pdu==NULL) { LOG_E(PHY,"dlsch_harq->pdu == NULL SFN/SF:%04d%d dlsch[rnti:%x] dlsch_harq[pdu:%p pdsch_start:%d Qm:%d Nl:%d round:%d nb_rb:%d rb_alloc[0]:%d]\n", frame,subframe,dlsch->rnti, dlsch_harq->pdu, - dlsch_harq->pdsch_start,dlsch_harq->Qm,dlsch_harq->Nl,dlsch_harq->round,dlsch_harq->nb_rb,dlsch_harq->rb_alloc[0]); + dlsch_harq->pdsch_start,dlsch_harq->Qm,dlsch_harq->Nl,dlsch_harq->DLround,dlsch_harq->nb_rb,dlsch_harq->rb_alloc[0]); return false; } start_meas(&eNB->dlsch_encoding_stats); dlsch_encoding_all(eNB, + proc, dlsch_harq->pdu, dlsch_harq->pdsch_start, dlsch, @@ -306,6 +307,14 @@ bool dlsch_procedures(PHY_VARS_eNB *eNB, &eNB->dlsch_interleaving_stats); stop_meas(&eNB->dlsch_encoding_stats); + if ( proc->threadPool.activated ) { + // Wait all other threads finish to process + while (proc->nbEncode) { + pullTpool(&proc->respEncode, &proc->threadPool); + proc->nbEncode--; + } + } + if(eNB->dlsch_encoding_stats.p_time>500*3000 && opp_enabled == 1) { print_meas_now(&eNB->dlsch_encoding_stats,"total coding",stderr); } @@ -314,8 +323,8 @@ bool dlsch_procedures(PHY_VARS_eNB *eNB, #else dlsch->active = 0; #endif - dlsch_harq->round++; - LOG_D(PHY,"Generated DLSCH dlsch_harq[round:%d]\n",dlsch_harq->round); + dlsch_harq->DLround++; + LOG_D(PHY,"Generated DLSCH dlsch_harq[round:%d]\n",dlsch_harq->DLround); return true; } return false; @@ -359,7 +368,7 @@ void pdsch_procedures(PHY_VARS_eNB *eNB, dlsch->ue_type==0 ? dlsch1 : (LTE_eNB_DLSCH_t *)NULL); stop_meas(&eNB->dlsch_modulation_stats); - LOG_D(PHY,"Generated PDSCH dlsch_harq[round:%d]\n",dlsch_harq->round); + LOG_D(PHY,"Generated PDSCH dlsch_harq[round:%d]\n",dlsch_harq->DLround); } @@ -1146,7 +1155,7 @@ uci_procedures(PHY_VARS_eNB *eNB, if (eNB->first_sr[uci->ue_id] == 1) { // this is the first request for uplink after Connection Setup, so clear HARQ process 0 use for Msg4 eNB->first_sr[uci->ue_id] = 0; - eNB->dlsch[uci->ue_id][0]->harq_processes[0]->round = 0; + eNB->dlsch[uci->ue_id][0]->harq_processes[0]->DLround = 0; eNB->dlsch[uci->ue_id][0]->harq_processes[0]->status = SCH_IDLE; LOG_D (PHY, "[eNB %d][SR %x] Frame %d subframe %d First SR\n", eNB->Mod_id, eNB->ulsch[uci->ue_id]->rnti, frame, subframe); } @@ -1156,6 +1165,87 @@ uci_procedures(PHY_VARS_eNB *eNB, } // end loop for (int i = 0; i < NUMBER_OF_UE_MAX; i++) { } +#if 0 +void post_decode(request_t* decodeResult) { + turboDecode_t * rdata=(turboDecode_t *) decodeResult->data; + LTE_eNB_ULSCH_t *ulsch = rdata->eNB->ulsch[rdata->UEid]; + LTE_UL_eNB_HARQ_t *ulsch_harq = rdata->ulsch_harq; + PHY_VARS_eNB *eNB=rdata->eNB; + bool decodeSucess=rdata->decodeIterations <= rdata->maxIterations; + ulsch_harq->processedSegments++; + if (decodeSucess) { + int Fbytes=rdata->Fbits>>3; + int Kr=rdata->segment_r < ulsch_harq->Cminus? + ulsch_harq->Kminus: + ulsch_harq->Kplus; + int Kr_bytes = Kr>>3; + int blockSize=Kr_bytes - Fbytes - (rdata->nbSegments>1?3:0); + memcpy(ulsch_harq->b+rdata->offset, + rdata->decoded_bytes+Fbytes, + blockSize); + + } else { + if (rdata->nbSegments > 1 ) { + // Purge pending decoding of the same TDU + union turboReqUnion idInFailure= {.p=decodeResult->id}; + rnti_t rntiInFailure=idInFailure.s.rnti; + tpool_t * tp=&proc->threadPool; + mutexlock(tp->lockRequests); + request_t* pending=NULL; + while ( (pending=searchRNTI(tp, rntiInFailure)) != NULL) { + LOG_W(MAC,"removing a CB belonging to a bad TPU"); + freeRequest(pending); + mutexlock(tp->lockReportDone); + tp->notFinishedJobs--; + mutexunlock(tp->lockReportDone); + } + mutexunlock(tp->lockRequests); + } + } + + // Check if TDU is complete: either we have all blocks in success + // either at least one block can't be decoded + // Maybe we receive decoded block alter a first failure, + // so we protect ourselves against multiple executions + if ( (rdata->nbSegments == ulsch_harq->processedSegments || decodeSucess==false) && + ulsch_harq->processedBadSegment == 0 ) { + //compute the expected ULSCH RX power (for the stats) + ulsch_harq->delta_TF = get_hundred_times_delta_IF_eNB(eNB,rdata->UEid,rdata->harq_pid, 0); // 0 means bw_factor is not considered + + if (ulsch_harq->cqi_crc_status == 1) + fill_ulsch_cqi_indication(eNB,rdata->frame,rdata->subframe, + ulsch_harq, + ulsch->rnti); + + fill_crc_indication(eNB,rdata->UEid,rdata->frame,rdata->subframe,decodeSucess?0:1); // indicate result to MAC + fill_rx_indication(eNB,rdata->UEid,rdata->frame,rdata->subframe); // indicate SDU to MAC + + if (!decodeSucess) { + ulsch_harq->processedBadSegment =1; + if (ulsch_harq->round >= 3) { + ulsch_harq->status = SCH_IDLE; + ulsch_harq->handled = 0; + ulsch->harq_mask &= ~(1 << rdata->harq_pid); + ulsch_harq->round = 0; + } + + /* Mark the HARQ process to release it later if max transmission reached + * (see below). + * MAC does not send the max transmission count, we have to deal with it + * locally in PHY. + */ + ulsch_harq->handled = 1; + } else { + ulsch_harq->status = SCH_IDLE; + ulsch->harq_mask &= ~(1 << rdata->harq_pid); + } // ulsch not in error + + if (ulsch_harq->O_ACK>0) + fill_ulsch_harq_indication(eNB,ulsch_harq,ulsch->rnti,rdata->frame,rdata->subframe,ulsch->bundling); + } +} +#endif + void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { uint32_t ret=0,i; uint32_t harq_pid; @@ -1354,6 +1444,49 @@ void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { LOG_W (PHY, "Removing stale ULSCH config for UE %x harq_pid %d (harq_mask is now 0x%2.2x)\n", ulsch->rnti, harq_pid, ulsch->harq_mask); } } // for (i=0; ithreadPool.activated ) { + // Wait all other threads finish to process + //printf("%s:%d:%d\n", __FILE__,__LINE__,eNB->proc->threadPool.notFinishedJobs); + int rr=0; + mutexlock(proc->threadPool.lockReportDone); + while ( proc->threadPool.notFinishedJobs > 0 ) { + //printf("%s:%d:%d\n", __FILE__,__LINE__,eNB->proc->threadPool.notFinishedJobs); + struct timespec t; + clock_gettime(CLOCK_REALTIME,&t); + t.tv_nsec+=1*1000*1000; + if ( t.tv_nsec >= 1000*1000*1000 ) { + t.tv_nsec -= 1000*1000*1000; + t.tv_sec++; + } + if ((rr=pthread_cond_timedwait(&proc->threadPool.notifDone,&proc.threadPool.lockReportDone, &t))!=0) { + LOG_E(PHY,"timedwait1:%s,%p,%p,%p,%d\n", rr==ETIMEDOUT?"ETIMEDOUT":"other", + proc->threadPool.oldestRequests, + proc->threadPool.newestRequests, + proc->threadPool.doneRequests, + proc->threadPool.notFinishedJobs); + proc->threadPool.oldestRequests=NULL; + proc->threadPool.newestRequests=NULL; + proc->threadPool.doneRequests=NULL; + proc->threadPool.notFinishedJobs=0; + } + } + mutexunlock(proc->threadPool.lockReportDone); + } + + request_t* tmp; + while ((tmp=proc->threadPool.doneRequests)!=NULL) { + turboDecode_t * rdata=(turboDecode_t *) tmp->data; + tmp->decodeIterations=rdata->decodeIterations; + post_decode(tmp); + tmp->returnTime=rdtsc(); + tmp->cumulSubframe=tmp->returnTime-startTime; + // Ignore write error (if no trace listner) + if (write(proc->threadPool.traceFd, tmp, sizeof(request_t)- 2*sizeof(void*))) {}; + proc->threadPool.doneRequests=tmp->next; + freeRequest(tmp); + } + #endif } extern int oai_exit; @@ -1515,7 +1648,7 @@ static void do_release_harq(PHY_VARS_eNB *eNB, #endif - if (dlsch0_harq->round >= after_rounds) { + if (dlsch0_harq->DLround >= after_rounds) { dlsch0_harq->status = SCH_IDLE; dlsch0->harq_mask &= ~(1 << harq_pid); } @@ -1564,7 +1697,7 @@ static void do_release_harq(PHY_VARS_eNB *eNB, T_INT(harq_pid)); } #endif - if (dlsch0_harq->round >= after_rounds) { + if (dlsch0_harq->DLround >= after_rounds) { dlsch0_harq->status = SCH_IDLE; if ((dlsch1_harq == NULL) || ((dlsch1_harq != NULL) && (dlsch1_harq->status == SCH_IDLE))) { diff --git a/openair2/PHY_INTERFACE/IF_Module.h b/openair2/PHY_INTERFACE/IF_Module.h index 0e8daf064f..790a5c98e6 100644 --- a/openair2/PHY_INTERFACE/IF_Module.h +++ b/openair2/PHY_INTERFACE/IF_Module.h @@ -39,6 +39,7 @@ #include "nfapi_interface.h" #include "platform_constants.h" #include "platform_types.h" +#include #define MAX_NUM_DL_PDU 100 #define MAX_NUM_UL_PDU 100 @@ -179,6 +180,11 @@ typedef struct { pthread_cond_t cond_RUs; /// mutex for RXn-TXnp4 processing thread pthread_mutex_t mutex_RUs; + tpool_t threadPool; + int nbEncode; + int nbDecode; + notifiedFIFO_t respEncode; + notifiedFIFO_t respDecode; } L1_rxtx_proc_t; typedef struct IF_Module_s{ diff --git a/targets/RT/USER/lte-softmodem.h b/targets/RT/USER/lte-softmodem.h index 33d4dc3b09..3a02868f56 100644 --- a/targets/RT/USER/lte-softmodem.h +++ b/targets/RT/USER/lte-softmodem.h @@ -175,6 +175,7 @@ /* optname helpstr paramflags XXXptr defXXXval type numelt */ /*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ #define RF_CONFIG_FILE softmodem_params.rf_config_file +#define TP_CONFIG softmodem_params.threadPoolConfig #define PHY_TEST softmodem_params.phy_test #define WAIT_FOR_SYNC softmodem_params.wait_for_sync #define SINGLE_THREAD_FLAG softmodem_params.single_thread_flag @@ -187,6 +188,7 @@ #define USIM_TEST softmodem_params.usim_test #define CMDLINE_PARAMS_DESC { \ {"rf-config-file", CONFIG_HLP_RFCFGF, 0, strptr:(char **)&RF_CONFIG_FILE, defstrval:NULL, TYPE_STRING, sizeof(RF_CONFIG_FILE)}, \ + {"turbo-thread-pool", NULL, 0, strptr:(char **)&TP_CONFIG, defstrval:NULL, TYPE_STRING, sizeof(TP_CONFIG)}, \ {"ulsch-max-errors", CONFIG_HLP_ULMAXE, 0, uptr:&ULSCH_max_consecutive_errors, defuintval:0, TYPE_UINT, 0}, \ {"phy-test", CONFIG_HLP_PHYTST, PARAMFLAG_BOOL, iptr:&PHY_TEST, defintval:0, TYPE_INT, 0}, \ {"usim-test", CONFIG_HLP_USIM, PARAMFLAG_BOOL, u8ptr:&USIM_TEST, defintval:0, TYPE_UINT8, 0}, \ @@ -253,6 +255,7 @@ typedef struct { uint64_t optmask; THREAD_STRUCT thread_struct; char rf_config_file[1024]; + char threadPoolConfig[1024]; int phy_test; uint8_t usim_test; int emulate_rf; From 13122a272e42014fcd48fec55a47fd6205d43924 Mon Sep 17 00:00:00 2001 From: laurent Date: Thu, 31 Oct 2019 17:28:21 +0100 Subject: [PATCH 057/240] ul in parallel monolithic case, ul in parallel memory leak fix --- common/utils/threadPool/thread-pool.c | 7 +- common/utils/threadPool/thread-pool.h | 39 ++- executables/main-fs6.c | 2 +- executables/main-ocp.c | 9 +- openair1/PHY/LTE_TRANSPORT/dlsch_coding.c | 1 + openair1/PHY/LTE_TRANSPORT/transport_eNB.h | 1 + openair1/PHY/LTE_TRANSPORT/transport_proto.h | 2 + openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c | 342 ++++++++----------- openair1/PHY/defs_eNB.h | 9 +- openair1/SCHED/phy_procedures_lte_eNb.c | 329 +++++------------- 10 files changed, 272 insertions(+), 469 deletions(-) diff --git a/common/utils/threadPool/thread-pool.c b/common/utils/threadPool/thread-pool.c index 4cc56fc9b8..1b7aa960ba 100644 --- a/common/utils/threadPool/thread-pool.c +++ b/common/utils/threadPool/thread-pool.c @@ -84,7 +84,7 @@ void *one_thread(void *arg) { delNotifiedFIFO_elt(elt); else pushNotifiedFIFO(elt->reponseFifo, elt); - + myThread->runningOnKey=-1; mutexunlock(tp->incomingFifo.lockF); } } while (true); @@ -116,7 +116,7 @@ void initTpool(char *params,tpool_t *pool, bool performanceMeas) { pool->nbThreads=0; pool->restrictRNTI=false; curptr=strtok_r(params,",",&saveptr); - + struct one_thread * ptr; while ( curptr!=NULL ) { int c=toupper(curptr[0]); @@ -130,8 +130,9 @@ void initTpool(char *params,tpool_t *pool, bool performanceMeas) { break; default: + ptr=pool->allthreads; pool->allthreads=(struct one_thread *)malloc(sizeof(struct one_thread)); - pool->allthreads->next=pool->allthreads; + pool->allthreads->next=ptr; printf("create a thread for core %d\n", atoi(curptr)); pool->allthreads->coreID=atoi(curptr); pool->allthreads->id=pool->nbThreads; diff --git a/common/utils/threadPool/thread-pool.h b/common/utils/threadPool/thread-pool.h index 6f34508c5a..d68918a163 100644 --- a/common/utils/threadPool/thread-pool.h +++ b/common/utils/threadPool/thread-pool.h @@ -137,8 +137,9 @@ static inline notifiedFIFO_elt_t *pollNotifiedFIFO(notifiedFIFO_t *nf) { // This function aborts all messages matching the key // If the queue is used in thread pools, it doesn't cancels already running processing // because the message has already been picked -static inline void abortNotifiedFIFO(notifiedFIFO_t *nf, uint64_t key) { +static inline int abortNotifiedFIFO(notifiedFIFO_t *nf, uint64_t key) { mutexlock(nf->lockF); + int nbDeleted=0; notifiedFIFO_elt_t **start=&nf->outF; while(*start!=NULL) { @@ -146,13 +147,15 @@ static inline void abortNotifiedFIFO(notifiedFIFO_t *nf, uint64_t key) { notifiedFIFO_elt_t *request=*start; *start=(*start)->next; delNotifiedFIFO_elt(request); - } - - if (*start != NULL) + nbDeleted++; + } else start=&(*start)->next; } + if (nf->outF == NULL) + nf->inF=NULL; mutexunlock(nf->lockF); + return nbDeleted; } struct one_thread { @@ -181,8 +184,17 @@ typedef struct thread_pool { static inline void pushTpool(tpool_t *t, notifiedFIFO_elt_t *msg) { if (t->measurePerf) msg->creationTime=rdtsc(); - - pushNotifiedFIFO(&t->incomingFifo, msg); + if ( t->activated) + pushNotifiedFIFO(&t->incomingFifo, msg); + else { + if (t->measurePerf) + msg->startProcessingTime=rdtsc(); + msg->processingFunc(NotifiedFifoData(msg)); + if (t->measurePerf) + msg->endProcessingTime=rdtsc(); + if (msg->reponseFifo) + pushNotifiedFIFO(msg->reponseFifo, msg); + } } static inline notifiedFIFO_elt_t *pullTpool(notifiedFIFO_t *responseFifo, tpool_t *t) { @@ -212,7 +224,8 @@ static inline notifiedFIFO_elt_t *tryPullTpool(notifiedFIFO_t *responseFifo, tpo return msg; } -static inline void abortTpool(tpool_t *t, uint64_t key) { +static inline int abortTpool(tpool_t *t, uint64_t key) { + int nbRemoved=0; notifiedFIFO_t *nf=&t->incomingFifo; mutexlock(nf->lockF); notifiedFIFO_elt_t **start=&nf->outF; @@ -222,22 +235,26 @@ static inline void abortTpool(tpool_t *t, uint64_t key) { notifiedFIFO_elt_t *request=*start; *start=(*start)->next; delNotifiedFIFO_elt(request); - } - - if (*start != NULL) + nbRemoved++; + } else start=&(*start)->next; } + if (t->incomingFifo.outF==NULL) + t->incomingFifo.inF=NULL; struct one_thread *ptr=t->allthreads; while(ptr!=NULL) { - if (ptr->runningOnKey==key) + if (ptr->runningOnKey==key) { ptr->abortFlag=true; + nbRemoved++; + } ptr=ptr->next; } mutexunlock(nf->lockF); + return nbRemoved; } void initTpool(char *params,tpool_t *pool, bool performanceMeas); diff --git a/executables/main-fs6.c b/executables/main-fs6.c index 1416572d76..f2c95f86d4 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -615,7 +615,7 @@ void pusch_procedures_fromsplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB * &ulsch_harq->Kplus, &ulsch_harq->Kminus, &ulsch_harq->F); - int ret = ulsch_decoding_data(eNB, i, harq_pid, + int ret = ulsch_decoding_data(eNB, proc, i, harq_pid, ulsch_harq->nb_rb>20 ? 1 : 0); stop_meas(&eNB->ulsch_decoding_stats); LOG_D(PHY, diff --git a/executables/main-ocp.c b/executables/main-ocp.c index 34cd950ce7..4e657e6d28 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -692,13 +692,14 @@ static void *ru_thread( void *param ) { L1_rxtx_proc_t L1proc; L1_rxtx_proc_t *proc=&L1proc; - if ( strlen(get_softmodem_params()->threadPoolConfig) > 0 ) { + if ( strlen(get_softmodem_params()->threadPoolConfig) > 0 ) initTpool(get_softmodem_params()->threadPoolConfig, &L1proc.threadPool, true); - initNotifiedFIFO(&L1proc.respEncode); - initNotifiedFIFO(&L1proc.respDecode); - } else + else initTpool("n", &L1proc.threadPool, true); + initNotifiedFIFO(&L1proc.respEncode); + initNotifiedFIFO(&L1proc.respDecode); + if (ru->if_south == LOCAL_RF) { // configure RF parameters only fill_rf_config(ru,ru->rf_config_file); init_frame_parms(&ru->frame_parms,1); diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c index ea6bf29ac7..5024650d62 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c @@ -398,6 +398,7 @@ int dlsch_encoding(PHY_VARS_eNB *eNB, proc->nbEncode++; } else { TPencode(rdata); + delNotifiedFIFO_elt(req); } int Qm=hadlsch->Qm; diff --git a/openair1/PHY/LTE_TRANSPORT/transport_eNB.h b/openair1/PHY/LTE_TRANSPORT/transport_eNB.h index 9e78eb75a0..0737d4c56a 100644 --- a/openair1/PHY/LTE_TRANSPORT/transport_eNB.h +++ b/openair1/PHY/LTE_TRANSPORT/transport_eNB.h @@ -288,6 +288,7 @@ typedef struct { uint8_t rvidx; /// soft bits for each received segment ("w"-sequence)(for definition see 36-212 V8.6 2009-03, p.15) int16_t w[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)]; + int16_t pusch_rep_buffer[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)]; /// soft bits for each received segment ("d"-sequence)(for definition see 36-212 V8.6 2009-03, p.15) //TBD int16_t *d[MAX_NUM_ULSCH_SEGMENTS]; diff --git a/openair1/PHY/LTE_TRANSPORT/transport_proto.h b/openair1/PHY/LTE_TRANSPORT/transport_proto.h index a358df3ff3..0d8fcfa29e 100644 --- a/openair1/PHY/LTE_TRANSPORT/transport_proto.h +++ b/openair1/PHY/LTE_TRANSPORT/transport_proto.h @@ -469,6 +469,7 @@ void rx_ulsch(PHY_VARS_eNB *eNB, int ulsch_decoding_data_all(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, int UE_id, int harq_pid, int llr8_flag); @@ -513,6 +514,7 @@ int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB, @returns 0 on success */ int ulsch_decoding_data(PHY_VARS_eNB *eNB, + L1_rxtx_proc_t *proc, int UE_id, int harq_pid, int llr8_flag); diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index 64b83c524a..4cfdcbdb41 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -213,72 +213,26 @@ uint8_t extract_cqi_crc(uint8_t *cqi,uint8_t CQI_LENGTH) { extern int oai_exit; -int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) { - unsigned int r,r_offset=0,Kr,Kr_bytes; - uint8_t crc_type; - int offset = 0; - int ret = 1; - int16_t dummy_w[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)]; - LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id]; - LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; - int G = ulsch_harq->G; - unsigned int E; - decoder_if_t *tc; - static int32_t pusch_rep_buffer[3*(6144+64)]; - int max_Ncb; - - if (llr8_flag == 0) - tc = *decoder16; - else - tc = *decoder8; - - if(ulsch_harq->repetition_number == 1) { - memset(pusch_rep_buffer,0,(sizeof(int32_t)*3*(6144+64))) ; // reset the buffer every new repetitions - } - - for (r=0; rC; r++) { - // printf("before subblock deinterleaving c[%d] = %p\n",r,ulsch_harq->c[r]); - // Get Turbo interleaver parameters - if (rCminus) - Kr = ulsch_harq->Kminus; - else - Kr = ulsch_harq->Kplus; - - Kr_bytes = Kr>>3; - memset(&dummy_w[r][0],0,3*(6144+64)*sizeof(short)); - ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8), - (uint8_t *)&dummy_w[r][0], +void processULSegment(void * arg) { + turboDecode_t* rdata=(turboDecode_t*) arg; + PHY_VARS_eNB *eNB=rdata->eNB; + LTE_UL_eNB_HARQ_t *ulsch_harq=rdata->ulsch_harq; + int r=rdata->segment_r; + int G=ulsch_harq->G; + int Kr_bytes=rdata->Kr>>3; + int16_t dummy_w[3*(6144+64)]; + + memset(&dummy_w[0],0,3*(6144+64)*sizeof(short)); + ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8), + (uint8_t *)&dummy_w[0], (r==0) ? ulsch_harq->F : 0); -#ifdef DEBUG_ULSCH_DECODING - printf("Rate Matching Segment %u (coded bits (G) %d,unpunctured/repeated bits %u, Q_m %d, Nl %d, r_offset %d)...\n", - r, G, - Kr*3, - ulsch_harq->Qm, - ulsch_harq->Nl, r_offset); -#endif - start_meas(&eNB->ulsch_rate_unmatching_stats); - #ifdef FS6 - if ( getenv("fs6") != NULL && strncasecmp( getenv("fs6"), "du", 2) == 0 ) { - int Gp=G/ulsch_harq->Qm; - int GpmodC = Gp%ulsch_harq->C; - - if (r < (ulsch_harq->C-(GpmodC))) - E = ulsch_harq->Qm * (Gp/ulsch_harq->C); - else - E = ulsch_harq->Qm * ((GpmodC==0?0:1) + (Gp/ulsch_harq->C)); - sendFs6Ul(eNB, UE_id, harq_pid, r, ulsch_harq->e+r_offset, E*sizeof(int16_t), r_offset); - - r_offset += E; - continue; - } - - #endif - - if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r], + start_meas(&eNB->ulsch_deinterleaving_stats); + unsigned int E; + if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r], G, ulsch_harq->w[r], - (uint8_t *) &dummy_w[r][0], - ulsch_harq->e+r_offset, + (uint8_t *) &dummy_w[0], + ulsch_harq->e+rdata->r_offset, ulsch_harq->C, NSOFT, 0, //Uplink @@ -290,157 +244,131 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) r, &E)==-1) { LOG_E(PHY,"ulsch_decoding.c: Problem in rate matching\n"); - return(-1); + return; + } + stop_meas(&eNB->ulsch_rate_unmatching_stats); + int max_Ncb = 3*ulsch_harq->RTC[r]*32 ; + + if(ulsch_harq->repetition_number == 1) { + memset(ulsch_harq->pusch_rep_buffer[r],0,(sizeof(int32_t)*3*(6144+64))) ; // reset the buffer every new repetitions + } + if(ulsch_harq->total_number_of_repetitions > 1) { + if (ulsch_harq->rvidx==1) { + LOG_E(PHY,"Adding HARQ data for segment: %d\n", r); + // Store the result of HARQ combining in the last emtc repetitions of sequence 0,2,3,1 + for (int nn=0; nnpusch_rep_buffer[r][nn] += ulsch_harq->w[r][nn] ; } - stop_meas(&eNB->ulsch_rate_unmatching_stats); - max_Ncb = 3*ulsch_harq->RTC[r]*32 ; - - if(ulsch_harq->total_number_of_repetitions > 1) { - if (ulsch_harq->rvidx==1) { - // Store the result of HARQ combining in the last emtc repetitions of sequence 0,2,3,1 - for (int nn=0; nnw[r][nn] ; - } - } - - if (ulsch_harq->repetition_number == ulsch_harq->total_number_of_repetitions) { - for (int nn=0; nnw[r][nn] = pusch_rep_buffer[nn] ; - } - } - } - - r_offset += E; - start_meas(&eNB->ulsch_deinterleaving_stats); - #if 0 - start_meas(&eNB->ulsch_deinterleaving_stats); - req=createRequest(DECODE,sizeof(turboDecode_t)); - req->startUELoop=eNB->proc.threadPool.startProcessingUE; - union turboReqUnion id= {.s={eNB->ulsch[UE_id]->rnti,frame,subframe,r,0}}; - req->id= id.p; - turboDecode_t * rdata=(turboDecode_t *) req->data; - #endif - sub_block_deinterleaving_turbo(4+Kr, - &ulsch_harq->d[r][96], - ulsch_harq->w[r]); - stop_meas(&eNB->ulsch_deinterleaving_stats); - - if (ulsch_harq->C == 1) - crc_type = CRC24_A; - else - crc_type = CRC24_B; - #if 0 - rdata->frame=frame; - rdata->subframe=subframe; - rdata->UEid=UE_id; - rdata->harq_pid=harq_pid; - rdata->Kr=Kr; - rdata->maxIterations=eNB->ulsch[UE_id]->max_turbo_iterations; - rdata->ulsch_harq=ulsch_harq; - rdata->eNB=eNB; - rdata->nbSegments=ulsch_harq->C; - rdata->segment_r=r; - rdata->Fbits=(r==0) ? ulsch_harq->F : 0; - rdata->offset=offset; - rdata->function=td; - int Fbytes=rdata->Fbits>>3; - int blockSize=Kr_bytes - Fbytes - (rdata->nbSegments>1?3:0); - if ( eNB->proc.threadPool.activated) { - add_request(req, &eNB->proc.threadPool); - req=NULL; - } else { - req->startProcessingTime=rdtsc(); - rdata->decodeIterations = td( rdata->soft_bits+96, - rdata->decoded_bytes, - rdata->Kr, - f1f2mat_old[rdata->iind*2], - f1f2mat_old[(rdata->iind*2)+1], - rdata->maxIterations, - rdata->nbSegments == 1 ? CRC24_A: CRC24_B, - rdata->Fbits, - &eNB->ulsch_tc_init_stats, - &eNB->ulsch_tc_alpha_stats, - &eNB->ulsch_tc_beta_stats, - &eNB->ulsch_tc_gamma_stats, - &eNB->ulsch_tc_ext_stats, - &eNB->ulsch_tc_intl1_stats, - &eNB->ulsch_tc_intl2_stats); - - stop_meas(&eNB->ulsch_turbo_decoding_stats); - req->returnTime=req->endProcessingTime=rdtsc(); - req->decodeIterations=rdata->decodeIterations; - req->coreId=0; - req->processedBy[0]=0; - req->next=eNB->proc.threadPool.doneRequests; - eNB->proc.threadPool.doneRequests=req; - - if (rdata->decodeIterations > eNB->ulsch[UE_id]->max_turbo_iterations ) - // Entire TPU need retransmission - break; - } -offset += blockSize; - eNB->proc.threadPool.startProcessingUE=rdtsc(); - #endif - start_meas(&eNB->ulsch_turbo_decoding_stats); - ret = tc(&ulsch_harq->d[r][96], - NULL, - ulsch_harq->c[r], - NULL, - Kr, - ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS, - crc_type, - (r==0) ? ulsch_harq->F : 0, - &eNB->ulsch_tc_init_stats, - &eNB->ulsch_tc_alpha_stats, - &eNB->ulsch_tc_beta_stats, - &eNB->ulsch_tc_gamma_stats, - &eNB->ulsch_tc_ext_stats, - &eNB->ulsch_tc_intl1_stats, - &eNB->ulsch_tc_intl2_stats); - stop_meas(&eNB->ulsch_turbo_decoding_stats); - LOG_D(PHY,"turbo decode in %d iter\n",ret); - - // Reassembly of Transport block here - - if (ret != (1+ulsch->max_turbo_iterations)) { - if (rCminus) - Kr = ulsch_harq->Kminus; - else - Kr = ulsch_harq->Kplus; - - Kr_bytes = Kr>>3; - - if (r==0) { - memcpy(ulsch_harq->b, - &ulsch_harq->c[0][(ulsch_harq->F>>3)], - Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0)); - offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0); - } else { - memcpy(ulsch_harq->b+offset, - ulsch_harq->c[r], - Kr_bytes - ((ulsch_harq->C>1)?3:0)); - offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0)); - } - } else { - break; + if (ulsch_harq->repetition_number == ulsch_harq->total_number_of_repetitions) { + LOG_E(PHY,"Will use HARQ data sum up for segment: %d\n", r); + for (int nn=0; nnw[r][nn] = ulsch_harq->pusch_rep_buffer[r][nn] ; } } + int16_t soft_bits[3*8*6144+12+96] __attribute__((aligned(32))); + sub_block_deinterleaving_turbo(4+rdata->Kr, + soft_bits+96, + ulsch_harq->w[r]); + stop_meas(&eNB->ulsch_deinterleaving_stats); + rdata->decodeIterations = rdata->function( soft_bits+96, + NULL, + rdata->decoded_bytes, + NULL, + rdata->Kr, + rdata->maxIterations, + rdata->nbSegments == 1 ? CRC24_A: CRC24_B, + rdata->Fbits, + &eNB->ulsch_tc_init_stats, + &eNB->ulsch_tc_alpha_stats, + &eNB->ulsch_tc_beta_stats, + &eNB->ulsch_tc_gamma_stats, + &eNB->ulsch_tc_ext_stats, + &eNB->ulsch_tc_intl1_stats, + &eNB->ulsch_tc_intl2_stats); + stop_meas(&eNB->ulsch_turbo_decoding_stats); + +} +int ulsch_decoding_data(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, + int UE_id,int harq_pid,int llr8_flag) { + unsigned int r_offset=0; + int offset = 0; + LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id]; + LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid]; + int G = ulsch_harq->G; + unsigned int E; + int ret=0; + + decoder_if_t * td=llr8_flag == 0 ? + *decoder16 : *decoder8; + ulsch_harq->processedSegments=0; + + for (int r=0; rC; r++) { + // printf("before subblock deinterleaving c[%d] = %p\n",r,ulsch_harq->c[r]); + // Get Turbo interleaver parameters + unsigned int Kr= rCminus ? + ulsch_harq->Kminus :ulsch_harq->Kplus; + unsigned int Kr_bytes = Kr>>3; + +#ifdef DEBUG_ULSCH_DECODING + printf("Rate Matching Segment %u (coded bits (G) %d,unpunctured/repeated bits %u, Q_m %d, Nl %d, r_offset %d)...\n", + r, G, + Kr*3, + ulsch_harq->Qm, + ulsch_harq->Nl, r_offset); +#endif + int Gp=G/ulsch_harq->Qm; + int GpmodC = Gp%ulsch_harq->C; + + if (r < (ulsch_harq->C-(GpmodC))) + E = ulsch_harq->Qm * (Gp/ulsch_harq->C); + else + E = ulsch_harq->Qm * ((GpmodC==0?0:1) + (Gp/ulsch_harq->C)); +#ifdef FS6 + if ( getenv("fs6") != NULL && strncasecmp( getenv("fs6"), "du", 2) == 0 ) { + + sendFs6Ul(eNB, UE_id, harq_pid, r, ulsch_harq->e+r_offset, E*sizeof(int16_t), r_offset); + + r_offset += E; + continue; + } + +#endif + + union turboReqUnion id= {.s={ulsch->rnti,proc->frame_rx,proc->subframe_rx,0,0}}; + notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(turboDecode_t), id.p, &proc->respDecode, processULSegment); + turboDecode_t * rdata=(turboDecode_t *) NotifiedFifoData(req); + + rdata->eNB=eNB; + rdata->frame=proc->frame_rx; + rdata->subframe=proc->subframe_rx; + rdata->UEid=UE_id; + rdata->harq_pid=harq_pid; + rdata->Kr=Kr; + rdata->maxIterations=eNB->ulsch[UE_id]->max_turbo_iterations; + rdata->ulsch_harq=ulsch_harq; + rdata->eNB=eNB; + rdata->nbSegments=ulsch_harq->C; + rdata->segment_r=r; + rdata->Fbits=(r==0) ? ulsch_harq->F : 0; + rdata->r_offset=r_offset; + rdata->offset=offset; + rdata->function=td; + int Fbytes=(r==0) ? rdata->Fbits>>3 : 0; + int sz=Kr_bytes - Fbytes - ((ulsch_harq->C>1)?3:0); + pushTpool(&proc->threadPool,req); + proc->nbDecode++; + LOG_D(PHY,"Added a block to decode, in pipe: %d\n",proc->nbDecode); + r_offset+=E; + offset+=sz; + } return(ret); } -int ulsch_decoding_data_all(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) { - int ret = 0; - /*if(get_thread_worker_conf() == WORKER_ENABLE) - { - ret = ulsch_decoding_data_2thread(eNB,UE_id,harq_pid,llr8_flag); - } - else*/ - { - ret = ulsch_decoding_data(eNB,UE_id,harq_pid,llr8_flag); - } - return ret; +int ulsch_decoding_data_all(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, + int UE_id,int harq_pid,int llr8_flag) { + return ulsch_decoding_data(eNB,proc,UE_id,harq_pid,llr8_flag); } static inline unsigned int lte_gold_unscram(unsigned int *x1, unsigned int *x2, unsigned char reset) __attribute__((always_inline)); @@ -1158,7 +1086,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, LOG_D(PHY,"frame %d subframe %d O_ACK:%d o_ACK[]=%d:%d:%d:%d\n",frame,subframe,ulsch_harq->O_ACK,ulsch_harq->o_ACK[0],ulsch_harq->o_ACK[1],ulsch_harq->o_ACK[2],ulsch_harq->o_ACK[3]); // Do ULSCH Decoding for data portion - ret = ulsch_decoding_data_all(eNB,UE_id,harq_pid,llr8_flag); + ret = ulsch_decoding_data_all(eNB,proc, UE_id,harq_pid,llr8_flag); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING0+harq_pid,0); return(ret); } diff --git a/openair1/PHY/defs_eNB.h b/openair1/PHY/defs_eNB.h index 718ede5715..51b2e9c4ae 100644 --- a/openair1/PHY/defs_eNB.h +++ b/openair1/PHY/defs_eNB.h @@ -871,20 +871,19 @@ union turboReqUnion { }; typedef struct TurboDecode_s { - decoder_if_t *function; - int16_t soft_bits[3*8*6144+12+96] __attribute__((aligned(32))); - uint8_t decoded_bytes[3+768] __attribute__((aligned(32))); + PHY_VARS_eNB *eNB; + decoder_if_t *function; + uint8_t decoded_bytes[3+1768] __attribute__((aligned(32))); int UEid; int harq_pid; int frame; int subframe; - int iind; int Fbits; int Kr; LTE_UL_eNB_HARQ_t *ulsch_harq; - PHY_VARS_eNB *eNB; int nbSegments; int segment_r; + int r_offset; int offset; int maxIterations; int decodeIterations; diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 94689ed246..2b032c208a 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -310,7 +310,7 @@ bool dlsch_procedures(PHY_VARS_eNB *eNB, if ( proc->threadPool.activated ) { // Wait all other threads finish to process while (proc->nbEncode) { - pullTpool(&proc->respEncode, &proc->threadPool); + delNotifiedFIFO_elt(pullTpool(&proc->respEncode, &proc->threadPool)); proc->nbEncode--; } } @@ -1165,86 +1165,92 @@ uci_procedures(PHY_VARS_eNB *eNB, } // end loop for (int i = 0; i < NUMBER_OF_UE_MAX; i++) { } -#if 0 -void post_decode(request_t* decodeResult) { - turboDecode_t * rdata=(turboDecode_t *) decodeResult->data; - LTE_eNB_ULSCH_t *ulsch = rdata->eNB->ulsch[rdata->UEid]; - LTE_UL_eNB_HARQ_t *ulsch_harq = rdata->ulsch_harq; - PHY_VARS_eNB *eNB=rdata->eNB; - bool decodeSucess=rdata->decodeIterations <= rdata->maxIterations; - ulsch_harq->processedSegments++; - if (decodeSucess) { - int Fbytes=rdata->Fbits>>3; - int Kr=rdata->segment_r < ulsch_harq->Cminus? - ulsch_harq->Kminus: - ulsch_harq->Kplus; - int Kr_bytes = Kr>>3; - int blockSize=Kr_bytes - Fbytes - (rdata->nbSegments>1?3:0); - memcpy(ulsch_harq->b+rdata->offset, - rdata->decoded_bytes+Fbytes, - blockSize); +void postDecode(L1_rxtx_proc_t *proc, notifiedFIFO_elt_t *req) { + turboDecode_t * rdata=(turboDecode_t *) NotifiedFifoData(req); - } else { - if (rdata->nbSegments > 1 ) { - // Purge pending decoding of the same TDU - union turboReqUnion idInFailure= {.p=decodeResult->id}; - rnti_t rntiInFailure=idInFailure.s.rnti; - tpool_t * tp=&proc->threadPool; - mutexlock(tp->lockRequests); - request_t* pending=NULL; - while ( (pending=searchRNTI(tp, rntiInFailure)) != NULL) { - LOG_W(MAC,"removing a CB belonging to a bad TPU"); - freeRequest(pending); - mutexlock(tp->lockReportDone); - tp->notFinishedJobs--; - mutexunlock(tp->lockReportDone); - } - mutexunlock(tp->lockRequests); - } + LTE_eNB_ULSCH_t *ulsch = rdata->eNB->ulsch[rdata->UEid]; + LTE_UL_eNB_HARQ_t *ulsch_harq = rdata->ulsch_harq; + PHY_VARS_eNB *eNB=rdata->eNB; + + bool decodeSucess=rdata->decodeIterations <= rdata->maxIterations; + ulsch_harq->processedSegments++; + LOG_D(PHY, "processing result of segment: %d, ue %d, processed %d/%d\n", + rdata->segment_r, rdata->UEid, ulsch_harq->processedSegments, rdata->nbSegments); + proc->nbDecode--; + LOG_D(PHY,"remain to decoded in subframe: %d\n", proc->nbDecode); + if (decodeSucess) { + int Fbytes=(rdata->segment_r==0) ? rdata->Fbits>>3 : 0; + int sz=(rdata->Kr>>3) - Fbytes - ((ulsch_harq->C>1)?3:0); + memcpy(ulsch_harq->b+rdata->offset, + rdata->decoded_bytes+Fbytes, + sz); + } else { + if ( rdata->nbSegments != ulsch_harq->processedSegments ) { + int nb=abortTpool(&proc->threadPool, req->key); + printf("nb1:%d\n", nb); + nb+=abortNotifiedFIFO(&proc->respDecode, req->key); + printf("nb2:%d\n", nb); + proc->nbDecode-=nb; + LOG_I(PHY,"uplink segment error %d/%d, aborted %d segments",rdata->segment_r,rdata->nbSegments, nb); + AssertFatal(ulsch_harq->processedSegments+nb == rdata->nbSegments,"processed: %d, aborted: %d, total %d\n", + ulsch_harq->processedSegments, nb, rdata->nbSegments); + ulsch_harq->processedSegments=rdata->nbSegments; } + } - // Check if TDU is complete: either we have all blocks in success - // either at least one block can't be decoded - // Maybe we receive decoded block alter a first failure, - // so we protect ourselves against multiple executions - if ( (rdata->nbSegments == ulsch_harq->processedSegments || decodeSucess==false) && - ulsch_harq->processedBadSegment == 0 ) { - //compute the expected ULSCH RX power (for the stats) - ulsch_harq->delta_TF = get_hundred_times_delta_IF_eNB(eNB,rdata->UEid,rdata->harq_pid, 0); // 0 means bw_factor is not considered - - if (ulsch_harq->cqi_crc_status == 1) - fill_ulsch_cqi_indication(eNB,rdata->frame,rdata->subframe, - ulsch_harq, - ulsch->rnti); - - fill_crc_indication(eNB,rdata->UEid,rdata->frame,rdata->subframe,decodeSucess?0:1); // indicate result to MAC - fill_rx_indication(eNB,rdata->UEid,rdata->frame,rdata->subframe); // indicate SDU to MAC - - if (!decodeSucess) { - ulsch_harq->processedBadSegment =1; - if (ulsch_harq->round >= 3) { - ulsch_harq->status = SCH_IDLE; - ulsch_harq->handled = 0; - ulsch->harq_mask &= ~(1 << rdata->harq_pid); - ulsch_harq->round = 0; - } - - /* Mark the HARQ process to release it later if max transmission reached - * (see below). - * MAC does not send the max transmission count, we have to deal with it - * locally in PHY. - */ - ulsch_harq->handled = 1; - } else { - ulsch_harq->status = SCH_IDLE; - ulsch->harq_mask &= ~(1 << rdata->harq_pid); - } // ulsch not in error - - if (ulsch_harq->O_ACK>0) - fill_ulsch_harq_indication(eNB,ulsch_harq,ulsch->rnti,rdata->frame,rdata->subframe,ulsch->bundling); - } + // if this UE segments are all done + if ( rdata->nbSegments == ulsch_harq->processedSegments) { + //compute the expected ULSCH RX power (for the stats) + int i=rdata->UEid; + ulsch_harq->delta_TF = get_hundred_times_delta_IF_eNB(eNB,i,rdata->harq_pid, 0); // 0 means bw_factor is not considered + if (RC.mac != NULL) { /* ulsim does not use RC.mac context. */ + if (ulsch_harq->cqi_crc_status == 1) { + fill_ulsch_cqi_indication(eNB,rdata->frame,rdata->subframe,ulsch_harq,ulsch->rnti); + RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_flag &= (~(1 << rdata->subframe)); + } else { + if(RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_flag & (1 << rdata->subframe) ) { + RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_flag &= (~(1 << rdata->subframe)); + RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_timer=30; + LOG_D(PHY,"Frame %d,Subframe %d, We're supposed to get a cqi here. Set cqi_req_timer to 30.\n",rdata->frame,rdata->subframe); + } + } + } + + if (!decodeSucess) { + fill_crc_indication(eNB,i,rdata->frame,rdata->subframe,1); // indicate NAK to MAC + fill_rx_indication(eNB,i,rdata->frame,rdata->subframe); // indicate SDU to MAC + LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d Error receiving ULSCH, round %d/%d (ACK %d,%d)\n", + eNB->Mod_id,rdata->harq_pid, + rdata->frame,rdata->subframe, i, + ulsch_harq->round, + ulsch->Mlimit, + ulsch_harq->o_ACK[0], + ulsch_harq->o_ACK[1]); + + if (ulsch_harq->round >= 3) { + ulsch_harq->status = SCH_IDLE; + ulsch_harq->handled = 0; + ulsch->harq_mask &= ~(1 << rdata->harq_pid); + ulsch_harq->round = 0; + } + /* Mark the HARQ process to release it later if max transmission reached + * (see below). + * MAC does not send the max transmission count, we have to deal with it + * locally in PHY. + */ + ulsch_harq->handled = 1; + } // ulsch in error + else if(ulsch_harq->repetition_number == ulsch_harq->total_number_of_repetitions){ + fill_crc_indication(eNB,i,rdata->frame,rdata->subframe,0); // indicate ACK to MAC + fill_rx_indication(eNB,i,rdata->frame,rdata->subframe); // indicate SDU to MAC + ulsch_harq->status = SCH_IDLE; + ulsch->harq_mask &= ~(1 << rdata->harq_pid); + } // ulsch not in error + + if (ulsch_harq->O_ACK>0) + fill_ulsch_harq_indication(eNB,ulsch_harq,ulsch->rnti,rdata->frame,rdata->subframe,ulsch->bundling); + } } -#endif void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { uint32_t ret=0,i; @@ -1316,121 +1322,7 @@ void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { ulsch_harq->V_UL_DAI, ulsch_harq->nb_rb>20 ? 1 : 0); stop_meas(&eNB->ulsch_decoding_stats); - LOG_D(PHY, - "[eNB %d][PUSCH %d] frame %d subframe %d RNTI %x RX power (%d,%d) N0 (%d,%d) dB ACK (%d,%d), decoding iter %d ulsch_harq->cqi_crc_status:%d ackBits:%d ulsch_decoding_stats[t:%lld max:%lld]\n", - eNB->Mod_id,harq_pid, - frame,subframe, - ulsch->rnti, - dB_fixed(eNB->pusch_vars[i]->ulsch_power[0]), - dB_fixed(eNB->pusch_vars[i]->ulsch_power[1]), - 30,//eNB->measurements.n0_power_dB[0], - 30,//eNB->measurements.n0_power_dB[1], - ulsch_harq->o_ACK[0], - ulsch_harq->o_ACK[1], - ret, - ulsch_harq->cqi_crc_status, - ulsch_harq->O_ACK, - eNB->ulsch_decoding_stats.p_time, eNB->ulsch_decoding_stats.max); - if (ulsch_harq->repetition_number < ulsch_harq->total_number_of_repetitions){ - ulsch_harq->rvidx = rvidx_tab[(ulsch_harq->repetition_number%4)] ; // Set the correct rvidx for the next emtc repetitions - ulsch_harq->repetition_number +=1 ; // Increment repetition_number for the next ULSCH allocation - } - //compute the expected ULSCH RX power (for the stats) - ulsch_harq->delta_TF = get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 0); // 0 means bw_factor is not considered - - if (RC.mac != NULL) { /* ulsim does not use RC.mac context. */ - if (ulsch_harq->cqi_crc_status == 1) { -#ifdef DEBUG_PHY_PROC - //if (((frame%10) == 0) || (frame < 50)) - print_CQI(ulsch_harq->o,ulsch_harq->uci_format,0,fp->N_RB_DL); -#endif - fill_ulsch_cqi_indication(eNB,frame,subframe,ulsch_harq,ulsch->rnti); - RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_flag &= (~(1 << subframe)); - } else { - if(RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_flag & (1 << subframe) ) { - RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_flag &= (~(1 << subframe)); - RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_timer=30; - LOG_D(PHY,"Frame %d,Subframe %d, We're supposed to get a cqi here. Set cqi_req_timer to 30.\n",frame,subframe); - } - } - } - - if (ret == (1+MAX_TURBO_ITERATIONS)) { - T(T_ENB_PHY_ULSCH_UE_NACK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(ulsch->rnti), - T_INT(harq_pid)); - fill_crc_indication(eNB,i,frame,subframe,1); // indicate NAK to MAC - fill_rx_indication(eNB,i,frame,subframe); // indicate SDU to MAC - LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d Error receiving ULSCH, round %d/%d (ACK %d,%d)\n", - eNB->Mod_id,harq_pid, - frame,subframe, i, - ulsch_harq->round, - ulsch->Mlimit, - ulsch_harq->o_ACK[0], - ulsch_harq->o_ACK[1]); - - if (ulsch_harq->round >= 3) { - ulsch_harq->status = SCH_IDLE; - ulsch_harq->handled = 0; - ulsch->harq_mask &= ~(1 << harq_pid); - ulsch_harq->round = 0; - } - - MSC_LOG_RX_DISCARDED_MESSAGE( - MSC_PHY_ENB,MSC_PHY_UE, - NULL,0, - "%05u:%02u ULSCH received rnti %x harq id %u round %d", - frame,subframe, - ulsch->rnti,harq_pid, - ulsch_harq->round-1 - ); - /* Mark the HARQ process to release it later if max transmission reached - * (see below). - * MAC does not send the max transmission count, we have to deal with it - * locally in PHY. - */ - ulsch_harq->handled = 1; - } // ulsch in error - else if(ulsch_harq->repetition_number == ulsch_harq->total_number_of_repetitions){ - fill_crc_indication(eNB,i,frame,subframe,0); // indicate ACK to MAC - fill_rx_indication(eNB,i,frame,subframe); // indicate SDU to MAC - ulsch_harq->status = SCH_IDLE; - ulsch->harq_mask &= ~(1 << harq_pid); - T (T_ENB_PHY_ULSCH_UE_ACK, T_INT (eNB->Mod_id), T_INT (frame), T_INT (subframe), T_INT (ulsch->rnti), T_INT (harq_pid)); - MSC_LOG_RX_MESSAGE( - MSC_PHY_ENB,MSC_PHY_UE, - NULL,0, - "%05u:%02u ULSCH received rnti %x harq id %u", - frame,subframe, - ulsch->rnti,harq_pid - ); -#ifdef DEBUG_PHY_PROC -#ifdef DEBUG_ULSCH - LOG_D(PHY,"[eNB] Frame %d, Subframe %d : ULSCH SDU (RX harq_pid %d) %d bytes:",frame,subframe, - harq_pid,ulsch_harq->TBS>>3); - - for (j=0; jTBS>>3; j++) - LOG_T(PHY,"%x.",ulsch->harq_processes[harq_pid]->b[j]); - - LOG_T(PHY,"\n"); -#endif -#endif - } // ulsch not in error - - if (ulsch_harq->O_ACK>0) fill_ulsch_harq_indication(eNB,ulsch_harq,ulsch->rnti,frame,subframe,ulsch->bundling); - - LOG_D(PHY,"[eNB %d] Frame %d subframe %d: received ULSCH harq_pid %d for UE %d, ret = %d, CQI CRC Status %d, ACK %d,%d, ulsch_errors %d/%d\n", - eNB->Mod_id,frame,subframe, - harq_pid, - i, - ret, - ulsch_harq->cqi_crc_status, - ulsch_harq->o_ACK[0], - ulsch_harq->o_ACK[1], - eNB->UE_stats[i].ulsch_errors[harq_pid], - eNB->UE_stats[i].ulsch_decoding_attempts[harq_pid][0]); - } // if ((ulsch) && - // (ulsch->rnti>0) && - // (ulsch_harq->status == ACTIVE)) + } else if ((ulsch) && (ulsch->rnti>0) && (ulsch_harq->status == ACTIVE) && @@ -1444,56 +1336,17 @@ void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { LOG_W (PHY, "Removing stale ULSCH config for UE %x harq_pid %d (harq_mask is now 0x%2.2x)\n", ulsch->rnti, harq_pid, ulsch->harq_mask); } } // for (i=0; ithreadPool.activated ) { - // Wait all other threads finish to process - //printf("%s:%d:%d\n", __FILE__,__LINE__,eNB->proc->threadPool.notFinishedJobs); - int rr=0; - mutexlock(proc->threadPool.lockReportDone); - while ( proc->threadPool.notFinishedJobs > 0 ) { - //printf("%s:%d:%d\n", __FILE__,__LINE__,eNB->proc->threadPool.notFinishedJobs); - struct timespec t; - clock_gettime(CLOCK_REALTIME,&t); - t.tv_nsec+=1*1000*1000; - if ( t.tv_nsec >= 1000*1000*1000 ) { - t.tv_nsec -= 1000*1000*1000; - t.tv_sec++; - } - if ((rr=pthread_cond_timedwait(&proc->threadPool.notifDone,&proc.threadPool.lockReportDone, &t))!=0) { - LOG_E(PHY,"timedwait1:%s,%p,%p,%p,%d\n", rr==ETIMEDOUT?"ETIMEDOUT":"other", - proc->threadPool.oldestRequests, - proc->threadPool.newestRequests, - proc->threadPool.doneRequests, - proc->threadPool.notFinishedJobs); - proc->threadPool.oldestRequests=NULL; - proc->threadPool.newestRequests=NULL; - proc->threadPool.doneRequests=NULL; - proc->threadPool.notFinishedJobs=0; - } - } - mutexunlock(proc->threadPool.lockReportDone); - } - - request_t* tmp; - while ((tmp=proc->threadPool.doneRequests)!=NULL) { - turboDecode_t * rdata=(turboDecode_t *) tmp->data; - tmp->decodeIterations=rdata->decodeIterations; - post_decode(tmp); - tmp->returnTime=rdtsc(); - tmp->cumulSubframe=tmp->returnTime-startTime; - // Ignore write error (if no trace listner) - if (write(proc->threadPool.traceFd, tmp, sizeof(request_t)- 2*sizeof(void*))) {}; - proc->threadPool.doneRequests=tmp->next; - freeRequest(tmp); - } - #endif + + while (proc->nbDecode > 0) { + notifiedFIFO_elt_t *req=pullTpool(&proc->respDecode, &proc->threadPool); + postDecode(proc, req); + delNotifiedFIFO_elt(req); + } } + extern int oai_exit; -extern void *td_thread (void *); - -extern void *te_thread (void *); void fill_rx_indication(PHY_VARS_eNB *eNB,int UE_id,int frame,int subframe) { nfapi_rx_indication_pdu_t *pdu; From aa10676e900746c0cfe745ee0948971ba47ce2fc Mon Sep 17 00:00:00 2001 From: laurent Date: Thu, 31 Oct 2019 17:48:31 +0100 Subject: [PATCH 058/240] parallel UL, split mode --- executables/main-fs6.c | 102 ++---------------------------------- executables/split_headers.h | 1 + 2 files changed, 6 insertions(+), 97 deletions(-) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index f2c95f86d4..15108b0e45 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -618,103 +618,6 @@ void pusch_procedures_fromsplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB * int ret = ulsch_decoding_data(eNB, proc, i, harq_pid, ulsch_harq->nb_rb>20 ? 1 : 0); stop_meas(&eNB->ulsch_decoding_stats); - LOG_D(PHY, - "[eNB %d][PUSCH %d] frame %d subframe %d RNTI %x RX power (%d,%d) N0 (%d,%d) dB ACK (%d,%d), decoding iter %d ulsch_harq->cqi_crc_status:%d ackBits:%d ulsch_decoding_stats[t:%lld max:%lld]\n", - eNB->Mod_id,harq_pid, - frame,subframe, - ulsch->rnti, - dB_fixed(eNB->pusch_vars[i]->ulsch_power[0]), - dB_fixed(eNB->pusch_vars[i]->ulsch_power[1]), - 30,//eNB->measurements.n0_power_dB[0], - 30,//eNB->measurements.n0_power_dB[1], - ulsch_harq->o_ACK[0], - ulsch_harq->o_ACK[1], - ret, - ulsch_harq->cqi_crc_status, - ulsch_harq->O_ACK, - eNB->ulsch_decoding_stats.p_time, eNB->ulsch_decoding_stats.max); - //compute the expected ULSCH RX power (for the stats) - ulsch_harq->delta_TF = get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 0); // 0 means bw_factor is not considered - - if (RC.mac != NULL) { /* ulsim does not use RC.mac context. */ - if (ulsch_harq->cqi_crc_status == 1) { -#ifdef DEBUG_PHY_PROC - //if (((frame%10) == 0) || (frame < 50)) - print_CQI(ulsch_harq->o,ulsch_harq->uci_format,0,fp->N_RB_DL); -#endif - fill_ulsch_cqi_indication(eNB,frame,subframe,ulsch_harq,ulsch->rnti); - RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_flag &= (~(1 << subframe)); - } else { - if(RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_flag & (1 << subframe) ) { - RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_flag &= (~(1 << subframe)); - RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_timer=30; - LOG_D(PHY,"Frame %d,Subframe %d, We're supposed to get a cqi here. Set cqi_req_timer to 30.\n",frame,subframe); - } - } - } - - if (ret == (1+MAX_TURBO_ITERATIONS)) { - T(T_ENB_PHY_ULSCH_UE_NACK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(ulsch->rnti), - T_INT(harq_pid)); - fill_crc_indication(eNB,i,frame,subframe,1); // indicate NAK to MAC - fill_rx_indication_from_split(bufferZone, eNB,i,frame,subframe, ul_propa); // indicate SDU to MAC - LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d Error receiving ULSCH, round %d/%d (ACK %d,%d)\n", - eNB->Mod_id,harq_pid, - frame,subframe, i, - ulsch_harq->round, - ulsch->Mlimit, - ulsch_harq->o_ACK[0], - ulsch_harq->o_ACK[1]); - - if (ulsch_harq->round >= 3) { - ulsch_harq->status = SCH_IDLE; - ulsch_harq->handled = 0; - ulsch->harq_mask &= ~(1 << harq_pid); - ulsch_harq->round = 0; - } - - MSC_LOG_RX_DISCARDED_MESSAGE( - MSC_PHY_ENB,MSC_PHY_UE, - NULL,0, - "%05u:%02u ULSCH received rnti %x harq id %u round %d", - frame,subframe, - ulsch->rnti,harq_pid, - ulsch_harq->round-1 - ); - /* Mark the HARQ process to release it later if max transmission reached - * (see below). - * MAC does not send the max transmission count, we have to deal with it - * locally in PHY. - */ - ulsch_harq->handled = 1; - } // ulsch in error - else { - fill_crc_indication(eNB,i,frame,subframe,0); // indicate ACK to MAC - fill_rx_indication_from_split(bufferZone, eNB,i,frame,subframe, ul_propa); // indicate SDU to MAC - ulsch_harq->status = SCH_IDLE; - ulsch->harq_mask &= ~(1 << harq_pid); - T (T_ENB_PHY_ULSCH_UE_ACK, T_INT (eNB->Mod_id), T_INT (frame), T_INT (subframe), T_INT (ulsch->rnti), T_INT (harq_pid)); - MSC_LOG_RX_MESSAGE( - MSC_PHY_ENB,MSC_PHY_UE, - NULL,0, - "%05u:%02u ULSCH received rnti %x harq id %u", - frame,subframe, - ulsch->rnti,harq_pid - ); - } // ulsch not in error - - if (ulsch_harq->O_ACK>0) fill_ulsch_harq_indication(eNB,ulsch_harq,ulsch->rnti,frame,subframe,ulsch->bundling); - - LOG_D(PHY,"[eNB %d] Frame %d subframe %d: received ULSCH harq_pid %d for UE %d, ret = %d, CQI CRC Status %d, ACK %d,%d, ulsch_errors %d/%d\n", - eNB->Mod_id,frame,subframe, - harq_pid, - i, - ret, - ulsch_harq->cqi_crc_status, - ulsch_harq->o_ACK[0], - ulsch_harq->o_ACK[1], - eNB->UE_stats[i].ulsch_errors[harq_pid], - eNB->UE_stats[i].ulsch_decoding_attempts[harq_pid][0]); } // if ((ulsch) && // (ulsch->rnti>0) && // (ulsch_harq->status == ACTIVE)) @@ -731,6 +634,11 @@ void pusch_procedures_fromsplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB * LOG_W (PHY, "Removing stale ULSCH config for UE %x harq_pid %d (harq_mask is now 0x%2.2x)\n", ulsch->rnti, harq_pid, ulsch->harq_mask); } } // for (i=0; inbDecode > 0) { + notifiedFIFO_elt_t *req=pullTpool(&proc->respDecode, &proc->threadPool); + postDecode(proc, req); + delNotifiedFIFO_elt(req); + } } void recvFs6Ul(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, ul_propagation_t *ul_propa) { diff --git a/executables/split_headers.h b/executables/split_headers.h index 1849efffc7..b013617cfd 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -247,6 +247,7 @@ bool dlsch_procedures(PHY_VARS_eNB *eNB, int harq_pid, LTE_eNB_DLSCH_t *dlsch, LTE_eNB_UE_stats *ue_stats) ; +void postDecode(L1_rxtx_proc_t *proc, notifiedFIFO_elt_t *req); void pdsch_procedures(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int harq_pid, From 3ce5d400648335209992ef145d6c6aa832b33883 Mon Sep 17 00:00:00 2001 From: laurent Date: Thu, 31 Oct 2019 20:49:42 +0100 Subject: [PATCH 059/240] add comments in data structures, gcc warnings fixed --- executables/main-fs6.c | 2 +- executables/main-ocp.c | 7 ++--- executables/split_headers.h | 36 +++++++++++++++-------- openair1/SCHED/phy_procedures_lte_eNb.c | 9 ++---- openair2/LAYER2/MAC/eNB_scheduler_ulsch.c | 5 ++-- 5 files changed, 33 insertions(+), 26 deletions(-) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index 15108b0e45..f4ea039073 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -615,7 +615,7 @@ void pusch_procedures_fromsplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB * &ulsch_harq->Kplus, &ulsch_harq->Kminus, &ulsch_harq->F); - int ret = ulsch_decoding_data(eNB, proc, i, harq_pid, + ulsch_decoding_data(eNB, proc, i, harq_pid, ulsch_harq->nb_rb>20 ? 1 : 0); stop_meas(&eNB->ulsch_decoding_stats); } // if ((ulsch) && diff --git a/executables/main-ocp.c b/executables/main-ocp.c index 4e657e6d28..3fe1334228 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -623,8 +623,7 @@ void rx_rf(RU_t *ru, L1_rxtx_proc_t *proc) { setAllfromTS(timestamp_rx, proc); } -int tx_rf(RU_t *ru, L1_rxtx_proc_t *proc) { - int ret=0; +void tx_rf(RU_t *ru, L1_rxtx_proc_t *proc) { LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; void *txp[ru->nb_tx]; int i; @@ -672,7 +671,7 @@ int tx_rf(RU_t *ru, L1_rxtx_proc_t *proc) { /* add fail safe for late command end */ // prepare tx buffer pointers - ret=ru->rfdevice.trx_write_func(&ru->rfdevice, + ru->rfdevice.trx_write_func(&ru->rfdevice, proc->timestamp_tx+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension, txp, siglen+sf_extension, @@ -682,7 +681,7 @@ int tx_rf(RU_t *ru, L1_rxtx_proc_t *proc) { (long long unsigned int)proc->timestamp_tx,proc->frame_tx,proc->subframe_tx); } - return ret; + return; } static void *ru_thread( void *param ) { diff --git a/executables/split_headers.h b/executables/split_headers.h index b013617cfd..a0c540e42f 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -13,10 +13,9 @@ #define MTU 65536 #define UDP_TIMEOUT 900000L // in micro second (struct timeval, NOT struct timespec) // linux may timeout for a much longer time (up to 10ms) -#define MAX_BLOCKS 16 -#define blockAlign 32 //bytes - +#define blockAlign 32 //bytes to align memory for SIMD copy (256 bits vectors) +// FS6 transport configuration and handler typedef struct { char *sourceIP; char *sourcePort; @@ -29,6 +28,8 @@ typedef struct { #define CTsentCUv0 0xA500 #define CTsentDUv0 0x5A00 +// Main FS6 transport layer header +// All packets starts with this header typedef struct commonUDP_s { uint64_t timestamp; // id of the group (subframe for LTE) uint16_t nbBlocks; // total number of blocks for this timestamp @@ -37,14 +38,8 @@ typedef struct commonUDP_s { uint16_t contentBytes; // will be sent in a UDP packet, so must be < 2^16 bytes } commonUDP_t; -typedef struct frequency_s { - int frame; - int subframe; - int sampleSize; - int nbAnt; - int nbSamples; -} frequency_t; - +// FS6 UL common header (DU to CU) +// gives the RACH detection data and is always sent to inform the CU that a subframe arrived typedef struct { uint16_t max_preamble[4]; uint16_t max_preamble_energy[4]; @@ -52,6 +47,8 @@ typedef struct { uint16_t avg_preamble_energy[4]; } fs6_ul_t; +// FS6 DL common header (CU to DU) +// gives the DCI configuration from each subframe typedef struct { uint8_t pbch_pdu[4]; int num_pdcch_symbols; @@ -62,6 +59,9 @@ typedef struct { LTE_eNB_PHICH phich_vars; } fs6_dl_t; +// a value to type all sub packets, +// to detect errors, and to be able to extend to other versions +// the first byte of each sub structure should match one of these values enum pckType { fs6UlConfig=25, fs6DlConfig=26, @@ -72,6 +72,8 @@ enum pckType { fs6ULindicationSr=41, }; +// CU to DU definition of a future UL subframe decode +// defines a UE future data plane typedef struct { enum pckType type:8; uint16_t UE_id; @@ -136,6 +138,8 @@ typedef struct { uint16_t cba_rnti[4];//NUM_MAX_CBA_GROUP]; } fs6_dl_ulsched_t; +// CU to DU defintion of a DL packet for a given UE +// The data itself is padded at the end of this structure typedef struct { enum pckType type:8; int UE_id; @@ -150,24 +154,28 @@ typedef struct { uint8_t pdsch_start; uint8_t sib1_br_flag; uint16_t i0; - uint32_t rb_alloc[4];; + uint32_t rb_alloc[4]; int dataLen; } fs6_dl_uespec_t; +// CU to DU definition of CCH channel typedef struct { int16_t UE_id; LTE_eNB_UCI cch_vars; } fs6_dl_uespec_ulcch_element_t; +// header to group all UE CCH channels definitions in one UDP packet typedef struct { enum pckType type:8; int16_t nb_active_ue; } fs6_dl_uespec_ulcch_t; +// code internal, not transmitted as this typedef struct { int ta; } ul_propagation_t; +// One UE UL data, data plane, UE data appended after the header typedef struct { enum pckType type:8; short UE_id; @@ -184,6 +192,7 @@ typedef struct { uint8_t cqi_crc_status; } fs6_ul_uespec_t; +// UL UCI (control plane), per UE typedef struct { enum pckType type:8; int UEid; @@ -198,6 +207,7 @@ typedef struct { int32_t stat; } fs6_ul_uespec_uci_element_t; +// all segments UCI grouped in one UDP packet typedef struct { enum pckType type:8; int16_t nb_active_ue; @@ -239,7 +249,7 @@ void *du_fs6(void *arg); void fill_rf_config(RU_t *ru, char *rf_config_file); int init_rf(RU_t *ru); void rx_rf(RU_t *ru, L1_rxtx_proc_t *proc); -int tx_rf(RU_t *ru, L1_rxtx_proc_t *proc); +void tx_rf(RU_t *ru, L1_rxtx_proc_t *proc); void common_signal_procedures (PHY_VARS_eNB *eNB,int frame, int subframe); void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc); bool dlsch_procedures(PHY_VARS_eNB *eNB, diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 2b032c208a..3036c383f2 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -1187,11 +1187,9 @@ void postDecode(L1_rxtx_proc_t *proc, notifiedFIFO_elt_t *req) { } else { if ( rdata->nbSegments != ulsch_harq->processedSegments ) { int nb=abortTpool(&proc->threadPool, req->key); - printf("nb1:%d\n", nb); nb+=abortNotifiedFIFO(&proc->respDecode, req->key); - printf("nb2:%d\n", nb); proc->nbDecode-=nb; - LOG_I(PHY,"uplink segment error %d/%d, aborted %d segments",rdata->segment_r,rdata->nbSegments, nb); + LOG_I(PHY,"uplink segment error %d/%d, aborted %d segments\n",rdata->segment_r,rdata->nbSegments, nb); AssertFatal(ulsch_harq->processedSegments+nb == rdata->nbSegments,"processed: %d, aborted: %d, total %d\n", ulsch_harq->processedSegments, nb, rdata->nbSegments); ulsch_harq->processedSegments=rdata->nbSegments; @@ -1253,7 +1251,7 @@ void postDecode(L1_rxtx_proc_t *proc, notifiedFIFO_elt_t *req) { } void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { - uint32_t ret=0,i; + uint32_t i; uint32_t harq_pid; uint8_t nPRS; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; @@ -1262,7 +1260,6 @@ void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { const int subframe = proc->subframe_rx; const int frame = proc->frame_rx; uint32_t harq_pid0 = subframe2harq_pid(&eNB->frame_parms,frame,subframe); - int rvidx_tab[4] = {0,2,3,1}; for (i = 0; i < NUMBER_OF_UE_MAX; i++) { ulsch = eNB->ulsch[i]; @@ -1316,7 +1313,7 @@ void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { rx_ulsch(eNB,proc, i); stop_meas(&eNB->ulsch_demodulation_stats); start_meas(&eNB->ulsch_decoding_stats); - ret = ulsch_decoding(eNB,proc, + ulsch_decoding(eNB,proc, i, 0, // control_only_flag ulsch_harq->V_UL_DAI, diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index 4aa09b59de..f41d866221 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -184,7 +184,7 @@ rx_sdu(const module_id_t enb_mod_idP, UE_template_ptr->scheduled_ul_bytes = 0; } } else { // sduP == NULL => error - LOG_W(MAC, "[eNB %d][PUSCH %d] CC_id %d %d.%d ULSCH in error in round %d, ul_cqi %d, UE_id %d, RNTI %x\n", + LOG_W(MAC, "[eNB %d][PUSCH %d] CC_id %d %d.%d ULSCH in error in round %d, ul_cqi %d, UE_id %d, RNTI %x (len %d)\n", enb_mod_idP, harq_pid, CC_idP, @@ -193,7 +193,8 @@ rx_sdu(const module_id_t enb_mod_idP, UE_scheduling_control->round_UL[CC_idP][harq_pid], ul_cqi, UE_id, - current_rnti); + current_rnti, + sdu_lenP); if (ul_cqi > 200) { // too high energy pattern UE_scheduling_control->pusch_snr[CC_idP] = ul_cqi; From e8091083b0d817cf22f1f522aa6c46aa06ce0100 Mon Sep 17 00:00:00 2001 From: laurent Date: Mon, 4 Nov 2019 16:11:09 +0100 Subject: [PATCH 060/240] restore ue compilation with ocp-softmodem, some RF simulator improvement --- executables/main-fs6.c | 3 +- executables/main-ocp.c | 10 +- executables/split_headers.h | 2 +- openair1/PHY/LTE_TRANSPORT/transport_eNB.h | 2 +- .../PHY/LTE_UE_TRANSPORT/dlsch_decoding.c | 2 +- openair1/PHY/defs_eNB.h | 368 +++++++++- openair2/UTIL/MEM/mem_block.c | 668 ------------------ openair2/UTIL/MEM/mem_block.h | 110 --- openair2/UTIL/MEM/mem_mngt.c | 489 ------------- openair2/UTIL/MEM/mem_mngt_proto_extern.h | 21 - openair2/UTIL/MEM/mem_pool.h | 38 - targets/ARCH/rfsimulator/simulator.c | 106 +-- targets/RT/USER/lte-enb.c | 19 +- targets/RT/USER/lte-ru.c | 47 +- targets/RT/USER/lte-ue.c | 68 +- targets/RT/USER/lte-uesoftmodem.c | 6 + 16 files changed, 523 insertions(+), 1436 deletions(-) delete mode 100644 openair2/UTIL/MEM/mem_block.c delete mode 100644 openair2/UTIL/MEM/mem_mngt.c delete mode 100644 openair2/UTIL/MEM/mem_mngt_proto_extern.h delete mode 100644 openair2/UTIL/MEM/mem_pool.h diff --git a/executables/main-fs6.c b/executables/main-fs6.c index f4ea039073..471ad0f1eb 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -616,7 +616,7 @@ void pusch_procedures_fromsplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB * &ulsch_harq->Kminus, &ulsch_harq->F); ulsch_decoding_data(eNB, proc, i, harq_pid, - ulsch_harq->nb_rb>20 ? 1 : 0); + ulsch_harq->nb_rb>20 ? 1 : 0); stop_meas(&eNB->ulsch_decoding_stats); } // if ((ulsch) && // (ulsch->rnti>0) && @@ -634,6 +634,7 @@ void pusch_procedures_fromsplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB * LOG_W (PHY, "Removing stale ULSCH config for UE %x harq_pid %d (harq_mask is now 0x%2.2x)\n", ulsch->rnti, harq_pid, ulsch->harq_mask); } } // for (i=0; inbDecode > 0) { notifiedFIFO_elt_t *req=pullTpool(&proc->respDecode, &proc->threadPool); postDecode(proc, req); diff --git a/executables/main-ocp.c b/executables/main-ocp.c index 3fe1334228..8810115197 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -672,11 +672,11 @@ void tx_rf(RU_t *ru, L1_rxtx_proc_t *proc) { /* add fail safe for late command end */ // prepare tx buffer pointers ru->rfdevice.trx_write_func(&ru->rfdevice, - proc->timestamp_tx+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension, - txp, - siglen+sf_extension, - ru->nb_tx, - flags); + proc->timestamp_tx+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension, + txp, + siglen+sf_extension, + ru->nb_tx, + flags); LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, subframe %d\n",ru->idx, (long long unsigned int)proc->timestamp_tx,proc->frame_tx,proc->subframe_tx); } diff --git a/executables/split_headers.h b/executables/split_headers.h index a0c540e42f..550f189e02 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -73,7 +73,7 @@ enum pckType { }; // CU to DU definition of a future UL subframe decode -// defines a UE future data plane +// defines a UE future data plane typedef struct { enum pckType type:8; uint16_t UE_id; diff --git a/openair1/PHY/LTE_TRANSPORT/transport_eNB.h b/openair1/PHY/LTE_TRANSPORT/transport_eNB.h index 0737d4c56a..99e954238c 100644 --- a/openair1/PHY/LTE_TRANSPORT/transport_eNB.h +++ b/openair1/PHY/LTE_TRANSPORT/transport_eNB.h @@ -103,7 +103,7 @@ typedef struct { /// Concatenated "e"-sequences (for definition see 36-212 V8.6 2009-03, p.17-18) uint8_t e[MAX_NUM_CHANNEL_BITS] __attribute__((aligned(32))); /// Turbo-code outputs (36-212 V8.6 2009-03, p.12 - //uint8_t *d[MAX_NUM_DLSCH_SEGMENTS];//[(96+3+(3*6144))]; + uint8_t *d[MAX_NUM_DLSCH_SEGMENTS];//[(96+3+(3*6144))]; /// Sub-block interleaver outputs (36-212 V8.6 2009-03, p.16-17) uint8_t w[MAX_NUM_DLSCH_SEGMENTS][3*6144]; /// Number of code segments (for definition see 36-212 V8.6 2009-03, p.9) diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c index 4ca9a7c762..f8d03fcb50 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c @@ -705,7 +705,7 @@ int dlsch_encoding_SIC(PHY_VARS_UE *ue, G = get_G(frame_parms,nb_rb,dlsch->harq_processes[harq_pid]->rb_alloc,mod_order,dlsch->harq_processes[harq_pid]->Nl,num_pdcch_symbols,frame,subframe,beamforming_mode); // if (dlsch->harq_processes[harq_pid]->Ndi == 1) { // this is a new packet - if (dlsch->harq_processes[harq_pid]->round == 0) { // this is a new packet + if (dlsch->harq_processes[harq_pid]->DLround == 0) { // this is a new packet #ifdef DEBUG_DLSCH_CODING printf("SIC encoding thinks this is a new packet \n"); #endif diff --git a/openair1/PHY/defs_eNB.h b/openair1/PHY/defs_eNB.h index 51b2e9c4ae..e602382a71 100644 --- a/openair1/PHY/defs_eNB.h +++ b/openair1/PHY/defs_eNB.h @@ -73,6 +73,217 @@ +typedef struct RU_proc_t_s { + /// Pointer to associated RU descriptor + struct RU_t_s *ru; + /// timestamp received from HW + openair0_timestamp timestamp_rx; + /// timestamp to send to "slave rru" + openair0_timestamp timestamp_tx; + /// subframe to act upon for reception + int subframe_rx; + /// subframe to act upon for transmission + int subframe_tx; + /// subframe to act upon for reception of prach + int subframe_prach; +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + /// subframe to act upon for reception of prach BL/CE UEs + int subframe_prach_br; +#endif + /// frame to act upon for reception + int frame_rx; + /// frame to act upon for transmission + int frame_tx; + /// unwrapped frame count + int frame_tx_unwrap; + /// frame to act upon for reception of prach + int frame_prach; +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + /// frame to act upon for reception of prach + int frame_prach_br; +#endif + /// frame offset for slave RUs (to correct for frame asynchronism at startup) + int frame_offset; + /// \brief Instance count for FH processing thread. + /// \internal This variable is protected by \ref mutex_FH. + int instance_cnt_FH; + int instance_cnt_FH1; + /// \internal This variable is protected by \ref mutex_prach. + int instance_cnt_prach; +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + /// \internal This variable is protected by \ref mutex_prach. + int instance_cnt_prach_br; +#endif + /// \internal This variable is protected by \ref mutex_synch. + int instance_cnt_synch; + /// \internal This variable is protected by \ref mutex_eNBs. + int instance_cnt_eNBs; + /// \brief Instance count for rx processing thread. + /// \internal This variable is protected by \ref mutex_asynch_rxtx. + int instance_cnt_asynch_rxtx; + /// \internal This variable is protected by \ref mutex_fep + int instance_cnt_fep; + /// \internal This variable is protected by \ref mutex_feptx + int instance_cnt_feptx; + + /// \internal This variable is protected by \ref mutex_ru_thread + int instance_cnt_ru; + /// pthread structure for RU FH processing thread + pthread_t pthread_FH; + /// pthread structure for RU control thread + pthread_t pthread_ctrl; + + /// This varible is protected by \ref mutex_emulatedRF + int instance_cnt_emulateRF; + /// pthread structure for RU FH processing thread + + pthread_t pthread_FH1; + + /// pthread structure for RU prach processing thread + pthread_t pthread_prach; +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + /// pthread structure for RU prach processing thread BL/CE UEs + pthread_t pthread_prach_br; +#endif + /// pthread struct for RU synch thread + pthread_t pthread_synch; + /// pthread struct for RU RX FEP worker thread + pthread_t pthread_fep; + /// pthread struct for RU TX FEP worker thread + pthread_t pthread_feptx; + /// pthread struct for emulated RF + pthread_t pthread_emulateRF; + /// pthread structure for asychronous RX/TX processing thread + pthread_t pthread_asynch_rxtx; + /// flag to indicate first RX acquisition + int first_rx; + /// flag to indicate first TX transmission + int first_tx; + /// pthread attributes for RU FH processing thread + pthread_attr_t attr_FH; + + /// pthread attributes for RU control thread + pthread_attr_t attr_ctrl; + + pthread_attr_t attr_FH1; + + /// pthread attributes for RU prach + pthread_attr_t attr_prach; +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + /// pthread attributes for RU prach BL/CE UEs + pthread_attr_t attr_prach_br; +#endif + /// pthread attributes for RU synch thread + pthread_attr_t attr_synch; + /// pthread attributes for asynchronous RX thread + pthread_attr_t attr_asynch_rxtx; + /// pthread attributes for worker fep thread + pthread_attr_t attr_fep; + /// pthread attributes for worker feptx thread + pthread_attr_t attr_feptx; + /// pthread attributes for emulated RF + pthread_attr_t attr_emulateRF; + /// scheduling parameters for RU FH thread + struct sched_param sched_param_FH; + struct sched_param sched_param_FH1; + /// scheduling parameters for RU prach thread + struct sched_param sched_param_prach; +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + /// scheduling parameters for RU prach thread BL/CE UEs + struct sched_param sched_param_prach_br; +#endif + /// scheduling parameters for RU synch thread + struct sched_param sched_param_synch; + /// scheduling parameters for asynch_rxtx thread + struct sched_param sched_param_asynch_rxtx; + /// condition variable for RU FH thread + pthread_cond_t cond_FH; + pthread_cond_t cond_FH1; + /// condition variable for RU prach thread + pthread_cond_t cond_prach; +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + /// condition variable for RU prach thread BL/CE UEs + pthread_cond_t cond_prach_br; +#endif + /// condition variable for RU synch thread + pthread_cond_t cond_synch; + /// condition variable for asynch RX/TX thread + pthread_cond_t cond_asynch_rxtx; + /// condition variable for RU RX FEP thread + pthread_cond_t cond_fep; + /// condition variable for RU TX FEP thread + pthread_cond_t cond_feptx; + /// condition variable for emulated RF + pthread_cond_t cond_emulateRF; + /// condition variable for eNB signal + pthread_cond_t cond_eNBs; + /// condition variable for ru_thread + pthread_cond_t cond_ru_thread; + /// mutex for RU FH + pthread_mutex_t mutex_FH; + pthread_mutex_t mutex_FH1; + /// mutex for RU prach + pthread_mutex_t mutex_prach; +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + /// mutex for RU prach BL/CE UEs + pthread_mutex_t mutex_prach_br; +#endif + /// mutex for RU synch + pthread_mutex_t mutex_synch; + /// mutex for eNB signal + pthread_mutex_t mutex_eNBs; + /// mutex for asynch RX/TX thread + pthread_mutex_t mutex_asynch_rxtx; + /// mutex for fep RX worker thread + pthread_mutex_t mutex_fep; + /// mutex for fep TX worker thread + pthread_mutex_t mutex_feptx; + + /// mutex for ru_thread + pthread_mutex_t mutex_ru; + + /// mutex for emulated RF thread + pthread_mutex_t mutex_emulateRF; + + /// symbol mask for IF4p5 reception per subframe + uint32_t symbol_mask[10]; + /// time measurements for each subframe + struct timespec t[10]; + /// number of slave threads + int num_slaves; + /// array of pointers to slaves + struct RU_proc_t_s **slave_proc; +#ifdef PHY_TX_THREAD + /// pthread structure for PRACH thread + pthread_t pthread_phy_tx; + pthread_mutex_t mutex_phy_tx; + pthread_cond_t cond_phy_tx; + /// \internal This variable is protected by \ref mutex_phy_tx. + int instance_cnt_phy_tx; + /// frame to act upon for transmission + int frame_phy_tx; + /// subframe to act upon for transmission + int subframe_phy_tx; + /// timestamp to send to "slave rru" + openair0_timestamp timestamp_phy_tx; + /// pthread structure for RF TX thread + pthread_t pthread_rf_tx; + pthread_mutex_t mutex_rf_tx; + pthread_cond_t cond_rf_tx; + /// \internal This variable is protected by \ref mutex_rf_tx. + int instance_cnt_rf_tx; +#endif +#if defined(PRE_SCD_THREAD) + pthread_t pthread_pre_scd; + /// condition variable for time processing thread + pthread_cond_t cond_pre_scd; + /// mutex for time thread + pthread_mutex_t mutex_pre_scd; + int instance_pre_scd; +#endif + int emulate_rf_busy; +} RU_proc_t; + typedef enum { LOCAL_RF =0, REMOTE_IF5 =1, @@ -257,7 +468,7 @@ typedef struct RU_t_s{ /// value to be passed using command uint16_t cmdval; /// process scheduling variables - //RU_proc_t proc; + RU_proc_t proc; /// stats thread pthread descriptor pthread_t ru_stats_thread; /// OTA synchronization signal @@ -547,6 +758,159 @@ typedef struct { pthread_mutex_t mutex_te; } te_params; +/// Context data structure for eNB subframe processing +typedef struct L1_proc_t_s { + /// Component Carrier index + uint8_t CC_id; + /// thread index + int thread_index; + /// timestamp received from HW + openair0_timestamp timestamp_rx; + /// timestamp to send to "slave rru" + openair0_timestamp timestamp_tx; + /// subframe to act upon for reception + int subframe_rx; + /// subframe to act upon for PRACH + int subframe_prach; +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + /// subframe to act upon for reception of prach BL/CE UEs + int subframe_prach_br; +#endif + /// frame to act upon for reception + int frame_rx; + /// frame to act upon for transmission + int frame_tx; + /// frame to act upon for PRACH + int frame_prach; +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + /// frame to act upon for PRACH BL/CE UEs + int frame_prach_br; +#endif + /// \internal This variable is protected by \ref mutex_td. + int instance_cnt_td; + /// \internal This variable is protected by \ref mutex_te. + int instance_cnt_te; + /// \internal This variable is protected by \ref mutex_prach. + int instance_cnt_prach; +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + /// \internal This variable is protected by \ref mutex_prach for BL/CE UEs. + int instance_cnt_prach_br; +#endif + // instance count for over-the-air eNB synchronization + int instance_cnt_synch; + + + /// \internal This variable is protected by \ref mutex_asynch_rxtx. + int instance_cnt_asynch_rxtx; + /// pthread structure for asychronous RX/TX processing thread + pthread_t pthread_asynch_rxtx; + /// flag to indicate first RX acquisition + int first_rx; + /// flag to indicate first TX transmission + int first_tx; + /// pthread attributes for parallel turbo-decoder thread + pthread_attr_t attr_td; + /// pthread attributes for parallel turbo-encoder thread + pthread_attr_t attr_te; + /// pthread attributes for single eNB processing thread + pthread_attr_t attr_single; + /// pthread attributes for prach processing thread + pthread_attr_t attr_prach; +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + /// pthread attributes for prach processing thread BL/CE UEs + pthread_attr_t attr_prach_br; +#endif + /// pthread attributes for asynchronous RX thread + pthread_attr_t attr_asynch_rxtx; + /// scheduling parameters for parallel turbo-decoder thread + struct sched_param sched_param_td; + /// scheduling parameters for parallel turbo-encoder thread + struct sched_param sched_param_te; + /// scheduling parameters for single eNB thread + struct sched_param sched_param_single; + /// scheduling parameters for prach thread + struct sched_param sched_param_prach; +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + /// scheduling parameters for prach thread + struct sched_param sched_param_prach_br; +#endif + /// scheduling parameters for asynch_rxtx thread + struct sched_param sched_param_asynch_rxtx; + /// pthread structure for parallel turbo-decoder thread + pthread_t pthread_td; + /// pthread structure for parallel turbo-encoder thread + pthread_t pthread_te; + /// pthread structure for PRACH thread + pthread_t pthread_prach; +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + /// pthread structure for PRACH thread BL/CE UEs + pthread_t pthread_prach_br; +#endif + /// condition variable for parallel turbo-decoder thread + pthread_cond_t cond_td; + /// condition variable for parallel turbo-encoder thread + pthread_cond_t cond_te; + /// condition variable for PRACH processing thread; + pthread_cond_t cond_prach; +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + /// condition variable for PRACH processing thread BL/CE UEs; + pthread_cond_t cond_prach_br; +#endif + + /// condition variable for asynch RX/TX thread + pthread_cond_t cond_asynch_rxtx; + /// mutex for parallel turbo-decoder thread + pthread_mutex_t mutex_td; + /// mutex for parallel turbo-encoder thread + pthread_mutex_t mutex_te; + /// mutex for PRACH thread + pthread_mutex_t mutex_prach; +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + /// mutex for PRACH thread for BL/CE UEs + pthread_mutex_t mutex_prach_br; +#endif + /// mutex for asynch RX/TX thread + pthread_mutex_t mutex_asynch_rxtx; + /// mutex for RU access to eNB processing (PDSCH/PUSCH) + pthread_mutex_t mutex_RU; + /// mutex for eNB processing to access RU TX (PDSCH/PUSCH) + pthread_mutex_t mutex_RU_tx; + /// mutex for RU access to eNB processing (PRACH) + pthread_mutex_t mutex_RU_PRACH; + /// mutex for RU access to eNB processing (PRACH BR) + pthread_mutex_t mutex_RU_PRACH_br; + /// mask for RUs serving eNB (PDSCH/PUSCH) + int RU_mask[10]; + /// mask for RUs serving eNB (PDSCH/PUSCH) + int RU_mask_tx; + /// time measurements for RU arrivals + struct timespec t[10]; + /// Timing statistics (RU_arrivals) + time_stats_t ru_arrival_time; + /// mask for RUs serving eNB (PRACH) + int RU_mask_prach; +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + /// mask for RUs serving eNB (PRACH) + int RU_mask_prach_br; +#endif + /// parameters for turbo-decoding worker thread + td_params tdp; + /// parameters for turbo-encoding worker thread + te_params tep[3]; + /// set of scheduling variables RXn-TXnp4 threads + L1_rxtx_proc_t L1_proc,L1_proc_tx; + /// stats thread pthread descriptor + pthread_t process_stats_thread; + /// for waking up tx procedure + RU_proc_t *ru_proc; +} L1_proc_t; + + + + + + + typedef struct { //unsigned int rx_power[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX]; //! estimated received signal power (linear) //unsigned short rx_power_dB[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX]; //! estimated received signal power (dB) @@ -608,7 +972,7 @@ typedef struct PHY_VARS_eNB_s { module_id_t Mod_id; uint8_t CC_id; uint8_t configured; - //L1_proc_t proc; + L1_proc_t proc; int single_thread_flag; int abstraction_flag; int num_RU; diff --git a/openair2/UTIL/MEM/mem_block.c b/openair2/UTIL/MEM/mem_block.c deleted file mode 100644 index 0150ef00cd..0000000000 --- a/openair2/UTIL/MEM/mem_block.c +++ /dev/null @@ -1,668 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*************************************************************************** - mem_block.c - description - ------------------- - AUTHOR : Lionel GAUTHIER - COMPANY : EURECOM - EMAIL : Lionel.Gauthier@eurecom.fr - - - ***************************************************************************/ -#define MEM_BLOCK_C -//#include "rtos_header.h" -#include "mem_block.h" -#include "mem_pool.h" -#include "list.h" -#include "LAYER2/MAC/mac_extern.h" -#include "assertions.h" -/* all function calls are protected by a mutex - * to ensure that many threads calling them at - * the same time don't mess up. - * We might be more clever in the future, it's a - * bit overkill. - * Commenting this define removes the protection, - * so be careful with it. - */ -#define MEMBLOCK_BIG_LOCK - -#ifdef MEMBLOCK_BIG_LOCK -static pthread_mutex_t mtex = PTHREAD_MUTEX_INITIALIZER; -#endif - -//----------------------------------------------------------------------------- -//#define DEBUG_MEM_MNGT_FREE -//#define DEBUG_MEM_MNGT_ALLOC_SIZE -//#define DEBUG_MEM_MNGT_ALLOC -//----------------------------------------------------------------------------- -#if defined(DEBUG_MEM_MNGT_ALLOC) -uint32_t counters[14] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -#endif -//----------------------------------------------------------------------------- -/* - * initialize all ures - */ -extern mem_pool *memBlockVar; -void * -pool_buffer_init (void) -{ - //----------------------------------------------------------------------------- - - uint32_t index, mb_index, pool_index; - mem_pool *memory = (mem_pool *) &mem_block_var; - memBlockVar=malloc(sizeof(mem_pool)); - int pool_sizes[14] = { MEM_MNGT_MB0_NB_BLOCKS, MEM_MNGT_MB1_NB_BLOCKS, - MEM_MNGT_MB2_NB_BLOCKS, MEM_MNGT_MB3_NB_BLOCKS, - MEM_MNGT_MB4_NB_BLOCKS, MEM_MNGT_MB5_NB_BLOCKS, - MEM_MNGT_MB6_NB_BLOCKS, MEM_MNGT_MB7_NB_BLOCKS, - MEM_MNGT_MB8_NB_BLOCKS, MEM_MNGT_MB9_NB_BLOCKS, - MEM_MNGT_MB10_NB_BLOCKS, MEM_MNGT_MB11_NB_BLOCKS, - MEM_MNGT_MB12_NB_BLOCKS, MEM_MNGT_MBCOPY_NB_BLOCKS - }; - -#ifdef MEMBLOCK_BIG_LOCK - if (pthread_mutex_lock(&mtex)) abort(); -#endif - - memset (memory, 0, sizeof (mem_pool)); - mb_index = 0; - - // LG_TEST - for (pool_index = 0; pool_index <= MEM_MNGT_POOL_ID_COPY; pool_index++) { - list_init (&memory->mem_lists[pool_index], "POOL"); - - for (index = 0; index < pool_sizes[pool_index]; index++) { - //memory->mem_blocks[mb_index + index].previous = NULL; -> done in memset 0 - //memory->mem_blocks[mb_index + index].next = NULL; -> done in memset 0 - switch (pool_index) { - case 0: - memory->mem_blocks[mb_index + index].data = (unsigned char*)&(memory->mem_pool0[index][0]); - break; - - case 1: - memory->mem_blocks[mb_index + index].data = (unsigned char*)&(memory->mem_pool1[index][0]); - break; - - case 2: - memory->mem_blocks[mb_index + index].data = (unsigned char*)&(memory->mem_pool2[index][0]); - break; - - case 3: - memory->mem_blocks[mb_index + index].data = (unsigned char*)&(memory->mem_pool3[index][0]); - break; - - case 4: - memory->mem_blocks[mb_index + index].data = (unsigned char*)&(memory->mem_pool4[index][0]); - break; - - case 5: - memory->mem_blocks[mb_index + index].data = (unsigned char*)&(memory->mem_pool5[index][0]); - break; - - case 6: - memory->mem_blocks[mb_index + index].data = (unsigned char*)&(memory->mem_pool6[index][0]); - break; - - case 7: - memory->mem_blocks[mb_index + index].data = (unsigned char*)&(memory->mem_pool7[index][0]); - break; - - case 8: - memory->mem_blocks[mb_index + index].data = (unsigned char*)&(memory->mem_pool8[index][0]); - break; - - case 9: - memory->mem_blocks[mb_index + index].data = (unsigned char*)&(memory->mem_pool9[index][0]); - break; - - case 10: - memory->mem_blocks[mb_index + index].data = (unsigned char*)&(memory->mem_pool10[index][0]); - break; - - case 11: - memory->mem_blocks[mb_index + index].data = (unsigned char*)&(memory->mem_pool11[index][0]); - break; - - case 12: - memory->mem_blocks[mb_index + index].data = (unsigned char*)&(memory->mem_pool12[index][0]); - break; - - default: - ; - memory->mem_blocks[mb_index + index].data = NULL; // pool copy - - } - - memory->mem_blocks[mb_index + index].pool_id = pool_index; - list_add_tail_eurecom (&memory->mem_blocks[mb_index + index], &memory->mem_lists[pool_index]); - } - - mb_index += pool_sizes[pool_index]; - } - -#ifdef MEMBLOCK_BIG_LOCK - if (pthread_mutex_unlock(&mtex)) abort(); -#endif - - return 0; -} - -//----------------------------------------------------------------------------- -void * -pool_buffer_clean (void *arg) -{ - //----------------------------------------------------------------------------- - return 0; -} -//----------------------------------------------------------------------------- -void -free_mem_block (mem_block_t * leP, const char* caller) -{ - //----------------------------------------------------------------------------- - - if (!(leP)) { - LOG_W (RLC,"[MEM_MNGT][FREE] WARNING FREE NULL MEM_BLOCK\n"); - return; - } - -#ifdef MEMBLOCK_BIG_LOCK - if (pthread_mutex_lock(&mtex)) abort(); -#endif - -#ifdef DEBUG_MEM_MNGT_FREE - LOG_D (RLC,"[MEM_MNGT][FREE] free_mem_block() %p pool: %d\n", leP, leP->pool_id); -#endif -#ifdef DEBUG_MEM_MNGT_ALLOC - check_free_mem_block (leP); -#endif - - if (leP->pool_id <= MEM_MNGT_POOL_ID_COPY) { - list_add_tail_eurecom (leP, &mem_block_var.mem_lists[leP->pool_id]); -#ifdef DEBUG_MEM_MNGT_ALLOC - counters[leP->pool_id] -= 1; - LGO_D (RLC,"[%s][MEM_MNGT][INFO] after pool[%2d] freed: counters = {%2d %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d}\n", - caller, leP->pool_id, - counters[0],counters[1],counters[2],counters[3],counters[4], - counters[5],counters[6],counters[7],counters[8],counters[9], - counters[10],counters[11]); -#endif - leP = NULL; // this prevent from freeing the block twice - } else { - LOG_E (RLC,"[MEM_MNGT][FREE] ERROR free_mem_block() unknown pool_id : %d\n", leP->pool_id); - } - -#ifdef MEMBLOCK_BIG_LOCK - if (pthread_mutex_unlock(&mtex)) abort(); -#endif -} - -//----------------------------------------------------------------------------- -mem_block_t * -get_free_mem_block (uint32_t sizeP, const char* caller) -{ - //----------------------------------------------------------------------------- - mem_block_t *le = NULL; - int pool_selected; - int size; - - if (sizeP > MEM_MNGT_MB12_BLOCK_SIZE) { - LOG_E (RLC,"[MEM_MNGT][ERROR][FATAL] size requested %d out of bounds\n", sizeP); - display_mem_load (); - AssertFatal(1==0,"get_free_mem_block size requested out of bounds"); - return NULL; - } - -#ifdef MEMBLOCK_BIG_LOCK - if (pthread_mutex_lock(&mtex)) abort(); -#endif - - size = sizeP >> 6; - pool_selected = 0; - - while ((size)) { - pool_selected += 1; - size = size >> 1; - } - - // pool is selected according to the size requested, now get a block - // if no block is available pick one in an other pool - do { - if ((le = list_remove_head (&mem_block_var.mem_lists[pool_selected]))) { -#ifdef DEBUG_MEM_MNGT_ALLOC - counters[pool_selected] += 1; - LOG_D (RLC,"[%s][MEM_MNGT][INFO] after pool[%2d] allocated: counters = {%2d %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d}\n", - caller, - pool_selected, - counters[0],counters[1],counters[2],counters[3],counters[4], - counters[5],counters[6],counters[7],counters[8],counters[9], - counters[10],counters[11]); -#endif -#ifdef DEBUG_MEM_MNGT_ALLOC_SIZE - LOG_D (RLC,"[MEM_MNGT][INFO] ALLOC MEM_BLOCK SIZE %d bytes pool %d (%p)\n", sizeP, pool_selected,le); -#endif - - AssertFatal(le->pool_id == pool_selected, "Unexpected pool ID!"); - -#ifdef MEMBLOCK_BIG_LOCK - if (pthread_mutex_unlock(&mtex)) abort(); -#endif - - return le; - } - -#ifdef DEBUG_MEM_MNGT_ALLOC - LOG_E (RLC,"[MEM_MNGT][ERROR][MINOR] memory pool %d is empty trying next pool alloc count = %d\n", pool_selected, counters[pool_selected]); - // display_mem_load (); - // check_mem_area ((void *)&mem_block_var); -#endif - } while (pool_selected++ < 12); - - LOG_E(PHY, "[MEM_MNGT][ERROR][FATAL] failed allocating MEM_BLOCK size %d byes (pool_selected=%d size=%d)\n", sizeP, pool_selected, size); -// display_mem_load(); -// AssertFatal(1==0,"get_free_mem_block failed"); - LOG_E(MAC,"[MEM_MNGT][ERROR][FATAL] get_free_mem_block failed!!!\n"); -#ifdef MEMBLOCK_BIG_LOCK - if (pthread_mutex_unlock(&mtex)) abort(); -#endif - - return NULL; -}; - -//----------------------------------------------------------------------------- -mem_block_t * -get_free_copy_mem_block (void) -{ - //----------------------------------------------------------------------------- - mem_block_t *le; - -#ifdef MEMBLOCK_BIG_LOCK - AssertFatal(0, "This function is not handled properly but not used anywhere. FIXME?\n"); -#endif - - if ((le = list_remove_head (&mem_block_var.mem_lists[MEM_MNGT_POOL_ID_COPY]))) { -#ifdef DEBUG_MEM_MNGT_ALLOC_SIZE - LOG_D (RLC,"[MEM_MNGT][INFO] ALLOC COPY MEM BLOCK (%p)\n",le); -#endif -#ifdef DEBUG_MEM_MNGT_ALLOC - counters[MEM_MNGT_POOL_ID_COPY] += 1; - LOG_D (RLC,"[MEM_MNGT][INFO] pool counters = {%2d %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d %2d}\n", - counters[0],counters[1],counters[2],counters[3],counters[4], - counters[5],counters[6],counters[7],counters[8],counters[9], - counters[10],counters[11]); -#endif - return le; - } else { - LOG_E (RLC,"[MEM_MNGT][ERROR] POOL COPY IS EMPTY\n"); - //#ifdef DEBUG_MEM_MNGT_ALLOC - check_mem_area (); - // break_point (); - //#endif - - AssertFatal(1==0,"mem pool is empty"); - return NULL; - } -} - -//----------------------------------------------------------------------------- -mem_block_t * -copy_mem_block (mem_block_t * leP, mem_block_t * destP) -{ - //----------------------------------------------------------------------------- - -#ifdef MEMBLOCK_BIG_LOCK - AssertFatal(0, "This function is not handled properly but not used anywhere. FIXME?\n"); -#endif - - if ((destP != NULL) && (leP != NULL) && (destP->pool_id == MEM_MNGT_POOL_ID_COPY)) { - destP->data = leP->data; - } else { - LOG_E (RLC,"[MEM_MNGT][COPY] copy_mem_block() pool dest src or dest is NULL\n"); - } - - return destP; -} - -//----------------------------------------------------------------------------- -void -display_mem_load (void) -{ - //----------------------------------------------------------------------------- -#ifdef MEMBLOCK_BIG_LOCK - /* this function does not need to be protected, do nothing */ -#endif - - mem_pool *memory = (mem_pool *) &mem_block_var; - - LOG_D (RLC,"POOL 0 (%d elements of %d Bytes): ", MEM_MNGT_MB0_NB_BLOCKS, MEM_MNGT_MB0_BLOCK_SIZE); - list_display (&memory->mem_lists[MEM_MNGT_POOL_ID0]); - LOG_D (RLC,"POOL 1 (%d elements of %d Bytes): ", MEM_MNGT_MB1_NB_BLOCKS, MEM_MNGT_MB1_BLOCK_SIZE); - list_display (&memory->mem_lists[MEM_MNGT_POOL_ID1]); - LOG_D (RLC,"POOL 2 (%d elements of %d Bytes): ", MEM_MNGT_MB2_NB_BLOCKS, MEM_MNGT_MB2_BLOCK_SIZE); - list_display (&memory->mem_lists[MEM_MNGT_POOL_ID2]); - LOG_D (RLC,"POOL 3 (%d elements of %d Bytes): ", MEM_MNGT_MB3_NB_BLOCKS, MEM_MNGT_MB3_BLOCK_SIZE); - list_display (&memory->mem_lists[MEM_MNGT_POOL_ID3]); - LOG_D (RLC,"POOL 4 (%d elements of %d Bytes): ", MEM_MNGT_MB4_NB_BLOCKS, MEM_MNGT_MB4_BLOCK_SIZE); - list_display (&memory->mem_lists[MEM_MNGT_POOL_ID4]); - LOG_D (RLC,"POOL 5 (%d elements of %d Bytes): ", MEM_MNGT_MB5_NB_BLOCKS, MEM_MNGT_MB5_BLOCK_SIZE); - list_display (&memory->mem_lists[MEM_MNGT_POOL_ID5]); - LOG_D (RLC,"POOL 6 (%d elements of %d Bytes): ", MEM_MNGT_MB6_NB_BLOCKS, MEM_MNGT_MB6_BLOCK_SIZE); - list_display (&memory->mem_lists[MEM_MNGT_POOL_ID6]); - LOG_D (RLC,"POOL 7 (%d elements of %d Bytes): ", MEM_MNGT_MB7_NB_BLOCKS, MEM_MNGT_MB7_BLOCK_SIZE); - list_display (&memory->mem_lists[MEM_MNGT_POOL_ID7]); - LOG_D (RLC,"POOL 8 (%d elements of %d Bytes): ", MEM_MNGT_MB8_NB_BLOCKS, MEM_MNGT_MB8_BLOCK_SIZE); - list_display (&memory->mem_lists[MEM_MNGT_POOL_ID8]); - LOG_D (RLC,"POOL 9 (%d elements of %d Bytes): ", MEM_MNGT_MB9_NB_BLOCKS, MEM_MNGT_MB9_BLOCK_SIZE); - list_display (&memory->mem_lists[MEM_MNGT_POOL_ID9]); - LOG_D (RLC,"POOL 10 (%d elements of %d Bytes): ", MEM_MNGT_MB10_NB_BLOCKS, MEM_MNGT_MB10_BLOCK_SIZE); - list_display (&memory->mem_lists[MEM_MNGT_POOL_ID10]); - LOG_D (RLC,"POOL 11 (%d elements of %d Bytes): ", MEM_MNGT_MB11_NB_BLOCKS, MEM_MNGT_MB11_BLOCK_SIZE); - list_display (&memory->mem_lists[MEM_MNGT_POOL_ID11]); - LOG_D (RLC,"POOL 12 (%d elements of %d Bytes): ", MEM_MNGT_MB12_NB_BLOCKS, MEM_MNGT_MB12_BLOCK_SIZE); - list_display (&memory->mem_lists[MEM_MNGT_POOL_ID12]); - LOG_D (RLC,"POOL C (%d elements): ", MEM_MNGT_MBCOPY_NB_BLOCKS); - list_display (&memory->mem_lists[MEM_MNGT_POOL_ID_COPY]); -} - -//----------------------------------------------------------------------------- -void -check_mem_area (void) -{ - //----------------------------------------------------------------------------- - int index, mb_index; - mem_pool *memory = (mem_pool *) &mem_block_var; - -#ifdef MEMBLOCK_BIG_LOCK - AssertFatal(0, "This function is not handled properly but not used anywhere. FIXME?\n"); -#endif - - for (index = 0; index < MEM_MNGT_MB0_NB_BLOCKS; index++) { - if ((memory->mem_blocks[index].data != (unsigned char*)&(memory->mem_pool0[index][0])) && (memory->mem_blocks[index].pool_id != MEM_MNGT_POOL_ID0)) { - LOG_D (RLC,"[MEM] ERROR POOL0 block index %d\n", index); - } - } - - mb_index = MEM_MNGT_MB0_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB1_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != (unsigned char*)&(memory->mem_pool1[index][0])) - && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID1)) { - LOG_D (RLC,"[MEM] ERROR POOL1 block index %d\n", index); - } - } - - mb_index += MEM_MNGT_MB1_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB2_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != (unsigned char*)&(memory->mem_pool2[index][0])) - && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID2)) { - LOG_D (RLC,"[MEM] ERROR POOL2 block index %d\n", index); - } - } - - mb_index += MEM_MNGT_MB2_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB3_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != (unsigned char*)&(memory->mem_pool3[index][0])) - && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID3)) { - LOG_D (RLC,"[MEM] ERROR POOL3 block index %d\n", index); - } - } - - mb_index += MEM_MNGT_MB3_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB4_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != (unsigned char*)&(memory->mem_pool4[index][0])) - && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID4)) { - LOG_D (RLC,"[MEM] ERROR POOL4 block index %d\n", index); - } - } - - mb_index += MEM_MNGT_MB4_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB5_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != (unsigned char*)&(memory->mem_pool5[index][0])) - && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID5)) { - LOG_D (RLC,"[MEM] ERROR POOL5 block index %d\n", index); - } - } - - mb_index += MEM_MNGT_MB5_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB6_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != (unsigned char*)&(memory->mem_pool6[index][0])) - && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID6)) { - LOG_D (RLC,"[MEM] ERROR POOL6 block index %d\n", index); - } - } - - mb_index += MEM_MNGT_MB6_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB7_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != (unsigned char*)&(memory->mem_pool7[index][0])) - && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID7)) { - LOG_D (RLC,"[MEM] ERROR POOL7 block index %d\n", index); - } - } - - mb_index += MEM_MNGT_MB7_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB8_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != (unsigned char*)&(memory->mem_pool8[index][0])) - && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID8)) { - LOG_D (RLC,"[MEM] ERROR POOL8 block index %d\n", index); - } - } - - mb_index += MEM_MNGT_MB8_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB9_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != (unsigned char*)&(memory->mem_pool9[index][0])) - && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID9)) { - LOG_D (RLC,"[MEM] ERROR POOL9 block index %d\n", index); - } - } - - mb_index += MEM_MNGT_MB9_NB_BLOCKS; - - for (index = mb_index; index < MEM_MNGT_MB10_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != (unsigned char*)&(memory->mem_pool10[index][0])) - && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID10)) { - LOG_D (RLC,"[MEM] ERROR POOL10 block index %d\n", index); - } - } - - mb_index += MEM_MNGT_MB10_NB_BLOCKS; - - for (index = mb_index; index < MEM_MNGT_MB11_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != (unsigned char*)&(memory->mem_pool11[index][0])) - && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID11)) { - LOG_D (RLC,"[MEM] ERROR POOL11 block index %d\n", index); - } - } - - mb_index += MEM_MNGT_MB11_NB_BLOCKS; - - for (index = mb_index; index < MEM_MNGT_MB12_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != (unsigned char*)&(memory->mem_pool12[index][0])) - && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID12)) { - LOG_D (RLC,"[MEM] ERROR POOL12 block index %d\n", index); - } - } - - mb_index += MEM_MNGT_MB12_NB_BLOCKS; - - for (index = mb_index; index < MEM_MNGT_NB_ELEMENTS; index++) { - if ((memory->mem_blocks[index].data != NULL) && (memory->mem_blocks[index].pool_id != MEM_MNGT_POOL_ID_COPY)) { - LOG_D (RLC,"[MEM] ERROR POOL COPY block index %d\n", index); - } - } -} - -//----------------------------------------------------------------------------- -void -check_free_mem_block (mem_block_t * leP) -{ - //----------------------------------------------------------------------------- - ptrdiff_t block_index; - -#ifdef MEMBLOCK_BIG_LOCK - /* this function does not SEEM TO need to be protected, do nothing (for the moment) */ -#endif - - if ((leP >= mem_block_var.mem_blocks) && (leP <= &mem_block_var.mem_blocks[MEM_MNGT_NB_ELEMENTS-1])) { - // the pointer is inside the memory region - block_index = leP - mem_block_var.mem_blocks; - // block_index is now: 0 <= block_index < MEM_MNGT_NB_ELEMENTS - - if (block_index < MEM_MNGT_MB0_NB_BLOCKS) { - if ((leP->data != (unsigned char*)mem_block_var.mem_pool0[block_index]) && (leP->pool_id != MEM_MNGT_POOL_ID0)) { - LOG_D (RLC,"[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - - return; - } - - block_index -= MEM_MNGT_MB0_NB_BLOCKS; - - if (block_index < MEM_MNGT_MB1_NB_BLOCKS) { - if ((leP->data != (unsigned char*)mem_block_var.mem_pool1[block_index]) && (leP->pool_id != MEM_MNGT_POOL_ID1)) { - LOG_D (RLC,"[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - - return; - } - - block_index -= MEM_MNGT_MB1_NB_BLOCKS; - - if (block_index < MEM_MNGT_MB2_NB_BLOCKS) { - if ((leP->data != (unsigned char*)mem_block_var.mem_pool2[block_index]) && (leP->pool_id != MEM_MNGT_POOL_ID2)) { - LOG_D (RLC,"[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - - return; - } - - block_index -= MEM_MNGT_MB2_NB_BLOCKS; - - if (block_index < MEM_MNGT_MB3_NB_BLOCKS) { - if ((leP->data != (unsigned char*)mem_block_var.mem_pool3[block_index]) && (leP->pool_id != MEM_MNGT_POOL_ID3)) { - LOG_D (RLC,"[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - - return; - } - - block_index -= MEM_MNGT_MB3_NB_BLOCKS; - - if (block_index < MEM_MNGT_MB4_NB_BLOCKS) { - if ((leP->data != (unsigned char*)mem_block_var.mem_pool4[block_index]) && (leP->pool_id != MEM_MNGT_POOL_ID4)) { - LOG_D (RLC,"[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - - return; - } - - block_index -= MEM_MNGT_MB4_NB_BLOCKS; - - if (block_index < MEM_MNGT_MB5_NB_BLOCKS) { - if ((leP->data != (unsigned char*)mem_block_var.mem_pool5[block_index]) && (leP->pool_id != MEM_MNGT_POOL_ID5)) { - LOG_D (RLC,"[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - - return; - } - - block_index -= MEM_MNGT_MB5_NB_BLOCKS; - - if (block_index < MEM_MNGT_MB6_NB_BLOCKS) { - if ((leP->data != (unsigned char*)mem_block_var.mem_pool6[block_index]) && (leP->pool_id != MEM_MNGT_POOL_ID6)) { - LOG_D (RLC,"[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - - return; - } - - block_index -= MEM_MNGT_MB6_NB_BLOCKS; - - if (block_index < MEM_MNGT_MB7_NB_BLOCKS) { - if ((leP->data != (unsigned char*)mem_block_var.mem_pool7[block_index]) && (leP->pool_id != MEM_MNGT_POOL_ID7)) { - LOG_D (RLC,"[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - - return; - } - - block_index -= MEM_MNGT_MB7_NB_BLOCKS; - - if (block_index < MEM_MNGT_MB8_NB_BLOCKS) { - if ((leP->data != (unsigned char*)mem_block_var.mem_pool8[block_index]) && (leP->pool_id != MEM_MNGT_POOL_ID8)) { - LOG_D (RLC,"[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - - return; - } - - block_index -= MEM_MNGT_MB8_NB_BLOCKS; - - if (block_index < MEM_MNGT_MB9_NB_BLOCKS) { - if ((leP->data != (unsigned char*)mem_block_var.mem_pool9[block_index]) && (leP->pool_id != MEM_MNGT_POOL_ID9)) { - LOG_D (RLC,"[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - - return; - } - - block_index -= MEM_MNGT_MB9_NB_BLOCKS; - - if (block_index < MEM_MNGT_MB10_NB_BLOCKS) { - if ((leP->data != (unsigned char*)mem_block_var.mem_pool10[block_index]) && (leP->pool_id != MEM_MNGT_POOL_ID10)) { - LOG_D (RLC,"[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - - return; - } - - block_index -= MEM_MNGT_MB10_NB_BLOCKS; - - if (block_index < MEM_MNGT_MB11_NB_BLOCKS) { - if ((leP->data != (unsigned char*)mem_block_var.mem_pool11[block_index]) && (leP->pool_id != MEM_MNGT_POOL_ID11)) { - LOG_D (RLC,"[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - - return; - } - - block_index -= MEM_MNGT_MB11_NB_BLOCKS; - - if (block_index < MEM_MNGT_MB12_NB_BLOCKS) { - if ((leP->data != (unsigned char*)mem_block_var.mem_pool12[block_index]) && (leP->pool_id != MEM_MNGT_POOL_ID12)) { - LOG_D (RLC,"[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - - return; - } - } else { - LOG_D (RLC,"[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - - // the block is ok -} diff --git a/openair2/UTIL/MEM/mem_block.h b/openair2/UTIL/MEM/mem_block.h index 4d8ed4e89b..0d99430640 100644 --- a/openair2/UTIL/MEM/mem_block.h +++ b/openair2/UTIL/MEM/mem_block.h @@ -57,91 +57,8 @@ mem_block_t *get_free_copy_mem_block (void); mem_block_t *get_free_copy_mem_block_up (void); mem_block_t *copy_mem_block (mem_block_t * leP, mem_block_t * destP); void display_mem_load (void); - -void check_mem_area (void); -void check_free_mem_block (mem_block_t * leP); -# define MEM_SCALE MAX_MOBILES_PER_ENB -// definition of the size of the allocated memory area -# define MEM_MNGT_MB0_BLOCK_SIZE 64 -// 64 -# define MEM_MNGT_MB0_NB_BLOCKS 4096 * MEM_SCALE -# define MEM_MNGT_POOL_ID0 0 - -# define MEM_MNGT_MB1_BLOCK_SIZE MEM_MNGT_MB0_BLOCK_SIZE*2 -// 128 -# define MEM_MNGT_MB1_NB_BLOCKS 4096 * MEM_SCALE -# define MEM_MNGT_POOL_ID1 1 - -# define MEM_MNGT_MB2_BLOCK_SIZE MEM_MNGT_MB0_BLOCK_SIZE*4 -// 256 -# define MEM_MNGT_MB2_NB_BLOCKS 2048 * MEM_SCALE -# define MEM_MNGT_POOL_ID2 2 - -# define MEM_MNGT_MB3_BLOCK_SIZE MEM_MNGT_MB0_BLOCK_SIZE*8 -// 512 -# define MEM_MNGT_MB3_NB_BLOCKS 2048 * MEM_SCALE -# define MEM_MNGT_POOL_ID3 3 - -# define MEM_MNGT_MB4_BLOCK_SIZE MEM_MNGT_MB0_BLOCK_SIZE*16 -// 1024 -# define MEM_MNGT_MB4_NB_BLOCKS 1024 * MEM_SCALE -# define MEM_MNGT_POOL_ID4 4 - -# define MEM_MNGT_MB5_BLOCK_SIZE MEM_MNGT_MB0_BLOCK_SIZE*32 -// 2048 -# define MEM_MNGT_MB5_NB_BLOCKS 1024 * MEM_SCALE // LG WAS 1024 -# define MEM_MNGT_POOL_ID5 5 - -# define MEM_MNGT_MB6_BLOCK_SIZE MEM_MNGT_MB0_BLOCK_SIZE*64 -// 4096 -# define MEM_MNGT_MB6_NB_BLOCKS 1024 * MEM_SCALE // LG WAS 256 -# define MEM_MNGT_POOL_ID6 6 - -# define MEM_MNGT_MB7_BLOCK_SIZE MEM_MNGT_MB0_BLOCK_SIZE*128 -// 8192 -# define MEM_MNGT_MB7_NB_BLOCKS 64* MEM_SCALE // LG WAS 32 -# define MEM_MNGT_POOL_ID7 7 - -# define MEM_MNGT_MB8_BLOCK_SIZE MEM_MNGT_MB0_BLOCK_SIZE*256 - -#ifdef JUMBO_FRAMES -# define MEM_MNGT_MB8_NB_BLOCKS 256 * MEM_SCALE -#else -# define MEM_MNGT_MB8_NB_BLOCKS 16 * MEM_SCALE -// 16384 -#endif -# define MEM_MNGT_POOL_ID8 8 - -# define MEM_MNGT_MB9_BLOCK_SIZE MEM_MNGT_MB0_BLOCK_SIZE*512 -// 32768 -# define MEM_MNGT_MB9_NB_BLOCKS 8 * MEM_SCALE -# define MEM_MNGT_POOL_ID9 9 - -# define MEM_MNGT_MB10_BLOCK_SIZE MEM_MNGT_MB0_BLOCK_SIZE*1024 -// 65536 -# define MEM_MNGT_MB10_NB_BLOCKS 0 * MEM_SCALE -# define MEM_MNGT_POOL_ID10 10 - -# define MEM_MNGT_MB11_BLOCK_SIZE MEM_MNGT_MB0_BLOCK_SIZE*2048 -// 131072 -# define MEM_MNGT_MB11_NB_BLOCKS 0 * MEM_SCALE -# define MEM_MNGT_POOL_ID11 11 - -# define MEM_MNGT_MB12_BLOCK_SIZE MEM_MNGT_MB0_BLOCK_SIZE*4096 -// 262144 -# define MEM_MNGT_MB12_NB_BLOCKS 32 * MEM_SCALE -//# define MEM_MNGT_MB12_NB_BLOCKS 4096 * MEM_SCALE - -# define MEM_MNGT_POOL_ID12 12 - - -# define MEM_MNGT_MBCOPY_NB_BLOCKS 1024 -# define MEM_MNGT_NB_ELEMENTS MEM_MNGT_MB0_NB_BLOCKS + MEM_MNGT_MB1_NB_BLOCKS + MEM_MNGT_MB2_NB_BLOCKS + MEM_MNGT_MB3_NB_BLOCKS + MEM_MNGT_MB4_NB_BLOCKS + MEM_MNGT_MB5_NB_BLOCKS + MEM_MNGT_MB6_NB_BLOCKS + MEM_MNGT_MB7_NB_BLOCKS + MEM_MNGT_MB8_NB_BLOCKS + MEM_MNGT_MB9_NB_BLOCKS + MEM_MNGT_MB10_NB_BLOCKS + MEM_MNGT_MB11_NB_BLOCKS + MEM_MNGT_MB12_NB_BLOCKS + MEM_MNGT_MBCOPY_NB_BLOCKS -# define MEM_MNGT_POOL_ID_COPY 13 - #define LIST_NAME_MAX_CHAR 32 - typedef struct { struct mem_block_t *head; struct mem_block_t *tail; @@ -156,33 +73,6 @@ typedef struct { char name[LIST_NAME_MAX_CHAR]; } list_t; - - -typedef struct { - //----------------------------------------------------------- - // basic memory management - //----------------------------------------------------------- - char mem_pool0[MEM_MNGT_MB0_NB_BLOCKS][MEM_MNGT_MB0_BLOCK_SIZE]; - char mem_pool1[MEM_MNGT_MB1_NB_BLOCKS][MEM_MNGT_MB1_BLOCK_SIZE]; - char mem_pool2[MEM_MNGT_MB2_NB_BLOCKS][MEM_MNGT_MB2_BLOCK_SIZE]; - char mem_pool3[MEM_MNGT_MB3_NB_BLOCKS][MEM_MNGT_MB3_BLOCK_SIZE]; - char mem_pool4[MEM_MNGT_MB4_NB_BLOCKS][MEM_MNGT_MB4_BLOCK_SIZE]; - char mem_pool5[MEM_MNGT_MB5_NB_BLOCKS][MEM_MNGT_MB5_BLOCK_SIZE]; - char mem_pool6[MEM_MNGT_MB6_NB_BLOCKS][MEM_MNGT_MB6_BLOCK_SIZE]; - char mem_pool7[MEM_MNGT_MB7_NB_BLOCKS][MEM_MNGT_MB7_BLOCK_SIZE]; - char mem_pool8[MEM_MNGT_MB8_NB_BLOCKS][MEM_MNGT_MB8_BLOCK_SIZE]; - char mem_pool9[MEM_MNGT_MB9_NB_BLOCKS][MEM_MNGT_MB9_BLOCK_SIZE]; - char mem_pool10[MEM_MNGT_MB10_NB_BLOCKS][MEM_MNGT_MB10_BLOCK_SIZE]; - char mem_pool11[MEM_MNGT_MB11_NB_BLOCKS][MEM_MNGT_MB11_BLOCK_SIZE]; - char mem_pool12[MEM_MNGT_MB12_NB_BLOCKS][MEM_MNGT_MB12_BLOCK_SIZE]; - mem_block_t mem_blocks[MEM_MNGT_NB_ELEMENTS]; - list_t mem_lists[14]; - -} mem_pool; - -mem_pool *memBlockVar; -#define mem_block_var (*memBlockVar) - #ifdef __cplusplus } #endif diff --git a/openair2/UTIL/MEM/mem_mngt.c b/openair2/UTIL/MEM/mem_mngt.c deleted file mode 100644 index 57c90ea4f9..0000000000 --- a/openair2/UTIL/MEM/mem_mngt.c +++ /dev/null @@ -1,489 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*************************************************************************** - mem_mngt.c - description - ------------------- - AUTHOR : Lionel GAUTHIER - COMPANY : EURECOM - EMAIL : Lionel.Gauthier@eurecom.fr - - - ***************************************************************************/ -#define MEM_MNGT_C -#include "rtos_header.h" -#include "platform.h" -#include "protocol_vars_extern.h" -#include "print.h" - -#include "mem_block.h" -#include "mem_pool.h" -#include "lists_proto_extern.h" -#include "umts_sched.h" -//----------------------------------------------------------------------------- -#define DEBUG_MEM_MNGT_FREE -#define DEBUG_MEM_MNGT_ALLOC_SIZE -#define DEBUG_MEM_MNGT_ALLOC -#ifdef DEBUG_MEM_MNGT_ADDR -# define PRINT_MEM_MNGT_ADDR msg -#else -# define PRINT_MEM_MNGT_ADDR -// -#endif -//----------------------------------------------------------------------------- -uint32_t counters[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -//----------------------------------------------------------------------------- -/* - * initialize all ures - */ -void * -pool_buffer_init (void *arg) -{ - //----------------------------------------------------------------------------- - - uint32_t index, mb_index, pool_index; - mem_pool *memory = (mem_pool *) arg; - int pool_sizes[11] = { MEM_MNGT_MB0_NB_BLOCKS, MEM_MNGT_MB1_NB_BLOCKS, - MEM_MNGT_MB2_NB_BLOCKS, MEM_MNGT_MB3_NB_BLOCKS, - MEM_MNGT_MB4_NB_BLOCKS, MEM_MNGT_MB5_NB_BLOCKS, - MEM_MNGT_MB6_NB_BLOCKS, MEM_MNGT_MB7_NB_BLOCKS, - MEM_MNGT_MB8_NB_BLOCKS, MEM_MNGT_MB9_NB_BLOCKS, - MEM_MNGT_MBCOPY_NB_BLOCKS - }; - - memset (memory, 0, sizeof (mem_pool)); - mb_index = 0; - - // LG_TEST - for (pool_index = 0; pool_index <= MEM_MNGT_POOL_ID_COPY; pool_index++) { - init_list (&memory->mem_lists[pool_index], "POOL"); - - for (index = 0; index < pool_sizes[pool_index]; index++) { - //memory->mem_blocks[mb_index + index].previous = NULL; -> done in memset 0 - //memory->mem_blocks[mb_index + index].next = NULL; -> done in memset 0 - switch (pool_index) { - case 0: - memory->mem_blocks[mb_index + index].data = &(memory->mem_pool0[index][0]); - break; - - case 1: - memory->mem_blocks[mb_index + index].data = &(memory->mem_pool1[index][0]); - break; - - case 2: - memory->mem_blocks[mb_index + index].data = &(memory->mem_pool2[index][0]); - break; - - case 3: - memory->mem_blocks[mb_index + index].data = &(memory->mem_pool3[index][0]); - break; - - case 4: - memory->mem_blocks[mb_index + index].data = &(memory->mem_pool4[index][0]); - break; - - case 5: - memory->mem_blocks[mb_index + index].data = &(memory->mem_pool5[index][0]); - break; - - case 6: - memory->mem_blocks[mb_index + index].data = &(memory->mem_pool6[index][0]); - break; - - case 7: - memory->mem_blocks[mb_index + index].data = &(memory->mem_pool7[index][0]); - break; - - case 8: - memory->mem_blocks[mb_index + index].data = &(memory->mem_pool8[index][0]); - break; - - case 9: - memory->mem_blocks[mb_index + index].data = &(memory->mem_pool9[index][0]); - break; - - default: - ; - memory->mem_blocks[mb_index + index].data = NULL; // pool copy - - } - - memory->mem_blocks[mb_index + index].pool_id = pool_index; - add_tail (&memory->mem_blocks[mb_index + index], &memory->mem_lists[pool_index]); - } - - mb_index += pool_sizes[pool_index]; - } - - return 0; -} - -//----------------------------------------------------------------------------- -void * -pool_buffer_clean (void *arg) -{ - //----------------------------------------------------------------------------- -#ifndef NO_THREAD_SAFE - mem_pool *memory = (mem_pool *) arg; - pthread_mutex_destroy (&memory->mem_lists[MEM_MNGT_POOL_ID0].mutex); - pthread_mutex_destroy (&memory->mem_lists[MEM_MNGT_POOL_ID1].mutex); - pthread_mutex_destroy (&memory->mem_lists[MEM_MNGT_POOL_ID2].mutex); - pthread_mutex_destroy (&memory->mem_lists[MEM_MNGT_POOL_ID3].mutex); - pthread_mutex_destroy (&memory->mem_lists[MEM_MNGT_POOL_ID4].mutex); - pthread_mutex_destroy (&memory->mem_lists[MEM_MNGT_POOL_ID5].mutex); - pthread_mutex_destroy (&memory->mem_lists[MEM_MNGT_POOL_ID6].mutex); - pthread_mutex_destroy (&memory->mem_lists[MEM_MNGT_POOL_ID7].mutex); - pthread_mutex_destroy (&memory->mem_lists[MEM_MNGT_POOL_ID8].mutex); - pthread_mutex_destroy (&memory->mem_lists[MEM_MNGT_POOL_ID9].mutex); - pthread_mutex_destroy (&memory->mem_lists[MEM_MNGT_POOL_ID_COPY].mutex); -#endif - return 0; -} -//----------------------------------------------------------------------------- -void -free_mem_block (mem_block_t * leP, __func__) -{ - //----------------------------------------------------------------------------- - - if (!(leP)) { - msg ("[MEM_MNGT][FREE] WARNING FREE NULL MEM_BLOCK\n"); - return; - } - -#ifdef DEBUG_MEM_MNGT_FREE - msg ("[MEM_MNGT][FREE] free_mem_block() %p pool: %d\n", leP, leP->pool_id, __func__); -#endif -#ifdef DEBUG_MEM_MNGT_ALLOC - check_free_mem_block (leP, __func__); -#endif - - if (leP->pool_id <= MEM_MNGT_POOL_ID_COPY) { - add_tail (leP, &mem->mem_lists[leP->pool_id]); -#ifdef DEBUG_MEM_MNGT_ALLOC - counters[leP->pool_id] -= 1; -#endif - leP = NULL; // this prevent from freeing the block twice - } else { - msg ("[MEM_MNGT][FREE] ERROR free_mem_block() unknown pool_id : %d\n", leP->pool_id, __func__); - } -} - - -//----------------------------------------------------------------------------- -mem_block_t * -get_free_mem_block (uint16_t sizeP, __func__) -{ - //----------------------------------------------------------------------------- - mem_block_t *le = NULL; - int pool_selected; - int size; - - if (sizeP > MEM_MNGT_MB9_BLOCK_SIZE) { - msg ("[MEM_MNGT][ERROR][FATAL] size requested %d out of bounds %d\n",sizeP,MEM_MNGT_MB9_BLOCK_SIZE); - wcdma_handle_error (WCDMA_ERROR_OUT_OF_MEM_BLOCK); - return NULL; - } - - size = sizeP >> 6; - pool_selected = 0; - - while ((size)) { - pool_selected += 1; - size = size >> 1; - } - - // pool is selected according to the size requested, now get a block - // if no block is available pick one in an other pool - do { - if ((le = remove_head (&mem->mem_lists[pool_selected]))) { -#ifdef DEBUG_MEM_MNGT_ALLOC - counters[pool_selected] += 1; -#endif -#ifdef DEBUG_MEM_MNGT_ALLOC_SIZE - msg ("[MEM_MNGT][INFO] ALLOC MEM_BLOCK SIZE %d bytes pool %d\n", sizeP, pool_selected); -#endif - return le; - } - -#ifdef DEBUG_MEM_MNGT_ALLOC - msg ("[MEM_MNGT][ERROR][MINOR] memory pool %d is empty trying next pool alloc count = %d\n", pool_selected, counters[pool_selected]); - display_mem_load (); - check_mem_area (mem); -#endif - } while (pool_selected++ < 9); - - msg ("[MEM_MNGT][ERROR][FATAL] size %d requested out of bounds or memory pools empty\n", sizeP); - wcdma_handle_error (WCDMA_ERROR_OUT_OF_MEM_BLOCK); - return NULL; -}; - -//----------------------------------------------------------------------------- -mem_block_t * -get_free_copy_mem_block (void) -{ - //----------------------------------------------------------------------------- - mem_block_t *le; - - if ((le = remove_head (&mem->mem_lists[MEM_MNGT_POOL_ID_COPY]))) { - return le; - } else { - msg ("[MEM_MNGT][ERROR] POOL COPY IS EMPTY\n"); - display_mem_load (); -#ifdef DEBUG_MEM_MNGT_ALLOC - check_mem_area (mem); - break_point (); -#endif - wcdma_handle_error (WCDMA_ERROR_OUT_OF_MEM_BLOCK); - - return NULL; - } -} - -//----------------------------------------------------------------------------- -mem_block_t * -copy_mem_block (mem_block_t * leP, mem_block_t * destP) -{ - //----------------------------------------------------------------------------- - - if ((destP != NULL) && (leP != NULL) && (destP->pool_id == MEM_MNGT_POOL_ID_COPY)) { - destP->data = leP->data; - } else { - msg ("[MEM_MNGT][COPY] copy_mem_block() pool dest src or dest is NULL\n"); - } - - return destP; -} - -//----------------------------------------------------------------------------- -void -display_mem_load (void) -{ - //----------------------------------------------------------------------------- - - msg ("POOL 0 (%d elements of %d Bytes): \n", MEM_MNGT_MB0_NB_BLOCKS, MEM_MNGT_MB0_BLOCK_SIZE); - display_list (&mem->mem_lists[MEM_MNGT_POOL_ID0]); - msg ("POOL 1 (%d elements of %d Bytes): \n", MEM_MNGT_MB1_NB_BLOCKS, MEM_MNGT_MB1_BLOCK_SIZE); - display_list (&mem->mem_lists[MEM_MNGT_POOL_ID1]); - msg ("POOL 2 (%d elements of %d Bytes): \n", MEM_MNGT_MB2_NB_BLOCKS, MEM_MNGT_MB2_BLOCK_SIZE); - display_list (&mem->mem_lists[MEM_MNGT_POOL_ID2]); - msg ("POOL 3 (%d elements of %d Bytes): \n", MEM_MNGT_MB3_NB_BLOCKS, MEM_MNGT_MB3_BLOCK_SIZE); - display_list (&mem->mem_lists[MEM_MNGT_POOL_ID3]); - msg ("POOL 4 (%d elements of %d Bytes): \n", MEM_MNGT_MB4_NB_BLOCKS, MEM_MNGT_MB4_BLOCK_SIZE); - display_list (&mem->mem_lists[MEM_MNGT_POOL_ID4]); - msg ("POOL 5 (%d elements of %d Bytes): \n", MEM_MNGT_MB5_NB_BLOCKS, MEM_MNGT_MB5_BLOCK_SIZE); - display_list (&mem->mem_lists[MEM_MNGT_POOL_ID5]); - msg ("POOL 6 (%d elements of %d Bytes): \n", MEM_MNGT_MB6_NB_BLOCKS, MEM_MNGT_MB6_BLOCK_SIZE); - display_list (&mem->mem_lists[MEM_MNGT_POOL_ID6]); - msg ("POOL 7 (%d elements of %d Bytes): \n", MEM_MNGT_MB7_NB_BLOCKS, MEM_MNGT_MB7_BLOCK_SIZE); - display_list (&mem->mem_lists[MEM_MNGT_POOL_ID7]); - msg ("POOL 8 (%d elements of %d Bytes): \n", MEM_MNGT_MB8_NB_BLOCKS, MEM_MNGT_MB8_BLOCK_SIZE); - display_list (&mem->mem_lists[MEM_MNGT_POOL_ID8]); - msg ("POOL 9 (%d elements of %d Bytes): \n", MEM_MNGT_MB9_NB_BLOCKS, MEM_MNGT_MB9_BLOCK_SIZE); - display_list (&mem->mem_lists[MEM_MNGT_POOL_ID9]); - msg ("POOL C (%d elements): \n", MEM_MNGT_MBCOPY_NB_BLOCKS); - display_list (&mem->mem_lists[MEM_MNGT_POOL_ID_COPY]); -} - -//----------------------------------------------------------------------------- -void -check_mem_area (void *arg) -{ - //----------------------------------------------------------------------------- - int index, mb_index; - mem_pool *memory = (mem_pool *) arg; - - for (index = 0; index < MEM_MNGT_MB0_NB_BLOCKS; index++) { - if ((memory->mem_blocks[index].data != &(memory->mem_pool0[index][0])) && (memory->mem_blocks[index].pool_id != MEM_MNGT_POOL_ID0)) { - msg ("[MEM] ERROR POOL0 block index %d\n", index); - break_point (); - } - } - - mb_index = MEM_MNGT_MB0_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB1_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != &(memory->mem_pool1[index][0])) && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID1)) { - msg ("[MEM] ERROR POOL1 block index %d\n", index); - break_point (); - } - } - - mb_index += MEM_MNGT_MB1_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB2_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != &(memory->mem_pool2[index][0])) && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID2)) { - msg ("[MEM] ERROR POOL2 block index %d\n", index); - break_point (); - } - } - - mb_index += MEM_MNGT_MB2_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB3_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != &(memory->mem_pool3[index][0])) && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID3)) { - msg ("[MEM] ERROR POOL3 block index %d\n", index); - break_point (); - } - } - - mb_index += MEM_MNGT_MB3_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB4_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != &(memory->mem_pool4[index][0])) && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID4)) { - msg ("[MEM] ERROR POOL4 block index %d\n", index); - break_point (); - } - } - - mb_index += MEM_MNGT_MB4_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB5_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != &(memory->mem_pool5[index][0])) && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID5)) { - msg ("[MEM] ERROR POOL5 block index %d\n", index); - break_point (); - } - } - - mb_index += MEM_MNGT_MB5_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB6_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != &(memory->mem_pool6[index][0])) && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID6)) { - msg ("[MEM] ERROR POOL6 block index %d\n", index); - break_point (); - } - } - - mb_index += MEM_MNGT_MB6_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB7_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != &(memory->mem_pool7[index][0])) && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID7)) { - msg ("[MEM] ERROR POOL7 block index %d\n", index); - break_point (); - } - } - - mb_index += MEM_MNGT_MB7_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB8_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != &(memory->mem_pool8[index][0])) && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID8)) { - msg ("[MEM] ERROR POOL8 block index %d\n", index); - break_point (); - } - } - - mb_index += MEM_MNGT_MB8_NB_BLOCKS; - - for (index = 0; index < MEM_MNGT_MB9_NB_BLOCKS; index++) { - if ((memory->mem_blocks[mb_index + index].data != &(memory->mem_pool9[index][0])) && (memory->mem_blocks[mb_index + index].pool_id != MEM_MNGT_POOL_ID9)) { - msg ("[MEM] ERROR POOL9 block index %d\n", index); - break_point (); - } - } - - mb_index += MEM_MNGT_MB9_NB_BLOCKS; - - for (index = mb_index; index < MEM_MNGT_NB_ELEMENTS; index++) { - if ((memory->mem_blocks[index].data != NULL) && (memory->mem_blocks[index].pool_id != MEM_MNGT_POOL_ID_COPY)) { - msg ("[MEM] ERROR POOL COPY block index %d\n", index); - break_point (); - } - } -} - -//----------------------------------------------------------------------------- -void -check_free_mem_block (mem_block_t * leP, __func__) -{ - //----------------------------------------------------------------------------- - int block_index; - - if ((leP >= &mem->mem_blocks[0]) && (leP <= &mem->mem_blocks[MEM_MNGT_NB_ELEMENTS])) { - block_index = ((uint32_t) leP - (uint32_t) (&mem->mem_blocks[0])) / sizeof (mem_block_t); - - if (block_index < MEM_MNGT_MB0_NB_BLOCKS) { - if (((uint32_t) (leP->data) != (uint32_t) (&(mem->mem_pool0[block_index][0]))) && (leP->pool_id != MEM_MNGT_POOL_ID0)) { - msg ("[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - } else if (block_index < (MEM_MNGT_MB0_NB_BLOCKS + MEM_MNGT_MB1_NB_BLOCKS)) { - if ((leP->data != &(mem->mem_pool1[block_index][0])) && (leP->pool_id != MEM_MNGT_POOL_ID1)) { - msg ("[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - } else if (block_index < MEM_MNGT_MB0_NB_BLOCKS + MEM_MNGT_MB1_NB_BLOCKS + MEM_MNGT_MB2_NB_BLOCKS) { - if ((leP->data != &(mem->mem_pool2[block_index][0])) && (leP->pool_id != MEM_MNGT_POOL_ID2)) { - msg ("[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - } else if (block_index < MEM_MNGT_MB0_NB_BLOCKS + MEM_MNGT_MB1_NB_BLOCKS + MEM_MNGT_MB2_NB_BLOCKS + MEM_MNGT_MB3_NB_BLOCKS) { - if ((leP->data != &(mem->mem_pool3[block_index][0])) && (leP->pool_id != MEM_MNGT_POOL_ID3)) { - msg ("[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - } else if (block_index < MEM_MNGT_MB0_NB_BLOCKS + MEM_MNGT_MB1_NB_BLOCKS + MEM_MNGT_MB2_NB_BLOCKS + MEM_MNGT_MB3_NB_BLOCKS + MEM_MNGT_MB4_NB_BLOCKS) { - if ((leP->data != &(mem->mem_pool4[block_index][0])) && (leP->pool_id != MEM_MNGT_POOL_ID4)) { - msg ("[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - } else if (block_index < MEM_MNGT_MB0_NB_BLOCKS + MEM_MNGT_MB1_NB_BLOCKS + MEM_MNGT_MB2_NB_BLOCKS + MEM_MNGT_MB3_NB_BLOCKS + MEM_MNGT_MB4_NB_BLOCKS + - MEM_MNGT_MB5_NB_BLOCKS) { - if ((leP->data != &(mem->mem_pool5[block_index][0])) && (leP->pool_id != MEM_MNGT_POOL_ID5)) { - msg ("[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - } else if (block_index < - MEM_MNGT_MB0_NB_BLOCKS + MEM_MNGT_MB1_NB_BLOCKS + MEM_MNGT_MB2_NB_BLOCKS + MEM_MNGT_MB3_NB_BLOCKS + MEM_MNGT_MB4_NB_BLOCKS + MEM_MNGT_MB5_NB_BLOCKS + - MEM_MNGT_MB6_NB_BLOCKS) { - if ((leP->data != &(mem->mem_pool6[block_index][0])) && (leP->pool_id != MEM_MNGT_POOL_ID6)) { - msg ("[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - } else if (block_index < - MEM_MNGT_MB0_NB_BLOCKS + MEM_MNGT_MB1_NB_BLOCKS + MEM_MNGT_MB2_NB_BLOCKS + MEM_MNGT_MB3_NB_BLOCKS + MEM_MNGT_MB4_NB_BLOCKS + MEM_MNGT_MB5_NB_BLOCKS + - MEM_MNGT_MB6_NB_BLOCKS + - MEM_MNGT_MB7_NB_BLOCKS) { - if ((leP->data != &(mem->mem_pool7[block_index][0])) && (leP->pool_id != MEM_MNGT_POOL_ID7)) { - msg ("[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - } else if (block_index < - MEM_MNGT_MB0_NB_BLOCKS + MEM_MNGT_MB1_NB_BLOCKS + MEM_MNGT_MB2_NB_BLOCKS + MEM_MNGT_MB3_NB_BLOCKS + MEM_MNGT_MB4_NB_BLOCKS + MEM_MNGT_MB5_NB_BLOCKS + - MEM_MNGT_MB6_NB_BLOCKS + - MEM_MNGT_MB7_NB_BLOCKS + MEM_MNGT_MB8_NB_BLOCKS) { - if ((leP->data != &(mem->mem_pool8[block_index][0])) && (leP->pool_id != MEM_MNGT_POOL_ID8)) { - msg ("[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - } else if (block_index < - MEM_MNGT_MB0_NB_BLOCKS + MEM_MNGT_MB1_NB_BLOCKS + MEM_MNGT_MB2_NB_BLOCKS + MEM_MNGT_MB3_NB_BLOCKS + MEM_MNGT_MB4_NB_BLOCKS + MEM_MNGT_MB5_NB_BLOCKS + - MEM_MNGT_MB6_NB_BLOCKS + - MEM_MNGT_MB7_NB_BLOCKS + MEM_MNGT_MB8_NB_BLOCKS + MEM_MNGT_MB9_NB_BLOCKS) { - if ((leP->data != &(mem->mem_pool9[block_index][0])) && (leP->pool_id != MEM_MNGT_POOL_ID9)) { - msg ("[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } - } - - } else { - msg ("[MEM][ERROR][FATAL] free mem block is corrupted\n"); - } -} - -//----------------------------------------------------------------------------- -void -break_point (void) -{ - //----------------------------------------------------------------------------- - int break_var; - - msg ("[BREAK_POINT]\n"); - break_var = 1; -} diff --git a/openair2/UTIL/MEM/mem_mngt_proto_extern.h b/openair2/UTIL/MEM/mem_mngt_proto_extern.h deleted file mode 100644 index 4690bba42e..0000000000 --- a/openair2/UTIL/MEM/mem_mngt_proto_extern.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - diff --git a/openair2/UTIL/MEM/mem_pool.h b/openair2/UTIL/MEM/mem_pool.h deleted file mode 100644 index cc0face78c..0000000000 --- a/openair2/UTIL/MEM/mem_pool.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*************************************************************************** - mem_pool.h - description - ------------------- - AUTHOR : Lionel GAUTHIER - COMPANY : EURECOM - EMAIL : Lionel.Gauthier@eurecom.fr - - - ***************************************************************************/ -#ifndef __MEM_POOL_H__ -# define __MEM_POOL_H__ - -# include "list.h" -# include "mem_block.h" - - -#endif diff --git a/targets/ARCH/rfsimulator/simulator.c b/targets/ARCH/rfsimulator/simulator.c index 7a7e1a31f8..b85cdb507a 100644 --- a/targets/ARCH/rfsimulator/simulator.c +++ b/targets/ARCH/rfsimulator/simulator.c @@ -33,7 +33,7 @@ #include #define PORT 4043 //default TCP port for this simulator -#define CirSize 3072000 // 100ms is enough +#define CirSize 307200 // 100ms is enough #define sampleToByte(a,b) ((a)*(b)*sizeof(sample_t)) #define byteToSample(a,b) ((a)/(sizeof(sample_t)*(b))) @@ -106,7 +106,7 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) { ptr->headerMode=true; ptr->transferPtr=(char *)&ptr->th; ptr->remainToTransfer=sizeof(samplesBlockHeader_t); - int sendbuff=1000*1000*10; + int sendbuff=1000*1000*100; AssertFatal ( setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff)) == 0, ""); struct epoll_event ev= {0}; ev.events = EPOLLIN | EPOLLRDHUP; @@ -183,7 +183,7 @@ void setblocking(int sock, enum blocking_t active) { AssertFatal(fcntl(sock, F_SETFL, opts) >= 0, ""); } -static bool flushInput(rfsimulator_state_t *t, int timeout); +static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps); void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) { if (t->saveIQfile != -1) { @@ -207,7 +207,8 @@ void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) { if(errno==EAGAIN) { // The opposite side is saturated // we read incoming sockets meawhile waiting - flushInput(t, 5); + //flushInput(t, 5); + usleep(500); continue; } else return; @@ -316,17 +317,19 @@ sin_addr: return 0; } -int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) { - rfsimulator_state_t *t = device->priv; +static int rfsimulator_write_internal(rfsimulator_state_t *t, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) { LOG_D(HW,"sending %d samples at time: %ld\n", nsamps, timestamp); for (int i=0; ibuf[i]; if (b->conn_sock >= 0 ) { - if ( abs((double)b->lastWroteTS-timestamp) > (double)CirSize) - LOG_E(HW,"Tx/Rx shift too large Tx:%lu, Rx:%lu\n", b->lastWroteTS, b->lastReceivedTS); + pthread_mutex_lock(&Sockmutex); + if ( b->lastWroteTS != 0 && abs((double)b->lastWroteTS-timestamp) > (double)CirSize) + LOG_E(HW,"Discontinuous TX gap too large Tx:%lu, %lu\n", b->lastWroteTS, timestamp); + + AssertFatal(b->lastWroteTS <= timestamp+1, " Not supported to send Tx out of order (same in USRP) %lu, %lu\n", b->lastWroteTS, timestamp); samplesBlockHeader_t header= {t->typeStamp, nsamps, nbAnt, timestamp}; fullwrite(b->conn_sock,&header, sizeof(header), t); sample_t tmpSamples[nsamps][nbAnt]; @@ -342,19 +345,23 @@ int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, voi fullwrite(b->conn_sock, (void *)tmpSamples, sampleToByte(nsamps,nbAnt), t); b->lastWroteTS=timestamp+nsamps; } + + pthread_mutex_unlock(&Sockmutex); } } 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 - flushInput(t, 0); - pthread_mutex_unlock(&Sockmutex); return nsamps; } -static bool flushInput(rfsimulator_state_t *t, int timeout) { +int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) { + return rfsimulator_write_internal(device->priv, timestamp, samplesVoid, nsamps, nbAnt, flags); +} + + + +static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initial) { // Process all incoming events on sockets // store the data in lists struct epoll_event events[FD_SETSIZE]= {0}; @@ -375,7 +382,29 @@ static bool flushInput(rfsimulator_state_t *t, int timeout) { AssertFatal( (conn_sock = accept(t->listen_sock,NULL,NULL)) != -1, ""); setblocking(conn_sock, notBlocking); allocCirBuf(t, conn_sock); - LOG_I(HW,"A ue connected\n"); + LOG_I(HW,"A ue connected, sending the current time\n"); + struct complex16 v= {0}; + void *samplesVoid[t->tx_num_channels]; + + for ( int i=0; i < t->tx_num_channels; i++) + samplesVoid[i]=(void *)&v; + + pthread_mutex_lock(&Sockmutex); + openair0_timestamp timestamp=1; + + for (int i=0; ibuf[i]; + + if (t->buf[i].circularBuf != NULL && t->buf[i].lastWroteTS > 1) { + timestamp=b->lastWroteTS; + break; + } + } + + pthread_mutex_unlock(&Sockmutex); + rfsimulator_write_internal(t, timestamp-1, + samplesVoid, 1, + t->tx_num_channels, 1); } else { if ( events[nbEv].events & (EPOLLHUP | EPOLLERR | EPOLLRDHUP) ) { socketError(t,fd); @@ -432,26 +461,34 @@ static bool flushInput(rfsimulator_state_t *t, int timeout) { } if ( abs(b->th.timestamp-b->lastReceivedTS) > 50 ) - LOG_W(HW,"gap of: %ld in reception\n", b->th.timestamp-b->lastReceivedTS ); + LOG_W(HW,"UEsock: %d gap of: %ld in reception\n", fd, b->th.timestamp-b->lastReceivedTS ); } b->lastReceivedTS=b->th.timestamp; - AssertFatal(b->lastWroteTS == 0 || ( abs((double)b->lastWroteTS-b->lastReceivedTS) < (double)CirSize), - "Tx/Rx shift too large Tx:%lu, Rx:%lu\n", b->lastWroteTS, b->lastReceivedTS); + pthread_mutex_lock(&Sockmutex); + + if (b->lastWroteTS != 0 && ( abs((double)b->lastWroteTS-b->lastReceivedTS) > (double)CirSize)) + LOG_E(HW,"UEsock: %d Tx/Rx shift too large Tx:%lu, Rx:%lu\n", fd, b->lastWroteTS, b->lastReceivedTS); + + pthread_mutex_unlock(&Sockmutex); 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); + LOG_D(HW,"UEsock: %d Set b->lastReceivedTS %ld\n", fd, 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 ( t->nextTimestamp == 0 && b->th.size < b->lastReceivedTS) { + t->nextTimestamp=b->lastReceivedTS > nsamps_for_initial ? + b->lastReceivedTS - nsamps_for_initial : + 0; + LOG_W(HW,"UE got first timestamp: starting at %lu\n", t->nextTimestamp); + } if ( b->remainToTransfer==0) { - LOG_D(HW,"Completed block reception: %ld\n", b->lastReceivedTS); + LOG_D(HW,"UEsock: %d Completed block reception: %ld\n", fd, b->lastReceivedTS); b->headerMode=true; b->transferPtr=(char *)&b->th; b->remainToTransfer=sizeof(samplesBlockHeader_t); @@ -469,7 +506,6 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo 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 @@ -485,7 +521,7 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo if ( t->nextTimestamp == 0) LOG_W(HW,"No connected device, generating void samples...\n"); - if (!flushInput(t, 10)) { + if (!flushInput(t, 10, nsamps)) { for (int x=0; x < nbAnt; x++) memset(samplesVoid[x],0,sampleToByte(nsamps,1)); @@ -495,7 +531,6 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo LOG_W(HW,"Generated void samples for Rx: %ld\n", t->nextTimestamp); *ptimestamp = t->nextTimestamp-nsamps; - pthread_mutex_unlock(&Sockmutex); return nsamps; } } else { @@ -507,26 +542,6 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo for ( int sock=0; sockbuf[sock]; - if ( b->circularBuf) { - LOG_D(HW,"sock: %d, lastWroteTS: %lu, lastRecvTS: %lu, TS must be avail: %lu\n", - sock, b->lastWroteTS, - b->lastReceivedTS, - t->nextTimestamp+nsamps); - - if ( b->lastReceivedTS > b->lastWroteTS ) { - // The caller momdem (NB, UE, ...) must send Tx in advance, so we fill TX if Rx is in advance - // This occurs for example when UE is in sync mode: it doesn't transmit - // with USRP, it seems ok: if "tx stream" is off, we may consider it actually cuts the Tx power - struct complex16 v= {0}; - void *samplesVoid[b->th.nbAnt]; - - for ( int i=0; i th.nbAnt; i++) - samplesVoid[i]=(void *)&v; - - rfsimulator_write(device, b->lastReceivedTS, samplesVoid, 1, b->th.nbAnt, 0); - } - } - if ( b->circularBuf ) if ( t->nextTimestamp+nsamps > b->lastReceivedTS ) { have_to_wait=true; @@ -539,7 +554,7 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo ptr->lastReceivedTS, t->nextTimestamp+nsamps); */ - flushInput(t, 3); + flushInput(t, 3, nsamps); } while (have_to_wait); } @@ -586,7 +601,6 @@ 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) { diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index e31149b665..f0f1829cad 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -264,7 +264,7 @@ static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name eNB->UL_INFO.subframe = proc->subframe_rx; eNB->UL_INFO.module_id = eNB->Mod_id; eNB->UL_INFO.CC_id = eNB->CC_id; - eNB->if_inst->UL_indication(&eNB->UL_INFO); + eNB->if_inst->UL_indication(&eNB->UL_INFO, proc); AssertFatal((ret= pthread_mutex_unlock(&eNB->UL_INFO_mutex))==0,"error unlocking UL_INFO_mutex, return %d\n",ret); /* this conflict resolution may be totally wrong, to be tested */ @@ -762,7 +762,7 @@ static void *eNB_thread_prach( void *param ) { if (oai_exit) break; LOG_D(PHY,"Running eNB prach procedures\n"); - prach_procedures(eNB + prach_procedures(eNB, &eNB->proc.L1_proc #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) ,0 #endif @@ -796,7 +796,7 @@ static void *eNB_thread_prach_br( void *param ) { if (oai_exit) break; LOG_D(PHY,"Running eNB prach procedures for BL/CE UEs\n"); - prach_procedures(eNB,1); + prach_procedures(eNB, &eNB->proc.L1_proc,1); if (release_thread(&proc->mutex_prach_br,&proc->instance_cnt_prach_br,"eNB_prach_thread_br") < 0) break; } @@ -810,11 +810,6 @@ static void *eNB_thread_prach_br( void *param ) { -extern void init_td_thread(PHY_VARS_eNB *); -extern void init_te_thread(PHY_VARS_eNB *); -extern void kill_td_thread(PHY_VARS_eNB *); -extern void kill_te_thread(PHY_VARS_eNB *); - static void *process_stats_thread(void *param) { PHY_VARS_eNB *eNB = (PHY_VARS_eNB *)param; wait_sync("process_stats_thread"); @@ -919,12 +914,12 @@ void init_eNB_proc(int inst) { // attr_td = &proc->attr_td; // attr_te = &proc->attr_te; #endif - +/* if(get_thread_worker_conf() == WORKER_ENABLE) { init_te_thread(eNB); init_td_thread(eNB); } - +*/ LOG_I(PHY,"eNB->single_thread_flag:%d\n", eNB->single_thread_flag); if ((get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT) && NFAPI_MODE!=NFAPI_MODE_VNF) { @@ -990,12 +985,12 @@ void kill_eNB_proc(int inst) { proc = &eNB->proc; L1_proc = &proc->L1_proc; L1_proc_tx = &proc->L1_proc_tx; - +/* if(get_thread_worker_conf() == WORKER_ENABLE) { kill_td_thread(eNB); kill_te_thread(eNB); } - +*/ LOG_I(PHY, "Killing TX CC_id %d inst %d\n", CC_id, inst ); if ((get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) && NFAPI_MODE!=NFAPI_MODE_VNF) { diff --git a/targets/RT/USER/lte-ru.c b/targets/RT/USER/lte-ru.c index 9310d55595..90af3c4eed 100644 --- a/targets/RT/USER/lte-ru.c +++ b/targets/RT/USER/lte-ru.c @@ -176,7 +176,7 @@ static inline void fh_if4p5_south_out(RU_t *ru) { void fh_if5_south_in(RU_t *ru,int *frame, int *subframe) { LTE_DL_FRAME_PARMS *fp = &ru->frame_parms; RU_proc_t *proc = &ru->proc; - recv_IF5(ru, &proc->timestamp_rx, *subframe, IF5_RRH_GW_UL); + recv_IF5(ru, &ru->eNB_list[0]->proc.L1_proc, &proc->timestamp_rx, *subframe, IF5_RRH_GW_UL); proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023; proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10; @@ -391,7 +391,7 @@ void fh_if5_north_asynch_in(RU_t *ru,int *frame,int *subframe) { RU_proc_t *proc = &ru->proc; int subframe_tx,frame_tx; openair0_timestamp timestamp_tx; - recv_IF5(ru, ×tamp_tx, *subframe, IF5_RRH_GW_DL); + recv_IF5(ru,&ru->eNB_list[0]->proc.L1_proc, ×tamp_tx, *subframe, IF5_RRH_GW_DL); // printf("Received subframe %d (TS %llu) from RCC\n",subframe_tx,timestamp_tx); subframe_tx = (timestamp_tx/fp->samples_per_tti)%10; frame_tx = (timestamp_tx/(fp->samples_per_tti*10))&1023; @@ -482,9 +482,9 @@ void fh_if4p5_north_asynch_in(RU_t *ru,int *frame,int *subframe) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_IF4P5_NORTH_ASYNCH_IN,subframe_tx); } - if (ru->feptx_ofdm) ru->feptx_ofdm(ru); + if (ru->feptx_ofdm) ru->feptx_ofdm(ru, &ru->eNB_list[0]->proc.L1_proc ); - if (ru->fh_south_out) ru->fh_south_out(ru); + if (ru->fh_south_out) ru->fh_south_out(ru , &ru->eNB_list[0]->proc.L1_proc); } void fh_if5_north_out(RU_t *ru) { @@ -931,12 +931,14 @@ void *ru_thread_prach( void *param ) { if (ru->eNB_list[0]) { prach_procedures( ru->eNB_list[0] + , &ru->eNB_list[0]->proc.L1_proc #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) ,0 #endif ); } else { rx_prach(NULL, + &ru->eNB_list[0]->proc.L1_proc, ru, NULL, NULL, @@ -976,6 +978,7 @@ void *ru_thread_prach_br( void *param ) { if (oai_exit) break; rx_prach(NULL, + &ru->eNB_list[0]->proc.L1_proc, ru, NULL, NULL, @@ -1176,7 +1179,7 @@ void wakeup_L1s(RU_t *ru) { if (ru->wait_cnt == 0) { if (ru->num_eNB==1 && ru->eNB_top!=0 && get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD) - ru->eNB_top(eNB_list[0],proc->frame_rx,proc->subframe_rx,string,ru); + ru->eNB_top(eNB_list[0],&proc->L1_proc, proc->frame_rx,proc->subframe_rx,string,ru); else { for (i=0; inum_eNB; i++) { eNB_list[i]->proc.ru_proc = &ru->proc; @@ -1493,14 +1496,14 @@ void *ru_thread_tx( void *param ) { if (oai_exit) break; // do TX front-end processing if needed (precoding and/or IDFTs) - if (ru->feptx_prec) ru->feptx_prec(ru); + if (ru->feptx_prec) ru->feptx_prec(ru, L1_proc); // do OFDM if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru); + if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru, L1_proc); if(!(get_softmodem_params()->emulate_rf)) { // do outgoing fronthaul (south) if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru); + if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru, L1_proc); } LOG_D(PHY,"ru_thread_tx: releasing RU TX in %d.%d\n",proc->frame_tx,proc->subframe_tx); @@ -1765,7 +1768,7 @@ void *ru_thread( void *param ) { wakeup_slaves(proc); // do RX front-end processing (frequency-shift, dft) if needed - if (ru->feprx) ru->feprx(ru); + if (ru->feprx) ru->feprx(ru, &ru->eNB_list[0]->proc.L1_proc); // wakeup all eNB processes waiting for this RU AssertFatal((ret=pthread_mutex_lock(&proc->mutex_eNBs))==0,"mutex_lock returns %d\n",ret); @@ -1801,14 +1804,14 @@ void *ru_thread( void *param ) { if(get_thread_parallel_conf() == PARALLEL_SINGLE_THREAD || ru->num_eNB==0) { // do TX front-end processing if needed (precoding and/or IDFTs) - if (ru->feptx_prec) ru->feptx_prec(ru); + if (ru->feptx_prec) ru->feptx_prec(ru, &ru->eNB_list[0]->proc.L1_proc); // do OFDM if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru); + if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru, &ru->eNB_list[0]->proc.L1_proc); if(!(get_softmodem_params()->emulate_rf)) { // do outgoing fronthaul (south) if needed - if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru); + if ((ru->fh_north_asynch_in == NULL) && (ru->fh_south_out)) ru->fh_south_out(ru, &ru->eNB_list[0]->proc.L1_proc); if ((ru->fh_north_out) && (ru->state!=RU_CHECK_SYNC)) ru->fh_north_out(ru); } @@ -2240,12 +2243,12 @@ void init_RU_proc(RU_t *ru) { exit(-1); } } - +/* if (get_thread_worker_conf() == WORKER_ENABLE) { init_fep_thread(ru,NULL); init_feptx_thread(ru,NULL); } - +*/ if (opp_enabled == 1) pthread_create(&ru->ru_stats_thread,NULL,ru_stats_thread,(void *)ru); if (ru->function == eNodeB_3GPP) { @@ -2286,14 +2289,14 @@ void kill_RU_proc(RU_t *ru) { pthread_mutex_destroy( &proc->mutex_rf_tx); pthread_cond_destroy( &proc->cond_rf_tx); #endif - +/* if (get_thread_worker_conf() == WORKER_ENABLE) { LOG_D(PHY, "killing FEP thread\n"); kill_fep_thread(ru); LOG_D(PHY, "killing FEP TX thread\n"); kill_feptx_thread(ru); } - +*/ AssertFatal((ret=pthread_mutex_lock(&proc->mutex_FH))==0,"mutex_lock returns %d\n",ret); proc->instance_cnt_FH = 0; pthread_cond_signal(&proc->cond_FH); @@ -2453,8 +2456,8 @@ void set_function_spec_param(RU_t *ru) { ru->fh_north_out = fh_if4p5_north_out; // send_IF4p5 on reception ru->fh_south_out = tx_rf; // send output to RF ru->fh_north_asynch_in = fh_if4p5_north_asynch_in; // TX packets come asynchronously - ru->feprx = (get_thread_worker_conf() == WORKER_DISABLE) ? fep_full :ru_fep_full_2thread; // RX DFTs - ru->feptx_ofdm = (get_thread_worker_conf() == WORKER_DISABLE) ? feptx_ofdm : feptx_ofdm_2thread; // this is fep with idft only (no precoding in RRU) + ru->feprx = fep_full; // RX DFTs + ru->feptx_ofdm = feptx_ofdm; // this is fep with idft only (no precoding in RRU) ru->feptx_prec = NULL; ru->start_if = start_if; // need to start the if interface for if4p5 ru->ifdevice.host_type = RRU_HOST; @@ -2475,8 +2478,8 @@ void set_function_spec_param(RU_t *ru) { malloc_IF4p5_buffer(ru); } else if (ru->function == eNodeB_3GPP) { ru->do_prach = 0; // no prach processing in RU - ru->feprx = (get_thread_worker_conf() == WORKER_DISABLE) ? fep_full : ru_fep_full_2thread; // RX DFTs - ru->feptx_ofdm = (get_thread_worker_conf() == WORKER_DISABLE) ? feptx_ofdm : feptx_ofdm_2thread; // this is fep with idft and precoding + ru->feprx = fep_full; // RX DFTs + ru->feptx_ofdm = feptx_ofdm; // this is fep with idft and precoding ru->feptx_prec = feptx_prec; // this is fep with idft and precoding ru->fh_north_in = NULL; // no incoming fronthaul from north ru->fh_north_out = NULL; // no outgoing fronthaul to north @@ -2505,9 +2508,9 @@ void set_function_spec_param(RU_t *ru) { case REMOTE_IF5: // the remote unit is IF5 RRU ru->do_prach = 0; - ru->feprx = (get_thread_worker_conf() == WORKER_DISABLE) ? fep_full : fep_full; // this is frequency-shift + DFTs + ru->feprx = fep_full; // this is frequency-shift + DFTs ru->feptx_prec = feptx_prec; // need to do transmit Precoding + IDFTs - ru->feptx_ofdm = (get_thread_worker_conf() == WORKER_DISABLE) ? feptx_ofdm : feptx_ofdm_2thread; // need to do transmit Precoding + IDFTs + ru->feptx_ofdm = feptx_ofdm ; // need to do transmit Precoding + IDFTs if (ru->if_timing == synch_to_other) { ru->fh_south_in = fh_slave_south_in; // synchronize to master diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c index 6c4087d08f..23fc5e3aba 100644 --- a/targets/RT/USER/lte-ue.c +++ b/targets/RT/USER/lte-ue.c @@ -1492,6 +1492,23 @@ static void *UE_phy_stub_thread_rxn_txnp4(void *arg) { * \param arg unused * \returns a pointer to an int. The storage is not on the heap and must not be freed. */ +void write_dummy(PHY_VARS_UE *UE, openair0_timestamp timestamp) { + // we have to write to tell explicitly to the eNB, else it will wait for us forever + // we write the next subframe (always write in future of what we received) + // + struct complex16 v= {0}; + void *samplesVoid[UE->frame_parms.nb_antennas_tx]; + + for ( int i=0; i < UE->frame_parms.nb_antennas_tx; i++) + samplesVoid[i]=(void *)&v; + + AssertFatal( 1 == UE->rfdevice.trx_write_func(&UE->rfdevice, + timestamp+2*UE->frame_parms.samples_per_tti, + samplesVoid, + 1, + UE->frame_parms.nb_antennas_tx, + 1),""); +} void *UE_thread(void *arg) { PHY_VARS_UE *UE = (PHY_VARS_UE *) arg; @@ -1542,21 +1559,25 @@ void *UE_thread(void *arg) { int instance_cnt_synch = UE->proc.instance_cnt_synch; int is_synchronized = UE->is_synchronized; AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), ""); - + if (is_synchronized == 0) { if (instance_cnt_synch < 0) { // we can invoke the synch // grab 10 ms of signal and wakeup synch thread - for (int i=0; iframe_parms.nb_antennas_rx; i++) - rxp[i] = (void *)&UE->common_vars.rxdata[i][0]; - if (UE->mode != loop_through_memory) - AssertFatal( UE->frame_parms.samples_per_tti*10 == - UE->rfdevice.trx_read_func(&UE->rfdevice, - ×tamp, - rxp, - UE->frame_parms.samples_per_tti*10, - UE->frame_parms.nb_antennas_rx), ""); - + for(int sf=0; sf<10; sf++) { + for (int i=0; iframe_parms.nb_antennas_rx; i++) + rxp[i] = (void *)&UE->common_vars.rxdata[i][UE->frame_parms.samples_per_tti*sf]; + + AssertFatal( UE->frame_parms.samples_per_tti == + UE->rfdevice.trx_read_func(&UE->rfdevice, + ×tamp, + rxp, + UE->frame_parms.samples_per_tti, + UE->frame_parms.nb_antennas_rx), ""); + if (IS_SOFTMODEM_RFSIM ) + write_dummy(UE, timestamp); + } + AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), ""); instance_cnt_synch = ++UE->proc.instance_cnt_synch; @@ -1579,13 +1600,16 @@ void *UE_thread(void *arg) { for (int i=0; iframe_parms.nb_antennas_rx; i++) rxp[i] = (void *)&dummy_rx[i][0]; - for (int sf=0; sf<10; sf++) + for (int sf=0; sf<10; sf++) { // printf("Reading dummy sf %d\n",sf); UE->rfdevice.trx_read_func(&UE->rfdevice, ×tamp, rxp, UE->frame_parms.samples_per_tti, UE->frame_parms.nb_antennas_rx); + if (IS_SOFTMODEM_RFSIM ) + write_dummy(UE, timestamp); + } } #endif @@ -1598,12 +1622,18 @@ void *UE_thread(void *arg) { if (UE->mode != loop_through_memory) { if (UE->no_timing_correction==0) { LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode); - AssertFatal(UE->rx_offset == - UE->rfdevice.trx_read_func(&UE->rfdevice, - ×tamp, - (void **)UE->common_vars.rxdata, - UE->rx_offset, - UE->frame_parms.nb_antennas_rx),""); + while ( UE->rx_offset ) { + size_t s=min(UE->rx_offset,UE->frame_parms.samples_per_tti); + AssertFatal(s == + UE->rfdevice.trx_read_func(&UE->rfdevice, + ×tamp, + (void **)UE->common_vars.rxdata, + s, + UE->frame_parms.nb_antennas_rx),""); + if (IS_SOFTMODEM_RFSIM ) + write_dummy(UE, timestamp); + UE->rx_offset-=s; + } } UE->rx_offset=0; @@ -1644,7 +1674,7 @@ void *UE_thread(void *arg) { pthread_mutex_unlock(&proc->mutex_rxtx); } - usleep(3000); + usleep(300); } LOG_D(PHY,"Process Subframe %d thread Idx %d \n", sub_frame, UE->current_thread_id[sub_frame]); diff --git a/targets/RT/USER/lte-uesoftmodem.c b/targets/RT/USER/lte-uesoftmodem.c index 9995b43f90..88b9b13233 100644 --- a/targets/RT/USER/lte-uesoftmodem.c +++ b/targets/RT/USER/lte-uesoftmodem.c @@ -597,6 +597,11 @@ void init_pdcp(void) { pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind); } +// Stupid function addition because UE itti messages queues definition is common with eNB +void *rrc_enb_process_itti_msg(void *notUsed) { + return NULL; +} + int main( int argc, char **argv ) { int CC_id; uint8_t abstraction_flag=0; @@ -657,6 +662,7 @@ int main( int argc, char **argv ) { pthread_cond_init(&sync_cond,NULL); pthread_mutex_init(&sync_mutex, NULL); printf("ITTI init\n"); +#define UE itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info); // initialize mscgen log after ITTI From beda33b8f1a5f6c0f08c8fcdd04662b7d652ff9b Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Mon, 11 Nov 2019 20:15:27 +0100 Subject: [PATCH 061/240] CI: fix UL iperf in distributed env Signed-off-by: Raphael Defosseux --- ci-scripts/Jenkinsfile-inria-r2lab | 4 - ci-scripts/main.py | 99 ++++++++++++++++--- .../enb_ue_usrp210_band7_test_05mhz_tm1.xml | 2 +- .../enb_usrp210_band7_test_05mhz_tm1.xml | 86 ++++++++-------- 4 files changed, 129 insertions(+), 62 deletions(-) diff --git a/ci-scripts/Jenkinsfile-inria-r2lab b/ci-scripts/Jenkinsfile-inria-r2lab index 6ae7522999..778c571645 100644 --- a/ci-scripts/Jenkinsfile-inria-r2lab +++ b/ci-scripts/Jenkinsfile-inria-r2lab @@ -183,7 +183,6 @@ pipeline { sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labEPC0} \"echo ${fitpasswd} | sudo -S ifconfig control:m11 172.16.1.102 up\"'" sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labEPC0} \"echo ${fitpasswd} | sudo -S ifconfig control:m10 192.168.10.110 up\"'" sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labEPC0} \"echo ${fitpasswd} | sudo -S ifconfig control:sxu 172.55.55.102 up\"'" - sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labEPC0} \"echo ${fitpasswd} | sudo -S ifconfig control:s1u 192.168.248.159 up\"'" sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labEPC0} \"echo ${fitpasswd} | sudo -S ifconfig control:sxc 172.55.55.101 up\"'" sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labEPC0} \"echo ${fitpasswd} | sudo -S ifconfig control:s5c 172.58.58.102 up\"'" sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labEPC0} \"echo ${fitpasswd} | sudo -S ifconfig control:p5c 172.58.58.101 up\"'" @@ -195,9 +194,6 @@ pipeline { sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labEPC0} \"echo ${fitpasswd} | sudo -S ip rule add from 12.0.0.0/8 table lte\"'" sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labEPC0} \"echo ${fitpasswd} | sudo -S ip rule add from 12.1.1.0/8 table lte\"'" - // Adding a route on the eNB for the S1U interface - sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labENB0} \"echo ${fitpasswd} | sudo -S ip route add 192.168.248.0/24 via ${r2labEPC0IpAddr} dev control\"'" - // For the moment, simple way to route traffic from python executor to any UEs sh "ssh -t inria_oaici@faraday.inria.fr 'ssh -t -b 192.168.3.100 ${fituser}@${r2labPythonExe} \"echo ${fitpasswd} | sudo -S ip route add 12.1.1.0/24 via ${r2labEPC0IpAddr} dev control\"'" } diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 0909b42747..a60a31c04a 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -1856,11 +1856,27 @@ class SSHConnection(): def Ping_common(self, lock, UE_IPAddress, device_id, statusQueue): try: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('cd scripts', '\$', 5) + # Launch ping on the EPC side (true for ltebox and old open-air-cn) + # But for OAI-Rel14-CUPS, we launch from python executor + launchFromEpc = True + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + launchFromEpc = False ping_time = re.findall("-c (\d+)",str(self.ping_args)) - ping_status = self.command('stdbuf -o0 ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) + + if launchFromEpc: + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('cd ' + self.EPCSourceCodePath, '\$', 5) + self.command('cd scripts', '\$', 5) + ping_status = self.command('stdbuf -o0 ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) + else: + cmd = 'ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 > ping_' + self.testCase_id + '_' + device_id + '.log' + message = cmd + '\n' + logging.debug(cmd) + ret = subprocess.run(cmd, shell=True) + ping_status = ret.returncode + self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'ping_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('cat ' + self.EPCSourceCodePath + '/scripts/ping_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) # TIMEOUT CASE if ping_status < 0: message = 'Ping with UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT!' @@ -2170,7 +2186,7 @@ class SSHConnection(): req_bandwidth = '%.1f Gbits/sec' % req_bw req_bw = req_bw * 1000000000 - result = re.search('Server Report:\\\\r\\\\n(?:|\[ *\d+\].*) (?P[0-9\.]+ [KMG]bits\/sec) +(?P[0-9\.]+ ms) +(\d+\/..\d+) (\((?P[0-9\.]+)%\))', str(self.ssh.before)) + result = re.search('Server Report:\\\\r\\\\n(?:|\[ *\d+\].*) (?P[0-9\.]+ [KMG]bits\/sec) +(?P[0-9\.]+ ms) +(\d+\/..\d+) +(\((?P[0-9\.]+)%\))', str(self.ssh.before)) if result is not None: bitrate = result.group('bitrate') packetloss = result.group('packetloss') @@ -2218,6 +2234,8 @@ class SSHConnection(): statusQueue.put(msg) lock.release() return 0 + else: + return -2 def Iperf_analyzeV2Server(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): if (not os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): @@ -2387,11 +2405,17 @@ class SSHConnection(): self.command('echo $USER; nohup iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.EPCUserName, 5) self.close() else: - if udpIperf: - cmd = 'nohup iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log 2>&1 &' + if self.ueIperfVersion == self.dummyIperfVersion: + prefix = '' else: - cmd = 'nohup iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log 2>&1 &' - logging.debug(cmd + '\n') + prefix = '' + if self.ueIperfVersion == '2.0.5': + prefix = '/opt/iperf-2.0.5/bin/' + if udpIperf: + cmd = 'nohup ' + prefix + 'iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log 2>&1 &' + else: + cmd = 'nohup ' + prefix + 'iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log 2>&1 &' + logging.debug(cmd) subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, encoding='utf-8') time.sleep(0.5) @@ -2416,7 +2440,12 @@ class SSHConnection(): if (device_id == 'OAI-UE'): iperf_status = self.command('iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + ' -B ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) else: - iperf_status = self.command('stdbuf -o0 adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '" 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + if self.ADBCentralized: + iperf_status = self.command('stdbuf -o0 adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '" 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + else: + iperf_status = self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '"\' 2>&1 > iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + self.command('fromdos -o iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + self.command('cat iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) # TIMEOUT Case if iperf_status < 0: self.close() @@ -2435,12 +2464,12 @@ class SSHConnection(): self.close() else: cmd = 'killall --signal SIGKILL iperf' - logging.debug(cmd + '\n') + logging.debug(cmd) subprocess.run(cmd, shell=True) time.sleep(1) self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') # in case of failure, retrieve server log - if (clientStatus == -1): + if (clientStatus == -1) or (clientStatus == -2): if launchFromEpc: time.sleep(1) if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): @@ -2459,6 +2488,8 @@ class SSHConnection(): return useIperf3 = False udpIperf = True + + self.ueIperfVersion = '2.0.5' if (device_id != 'OAI-UE'): self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) # if by chance ADB server and EPC are on the same remote host, at least log collection will take care of it @@ -2478,9 +2509,30 @@ class SSHConnection(): self.close() self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) return + else: + if self.ADBCentralized: + self.command('adb -s ' + device_id + ' shell "/data/local/tmp/iperf --version"', '\$', 5) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf --version"\'', '\$', 60) + result = re.search('iperf version 2.0.5', str(self.ssh.before)) + if result is not None: + self.ueIperfVersion = '2.0.5' + result = re.search('iperf version 2.0.10', str(self.ssh.before)) + if result is not None: + self.ueIperfVersion = '2.0.10' else: useIperf3 = True self.close() + else: + self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + self.command('iperf --version', '\$', 5) + result = re.search('iperf version 2.0.5', str(self.ssh.before)) + if result is not None: + self.ueIperfVersion = '2.0.5' + result = re.search('iperf version 2.0.10', str(self.ssh.before)) + if result is not None: + self.ueIperfVersion = '2.0.10' + self.close() # in case of iperf, UL has its own function if (not useIperf3): result = re.search('-R', str(self.iperf_args)) @@ -2515,7 +2567,7 @@ class SSHConnection(): self.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) else: self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - self.command('echo $USER; nohup ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &\' > /dev/null 2>&1', self.ADBUserName, 60) + self.command('echo $USER; nohup ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" \' 2>&1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 60) time.sleep(0.5) self.close() @@ -2551,7 +2603,13 @@ class SSHConnection(): if launchFromEpc: iperf_status = self.command('stdbuf -o0 iperf -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) else: - cmd = 'iperf -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 > iperf_' + self.testCase_id + '_' + device_id + '.log' + if self.ueIperfVersion == self.dummyIperfVersion: + prefix = '' + else: + prefix = '' + if self.ueIperfVersion == '2.0.5': + prefix = '/opt/iperf-2.0.5/bin/' + cmd = prefix + 'iperf -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 > iperf_' + self.testCase_id + '_' + device_id + '.log' message = cmd + '\n' logging.debug(cmd) ret = subprocess.run(cmd, shell=True) @@ -2596,6 +2654,7 @@ class SSHConnection(): self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') else: self.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, self.EPCSourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + self.command('fromdos -o iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) # in case of OAI UE: @@ -2730,6 +2789,18 @@ class SSHConnection(): self.CreateHtmlTestRow(self.iperf_args, 'KO', UE_IP_ADDRESS_ISSUE) self.AutoTerminateUEandeNB() return + + self.dummyIperfVersion = '2.0.10' + #cmd = 'iperf --version' + #logging.debug(cmd + '\n') + #iperfStdout = subprocess.check_output(cmd, shell=True, universal_newlines=True) + #result = re.search('iperf version 2.0.5', str(iperfStdout.strip())) + #if result is not None: + # dummyIperfVersion = '2.0.5' + #result = re.search('iperf version 2.0.10', str(iperfStdout.strip())) + #if result is not None: + # dummyIperfVersion = '2.0.10' + multi_jobs = [] i = 0 ue_num = len(self.UEIPAddresses) diff --git a/ci-scripts/xml_files/inria/enb_ue_usrp210_band7_test_05mhz_tm1.xml b/ci-scripts/xml_files/inria/enb_ue_usrp210_band7_test_05mhz_tm1.xml index 1471b9a016..0196bf1ab6 100644 --- a/ci-scripts/xml_files/inria/enb_ue_usrp210_band7_test_05mhz_tm1.xml +++ b/ci-scripts/xml_files/inria/enb_ue_usrp210_band7_test_05mhz_tm1.xml @@ -68,7 +68,7 @@ Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 diff --git a/ci-scripts/xml_files/inria/enb_usrp210_band7_test_05mhz_tm1.xml b/ci-scripts/xml_files/inria/enb_usrp210_band7_test_05mhz_tm1.xml index 6bc52568c3..964550d872 100644 --- a/ci-scripts/xml_files/inria/enb_usrp210_band7_test_05mhz_tm1.xml +++ b/ci-scripts/xml_files/inria/enb_usrp210_band7_test_05mhz_tm1.xml @@ -24,11 +24,11 @@ test-05-tm1 Test-05MHz-TM1 tasks - 4 + 1 - 030201 040101 + 040101 030201 030103 000002 - 040301 000002 040504 000001 040401 + 040301 000002 040504 040605 040606 040645 040646 040401 040301 000002 040505 000001 040401 040301 000002 040506 000001 040401 040301 000002 040507 000001 040401 @@ -114,252 +114,252 @@ Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 Ping ping (5MHz - 20 sec) - -I 192.168.248.159 -c 20 + -c 20 5 @@ -372,8 +372,8 @@ Iperf - iperf (5MHz - DL/12Mbps/UDP)(30 sec) - -u -b 12M -t 30 -i 1 -fm + iperf (5MHz - DL/15Mbps/UDP)(30 sec) + -u -b 15M -t 30 -i 1 -fm 50 @@ -386,8 +386,8 @@ Iperf - iperf (5MHz - UL/2Mbps/UDP)(30 sec) - -u -b 2M -t 30 -i 1 -fm -R + iperf (5MHz - UL/3.8Mbps/UDP)(30 sec) + -u -b 3.8M -t 30 -i 1 -fm -R 50 From 08ea6180670b359ae96feb6a9a58fb86136710bc Mon Sep 17 00:00:00 2001 From: laurent Date: Tue, 19 Nov 2019 13:27:28 +0100 Subject: [PATCH 062/240] fix important bug in CU, merge thread pool improvement and rf simulator improvements made initialy in 5G branch --- common/utils/threadPool/thread-pool.c | 30 ++---- common/utils/threadPool/thread-pool.h | 75 ++++++++------ executables/main-fs6.c | 17 ++- executables/main-ocp.c | 2 +- targets/ARCH/rfsimulator/simulator.c | 142 ++++++++++++++++---------- 5 files changed, 156 insertions(+), 110 deletions(-) diff --git a/common/utils/threadPool/thread-pool.c b/common/utils/threadPool/thread-pool.c index 1b7aa960ba..dd3d16d717 100644 --- a/common/utils/threadPool/thread-pool.c +++ b/common/utils/threadPool/thread-pool.c @@ -49,23 +49,6 @@ void *one_thread(void *arg) { struct one_thread *myThread=(struct one_thread *) arg; struct thread_pool *tp=myThread->pool; - // configure the thread core assignment - // TBD: reserve the core for us exclusively - if ( myThread->coreID >= 0 && myThread->coreID < get_nprocs_conf()) { - cpu_set_t cpuset; - CPU_ZERO(&cpuset); - CPU_SET(myThread->coreID, &cpuset); - pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - } - - //Configure the thread scheduler policy for Linux - struct sched_param sparam= {0}; - sparam.sched_priority = sched_get_priority_max(SCHED_RR); - pthread_setschedparam(pthread_self(), SCHED_RR, &sparam); - // set the thread name for debugging - sprintf(myThread->name,"Tpool_%d",myThread->coreID); - pthread_setname_np(pthread_self(), myThread->name ); - // Infinite loop to process requests do { notifiedFIFO_elt_t *elt=pullNotifiedFifoRemember(&tp->incomingFifo, myThread); @@ -106,10 +89,6 @@ void initTpool(char *params,tpool_t *pool, bool performanceMeas) { } else pool->traceFd=-1; - //Configure the thread scheduler policy for Linux - struct sched_param sparam= {0}; - sparam.sched_priority = sched_get_priority_max(SCHED_RR)-1; - pthread_setschedparam(pthread_self(), SCHED_RR, &sparam); pool->activated=true; initNotifiedFIFO(&pool->incomingFifo); char *saveptr, * curptr; @@ -137,7 +116,11 @@ void initTpool(char *params,tpool_t *pool, bool performanceMeas) { pool->allthreads->coreID=atoi(curptr); pool->allthreads->id=pool->nbThreads; pool->allthreads->pool=pool; - pthread_create(&pool->allthreads->threadID, NULL, one_thread, (void *)pool->allthreads); + //Configure the thread scheduler policy for Linux + // set the thread name for debugging + sprintf(pool->allthreads->name,"Tpool_%d",pool->allthreads->coreID); + threadCreate(&pool->allthreads->threadID, one_thread, (void *)pool->allthreads, + pool->allthreads->name, pool->allthreads->coreID, OAI_PRIORITY_RT); pool->nbThreads++; } @@ -152,6 +135,9 @@ void initTpool(char *params,tpool_t *pool, bool performanceMeas) { #ifdef TEST_THREAD_POOL +void exit_function(const char *file, const char *function, const int line, const char *s) { +} + struct testData { int id; char txt[30]; diff --git a/common/utils/threadPool/thread-pool.h b/common/utils/threadPool/thread-pool.h index d68918a163..d358db5f00 100644 --- a/common/utils/threadPool/thread-pool.h +++ b/common/utils/threadPool/thread-pool.h @@ -11,6 +11,7 @@ #include #include #include +#include #ifdef DEBUG #define THREADINIT PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP @@ -77,41 +78,60 @@ static inline void delNotifiedFIFO_elt(notifiedFIFO_elt_t *elt) { //LOG_W(UTIL,"delNotifiedFIFO on something not allocated by newNotifiedFIFO\n"); } +static inline void initNotifiedFIFO_nothreadSafe(notifiedFIFO_t *nf) { + nf->inF=NULL; + nf->outF=NULL; +} static inline void initNotifiedFIFO(notifiedFIFO_t *nf) { mutexinit(nf->lockF); condinit (nf->notifF); - nf->inF=NULL; - nf->outF=NULL; + initNotifiedFIFO_nothreadSafe(nf); // No delete function: the creator has only to free the memory } -static inline void pushNotifiedFIFO(notifiedFIFO_t *nf, notifiedFIFO_elt_t *msg) { - mutexlock(nf->lockF); +static inline void pushNotifiedFIFO_nothreadSafe(notifiedFIFO_t *nf, notifiedFIFO_elt_t *msg) { msg->next=NULL; if (nf->outF == NULL) nf->outF = msg; - if (nf->inF) + if (nf->inF != NULL) nf->inF->next = msg; nf->inF = msg; +} + +static inline void pushNotifiedFIFO(notifiedFIFO_t *nf, notifiedFIFO_elt_t *msg) { + mutexlock(nf->lockF); + pushNotifiedFIFO_nothreadSafe(nf,msg); condbroadcast(nf->notifF); mutexunlock(nf->lockF); } -static inline notifiedFIFO_elt_t *pullNotifiedFIFO(notifiedFIFO_t *nf) { - mutexlock(nf->lockF); - - while(!nf->outF) - condwait(nf->notifF, nf->lockF); +static inline notifiedFIFO_elt_t *pullNotifiedFIFO_nothreadSafe(notifiedFIFO_t *nf) { + if (nf->outF == NULL) + return NULL; notifiedFIFO_elt_t *ret=nf->outF; + + if (nf->outF==nf->outF->next) + LOG_E(TMR,"Circular list in thread pool: push several times the same buffer is forbidden\n"); + nf->outF=nf->outF->next; if (nf->outF==NULL) nf->inF=NULL; + return ret; +} + +static inline notifiedFIFO_elt_t *pullNotifiedFIFO(notifiedFIFO_t *nf) { + mutexlock(nf->lockF); + notifiedFIFO_elt_t *ret; + + while((ret=pullNotifiedFIFO_nothreadSafe(nf)) == NULL) + condwait(nf->notifF, nf->lockF); + mutexunlock(nf->lockF); return ret; } @@ -122,14 +142,7 @@ static inline notifiedFIFO_elt_t *pollNotifiedFIFO(notifiedFIFO_t *nf) { if (tmp != 0 ) return NULL; - notifiedFIFO_elt_t *ret=nf->outF; - - if (ret!=NULL) - nf->outF=nf->outF->next; - - if (nf->outF==NULL) - nf->inF=NULL; - + notifiedFIFO_elt_t *ret=pullNotifiedFIFO_nothreadSafe(nf); mutexunlock(nf->lockF); return ret; } @@ -151,6 +164,7 @@ static inline int abortNotifiedFIFO(notifiedFIFO_t *nf, uint64_t key) { } else start=&(*start)->next; } + if (nf->outF == NULL) nf->inF=NULL; @@ -184,16 +198,20 @@ typedef struct thread_pool { static inline void pushTpool(tpool_t *t, notifiedFIFO_elt_t *msg) { if (t->measurePerf) msg->creationTime=rdtsc(); + if ( t->activated) pushNotifiedFIFO(&t->incomingFifo, msg); else { - if (t->measurePerf) - msg->startProcessingTime=rdtsc(); - msg->processingFunc(NotifiedFifoData(msg)); - if (t->measurePerf) - msg->endProcessingTime=rdtsc(); - if (msg->reponseFifo) - pushNotifiedFIFO(msg->reponseFifo, msg); + if (t->measurePerf) + msg->startProcessingTime=rdtsc(); + + msg->processingFunc(NotifiedFifoData(msg)); + + if (t->measurePerf) + msg->endProcessingTime=rdtsc(); + + if (msg->reponseFifo) + pushNotifiedFIFO(msg->reponseFifo, msg); } } @@ -202,10 +220,8 @@ static inline notifiedFIFO_elt_t *pullTpool(notifiedFIFO_t *responseFifo, tpool_ if (t->measurePerf) msg->returnTime=rdtsc(); - - if (t->traceFd) + if (t->traceFd >= 0) if(write(t->traceFd, msg, sizeof(*msg))); - return msg; } @@ -217,10 +233,8 @@ static inline notifiedFIFO_elt_t *tryPullTpool(notifiedFIFO_t *responseFifo, tpo if (t->measurePerf) msg->returnTime=rdtsc(); - if (t->traceFd) if(write(t->traceFd, msg, sizeof(*msg))); - return msg; } @@ -239,6 +253,7 @@ static inline int abortTpool(tpool_t *t, uint64_t key) { } else start=&(*start)->next; } + if (t->incomingFifo.outF==NULL) t->incomingFifo.inF=NULL; diff --git a/executables/main-fs6.c b/executables/main-fs6.c index 471ad0f1eb..638db0ac11 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -1324,6 +1324,9 @@ void *DL_du_fs6(void *arg) { feptx_prec(ru, &L1_proc); feptx_ofdm(ru, &L1_proc); tx_rf(ru, &L1_proc); + + if ( IS_SOFTMODEM_RFSIM ) + return NULL; } return NULL; @@ -1443,13 +1446,22 @@ void *cu_fs6(void *arg) { remoteIP=DU_IP; AssertFatal(createUDPsock(NULL, CU_PORT, remoteIP, DU_PORT, &sockFS6), ""); + + L1_rxtx_proc_t L1proc= {0}; + if ( strlen(get_softmodem_params()->threadPoolConfig) > 0 ) + initTpool(get_softmodem_params()->threadPoolConfig, &L1proc.threadPool, true); + else + initTpool("n", &L1proc.threadPool, true); + + initNotifiedFIFO(&L1proc.respEncode); + initNotifiedFIFO(&L1proc.respDecode); + uint64_t timeStamp=0; initStaticTime(begingWait); initStaticTime(begingWait2); initRefTimes(waitDUAndProcessingUL); initRefTimes(makeSendDL); initRefTimes(fullLoop); - L1_rxtx_proc_t L1proc= {0}; while(1) { timeStamp+=ru->frame_parms.samples_per_tti; @@ -1496,6 +1508,7 @@ void *du_fs6(void *arg) { initRefTimes(waitRxAndProcessingUL); initRefTimes(fullLoop); pthread_t t; + if ( !IS_SOFTMODEM_RFSIM ) threadCreate(&t, DL_du_fs6, (void *)ru, "MainDuTx", -1, OAI_PRIORITY_RT_MAX); while(1) { @@ -1503,6 +1516,8 @@ void *du_fs6(void *arg) { updateTimesReset(begingWait, &fullLoop, 1000, true,"DU for full SubFrame (must be less 1ms)"); pickStaticTime(begingWait); UL_du_fs6(ru, &L1proc); + if ( IS_SOFTMODEM_RFSIM ) + DL_du_fs6((void *)ru); updateTimesReset(begingWait, &waitRxAndProcessingUL, 1000, true,"DU Time in wait Rx + Ul processing"); } diff --git a/executables/main-ocp.c b/executables/main-ocp.c index 8810115197..819eab0ee6 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -688,7 +688,7 @@ static void *ru_thread( void *param ) { setbuf(stdout, NULL); setbuf(stderr, NULL); RU_t *ru = (RU_t *)param; - L1_rxtx_proc_t L1proc; + L1_rxtx_proc_t L1proc={0}; L1_rxtx_proc_t *proc=&L1proc; if ( strlen(get_softmodem_params()->threadPoolConfig) > 0 ) diff --git a/targets/ARCH/rfsimulator/simulator.c b/targets/ARCH/rfsimulator/simulator.c index b85cdb507a..95eeb38aa0 100644 --- a/targets/ARCH/rfsimulator/simulator.c +++ b/targets/ARCH/rfsimulator/simulator.c @@ -70,8 +70,8 @@ typedef struct complex16 sample_t; // 2*16 bits complex number typedef struct buffer_s { int conn_sock; openair0_timestamp lastReceivedTS; - openair0_timestamp lastWroteTS; bool headerMode; + bool trashingPacket; samplesBlockHeader_t th; char *transferPtr; uint64_t remainToTransfer; @@ -83,6 +83,7 @@ typedef struct buffer_s { typedef struct { int listen_sock, epollfd; openair0_timestamp nextTimestamp; + openair0_timestamp lastWroteTS; uint64_t typeStamp; char *ip; uint16_t port; @@ -102,8 +103,8 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) { ptr->circularBufEnd=((char *)ptr->circularBuf)+sampleToByte(CirSize,1); ptr->conn_sock=sock; ptr->lastReceivedTS=0; - ptr->lastWroteTS=0; ptr->headerMode=true; + ptr->trashingPacket=false; ptr->transferPtr=(char *)&ptr->th; ptr->remainToTransfer=sizeof(samplesBlockHeader_t); int sendbuff=1000*1000*100; @@ -219,8 +220,6 @@ void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) { } } - - void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) { char *saveF=NULL; char *modelname=NULL; @@ -317,19 +316,16 @@ sin_addr: return 0; } -static int rfsimulator_write_internal(rfsimulator_state_t *t, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) { +static int rfsimulator_write_internal(rfsimulator_state_t *t, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags, bool alreadyLocked) { + if (!alreadyLocked) + pthread_mutex_lock(&Sockmutex); + LOG_D(HW,"sending %d samples at time: %ld\n", nsamps, timestamp); for (int i=0; ibuf[i]; if (b->conn_sock >= 0 ) { - pthread_mutex_lock(&Sockmutex); - - if ( b->lastWroteTS != 0 && abs((double)b->lastWroteTS-timestamp) > (double)CirSize) - LOG_E(HW,"Discontinuous TX gap too large Tx:%lu, %lu\n", b->lastWroteTS, timestamp); - - AssertFatal(b->lastWroteTS <= timestamp+1, " Not supported to send Tx out of order (same in USRP) %lu, %lu\n", b->lastWroteTS, timestamp); samplesBlockHeader_t header= {t->typeStamp, nsamps, nbAnt, timestamp}; fullwrite(b->conn_sock,&header, sizeof(header), t); sample_t tmpSamples[nsamps][nbAnt]; @@ -343,24 +339,29 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t, openair0_timestamp if (b->conn_sock >= 0 ) { fullwrite(b->conn_sock, (void *)tmpSamples, sampleToByte(nsamps,nbAnt), t); - b->lastWroteTS=timestamp+nsamps; } - - pthread_mutex_unlock(&Sockmutex); } } + if ( t->lastWroteTS != 0 && abs((double)t->lastWroteTS-timestamp) > (double)CirSize) + LOG_E(HW,"Discontinuous TX gap too large Tx:%lu, %lu\n", t->lastWroteTS, timestamp); + + AssertFatal(t->lastWroteTS <= timestamp+1, " Not supported to send Tx out of order (same in USRP) %lu, %lu\n", + t->lastWroteTS, timestamp); + t->lastWroteTS=timestamp+nsamps; + + if (!alreadyLocked) + pthread_mutex_unlock(&Sockmutex); + 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) ); return nsamps; } int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) { - return rfsimulator_write_internal(device->priv, timestamp, samplesVoid, nsamps, nbAnt, flags); + return rfsimulator_write_internal(device->priv, timestamp, samplesVoid, nsamps, nbAnt, flags, false); } - - static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initial) { // Process all incoming events on sockets // store the data in lists @@ -389,22 +390,9 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi for ( int i=0; i < t->tx_num_channels; i++) samplesVoid[i]=(void *)&v; - pthread_mutex_lock(&Sockmutex); - openair0_timestamp timestamp=1; - - for (int i=0; ibuf[i]; - - if (t->buf[i].circularBuf != NULL && t->buf[i].lastWroteTS > 1) { - timestamp=b->lastWroteTS; - break; - } - } - - pthread_mutex_unlock(&Sockmutex); - rfsimulator_write_internal(t, timestamp-1, + rfsimulator_write_internal(t, t->lastWroteTS > 1 ? t->lastWroteTS-1 : 0, samplesVoid, 1, - t->tx_num_channels, 1); + t->tx_num_channels, 1, false); } else { if ( events[nbEv].events & (EPOLLHUP | EPOLLERR | EPOLLRDHUP) ) { socketError(t,fd); @@ -450,25 +438,41 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi (t->typeStamp == ENB_MAGICDL_FDD && b->th.magic==UE_MAGICDL_FDD), "Socket Error in protocol"); b->headerMode=false; - if ( b->lastReceivedTS != b->th.timestamp) { + if ( t->nextTimestamp == 0 ) { // First block in UE, resync with the eNB current TS + t->nextTimestamp=b->th.timestamp> nsamps_for_initial ? + b->th.timestamp - nsamps_for_initial : + 0; + b->lastReceivedTS=b->th.timestamp> nsamps_for_initial ? + b->th.timestamp : + nsamps_for_initial; + LOG_W(HW,"UE got first timestamp: starting at %lu\n", t->nextTimestamp); + b->trashingPacket=true; + } else 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].r=0; b->circularBuf[(index*nbAnt+a)%CirSize].i=0; } } - - if ( abs(b->th.timestamp-b->lastReceivedTS) > 50 ) + if (b->lastReceivedTS != 0 && b->th.timestamp-b->lastReceivedTS > 50 ) LOG_W(HW,"UEsock: %d gap of: %ld in reception\n", fd, b->th.timestamp-b->lastReceivedTS ); - } + b->lastReceivedTS=b->th.timestamp; + + } else if ( b->lastReceivedTS > b->th.timestamp && b->th.size == 1 ) { + LOG_W(HW,"Received Rx/Tx synchro out of order\n"); + b->trashingPacket=true; + } else if ( b->lastReceivedTS == b->th.timestamp ) { + // normal case + } else { + abort(); + AssertFatal(false, "received data in past: current is %lu, new reception: %lu!\n", b->lastReceivedTS, b->th.timestamp); } - b->lastReceivedTS=b->th.timestamp; pthread_mutex_lock(&Sockmutex); - if (b->lastWroteTS != 0 && ( abs((double)b->lastWroteTS-b->lastReceivedTS) > (double)CirSize)) - LOG_E(HW,"UEsock: %d Tx/Rx shift too large Tx:%lu, Rx:%lu\n", fd, b->lastWroteTS, b->lastReceivedTS); + if (t->lastWroteTS != 0 && ( abs((double)t->lastWroteTS-b->lastReceivedTS) > (double)CirSize)) + LOG_E(HW,"UEsock: %d Tx/Rx shift too large Tx:%lu, Rx:%lu\n", fd, t->lastWroteTS, b->lastReceivedTS); pthread_mutex_unlock(&Sockmutex); b->transferPtr=(char *)&b->circularBuf[b->lastReceivedTS%CirSize]; @@ -477,22 +481,17 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi if ( b->headerMode==false ) { LOG_D(HW,"UEsock: %d Set b->lastReceivedTS %ld\n", fd, b->lastReceivedTS); - b->lastReceivedTS=b->th.timestamp+b->th.size-byteToSample(b->remainToTransfer,b->th.nbAnt); + if ( ! b->trashingPacket ) { + 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 && b->th.size < b->lastReceivedTS) { - t->nextTimestamp=b->lastReceivedTS > nsamps_for_initial ? - b->lastReceivedTS - nsamps_for_initial : - 0; - LOG_W(HW,"UE got first timestamp: starting at %lu\n", t->nextTimestamp); - } - - if ( b->remainToTransfer==0) { - LOG_D(HW,"UEsock: %d Completed block reception: %ld\n", fd, b->lastReceivedTS); - b->headerMode=true; - b->transferPtr=(char *)&b->th; - b->remainToTransfer=sizeof(samplesBlockHeader_t); - b->th.magic=-1; + if ( b->remainToTransfer==0) { + LOG_D(HW,"UEsock: %d Completed block reception: %ld\n", fd, b->lastReceivedTS); + b->headerMode=true; + b->transferPtr=(char *)&b->th; + b->remainToTransfer=sizeof(samplesBlockHeader_t); + b->th.magic=-1; + b->trashingPacket=false; } } } @@ -528,12 +527,43 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo t->nextTimestamp+=nsamps; if ( ((t->nextTimestamp/nsamps)%100) == 0) - LOG_W(HW,"Generated void samples for Rx: %ld\n", t->nextTimestamp); + LOG_W(HW,"No UE, Generated void samples for Rx: %ld\n", t->nextTimestamp); *ptimestamp = t->nextTimestamp-nsamps; return nsamps; } } else { + pthread_mutex_lock(&Sockmutex); + + if ( t->nextTimestamp > 0 && t->lastWroteTS < t->nextTimestamp) { + pthread_mutex_unlock(&Sockmutex); + usleep(10000); + pthread_mutex_lock(&Sockmutex); + if ( t->lastWroteTS < t->nextTimestamp ) { + // Assuming Tx is not done fully in another thread + // We can never write is the past from the received time + // So, the node perform receive but will never write these symbols + // let's tell this to the opposite node + // We send timestamp for nb samples required + // assuming this should have been done earlier if a Tx would exist + pthread_mutex_unlock(&Sockmutex); + struct complex16 v= {0}; + void *samplesVoid[t->tx_num_channels]; + + for ( int i=0; i < t->tx_num_channels; i++) + samplesVoid[i]=(void *)&v; + LOG_I(HW, "No samples Tx occured, so we send 1 sample to notify it: Tx:%lu, Rx:%lu\n", + t->lastWroteTS, t->nextTimestamp); + rfsimulator_write_internal(t, t->nextTimestamp, + samplesVoid, 1, + t->tx_num_channels, 1, true); + } else { + pthread_mutex_unlock(&Sockmutex); + LOG_W(HW, "trx_write came from another thread\n"); + } + } else + pthread_mutex_unlock(&Sockmutex); + bool have_to_wait; do { From f7a9226438296f2acadb074a0be89feb4a4850c5 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Fri, 29 Nov 2019 11:52:01 +0100 Subject: [PATCH 063/240] CI: add initial support to do X2 HO at Inria Signed-off-by: Raphael Defosseux --- ci-scripts/Jenkinsfile-inria-r2lab | 13 +- .../inria/enb_usrp210_band7_build.xml | 13 +- ...enb_usrp210_band7_x2_ho_test_05Mhz_tm1.xml | 128 ++++++++++++++++++ 3 files changed, 148 insertions(+), 6 deletions(-) create mode 100644 ci-scripts/xml_files/inria/enb_usrp210_band7_x2_ho_test_05Mhz_tm1.xml diff --git a/ci-scripts/Jenkinsfile-inria-r2lab b/ci-scripts/Jenkinsfile-inria-r2lab index 778c571645..555017a533 100644 --- a/ci-scripts/Jenkinsfile-inria-r2lab +++ b/ci-scripts/Jenkinsfile-inria-r2lab @@ -59,6 +59,9 @@ def r2labEPC0IpAddr = r2labBaseIpAddr + r2labEPC0Idx def r2labUE0Idx = '6' def r2labUE0 = 'fit0' + r2labUE0Idx def r2labUE0IpAddr = r2labBaseIpAddr + r2labUE0Idx +def r2labENB1Idx = '16' +def r2labENB1 = 'fit' + r2labENB1Idx +def r2labENB1IpAddr = r2labBaseIpAddr + r2labENB1Idx pipeline { agent { @@ -144,9 +147,9 @@ pipeline { sh "ssh -t inria_oaici@faraday.inria.fr 'rwait --silent ${r2labPythonExeIdx}'" echo '\u2705 \u001B[32mLoad Image for one eNB\u001B[0m' - sh "ssh -t inria_oaici@faraday.inria.fr 'rload -i oai-ci-cd-u18-lowlatency-enb-ue ${r2labENB0Idx} > /dev/null 2>&1'" - sh "ssh -t inria_oaici@faraday.inria.fr 'rwait --silent ${r2labENB0Idx}'" - sh "ssh -t inria_oaici@faraday.inria.fr 'uon ${r2labENB0Idx}'" + sh "ssh -t inria_oaici@faraday.inria.fr 'rload -i oai-ci-cd-u18-lowlatency-enb-ue ${r2labENB0Idx},${r2labENB1Idx} > /dev/null 2>&1'" + sh "ssh -t inria_oaici@faraday.inria.fr 'rwait --silent ${r2labENB0Idx},${r2labENB1Idx}'" + sh "ssh -t inria_oaici@faraday.inria.fr 'uon ${r2labENB0Idx},${r2labENB1Idx}'" echo '\u2705 \u001B[32mLoad Image for one OAI UE\u001B[0m' sh "ssh -t inria_oaici@faraday.inria.fr 'rload -i oai-ci-cd-u18-lowlatency-enb-ue ${r2labUE0Idx} > /dev/null 2>&1'" @@ -157,7 +160,7 @@ pipeline { sh "ssh -t inria_oaici@faraday.inria.fr 'rload -i oai-ci-cd-u18-lowlatency-epc ${r2labEPC0Idx} > /dev/null 2>&1'" sh "ssh -t inria_oaici@faraday.inria.fr 'rwait --silent ${r2labEPC0Idx}'" - sh "ssh -t inria_oaici@faraday.inria.fr 'nodes ${r2labUE0Idx},${r2labPythonExeIdx},${r2labEPC0Idx},${r2labENB0Idx} && st'" + sh "ssh -t inria_oaici@faraday.inria.fr 'nodes ${r2labUE0Idx},${r2labPythonExeIdx},${r2labEPC0Idx},${r2labENB0Idx},${r2labENB1Idx} && st'" } } } @@ -210,7 +213,7 @@ pipeline { String[] myXmlTestSuite = testXMLFile.split("\\r?\\n") for (xmlFile in myXmlTestSuite) { try { - sh "ssh -t -t inria_oaici@faraday.inria.fr 'ssh -t -t -b 192.168.3.100 ${fituser}@${r2labPythonExe} \"cd openairinterface5g/ci-scripts && python3 main.py --mode=TesteNB --ranRepository=https://gitlab.eurecom.fr/oai/openairinterface5g --ranBranch=${ranRepoBranch} --ranCommitID=${GIT_COMMIT_TO_RUN} --ranAllowMerge=false --eNBIPAddress=${r2labENB0IpAddr} --eNBUserName=${fituser} --eNBPassword=${fitpasswd} --eNBSourceCodePath=/home/${fituser}/openairinterface5g --UEIPAddress=${r2labUE0IpAddr} --UEUserName=${fituser} --UEPassword=${fitpasswd} --UESourceCodePath=/home/${fituser}/openairinterface5g --EPCIPAddress=${r2labEPC0IpAddr} --EPCType=OAI-Rel14-CUPS --EPCUserName=${fituser} --EPCPassword=${fitpasswd} --EPCSourceCodePath=/home/${fituser}/openair-cn --ADBIPAddress=${r2labEPC0IpAddr} --ADBUserName=${fituser} --ADBPassword=${fitpasswd} --ADBType=distributed --XMLTestFile=${xmlFile}\"'" + sh "ssh -t -t inria_oaici@faraday.inria.fr 'ssh -t -t -b 192.168.3.100 ${fituser}@${r2labPythonExe} \"cd openairinterface5g/ci-scripts && python3 main.py --mode=TesteNB --ranRepository=https://gitlab.eurecom.fr/oai/openairinterface5g --ranBranch=${ranRepoBranch} --ranCommitID=${GIT_COMMIT_TO_RUN} --ranAllowMerge=false --eNBIPAddress=${r2labENB0IpAddr} --eNBUserName=${fituser} --eNBPassword=${fitpasswd} --eNBSourceCodePath=/home/${fituser}/openairinterface5g --eNB1IPAddress=${r2labENB1IpAddr} --eNB1UserName=${fituser} --eNB1Password=${fitpasswd} --eNB1SourceCodePath=/home/${fituser}/openairinterface5g --UEIPAddress=${r2labUE0IpAddr} --UEUserName=${fituser} --UEPassword=${fitpasswd} --UESourceCodePath=/home/${fituser}/openairinterface5g --EPCIPAddress=${r2labEPC0IpAddr} --EPCType=OAI-Rel14-CUPS --EPCUserName=${fituser} --EPCPassword=${fitpasswd} --EPCSourceCodePath=/home/${fituser}/openair-cn --ADBIPAddress=${r2labEPC0IpAddr} --ADBUserName=${fituser} --ADBPassword=${fitpasswd} --ADBType=distributed --XMLTestFile=${xmlFile}\"'" } catch (Exception e) { currentBuild.result = 'FAILURE' buildStageStatus = false diff --git a/ci-scripts/xml_files/inria/enb_usrp210_band7_build.xml b/ci-scripts/xml_files/inria/enb_usrp210_band7_build.xml index 776c92106d..d3e9825923 100644 --- a/ci-scripts/xml_files/inria/enb_usrp210_band7_build.xml +++ b/ci-scripts/xml_files/inria/enb_usrp210_band7_build.xml @@ -26,13 +26,24 @@ wrench 010101 + 010102 Build_eNB - Build eNB (USRP) + Build eNB #0 (USRP) -w USRP -c --eNB + 0 + 0 + + + + Build_eNB + Build eNB #1 (USRP) + -w USRP -c --eNB + 1 + 1 diff --git a/ci-scripts/xml_files/inria/enb_usrp210_band7_x2_ho_test_05Mhz_tm1.xml b/ci-scripts/xml_files/inria/enb_usrp210_band7_x2_ho_test_05Mhz_tm1.xml new file mode 100644 index 0000000000..f10465f688 --- /dev/null +++ b/ci-scripts/xml_files/inria/enb_usrp210_band7_x2_ho_test_05Mhz_tm1.xml @@ -0,0 +1,128 @@ + + + test-x2-ho-05-tm1 + Test-X2-Handover-05MHz-TM1 + tasks + 1 + + 040101 030201 + 050102 + 030104 000002 + 040301 000002 040540 040615 040616 040655 040656 040401 + 040201 000002 030201 + 050202 + + + + + Initialize_UE + Initialize UE + + + + Terminate_UE + Terminate UE + + + + IdleSleep + Sleep for 10 sec + 10 + + + + IdleSleep + Sleep for 3 sec + 3 + + + + Initialize_eNB + Initialize eNB (FDD/Band7/5MHz) + -O ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf --eNBs.[0].rrc_inactivity_threshold 0 --RUs.[0].max_rxgain 120 --eNBs.[0].component_carriers.[0].pusch_p0_Nominal -90 --eNBs.[0].component_carriers.[0].pucch_p0_Nominal -96 --eNBs.[0].tracking_area_code 600 --eNBs.[0].plmn_list.[0].mnc 95 --THREAD_STRUCT.[0].parallel_config PARALLEL_RU_L1_TRX_SPLIT --eNBs.[0].enable_measurement_reports yes --eNBs.[0].enable_x2 yes + 0 + 0 + + + + Terminate_eNB + Terminate eNB + + + + Initialize_FlexranCtrl + Starting Flexran Controller + + + + Terminate_FlexranCtrl + Stopping Flexran Controller + + + + Attach_UE + Attach UE + + + + Detach_UE + Detach UE + + + + Ping + ping (5MHz - 20 sec) + -c 20 + 5 + + + + Iperf + iperf (5MHz - DL/1Mbps/UDP)(30 sec) + -u -b 1M -t 30 -i 1 -fm + 50 + + + + Iperf + iperf (5MHz - DL/15Mbps/UDP)(30 sec) + -u -b 15M -t 30 -i 1 -fm + 50 + + + + Iperf + iperf (5MHz - UL/1Mbps/UDP)(30 sec) + -u -b 1M -t 30 -i 1 -fm -R + 50 + + + + Iperf + iperf (5MHz - UL/3.8Mbps/UDP)(30 sec) + -u -b 3.8M -t 30 -i 1 -fm -R + 50 + + + From 0b8a25ee90b1b5329eb9e4c8b79ae0e7b84bcd8a Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Fri, 29 Nov 2019 13:57:42 +0100 Subject: [PATCH 064/240] CI: finalizing offline the X2 handover scenario at inria --> to be tested Signed-off-by: Raphael Defosseux --- ci-scripts/main.py | 1 + ...enb_usrp210_band7_x2_ho_test_05Mhz_tm1.xml | 84 +++++++++++++++++-- 2 files changed, 78 insertions(+), 7 deletions(-) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index a60a31c04a..bac3599150 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -821,6 +821,7 @@ class SSHConnection(): self.command('source oaienv', '\$', 5) self.command('cd cmake_targets', '\$', 5) self.command('echo "ulimit -c unlimited && ./lte_build_oai/build/lte-softmodem -O ' + lSourcePath + '/' + ci_full_config_file + extra_options + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + self.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) self.command('chmod 775 ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) self.command('echo ' + lPassWord + ' | sudo -S rm -Rf enb_' + self.testCase_id + '.log', '\$', 5) self.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=enb' + str(self.eNB_instance) + '_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) diff --git a/ci-scripts/xml_files/inria/enb_usrp210_band7_x2_ho_test_05Mhz_tm1.xml b/ci-scripts/xml_files/inria/enb_usrp210_band7_x2_ho_test_05Mhz_tm1.xml index f10465f688..af09934d2b 100644 --- a/ci-scripts/xml_files/inria/enb_usrp210_band7_x2_ho_test_05Mhz_tm1.xml +++ b/ci-scripts/xml_files/inria/enb_usrp210_band7_x2_ho_test_05Mhz_tm1.xml @@ -26,11 +26,16 @@ tasks 1 - 040101 030201 + 040101 030201 030202 050102 - 030104 000002 - 040301 000002 040540 040615 040616 040655 040656 040401 - 040201 000002 030201 + 030104 000002 030105 000002 + 040301 000002 + 040540 040615 040616 040655 040656 + 050401 000001 + 040541 040617 040618 040657 040658 + 040401 000001 + 040542 + 040201 000002 030201 030202 050202 @@ -59,15 +64,32 @@ Initialize_eNB - Initialize eNB (FDD/Band7/5MHz) - -O ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf --eNBs.[0].rrc_inactivity_threshold 0 --RUs.[0].max_rxgain 120 --eNBs.[0].component_carriers.[0].pusch_p0_Nominal -90 --eNBs.[0].component_carriers.[0].pucch_p0_Nominal -96 --eNBs.[0].tracking_area_code 600 --eNBs.[0].plmn_list.[0].mnc 95 --THREAD_STRUCT.[0].parallel_config PARALLEL_RU_L1_TRX_SPLIT --eNBs.[0].enable_measurement_reports yes --eNBs.[0].enable_x2 yes + Initialize eNB #0 (FDD/Band7/5MHz) + -O ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf --eNBs.[0].rrc_inactivity_threshold 0 --RUs.[0].max_rxgain 120 --eNBs.[0].component_carriers.[0].pusch_p0_Nominal -90 --eNBs.[0].component_carriers.[0].pucch_p0_Nominal -96 --eNBs.[0].tracking_area_code 600 --eNBs.[0].plmn_list.[0].mnc 95 --THREAD_STRUCT.[0].parallel_config PARALLEL_RU_L1_TRX_SPLIT --eNBs.[0].enable_measurement_reports yes --eNBs.[0].enable_x2 yes --eNBs.[0].nr_cellid 123456 0 0 + + Initialize_eNB + Initialize eNB #1 (FDD/Band7/5MHz) + -O ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf --eNBs.[0].rrc_inactivity_threshold 0 --RUs.[0].max_rxgain 120 --eNBs.[0].component_carriers.[0].pusch_p0_Nominal -90 --eNBs.[0].component_carriers.[0].pucch_p0_Nominal -96 --eNBs.[0].tracking_area_code 600 --eNBs.[0].plmn_list.[0].mnc 95 --THREAD_STRUCT.[0].parallel_config PARALLEL_RU_L1_TRX_SPLIT --eNBs.[0].enable_measurement_reports yes --eNBs.[0].enable_x2 yes --eNBs.[0].target_enb_x2_ip_address.[0].ipv4 CI_RCC_IP_ADDR --eNBs.[0].target_enb_x2_ip_address.[0].preference ipv4 --eNBs.[0].eNB_ID 0xe01 --eNBs.[0].component_carriers.[0].Nid_cell 1 --eNBs.[0].nr_cellid 98765 + 1 + 1 + + Terminate_eNB - Terminate eNB + Terminate eNB #0 + 0 + 0 + + + + Terminate_eNB + Terminate eNB #1 + 1 + 1 @@ -97,6 +119,20 @@ 5 + + Ping + ping (5MHz - 20 sec) + -c 20 + 50 + + + + Ping + ping (5MHz - 20 sec) + -c 20 + 50 + + Iperf iperf (5MHz - DL/1Mbps/UDP)(30 sec) @@ -111,6 +147,20 @@ 50 + + Iperf + iperf (5MHz - DL/1Mbps/UDP)(30 sec) + -u -b 1M -t 30 -i 1 -fm + 50 + + + + Iperf + iperf (5MHz - DL/15Mbps/UDP)(30 sec) + -u -b 15M -t 30 -i 1 -fm + 50 + + Iperf iperf (5MHz - UL/1Mbps/UDP)(30 sec) @@ -125,4 +175,24 @@ 50 + + Iperf + iperf (5MHz - UL/1Mbps/UDP)(30 sec) + -u -b 1M -t 30 -i 1 -fm -R + 50 + + + + Iperf + iperf (5MHz - UL/3.8Mbps/UDP)(30 sec) + -u -b 3.8M -t 30 -i 1 -fm -R + 50 + + + + Perform_X2_Handover + Doing a Flexran-Controlled X2 Handover + network + + From 47abf562db29f1a1128990e8cbc27d29fba8a511 Mon Sep 17 00:00:00 2001 From: laurent Date: Fri, 6 Dec 2019 16:24:47 +0100 Subject: [PATCH 065/240] add FS6 transport time measurement --- common/config/config_userapi.c | 2 +- executables/main-fs6.c | 60 +++++++++++++++++++++----- executables/main-ocp.c | 2 +- executables/split_headers.h | 3 ++ executables/transport_split.c | 1 + nfapi/oai_integration/nfapi.c | 2 +- openair2/UTIL/OPT/probe.c | 6 +-- targets/ARCH/rfsimulator/simulator.c | 10 +++-- targets/RT/USER/lte-softmodem-common.c | 18 ++++---- targets/RT/USER/lte-uesoftmodem.c | 10 ++--- 10 files changed, 80 insertions(+), 34 deletions(-) diff --git a/common/config/config_userapi.c b/common/config/config_userapi.c index 9b42dd209f..9ba507a6ec 100644 --- a/common/config/config_userapi.c +++ b/common/config/config_userapi.c @@ -81,7 +81,7 @@ char *config_check_valptr(paramdef_t *cfgoptions, char **ptr, int length) { } if (*ptr == NULL) { - *ptr = malloc(length); + *ptr = malloc(length>40?length:40); // LTS: dummy fix, waiting Francois full fix in 4G branch if ( *ptr != NULL) { memset(*ptr,0,length); diff --git a/executables/main-fs6.c b/executables/main-fs6.c index 638db0ac11..e39fad1c04 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -82,7 +82,34 @@ static inline void updateTimesReset(uint64_t start, Meas *M, int period, bool Ma } } +static inline void measTransportTime(uint64_t DuSend, uint64_t CuMicroSec, Meas *M, int period, bool MaxMin, char *txt) { + if (DuSend!=0) { + uint64_t end=rdtsc(); + long long diff=(end-DuSend)/(cpuf*1000)-CuMicroSec; + LOG_E(HW, "total: %f, cu time %lu\n", (end-DuSend)/(cpuf*1000), CuMicroSec); + M->maxArray[0]=diff; + M->sum+=diff; + M->iterations++; + + if ( MaxMin) + qsort(M->maxArray, 11, sizeof(uint64_t), cmpint); + else + qsort(M->maxArray, 11, sizeof(uint64_t), cmpintRev); + + printMeas2(txt,M,period, MaxMin); + + if (M->iterations%period == 0 ) { + bzero(M,sizeof(*M)); + + if (!MaxMin) + for (int i=0; i<11; i++) + M->maxArray[i]=INT_MAX; + } + } +} + #define ceil16_bytes(a) ((((a+15)/16)*16)/8) + static void fs6Dlunpack(void *out, void *in, int szUnpacked) { static uint64_t *lut=NULL; @@ -1297,12 +1324,16 @@ void *DL_du_fs6(void *arg) { RU_t *ru=(RU_t *)arg; static uint64_t lastTS; L1_rxtx_proc_t L1_proc= {0}; + initStaticTime(begingWait); + initStaticTime(begingProcessing); + initRefTimes(fullLoop); + initRefTimes(DuHigh); + initRefTimes(DuLow); + initRefTimes(transportTime); while (1) { for (int i=0; inum_eNB; i++) { initBufferZone(bufferZone); - initStaticTime(begingWait); - initRefTimes(fullLoop); pickStaticTime(begingWait); int nb_blocks=receiveSubFrame(&sockFS6, bufferZone, sizeof(bufferZone), CTsentCUv0 ); updateTimesReset(begingWait, &fullLoop, 1000, false, "DU wait CU"); @@ -1313,18 +1344,22 @@ void *DL_du_fs6(void *arg) { lastTS+ru->eNB_list[i]->frame_parms.samples_per_tti, hUDP(bufferZone)->timestamp); } - + pickStaticTime(begingProcessing); lastTS=hUDP(bufferZone)->timestamp; setAllfromTS(hUDP(bufferZone)->timestamp - sf_ahead*ru->eNB_list[i]->frame_parms.samples_per_tti, &L1_proc); + measTransportTime(hDL(bufferZone)->DuClock, hDL(bufferZone)->CuSpentMicroSec, + &transportTime, 1000, false, "Transport time, to CU + from CU for one subframe"); phy_procedures_eNB_TX_fromsplit( bufferZone, nb_blocks, ru->eNB_list[i], &L1_proc, 1); + updateTimesReset(begingProcessing, &DuHigh, 1000, false, "DU high layer1 processing for DL"); } else LOG_E(PHY,"DL not received for subframe\n"); } - + pickStaticTime(begingProcessing); feptx_prec(ru, &L1_proc); feptx_ofdm(ru, &L1_proc); tx_rf(ru, &L1_proc); - + updateTimesReset(begingProcessing, &DuLow, 1000, false, "DU low layer1 processing for DL"); + if ( IS_SOFTMODEM_RFSIM ) return NULL; } @@ -1371,7 +1406,7 @@ void UL_du_fs6(RU_t *ru, L1_rxtx_proc_t *proc) { } } -void DL_cu_fs6(RU_t *ru, L1_rxtx_proc_t *proc) { +void DL_cu_fs6(RU_t *ru, L1_rxtx_proc_t *proc, uint64_t DuClock, uint64_t startCycle) { // Fixme: datamodel issue PHY_VARS_eNB *eNB = RC.eNB[0][0]; pthread_mutex_lock(&eNB->UL_INFO_mutex); @@ -1390,17 +1425,21 @@ void DL_cu_fs6(RU_t *ru, L1_rxtx_proc_t *proc) { hUDP(bufferZone)->blockID=0; hUDP(bufferZone)->contentBytes=sizeof(fs6_dl_t); } - + hDL(bufferZone)->DuClock=DuClock; + hDL(bufferZone)->CuSpentMicroSec=(rdtsc()-startCycle)/(cpuf*1000); + sendSubFrame(&sockFS6, bufferZone, sizeof(fs6_dl_t), CTsentCUv0 ); return; } -void UL_cu_fs6(RU_t *ru, L1_rxtx_proc_t *proc, uint64_t *TS) { +void UL_cu_fs6(RU_t *ru, L1_rxtx_proc_t *proc, uint64_t *TS, uint64_t * DuClock, uint64_t * startProcessing) { initBufferZone(bufferZone); initStaticTime(begingWait); initRefTimes(fullLoop); pickStaticTime(begingWait); int nb_blocks=receiveSubFrame(&sockFS6, bufferZone, sizeof(bufferZone), CTsentDUv0 ); + * DuClock=hUDP(bufferZone)->senderClock; + * startProcessing=rdtsc(); updateTimesReset(begingWait, &fullLoop, 1000, false, "CU wait DU"); if (nb_blocks ==0) { @@ -1462,15 +1501,16 @@ void *cu_fs6(void *arg) { initRefTimes(waitDUAndProcessingUL); initRefTimes(makeSendDL); initRefTimes(fullLoop); + uint64_t DuClock=0, startProcessing=0; while(1) { timeStamp+=ru->frame_parms.samples_per_tti; updateTimesReset(begingWait, &fullLoop, 1000, true, "CU for full SubFrame (must be less 1ms)"); pickStaticTime(begingWait); + UL_cu_fs6(ru, &L1proc, &timeStamp, &DuClock, &startProcessing); updateTimesReset(begingWait, &waitDUAndProcessingUL, 1000, true,"CU Time in wait Rx + Ul processing"); - UL_cu_fs6(ru, &L1proc, &timeStamp); pickStaticTime(begingWait2); - DL_cu_fs6(ru, &L1proc); + DL_cu_fs6(ru, &L1proc, DuClock, startProcessing); updateTimesReset(begingWait2, &makeSendDL, 1000, true,"CU Time in DL build+send"); } diff --git a/executables/main-ocp.c b/executables/main-ocp.c index 819eab0ee6..fe36d89bc4 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -613,7 +613,7 @@ void rx_rf(RU_t *ru, L1_rxtx_proc_t *proc) { #endif } - if (timestamp_rx - old_ts != fp->samples_per_tti) { + if (old_ts != 0 && timestamp_rx - old_ts != fp->samples_per_tti) { LOG_E(HW,"impossible shift in rx stream, rx: %ld, previous rx distance: %ld, should be %d\n", timestamp_rx, proc->timestamp_rx - old_ts, fp->samples_per_tti); //ru->ts_offset += (proc->timestamp_rx - old_ts - fp->samples_per_tti); //proc->timestamp_rx = ts-ru->ts_offset; diff --git a/executables/split_headers.h b/executables/split_headers.h index 550f189e02..93f1ac3bdf 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -36,6 +36,7 @@ typedef struct commonUDP_s { uint16_t blockID; // id: 0..nbBocks-1 uint16_t contentType; // defines the content format uint16_t contentBytes; // will be sent in a UDP packet, so must be < 2^16 bytes + uint64_t senderClock; } commonUDP_t; // FS6 UL common header (DU to CU) @@ -57,6 +58,8 @@ typedef struct { int num_mdci; int amp; LTE_eNB_PHICH phich_vars; + uint64_t DuClock; + uint64_t CuSpentMicroSec; } fs6_dl_t; // a value to type all sub packets, diff --git a/executables/transport_split.c b/executables/transport_split.c index d54b2692ca..ee19db082f 100644 --- a/executables/transport_split.c +++ b/executables/transport_split.c @@ -129,6 +129,7 @@ int receiveSubFrame(UDPsock_t *sock, void *bufferZone, int bufferSize, uint16_t int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize, uint16_t contentType) { commonUDP_t *UDPheader=(commonUDP_t *)bufferZone ; UDPheader->contentType=contentType; + UDPheader->senderClock=rdtsc(); int nbBlocks=UDPheader->nbBlocks; int blockId=0; diff --git a/nfapi/oai_integration/nfapi.c b/nfapi/oai_integration/nfapi.c index 4fc35fd951..86d1ae3127 100644 --- a/nfapi/oai_integration/nfapi.c +++ b/nfapi/oai_integration/nfapi.c @@ -29,7 +29,7 @@ typedef struct { nfapi_mode_t nfapi_mode; } nfapi_params_t; -static nfapi_params_t nfapi_params; +static nfapi_params_t nfapi_params = {0}; void set_thread_priority(int priority) { //printf("%s(priority:%d)\n", __FUNCTION__, priority); diff --git a/openair2/UTIL/OPT/probe.c b/openair2/UTIL/OPT/probe.c index 88adb1b209..2cfda081ee 100644 --- a/openair2/UTIL/OPT/probe.c +++ b/openair2/UTIL/OPT/probe.c @@ -98,8 +98,8 @@ int opt_enabled=0; //static unsigned char g_PDUBuffer[1600]; //static unsigned int g_PDUOffset; -static char *in_ip; -static char *in_path; +static char in_ip[128]={0}; +static char in_path[128]={0}; FILE *file_fd = NULL; pcap_hdr_t file_header = { 0xa1b2c3d4, /* magic number */ @@ -450,7 +450,7 @@ int init_opt(void) { char *in_type=NULL; paramdef_t opt_params[] = OPT_PARAMS_DESC ; checkedparam_t opt_checkParams[] = OPTPARAMS_CHECK_DESC; - uint16_t in_port; + uint16_t in_port=0; config_set_checkfunctions(opt_params, opt_checkParams, sizeof(opt_params)/sizeof(paramdef_t)); config_get( opt_params,sizeof(opt_params)/sizeof(paramdef_t),OPT_CONFIGPREFIX); diff --git a/targets/ARCH/rfsimulator/simulator.c b/targets/ARCH/rfsimulator/simulator.c index 95eeb38aa0..ec5953e941 100644 --- a/targets/ARCH/rfsimulator/simulator.c +++ b/targets/ARCH/rfsimulator/simulator.c @@ -346,7 +346,8 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t, openair0_timestamp if ( t->lastWroteTS != 0 && abs((double)t->lastWroteTS-timestamp) > (double)CirSize) LOG_E(HW,"Discontinuous TX gap too large Tx:%lu, %lu\n", t->lastWroteTS, timestamp); - AssertFatal(t->lastWroteTS <= timestamp+1, " Not supported to send Tx out of order (same in USRP) %lu, %lu\n", + if (t->lastWroteTS >= timestamp+1) + LOG_E(HW,"Not supported to send Tx out of order (same in USRP) %lu, %lu\n", t->lastWroteTS, timestamp); t->lastWroteTS=timestamp+nsamps; @@ -420,7 +421,7 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi if ( sz < 0 ) { if ( errno != EAGAIN ) { LOG_E(HW,"socket failed %s\n", strerror(errno)); - abort(); + //abort(); } } else if ( sz == 0 ) continue; @@ -466,8 +467,9 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi } else if ( b->lastReceivedTS == b->th.timestamp ) { // normal case } else { - abort(); - AssertFatal(false, "received data in past: current is %lu, new reception: %lu!\n", b->lastReceivedTS, b->th.timestamp); } + LOG_E(HW, "received data in past: current is %lu, new reception: %lu!\n", b->lastReceivedTS, b->th.timestamp); + b->trashingPacket=true; + } pthread_mutex_lock(&Sockmutex); diff --git a/targets/RT/USER/lte-softmodem-common.c b/targets/RT/USER/lte-softmodem-common.c index 5cc18362da..aaf7d4483d 100644 --- a/targets/RT/USER/lte-softmodem-common.c +++ b/targets/RT/USER/lte-softmodem-common.c @@ -54,16 +54,16 @@ softmodem_params_t *get_softmodem_params(void) { } void get_common_options(void) { - uint32_t online_log_messages; - uint32_t glog_level ; - uint32_t start_telnetsrv; - uint32_t noS1; - uint32_t nokrnmod; - uint32_t nonbiot; - uint32_t rfsim; - uint32_t basicsim; + uint32_t online_log_messages=0; + uint32_t glog_level =0; + uint32_t start_telnetsrv=0; + uint32_t noS1=0; + uint32_t nokrnmod=0; + uint32_t nonbiot=0; + uint32_t rfsim=0; + uint32_t basicsim=0; char *logmem_filename = NULL; - uint32_t do_forms; + uint32_t do_forms=0; paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC ; paramdef_t cmdline_logparams[] =CMDLINE_LOGPARAMS_DESC ; checkedparam_t cmdline_log_CheckParams[] = CMDLINE_LOGPARAMS_CHECK_DESC; diff --git a/targets/RT/USER/lte-uesoftmodem.c b/targets/RT/USER/lte-uesoftmodem.c index 88b9b13233..a2a7b69107 100644 --- a/targets/RT/USER/lte-uesoftmodem.c +++ b/targets/RT/USER/lte-uesoftmodem.c @@ -320,13 +320,13 @@ void exit_function(const char *file, const char *function, const int line, const extern int16_t dlsch_demod_shift; static void get_options(void) { - int CC_id; - int tddflag; + int CC_id=0; + int tddflag=0; char *loopfile=NULL; int dumpframe=0; - int timingadv; - uint8_t nfapi_mode; - int simL1flag ; + int timingadv=0; + uint8_t nfapi_mode=0; + int simL1flag =0; set_default_frame_parms(frame_parms); CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP); /* unknown parameters on command line will be checked in main From 8dedd093fbb6df3ec958b6d3eee4b538fd5bb12d Mon Sep 17 00:00:00 2001 From: laurent Date: Fri, 6 Dec 2019 18:41:30 +0100 Subject: [PATCH 066/240] remove a forgotten test trace, re-indentation of modified source files --- executables/main-fs6.c | 37 +++++++++++++++++++---------------- executables/main-ocp.c | 2 +- executables/transport_split.c | 11 ++++++----- 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index e39fad1c04..0dbd9a3b45 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -86,7 +86,6 @@ static inline void measTransportTime(uint64_t DuSend, uint64_t CuMicroSec, Meas if (DuSend!=0) { uint64_t end=rdtsc(); long long diff=(end-DuSend)/(cpuf*1000)-CuMicroSec; - LOG_E(HW, "total: %f, cu time %lu\n", (end-DuSend)/(cpuf*1000), CuMicroSec); M->maxArray[0]=diff; M->sum+=diff; M->iterations++; @@ -1344,24 +1343,26 @@ void *DL_du_fs6(void *arg) { lastTS+ru->eNB_list[i]->frame_parms.samples_per_tti, hUDP(bufferZone)->timestamp); } - pickStaticTime(begingProcessing); + + pickStaticTime(begingProcessing); lastTS=hUDP(bufferZone)->timestamp; setAllfromTS(hUDP(bufferZone)->timestamp - sf_ahead*ru->eNB_list[i]->frame_parms.samples_per_tti, &L1_proc); - measTransportTime(hDL(bufferZone)->DuClock, hDL(bufferZone)->CuSpentMicroSec, - &transportTime, 1000, false, "Transport time, to CU + from CU for one subframe"); + measTransportTime(hDL(bufferZone)->DuClock, hDL(bufferZone)->CuSpentMicroSec, + &transportTime, 1000, false, "Transport time, to CU + from CU for one subframe"); phy_procedures_eNB_TX_fromsplit( bufferZone, nb_blocks, ru->eNB_list[i], &L1_proc, 1); - updateTimesReset(begingProcessing, &DuHigh, 1000, false, "DU high layer1 processing for DL"); + updateTimesReset(begingProcessing, &DuHigh, 1000, false, "DU high layer1 processing for DL"); } else LOG_E(PHY,"DL not received for subframe\n"); } + pickStaticTime(begingProcessing); feptx_prec(ru, &L1_proc); feptx_ofdm(ru, &L1_proc); tx_rf(ru, &L1_proc); updateTimesReset(begingProcessing, &DuLow, 1000, false, "DU low layer1 processing for DL"); - - if ( IS_SOFTMODEM_RFSIM ) - return NULL; + + if ( IS_SOFTMODEM_RFSIM ) + return NULL; } return NULL; @@ -1425,21 +1426,21 @@ void DL_cu_fs6(RU_t *ru, L1_rxtx_proc_t *proc, uint64_t DuClock, uint64_t start hUDP(bufferZone)->blockID=0; hUDP(bufferZone)->contentBytes=sizeof(fs6_dl_t); } + hDL(bufferZone)->DuClock=DuClock; hDL(bufferZone)->CuSpentMicroSec=(rdtsc()-startCycle)/(cpuf*1000); - sendSubFrame(&sockFS6, bufferZone, sizeof(fs6_dl_t), CTsentCUv0 ); return; } -void UL_cu_fs6(RU_t *ru, L1_rxtx_proc_t *proc, uint64_t *TS, uint64_t * DuClock, uint64_t * startProcessing) { +void UL_cu_fs6(RU_t *ru, L1_rxtx_proc_t *proc, uint64_t *TS, uint64_t *DuClock, uint64_t *startProcessing) { initBufferZone(bufferZone); initStaticTime(begingWait); initRefTimes(fullLoop); pickStaticTime(begingWait); int nb_blocks=receiveSubFrame(&sockFS6, bufferZone, sizeof(bufferZone), CTsentDUv0 ); * DuClock=hUDP(bufferZone)->senderClock; - * startProcessing=rdtsc(); + * startProcessing=rdtsc(); updateTimesReset(begingWait, &fullLoop, 1000, false, "CU wait DU"); if (nb_blocks ==0) { @@ -1485,8 +1486,8 @@ void *cu_fs6(void *arg) { remoteIP=DU_IP; AssertFatal(createUDPsock(NULL, CU_PORT, remoteIP, DU_PORT, &sockFS6), ""); - L1_rxtx_proc_t L1proc= {0}; + if ( strlen(get_softmodem_params()->threadPoolConfig) > 0 ) initTpool(get_softmodem_params()->threadPoolConfig, &L1proc.threadPool, true); else @@ -1494,7 +1495,6 @@ void *cu_fs6(void *arg) { initNotifiedFIFO(&L1proc.respEncode); initNotifiedFIFO(&L1proc.respDecode); - uint64_t timeStamp=0; initStaticTime(begingWait); initStaticTime(begingWait2); @@ -1548,16 +1548,19 @@ void *du_fs6(void *arg) { initRefTimes(waitRxAndProcessingUL); initRefTimes(fullLoop); pthread_t t; - if ( !IS_SOFTMODEM_RFSIM ) - threadCreate(&t, DL_du_fs6, (void *)ru, "MainDuTx", -1, OAI_PRIORITY_RT_MAX); + + if ( !IS_SOFTMODEM_RFSIM ) + threadCreate(&t, DL_du_fs6, (void *)ru, "MainDuTx", -1, OAI_PRIORITY_RT_MAX); while(1) { L1_rxtx_proc_t L1proc; updateTimesReset(begingWait, &fullLoop, 1000, true,"DU for full SubFrame (must be less 1ms)"); pickStaticTime(begingWait); UL_du_fs6(ru, &L1proc); - if ( IS_SOFTMODEM_RFSIM ) - DL_du_fs6((void *)ru); + + if ( IS_SOFTMODEM_RFSIM ) + DL_du_fs6((void *)ru); + updateTimesReset(begingWait, &waitRxAndProcessingUL, 1000, true,"DU Time in wait Rx + Ul processing"); } diff --git a/executables/main-ocp.c b/executables/main-ocp.c index fe36d89bc4..2fad1bf08f 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -688,7 +688,7 @@ static void *ru_thread( void *param ) { setbuf(stdout, NULL); setbuf(stderr, NULL); RU_t *ru = (RU_t *)param; - L1_rxtx_proc_t L1proc={0}; + L1_rxtx_proc_t L1proc= {0}; L1_rxtx_proc_t *proc=&L1proc; if ( strlen(get_softmodem_params()->threadPoolConfig) > 0 ) diff --git a/executables/transport_split.c b/executables/transport_split.c index ee19db082f..1ed95db7a0 100644 --- a/executables/transport_split.c +++ b/executables/transport_split.c @@ -58,8 +58,10 @@ bool createUDPsock (char *sourceIP, char *sourcePort, char *destIP, char *destPo int enable=1; AssertFatal(setsockopt(result->sockHandler, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable))==0,""); struct timeval tv= {0,UDP_TIMEOUT}; + if (IS_SOFTMODEM_RFSIM) tv.tv_sec=2; //debug: wait 2 seconds for human understanding + AssertFatal(setsockopt(result->sockHandler, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(tv)) ==0,""); // Make a send/recv buffer larger than a a couple of subframe // so the kernel will store for us in and out paquets @@ -118,9 +120,9 @@ int receiveSubFrame(UDPsock_t *sock, void *bufferZone, int bufferSize, uint16_t rcved++; bufferZone+=ret; } - LOG_D(HW,"Received: blocks: %d/%d, size %d, TS: %lu\n", - rcved, bufOrigin->nbBlocks, ret, bufOrigin->timestamp); + LOG_D(HW,"Received: blocks: %d/%d, size %d, TS: %lu\n", + rcved, bufOrigin->nbBlocks, ret, bufOrigin->timestamp); } while ( rcved == 0 || rcved < bufOrigin->nbBlocks ); return rcved; @@ -159,11 +161,10 @@ int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize, ui sz, ret, errno, strerror(errno)); LOG_D(HW,"Sent: TS: %lu, blocks %d/%d, block size : %d \n", - UDPheader->timestamp, UDPheader->nbBlocks-nbBlocks, UDPheader->nbBlocks, sz); - + UDPheader->timestamp, UDPheader->nbBlocks-nbBlocks, UDPheader->nbBlocks, sz); bufferZone+=sz; nbBlocks--; } while (nbBlocks); - return 0; + return 0; } From 9b1846ea767319ddfc3a4b26214259edaa29bed6 Mon Sep 17 00:00:00 2001 From: Gabriele Perrone Date: Mon, 9 Dec 2019 14:20:38 +0100 Subject: [PATCH 067/240] que beau fichier --- ci-scripts/cnrie.sh | 1 + 1 file changed, 1 insertion(+) create mode 100644 ci-scripts/cnrie.sh diff --git a/ci-scripts/cnrie.sh b/ci-scripts/cnrie.sh new file mode 100644 index 0000000000..5b2c026ee6 --- /dev/null +++ b/ci-scripts/cnrie.sh @@ -0,0 +1 @@ +this is a bs \ No newline at end of file From a1cb460a0194fe283d397d1f0311164e01998676 Mon Sep 17 00:00:00 2001 From: Gabriele Perrone Date: Mon, 9 Dec 2019 14:46:59 +0100 Subject: [PATCH 068/240] repeatCounts reading from command line instead than xml file --- ci-scripts/main-cnt-mod.py | 4927 ++++++++++++++++++++++++++++++++++++ 1 file changed, 4927 insertions(+) create mode 100644 ci-scripts/main-cnt-mod.py diff --git a/ci-scripts/main-cnt-mod.py b/ci-scripts/main-cnt-mod.py new file mode 100644 index 0000000000..439dc0cfe4 --- /dev/null +++ b/ci-scripts/main-cnt-mod.py @@ -0,0 +1,4927 @@ +# /* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (the "License"); you may not use this file +# * except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.openairinterface.org/?page_id=698 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# Python for CI of OAI-eNB + COTS-UE +# +# Required Python Version +# Python 3.x +# +# Required Python Package +# pexpect +#--------------------------------------------------------------------- + +#----------------------------------------------------------- +# Version +#----------------------------------------------------------- +Version = '0.1' + +#----------------------------------------------------------- +# Constants +#----------------------------------------------------------- +ALL_PROCESSES_OK = 0 +ENB_PROCESS_FAILED = -1 +ENB_PROCESS_OK = +1 +ENB_PROCESS_SEG_FAULT = -11 +ENB_PROCESS_ASSERTION = -12 +ENB_PROCESS_REALTIME_ISSUE = -13 +ENB_PROCESS_NOLOGFILE_TO_ANALYZE = -14 +ENB_PROCESS_SLAVE_RRU_NOT_SYNCED = -15 +HSS_PROCESS_FAILED = -2 +HSS_PROCESS_OK = +2 +MME_PROCESS_FAILED = -3 +MME_PROCESS_OK = +3 +SPGW_PROCESS_FAILED = -4 +SPGW_PROCESS_OK = +4 +UE_IP_ADDRESS_ISSUE = -5 +OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE = -20 +OAI_UE_PROCESS_COULD_NOT_SYNC = -21 +OAI_UE_PROCESS_ASSERTION = -22 +OAI_UE_PROCESS_FAILED = -23 +OAI_UE_PROCESS_NO_TUNNEL_INTERFACE = -24 +OAI_UE_PROCESS_OK = +6 + +UE_STATUS_DETACHED = 0 +UE_STATUS_DETACHING = 1 +UE_STATUS_ATTACHING = 2 +UE_STATUS_ATTACHED = 3 + +X2_HO_REQ_STATE__IDLE = 0 +X2_HO_REQ_STATE__TARGET_RECEIVES_REQ = 1 +X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE = 2 +X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ = 3 +X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK = 10 + +#----------------------------------------------------------- +# Import +#----------------------------------------------------------- +import sys # arg +import re # reg +import pexpect # pexpect +import time # sleep +import os +import subprocess +import xml.etree.ElementTree as ET +import logging +import datetime +import signal +from multiprocessing import Process, Lock, SimpleQueue +logging.basicConfig( + level=logging.DEBUG, + format="[%(asctime)s] %(name)s:%(levelname)s: %(message)s" +) + +#----------------------------------------------------------- +# Class Declaration +#----------------------------------------------------------- +class SSHConnection(): + def __init__(self): + self.prematureExit = False + self.ranRepository = '' + self.ranBranch = '' + self.ranAllowMerge = False + self.ranCommitID = '' + self.ranTargetBranch = '' + self.eNBIPAddress = '' + self.eNBUserName = '' + self.eNBPassword = '' + self.eNBSourceCodePath = '' + self.EPCIPAddress = '' + self.EPCUserName = '' + self.EPCPassword = '' + self.eNB1IPAddress = '' + self.eNB1UserName = '' + self.eNB1Password = '' + self.eNB1SourceCodePath = '' + self.eNB2IPAddress = '' + self.eNB2UserName = '' + self.eNB2Password = '' + self.eNB2SourceCodePath = '' + self.EPCSourceCodePath = '' + self.EPCType = '' + self.EPC_PcapFileName = '' + self.ADBIPAddress = '' + self.ADBUserName = '' + self.ADBPassword = '' + self.ADBCentralized = True + self.testCase_id = '' + self.testXMLfiles = [] + self.nbTestXMLfiles = 0 + self.desc = '' + self.Build_eNB_args = '' + self.backgroundBuild = False + self.backgroundBuildTestId = ['', '', ''] + self.Initialize_eNB_args = '' + self.eNB_instance = '' + self.eNB_serverId = '' + self.eNBLogFiles = ['', '', ''] + self.eNBOptions = ['', '', ''] + self.ping_args = '' + self.ping_packetloss_threshold = '' + self.iperf_args = '' + self.iperf_packetloss_threshold = '' + self.iperf_profile = '' + self.nbMaxUEtoAttach = -1 + self.UEDevices = [] + self.UEDevicesStatus = [] + self.UEDevicesRemoteServer = [] + self.UEDevicesRemoteUser = [] + self.UEDevicesOffCmd = [] + self.UEDevicesOnCmd = [] + self.UEDevicesRebootCmd = [] + self.CatMDevices = [] + self.UEIPAddresses = [] + self.htmlFile = '' + self.htmlHeaderCreated = False + self.htmlFooterCreated = False + self.htmlUEConnected = -1 + self.htmleNBFailureMsg = '' + self.htmlUEFailureMsg = '' + self.picocom_closure = False + self.idle_sleep_time = 0 + self.x2_ho_options = 'network' + self.x2NbENBs = 0 + self.x2ENBBsIds = [] + self.x2ENBConnectedUEs = [] + self.htmlTabRefs = [] + self.htmlTabNames = [] + self.htmlTabIcons = [] + # repeatCounts was a list --> becomes an integer + self.repeatCounts = 1 + self.finalStatus = False + self.OsVersion = '' + self.KernelVersion = '' + self.UhdVersion = '' + self.UsrpBoard = '' + self.CpuNb = '' + self.CpuModel = '' + self.CpuMHz = '' + self.UEIPAddress = '' + self.UEUserName = '' + self.UEPassword = '' + self.UE_instance = '' + self.UESourceCodePath = '' + self.UELogFile = '' + self.Build_OAI_UE_args = '' + self.Initialize_OAI_UE_args = '' + self.flexranCtrlInstalled = False + self.flexranCtrlStarted = False + self.expectedNbOfConnectedUEs = 0 + self.startTime = 0 + + def open(self, ipaddress, username, password): + count = 0 + connect_status = False + while count < 4: + self.ssh = pexpect.spawn('ssh', [username + '@' + ipaddress], timeout = 5) + self.sshresponse = self.ssh.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', 'Last login', pexpect.EOF, pexpect.TIMEOUT]) + if self.sshresponse == 0: + self.ssh.sendline('yes') + self.ssh.expect('password:') + self.ssh.sendline(password) + self.sshresponse = self.ssh.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if self.sshresponse == 0: + count = 10 + connect_status = True + else: + logging.debug('self.sshresponse = ' + str(self.sshresponse)) + elif self.sshresponse == 1: + self.ssh.sendline(password) + self.sshresponse = self.ssh.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if self.sshresponse == 0: + count = 10 + connect_status = True + else: + logging.debug('self.sshresponse = ' + str(self.sshresponse)) + elif self.sshresponse == 2: + # Checking if we are really on the remote client defined by its IP address + self.command('stdbuf -o0 ifconfig | egrep --color=never "inet addr:|inet "', '\$', 5) + result = re.search(str(ipaddress), str(self.ssh.before)) + if result is None: + self.close() + else: + count = 10 + connect_status = True + else: + # debug output + logging.debug(str(self.ssh.before)) + logging.debug('self.sshresponse = ' + str(self.sshresponse)) + # adding a tempo when failure + if not connect_status: + time.sleep(1) + count += 1 + if connect_status: + pass + else: + sys.exit('SSH Connection Failed') + + def command(self, commandline, expectedline, timeout): + logging.debug(commandline) + self.ssh.timeout = timeout + self.ssh.sendline(commandline) + self.sshresponse = self.ssh.expect([expectedline, pexpect.EOF, pexpect.TIMEOUT]) + if self.sshresponse == 0: + return 0 + elif self.sshresponse == 1: + logging.debug('\u001B[1;37;41m Unexpected EOF \u001B[0m') + logging.debug('Expected Line : ' + expectedline) + sys.exit(self.sshresponse) + elif self.sshresponse == 2: + logging.debug('\u001B[1;37;41m Unexpected TIMEOUT \u001B[0m') + logging.debug('Expected Line : ' + expectedline) + result = re.search('ping |iperf |picocom', str(commandline)) + if result is None: + logging.debug(str(self.ssh.before)) + sys.exit(self.sshresponse) + else: + return -1 + else: + logging.debug('\u001B[1;37;41m Unexpected Others \u001B[0m') + logging.debug('Expected Line : ' + expectedline) + sys.exit(self.sshresponse) + + def close(self): + self.ssh.timeout = 5 + self.ssh.sendline('exit') + self.sshresponse = self.ssh.expect([pexpect.EOF, pexpect.TIMEOUT]) + if self.sshresponse == 0: + pass + elif self.sshresponse == 1: + if not self.picocom_closure: + logging.debug('\u001B[1;37;41m Unexpected TIMEOUT during closing\u001B[0m') + else: + logging.debug('\u001B[1;37;41m Unexpected Others during closing\u001B[0m') + + def copyin(self, ipaddress, username, password, source, destination): + count = 0 + copy_status = False + logging.debug('scp '+ username + '@' + ipaddress + ':' + source + ' ' + destination) + while count < 10: + scp_spawn = pexpect.spawn('scp '+ username + '@' + ipaddress + ':' + source + ' ' + destination, timeout = 100) + scp_response = scp_spawn.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if scp_response == 0: + scp_spawn.sendline('yes') + scp_spawn.expect('password:') + scp_spawn.sendline(password) + scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if scp_response == 0: + count = 10 + copy_status = True + else: + logging.debug('1 - scp_response = ' + str(scp_response)) + elif scp_response == 1: + scp_spawn.sendline(password) + scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if scp_response == 0 or scp_response == 3: + count = 10 + copy_status = True + else: + logging.debug('2 - scp_response = ' + str(scp_response)) + elif scp_response == 2: + count = 10 + copy_status = True + else: + logging.debug('3 - scp_response = ' + str(scp_response)) + # adding a tempo when failure + if not copy_status: + time.sleep(1) + count += 1 + if copy_status: + return 0 + else: + return -1 + + def copyout(self, ipaddress, username, password, source, destination): + count = 0 + copy_status = False + logging.debug('scp ' + source + ' ' + username + '@' + ipaddress + ':' + destination) + while count < 4: + scp_spawn = pexpect.spawn('scp ' + source + ' ' + username + '@' + ipaddress + ':' + destination, timeout = 100) + scp_response = scp_spawn.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if scp_response == 0: + scp_spawn.sendline('yes') + scp_spawn.expect('password:') + scp_spawn.sendline(password) + scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if scp_response == 0: + count = 10 + copy_status = True + else: + logging.debug('1 - scp_response = ' + str(scp_response)) + elif scp_response == 1: + scp_spawn.sendline(password) + scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if scp_response == 0 or scp_response == 3: + count = 10 + copy_status = True + else: + logging.debug('2 - scp_response = ' + str(scp_response)) + elif scp_response == 2: + count = 10 + copy_status = True + else: + logging.debug('3 - scp_response = ' + str(scp_response)) + # adding a tempo when failure + if not copy_status: + time.sleep(1) + count += 1 + if copy_status: + pass + else: + sys.exit('SCP failed') + + def BuildeNB(self): + if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': + Usage() + sys.exit('Insufficient Parameter') + if self.eNB_serverId == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = self.eNBSourceCodePath + elif self.eNB_serverId == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + lSourcePath = self.eNB1SourceCodePath + elif self.eNB_serverId == '2': + lIpAddr = self.eNB2IPAddress + lUserName = self.eNB2UserName + lPassWord = self.eNB2Password + lSourcePath = self.eNB2SourceCodePath + if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': + Usage() + sys.exit('Insufficient Parameter') + self.open(lIpAddr, lUserName, lPassWord) + self.command('mkdir -p ' + lSourcePath, '\$', 5) + self.command('cd ' + lSourcePath, '\$', 5) + self.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + self.ranRepository + ' .; else stdbuf -o0 git fetch; fi', '\$', 600) + # Raphael: here add a check if git clone or git fetch went smoothly + self.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) + self.command('git config user.name "OAI Jenkins"', '\$', 5) + # Checking the BUILD INFO file + if not self.backgroundBuild: + self.command('ls *.txt', '\$', 5) + result = re.search('LAST_BUILD_INFO', str(self.ssh.before)) + if result is not None: + mismatch = False + self.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) + result = re.search(self.ranCommitID, str(self.ssh.before)) + if result is None: + mismatch = True + self.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) + if (self.ranAllowMerge): + result = re.search('YES', str(self.ssh.before)) + if result is None: + mismatch = True + self.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) + if self.ranTargetBranch == '': + result = re.search('develop', str(self.ssh.before)) + else: + result = re.search(self.ranTargetBranch, str(self.ssh.before)) + if result is None: + mismatch = True + else: + result = re.search('NO', str(self.ssh.before)) + if result is None: + mismatch = True + if not mismatch: + self.close() + self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) + return + + self.command('echo ' + lPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30) + # if the commit ID is provided use it to point to it + if self.ranCommitID != '': + self.command('git checkout -f ' + self.ranCommitID, '\$', 5) + # if the branch is not develop, then it is a merge request and we need to do + # the potential merge. Note that merge conflicts should already been checked earlier + if (self.ranAllowMerge): + if self.ranTargetBranch == '': + if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'): + self.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) + else: + logging.debug('Merging with the target branch: ' + self.ranTargetBranch) + self.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5) + self.command('source oaienv', '\$', 5) + self.command('cd cmake_targets', '\$', 5) + self.command('mkdir -p log', '\$', 5) + self.command('chmod 777 log', '\$', 5) + # no need to remove in log (git clean did the trick) + if self.backgroundBuild: + self.command('echo "./build_oai ' + self.Build_eNB_args + '" > ./my-lte-softmodem-build.sh', '\$', 5) + self.command('chmod 775 ./my-lte-softmodem-build.sh', '\$', 5) + self.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=build_enb_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/compile_oai_enb.log ./my-lte-softmodem-build.sh', '\$', 5) + self.close() + self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) + self.backgroundBuildTestId[int(self.eNB_instance)] = self.testCase_id + return + self.command('stdbuf -o0 ./build_oai ' + self.Build_eNB_args + ' 2>&1 | stdbuf -o0 tee compile_oai_enb.log', 'Bypassing the Tests|build have failed', 1500) + self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.testCase_id) + + def WaitBuildeNBisFinished(self): + if self.eNB_serverId == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = self.eNBSourceCodePath + elif self.eNB_serverId == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + lSourcePath = self.eNB1SourceCodePath + elif self.eNB_serverId == '2': + lIpAddr = self.eNB2IPAddress + lUserName = self.eNB2UserName + lPassWord = self.eNB2Password + lSourcePath = self.eNB2SourceCodePath + if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': + Usage() + sys.exit('Insufficient Parameter') + self.open(lIpAddr, lUserName, lPassWord) + count = 40 + buildOAIprocess = True + while (count > 0) and buildOAIprocess: + self.command('ps aux | grep --color=never build_ | grep -v grep', '\$', 3) + result = re.search('build_oai', str(self.ssh.before)) + if result is None: + buildOAIprocess = False + else: + count -= 1 + time.sleep(30) + self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.backgroundBuildTestId[int(self.eNB_instance)]) + + def checkBuildeNB(self, lIpAddr, lUserName, lPassWord, lSourcePath, testcaseId): + self.command('cd ' + lSourcePath + '/cmake_targets', '\$', 3) + self.command('ls lte_build_oai/build', '\$', 3) + self.command('ls lte_build_oai/build', '\$', 3) + buildStatus = True + result = re.search('lte-softmodem', str(self.ssh.before)) + if result is None: + buildStatus = False + else: + # Generating a BUILD INFO file + self.command('echo "SRC_BRANCH: ' + self.ranBranch + '" > ../LAST_BUILD_INFO.txt', '\$', 2) + self.command('echo "SRC_COMMIT: ' + self.ranCommitID + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) + if (self.ranAllowMerge): + self.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2) + if self.ranTargetBranch == '': + self.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2) + else: + self.command('echo "TGT_BRANCH: ' + self.ranTargetBranch + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) + else: + self.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) + self.command('mkdir -p build_log_' + testcaseId, '\$', 5) + self.command('mv log/* ' + 'build_log_' + testcaseId, '\$', 5) + self.command('mv compile_oai_enb.log ' + 'build_log_' + testcaseId, '\$', 5) + if self.eNB_serverId != '0': + self.command('cd cmake_targets', '\$', 5) + self.command('if [ -e tmp_build' + testcaseId + '.zip ]; then rm -f tmp_build' + testcaseId + '.zip; fi', '\$', 5) + self.command('zip -r -qq tmp_build' + testcaseId + '.zip build_log_' + testcaseId, '\$', 5) + self.close() + if (os.path.isfile('./tmp_build' + testcaseId + '.zip')): + os.remove('./tmp_build' + testcaseId + '.zip') + self.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/tmp_build' + testcaseId + '.zip', '.') + if (os.path.isfile('./tmp_build' + testcaseId + '.zip')): + self.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './tmp_build' + testcaseId + '.zip', self.eNBSourceCodePath + '/cmake_targets/.') + os.remove('./tmp_build' + testcaseId + '.zip') + self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) + self.command('cd ' + self.eNBSourceCodePath + '/cmake_targets', '\$', 5) + self.command('unzip -qq -DD tmp_build' + testcaseId + '.zip', '\$', 5) + self.command('rm -f tmp_build' + testcaseId + '.zip', '\$', 5) + self.close() + else: + self.close() + + if buildStatus: + self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) + else: + logging.error('\u001B[1m Building OAI eNB Failed\u001B[0m') + self.CreateHtmlTestRow(self.Build_eNB_args, 'KO', ALL_PROCESSES_OK) + self.CreateHtmlTabFooter(False) + sys.exit(1) + + def BuildOAIUE(self): + if self.UEIPAddress == '' or self.ranRepository == '' or self.ranBranch == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + self.command('mkdir -p ' + self.UESourceCodePath, '\$', 5) + self.command('cd ' + self.UESourceCodePath, '\$', 5) + self.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + self.ranRepository + ' .; else stdbuf -o0 git fetch; fi', '\$', 600) + # here add a check if git clone or git fetch went smoothly + self.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) + self.command('git config user.name "OAI Jenkins"', '\$', 5) + self.command('ls *.txt', '\$', 5) + result = re.search('LAST_BUILD_INFO', str(self.ssh.before)) + if result is not None: + mismatch = False + self.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) + result = re.search(self.ranCommitID, str(self.ssh.before)) + if result is None: + mismatch = True + self.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) + if (self.ranAllowMerge): + result = re.search('YES', str(self.ssh.before)) + if result is None: + mismatch = True + self.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) + if self.ranTargetBranch == '': + result = re.search('develop', str(self.ssh.before)) + else: + result = re.search(self.ranTargetBranch, str(self.ssh.before)) + if result is None: + mismatch = True + else: + result = re.search('NO', str(self.ssh.before)) + if result is None: + mismatch = True + if not mismatch: + self.close() + self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) + return + + self.command('echo ' + self.UEPassword + ' | sudo -S git clean -x -d -ff', '\$', 30) + # if the commit ID is provided use it to point to it + if self.ranCommitID != '': + self.command('git checkout -f ' + self.ranCommitID, '\$', 5) + # if the branch is not develop, then it is a merge request and we need to do + # the potential merge. Note that merge conflicts should already been checked earlier + if (self.ranAllowMerge): + if self.ranTargetBranch == '': + if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'): + self.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) + else: + logging.debug('Merging with the target branch: ' + self.ranTargetBranch) + self.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5) + self.command('source oaienv', '\$', 5) + self.command('cd cmake_targets', '\$', 5) + self.command('mkdir -p log', '\$', 5) + self.command('chmod 777 log', '\$', 5) + # no need to remove in log (git clean did the trick) + self.command('stdbuf -o0 ./build_oai ' + self.Build_OAI_UE_args + ' 2>&1 | stdbuf -o0 tee compile_oai_ue.log', 'Bypassing the Tests|build have failed', 600) + self.command('ls lte_build_oai/build', '\$', 3) + self.command('ls lte_build_oai/build', '\$', 3) + buildStatus = True + result = re.search('lte-uesoftmodem', str(self.ssh.before)) + if result is None: + buildStatus = False + self.command('mkdir -p build_log_' + self.testCase_id, '\$', 5) + self.command('mv log/* ' + 'build_log_' + self.testCase_id, '\$', 5) + self.command('mv compile_oai_ue.log ' + 'build_log_' + self.testCase_id, '\$', 5) + if buildStatus: + # Generating a BUILD INFO file + self.command('echo "SRC_BRANCH: ' + self.ranBranch + '" > ../LAST_BUILD_INFO.txt', '\$', 2) + self.command('echo "SRC_COMMIT: ' + self.ranCommitID + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) + if (self.ranAllowMerge): + self.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2) + if self.ranTargetBranch == '': + self.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2) + else: + self.command('echo "TGT_BRANCH: ' + self.ranTargetBranch + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) + else: + self.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) + self.close() + self.CreateHtmlTestRow(self.Build_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE') + else: + self.close() + logging.error('\u001B[1m Building OAI UE Failed\u001B[0m') + self.CreateHtmlTestRow(self.Build_OAI_UE_args, 'KO', ALL_PROCESSES_OK, 'OAI UE') + self.CreateHtmlTabFooter(False) + sys.exit(1) + + def InitializeHSS(self): + if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': + Usage() + sys.exit('Insufficient Parameter') + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + logging.debug('Using the OAI EPC Release 14 Cassandra-based HSS') + self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + logging.debug('\u001B[1m Launching tshark on all interfaces \u001B[0m') + EPC_PcapFileName = 'epc_' + self.testCase_id + '.pcap' + self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f ' + EPC_PcapFileName, '\$', 5) + self.command('echo $USER; nohup sudo tshark -f "tcp port not 22 and port not 53" -i any -w ' + self.EPCSourceCodePath + '/scripts/' + EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', self.EPCUserName, 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S mkdir -p logs', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f hss_' + self.testCase_id + '.log logs/hss*.*', '\$', 5) + self.command('echo "oai_hss -j /usr/local/etc/oai/hss_rel14.json" > ./my-hss.sh', '\$', 5) + self.command('chmod 755 ./my-hss.sh', '\$', 5) + self.command('sudo daemon --unsafe --name=hss_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/hss_' + self.testCase_id + '.log ./my-hss.sh', '\$', 5) + elif re.match('OAI', self.EPCType, re.IGNORECASE): + logging.debug('Using the OAI EPC HSS') + self.command('cd ' + self.EPCSourceCodePath, '\$', 5) + self.command('source oaienv', '\$', 5) + self.command('cd scripts', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S ./run_hss 2>&1 | stdbuf -o0 awk \'{ print strftime("[%Y/%m/%d %H:%M:%S] ",systime()) $0 }\' | stdbuf -o0 tee -a hss_' + self.testCase_id + '.log &', 'Core state: 2 -> 3', 35) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + logging.debug('Using the ltebox simulated HSS') + self.command('if [ -d ' + self.EPCSourceCodePath + '/scripts ]; then echo ' + self.eNBPassword + ' | sudo -S rm -Rf ' + self.EPCSourceCodePath + '/scripts ; fi', '\$', 5) + self.command('mkdir -p ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + self.command('cd /opt/hss_sim0609', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f hss.log daemon.log', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S echo "Starting sudo session" && sudo daemon --unsafe --name=simulated_hss --chdir=/opt/hss_sim0609 ./starthss_real ', '\$', 5) + else: + logging.error('This option should not occur!') + self.close() + self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) + + def InitializeMME(self): + if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': + Usage() + sys.exit('Insufficient Parameter') + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + logging.debug('Using the OAI EPC Release 14 MME') + self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f mme_' + self.testCase_id + '.log', '\$', 5) + self.command('echo "./run_mme --config-file /usr/local/etc/oai/mme.conf --set-virt-if" > ./my-mme.sh', '\$', 5) + self.command('chmod 755 ./my-mme.sh', '\$', 5) + self.command('sudo daemon --unsafe --name=mme_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/mme_' + self.testCase_id + '.log ./my-mme.sh', '\$', 5) + elif re.match('OAI', self.EPCType, re.IGNORECASE): + self.command('cd ' + self.EPCSourceCodePath, '\$', 5) + self.command('source oaienv', '\$', 5) + self.command('cd scripts', '\$', 5) + self.command('stdbuf -o0 hostname', '\$', 5) + result = re.search('hostname\\\\r\\\\n(?P[a-zA-Z0-9\-\_]+)\\\\r\\\\n', str(self.ssh.before)) + if result is None: + logging.debug('\u001B[1;37;41m Hostname Not Found! \u001B[0m') + sys.exit(1) + host_name = result.group('host_name') + self.command('echo ' + self.EPCPassword + ' | sudo -S ./run_mme 2>&1 | stdbuf -o0 tee -a mme_' + self.testCase_id + '.log &', 'MME app initialization complete', 100) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + self.command('cd /opt/ltebox/tools', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S ./start_mme', '\$', 5) + else: + logging.error('This option should not occur!') + self.close() + self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) + + def InitializeSPGW(self): + if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': + Usage() + sys.exit('Insufficient Parameter') + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + logging.debug('Using the OAI EPC Release 14 SPGW-CUPS') + self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f spgwc_' + self.testCase_id + '.log spgwu_' + self.testCase_id + '.log', '\$', 5) + self.command('echo "spgwc -c /usr/local/etc/oai/spgw_c.conf" > ./my-spgwc.sh', '\$', 5) + self.command('chmod 755 ./my-spgwc.sh', '\$', 5) + self.command('sudo daemon --unsafe --name=spgwc_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/spgwc_' + self.testCase_id + '.log ./my-spgwc.sh', '\$', 5) + time.sleep(5) + self.command('echo "spgwu -c /usr/local/etc/oai/spgw_u.conf" > ./my-spgwu.sh', '\$', 5) + self.command('chmod 755 ./my-spgwu.sh', '\$', 5) + self.command('sudo daemon --unsafe --name=spgwu_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/spgwu_' + self.testCase_id + '.log ./my-spgwu.sh', '\$', 5) + elif re.match('OAI', self.EPCType, re.IGNORECASE): + self.command('cd ' + self.EPCSourceCodePath, '\$', 5) + self.command('source oaienv', '\$', 5) + self.command('cd scripts', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S ./run_spgw 2>&1 | stdbuf -o0 tee -a spgw_' + self.testCase_id + '.log &', 'Initializing SPGW-APP task interface: DONE', 30) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + self.command('cd /opt/ltebox/tools', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S ./start_xGw', '\$', 5) + else: + logging.error('This option should not occur!') + self.close() + self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) + + def CheckFlexranCtrlInstallation(self): + if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '': + return + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('ls -ls /opt/flexran_rtc/*/rt_controller', '\$', 5) + result = re.search('/opt/flexran_rtc/build/rt_controller', str(self.ssh.before)) + if result is not None: + self.flexranCtrlInstalled = True + logging.debug('Flexran Controller is installed') + self.close() + + def InitializeFlexranCtrl(self): + if self.flexranCtrlInstalled == False: + return + if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '': + Usage() + sys.exit('Insufficient Parameter') + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('cd /opt/flexran_rtc', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f log/*.log', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S echo "build/rt_controller -c log_config/basic_log" > ./my-flexran-ctl.sh', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S chmod 755 ./my-flexran-ctl.sh', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S daemon --unsafe --name=flexran_rtc_daemon --chdir=/opt/flexran_rtc -o /opt/flexran_rtc/log/flexranctl_' + self.testCase_id + '.log ././my-flexran-ctl.sh', '\$', 5) + self.command('ps -aux | grep --color=never rt_controller', '\$', 5) + result = re.search('rt_controller -c ', str(self.ssh.before)) + if result is not None: + logging.debug('\u001B[1m Initialize FlexRan Controller Completed\u001B[0m') + self.flexranCtrlStarted = True + self.close() + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def InitializeeNB(self): + if self.eNB_serverId == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = self.eNBSourceCodePath + elif self.eNB_serverId == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + lSourcePath = self.eNB1SourceCodePath + elif self.eNB_serverId == '2': + lIpAddr = self.eNB2IPAddress + lUserName = self.eNB2UserName + lPassWord = self.eNB2Password + lSourcePath = self.eNB2SourceCodePath + if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': + Usage() + sys.exit('Insufficient Parameter') + check_eNB = False + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow(self.Initialize_eNB_args, 'KO', pStatus) + self.CreateHtmlTabFooter(False) + sys.exit(1) + # If tracer options is on, running tshark on EPC side and capture traffic b/ EPC and eNB + result = re.search('T_stdout', str(self.Initialize_eNB_args)) + if result is not None: + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('ip addr show | awk -f /tmp/active_net_interfaces.awk | egrep -v "lo|tun"', '\$', 5) + result = re.search('interfaceToUse=(?P[a-zA-Z0-9\-\_]+)done', str(self.ssh.before)) + if result is not None: + eth_interface = result.group('eth_interface') + logging.debug('\u001B[1m Launching tshark on interface ' + eth_interface + '\u001B[0m') + self.EPC_PcapFileName = 'enb_' + self.testCase_id + '_s1log.pcap' + self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f /tmp/' + self.EPC_PcapFileName, '\$', 5) + self.command('echo $USER; nohup sudo tshark -f "host ' + lIpAddr +'" -i ' + eth_interface + ' -w /tmp/' + self.EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', self.EPCUserName, 5) + self.close() + self.open(lIpAddr, lUserName, lPassWord) + self.command('cd ' + lSourcePath, '\$', 5) + # Initialize_eNB_args usually start with -O and followed by the location in repository + full_config_file = self.Initialize_eNB_args.replace('-O ','') + extra_options = '' + extIdx = full_config_file.find('.conf') + if (extIdx > 0): + extra_options = full_config_file[extIdx + 5:] + # if tracer options is on, compiling and running T Tracer + result = re.search('T_stdout', str(extra_options)) + if result is not None: + logging.debug('\u001B[1m Compiling and launching T Tracer\u001B[0m') + self.command('cd common/utils/T/tracer', '\$', 5) + self.command('make', '\$', 10) + self.command('echo $USER; nohup ./record -d ../T_messages.txt -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.raw -ON -off VCD -off HEAVY -off LEGACY_GROUP_TRACE -off LEGACY_GROUP_DEBUG > ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.log 2>&1 &', lUserName, 5) + self.command('cd ' + lSourcePath, '\$', 5) + full_config_file = full_config_file[:extIdx + 5] + config_path, config_file = os.path.split(full_config_file) + else: + sys.exit('Insufficient Parameter') + ci_full_config_file = config_path + '/ci-' + config_file + rruCheck = False + result = re.search('^rru|^rcc|^du.band', str(config_file)) + if result is not None: + rruCheck = True + # do not reset board twice in IF4.5 case + result = re.search('^rru|^enb|^du.band', str(config_file)) + if result is not None: + self.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 10) + result = re.search('type: b200', str(self.ssh.before)) + if result is not None: + logging.debug('Found a B2xx device --> resetting it') + self.command('echo ' + lPassWord + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10) + # Reloading FGPA bin firmware + self.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 15) + # Make a copy and adapt to EPC / eNB IP addresses + self.command('cp ' + full_config_file + ' ' + ci_full_config_file, '\$', 5) + self.command('sed -i -e \'s/CI_MME_IP_ADDR/' + self.EPCIPAddress + '/\' ' + ci_full_config_file, '\$', 2); + self.command('sed -i -e \'s/CI_ENB_IP_ADDR/' + lIpAddr + '/\' ' + ci_full_config_file, '\$', 2); + self.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2); + self.command('sed -i -e \'s/CI_RRU1_IP_ADDR/' + self.eNB1IPAddress + '/\' ' + ci_full_config_file, '\$', 2); + self.command('sed -i -e \'s/CI_RRU2_IP_ADDR/' + self.eNB2IPAddress + '/\' ' + ci_full_config_file, '\$', 2); + if self.flexranCtrlInstalled and self.flexranCtrlStarted: + self.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "yes";/\' ' + ci_full_config_file, '\$', 2); + else: + self.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "no";/\' ' + ci_full_config_file, '\$', 2); + # Launch eNB with the modified config file + self.command('source oaienv', '\$', 5) + self.command('cd cmake_targets', '\$', 5) + self.command('echo "ulimit -c unlimited && ./lte_build_oai/build/lte-softmodem -O ' + lSourcePath + '/' + ci_full_config_file + extra_options + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + self.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + self.command('chmod 775 ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + self.command('echo ' + lPassWord + ' | sudo -S rm -Rf enb_' + self.testCase_id + '.log', '\$', 5) + self.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=enb' + str(self.eNB_instance) + '_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + self.eNBLogFiles[int(self.eNB_instance)] = 'enb_' + self.testCase_id + '.log' + if extra_options != '': + self.eNBOptions[int(self.eNB_instance)] = extra_options + time.sleep(6) + doLoop = True + loopCounter = 10 + while (doLoop): + loopCounter = loopCounter - 1 + if (loopCounter == 0): + # In case of T tracer recording, we may need to kill it + result = re.search('T_stdout', str(self.Initialize_eNB_args)) + if result is not None: + self.command('killall --signal SIGKILL record', '\$', 5) + self.close() + doLoop = False + logging.error('\u001B[1;37;41m eNB logging system did not show got sync! \u001B[0m') + self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'KO', ALL_PROCESSES_OK) + # In case of T tracer recording, we need to kill tshark on EPC side + result = re.search('T_stdout', str(self.Initialize_eNB_args)) + if result is not None: + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + logging.debug('\u001B[1m Stopping tshark \u001B[0m') + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) + if self.EPC_PcapFileName != '': + time.sleep(0.5) + self.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 /tmp/' + self.EPC_PcapFileName, '\$', 5) + self.close() + time.sleep(1) + if self.EPC_PcapFileName != '': + copyin_res = self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + self.EPC_PcapFileName, '.') + if (copyin_res == 0): + self.copyout(lIpAddr, lUserName, lPassWord, self.EPC_PcapFileName, lSourcePath + '/cmake_targets/.') + self.prematureExit = True + return + else: + self.command('stdbuf -o0 cat enb_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync|Starting"', '\$', 4) + if rruCheck: + result = re.search('wait RUs', str(self.ssh.before)) + else: + result = re.search('got sync|Starting F1AP at CU', str(self.ssh.before)) + if result is None: + time.sleep(6) + else: + doLoop = False + self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'OK', ALL_PROCESSES_OK) + logging.debug('\u001B[1m Initialize eNB Completed\u001B[0m') + time.sleep(10) + + self.close() + + def InitializeUE_common(self, device_id, idx): + try: + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + if not self.ADBCentralized: + # Reboot UE + #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesRebootCmd[idx], '\$', 60) + # Wait + #time.sleep(60) + # Put in LTE-Mode only + #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode 11"\'', '\$', 60) + #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode1 11"\'', '\$', 60) + #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode2 11"\'', '\$', 60) + #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode3 11"\'', '\$', 60) + # enable data service + #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) + # we need to do radio on/off cycle to make sure of above changes + # airplane mode off // radio on + #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) + #time.sleep(10) + # airplane mode on // radio off + #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + + # normal procedure without reboot + # enable data service + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) + # airplane mode on // radio off + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + self.close() + return + # enable data service + self.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data enable"', '\$', 60) + + # The following commands are deprecated since we no longer work on Android 7+ + # self.command('stdbuf -o0 adb -s ' + device_id + ' shell settings put global airplane_mode_on 1', '\$', 10) + # self.command('stdbuf -o0 adb -s ' + device_id + ' shell am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true', '\$', 60) + # a dedicated script has to be installed inside the UE + # airplane mode on means call /data/local/tmp/off + if device_id == '84B7N16418004022': + self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) + else: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) + #airplane mode off means call /data/local/tmp/on + logging.debug('\u001B[1mUE (' + device_id + ') Initialize Completed\u001B[0m') + self.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def InitializeUE(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + multi_jobs = [] + i = 0 + for device_id in self.UEDevices: + p = Process(target = self.InitializeUE_common, args = (device_id,i,)) + p.daemon = True + p.start() + multi_jobs.append(p) + i += 1 + for job in multi_jobs: + job.join() + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def InitializeOAIUE(self): + if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) + if result is None: + check_eNB = True + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', pStatus) + self.CreateHtmlTabFooter(False) + sys.exit(1) + self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + # b2xx_fx3_utils reset procedure + self.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 10) + result = re.search('type: b200', str(self.ssh.before)) + if result is not None: + logging.debug('Found a B2xx device --> resetting it') + self.command('echo ' + self.UEPassword + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10) + # Reloading FGPA bin firmware + self.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 15) + else: + logging.debug('Did not find any B2xx device') + self.command('cd ' + self.UESourceCodePath, '\$', 5) + self.command('source oaienv', '\$', 5) + self.command('cd cmake_targets/lte_build_oai/build', '\$', 5) + result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) + # We may have to regenerate the .u* files + if result is None: + self.command('ls /tmp/*.sed', '\$', 5) + result = re.search('adapt_usim_parameters', str(self.ssh.before)) + if result is not None: + self.command('sed -f /tmp/adapt_usim_parameters.sed ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5) + else: + self.command('sed -e "s#93#92#" -e "s#8baf473f2f8fd09487cccbd7097c6862#fec86ba6eb707ed08905757b1bb44b8f#" -e "s#e734f8734007d6c5ce7a0508809e7e9c#C42449363BBAD02B66D16BC975D77CC1#" ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5) + self.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf .u*', '\$', 5) + self.command('echo ' + self.UEPassword + ' | sudo -S ../../../targets/bin/conf2uedata -c ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf -o .', '\$', 5) + # Launch UE with the modified config file + self.command('echo "ulimit -c unlimited && ./lte-uesoftmodem ' + self.Initialize_OAI_UE_args + '" > ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) + self.command('chmod 775 ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) + self.UELogFile = 'ue_' + self.testCase_id + '.log' + + # We are now looping several times to hope we really sync w/ an eNB + doOutterLoop = True + outterLoopCounter = 5 + gotSyncStatus = True + fullSyncStatus = True + while (doOutterLoop): + self.command('cd ' + self.UESourceCodePath + '/cmake_targets/lte_build_oai/build', '\$', 5) + self.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log', '\$', 5) + self.command('echo ' + self.UEPassword + ' | sudo -S -E daemon --inherit --unsafe --name=ue' + str(self.UE_instance) + '_daemon --chdir=' + self.UESourceCodePath + '/cmake_targets/lte_build_oai/build -o ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) + time.sleep(6) + self.command('cd ../..', '\$', 5) + doLoop = True + loopCounter = 10 + gotSyncStatus = True + # the 'got sync' message is for the UE threads synchronization + while (doLoop): + loopCounter = loopCounter - 1 + if (loopCounter == 0): + # Here should never occur + logging.error('"got sync" message never showed!') + gotSyncStatus = False + doLoop = False + continue + self.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4) + result = re.search('got sync', str(self.ssh.before)) + if result is None: + time.sleep(6) + else: + doLoop = False + logging.debug('Found "got sync" message!') + if gotSyncStatus == False: + # we certainly need to stop the lte-uesoftmodem process if it is still running! + self.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4) + result = re.search('lte-uesoftmodem', str(self.ssh.before)) + if result is not None: + self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT lte-uesoftmodem', '\$', 4) + time.sleep(3) + # We are now checking if sync w/ eNB DOES NOT OCCUR + # Usually during the cell synchronization stage, the UE returns with No cell synchronization message + doLoop = True + loopCounter = 10 + while (doLoop): + loopCounter = loopCounter - 1 + if (loopCounter == 0): + # Here we do have a great chance that the UE did cell-sync w/ eNB + doLoop = False + doOutterLoop = False + fullSyncStatus = True + continue + self.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4) + result = re.search('No cell synchronization found', str(self.ssh.before)) + if result is None: + time.sleep(6) + else: + doLoop = False + fullSyncStatus = False + logging.debug('Found: "No cell synchronization" message! --> try again') + time.sleep(6) + self.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4) + result = re.search('lte-uesoftmodem', str(self.ssh.before)) + if result is not None: + self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT lte-uesoftmodem', '\$', 4) + outterLoopCounter = outterLoopCounter - 1 + if (outterLoopCounter == 0): + doOutterLoop = False + + if fullSyncStatus and gotSyncStatus: + result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) + if result is None: + self.command('ifconfig oaitun_ue1', '\$', 4) + # ifconfig output is different between ubuntu 16 and ubuntu 18 + result = re.search('inet addr:1|inet 1', str(self.ssh.before)) + if result is not None: + logging.debug('\u001B[1m oaitun_ue1 interface is mounted and configured\u001B[0m') + tunnelInterfaceStatus = True + else: + logging.debug(str(self.ssh.before)) + logging.error('\u001B[1m oaitun_ue1 interface is either NOT mounted or NOT configured\u001B[0m') + tunnelInterfaceStatus = False + else: + tunnelInterfaceStatus = True + + self.close() + if fullSyncStatus and gotSyncStatus and tunnelInterfaceStatus: + self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE') + logging.debug('\u001B[1m Initialize OAI UE Completed\u001B[0m') + if (self.ADBIPAddress != 'none'): + self.UEDevices = [] + self.UEDevices.append('OAI-UE') + self.UEDevicesStatus = [] + self.UEDevicesStatus.append(UE_STATUS_DETACHED) + else: + self.htmlUEFailureMsg = 'oaitun_ue1 interface is either NOT mounted or NOT configured' + self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', OAI_UE_PROCESS_NO_TUNNEL_INTERFACE, 'OAI UE') + logging.error('\033[91mInitialize OAI UE Failed! \033[0m') + self.AutoTerminateUEandeNB() + + def checkDevTTYisUnlocked(self): + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + count = 0 + while count < 5: + self.command('echo ' + self.ADBPassword + ' | sudo -S lsof | grep ttyUSB0', '\$', 10) + result = re.search('picocom', str(self.ssh.before)) + if result is None: + count = 10 + else: + time.sleep(5) + count = count + 1 + self.close() + + def InitializeCatM(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + self.picocom_closure = True + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` + self.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) + self.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) + time.sleep(1) + # Calling twice AT to clear all buffers + self.command('AT', 'OK|ERROR', 5) + self.command('AT', 'OK', 5) + # Disabling the Radio + self.command('AT+CFUN=0', 'OK', 5) + logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') + # Checking if auto-attach is enabled + self.command('AT^AUTOATT?', 'OK', 5) + result = re.search('AUTOATT: (?P[0-9\-]+)', str(self.ssh.before)) + if result is not None: + if result.group('state') is not None: + autoAttachState = int(result.group('state')) + if autoAttachState is not None: + if autoAttachState == 0: + self.command('AT^AUTOATT=1', 'OK', 5) + logging.debug('\u001B[1m Auto-Attach enabled\u001B[0m') + else: + logging.debug('\u001B[1;37;41m Could not check Auto-Attach! \u001B[0m') + # Force closure of picocom but device might still be locked + self.close() + self.picocom_closure = False + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + self.checkDevTTYisUnlocked() + + def TerminateCatM(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + self.picocom_closure = True + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` + self.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) + self.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) + time.sleep(1) + # Calling twice AT to clear all buffers + self.command('AT', 'OK|ERROR', 5) + self.command('AT', 'OK', 5) + # Disabling the Radio + self.command('AT+CFUN=0', 'OK', 5) + logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') + self.close() + self.picocom_closure = False + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + self.checkDevTTYisUnlocked() + + def AttachCatM(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + self.picocom_closure = True + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` + self.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) + self.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) + time.sleep(1) + # Calling twice AT to clear all buffers + self.command('AT', 'OK|ERROR', 5) + self.command('AT', 'OK', 5) + # Enabling the Radio + self.command('AT+CFUN=1', 'SIMSTORE,READY', 5) + logging.debug('\u001B[1m Cellular Functionality enabled\u001B[0m') + time.sleep(4) + # We should check if we register + count = 0 + attach_cnt = 0 + attach_status = False + while count < 5: + self.command('AT+CEREG?', 'OK', 5) + result = re.search('CEREG: 2,(?P[0-9\-]+),', str(self.ssh.before)) + if result is not None: + mDataConnectionState = int(result.group('state')) + if mDataConnectionState is not None: + if mDataConnectionState == 1: + count = 10 + attach_status = True + result = re.search('CEREG: 2,1,"(?P[0-9A-Z]+)","(?P[0-9A-Z]+)"', str(self.ssh.before)) + if result is not None: + networky = result.group('networky') + networkz = result.group('networkz') + logging.debug('\u001B[1m CAT-M module attached to eNB (' + str(networky) + '/' + str(networkz) + ')\u001B[0m') + else: + logging.debug('\u001B[1m CAT-M module attached to eNB\u001B[0m') + else: + logging.debug('+CEREG: 2,' + str(mDataConnectionState)) + attach_cnt = attach_cnt + 1 + else: + logging.debug(str(self.ssh.before)) + attach_cnt = attach_cnt + 1 + count = count + 1 + time.sleep(1) + if attach_status: + self.command('AT+CESQ', 'OK', 5) + result = re.search('CESQ: 99,99,255,255,(?P[0-9]+),(?P[0-9]+)', str(self.ssh.before)) + if result is not None: + nRSRQ = int(result.group('rsrq')) + nRSRP = int(result.group('rsrp')) + if (nRSRQ is not None) and (nRSRP is not None): + logging.debug(' RSRQ = ' + str(-20+(nRSRQ/2)) + ' dB') + logging.debug(' RSRP = ' + str(-140+nRSRP) + ' dBm') + self.close() + self.picocom_closure = False + html_queue = SimpleQueue() + self.checkDevTTYisUnlocked() + if attach_status: + html_cell = '

CAT-M module Attachment Completed in ' + str(attach_cnt+4) + ' seconds'
+			if (nRSRQ is not None) and (nRSRP is not None):
+				html_cell += '\n   RSRQ = ' + str(-20+(nRSRQ/2)) + ' dB'
+				html_cell += '\n   RSRP = ' + str(-140+nRSRP) + ' dBm
' + else: + html_cell += '' + html_queue.put(html_cell) + self.CreateHtmlTestRowQueue('N/A', 'OK', 1, html_queue) + else: + logging.error('\u001B[1m CAT-M module Attachment Failed\u001B[0m') + html_cell = '
CAT-M module Attachment Failed
' + html_queue.put(html_cell) + self.CreateHtmlTestRowQueue('N/A', 'KO', 1, html_queue) + self.AutoTerminateUEandeNB() + + def PingCatM(self): + if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + check_eNB = True + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + self.AutoTerminateUEandeNB() + return + try: + statusQueue = SimpleQueue() + lock = Lock() + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('cd ' + self.EPCSourceCodePath, '\$', 5) + self.command('cd scripts', '\$', 5) + if re.match('OAI', self.EPCType, re.IGNORECASE): + logging.debug('Using the OAI EPC HSS: not implemented yet') + self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + self.CreateHtmlTabFooter(False) + sys.exit(1) + else: + self.command('egrep --color=never "Allocated ipv4 addr" /opt/ltebox/var/log/xGwLog.0', '\$', 5) + result = re.search('Allocated ipv4 addr: (?P[0-9\.]+) from Pool', str(self.ssh.before)) + if result is not None: + moduleIPAddr = result.group('ipaddr') + else: + self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + self.AutoTerminateUEandeNB() + return + ping_time = re.findall("-c (\d+)",str(self.ping_args)) + device_id = 'catm' + ping_status = self.command('stdbuf -o0 ping ' + self.ping_args + ' ' + str(moduleIPAddr) + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) + # TIMEOUT CASE + if ping_status < 0: + message = 'Ping with UE (' + str(moduleIPAddr) + ') crashed due to TIMEOUT!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.close() + self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) + return + result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', str(self.ssh.before)) + if result is None: + message = 'Packet Loss Not Found!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.close() + self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) + return + packetloss = result.group('packetloss') + if float(packetloss) == 100: + message = 'Packet Loss is 100%' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.close() + self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) + return + result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', str(self.ssh.before)) + if result is None: + message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.close() + self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) + return + rtt_min = result.group('rtt_min') + rtt_avg = result.group('rtt_avg') + rtt_max = result.group('rtt_max') + pal_msg = 'Packet Loss : ' + packetloss + '%' + min_msg = 'RTT(Min) : ' + rtt_min + ' ms' + avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms' + max_msg = 'RTT(Max) : ' + rtt_max + ' ms' + lock.acquire() + logging.debug('\u001B[1;37;44m ping result (' + moduleIPAddr + ') \u001B[0m') + logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') + qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg + packetLossOK = True + if packetloss is not None: + if float(packetloss) > float(self.ping_packetloss_threshold): + qMsg += '\nPacket Loss too high' + logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') + packetLossOK = False + elif float(packetloss) > 0: + qMsg += '\nPacket Loss is not 0%' + logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m') + lock.release() + self.close() + html_cell = '
CAT-M module\nIP Address  : ' + moduleIPAddr + '\n' + qMsg + '
' + statusQueue.put(html_cell) + if (packetLossOK): + self.CreateHtmlTestRowQueue(self.ping_args, 'OK', 1, statusQueue) + else: + self.CreateHtmlTestRowQueue(self.ping_args, 'KO', 1, statusQueue) + self.AutoTerminateUEandeNB() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def AttachUE_common(self, device_id, statusQueue, lock, idx): + try: + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + if self.ADBCentralized: + if device_id == '84B7N16418004022': + self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/on"', '\$', 60) + else: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60) + else: + # airplane mode off // radio on + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) + time.sleep(2) + max_count = 45 + count = max_count + while count > 0: + if self.ADBCentralized: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry" | grep -m 1 mDataConnectionState', '\$', 15) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\' | grep -m 1 mDataConnectionState', '\$', 60) + result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', str(self.ssh.before)) + if result is None: + logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m') + lock.acquire() + statusQueue.put(-1) + statusQueue.put(device_id) + statusQueue.put('mDataConnectionState Not Found!') + lock.release() + break + mDataConnectionState = int(result.group('state')) + if mDataConnectionState == 2: + logging.debug('\u001B[1mUE (' + device_id + ') Attach Completed\u001B[0m') + lock.acquire() + statusQueue.put(max_count - count) + statusQueue.put(device_id) + statusQueue.put('Attach Completed') + lock.release() + break + count = count - 1 + if count == 15 or count == 30: + logging.debug('\u001B[1;30;43m Retry UE (' + device_id + ') Flight Mode Off \u001B[0m') + if self.ADBCentralized: + if device_id == '84B7N16418004022': + self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) + else: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + time.sleep(0.5) + if self.ADBCentralized: + if device_id == '84B7N16418004022': + self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/on"', '\$', 60) + else: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) + time.sleep(0.5) + logging.debug('\u001B[1mWait UE (' + device_id + ') a second until mDataConnectionState=2 (' + str(max_count-count) + ' times)\u001B[0m') + time.sleep(1) + if count == 0: + logging.debug('\u001B[1;37;41m UE (' + device_id + ') Attach Failed \u001B[0m') + lock.acquire() + statusQueue.put(-1) + statusQueue.put(device_id) + statusQueue.put('Attach Failed') + lock.release() + self.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def AttachUE(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + check_eNB = True + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow('N/A', 'KO', pStatus) + self.AutoTerminateUEandeNB() + return + multi_jobs = [] + status_queue = SimpleQueue() + lock = Lock() + nb_ue_to_connect = 0 + for device_id in self.UEDevices: + if (self.nbMaxUEtoAttach == -1) or (nb_ue_to_connect < self.nbMaxUEtoAttach): + self.UEDevicesStatus[nb_ue_to_connect] = UE_STATUS_ATTACHING + p = Process(target = self.AttachUE_common, args = (device_id, status_queue, lock,nb_ue_to_connect,)) + p.daemon = True + p.start() + multi_jobs.append(p) + nb_ue_to_connect = nb_ue_to_connect + 1 + for job in multi_jobs: + job.join() + + if (status_queue.empty()): + self.CreateHtmlTestRow('N/A', 'KO', ALL_PROCESSES_OK) + self.AutoTerminateUEandeNB() + return + else: + attach_status = True + html_queue = SimpleQueue() + while (not status_queue.empty()): + count = status_queue.get() + if (count < 0): + attach_status = False + device_id = status_queue.get() + message = status_queue.get() + if (count < 0): + html_cell = '
UE (' + device_id + ')\n' + message + '
' + else: + html_cell = '
UE (' + device_id + ')\n' + message + ' in ' + str(count + 2) + ' seconds
' + html_queue.put(html_cell) + if (attach_status): + cnt = 0 + while cnt < len(self.UEDevices): + if self.UEDevicesStatus[cnt] == UE_STATUS_ATTACHING: + self.UEDevicesStatus[cnt] = UE_STATUS_ATTACHED + cnt += 1 + self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) + result = re.search('T_stdout', str(self.Initialize_eNB_args)) + if result is not None: + logging.debug('Waiting 5 seconds to fill up record file') + time.sleep(5) + else: + self.CreateHtmlTestRowQueue('N/A', 'KO', len(self.UEDevices), html_queue) + self.AutoTerminateUEandeNB() + + def DetachUE_common(self, device_id, idx): + try: + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + if self.ADBCentralized: + if device_id == '84B7N16418004022': + self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) + else: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + logging.debug('\u001B[1mUE (' + device_id + ') Detach Completed\u001B[0m') + self.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def DetachUE(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + check_eNB = True + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow('N/A', 'KO', pStatus) + self.AutoTerminateUEandeNB() + return + multi_jobs = [] + cnt = 0 + for device_id in self.UEDevices: + self.UEDevicesStatus[cnt] = UE_STATUS_DETACHING + p = Process(target = self.DetachUE_common, args = (device_id,cnt,)) + p.daemon = True + p.start() + multi_jobs.append(p) + cnt += 1 + for job in multi_jobs: + job.join() + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + result = re.search('T_stdout', str(self.Initialize_eNB_args)) + if result is not None: + logging.debug('Waiting 5 seconds to fill up record file') + time.sleep(5) + cnt = 0 + while cnt < len(self.UEDevices): + self.UEDevicesStatus[cnt] = UE_STATUS_DETACHED + cnt += 1 + + def RebootUE_common(self, device_id): + try: + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + previousmDataConnectionStates = [] + # Save mDataConnectionState + self.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) + self.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) + result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', str(self.ssh.before)) + if result is None: + logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m') + sys.exit(1) + previousmDataConnectionStates.append(int(result.group('state'))) + # Reboot UE + self.command('stdbuf -o0 adb -s ' + device_id + ' shell reboot', '\$', 10) + time.sleep(60) + previousmDataConnectionState = previousmDataConnectionStates.pop(0) + count = 180 + while count > 0: + count = count - 1 + self.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) + result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', str(self.ssh.before)) + if result is None: + mDataConnectionState = None + else: + mDataConnectionState = int(result.group('state')) + logging.debug('mDataConnectionState = ' + result.group('state')) + if mDataConnectionState is None or (previousmDataConnectionState == 2 and mDataConnectionState != 2): + logging.debug('\u001B[1mWait UE (' + device_id + ') a second until reboot completion (' + str(180-count) + ' times)\u001B[0m') + time.sleep(1) + else: + logging.debug('\u001B[1mUE (' + device_id + ') Reboot Completed\u001B[0m') + break + if count == 0: + logging.debug('\u001B[1;37;41m UE (' + device_id + ') Reboot Failed \u001B[0m') + sys.exit(1) + self.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def RebootUE(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + check_eNB = True + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow('N/A', 'KO', pStatus) + self.CreateHtmlTabFooter(False) + sys.exit(1) + multi_jobs = [] + for device_id in self.UEDevices: + p = Process(target = self.RebootUE_common, args = (device_id,)) + p.daemon = True + p.start() + multi_jobs.append(p) + for job in multi_jobs: + job.join() + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def DataDisableUE_common(self, device_id, idx): + try: + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # disable data service + if self.ADBCentralized: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data disable"', '\$', 60) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data disable"\'', '\$', 60) + logging.debug('\u001B[1mUE (' + device_id + ') Disabled Data Service\u001B[0m') + self.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def DataDisableUE(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + multi_jobs = [] + i = 0 + for device_id in self.UEDevices: + p = Process(target = self.DataDisableUE_common, args = (device_id,i,)) + p.daemon = True + p.start() + multi_jobs.append(p) + i += 1 + for job in multi_jobs: + job.join() + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def DataEnableUE_common(self, device_id, idx): + try: + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # enable data service + if self.ADBCentralized: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data enable"', '\$', 60) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) + logging.debug('\u001B[1mUE (' + device_id + ') Enabled Data Service\u001B[0m') + self.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def DataEnableUE(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + multi_jobs = [] + i = 0 + for device_id in self.UEDevices: + p = Process(target = self.DataEnableUE_common, args = (device_id,i,)) + p.daemon = True + p.start() + multi_jobs.append(p) + i += 1 + for job in multi_jobs: + job.join() + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def GetAllUEDevices(self, terminate_ue_flag): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + if self.ADBCentralized: + self.command('adb devices', '\$', 15) + self.UEDevices = re.findall("\\\\r\\\\n([A-Za-z0-9]+)\\\\tdevice",str(self.ssh.before)) + self.close() + else: + if (os.path.isfile('./phones_list.txt')): + os.remove('./phones_list.txt') + self.command('ls /etc/*/phones*.txt', '\$', 5) + result = re.search('/etc/ci/phones_list.txt', str(self.ssh.before)) + self.close() + if (result is not None) and (len(self.UEDevices) == 0): + self.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, '/etc/ci/phones_list.txt', '.') + if (os.path.isfile('./phones_list.txt')): + phone_list_file = open('./phones_list.txt', 'r') + for line in phone_list_file.readlines(): + line = line.strip() + result = re.search('^#', line) + if result is not None: + continue + comma_split = line.split(",") + self.UEDevices.append(comma_split[0]) + self.UEDevicesRemoteServer.append(comma_split[1]) + self.UEDevicesRemoteUser.append(comma_split[2]) + self.UEDevicesOffCmd.append(comma_split[3]) + self.UEDevicesOnCmd.append(comma_split[4]) + self.UEDevicesRebootCmd.append(comma_split[5]) + phone_list_file.close() + + if terminate_ue_flag == False: + if len(self.UEDevices) == 0: + logging.debug('\u001B[1;37;41m UE Not Found! \u001B[0m') + sys.exit(1) + if len(self.UEDevicesStatus) == 0: + cnt = 0 + while cnt < len(self.UEDevices): + self.UEDevicesStatus.append(UE_STATUS_DETACHED) + cnt += 1 + + def GetAllCatMDevices(self, terminate_ue_flag): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + if self.ADBCentralized: + self.command('lsusb | egrep "Future Technology Devices International, Ltd FT2232C" | sed -e "s#:.*##" -e "s# #_#g"', '\$', 15) + self.CatMDevices = re.findall("\\\\r\\\\n([A-Za-z0-9_]+)",str(self.ssh.before)) + else: + if (os.path.isfile('./modules_list.txt')): + os.remove('./modules_list.txt') + self.command('ls /etc/*/modules*.txt', '\$', 5) + result = re.search('/etc/ci/modules_list.txt', str(self.ssh.before)) + self.close() + if result is not None: + logging.debug('Found a module list file on ADB server') + if terminate_ue_flag == False: + if len(self.CatMDevices) == 0: + logging.debug('\u001B[1;37;41m CAT-M UE Not Found! \u001B[0m') + sys.exit(1) + self.close() + + def CheckUEStatus_common(self, lock, device_id, statusQueue, idx): + try: + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + if self.ADBCentralized: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry"', '\$', 15) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\'', '\$', 60) + result = re.search('mServiceState=(?P[0-9]+)', str(self.ssh.before)) + serviceState = 'Service State: UNKNOWN' + if result is not None: + lServiceState = int(result.group('serviceState')) + if lServiceState == 3: + serviceState = 'Service State: RADIO_POWERED_OFF' + if lServiceState == 1: + serviceState = 'Service State: OUT_OF_SERVICE' + if lServiceState == 0: + serviceState = 'Service State: IN_SERVICE' + if lServiceState == 2: + serviceState = 'Service State: EMERGENCY_ONLY' + result = re.search('mDataConnectionState=(?P[0-9]+)', str(self.ssh.before)) + dataConnectionState = 'Data State: UNKNOWN' + if result is not None: + lDataConnectionState = int(result.group('dataConnectionState')) + if lDataConnectionState == 0: + dataConnectionState = 'Data State: DISCONNECTED' + if lDataConnectionState == 1: + dataConnectionState = 'Data State: CONNECTING' + if lDataConnectionState == 2: + dataConnectionState = 'Data State: CONNECTED' + if lDataConnectionState == 3: + dataConnectionState = 'Data State: SUSPENDED' + result = re.search('mDataConnectionReason=(?P[0-9a-zA-Z_]+)', str(self.ssh.before)) + dataConnectionReason = 'Data Reason: UNKNOWN' + if result is not None: + dataConnectionReason = 'Data Reason: ' + result.group('dataConnectionReason') + lock.acquire() + logging.debug('\u001B[1;37;44m Status Check (' + str(device_id) + ') \u001B[0m') + logging.debug('\u001B[1;34m ' + serviceState + '\u001B[0m') + logging.debug('\u001B[1;34m ' + dataConnectionState + '\u001B[0m') + logging.debug('\u001B[1;34m ' + dataConnectionReason + '\u001B[0m') + statusQueue.put(0) + statusQueue.put(device_id) + qMsg = serviceState + '\n' + dataConnectionState + '\n' + dataConnectionReason + statusQueue.put(qMsg) + lock.release() + self.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def CheckStatusUE(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + check_eNB = True + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow('N/A', 'KO', pStatus) + self.CreateHtmlTabFooter(False) + sys.exit(1) + multi_jobs = [] + lock = Lock() + status_queue = SimpleQueue() + i = 0 + for device_id in self.UEDevices: + p = Process(target = self.CheckUEStatus_common, args = (lock,device_id,status_queue,i,)) + p.daemon = True + p.start() + multi_jobs.append(p) + i += 1 + for job in multi_jobs: + job.join() + if self.flexranCtrlInstalled and self.flexranCtrlStarted: + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('cd /opt/flexran_rtc', '\$', 5) + self.command('curl http://localhost:9999/stats | jq \'.\' > log/check_status_' + self.testCase_id + '.log 2>&1', '\$', 5) + self.command('cat log/check_status_' + self.testCase_id + '.log | jq \'.eNB_config[0].UE\' | grep -c rnti | sed -e "s#^#Nb Connected UE = #"', '\$', 5) + result = re.search('Nb Connected UE = (?P[0-9]+)', str(self.ssh.before)) + passStatus = True + if result is not None: + nb_ues = int(result.group('nb_ues')) + htmlOptions = 'Nb Connected UE(s) to eNB = ' + str(nb_ues) + logging.debug('\u001B[1;37;44m ' + htmlOptions + ' \u001B[0m') + if self.expectedNbOfConnectedUEs > -1: + if nb_ues != self.expectedNbOfConnectedUEs: + passStatus = False + else: + htmlOptions = 'N/A' + self.close() + else: + passStatus = True + htmlOptions = 'N/A' + + if (status_queue.empty()): + self.CreateHtmlTestRow(htmlOptions, 'KO', ALL_PROCESSES_OK) + self.AutoTerminateUEandeNB() + else: + check_status = True + html_queue = SimpleQueue() + while (not status_queue.empty()): + count = status_queue.get() + if (count < 0): + check_status = False + device_id = status_queue.get() + message = status_queue.get() + html_cell = '
UE (' + device_id + ')\n' + message + '
' + html_queue.put(html_cell) + if check_status and passStatus: + self.CreateHtmlTestRowQueue(htmlOptions, 'OK', len(self.UEDevices), html_queue) + else: + self.CreateHtmlTestRowQueue(htmlOptions, 'KO', len(self.UEDevices), html_queue) + self.AutoTerminateUEandeNB() + + def GetAllUEIPAddresses(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + ue_ip_status = 0 + self.UEIPAddresses = [] + if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): + if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + self.command('ifconfig oaitun_ue1', '\$', 4) + result = re.search('inet addr:(?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)|inet (?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)', str(self.ssh.before)) + if result is not None: + if result.group('ueipaddress') is not None: + UE_IPAddress = result.group('ueipaddress') + else: + UE_IPAddress = result.group('ueipaddress2') + logging.debug('\u001B[1mUE (' + self.UEDevices[0] + ') IP Address is ' + UE_IPAddress + '\u001B[0m') + self.UEIPAddresses.append(UE_IPAddress) + else: + logging.debug('\u001B[1;37;41m UE IP Address Not Found! \u001B[0m') + ue_ip_status -= 1 + self.close() + return ue_ip_status + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + idx = 0 + for device_id in self.UEDevices: + if self.UEDevicesStatus[idx] != UE_STATUS_ATTACHED: + idx += 1 + continue + count = 0 + while count < 4: + if self.ADBCentralized: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell "ip addr show | grep rmnet"', '\$', 15) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ip addr show | grep rmnet"\'', '\$', 60) + result = re.search('inet (?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\/[0-9]+[0-9a-zA-Z\.\s]+', str(self.ssh.before)) + if result is None: + logging.debug('\u001B[1;37;41m UE IP Address Not Found! \u001B[0m') + time.sleep(1) + count += 1 + else: + count = 10 + if count < 9: + ue_ip_status -= 1 + continue + UE_IPAddress = result.group('ueipaddress') + logging.debug('\u001B[1mUE (' + device_id + ') IP Address is ' + UE_IPAddress + '\u001B[0m') + for ueipaddress in self.UEIPAddresses: + if ueipaddress == UE_IPAddress: + logging.debug('\u001B[1mUE (' + device_id + ') IP Address ' + UE_IPAddress + ': has already been allocated to another device !' + '\u001B[0m') + ue_ip_status -= 1 + continue + self.UEIPAddresses.append(UE_IPAddress) + idx += 1 + self.close() + return ue_ip_status + + def ping_iperf_wrong_exit(self, lock, UE_IPAddress, device_id, statusQueue, message): + lock.acquire() + statusQueue.put(-1) + statusQueue.put(device_id) + statusQueue.put(UE_IPAddress) + statusQueue.put(message) + lock.release() + + def Ping_common(self, lock, UE_IPAddress, device_id, statusQueue): + try: + # Launch ping on the EPC side (true for ltebox and old open-air-cn) + # But for OAI-Rel14-CUPS, we launch from python executor + launchFromEpc = True + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + launchFromEpc = False + ping_time = re.findall("-c (\d+)",str(self.ping_args)) + + if launchFromEpc: + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('cd ' + self.EPCSourceCodePath, '\$', 5) + self.command('cd scripts', '\$', 5) + ping_status = self.command('stdbuf -o0 ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) + else: + cmd = 'ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 > ping_' + self.testCase_id + '_' + device_id + '.log' + message = cmd + '\n' + logging.debug(cmd) + ret = subprocess.run(cmd, shell=True) + ping_status = ret.returncode + self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'ping_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('cat ' + self.EPCSourceCodePath + '/scripts/ping_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + # TIMEOUT CASE + if ping_status < 0: + message = 'Ping with UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.close() + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) + return + result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', str(self.ssh.before)) + if result is None: + message = 'Packet Loss Not Found!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.close() + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) + return + packetloss = result.group('packetloss') + if float(packetloss) == 100: + message = 'Packet Loss is 100%' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.close() + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) + return + result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', str(self.ssh.before)) + if result is None: + message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.close() + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) + return + rtt_min = result.group('rtt_min') + rtt_avg = result.group('rtt_avg') + rtt_max = result.group('rtt_max') + pal_msg = 'Packet Loss : ' + packetloss + '%' + min_msg = 'RTT(Min) : ' + rtt_min + ' ms' + avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms' + max_msg = 'RTT(Max) : ' + rtt_max + ' ms' + lock.acquire() + logging.debug('\u001B[1;37;44m ping result (' + UE_IPAddress + ') \u001B[0m') + logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') + qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg + packetLossOK = True + if packetloss is not None: + if float(packetloss) > float(self.ping_packetloss_threshold): + qMsg += '\nPacket Loss too high' + logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') + packetLossOK = False + elif float(packetloss) > 0: + qMsg += '\nPacket Loss is not 0%' + logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m') + if (packetLossOK): + statusQueue.put(0) + else: + statusQueue.put(-1) + statusQueue.put(device_id) + statusQueue.put(UE_IPAddress) + statusQueue.put(qMsg) + lock.release() + self.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def PingNoS1_wrong_exit(self, qMsg): + html_queue = SimpleQueue() + html_cell = '
OAI UE ping result\n' + qMsg + '
' + html_queue.put(html_cell) + self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) + + def PingNoS1(self): + check_eNB = True + check_OAI_UE = True + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + self.AutoTerminateUEandeNB() + return + ping_from_eNB = re.search('oaitun_enb1', str(self.ping_args)) + if ping_from_eNB is not None: + if self.eNBIPAddress == '' or self.eNBUserName == '' or self.eNBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + else: + if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': + Usage() + sys.exit('Insufficient Parameter') + try: + if ping_from_eNB is not None: + self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) + self.command('cd ' + self.eNBSourceCodePath + '/cmake_targets/', '\$', 5) + else: + self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + self.command('cd ' + self.UESourceCodePath + '/cmake_targets/', '\$', 5) + self.command('cd cmake_targets', '\$', 5) + ping_time = re.findall("-c (\d+)",str(self.ping_args)) + ping_status = self.command('stdbuf -o0 ping ' + self.ping_args + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '.log', '\$', int(ping_time[0])*1.5) + # TIMEOUT CASE + if ping_status < 0: + message = 'Ping with OAI UE crashed due to TIMEOUT!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.PingNoS1_wrong_exit(message) + return + result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', str(self.ssh.before)) + if result is None: + message = 'Packet Loss Not Found!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.PingNoS1_wrong_exit(message) + return + packetloss = result.group('packetloss') + if float(packetloss) == 100: + message = 'Packet Loss is 100%' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.PingNoS1_wrong_exit(message) + return + result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', str(self.ssh.before)) + if result is None: + message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.PingNoS1_wrong_exit(message) + return + rtt_min = result.group('rtt_min') + rtt_avg = result.group('rtt_avg') + rtt_max = result.group('rtt_max') + pal_msg = 'Packet Loss : ' + packetloss + '%' + min_msg = 'RTT(Min) : ' + rtt_min + ' ms' + avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms' + max_msg = 'RTT(Max) : ' + rtt_max + ' ms' + logging.debug('\u001B[1;37;44m OAI UE ping result \u001B[0m') + logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') + qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg + packetLossOK = True + if packetloss is not None: + if float(packetloss) > float(self.ping_packetloss_threshold): + qMsg += '\nPacket Loss too high' + logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') + packetLossOK = False + elif float(packetloss) > 0: + qMsg += '\nPacket Loss is not 0%' + logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m') + self.close() + html_queue = SimpleQueue() + ip_addr = 'TBD' + html_cell = '
OAI UE ping result\n' + qMsg + '
' + html_queue.put(html_cell) + if packetLossOK: + self.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) + else: + self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) + + # copying on the EPC server for logCollection + if ping_from_eNB is not None: + copyin_res = self.copyin(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.eNBSourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') + else: + copyin_res = self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') + if (copyin_res == 0): + self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'ping_' + self.testCase_id + '.log', self.EPCSourceCodePath + '/scripts') + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def Ping(self): + result = re.search('noS1', str(self.Initialize_eNB_args)) + if result is not None: + self.PingNoS1() + return + if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + check_eNB = True + if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): + check_OAI_UE = True + else: + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + self.AutoTerminateUEandeNB() + return + ueIpStatus = self.GetAllUEIPAddresses() + if (ueIpStatus < 0): + self.CreateHtmlTestRow(self.ping_args, 'KO', UE_IP_ADDRESS_ISSUE) + self.AutoTerminateUEandeNB() + return + multi_jobs = [] + i = 0 + lock = Lock() + status_queue = SimpleQueue() + for UE_IPAddress in self.UEIPAddresses: + device_id = self.UEDevices[i] + p = Process(target = self.Ping_common, args = (lock,UE_IPAddress,device_id,status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + i = i + 1 + for job in multi_jobs: + job.join() + + if (status_queue.empty()): + self.CreateHtmlTestRow(self.ping_args, 'KO', ALL_PROCESSES_OK) + self.AutoTerminateUEandeNB() + else: + ping_status = True + html_queue = SimpleQueue() + while (not status_queue.empty()): + count = status_queue.get() + if (count < 0): + ping_status = False + device_id = status_queue.get() + ip_addr = status_queue.get() + message = status_queue.get() + html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' + html_queue.put(html_cell) + if (ping_status): + self.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) + else: + self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) + self.AutoTerminateUEandeNB() + + def Iperf_ComputeTime(self): + result = re.search('-t (?P\d+)', str(self.iperf_args)) + if result is None: + logging.debug('\u001B[1;37;41m Iperf time Not Found! \u001B[0m') + sys.exit(1) + return result.group('iperf_time') + + def Iperf_ComputeModifiedBW(self, idx, ue_num): + result = re.search('-b (?P[0-9\.]+)[KMG]', str(self.iperf_args)) + if result is None: + logging.debug('\u001B[1;37;41m Iperf bandwidth Not Found! \u001B[0m') + sys.exit(1) + iperf_bandwidth = result.group('iperf_bandwidth') + if self.iperf_profile == 'balanced': + iperf_bandwidth_new = float(iperf_bandwidth)/ue_num + if self.iperf_profile == 'single-ue': + iperf_bandwidth_new = float(iperf_bandwidth) + if self.iperf_profile == 'unbalanced': + # residual is 2% of max bw + residualBW = float(iperf_bandwidth) / 50 + if idx == 0: + iperf_bandwidth_new = float(iperf_bandwidth) - ((ue_num - 1) * residualBW) + else: + iperf_bandwidth_new = residualBW + iperf_bandwidth_str = '-b ' + iperf_bandwidth + iperf_bandwidth_str_new = '-b ' + ('%.2f' % iperf_bandwidth_new) + result = re.sub(iperf_bandwidth_str, iperf_bandwidth_str_new, str(self.iperf_args)) + if result is None: + logging.debug('\u001B[1;37;41m Calculate Iperf bandwidth Failed! \u001B[0m') + sys.exit(1) + return result + + def Iperf_analyzeV2TCPOutput(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): + self.command('awk -f /tmp/tcp_iperf_stats.awk /tmp/CI-eNB/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + result = re.search('Avg Bitrate : (?P[0-9\.]+ Mbits\/sec) Max Bitrate : (?P[0-9\.]+ Mbits\/sec) Min Bitrate : (?P[0-9\.]+ Mbits\/sec)', str(self.ssh.before)) + if result is not None: + avgbitrate = result.group('average') + maxbitrate = result.group('maximum') + minbitrate = result.group('minimum') + lock.acquire() + logging.debug('\u001B[1;37;44m TCP iperf result (' + UE_IPAddress + ') \u001B[0m') + msg = 'TCP Stats :\n' + if avgbitrate is not None: + logging.debug('\u001B[1;34m Avg Bitrate : ' + avgbitrate + '\u001B[0m') + msg += 'Avg Bitrate : ' + avgbitrate + '\n' + if maxbitrate is not None: + logging.debug('\u001B[1;34m Max Bitrate : ' + maxbitrate + '\u001B[0m') + msg += 'Max Bitrate : ' + maxbitrate + '\n' + if minbitrate is not None: + logging.debug('\u001B[1;34m Min Bitrate : ' + minbitrate + '\u001B[0m') + msg += 'Min Bitrate : ' + minbitrate + '\n' + statusQueue.put(0) + statusQueue.put(device_id) + statusQueue.put(UE_IPAddress) + statusQueue.put(msg) + lock.release() + return 0 + + def Iperf_analyzeV2Output(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): + result = re.search('-u', str(iperf_real_options)) + if result is None: + return self.Iperf_analyzeV2TCPOutput(lock, UE_IPAddress, device_id, statusQueue, iperf_real_options) + + result = re.search('Server Report:', str(self.ssh.before)) + if result is None: + result = re.search('read failed: Connection refused', str(self.ssh.before)) + if result is not None: + logging.debug('\u001B[1;37;41m Could not connect to iperf server! \u001B[0m') + else: + logging.debug('\u001B[1;37;41m Server Report and Connection refused Not Found! \u001B[0m') + return -1 + # Computing the requested bandwidth in float + result = re.search('-b (?P[0-9\.]+)[KMG]', str(iperf_real_options)) + if result is not None: + req_bandwidth = result.group('iperf_bandwidth') + req_bw = float(req_bandwidth) + result = re.search('-b [0-9\.]+K', str(iperf_real_options)) + if result is not None: + req_bandwidth = '%.1f Kbits/sec' % req_bw + req_bw = req_bw * 1000 + result = re.search('-b [0-9\.]+M', str(iperf_real_options)) + if result is not None: + req_bandwidth = '%.1f Mbits/sec' % req_bw + req_bw = req_bw * 1000000 + result = re.search('-b [0-9\.]+G', str(iperf_real_options)) + if result is not None: + req_bandwidth = '%.1f Gbits/sec' % req_bw + req_bw = req_bw * 1000000000 + + result = re.search('Server Report:\\\\r\\\\n(?:|\[ *\d+\].*) (?P[0-9\.]+ [KMG]bits\/sec) +(?P[0-9\.]+ ms) +(\d+\/..\d+) +(\((?P[0-9\.]+)%\))', str(self.ssh.before)) + if result is not None: + bitrate = result.group('bitrate') + packetloss = result.group('packetloss') + jitter = result.group('jitter') + lock.acquire() + logging.debug('\u001B[1;37;44m iperf result (' + UE_IPAddress + ') \u001B[0m') + iperfStatus = True + msg = 'Req Bitrate : ' + req_bandwidth + '\n' + logging.debug('\u001B[1;34m Req Bitrate : ' + req_bandwidth + '\u001B[0m') + if bitrate is not None: + msg += 'Bitrate : ' + bitrate + '\n' + logging.debug('\u001B[1;34m Bitrate : ' + bitrate + '\u001B[0m') + result = re.search('(?P[0-9\.]+) [KMG]bits/sec', str(bitrate)) + if result is not None: + actual_bw = float(str(result.group('real_bw'))) + result = re.search('[0-9\.]+ K', bitrate) + if result is not None: + actual_bw = actual_bw * 1000 + result = re.search('[0-9\.]+ M', bitrate) + if result is not None: + actual_bw = actual_bw * 1000000 + result = re.search('[0-9\.]+ G', bitrate) + if result is not None: + actual_bw = actual_bw * 1000000000 + br_loss = 100 * actual_bw / req_bw + bitperf = '%.2f ' % br_loss + msg += 'Bitrate Perf: ' + bitperf + '%\n' + logging.debug('\u001B[1;34m Bitrate Perf: ' + bitperf + '%\u001B[0m') + if packetloss is not None: + msg += 'Packet Loss : ' + packetloss + '%\n' + logging.debug('\u001B[1;34m Packet Loss : ' + packetloss + '%\u001B[0m') + if float(packetloss) > float(self.iperf_packetloss_threshold): + msg += 'Packet Loss too high!\n' + logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') + iperfStatus = False + if jitter is not None: + msg += 'Jitter : ' + jitter + '\n' + logging.debug('\u001B[1;34m Jitter : ' + jitter + '\u001B[0m') + if (iperfStatus): + statusQueue.put(0) + else: + statusQueue.put(-1) + statusQueue.put(device_id) + statusQueue.put(UE_IPAddress) + statusQueue.put(msg) + lock.release() + return 0 + else: + return -2 + + def Iperf_analyzeV2Server(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): + if (not os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not analyze from server log') + return + # Computing the requested bandwidth in float + result = re.search('-b (?P[0-9\.]+)[KMG]', str(iperf_real_options)) + if result is None: + logging.debug('Iperf bandwidth Not Found!') + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not compute Iperf bandwidth!') + return + else: + req_bandwidth = result.group('iperf_bandwidth') + req_bw = float(req_bandwidth) + result = re.search('-b [0-9\.]+K', str(iperf_real_options)) + if result is not None: + req_bandwidth = '%.1f Kbits/sec' % req_bw + req_bw = req_bw * 1000 + result = re.search('-b [0-9\.]+M', str(iperf_real_options)) + if result is not None: + req_bandwidth = '%.1f Mbits/sec' % req_bw + req_bw = req_bw * 1000000 + result = re.search('-b [0-9\.]+G', str(iperf_real_options)) + if result is not None: + req_bandwidth = '%.1f Gbits/sec' % req_bw + req_bw = req_bw * 1000000000 + + server_file = open('iperf_server_' + self.testCase_id + '_' + device_id + '.log', 'r') + br_sum = 0.0 + ji_sum = 0.0 + pl_sum = 0 + ps_sum = 0 + row_idx = 0 + for line in server_file.readlines(): + result = re.search('(?P[0-9\.]+ [KMG]bits\/sec) +(?P[0-9\.]+ ms) +(?P[0-9]+)/ +(?P[0-9]+)', str(line)) + if result is not None: + bitrate = result.group('bitrate') + jitter = result.group('jitter') + packetlost = result.group('lostPack') + packetsent = result.group('sentPack') + br = bitrate.split(' ') + ji = jitter.split(' ') + row_idx = row_idx + 1 + curr_br = float(br[0]) + pl_sum = pl_sum + int(packetlost) + ps_sum = ps_sum + int(packetsent) + if (br[1] == 'Kbits/sec'): + curr_br = curr_br * 1000 + if (br[1] == 'Mbits/sec'): + curr_br = curr_br * 1000 * 1000 + br_sum = curr_br + br_sum + ji_sum = float(ji[0]) + ji_sum + if (row_idx > 0): + br_sum = br_sum / row_idx + ji_sum = ji_sum / row_idx + br_loss = 100 * br_sum / req_bw + if (br_sum > 1000): + br_sum = br_sum / 1000 + if (br_sum > 1000): + br_sum = br_sum / 1000 + bitrate = '%.2f Mbits/sec' % br_sum + else: + bitrate = '%.2f Kbits/sec' % br_sum + else: + bitrate = '%.2f bits/sec' % br_sum + bitperf = '%.2f ' % br_loss + bitperf += '%' + jitter = '%.2f ms' % (ji_sum) + if (ps_sum > 0): + pl = float(100 * pl_sum / ps_sum) + packetloss = '%2.1f ' % (pl) + packetloss += '%' + else: + packetloss = 'unknown' + lock.acquire() + if (br_loss < 90): + statusQueue.put(1) + else: + statusQueue.put(0) + statusQueue.put(device_id) + statusQueue.put(UE_IPAddress) + req_msg = 'Req Bitrate : ' + req_bandwidth + bir_msg = 'Bitrate : ' + bitrate + brl_msg = 'Bitrate Perf: ' + bitperf + jit_msg = 'Jitter : ' + jitter + pal_msg = 'Packet Loss : ' + packetloss + statusQueue.put(req_msg + '\n' + bir_msg + '\n' + brl_msg + '\n' + jit_msg + '\n' + pal_msg + '\n') + logging.debug('\u001B[1;37;45m iperf result (' + UE_IPAddress + ') \u001B[0m') + logging.debug('\u001B[1;35m ' + req_msg + '\u001B[0m') + logging.debug('\u001B[1;35m ' + bir_msg + '\u001B[0m') + logging.debug('\u001B[1;35m ' + brl_msg + '\u001B[0m') + logging.debug('\u001B[1;35m ' + jit_msg + '\u001B[0m') + logging.debug('\u001B[1;35m ' + pal_msg + '\u001B[0m') + lock.release() + else: + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not analyze from server log') + + server_file.close() + + + def Iperf_analyzeV3Output(self, lock, UE_IPAddress, device_id, statusQueue): + result = re.search('(?P[0-9\.]+ [KMG]bits\/sec) +(?:|[0-9\.]+ ms +\d+\/\d+ \((?P[0-9\.]+)%\)) +(?:|receiver)\\\\r\\\\n(?:|\[ *\d+\] Sent \d+ datagrams)\\\\r\\\\niperf Done\.', str(self.ssh.before)) + if result is None: + result = re.search('(?Piperf: error - [a-zA-Z0-9 :]+)', str(self.ssh.before)) + lock.acquire() + statusQueue.put(-1) + statusQueue.put(device_id) + statusQueue.put(UE_IPAddress) + if result is not None: + logging.debug('\u001B[1;37;41m ' + result.group('error') + ' \u001B[0m') + statusQueue.put(result.group('error')) + else: + logging.debug('\u001B[1;37;41m Bitrate and/or Packet Loss Not Found! \u001B[0m') + statusQueue.put('Bitrate and/or Packet Loss Not Found!') + lock.release() + + bitrate = result.group('bitrate') + packetloss = result.group('packetloss') + lock.acquire() + logging.debug('\u001B[1;37;44m iperf result (' + UE_IPAddress + ') \u001B[0m') + logging.debug('\u001B[1;34m Bitrate : ' + bitrate + '\u001B[0m') + msg = 'Bitrate : ' + bitrate + '\n' + iperfStatus = True + if packetloss is not None: + logging.debug('\u001B[1;34m Packet Loss : ' + packetloss + '%\u001B[0m') + msg += 'Packet Loss : ' + packetloss + '%\n' + if float(packetloss) > float(self.iperf_packetloss_threshold): + logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') + msg += 'Packet Loss too high!\n' + iperfStatus = False + if (iperfStatus): + statusQueue.put(0) + else: + statusQueue.put(-1) + statusQueue.put(device_id) + statusQueue.put(UE_IPAddress) + statusQueue.put(msg) + lock.release() + + def Iperf_UL_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue): + udpIperf = True + result = re.search('-u', str(self.iperf_args)) + if result is None: + udpIperf = False + ipnumbers = UE_IPAddress.split('.') + if (len(ipnumbers) == 4): + ipnumbers[3] = '1' + EPC_Iperf_UE_IPAddress = ipnumbers[0] + '.' + ipnumbers[1] + '.' + ipnumbers[2] + '.' + ipnumbers[3] + + # Launch iperf server on EPC side (true for ltebox and old open-air-cn0 + # But for OAI-Rel14-CUPS, we launch from python executor and we are using its IP address as iperf client address + launchFromEpc = True + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + launchFromEpc = False + cmd = 'hostname -I' + ret = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, encoding='utf-8') + if ret.stdout is not None: + EPC_Iperf_UE_IPAddress = ret.stdout.strip() + port = 5001 + idx + if launchFromEpc: + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + if udpIperf: + self.command('echo $USER; nohup iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.EPCUserName, 5) + else: + self.command('echo $USER; nohup iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.EPCUserName, 5) + self.close() + else: + if self.ueIperfVersion == self.dummyIperfVersion: + prefix = '' + else: + prefix = '' + if self.ueIperfVersion == '2.0.5': + prefix = '/opt/iperf-2.0.5/bin/' + if udpIperf: + cmd = 'nohup ' + prefix + 'iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log 2>&1 &' + else: + cmd = 'nohup ' + prefix + 'iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log 2>&1 &' + logging.debug(cmd) + subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, encoding='utf-8') + time.sleep(0.5) + + # Launch iperf client on UE + if (device_id == 'OAI-UE'): + self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + self.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) + else: + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + iperf_time = self.Iperf_ComputeTime() + time.sleep(0.5) + + if udpIperf: + modified_options = self.Iperf_ComputeModifiedBW(idx, ue_num) + else: + modified_options = str(self.iperf_args) + modified_options = modified_options.replace('-R','') + time.sleep(0.5) + + self.command('rm -f iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + if (device_id == 'OAI-UE'): + iperf_status = self.command('iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + ' -B ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + else: + if self.ADBCentralized: + iperf_status = self.command('stdbuf -o0 adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '" 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + else: + iperf_status = self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '"\' 2>&1 > iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + self.command('fromdos -o iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + self.command('cat iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + # TIMEOUT Case + if iperf_status < 0: + self.close() + message = 'iperf on UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT !' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.close() + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) + return + clientStatus = self.Iperf_analyzeV2Output(lock, UE_IPAddress, device_id, statusQueue, modified_options) + self.close() + + # Kill iperf server on EPC side + if launchFromEpc: + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('killall --signal SIGKILL iperf', self.EPCUserName, 5) + self.close() + else: + cmd = 'killall --signal SIGKILL iperf' + logging.debug(cmd) + subprocess.run(cmd, shell=True) + time.sleep(1) + self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') + # in case of failure, retrieve server log + if (clientStatus == -1) or (clientStatus == -2): + if launchFromEpc: + time.sleep(1) + if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): + os.remove('iperf_server_' + self.testCase_id + '_' + device_id + '.log') + self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, self.EPCSourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) + # in case of OAI-UE + if (device_id == 'OAI-UE'): + self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_' + self.testCase_id + '_' + device_id + '.log', '.') + self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') + + def Iperf_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue): + try: + # Single-UE profile -- iperf only on one UE + if self.iperf_profile == 'single-ue' and idx != 0: + return + useIperf3 = False + udpIperf = True + + self.ueIperfVersion = '2.0.5' + if (device_id != 'OAI-UE'): + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # if by chance ADB server and EPC are on the same remote host, at least log collection will take care of it + self.command('if [ ! -d ' + self.EPCSourceCodePath + '/scripts ]; then mkdir -p ' + self.EPCSourceCodePath + '/scripts ; fi', '\$', 5) + self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + # Checking if iperf / iperf3 are installed + if self.ADBCentralized: + self.command('adb -s ' + device_id + ' shell "ls /data/local/tmp"', '\$', 5) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ls /data/local/tmp"\'', '\$', 60) + result = re.search('iperf3', str(self.ssh.before)) + if result is None: + result = re.search('iperf', str(self.ssh.before)) + if result is None: + message = 'Neither iperf nor iperf3 installed on UE!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.close() + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) + return + else: + if self.ADBCentralized: + self.command('adb -s ' + device_id + ' shell "/data/local/tmp/iperf --version"', '\$', 5) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf --version"\'', '\$', 60) + result = re.search('iperf version 2.0.5', str(self.ssh.before)) + if result is not None: + self.ueIperfVersion = '2.0.5' + result = re.search('iperf version 2.0.10', str(self.ssh.before)) + if result is not None: + self.ueIperfVersion = '2.0.10' + else: + useIperf3 = True + self.close() + else: + self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + self.command('iperf --version', '\$', 5) + result = re.search('iperf version 2.0.5', str(self.ssh.before)) + if result is not None: + self.ueIperfVersion = '2.0.5' + result = re.search('iperf version 2.0.10', str(self.ssh.before)) + if result is not None: + self.ueIperfVersion = '2.0.10' + self.close() + # in case of iperf, UL has its own function + if (not useIperf3): + result = re.search('-R', str(self.iperf_args)) + if result is not None: + self.Iperf_UL_common(lock, UE_IPAddress, device_id, idx, ue_num, statusQueue) + return + + # Launch the IPERF server on the UE side for DL + if (device_id == 'OAI-UE'): + self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + self.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) + self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + result = re.search('-u', str(self.iperf_args)) + if result is None: + self.command('echo $USER; nohup iperf -B ' + UE_IPAddress + ' -s -i 1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.UEUserName, 5) + udpIperf = False + else: + self.command('echo $USER; nohup iperf -B ' + UE_IPAddress + ' -u -s -i 1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.UEUserName, 5) + else: + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + if self.ADBCentralized: + if (useIperf3): + self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/iperf3 -s &', '\$', 5) + else: + self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + result = re.search('-u', str(self.iperf_args)) + if result is None: + self.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) + udpIperf = False + else: + self.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) + else: + self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + self.command('echo $USER; nohup ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" \' 2>&1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 60) + + time.sleep(0.5) + self.close() + + # Launch the IPERF client on the EPC side for DL (true for ltebox and old open-air-cn + # But for OAI-Rel14-CUPS, we launch from python executor + launchFromEpc = True + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + launchFromEpc = False + if launchFromEpc: + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + iperf_time = self.Iperf_ComputeTime() + time.sleep(0.5) + + if udpIperf: + modified_options = self.Iperf_ComputeModifiedBW(idx, ue_num) + else: + modified_options = str(self.iperf_args) + time.sleep(0.5) + + if launchFromEpc: + self.command('rm -f iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + else: + if (os.path.isfile('iperf_' + self.testCase_id + '_' + device_id + '.log')): + os.remove('iperf_' + self.testCase_id + '_' + device_id + '.log') + if (useIperf3): + self.command('stdbuf -o0 iperf3 -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + + clientStatus = 0 + self.Iperf_analyzeV3Output(lock, UE_IPAddress, device_id, statusQueue) + else: + if launchFromEpc: + iperf_status = self.command('stdbuf -o0 iperf -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + else: + if self.ueIperfVersion == self.dummyIperfVersion: + prefix = '' + else: + prefix = '' + if self.ueIperfVersion == '2.0.5': + prefix = '/opt/iperf-2.0.5/bin/' + cmd = prefix + 'iperf -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 > iperf_' + self.testCase_id + '_' + device_id + '.log' + message = cmd + '\n' + logging.debug(cmd) + ret = subprocess.run(cmd, shell=True) + iperf_status = ret.returncode + self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('cat ' + self.EPCSourceCodePath + '/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + if iperf_status < 0: + if launchFromEpc: + self.close() + message = 'iperf on UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT !' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) + return + clientStatus = self.Iperf_analyzeV2Output(lock, UE_IPAddress, device_id, statusQueue, modified_options) + self.close() + + # Kill the IPERF server that runs in background + if (device_id == 'OAI-UE'): + self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + self.command('killall iperf', '\$', 5) + else: + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + if self.ADBCentralized: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell ps | grep --color=never iperf | grep -v grep', '\$', 5) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ps" | grep --color=never iperf | grep -v grep\'', '\$', 60) + result = re.search('shell +(?P\d+)', str(self.ssh.before)) + if result is not None: + pid_iperf = result.group('pid') + if self.ADBCentralized: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell kill -KILL ' + pid_iperf, '\$', 5) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"\'', '\$', 60) + self.close() + # if the client report is absent, try to analyze the server log file + if (clientStatus == -1): + time.sleep(1) + if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): + os.remove('iperf_server_' + self.testCase_id + '_' + device_id + '.log') + if (device_id == 'OAI-UE'): + self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + else: + self.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, self.EPCSourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + self.command('fromdos -o iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) + + # in case of OAI UE: + if (device_id == 'OAI-UE'): + if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): + if not launchFromEpc: + self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') + else: + self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def IperfNoS1(self): + if self.eNBIPAddress == '' or self.eNBUserName == '' or self.eNBPassword == '' or self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': + Usage() + sys.exit('Insufficient Parameter') + check_eNB = True + check_OAI_UE = True + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) + self.AutoTerminateUEandeNB() + return + server_on_enb = re.search('-R', str(self.iperf_args)) + if server_on_enb is not None: + iServerIPAddr = self.eNBIPAddress + iServerUser = self.eNBUserName + iServerPasswd = self.eNBPassword + iClientIPAddr = self.UEIPAddress + iClientUser = self.UEUserName + iClientPasswd = self.UEPassword + else: + iServerIPAddr = self.UEIPAddress + iServerUser = self.UEUserName + iServerPasswd = self.UEPassword + iClientIPAddr = self.eNBIPAddress + iClientUser = self.eNBUserName + iClientPasswd = self.eNBPassword + # Starting the iperf server + self.open(iServerIPAddr, iServerUser, iServerPasswd) + # args SHALL be "-c client -u any" + # -c 10.0.1.2 -u -b 1M -t 30 -i 1 -fm -B 10.0.1.1 + # -B 10.0.1.1 -u -s -i 1 -fm + server_options = re.sub('-u.*$', '-u -s -i 1 -fm', str(self.iperf_args)) + server_options = server_options.replace('-c','-B') + self.command('rm -f /tmp/tmp_iperf_server_' + self.testCase_id + '.log', '\$', 5) + self.command('echo $USER; nohup iperf ' + server_options + ' > /tmp/tmp_iperf_server_' + self.testCase_id + '.log 2>&1 &', iServerUser, 5) + time.sleep(0.5) + self.close() + + # Starting the iperf client + modified_options = self.Iperf_ComputeModifiedBW(0, 1) + modified_options = modified_options.replace('-R','') + iperf_time = self.Iperf_ComputeTime() + self.open(iClientIPAddr, iClientUser, iClientPasswd) + self.command('rm -f /tmp/tmp_iperf_' + self.testCase_id + '.log', '\$', 5) + iperf_status = self.command('stdbuf -o0 iperf ' + modified_options + ' 2>&1 | stdbuf -o0 tee /tmp/tmp_iperf_' + self.testCase_id + '.log', '\$', int(iperf_time)*5.0) + status_queue = SimpleQueue() + lock = Lock() + if iperf_status < 0: + message = 'iperf on OAI UE crashed due to TIMEOUT !' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + clientStatus = -2 + else: + clientStatus = self.Iperf_analyzeV2Output(lock, '10.0.1.2', 'OAI-UE', status_queue, modified_options) + self.close() + + # Stopping the iperf server + self.open(iServerIPAddr, iServerUser, iServerPasswd) + self.command('killall --signal SIGKILL iperf', '\$', 5) + time.sleep(0.5) + self.close() + if (clientStatus == -1): + if (os.path.isfile('iperf_server_' + self.testCase_id + '.log')): + os.remove('iperf_server_' + self.testCase_id + '.log') + self.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log') + self.Iperf_analyzeV2Server(lock, '10.0.1.2', 'OAI-UE', status_queue, modified_options) + + # copying on the EPC server for logCollection + copyin_res = self.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log') + if (copyin_res == 0): + self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_OAI-UE.log', self.EPCSourceCodePath + '/scripts') + copyin_res = self.copyin(iClientIPAddr, iClientUser, iClientPasswd, '/tmp/tmp_iperf_' + self.testCase_id + '.log', 'iperf_' + self.testCase_id + '_OAI-UE.log') + if (copyin_res == 0): + self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_' + self.testCase_id + '_OAI-UE.log', self.EPCSourceCodePath + '/scripts') + iperf_noperf = False + if status_queue.empty(): + iperf_status = False + else: + iperf_status = True + html_queue = SimpleQueue() + while (not status_queue.empty()): + count = status_queue.get() + if (count < 0): + iperf_status = False + if (count > 0): + iperf_noperf = True + device_id = status_queue.get() + ip_addr = status_queue.get() + message = status_queue.get() + html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' + html_queue.put(html_cell) + if (iperf_noperf and iperf_status): + self.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) + elif (iperf_status): + self.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) + else: + self.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) + self.AutoTerminateUEandeNB() + + def Iperf(self): + result = re.search('noS1', str(self.Initialize_eNB_args)) + if result is not None: + self.IperfNoS1() + return + if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + check_eNB = True + if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): + check_OAI_UE = True + else: + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) + self.AutoTerminateUEandeNB() + return + ueIpStatus = self.GetAllUEIPAddresses() + if (ueIpStatus < 0): + self.CreateHtmlTestRow(self.iperf_args, 'KO', UE_IP_ADDRESS_ISSUE) + self.AutoTerminateUEandeNB() + return + + self.dummyIperfVersion = '2.0.10' + #cmd = 'iperf --version' + #logging.debug(cmd + '\n') + #iperfStdout = subprocess.check_output(cmd, shell=True, universal_newlines=True) + #result = re.search('iperf version 2.0.5', str(iperfStdout.strip())) + #if result is not None: + # dummyIperfVersion = '2.0.5' + #result = re.search('iperf version 2.0.10', str(iperfStdout.strip())) + #if result is not None: + # dummyIperfVersion = '2.0.10' + + multi_jobs = [] + i = 0 + ue_num = len(self.UEIPAddresses) + lock = Lock() + status_queue = SimpleQueue() + for UE_IPAddress in self.UEIPAddresses: + device_id = self.UEDevices[i] + p = Process(target = SSH.Iperf_common, args = (lock,UE_IPAddress,device_id,i,ue_num,status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + i = i + 1 + for job in multi_jobs: + job.join() + + if (status_queue.empty()): + self.CreateHtmlTestRow(self.iperf_args, 'KO', ALL_PROCESSES_OK) + self.AutoTerminateUEandeNB() + else: + iperf_status = True + iperf_noperf = False + html_queue = SimpleQueue() + while (not status_queue.empty()): + count = status_queue.get() + if (count < 0): + iperf_status = False + if (count > 0): + iperf_noperf = True + device_id = status_queue.get() + ip_addr = status_queue.get() + message = status_queue.get() + html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' + html_queue.put(html_cell) + if (iperf_noperf and iperf_status): + self.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) + elif (iperf_status): + self.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) + else: + self.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) + self.AutoTerminateUEandeNB() + + def CheckProcessExist(self, check_eNB, check_OAI_UE): + multi_jobs = [] + status_queue = SimpleQueue() + # in noS1 config, no need to check status from EPC + result = re.search('noS1', str(self.Initialize_eNB_args)) + if result is None: + p = Process(target = SSH.CheckHSSProcess, args = (status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + p = Process(target = SSH.CheckMMEProcess, args = (status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + p = Process(target = SSH.CheckSPGWProcess, args = (status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + else: + if (check_eNB == False) and (check_OAI_UE == False): + return 0 + if check_eNB: + p = Process(target = SSH.CheckeNBProcess, args = (status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + if check_OAI_UE: + p = Process(target = SSH.CheckOAIUEProcess, args = (status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + for job in multi_jobs: + job.join() + + if (status_queue.empty()): + return -15 + else: + result = 0 + while (not status_queue.empty()): + status = status_queue.get() + if (status < 0): + result = status + if result == ENB_PROCESS_FAILED: + fileCheck = re.search('enb_', str(self.eNBLogFiles[0])) + if fileCheck is not None: + self.copyin(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.eNBSourceCodePath + '/cmake_targets/' + self.eNBLogFiles[0], '.') + logStatus = self.AnalyzeLogFile_eNB(self.eNBLogFiles[0]) + if logStatus < 0: + result = logStatus + self.eNBLogFiles[0] = '' + if self.flexranCtrlInstalled and self.flexranCtrlStarted: + self.TerminateFlexranCtrl() + return result + + def CheckOAIUEProcessExist(self, initialize_OAI_UE_flag): + multi_jobs = [] + status_queue = SimpleQueue() + if initialize_OAI_UE_flag == False: + p = Process(target = SSH.CheckOAIUEProcess, args = (status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + for job in multi_jobs: + job.join() + + if (status_queue.empty()): + return -15 + else: + result = 0 + while (not status_queue.empty()): + status = status_queue.get() + if (status < 0): + result = status + if result == OAI_UE_PROCESS_FAILED: + fileCheck = re.search('ue_', str(self.UELogFile)) + if fileCheck is not None: + self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.') + logStatus = self.AnalyzeLogFile_UE(self.UELogFile) + if logStatus < 0: + result = logStatus + return result + + def CheckOAIUEProcess(self, status_queue): + try: + self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + self.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + result = re.search('lte-uesoftmodem', str(self.ssh.before)) + if result is None: + logging.debug('\u001B[1;37;41m OAI UE Process Not Found! \u001B[0m') + status_queue.put(OAI_UE_PROCESS_FAILED) + else: + status_queue.put(OAI_UE_PROCESS_OK) + self.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def CheckeNBProcess(self, status_queue): + try: + self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) + self.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + result = re.search('lte-softmodem', str(self.ssh.before)) + if result is None: + logging.debug('\u001B[1;37;41m eNB Process Not Found! \u001B[0m') + status_queue.put(ENB_PROCESS_FAILED) + else: + status_queue.put(ENB_PROCESS_OK) + self.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def CheckHSSProcess(self, status_queue): + try: + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('stdbuf -o0 ps -aux | grep --color=never hss | grep -v grep', '\$', 5) + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + result = re.search('oai_hss -j', str(self.ssh.before)) + elif re.match('OAI', self.EPCType, re.IGNORECASE): + result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + result = re.search('hss_sim s6as diam_hss', str(self.ssh.before)) + else: + logging.error('This should not happen!') + if result is None: + logging.debug('\u001B[1;37;41m HSS Process Not Found! \u001B[0m') + status_queue.put(HSS_PROCESS_FAILED) + else: + status_queue.put(HSS_PROCESS_OK) + self.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def CheckMMEProcess(self, status_queue): + try: + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('stdbuf -o0 ps -aux | grep --color=never mme | grep -v grep', '\$', 5) + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + result = re.search('mme -c', str(self.ssh.before)) + elif re.match('OAI', self.EPCType, re.IGNORECASE): + result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + result = re.search('mme', str(self.ssh.before)) + else: + logging.error('This should not happen!') + if result is None: + logging.debug('\u001B[1;37;41m MME Process Not Found! \u001B[0m') + status_queue.put(MME_PROCESS_FAILED) + else: + status_queue.put(MME_PROCESS_OK) + self.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def CheckSPGWProcess(self, status_queue): + try: + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + self.command('stdbuf -o0 ps -aux | grep --color=never spgw | grep -v grep', '\$', 5) + result = re.search('spgwu -c ', str(self.ssh.before)) + elif re.match('OAI', self.EPCType, re.IGNORECASE): + self.command('stdbuf -o0 ps -aux | grep --color=never spgw | grep -v grep', '\$', 5) + result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + self.command('stdbuf -o0 ps -aux | grep --color=never xGw | grep -v grep', '\$', 5) + result = re.search('xGw', str(self.ssh.before)) + else: + logging.error('This should not happen!') + if result is None: + logging.debug('\u001B[1;37;41m SPGW Process Not Found! \u001B[0m') + status_queue.put(SPGW_PROCESS_FAILED) + else: + status_queue.put(SPGW_PROCESS_OK) + self.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def AnalyzeLogFile_eNB(self, eNBlogFile): + if (not os.path.isfile('./' + eNBlogFile)): + return -1 + enb_log_file = open('./' + eNBlogFile, 'r') + exitSignalReceived = False + foundAssertion = False + msgAssertion = '' + msgLine = 0 + foundSegFault = False + foundRealTimeIssue = False + rrcSetupComplete = 0 + rrcReleaseRequest = 0 + rrcReconfigRequest = 0 + rrcReconfigComplete = 0 + rrcReestablishRequest = 0 + rrcReestablishComplete = 0 + rrcReestablishReject = 0 + rlcDiscardBuffer = 0 + rachCanceledProcedure = 0 + uciStatMsgCount = 0 + pdcpFailure = 0 + ulschFailure = 0 + cdrxActivationMessageCount = 0 + dropNotEnoughRBs = 0 + self.htmleNBFailureMsg = '' + isRRU = False + isSlave = False + slaveReceivesFrameResyncCmd = False + X2HO_state = X2_HO_REQ_STATE__IDLE + X2HO_inNbProcedures = 0 + X2HO_outNbProcedures = 0 + for line in enb_log_file.readlines(): + if X2HO_state == X2_HO_REQ_STATE__IDLE: + result = re.search('target eNB Receives X2 HO Req X2AP_HANDOVER_REQ', str(line)) + if result is not None: + X2HO_state = X2_HO_REQ_STATE__TARGET_RECEIVES_REQ + result = re.search('source eNB receives the X2 HO ACK X2AP_HANDOVER_REQ_ACK', str(line)) + if result is not None: + X2HO_state = X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK + if X2HO_state == X2_HO_REQ_STATE__TARGET_RECEIVES_REQ: + result = re.search('Received LTE_RRCConnectionReconfigurationComplete from UE', str(line)) + if result is not None: + X2HO_state = X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE + if X2HO_state == X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE: + result = re.search('issue rrc_eNB_send_PATH_SWITCH_REQ', str(line)) + if result is not None: + X2HO_state = X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ + if X2HO_state == X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ: + result = re.search('received path switch ack S1AP_PATH_SWITCH_REQ_ACK', str(line)) + if result is not None: + X2HO_state = X2_HO_REQ_STATE__IDLE + X2HO_inNbProcedures += 1 + if X2HO_state == X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK: + result = re.search('source eNB receives the X2 UE CONTEXT RELEASE X2AP_UE_CONTEXT_RELEASE', str(line)) + if result is not None: + X2HO_state = X2_HO_REQ_STATE__IDLE + X2HO_outNbProcedures += 1 + + if self.eNBOptions[int(self.eNB_instance)] != '': + res1 = re.search('max_rxgain (?P[0-9]+)', self.eNBOptions[int(self.eNB_instance)]) + res2 = re.search('max_rxgain (?P[0-9]+)', str(line)) + if res1 is not None and res2 is not None: + requested_option = int(res1.group('requested_option')) + applied_option = int(res2.group('applied_option')) + if requested_option == applied_option: + self.htmleNBFailureMsg += ' Command line option(s) correctly applied ' + self.eNBOptions[int(self.eNB_instance)] + '\n\n' + else: + self.htmleNBFailureMsg += ' Command line option(s) NOT applied ' + self.eNBOptions[int(self.eNB_instance)] + '\n\n' + result = re.search('Exiting OAI softmodem', str(line)) + if result is not None: + exitSignalReceived = True + result = re.search('[Ss]egmentation [Ff]ault', str(line)) + 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)) + if result is not None and not exitSignalReceived: + foundAssertion = True + result = re.search('LLL', str(line)) + if result is not None and not exitSignalReceived: + foundRealTimeIssue = True + if foundAssertion and (msgLine < 3): + msgLine += 1 + msgAssertion += str(line) + result = re.search('Setting function for RU', str(line)) + if result is not None: + isRRU = True + if isRRU: + result = re.search('RU 0 is_slave=yes', str(line)) + if result is not None: + isSlave = True + if isSlave: + result = re.search('Received RRU_frame_resynch command', str(line)) + if result is not None: + slaveReceivesFrameResyncCmd = True + result = re.search('LTE_RRCConnectionSetupComplete from UE', str(line)) + if result is not None: + rrcSetupComplete += 1 + result = re.search('Generate LTE_RRCConnectionRelease|Generate RRCConnectionRelease', str(line)) + if result is not None: + rrcReleaseRequest += 1 + result = re.search('Generate LTE_RRCConnectionReconfiguration', str(line)) + if result is not None: + rrcReconfigRequest += 1 + result = re.search('LTE_RRCConnectionReconfigurationComplete from UE rnti', str(line)) + if result is not None: + rrcReconfigComplete += 1 + result = re.search('LTE_RRCConnectionReestablishmentRequest', str(line)) + if result is not None: + rrcReestablishRequest += 1 + result = re.search('LTE_RRCConnectionReestablishmentComplete', str(line)) + if result is not None: + rrcReestablishComplete += 1 + result = re.search('LTE_RRCConnectionReestablishmentReject', str(line)) + if result is not None: + rrcReestablishReject += 1 + result = re.search('CDRX configuration activated after RRC Connection', str(line)) + if result is not None: + cdrxActivationMessageCount += 1 + result = re.search('uci->stat', str(line)) + if result is not None: + uciStatMsgCount += 1 + result = re.search('PDCP.*Out of Resources.*reason', str(line)) + if result is not None: + pdcpFailure += 1 + result = re.search('ULSCH in error in round', str(line)) + if result is not None: + ulschFailure += 1 + result = re.search('BAD all_segments_received', str(line)) + if result is not None: + rlcDiscardBuffer += 1 + 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: + statMsg = 'eNB showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + self.htmleNBFailureMsg += statMsg + '\n' + if pdcpFailure > 0: + statMsg = 'eNB showed ' + str(pdcpFailure) + ' "PDCP Out of Resources" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + self.htmleNBFailureMsg += statMsg + '\n' + if ulschFailure > 0: + 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') + self.htmleNBFailureMsg += rrcMsg + '\n' + if rrcReleaseRequest > 0: + rrcMsg = 'eNB requested ' + str(rrcReleaseRequest) + ' RRC Connection Release(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + if rrcReconfigRequest > 0 or rrcReconfigComplete > 0: + rrcMsg = 'eNB requested ' + str(rrcReconfigRequest) + ' RRC Connection Reconfiguration(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + rrcMsg = ' -- ' + str(rrcReconfigComplete) + ' were completed' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + if rrcReestablishRequest > 0 or rrcReestablishComplete > 0 or rrcReestablishReject > 0: + rrcMsg = 'eNB requested ' + str(rrcReestablishRequest) + ' RRC Connection Reestablishment(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + rrcMsg = ' -- ' + str(rrcReestablishComplete) + ' were completed' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + rrcMsg = ' -- ' + str(rrcReestablishReject) + ' were rejected' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + if X2HO_inNbProcedures > 0: + rrcMsg = 'eNB completed ' + str(X2HO_inNbProcedures) + ' X2 Handover Connection procedure(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + if X2HO_outNbProcedures > 0: + rrcMsg = 'eNB completed ' + str(X2HO_outNbProcedures) + ' X2 Handover Release procedure(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + if self.eNBOptions[int(self.eNB_instance)] != '': + res1 = re.search('drx_Config_present prSetup', self.eNBOptions[int(self.eNB_instance)]) + if res1 is not None: + if cdrxActivationMessageCount > 0: + rrcMsg = 'eNB activated the CDRX Configuration for ' + str(cdrxActivationMessageCount) + ' time(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + else: + rrcMsg = 'eNB did NOT ACTIVATE the CDRX Configuration' + logging.debug('\u001B[1;37;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + if rachCanceledProcedure > 0: + rachMsg = 'eNB cancelled ' + str(rachCanceledProcedure) + ' RA procedure(s)' + logging.debug('\u001B[1;30;43m ' + rachMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rachMsg + '\n' + if isRRU: + if isSlave: + if slaveReceivesFrameResyncCmd: + rruMsg = 'Slave RRU received the RRU_frame_resynch command from RAU' + logging.debug('\u001B[1;30;43m ' + rruMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rruMsg + '\n' + else: + rruMsg = 'Slave RRU DID NOT receive the RRU_frame_resynch command from RAU' + logging.debug('\u001B[1;37;41m ' + rruMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rruMsg + '\n' + self.prematureExit = True + return ENB_PROCESS_SLAVE_RRU_NOT_SYNCED + if foundSegFault: + logging.debug('\u001B[1;37;41m eNB ended with a Segmentation Fault! \u001B[0m') + return ENB_PROCESS_SEG_FAULT + if foundAssertion: + logging.debug('\u001B[1;37;41m eNB ended with an assertion! \u001B[0m') + self.htmleNBFailureMsg += msgAssertion + return ENB_PROCESS_ASSERTION + if foundRealTimeIssue: + logging.debug('\u001B[1;37;41m eNB faced real time issues! \u001B[0m') + self.htmleNBFailureMsg += 'eNB faced real time issues!\n' + #return ENB_PROCESS_REALTIME_ISSUE + if rlcDiscardBuffer > 0: + rlcMsg = 'eNB RLC discarded ' + str(rlcDiscardBuffer) + ' buffer(s)' + logging.debug('\u001B[1;37;41m ' + rlcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rlcMsg + '\n' + return ENB_PROCESS_REALTIME_ISSUE + return 0 + + def AnalyzeLogFile_UE(self, UElogFile): + if (not os.path.isfile('./' + UElogFile)): + return -1 + ue_log_file = open('./' + UElogFile, 'r') + exitSignalReceived = False + foundAssertion = False + msgAssertion = '' + msgLine = 0 + foundSegFault = False + foundRealTimeIssue = False + uciStatMsgCount = 0 + pdcpDataReqFailedCount = 0 + badDciCount = 0 + rrcConnectionRecfgComplete = 0 + no_cell_sync_found = False + mib_found = False + frequency_found = False + plmn_found = False + self.htmlUEFailureMsg = '' + for line in ue_log_file.readlines(): + result = re.search('Exiting OAI softmodem', str(line)) + if result is not None: + exitSignalReceived = True + result = re.search('System error|[Ss]egmentation [Ff]ault|======= Backtrace: =========|======= Memory map: ========', str(line)) + 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)) + if result is not None and not exitSignalReceived: + foundAssertion = True + result = re.search('LLL', str(line)) + if result is not None and not exitSignalReceived: + foundRealTimeIssue = True + if foundAssertion and (msgLine < 3): + msgLine += 1 + msgAssertion += str(line) + result = re.search('uci->stat', str(line)) + if result is not None and not exitSignalReceived: + uciStatMsgCount += 1 + result = re.search('PDCP data request failed', str(line)) + if result is not None and not exitSignalReceived: + pdcpDataReqFailedCount += 1 + result = re.search('bad DCI 1A', str(line)) + if result is not None and not exitSignalReceived: + badDciCount += 1 + result = re.search('Generating RRCConnectionReconfigurationComplete', str(line)) + if result is not None: + rrcConnectionRecfgComplete += 1 + # No cell synchronization found, abandoning + result = re.search('No cell synchronization found, abandoning', str(line)) + if result is not None: + no_cell_sync_found = True + result = re.search("MIB Information => ([a-zA-Z]{1,10}), ([a-zA-Z]{1,10}), NidCell (?P\d{1,3}), N_RB_DL (?P\d{1,3}), PHICH DURATION (?P\d), PHICH RESOURCE (?P.{1,4}), TX_ANT (?P\d)", str(line)) + if result is not None and (not mib_found): + try: + mibMsg = "MIB Information: " + result.group(1) + ', ' + result.group(2) + self.htmlUEFailureMsg += mibMsg + '\n' + logging.debug('\033[94m' + mibMsg + '\033[0m') + mibMsg = " nidcell = " + result.group('nidcell') + self.htmlUEFailureMsg += mibMsg + logging.debug('\033[94m' + mibMsg + '\033[0m') + mibMsg = " n_rb_dl = " + result.group('n_rb_dl') + self.htmlUEFailureMsg += mibMsg + '\n' + logging.debug('\033[94m' + mibMsg + '\033[0m') + mibMsg = " phich_duration = " + result.group('phich_duration') + self.htmlUEFailureMsg += mibMsg + logging.debug('\033[94m' + mibMsg + '\033[0m') + mibMsg = " phich_resource = " + result.group('phich_resource') + self.htmlUEFailureMsg += mibMsg + '\n' + logging.debug('\033[94m' + mibMsg + '\033[0m') + mibMsg = " tx_ant = " + result.group('tx_ant') + self.htmlUEFailureMsg += mibMsg + '\n' + logging.debug('\033[94m' + mibMsg + '\033[0m') + mib_found = True + except Exception as e: + logging.error('\033[91m' + "MIB marker was not found" + '\033[0m') + result = re.search("Measured Carrier Frequency (?P\d{1,15}) Hz", str(line)) + if result is not None and (not frequency_found): + try: + mibMsg = "Measured Carrier Frequency = " + result.group('measured_carrier_frequency') + ' Hz' + self.htmlUEFailureMsg += mibMsg + '\n' + logging.debug('\033[94m' + mibMsg + '\033[0m') + frequency_found = True + except Exception as e: + logging.error('\033[91m' + "Measured Carrier Frequency not found" + '\033[0m') + result = re.search("PLMN MCC (?P\d{1,3}), MNC (?P\d{1,3}), TAC", str(line)) + if result is not None and (not plmn_found): + try: + mibMsg = 'PLMN MCC = ' + result.group('mcc') + ' MNC = ' + result.group('mnc') + self.htmlUEFailureMsg += mibMsg + '\n' + logging.debug('\033[94m' + mibMsg + '\033[0m') + plmn_found = True + except Exception as e: + logging.error('\033[91m' + "PLMN not found" + '\033[0m') + result = re.search("Found (?P[\w,\s]{1,15}) \(name from internal table\)", str(line)) + if result is not None: + try: + mibMsg = "The operator is: " + result.group('operator') + self.htmlUEFailureMsg += mibMsg + '\n' + logging.debug('\033[94m' + mibMsg + '\033[0m') + except Exception as e: + logging.error('\033[91m' + "Operator name not found" + '\033[0m') + result = re.search("SIB5 InterFreqCarrierFreq element (.{1,4})/(.{1,4})", str(line)) + if result is not None: + try: + mibMsg = "SIB5 InterFreqCarrierFreq element " + result.group(1) + '/' + result.group(2) + self.htmlUEFailureMsg += mibMsg + ' -> ' + logging.debug('\033[94m' + mibMsg + '\033[0m') + except Exception as e: + logging.error('\033[91m' + "SIB5 InterFreqCarrierFreq element not found" + '\033[0m') + result = re.search("DL Carrier Frequency/ARFCN : (?P\d{1,15}/\d{1,4})", str(line)) + if result is not None: + try: + freq = result.group('carrier_frequency') + new_freq = re.sub('/[0-9]+','',freq) + float_freq = float(new_freq) / 1000000 + self.htmlUEFailureMsg += 'DL Freq: ' + ('%.1f' % float_freq) + ' MHz' + logging.debug('\033[94m' + " DL Carrier Frequency is: " + freq + '\033[0m') + except Exception as e: + logging.error('\033[91m' + " DL Carrier Frequency not found" + '\033[0m') + result = re.search("AllowedMeasBandwidth : (?P\d{1,7})", str(line)) + if result is not None: + try: + prb = result.group('allowed_bandwidth') + self.htmlUEFailureMsg += ' -- PRB: ' + prb + '\n' + logging.debug('\033[94m' + " AllowedMeasBandwidth: " + prb + '\033[0m') + except Exception as e: + logging.error('\033[91m' + " AllowedMeasBandwidth not found" + '\033[0m') + ue_log_file.close() + if rrcConnectionRecfgComplete > 0: + statMsg = 'UE connected to eNB (' + str(rrcConnectionRecfgComplete) + ' RRCConnectionReconfigurationComplete message(s) generated)' + logging.debug('\033[94m' + statMsg + '\033[0m') + self.htmlUEFailureMsg += statMsg + '\n' + if uciStatMsgCount > 0: + statMsg = 'UE showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + self.htmlUEFailureMsg += statMsg + '\n' + if pdcpDataReqFailedCount > 0: + statMsg = 'UE showed ' + str(pdcpDataReqFailedCount) + ' "PDCP data request failed" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + self.htmlUEFailureMsg += statMsg + '\n' + if badDciCount > 0: + statMsg = 'UE showed ' + str(badDciCount) + ' "bad DCI 1A" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + self.htmlUEFailureMsg += statMsg + '\n' + if foundSegFault: + logging.debug('\u001B[1;37;41m UE ended with a Segmentation Fault! \u001B[0m') + return ENB_PROCESS_SEG_FAULT + if foundAssertion: + logging.debug('\u001B[1;30;43m UE showed an assertion! \u001B[0m') + self.htmlUEFailureMsg += 'UE showed an assertion!\n' + if not mib_found or not frequency_found: + return OAI_UE_PROCESS_ASSERTION + if foundRealTimeIssue: + logging.debug('\u001B[1;37;41m UE faced real time issues! \u001B[0m') + self.htmlUEFailureMsg += 'UE faced real time issues!\n' + #return ENB_PROCESS_REALTIME_ISSUE + if no_cell_sync_found and not mib_found: + logging.debug('\u001B[1;37;41m UE could not synchronize ! \u001B[0m') + self.htmlUEFailureMsg += 'UE could not synchronize!\n' + return OAI_UE_PROCESS_COULD_NOT_SYNC + return 0 + + def TerminateeNB(self): + if self.eNB_serverId == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = self.eNBSourceCodePath + elif self.eNB_serverId == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + lSourcePath = self.eNB1SourceCodePath + elif self.eNB_serverId == '2': + lIpAddr = self.eNB2IPAddress + lUserName = self.eNB2UserName + lPassWord = self.eNB2Password + lSourcePath = self.eNB2SourceCodePath + if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': + Usage() + sys.exit('Insufficient Parameter') + self.open(lIpAddr, lUserName, lPassWord) + self.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) + self.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + result = re.search('lte-softmodem', str(self.ssh.before)) + if result is not None: + self.command('echo ' + lPassWord + ' | sudo -S daemon --name=enb' + str(self.eNB_instance) + '_daemon --stop', '\$', 5) + self.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGINT lte-softmodem || true', '\$', 5) + time.sleep(10) + self.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + result = re.search('lte-softmodem', str(self.ssh.before)) + if result is not None: + self.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGKILL lte-softmodem || true', '\$', 5) + time.sleep(5) + self.command('rm -f my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + self.close() + # If tracer options is on, stopping tshark on EPC side + result = re.search('T_stdout', str(self.Initialize_eNB_args)) + if result is not None: + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + logging.debug('\u001B[1m Stopping tshark \u001B[0m') + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) + time.sleep(1) + if self.EPC_PcapFileName != '': + self.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 /tmp/' + self.EPC_PcapFileName, '\$', 5) + self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + self.EPC_PcapFileName, '.') + self.copyout(lIpAddr, lUserName, lPassWord, self.EPC_PcapFileName, lSourcePath + '/cmake_targets/.') + self.close() + logging.debug('\u001B[1m Replaying RAW record file\u001B[0m') + self.open(lIpAddr, lUserName, lPassWord) + self.command('cd ' + lSourcePath + '/common/utils/T/tracer/', '\$', 5) + enbLogFile = self.eNBLogFiles[int(self.eNB_instance)] + raw_record_file = enbLogFile.replace('.log', '_record.raw') + replay_log_file = enbLogFile.replace('.log', '_replay.log') + extracted_txt_file = enbLogFile.replace('.log', '_extracted_messages.txt') + extracted_log_file = enbLogFile.replace('.log', '_extracted_messages.log') + self.command('./extract_config -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + extracted_txt_file, '\$', 5) + self.command('echo $USER; nohup ./replay -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + replay_log_file + ' 2>&1 &', lUserName, 5) + self.command('./textlog -d ' + lSourcePath + '/cmake_targets/' + extracted_txt_file + ' -no-gui -ON -full > ' + lSourcePath + '/cmake_targets/' + extracted_log_file, '\$', 5) + self.close() + self.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + extracted_log_file, '.') + logging.debug('\u001B[1m Analyzing eNB replay logfile \u001B[0m') + logStatus = self.AnalyzeLogFile_eNB(extracted_log_file) + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + self.eNBLogFiles[int(self.eNB_instance)] = '' + else: + analyzeFile = False + if self.eNBLogFiles[int(self.eNB_instance)] != '': + analyzeFile = True + fileToAnalyze = self.eNBLogFiles[int(self.eNB_instance)] + self.eNBLogFiles[int(self.eNB_instance)] = '' + if analyzeFile: + copyin_res = self.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + fileToAnalyze, '.') + if (copyin_res == -1): + logging.debug('\u001B[1;37;41m Could not copy eNB logfile to analyze it! \u001B[0m') + self.htmleNBFailureMsg = 'Could not copy eNB logfile to analyze it!' + self.CreateHtmlTestRow('N/A', 'KO', ENB_PROCESS_NOLOGFILE_TO_ANALYZE) + return + if self.eNB_serverId != '0': + self.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './' + fileToAnalyze, self.eNBSourceCodePath + '/cmake_targets/') + logging.debug('\u001B[1m Analyzing eNB logfile \u001B[0m ' + fileToAnalyze) + logStatus = self.AnalyzeLogFile_eNB(fileToAnalyze) + if (logStatus < 0): + self.CreateHtmlTestRow('N/A', 'KO', logStatus) + self.preamtureExit = True + return + else: + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + else: + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def TerminateHSS(self): + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT oai_hss || true', '\$', 5) + time.sleep(2) + self.command('stdbuf -o0 ps -aux | grep hss | grep -v grep', '\$', 5) + result = re.search('oai_hss -j', str(self.ssh.before)) + if result is not None: + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL oai_hss || true', '\$', 5) + self.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-hss.sh', '\$', 5) + elif re.match('OAI', self.EPCType, re.IGNORECASE): + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_hss oai_hss || true', '\$', 5) + time.sleep(2) + self.command('stdbuf -o0 ps -aux | grep hss | grep -v grep', '\$', 5) + result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) + if result is not None: + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_hss oai_hss || true', '\$', 5) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + self.command('cd ' + self.EPCSourceCodePath, '\$', 5) + self.command('cd scripts', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S daemon --name=simulated_hss --stop', '\$', 5) + time.sleep(1) + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL hss_sim', '\$', 5) + else: + logging.error('This should not happen!') + self.close() + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def TerminateMME(self): + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_mme mme || true', '\$', 5) + time.sleep(2) + self.command('stdbuf -o0 ps -aux | grep mme | grep -v grep', '\$', 5) + result = re.search('mme -c', str(self.ssh.before)) + if result is not None: + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_mme mme || true', '\$', 5) + self.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-mme.sh', '\$', 5) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + self.command('cd /opt/ltebox/tools', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S ./stop_mme', '\$', 5) + else: + logging.error('This should not happen!') + self.close() + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def TerminateSPGW(self): + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT spgwc spgwu || true', '\$', 5) + time.sleep(2) + self.command('stdbuf -o0 ps -aux | grep spgw | grep -v grep', '\$', 5) + result = re.search('spgwc -c |spgwu -c ', str(self.ssh.before)) + if result is not None: + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL spgwc spgwu || true', '\$', 5) + self.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-spgw*.sh', '\$', 5) + self.command('stdbuf -o0 ps -aux | grep tshark | grep -v grep', '\$', 5) + result = re.search('-w ', str(self.ssh.before)) + if result is not None: + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT tshark || true', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 ' + self.EPCSourceCodePath + '/scripts/*.pcap', '\$', 5) + elif re.match('OAI', self.EPCType, re.IGNORECASE): + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_spgw spgw || true', '\$', 5) + time.sleep(2) + self.command('stdbuf -o0 ps -aux | grep spgw | grep -v grep', '\$', 5) + result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) + if result is not None: + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_spgw spgw || true', '\$', 5) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + self.command('cd /opt/ltebox/tools', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S ./stop_xGw', '\$', 5) + else: + logging.error('This should not happen!') + self.close() + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def TerminateFlexranCtrl(self): + if self.flexranCtrlInstalled == False or self.flexranCtrlStarted == False: + return + if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '': + Usage() + sys.exit('Insufficient Parameter') + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('echo ' + self.EPCPassword + ' | sudo -S daemon --name=flexran_rtc_daemon --stop', '\$', 5) + time.sleep(1) + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL rt_controller', '\$', 5) + time.sleep(1) + self.close() + self.flexranCtrlStarted = False + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def TerminateUE_common(self, device_id, idx): + try: + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # back in airplane mode on (ie radio off) + if self.ADBCentralized: + if device_id == '84B7N16418004022': + self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) + else: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + logging.debug('\u001B[1mUE (' + device_id + ') Detach Completed\u001B[0m') + + if self.ADBCentralized: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell "ps | grep --color=never iperf | grep -v grep"', '\$', 5) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ps | grep --color=never iperf | grep -v grep"\'', '\$', 60) + result = re.search('shell +(?P\d+)', str(self.ssh.before)) + if result is not None: + pid_iperf = result.group('pid') + if self.ADBCentralized: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"', '\$', 5) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"\'', '\$', 60) + self.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def TerminateUE(self): + terminate_ue_flag = True + self.GetAllUEDevices(terminate_ue_flag) + multi_jobs = [] + i = 0 + for device_id in self.UEDevices: + p = Process(target= SSH.TerminateUE_common, args = (device_id,i,)) + p.daemon = True + p.start() + multi_jobs.append(p) + i += 1 + for job in multi_jobs: + job.join() + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def TerminateOAIUE(self): + self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + self.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) + self.command('ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + result = re.search('lte-uesoftmodem', str(self.ssh.before)) + if result is not None: + self.command('echo ' + self.UEPassword + ' | sudo -S daemon --name=ue' + str(self.UE_instance) + '_daemon --stop', '\$', 5) + self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGINT lte-uesoftmodem || true', '\$', 5) + time.sleep(10) + self.command('ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + result = re.search('lte-uesoftmodem', str(self.ssh.before)) + if result is not None: + self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGKILL lte-uesoftmodem || true', '\$', 5) + time.sleep(5) + self.command('rm -f my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) + self.close() + result = re.search('ue_', str(self.UELogFile)) + if result is not None: + copyin_res = self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.') + if (copyin_res == -1): + logging.debug('\u001B[1;37;41m Could not copy UE logfile to analyze it! \u001B[0m') + self.htmlUEFailureMsg = 'Could not copy UE logfile to analyze it!' + self.CreateHtmlTestRow('N/A', 'KO', OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE, 'UE') + self.UELogFile = '' + return + logging.debug('\u001B[1m Analyzing UE logfile \u001B[0m') + logStatus = self.AnalyzeLogFile_UE(self.UELogFile) + result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) + if result is not None: + ueAction = 'Sniffing' + else: + ueAction = 'Connection' + if (logStatus < 0): + logging.debug('\u001B[1m' + ueAction + ' Failed \u001B[0m') + self.htmlUEFailureMsg = '' + ueAction + ' Failed\n' + self.htmlUEFailureMsg + self.CreateHtmlTestRow('N/A', 'KO', logStatus, 'UE') + # In case of sniffing on commercial eNBs we have random results + # Not an error then + if (logStatus != OAI_UE_PROCESS_COULD_NOT_SYNC) or (ueAction != 'Sniffing'): + self.Initialize_OAI_UE_args = '' + self.AutoTerminateUEandeNB() + else: + logging.debug('\u001B[1m' + ueAction + ' Completed \u001B[0m') + self.htmlUEFailureMsg = '' + ueAction + ' Completed\n' + self.htmlUEFailureMsg + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + self.UELogFile = '' + else: + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def AutoTerminateUEandeNB(self): + if (self.ADBIPAddress != 'none'): + self.testCase_id = 'AUTO-KILL-UE' + self.desc = 'Automatic Termination of UE' + self.ShowTestID() + self.TerminateUE() + if (self.Initialize_OAI_UE_args != ''): + self.testCase_id = 'AUTO-KILL-UE' + self.desc = 'Automatic Termination of UE' + self.ShowTestID() + self.TerminateOAIUE() + if (self.Initialize_eNB_args != ''): + self.testCase_id = 'AUTO-KILL-eNB' + self.desc = 'Automatic Termination of eNB' + self.ShowTestID() + self.eNB_instance = '0' + self.TerminateeNB() + if self.flexranCtrlInstalled and self.flexranCtrlStarted: + self.testCase_id = 'AUTO-KILL-flexran-ctl' + self.desc = 'Automatic Termination of FlexRan CTL' + self.ShowTestID() + self.TerminateFlexranCtrl() + self.prematureExit = True + + def IdleSleep(self): + time.sleep(self.idle_sleep_time) + self.CreateHtmlTestRow(str(self.idle_sleep_time) + ' sec', 'OK', ALL_PROCESSES_OK) + + def X2_Status(self, idx, fileName): + cmd = "curl --silent http://" + self.EPCIPAddress + ":9999/stats | jq '.' > " + fileName + message = cmd + '\n' + logging.debug(cmd) + subprocess.run(cmd, shell=True) + if idx == 0: + cmd = "jq '.mac_stats | length' " + fileName + strNbEnbs = subprocess.check_output(cmd, shell=True, universal_newlines=True) + self.x2NbENBs = int(strNbEnbs.strip()) + cnt = 0 + while cnt < self.x2NbENBs: + cmd = "jq '.mac_stats[" + str(cnt) + "].bs_id' " + fileName + bs_id = subprocess.check_output(cmd, shell=True, universal_newlines=True) + self.x2ENBBsIds[idx].append(bs_id.strip()) + cmd = "jq '.mac_stats[" + str(cnt) + "].ue_mac_stats | length' " + fileName + stNbUEs = subprocess.check_output(cmd, shell=True, universal_newlines=True) + nbUEs = int(stNbUEs.strip()) + ueIdx = 0 + self.x2ENBConnectedUEs[idx].append([]) + while ueIdx < nbUEs: + cmd = "jq '.mac_stats[" + str(cnt) + "].ue_mac_stats[" + str(ueIdx) + "].rnti' " + fileName + rnti = subprocess.check_output(cmd, shell=True, universal_newlines=True) + self.x2ENBConnectedUEs[idx][cnt].append(rnti.strip()) + ueIdx += 1 + cnt += 1 + + msg = "FlexRan Controller is connected to " + str(self.x2NbENBs) + " eNB(s)" + logging.debug(msg) + message += msg + '\n' + cnt = 0 + while cnt < self.x2NbENBs: + msg = " -- eNB: " + str(self.x2ENBBsIds[idx][cnt]) + " is connected to " + str(len(self.x2ENBConnectedUEs[idx][cnt])) + " UE(s)" + logging.debug(msg) + message += msg + '\n' + ueIdx = 0 + while ueIdx < len(self.x2ENBConnectedUEs[idx][cnt]): + msg = " -- UE rnti: " + str(self.x2ENBConnectedUEs[idx][cnt][ueIdx]) + logging.debug(msg) + message += msg + '\n' + ueIdx += 1 + cnt += 1 + return message + + def Perform_X2_Handover(self): + html_queue = SimpleQueue() + fullMessage = '
'
+		msg = 'Doing X2 Handover w/ option ' + self.x2_ho_options
+		logging.debug(msg)
+		fullMessage += msg + '\n'
+		if self.x2_ho_options == 'network':
+			if self.flexranCtrlInstalled and self.flexranCtrlStarted:
+				self.x2ENBBsIds = []
+				self.x2ENBConnectedUEs = []
+				self.x2ENBBsIds.append([])
+				self.x2ENBBsIds.append([])
+				self.x2ENBConnectedUEs.append([])
+				self.x2ENBConnectedUEs.append([])
+				fullMessage += self.X2_Status(0, self.testCase_id + '_pre_ho.json') 
+
+				msg = "Activating the X2 Net control on each eNB"
+				logging.debug(msg)
+				fullMessage += msg + '\n'
+				eNB_cnt = self.x2NbENBs
+				cnt = 0
+				while cnt < eNB_cnt:
+					cmd = "curl -XPOST http://" + self.EPCIPAddress + ":9999/rrc/x2_ho_net_control/enb/" + str(self.x2ENBBsIds[0][cnt]) + "/1"
+					logging.debug(cmd)
+					fullMessage += cmd + '\n'
+					subprocess.run(cmd, shell=True)
+					cnt += 1
+				# Waiting for the activation to be active
+				time.sleep(10)
+				msg = "Switching UE(s) from eNB to eNB"
+				logging.debug(msg)
+				fullMessage += msg + '\n'
+				cnt = 0
+				while cnt < eNB_cnt:
+					ueIdx = 0
+					while ueIdx < len(self.x2ENBConnectedUEs[0][cnt]):
+						cmd = "curl -XPOST http://" + self.EPCIPAddress + ":9999/rrc/ho/senb/" + str(self.x2ENBBsIds[0][cnt]) + "/ue/" + str(self.x2ENBConnectedUEs[0][cnt][ueIdx]) + "/tenb/" + str(self.x2ENBBsIds[0][eNB_cnt - cnt - 1])
+						logging.debug(cmd)
+						fullMessage += cmd + '\n'
+						subprocess.run(cmd, shell=True)
+						ueIdx += 1
+					cnt += 1
+				time.sleep(10)
+				# check
+				logging.debug("Checking the Status after X2 Handover")
+				fullMessage += self.X2_Status(1, self.testCase_id + '_post_ho.json') 
+				cnt = 0
+				x2Status = True
+				while cnt < eNB_cnt:
+					if len(self.x2ENBConnectedUEs[0][cnt]) == len(self.x2ENBConnectedUEs[1][cnt]):
+						x2Status = False
+					cnt += 1
+				if x2Status:
+					msg = "X2 Handover was successful"
+					logging.debug(msg)
+					fullMessage += msg + '
' + html_queue.put(fullMessage) + self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) + else: + msg = "X2 Handover FAILED" + logging.error(msg) + fullMessage += msg + '' + html_queue.put(fullMessage) + self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) + else: + self.CreateHtmlTestRow('Cannot perform requested X2 Handover', 'KO', ALL_PROCESSES_OK) + + def LogCollectBuild(self): + if (self.eNBIPAddress != '' and self.eNBUserName != '' and self.eNBPassword != ''): + IPAddress = self.eNBIPAddress + UserName = self.eNBUserName + Password = self.eNBPassword + SourceCodePath = self.eNBSourceCodePath + elif (self.UEIPAddress != '' and self.UEUserName != '' and self.UEPassword != ''): + IPAddress = self.UEIPAddress + UserName = self.UEUserName + Password = self.UEPassword + SourceCodePath = self.UESourceCodePath + else: + sys.exit('Insufficient Parameter') + self.open(IPAddress, UserName, Password) + self.command('cd ' + SourceCodePath, '\$', 5) + self.command('cd cmake_targets', '\$', 5) + self.command('rm -f build.log.zip', '\$', 5) + self.command('zip build.log.zip build_log_*/*', '\$', 60) + self.close() + + def LogCollecteNB(self): + self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) + self.command('cd ' + self.eNBSourceCodePath, '\$', 5) + self.command('cd cmake_targets', '\$', 5) + self.command('echo ' + self.eNBPassword + ' | sudo -S rm -f enb.log.zip', '\$', 5) + self.command('echo ' + self.eNBPassword + ' | sudo -S zip enb.log.zip enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 60) + self.command('echo ' + self.eNBPassword + ' | sudo -S rm enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 5) + self.close() + + def LogCollectPing(self): + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('cd ' + self.EPCSourceCodePath, '\$', 5) + self.command('cd scripts', '\$', 5) + self.command('rm -f ping.log.zip', '\$', 5) + self.command('zip ping.log.zip ping*.log', '\$', 60) + self.command('rm ping*.log', '\$', 5) + self.close() + + def LogCollectIperf(self): + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('cd ' + self.EPCSourceCodePath, '\$', 5) + self.command('cd scripts', '\$', 5) + self.command('rm -f iperf.log.zip', '\$', 5) + self.command('zip iperf.log.zip iperf*.log', '\$', 60) + self.command('rm iperf*.log', '\$', 5) + self.close() + + def LogCollectHSS(self): + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + self.command('rm -f hss.log.zip', '\$', 5) + if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + self.command('zip hss.log.zip hss*.log', '\$', 60) + self.command('echo ' + self.EPCPassword + ' | sudo -S rm hss*.log', '\$', 5) + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + self.command('zip hss.log.zip logs/hss*.* *.pcap', '\$', 60) + self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f logs/hss*.* *.pcap', '\$', 5) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + self.command('cp /opt/hss_sim0609/hss.log .', '\$', 60) + self.command('zip hss.log.zip hss.log', '\$', 60) + else: + logging.error('This option should not occur!') + self.close() + + def LogCollectMME(self): + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + self.command('rm -f mme.log.zip', '\$', 5) + if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + self.command('zip mme.log.zip mme*.log', '\$', 60) + self.command('echo ' + self.EPCPassword + ' | sudo -S rm mme*.log', '\$', 5) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + self.command('cp /opt/ltebox/var/log/*Log.0 .', '\$', 5) + self.command('zip mme.log.zip mmeLog.0 s1apcLog.0 s1apsLog.0 s11cLog.0 libLog.0 s1apCodecLog.0', '\$', 60) + else: + logging.error('This option should not occur!') + self.close() + + def LogCollectSPGW(self): + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + self.command('rm -f spgw.log.zip', '\$', 5) + if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + self.command('zip spgw.log.zip spgw*.log', '\$', 60) + self.command('echo ' + self.EPCPassword + ' | sudo -S rm spgw*.log', '\$', 5) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + self.command('cp /opt/ltebox/var/log/xGwLog.0 .', '\$', 5) + self.command('zip spgw.log.zip xGwLog.0', '\$', 60) + else: + logging.error('This option should not occur!') + self.close() + + def LogCollectOAIUE(self): + self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + self.command('cd ' + self.UESourceCodePath, '\$', 5) + self.command('cd cmake_targets', '\$', 5) + self.command('echo ' + self.UEPassword + ' | sudo -S rm -f ue.log.zip', '\$', 5) + self.command('echo ' + self.UEPassword + ' | sudo -S zip ue.log.zip ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 60) + self.command('echo ' + self.UEPassword + ' | sudo -S rm ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 5) + self.close() + + def RetrieveSystemVersion(self, machine): + if self.eNBIPAddress == 'none' or self.UEIPAddress == 'none': + self.OsVersion = 'Ubuntu 16.04.5 LTS' + self.KernelVersion = '4.15.0-45-generic' + self.UhdVersion = '3.13.0.1-0' + self.UsrpBoard = 'B210' + self.CpuNb = '4' + self.CpuModel = 'Intel(R) Core(TM) i5-6200U' + self.CpuMHz = '2399.996 MHz' + return 0 + if machine == 'eNB': + if self.eNBIPAddress != '' and self.eNBUserName != '' and self.eNBPassword != '': + IPAddress = self.eNBIPAddress + UserName = self.eNBUserName + Password = self.eNBPassword + else: + return -1 + if machine == 'UE': + if self.UEIPAddress != '' and self.UEUserName != '' and self.UEPassword != '': + IPAddress = self.UEIPAddress + UserName = self.UEUserName + Password = self.UEPassword + else: + return -1 + + self.open(IPAddress, UserName, Password) + self.command('lsb_release -a', '\$', 5) + result = re.search('Description:\\\\t(?P[a-zA-Z0-9\-\_\.\ ]+)', str(self.ssh.before)) + if result is not None: + self.OsVersion = result.group('os_type') + logging.debug('OS is: ' + self.OsVersion) + self.command('uname -r', '\$', 5) + result = re.search('uname -r\\\\r\\\\n(?P[a-zA-Z0-9\-\_\.]+)', str(self.ssh.before)) + if result is not None: + self.KernelVersion = result.group('kernel_version') + logging.debug('Kernel Version is: ' + self.KernelVersion) + self.command('dpkg --list | egrep --color=never libuhd003', '\$', 5) + result = re.search('libuhd003:amd64 *(?P[0-9\.]+)', str(self.ssh.before)) + if result is not None: + self.UhdVersion = result.group('uhd_version') + logging.debug('UHD Version is: ' + self.UhdVersion) + self.command('echo ' + Password + ' | sudo -S uhd_find_devices', '\$', 15) + result = re.search('product: (?P[0-9A-Za-z]+)\\\\r\\\\n', str(self.ssh.before)) + if result is not None: + self.UsrpBoard = result.group('usrp_board') + logging.debug('USRP Board is: ' + self.UsrpBoard) + self.command('lscpu', '\$', 5) + result = re.search('CPU\(s\): *(?P[0-9]+).*Model name: *(?P[a-zA-Z0-9\-\_\.\ \(\)]+).*CPU MHz: *(?P[0-9\.]+)', str(self.ssh.before)) + if result is not None: + self.CpuNb = result.group('nb_cpus') + logging.debug('nb_cpus: ' + self.CpuNb) + self.CpuModel = result.group('model') + logging.debug('model: ' + self.CpuModel) + self.CpuMHz = result.group('cpu_mhz') + ' MHz' + logging.debug('cpu_mhz: ' + self.CpuMHz) + self.close() + +#----------------------------------------------------------- +# HTML Reporting.... +#----------------------------------------------------------- + def CreateHtmlHeader(self): + if (not self.htmlHeaderCreated): + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + logging.debug('\u001B[1m Creating HTML header \u001B[0m') + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + self.htmlFile = open('test_results.html', 'w') + self.htmlFile.write('\n') + self.htmlFile.write('\n') + self.htmlFile.write('\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Test Results for TEMPLATE_JOB_NAME job build #TEMPLATE_BUILD_ID\n') + self.htmlFile.write('\n') + self.htmlFile.write('
\n') + self.htmlFile.write('
\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write('
\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Job Summary -- Job: TEMPLATE_JOB_NAME -- Build-ID: TEMPLATE_BUILD_ID\n') + self.htmlFile.write('
\n') + self.htmlFile.write('
\n') + self.htmlFile.write('
TEMPLATE_STAGE_NAME
\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (self.ranAllowMerge): + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (self.ranAllowMerge): + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (self.ranAllowMerge): + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if self.ranAllowMerge != '': + commit_message = subprocess.check_output("git log -n1 --pretty=format:\"%s\" " + self.ranCommitID, shell=True, universal_newlines=True) + commit_message = commit_message.strip() + self.htmlFile.write(' \n') + if (self.ranAllowMerge): + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (self.ranAllowMerge): + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (self.ranTargetBranch == ''): + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write('
Build Start Time (UTC) TEMPLATE_BUILD_TIME
GIT Repository ' + self.ranRepository + '
Job Trigger Merge-RequestPush to Branch
Source Branch Branch' + self.ranBranch + '
Source Commit ID Commit ID ' + self.ranCommitID + '
Source Commit Message Commit Message ' + commit_message + '
Target Branch develop' + self.ranTargetBranch + '
\n') + + if (self.ADBIPAddress != 'none'): + terminate_ue_flag = True + self.GetAllUEDevices(terminate_ue_flag) + self.GetAllCatMDevices(terminate_ue_flag) + self.htmlUEConnected = len(self.UEDevices) + self.htmlFile.write('

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

\n') + self.htmlFile.write('

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

\n') + else: + self.UEDevices.append('OAI-UE') + self.htmlUEConnected = len(self.UEDevices) + self.htmlFile.write('

' + str(len(self.UEDevices)) + ' OAI UE(s) is(are) connected to CI bench

\n') + self.htmlFile.write('
\n') + self.htmlFile.write('
\n') + self.htmlFile.write('
\n') + self.htmlFile.close() + + def CreateHtmlTabHeader(self): + if (not self.htmlHeaderCreated): + if (not os.path.isfile('test_results.html')): + self.CreateHtmlHeader() + self.htmlFile = open('test_results.html', 'a') + if (self.nbTestXMLfiles == 1): + self.htmlFile.write('
\n') + self.htmlFile.write('

Test Summary for ' + self.testXMLfiles[0] + '

\n') + else: + self.htmlFile.write('
\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (self.htmlUEConnected == -1): + terminate_ue_flag = True + if (self.ADBIPAddress != 'none'): + self.GetAllUEDevices(terminate_ue_flag) + self.GetAllCatMDevices(terminate_ue_flag) + else: + self.UEDevices.append('OAI-UE') + self.htmlUEConnected = len(self.UEDevices) + + i = 0 + while (i < self.htmlUEConnected): + self.htmlFile.write(' \n') + i += 1 + self.htmlFile.write(' \n') + self.htmlHeaderCreated = True + + def CreateHtmlTabFooter(self, passStatus): + if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if passStatus: + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write('
Relative Time (ms)Test IdTest DescTest OptionsTest StatusUE' + str(i) + ' Status
Final Tab StatusPASS FAIL
\n') + self.htmlFile.write('
\n') + self.htmlFile.close() + time.sleep(1) + if passStatus: + cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__//' test_results.html" + subprocess.run(cmd, shell=True) + else: + cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__/<\/span>/' test_results.html" + subprocess.run(cmd, shell=True) + self.htmlFooterCreated = False + + def CreateHtmlFooter(self, passStatus): + if (os.path.isfile('test_results.html')): + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + logging.debug('\u001B[1m Creating HTML footer \u001B[0m') + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + + self.htmlFile = open('test_results.html', 'a') + self.htmlFile.write('
\n') + self.htmlFile.write('

\n') + self.htmlFile.write(' \n') + + machines = [ 'eNB', 'UE' ] + for machine in machines: + res = self.RetrieveSystemVersion(machine) + if res == -1: + continue + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if passStatus: + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write('
' + str(machine) + ' Server Characteristics
OS Version' + self.OsVersion + 'Kernel Version' + self.KernelVersion + 'UHD Version' + self.UhdVersion + 'USRP Board' + self.UsrpBoard + '
Nb CPUs' + self.CpuNb + 'CPU Model Name' + self.CpuModel + 'CPU Frequency' + self.CpuMHz + '
Final StatusPASS FAIL
\n') + self.htmlFile.write('

\n') + self.htmlFile.write('
End of Test Report -- Copyright 2018 OpenAirInterface. All Rights Reserved.
\n') + self.htmlFile.write('
\n') + self.htmlFile.write('\n') + self.htmlFile.close() + + def CreateHtmlTestRow(self, options, status, processesStatus, machine='eNB'): + if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): + currentTime = int(round(time.time() * 1000)) - self.startTime + self.htmlFile.write(' \n') + self.htmlFile.write(' ' + format(currentTime / 1000, '.1f') + '\n') + self.htmlFile.write(' ' + self.testCase_id + '\n') + self.htmlFile.write(' ' + self.desc + '\n') + self.htmlFile.write(' ' + str(options) + '\n') + if (str(status) == 'OK'): + self.htmlFile.write(' ' + str(status) + '\n') + elif (str(status) == 'KO'): + if (processesStatus == 0): + self.htmlFile.write(' ' + str(status) + '\n') + elif (processesStatus == ENB_PROCESS_FAILED): + self.htmlFile.write(' KO - eNB process not found\n') + elif (processesStatus == OAI_UE_PROCESS_FAILED): + self.htmlFile.write(' KO - OAI UE process not found\n') + elif (processesStatus == ENB_PROCESS_SEG_FAULT): + self.htmlFile.write(' KO - ' + machine + ' process ended in Segmentation Fault\n') + elif (processesStatus == ENB_PROCESS_ASSERTION) or (processesStatus == OAI_UE_PROCESS_ASSERTION): + self.htmlFile.write(' KO - ' + machine + ' process ended in Assertion\n') + elif (processesStatus == ENB_PROCESS_REALTIME_ISSUE): + self.htmlFile.write(' KO - ' + machine + ' process faced Real Time issue(s)\n') + elif (processesStatus == ENB_PROCESS_NOLOGFILE_TO_ANALYZE) or (processesStatus == OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE): + self.htmlFile.write(' OK?\n') + elif (processesStatus == ENB_PROCESS_SLAVE_RRU_NOT_SYNCED): + self.htmlFile.write(' KO - ' + machine + ' Slave RRU could not synch\n') + elif (processesStatus == OAI_UE_PROCESS_COULD_NOT_SYNC): + self.htmlFile.write(' KO - UE could not sync\n') + elif (processesStatus == HSS_PROCESS_FAILED): + self.htmlFile.write(' KO - HSS process not found\n') + elif (processesStatus == MME_PROCESS_FAILED): + self.htmlFile.write(' KO - MME process not found\n') + elif (processesStatus == SPGW_PROCESS_FAILED): + self.htmlFile.write(' KO - SPGW process not found\n') + elif (processesStatus == UE_IP_ADDRESS_ISSUE): + self.htmlFile.write(' KO - Could not retrieve UE IP address\n') + else: + self.htmlFile.write(' ' + str(status) + '\n') + else: + self.htmlFile.write(' ' + str(status) + '\n') + if (len(str(self.htmleNBFailureMsg)) > 2): + cellBgColor = 'white' + result = re.search('ended with|faced real time issues', self.htmleNBFailureMsg) + if result is not None: + cellBgColor = 'red' + else: + result = re.search('showed|Reestablishment|Could not copy eNB logfile', self.htmleNBFailureMsg) + if result is not None: + cellBgColor = 'orange' + self.htmlFile.write('
' + self.htmleNBFailureMsg + '
\n') + self.htmleNBFailureMsg = '' + elif (len(str(self.htmlUEFailureMsg)) > 2): + cellBgColor = 'white' + result = re.search('ended with|faced real time issues', self.htmlUEFailureMsg) + if result is not None: + cellBgColor = 'red' + else: + result = re.search('showed|Could not copy UE logfile|oaitun_ue1 interface is either NOT mounted or NOT configured', self.htmlUEFailureMsg) + if result is not None: + cellBgColor = 'orange' + self.htmlFile.write('
' + self.htmlUEFailureMsg + '
\n') + self.htmlUEFailureMsg = '' + else: + i = 0 + while (i < self.htmlUEConnected): + self.htmlFile.write(' -\n') + i += 1 + self.htmlFile.write(' \n') + + def CreateHtmlTestRowQueue(self, options, status, ue_status, ue_queue): + if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): + currentTime = int(round(time.time() * 1000)) - self.startTime + addOrangeBK = False + self.htmlFile.write(' \n') + self.htmlFile.write(' ' + format(currentTime / 1000, '.1f') + '\n') + self.htmlFile.write(' ' + self.testCase_id + '\n') + self.htmlFile.write(' ' + self.desc + '\n') + self.htmlFile.write(' ' + str(options) + '\n') + if (str(status) == 'OK'): + self.htmlFile.write(' ' + str(status) + '\n') + elif (str(status) == 'KO'): + self.htmlFile.write(' ' + str(status) + '\n') + else: + addOrangeBK = True + self.htmlFile.write(' ' + str(status) + '\n') + i = 0 + while (i < self.htmlUEConnected): + if (i < ue_status): + if (not ue_queue.empty()): + if (addOrangeBK): + self.htmlFile.write(' ' + str(ue_queue.get()).replace('white', 'orange') + '\n') + else: + self.htmlFile.write(' ' + str(ue_queue.get()) + '\n') + else: + self.htmlFile.write(' -\n') + else: + self.htmlFile.write(' -\n') + i += 1 + self.htmlFile.write(' \n') + +#----------------------------------------------------------- +# ShowTestID() +#----------------------------------------------------------- + def ShowTestID(self): + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + logging.debug('\u001B[1mTest ID:' + self.testCase_id + '\u001B[0m') + logging.debug('\u001B[1m' + self.desc + '\u001B[0m') + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + +#----------------------------------------------------------- +# Usage() +#----------------------------------------------------------- +def Usage(): + print('----------------------------------------------------------------------------------------------------------------------') + print('main.py Ver:' + Version) + print('----------------------------------------------------------------------------------------------------------------------') + print('Usage: python main.py [options]') + print(' --help Show this help.') + print(' --mode=[Mode]') + print(' TesteNB') + print(' InitiateHtml, FinalizeHtml') + print(' TerminateeNB, TerminateUE, TerminateHSS, TerminateMME, TerminateSPGW') + print(' LogCollectBuild, LogCollecteNB, LogCollectHSS, LogCollectMME, LogCollectSPGW, LogCollectPing, LogCollectIperf') + print('---------------------------------------------------------------------------------------------------- Git Options --') + print(' --ranRepository=[OAI RAN Repository URL]') + print(' --ranBranch=[OAI RAN Repository Branch]') + print(' --ranCommitID=[OAI RAN Repository Commit SHA-1]') + print(' --ranAllowMerge=[Allow Merge Request (with target branch) (true or false)]') + print(' --ranTargetBranch=[Target Branch in case of a Merge Request]') + print('--------------------------------------------------------------------------------------------- eNB Server Options --') + print(' --eNBIPAddress=[eNB\'s IP Address]') + print(' --eNBUserName=[eNB\'s Login User Name]') + print(' --eNBPassword=[eNB\'s Login Password]') + print(' --eNBSourceCodePath=[eNB\'s Source Code Path]') + print('------------------------------------------------------------------------------------------ OAI UE Server Options --') + print(' --UEIPAddress=[UE\'s IP Address]') + print(' --UEUserName=[UE\'s Login User Name]') + print(' --UEPassword=[UE\'s Login Password]') + print(' --UESourceCodePath=[UE\'s Source Code Path]') + print('--------------------------------------------------------------------------------------------- EPC Server Options --') + print(' --EPCIPAddress=[EPC\'s IP Address]') + print(' --EPCUserName=[EPC\'s Login User Name]') + print(' --EPCPassword=[EPC\'s Login Password]') + print(' --EPCSourceCodePath=[EPC\'s Source Code Path]') + print(' --EPCType=[EPC\'s Type: OAI or ltebox or OAI-Rel14-CUPS]') + print('--------------------------------------------------------------------------------------------- ABD Server Options --') + print(' --ADBIPAddress=[ADB\'s IP Address]') + print(' --ADBUserName=[ADB\'s Login User Name]') + print(' --ADBPassword=[ADB\'s Login Password]') + print('----------------------------------------------------------------------------------------------------------------------') + print(' --XMLTestFile=[XML Test File to be run]') + print('----------------------------------------------------------------------------------------------------------------------') + +def CheckClassValidity(action,id): + if action != 'Build_eNB' and action != 'WaitEndBuild_eNB' and action != 'Initialize_eNB' and action != 'Terminate_eNB' and action != 'Initialize_UE' and action != 'Terminate_UE' and action != 'Attach_UE' and action != 'Detach_UE' and action != 'Build_OAI_UE' and action != 'Initialize_OAI_UE' and action != 'Terminate_OAI_UE' and action != 'DataDisable_UE' and action != 'DataEnable_UE' and action != 'CheckStatusUE' and action != 'Ping' and action != 'Iperf' and action != 'Reboot_UE' and action != 'Initialize_FlexranCtrl' and action != 'Terminate_FlexranCtrl' and action != 'Initialize_HSS' and action != 'Terminate_HSS' and action != 'Initialize_MME' and action != 'Terminate_MME' and action != 'Initialize_SPGW' and action != 'Terminate_SPGW' and action != 'Initialize_CatM_module' and action != 'Terminate_CatM_module' and action != 'Attach_CatM_module' and action != 'Detach_CatM_module' and action != 'Ping_CatM_module' and action != 'IdleSleep' and action != 'Perform_X2_Handover': + logging.debug('ERROR: test-case ' + id + ' has wrong class ' + action) + return False + return True + +def GetParametersFromXML(action): + if action == 'Build_eNB': + SSH.Build_eNB_args = test.findtext('Build_eNB_args') + SSH.eNB_instance = test.findtext('eNB_instance') + if (SSH.eNB_instance is None): + SSH.eNB_instance = '0' + SSH.eNB_serverId = test.findtext('eNB_serverId') + if (SSH.eNB_serverId is None): + SSH.eNB_serverId = '0' + xmlBgBuildField = test.findtext('backgroundBuild') + if (xmlBgBuildField is None): + SSH.backgroundBuild = False + else: + if re.match('true', xmlBgBuildField, re.IGNORECASE): + SSH.backgroundBuild = True + else: + SSH.backgroundBuild = False + + if action == 'WaitEndBuild_eNB': + SSH.Build_eNB_args = test.findtext('Build_eNB_args') + SSH.eNB_instance = test.findtext('eNB_instance') + if (SSH.eNB_instance is None): + SSH.eNB_instance = '0' + SSH.eNB_serverId = test.findtext('eNB_serverId') + if (SSH.eNB_serverId is None): + SSH.eNB_serverId = '0' + + if action == 'Initialize_eNB': + SSH.Initialize_eNB_args = test.findtext('Initialize_eNB_args') + SSH.eNB_instance = test.findtext('eNB_instance') + if (SSH.eNB_instance is None): + SSH.eNB_instance = '0' + SSH.eNB_serverId = test.findtext('eNB_serverId') + if (SSH.eNB_serverId is None): + SSH.eNB_serverId = '0' + + if action == 'Terminate_eNB': + SSH.eNB_instance = test.findtext('eNB_instance') + if (SSH.eNB_instance is None): + SSH.eNB_instance = '0' + SSH.eNB_serverId = test.findtext('eNB_serverId') + if (SSH.eNB_serverId is None): + SSH.eNB_serverId = '0' + + if action == 'Attach_UE': + nbMaxUEtoAttach = test.findtext('nbMaxUEtoAttach') + if (nbMaxUEtoAttach is None): + SSH.nbMaxUEtoAttach = -1 + else: + SSH.nbMaxUEtoAttach = int(nbMaxUEtoAttach) + + if action == 'CheckStatusUE': + expectedNBUE = test.findtext('expectedNbOfConnectedUEs') + if (expectedNBUE is None): + SSH.expectedNbOfConnectedUEs = -1 + else: + SSH.expectedNbOfConnectedUEs = int(expectedNBUE) + + if action == 'Build_OAI_UE': + SSH.Build_OAI_UE_args = test.findtext('Build_OAI_UE_args') + + if action == 'Initialize_OAI_UE': + SSH.Initialize_OAI_UE_args = test.findtext('Initialize_OAI_UE_args') + SSH.UE_instance = test.findtext('UE_instance') + if (SSH.UE_instance is None): + SSH.UE_instance = '0' + + if action == 'Terminate_OAI_UE': + SSH.eNB_instance = test.findtext('UE_instance') + if (SSH.UE_instance is None): + SSH.UE_instance = '0' + + if action == 'Ping' or action == 'Ping_CatM_module': + SSH.ping_args = test.findtext('ping_args') + SSH.ping_packetloss_threshold = test.findtext('ping_packetloss_threshold') + + if action == 'Iperf': + SSH.iperf_args = test.findtext('iperf_args') + SSH.iperf_packetloss_threshold = test.findtext('iperf_packetloss_threshold') + SSH.iperf_profile = test.findtext('iperf_profile') + if (SSH.iperf_profile is None): + SSH.iperf_profile = 'balanced' + else: + if SSH.iperf_profile != 'balanced' and SSH.iperf_profile != 'unbalanced' and SSH.iperf_profile != 'single-ue': + logging.debug('ERROR: test-case has wrong profile ' + SSH.iperf_profile) + SSH.iperf_profile = 'balanced' + + if action == 'IdleSleep': + string_field = test.findtext('idle_sleep_time_in_sec') + if (string_field is None): + SSH.idle_sleep_time = 5 + else: + SSH.idle_sleep_time = int(string_field) + + if action == 'Perform_X2_Handover': + string_field = test.findtext('x2_ho_options') + if (string_field is None): + SSH.x2_ho_options = 'network' + else: + if string_field != 'network': + logging.error('ERROR: test-case has wrong option ' + string_field) + SSH.x2_ho_options = 'network' + else: + SSH.x2_ho_options = string_field + + +#check if given test is in list +#it is in list if one of the strings in 'list' is at the beginning of 'test' +def test_in_list(test, list): + for check in list: + check=check.replace('+','') + if (test.startswith(check)): + return True + return False + +def receive_signal(signum, frame): + sys.exit(1) + +#----------------------------------------------------------- +# Parameter Check +#----------------------------------------------------------- +mode = '' +SSH = SSHConnection() + +argvs = sys.argv +argc = len(argvs) +cwd = os.getcwd() + +while len(argvs) > 1: + myArgv = argvs.pop(1) # 0th is this file's name + if re.match('^\-\-help$', myArgv, re.IGNORECASE): + Usage() + sys.exit(0) + elif re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE) + mode = matchReg.group(1) + elif re.match('^\-\-eNBRepository=(.+)$|^\-\-ranRepository(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE) + else: + matchReg = re.match('^\-\-ranRepository=(.+)$', myArgv, re.IGNORECASE) + SSH.ranRepository = matchReg.group(1) + elif re.match('^\-\-eNB_AllowMerge=(.+)$|^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE) + else: + matchReg = re.match('^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE) + doMerge = matchReg.group(1) + if ((doMerge == 'true') or (doMerge == 'True')): + SSH.ranAllowMerge = True + elif re.match('^\-\-eNBBranch=(.+)$|^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE) + else: + matchReg = re.match('^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE) + SSH.ranBranch = matchReg.group(1) + elif re.match('^\-\-eNBCommitID=(.*)$|^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE) + else: + matchReg = re.match('^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE) + SSH.ranCommitID = matchReg.group(1) + elif re.match('^\-\-eNBTargetBranch=(.*)$|^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE) + else: + matchReg = re.match('^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE) + SSH.ranTargetBranch = matchReg.group(1) + elif re.match('^\-\-eNBIPAddress=(.+)$|^\-\-eNB[1-2]IPAddress=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE) + SSH.eNBIPAddress = matchReg.group(1) + elif re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE) + SSH.eNB1IPAddress = matchReg.group(1) + elif re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE) + SSH.eNB2IPAddress = matchReg.group(1) + elif re.match('^\-\-eNBUserName=(.+)$|^\-\-eNB[1-2]UserName=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE) + SSH.eNBUserName = matchReg.group(1) + elif re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE) + SSH.eNB1UserName = matchReg.group(1) + elif re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE) + SSH.eNB2UserName = matchReg.group(1) + elif re.match('^\-\-eNBPassword=(.+)$|^\-\-eNB[1-2]Password=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE) + SSH.eNBPassword = matchReg.group(1) + elif re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE) + SSH.eNB1Password = matchReg.group(1) + elif re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE) + SSH.eNB2Password = matchReg.group(1) + elif re.match('^\-\-eNBSourceCodePath=(.+)$|^\-\-eNB[1-2]SourceCodePath=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE) + SSH.eNBSourceCodePath = matchReg.group(1) + elif re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE) + SSH.eNB1SourceCodePath = matchReg.group(1) + elif re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE) + SSH.eNB2SourceCodePath = matchReg.group(1) + elif re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE) + SSH.EPCIPAddress = matchReg.group(1) + elif re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE) + SSH.EPCBranch = matchReg.group(1) + elif re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE) + SSH.EPCUserName = matchReg.group(1) + elif re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE) + SSH.EPCPassword = matchReg.group(1) + elif re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE) + SSH.EPCSourceCodePath = matchReg.group(1) + elif re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE) + if re.match('OAI', matchReg.group(1), re.IGNORECASE) or re.match('ltebox', matchReg.group(1), re.IGNORECASE) or re.match('OAI-Rel14-CUPS', matchReg.group(1), re.IGNORECASE): + SSH.EPCType = matchReg.group(1) + else: + sys.exit('Invalid EPC Type: ' + matchReg.group(1) + ' -- (should be OAI or ltebox or OAI-Rel14-CUPS)') + elif re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE) + SSH.ADBIPAddress = matchReg.group(1) + elif re.match('^\-\-ADBUserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-ADBUserName=(.+)$', myArgv, re.IGNORECASE) + SSH.ADBUserName = matchReg.group(1) + elif re.match('^\-\-ADBType=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-ADBType=(.+)$', myArgv, re.IGNORECASE) + if re.match('centralized', matchReg.group(1), re.IGNORECASE) or re.match('distributed', matchReg.group(1), re.IGNORECASE): + if re.match('distributed', matchReg.group(1), re.IGNORECASE): + SSH.ADBCentralized = False + else: + SSH.ADBCentralized = True + else: + sys.exit('Invalid ADB Type: ' + matchReg.group(1) + ' -- (should be centralized or distributed)') + elif re.match('^\-\-ADBPassword=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-ADBPassword=(.+)$', myArgv, re.IGNORECASE) + SSH.ADBPassword = matchReg.group(1) + elif re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE) + SSH.testXMLfiles.append(matchReg.group(1)) + SSH.nbTestXMLfiles += 1 + elif re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE) + SSH.UEIPAddress = matchReg.group(1) + elif re.match('^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE) + SSH.UEUserName = matchReg.group(1) + elif re.match('^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE) + SSH.UEPassword = matchReg.group(1) + elif re.match('^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE) + SSH.UESourceCodePath = matchReg.group(1) +# reading repeatCounts from command line + elif re.match('^\-\-repeatCounts=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-repeatCounts=(.+)$', myArgv, re.IGNORECASE) + SSH.repeatCounts = int(matchReg.group(1)) + elif re.match('^\-\-finalStatus=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-finalStatus=(.+)$', myArgv, re.IGNORECASE) + finalStatus = matchReg.group(1) + if ((finalStatus == 'true') or (finalStatus == 'True')): + SSH.finalStatus = True + else: + Usage() + sys.exit('Invalid Parameter: ' + myArgv) + +if re.match('^TerminateeNB$', mode, re.IGNORECASE): + if SSH.eNBIPAddress == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + SSH.eNB_serverId = '0' + SSH.eNB_instance = '0' + SSH.eNBSourceCodePath = '/tmp/' + SSH.TerminateeNB() +elif re.match('^TerminateUE$', mode, re.IGNORECASE): + if (SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == ''): + Usage() + sys.exit('Insufficient Parameter') + signal.signal(signal.SIGUSR1, receive_signal) + SSH.TerminateUE() +elif re.match('^TerminateOAIUE$', mode, re.IGNORECASE): + if SSH.UEIPAddress == '' or SSH.UEUserName == '' or SSH.UEPassword == '': + Usage() + sys.exit('Insufficient Parameter') + signal.signal(signal.SIGUSR1, receive_signal) + SSH.TerminateOAIUE() +elif re.match('^TerminateHSS$', mode, re.IGNORECASE): + if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + SSH.TerminateHSS() +elif re.match('^TerminateMME$', mode, re.IGNORECASE): + if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + SSH.TerminateMME() +elif re.match('^TerminateSPGW$', mode, re.IGNORECASE): + if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + SSH.TerminateSPGW() +elif re.match('^LogCollectBuild$', mode, re.IGNORECASE): + if (SSH.eNBIPAddress == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '' or SSH.eNBSourceCodePath == '') and (SSH.UEIPAddress == '' or SSH.UEUserName == '' or SSH.UEPassword == '' or SSH.UESourceCodePath == ''): + Usage() + sys.exit('Insufficient Parameter') + SSH.LogCollectBuild() +elif re.match('^LogCollecteNB$', mode, re.IGNORECASE): + if SSH.eNBIPAddress == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '' or SSH.eNBSourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + SSH.LogCollecteNB() +elif re.match('^LogCollectHSS$', mode, re.IGNORECASE): + if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + SSH.LogCollectHSS() +elif re.match('^LogCollectMME$', mode, re.IGNORECASE): + if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + SSH.LogCollectMME() +elif re.match('^LogCollectSPGW$', mode, re.IGNORECASE): + if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + SSH.LogCollectSPGW() +elif re.match('^LogCollectPing$', mode, re.IGNORECASE): + if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCSourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + SSH.LogCollectPing() +elif re.match('^LogCollectIperf$', mode, re.IGNORECASE): + if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCSourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + SSH.LogCollectIperf() +elif re.match('^LogCollectOAIUE$', mode, re.IGNORECASE): + if SSH.UEIPAddress == '' or SSH.UEUserName == '' or SSH.UEPassword == '' or SSH.UESourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + SSH.LogCollectOAIUE() +elif re.match('^InitiateHtml$', mode, re.IGNORECASE): + if (SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == ''): + Usage() + sys.exit('Insufficient Parameter') + count = 0 + foundCount = 0 + while (count < SSH.nbTestXMLfiles): + xml_test_file = cwd + "/" + SSH.testXMLfiles[count] + xml_test_file = sys.path[0] + "/" + SSH.testXMLfiles[count] + if (os.path.isfile(xml_test_file)): + xmlTree = ET.parse(xml_test_file) + xmlRoot = xmlTree.getroot() + SSH.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count))) + SSH.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-' + str(count))) + SSH.htmlTabIcons.append(xmlRoot.findtext('htmlTabIcon',default='info-sign')) + foundCount += 1 + count += 1 + if foundCount != SSH.nbTestXMLfiles: + SSH.nbTestXMLfiles = foundCount + SSH.CreateHtmlHeader() +elif re.match('^FinalizeHtml$', mode, re.IGNORECASE): + SSH.CreateHtmlFooter(SSH.finalStatus) +elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re.IGNORECASE): + if re.match('^TesteNB$', mode, re.IGNORECASE): + if SSH.eNBIPAddress == '' or SSH.ranRepository == '' or SSH.ranBranch == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '' or SSH.eNBSourceCodePath == '' or SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '' or SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + + if (SSH.EPCIPAddress != '') and (SSH.EPCIPAddress != 'none'): + SSH.copyout(SSH.EPCIPAddress, SSH.EPCUserName, SSH.EPCPassword, cwd + "/tcp_iperf_stats.awk", "/tmp") + SSH.copyout(SSH.EPCIPAddress, SSH.EPCUserName, SSH.EPCPassword, cwd + "/active_net_interfaces.awk", "/tmp") + else: + if SSH.UEIPAddress == '' or SSH.ranRepository == '' or SSH.ranBranch == '' or SSH.UEUserName == '' or SSH.UEPassword == '' or SSH.UESourceCodePath == '': + Usage() + sys.exit('UE: Insufficient Parameter') + + #read test_case_list.xml file + # if no parameters for XML file, use default value + if (SSH.nbTestXMLfiles != 1): + xml_test_file = cwd + "/test_case_list.xml" + else: + xml_test_file = cwd + "/" + SSH.testXMLfiles[0] + + xmlTree = ET.parse(xml_test_file) + xmlRoot = xmlTree.getroot() + + exclusion_tests=xmlRoot.findtext('TestCaseExclusionList',default='') + requested_tests=xmlRoot.findtext('TestCaseRequestedList',default='') + if (SSH.nbTestXMLfiles == 1): + SSH.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-0')) + SSH.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-0')) +# repeatCounts not read from the xml file +# repeatCount = xmlRoot.findtext('repeatCount',default='1') +# SSH.repeatCounts.append(int(repeatCount)) + all_tests=xmlRoot.findall('testCase') + + exclusion_tests=exclusion_tests.split() + requested_tests=requested_tests.split() + + #check that exclusion tests are well formatted + #(6 digits or less than 6 digits followed by +) + for test in exclusion_tests: + if (not re.match('^[0-9]{6}$', test) and + not re.match('^[0-9]{1,5}\+$', test)): + logging.debug('ERROR: exclusion test is invalidly formatted: ' + test) + sys.exit(1) + else: + logging.debug(test) + + #check that requested tests are well formatted + #(6 digits or less than 6 digits followed by +) + #be verbose + for test in requested_tests: + if (re.match('^[0-9]{6}$', test) or + re.match('^[0-9]{1,5}\+$', test)): + logging.debug('INFO: test group/case requested: ' + test) + else: + logging.debug('ERROR: requested test is invalidly formatted: ' + test) + sys.exit(1) + if (SSH.EPCIPAddress != '') and (SSH.EPCIPAddress != 'none'): + SSH.CheckFlexranCtrlInstallation() + + #get the list of tests to be done + todo_tests=[] + for test in requested_tests: + if (test_in_list(test, exclusion_tests)): + logging.debug('INFO: test will be skipped: ' + test) + else: + #logging.debug('INFO: test will be run: ' + test) + todo_tests.append(test) + + signal.signal(signal.SIGUSR1, receive_signal) + + SSH.CreateHtmlTabHeader() + + cnt = 0 + SSH.prematureExit = True + SSH.startTime = int(round(time.time() * 1000)) +# repeatCounts becomes an integer (was SSH.repeatCounts[0] --> becomes SSH.repeatCounts) + while cnt < SSH.repeatCounts and SSH.prematureExit: + SSH.prematureExit = False + for test_case_id in todo_tests: + if SSH.prematureExit: + break + for test in all_tests: + if SSH.prematureExit: + break + id = test.get('id') + if test_case_id != id: + continue + SSH.testCase_id = id + SSH.desc = test.findtext('desc') + action = test.findtext('class') + if (CheckClassValidity(action, id) == False): + continue + SSH.ShowTestID() + GetParametersFromXML(action) + if action == 'Initialize_UE' or action == 'Attach_UE' or action == 'Detach_UE' or action == 'Ping' or action == 'Iperf' or action == 'Reboot_UE' or action == 'DataDisable_UE' or action == 'DataEnable_UE' or action == 'CheckStatusUE': + if (SSH.ADBIPAddress != 'none'): + terminate_ue_flag = False + SSH.GetAllUEDevices(terminate_ue_flag) + if action == 'Build_eNB': + SSH.BuildeNB() + elif action == 'WaitEndBuild_eNB': + SSH.WaitBuildeNBisFinished() + elif action == 'Initialize_eNB': + SSH.InitializeeNB() + elif action == 'Terminate_eNB': + SSH.TerminateeNB() + elif action == 'Initialize_UE': + SSH.InitializeUE() + elif action == 'Terminate_UE': + SSH.TerminateUE() + elif action == 'Attach_UE': + SSH.AttachUE() + elif action == 'Detach_UE': + SSH.DetachUE() + elif action == 'DataDisable_UE': + SSH.DataDisableUE() + elif action == 'DataEnable_UE': + SSH.DataEnableUE() + elif action == 'CheckStatusUE': + SSH.CheckStatusUE() + elif action == 'Build_OAI_UE': + SSH.BuildOAIUE() + elif action == 'Initialize_OAI_UE': + SSH.InitializeOAIUE() + elif action == 'Terminate_OAI_UE': + SSH.TerminateOAIUE() + elif action == 'Initialize_CatM_module': + SSH.InitializeCatM() + elif action == 'Terminate_CatM_module': + SSH.TerminateCatM() + elif action == 'Attach_CatM_module': + SSH.AttachCatM() + elif action == 'Detach_CatM_module': + SSH.TerminateCatM() + elif action == 'Ping_CatM_module': + SSH.PingCatM() + elif action == 'Ping': + SSH.Ping() + elif action == 'Iperf': + SSH.Iperf() + elif action == 'Reboot_UE': + SSH.RebootUE() + elif action == 'Initialize_HSS': + SSH.InitializeHSS() + elif action == 'Terminate_HSS': + SSH.TerminateHSS() + elif action == 'Initialize_MME': + SSH.InitializeMME() + elif action == 'Terminate_MME': + SSH.TerminateMME() + elif action == 'Initialize_SPGW': + SSH.InitializeSPGW() + elif action == 'Terminate_SPGW': + SSH.TerminateSPGW() + elif action == 'Initialize_FlexranCtrl': + SSH.InitializeFlexranCtrl() + elif action == 'Terminate_FlexranCtrl': + SSH.TerminateFlexranCtrl() + elif action == 'IdleSleep': + SSH.IdleSleep() + elif action == 'Perform_X2_Handover': + SSH.Perform_X2_Handover() + else: + sys.exit('Invalid action') + cnt += 1 +# repeatCounts becomes an integer (was SSH.repeatCounts[0] --> becomes SSH.repeatCounts) + if cnt == SSH.repeatCounts and SSH.prematureExit: + logging.debug('Testsuite failed ' + str(cnt) + ' time(s)') + SSH.CreateHtmlTabFooter(False) + sys.exit('Failed Scenario') + else: + logging.info('Testsuite passed after ' + str(cnt) + ' time(s)') + SSH.CreateHtmlTabFooter(True) +else: + Usage() + sys.exit('Invalid mode') +sys.exit(0) From 75642c34c4f3ab9d90a130752a331464533a6b6e Mon Sep 17 00:00:00 2001 From: Gabriele Perrone Date: Mon, 9 Dec 2019 15:36:44 +0100 Subject: [PATCH 069/240] add a new main file for test with cnt changed into self.cnt --- ci-scripts/main-index-to-class.py | 4921 +++++++++++++++++++++++++++++ 1 file changed, 4921 insertions(+) create mode 100644 ci-scripts/main-index-to-class.py diff --git a/ci-scripts/main-index-to-class.py b/ci-scripts/main-index-to-class.py new file mode 100644 index 0000000000..04a31302ae --- /dev/null +++ b/ci-scripts/main-index-to-class.py @@ -0,0 +1,4921 @@ +# /* +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (the "License"); you may not use this file +# * except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.openairinterface.org/?page_id=698 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# Python for CI of OAI-eNB + COTS-UE +# +# Required Python Version +# Python 3.x +# +# Required Python Package +# pexpect +#--------------------------------------------------------------------- + +#----------------------------------------------------------- +# Version +#----------------------------------------------------------- +Version = '0.1' + +#----------------------------------------------------------- +# Constants +#----------------------------------------------------------- +ALL_PROCESSES_OK = 0 +ENB_PROCESS_FAILED = -1 +ENB_PROCESS_OK = +1 +ENB_PROCESS_SEG_FAULT = -11 +ENB_PROCESS_ASSERTION = -12 +ENB_PROCESS_REALTIME_ISSUE = -13 +ENB_PROCESS_NOLOGFILE_TO_ANALYZE = -14 +ENB_PROCESS_SLAVE_RRU_NOT_SYNCED = -15 +HSS_PROCESS_FAILED = -2 +HSS_PROCESS_OK = +2 +MME_PROCESS_FAILED = -3 +MME_PROCESS_OK = +3 +SPGW_PROCESS_FAILED = -4 +SPGW_PROCESS_OK = +4 +UE_IP_ADDRESS_ISSUE = -5 +OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE = -20 +OAI_UE_PROCESS_COULD_NOT_SYNC = -21 +OAI_UE_PROCESS_ASSERTION = -22 +OAI_UE_PROCESS_FAILED = -23 +OAI_UE_PROCESS_NO_TUNNEL_INTERFACE = -24 +OAI_UE_PROCESS_OK = +6 + +UE_STATUS_DETACHED = 0 +UE_STATUS_DETACHING = 1 +UE_STATUS_ATTACHING = 2 +UE_STATUS_ATTACHED = 3 + +X2_HO_REQ_STATE__IDLE = 0 +X2_HO_REQ_STATE__TARGET_RECEIVES_REQ = 1 +X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE = 2 +X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ = 3 +X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK = 10 + +#----------------------------------------------------------- +# Import +#----------------------------------------------------------- +import sys # arg +import re # reg +import pexpect # pexpect +import time # sleep +import os +import subprocess +import xml.etree.ElementTree as ET +import logging +import datetime +import signal +from multiprocessing import Process, Lock, SimpleQueue +logging.basicConfig( + level=logging.DEBUG, + format="[%(asctime)s] %(name)s:%(levelname)s: %(message)s" +) + +#----------------------------------------------------------- +# Class Declaration +#----------------------------------------------------------- +class SSHConnection(): + def __init__(self): + self.cnt = 0 # cnt from index to object of a class + self.prematureExit = False + self.ranRepository = '' + self.ranBranch = '' + self.ranAllowMerge = False + self.ranCommitID = '' + self.ranTargetBranch = '' + self.eNBIPAddress = '' + self.eNBUserName = '' + self.eNBPassword = '' + self.eNBSourceCodePath = '' + self.EPCIPAddress = '' + self.EPCUserName = '' + self.EPCPassword = '' + self.eNB1IPAddress = '' + self.eNB1UserName = '' + self.eNB1Password = '' + self.eNB1SourceCodePath = '' + self.eNB2IPAddress = '' + self.eNB2UserName = '' + self.eNB2Password = '' + self.eNB2SourceCodePath = '' + self.EPCSourceCodePath = '' + self.EPCType = '' + self.EPC_PcapFileName = '' + self.ADBIPAddress = '' + self.ADBUserName = '' + self.ADBPassword = '' + self.ADBCentralized = True + self.testCase_id = '' + self.testXMLfiles = [] + self.nbTestXMLfiles = 0 + self.desc = '' + self.Build_eNB_args = '' + self.backgroundBuild = False + self.backgroundBuildTestId = ['', '', ''] + self.Initialize_eNB_args = '' + self.eNB_instance = '' + self.eNB_serverId = '' + self.eNBLogFiles = ['', '', ''] + self.eNBOptions = ['', '', ''] + self.ping_args = '' + self.ping_packetloss_threshold = '' + self.iperf_args = '' + self.iperf_packetloss_threshold = '' + self.iperf_profile = '' + self.nbMaxUEtoAttach = -1 + self.UEDevices = [] + self.UEDevicesStatus = [] + self.UEDevicesRemoteServer = [] + self.UEDevicesRemoteUser = [] + self.UEDevicesOffCmd = [] + self.UEDevicesOnCmd = [] + self.UEDevicesRebootCmd = [] + self.CatMDevices = [] + self.UEIPAddresses = [] + self.htmlFile = '' + self.htmlHeaderCreated = False + self.htmlFooterCreated = False + self.htmlUEConnected = -1 + self.htmleNBFailureMsg = '' + self.htmlUEFailureMsg = '' + self.picocom_closure = False + self.idle_sleep_time = 0 + self.x2_ho_options = 'network' + self.x2NbENBs = 0 + self.x2ENBBsIds = [] + self.x2ENBConnectedUEs = [] + self.htmlTabRefs = [] + self.htmlTabNames = [] + self.htmlTabIcons = [] + self.repeatCounts = [] + self.finalStatus = False + self.OsVersion = '' + self.KernelVersion = '' + self.UhdVersion = '' + self.UsrpBoard = '' + self.CpuNb = '' + self.CpuModel = '' + self.CpuMHz = '' + self.UEIPAddress = '' + self.UEUserName = '' + self.UEPassword = '' + self.UE_instance = '' + self.UESourceCodePath = '' + self.UELogFile = '' + self.Build_OAI_UE_args = '' + self.Initialize_OAI_UE_args = '' + self.flexranCtrlInstalled = False + self.flexranCtrlStarted = False + self.expectedNbOfConnectedUEs = 0 + self.startTime = 0 + + def open(self, ipaddress, username, password): + count = 0 + connect_status = False + while count < 4: + self.ssh = pexpect.spawn('ssh', [username + '@' + ipaddress], timeout = 5) + self.sshresponse = self.ssh.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', 'Last login', pexpect.EOF, pexpect.TIMEOUT]) + if self.sshresponse == 0: + self.ssh.sendline('yes') + self.ssh.expect('password:') + self.ssh.sendline(password) + self.sshresponse = self.ssh.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if self.sshresponse == 0: + count = 10 + connect_status = True + else: + logging.debug('self.sshresponse = ' + str(self.sshresponse)) + elif self.sshresponse == 1: + self.ssh.sendline(password) + self.sshresponse = self.ssh.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if self.sshresponse == 0: + count = 10 + connect_status = True + else: + logging.debug('self.sshresponse = ' + str(self.sshresponse)) + elif self.sshresponse == 2: + # Checking if we are really on the remote client defined by its IP address + self.command('stdbuf -o0 ifconfig | egrep --color=never "inet addr:|inet "', '\$', 5) + result = re.search(str(ipaddress), str(self.ssh.before)) + if result is None: + self.close() + else: + count = 10 + connect_status = True + else: + # debug output + logging.debug(str(self.ssh.before)) + logging.debug('self.sshresponse = ' + str(self.sshresponse)) + # adding a tempo when failure + if not connect_status: + time.sleep(1) + count += 1 + if connect_status: + pass + else: + sys.exit('SSH Connection Failed') + + def command(self, commandline, expectedline, timeout): + logging.debug(commandline) + self.ssh.timeout = timeout + self.ssh.sendline(commandline) + self.sshresponse = self.ssh.expect([expectedline, pexpect.EOF, pexpect.TIMEOUT]) + if self.sshresponse == 0: + return 0 + elif self.sshresponse == 1: + logging.debug('\u001B[1;37;41m Unexpected EOF \u001B[0m') + logging.debug('Expected Line : ' + expectedline) + sys.exit(self.sshresponse) + elif self.sshresponse == 2: + logging.debug('\u001B[1;37;41m Unexpected TIMEOUT \u001B[0m') + logging.debug('Expected Line : ' + expectedline) + result = re.search('ping |iperf |picocom', str(commandline)) + if result is None: + logging.debug(str(self.ssh.before)) + sys.exit(self.sshresponse) + else: + return -1 + else: + logging.debug('\u001B[1;37;41m Unexpected Others \u001B[0m') + logging.debug('Expected Line : ' + expectedline) + sys.exit(self.sshresponse) + + def close(self): + self.ssh.timeout = 5 + self.ssh.sendline('exit') + self.sshresponse = self.ssh.expect([pexpect.EOF, pexpect.TIMEOUT]) + if self.sshresponse == 0: + pass + elif self.sshresponse == 1: + if not self.picocom_closure: + logging.debug('\u001B[1;37;41m Unexpected TIMEOUT during closing\u001B[0m') + else: + logging.debug('\u001B[1;37;41m Unexpected Others during closing\u001B[0m') + + def copyin(self, ipaddress, username, password, source, destination): + count = 0 + copy_status = False + logging.debug('scp '+ username + '@' + ipaddress + ':' + source + ' ' + destination) + while count < 10: + scp_spawn = pexpect.spawn('scp '+ username + '@' + ipaddress + ':' + source + ' ' + destination, timeout = 100) + scp_response = scp_spawn.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if scp_response == 0: + scp_spawn.sendline('yes') + scp_spawn.expect('password:') + scp_spawn.sendline(password) + scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if scp_response == 0: + count = 10 + copy_status = True + else: + logging.debug('1 - scp_response = ' + str(scp_response)) + elif scp_response == 1: + scp_spawn.sendline(password) + scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if scp_response == 0 or scp_response == 3: + count = 10 + copy_status = True + else: + logging.debug('2 - scp_response = ' + str(scp_response)) + elif scp_response == 2: + count = 10 + copy_status = True + else: + logging.debug('3 - scp_response = ' + str(scp_response)) + # adding a tempo when failure + if not copy_status: + time.sleep(1) + count += 1 + if copy_status: + return 0 + else: + return -1 + + def copyout(self, ipaddress, username, password, source, destination): + count = 0 + copy_status = False + logging.debug('scp ' + source + ' ' + username + '@' + ipaddress + ':' + destination) + while count < 4: + scp_spawn = pexpect.spawn('scp ' + source + ' ' + username + '@' + ipaddress + ':' + destination, timeout = 100) + scp_response = scp_spawn.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if scp_response == 0: + scp_spawn.sendline('yes') + scp_spawn.expect('password:') + scp_spawn.sendline(password) + scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if scp_response == 0: + count = 10 + copy_status = True + else: + logging.debug('1 - scp_response = ' + str(scp_response)) + elif scp_response == 1: + scp_spawn.sendline(password) + scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if scp_response == 0 or scp_response == 3: + count = 10 + copy_status = True + else: + logging.debug('2 - scp_response = ' + str(scp_response)) + elif scp_response == 2: + count = 10 + copy_status = True + else: + logging.debug('3 - scp_response = ' + str(scp_response)) + # adding a tempo when failure + if not copy_status: + time.sleep(1) + count += 1 + if copy_status: + pass + else: + sys.exit('SCP failed') + + def BuildeNB(self): + if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': + Usage() + sys.exit('Insufficient Parameter') + if self.eNB_serverId == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = self.eNBSourceCodePath + elif self.eNB_serverId == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + lSourcePath = self.eNB1SourceCodePath + elif self.eNB_serverId == '2': + lIpAddr = self.eNB2IPAddress + lUserName = self.eNB2UserName + lPassWord = self.eNB2Password + lSourcePath = self.eNB2SourceCodePath + if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': + Usage() + sys.exit('Insufficient Parameter') + self.open(lIpAddr, lUserName, lPassWord) + self.command('mkdir -p ' + lSourcePath, '\$', 5) + self.command('cd ' + lSourcePath, '\$', 5) + self.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + self.ranRepository + ' .; else stdbuf -o0 git fetch; fi', '\$', 600) + # Raphael: here add a check if git clone or git fetch went smoothly + self.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) + self.command('git config user.name "OAI Jenkins"', '\$', 5) + # Checking the BUILD INFO file + if not self.backgroundBuild: + self.command('ls *.txt', '\$', 5) + result = re.search('LAST_BUILD_INFO', str(self.ssh.before)) + if result is not None: + mismatch = False + self.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) + result = re.search(self.ranCommitID, str(self.ssh.before)) + if result is None: + mismatch = True + self.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) + if (self.ranAllowMerge): + result = re.search('YES', str(self.ssh.before)) + if result is None: + mismatch = True + self.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) + if self.ranTargetBranch == '': + result = re.search('develop', str(self.ssh.before)) + else: + result = re.search(self.ranTargetBranch, str(self.ssh.before)) + if result is None: + mismatch = True + else: + result = re.search('NO', str(self.ssh.before)) + if result is None: + mismatch = True + if not mismatch: + self.close() + self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) + return + + self.command('echo ' + lPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30) + # if the commit ID is provided use it to point to it + if self.ranCommitID != '': + self.command('git checkout -f ' + self.ranCommitID, '\$', 5) + # if the branch is not develop, then it is a merge request and we need to do + # the potential merge. Note that merge conflicts should already been checked earlier + if (self.ranAllowMerge): + if self.ranTargetBranch == '': + if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'): + self.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) + else: + logging.debug('Merging with the target branch: ' + self.ranTargetBranch) + self.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5) + self.command('source oaienv', '\$', 5) + self.command('cd cmake_targets', '\$', 5) + self.command('mkdir -p log', '\$', 5) + self.command('chmod 777 log', '\$', 5) + # no need to remove in log (git clean did the trick) + if self.backgroundBuild: + self.command('echo "./build_oai ' + self.Build_eNB_args + '" > ./my-lte-softmodem-build.sh', '\$', 5) + self.command('chmod 775 ./my-lte-softmodem-build.sh', '\$', 5) + self.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=build_enb_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/compile_oai_enb.log ./my-lte-softmodem-build.sh', '\$', 5) + self.close() + self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) + self.backgroundBuildTestId[int(self.eNB_instance)] = self.testCase_id + return + self.command('stdbuf -o0 ./build_oai ' + self.Build_eNB_args + ' 2>&1 | stdbuf -o0 tee compile_oai_enb.log', 'Bypassing the Tests|build have failed', 1500) + self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.testCase_id) + + def WaitBuildeNBisFinished(self): + if self.eNB_serverId == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = self.eNBSourceCodePath + elif self.eNB_serverId == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + lSourcePath = self.eNB1SourceCodePath + elif self.eNB_serverId == '2': + lIpAddr = self.eNB2IPAddress + lUserName = self.eNB2UserName + lPassWord = self.eNB2Password + lSourcePath = self.eNB2SourceCodePath + if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': + Usage() + sys.exit('Insufficient Parameter') + self.open(lIpAddr, lUserName, lPassWord) + count = 40 + buildOAIprocess = True + while (count > 0) and buildOAIprocess: + self.command('ps aux | grep --color=never build_ | grep -v grep', '\$', 3) + result = re.search('build_oai', str(self.ssh.before)) + if result is None: + buildOAIprocess = False + else: + count -= 1 + time.sleep(30) + self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.backgroundBuildTestId[int(self.eNB_instance)]) + + def checkBuildeNB(self, lIpAddr, lUserName, lPassWord, lSourcePath, testcaseId): + self.command('cd ' + lSourcePath + '/cmake_targets', '\$', 3) + self.command('ls lte_build_oai/build', '\$', 3) + self.command('ls lte_build_oai/build', '\$', 3) + buildStatus = True + result = re.search('lte-softmodem', str(self.ssh.before)) + if result is None: + buildStatus = False + else: + # Generating a BUILD INFO file + self.command('echo "SRC_BRANCH: ' + self.ranBranch + '" > ../LAST_BUILD_INFO.txt', '\$', 2) + self.command('echo "SRC_COMMIT: ' + self.ranCommitID + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) + if (self.ranAllowMerge): + self.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2) + if self.ranTargetBranch == '': + self.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2) + else: + self.command('echo "TGT_BRANCH: ' + self.ranTargetBranch + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) + else: + self.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) + self.command('mkdir -p build_log_' + testcaseId, '\$', 5) + self.command('mv log/* ' + 'build_log_' + testcaseId, '\$', 5) + self.command('mv compile_oai_enb.log ' + 'build_log_' + testcaseId, '\$', 5) + if self.eNB_serverId != '0': + self.command('cd cmake_targets', '\$', 5) + self.command('if [ -e tmp_build' + testcaseId + '.zip ]; then rm -f tmp_build' + testcaseId + '.zip; fi', '\$', 5) + self.command('zip -r -qq tmp_build' + testcaseId + '.zip build_log_' + testcaseId, '\$', 5) + self.close() + if (os.path.isfile('./tmp_build' + testcaseId + '.zip')): + os.remove('./tmp_build' + testcaseId + '.zip') + self.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/tmp_build' + testcaseId + '.zip', '.') + if (os.path.isfile('./tmp_build' + testcaseId + '.zip')): + self.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './tmp_build' + testcaseId + '.zip', self.eNBSourceCodePath + '/cmake_targets/.') + os.remove('./tmp_build' + testcaseId + '.zip') + self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) + self.command('cd ' + self.eNBSourceCodePath + '/cmake_targets', '\$', 5) + self.command('unzip -qq -DD tmp_build' + testcaseId + '.zip', '\$', 5) + self.command('rm -f tmp_build' + testcaseId + '.zip', '\$', 5) + self.close() + else: + self.close() + + if buildStatus: + self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) + else: + logging.error('\u001B[1m Building OAI eNB Failed\u001B[0m') + self.CreateHtmlTestRow(self.Build_eNB_args, 'KO', ALL_PROCESSES_OK) + self.CreateHtmlTabFooter(False) + sys.exit(1) + + def BuildOAIUE(self): + if self.UEIPAddress == '' or self.ranRepository == '' or self.ranBranch == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + self.command('mkdir -p ' + self.UESourceCodePath, '\$', 5) + self.command('cd ' + self.UESourceCodePath, '\$', 5) + self.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + self.ranRepository + ' .; else stdbuf -o0 git fetch; fi', '\$', 600) + # here add a check if git clone or git fetch went smoothly + self.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) + self.command('git config user.name "OAI Jenkins"', '\$', 5) + self.command('ls *.txt', '\$', 5) + result = re.search('LAST_BUILD_INFO', str(self.ssh.before)) + if result is not None: + mismatch = False + self.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) + result = re.search(self.ranCommitID, str(self.ssh.before)) + if result is None: + mismatch = True + self.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) + if (self.ranAllowMerge): + result = re.search('YES', str(self.ssh.before)) + if result is None: + mismatch = True + self.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) + if self.ranTargetBranch == '': + result = re.search('develop', str(self.ssh.before)) + else: + result = re.search(self.ranTargetBranch, str(self.ssh.before)) + if result is None: + mismatch = True + else: + result = re.search('NO', str(self.ssh.before)) + if result is None: + mismatch = True + if not mismatch: + self.close() + self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) + return + + self.command('echo ' + self.UEPassword + ' | sudo -S git clean -x -d -ff', '\$', 30) + # if the commit ID is provided use it to point to it + if self.ranCommitID != '': + self.command('git checkout -f ' + self.ranCommitID, '\$', 5) + # if the branch is not develop, then it is a merge request and we need to do + # the potential merge. Note that merge conflicts should already been checked earlier + if (self.ranAllowMerge): + if self.ranTargetBranch == '': + if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'): + self.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) + else: + logging.debug('Merging with the target branch: ' + self.ranTargetBranch) + self.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5) + self.command('source oaienv', '\$', 5) + self.command('cd cmake_targets', '\$', 5) + self.command('mkdir -p log', '\$', 5) + self.command('chmod 777 log', '\$', 5) + # no need to remove in log (git clean did the trick) + self.command('stdbuf -o0 ./build_oai ' + self.Build_OAI_UE_args + ' 2>&1 | stdbuf -o0 tee compile_oai_ue.log', 'Bypassing the Tests|build have failed', 600) + self.command('ls lte_build_oai/build', '\$', 3) + self.command('ls lte_build_oai/build', '\$', 3) + buildStatus = True + result = re.search('lte-uesoftmodem', str(self.ssh.before)) + if result is None: + buildStatus = False + self.command('mkdir -p build_log_' + self.testCase_id, '\$', 5) + self.command('mv log/* ' + 'build_log_' + self.testCase_id, '\$', 5) + self.command('mv compile_oai_ue.log ' + 'build_log_' + self.testCase_id, '\$', 5) + if buildStatus: + # Generating a BUILD INFO file + self.command('echo "SRC_BRANCH: ' + self.ranBranch + '" > ../LAST_BUILD_INFO.txt', '\$', 2) + self.command('echo "SRC_COMMIT: ' + self.ranCommitID + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) + if (self.ranAllowMerge): + self.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2) + if self.ranTargetBranch == '': + self.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2) + else: + self.command('echo "TGT_BRANCH: ' + self.ranTargetBranch + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) + else: + self.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) + self.close() + self.CreateHtmlTestRow(self.Build_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE') + else: + self.close() + logging.error('\u001B[1m Building OAI UE Failed\u001B[0m') + self.CreateHtmlTestRow(self.Build_OAI_UE_args, 'KO', ALL_PROCESSES_OK, 'OAI UE') + self.CreateHtmlTabFooter(False) + sys.exit(1) + + def InitializeHSS(self): + if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': + Usage() + sys.exit('Insufficient Parameter') + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + logging.debug('Using the OAI EPC Release 14 Cassandra-based HSS') + self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + logging.debug('\u001B[1m Launching tshark on all interfaces \u001B[0m') + EPC_PcapFileName = 'epc_' + self.testCase_id + '.pcap' + self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f ' + EPC_PcapFileName, '\$', 5) + self.command('echo $USER; nohup sudo tshark -f "tcp port not 22 and port not 53" -i any -w ' + self.EPCSourceCodePath + '/scripts/' + EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', self.EPCUserName, 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S mkdir -p logs', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f hss_' + self.testCase_id + '.log logs/hss*.*', '\$', 5) + self.command('echo "oai_hss -j /usr/local/etc/oai/hss_rel14.json" > ./my-hss.sh', '\$', 5) + self.command('chmod 755 ./my-hss.sh', '\$', 5) + self.command('sudo daemon --unsafe --name=hss_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/hss_' + self.testCase_id + '.log ./my-hss.sh', '\$', 5) + elif re.match('OAI', self.EPCType, re.IGNORECASE): + logging.debug('Using the OAI EPC HSS') + self.command('cd ' + self.EPCSourceCodePath, '\$', 5) + self.command('source oaienv', '\$', 5) + self.command('cd scripts', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S ./run_hss 2>&1 | stdbuf -o0 awk \'{ print strftime("[%Y/%m/%d %H:%M:%S] ",systime()) $0 }\' | stdbuf -o0 tee -a hss_' + self.testCase_id + '.log &', 'Core state: 2 -> 3', 35) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + logging.debug('Using the ltebox simulated HSS') + self.command('if [ -d ' + self.EPCSourceCodePath + '/scripts ]; then echo ' + self.eNBPassword + ' | sudo -S rm -Rf ' + self.EPCSourceCodePath + '/scripts ; fi', '\$', 5) + self.command('mkdir -p ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + self.command('cd /opt/hss_sim0609', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f hss.log daemon.log', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S echo "Starting sudo session" && sudo daemon --unsafe --name=simulated_hss --chdir=/opt/hss_sim0609 ./starthss_real ', '\$', 5) + else: + logging.error('This option should not occur!') + self.close() + self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) + + def InitializeMME(self): + if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': + Usage() + sys.exit('Insufficient Parameter') + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + logging.debug('Using the OAI EPC Release 14 MME') + self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f mme_' + self.testCase_id + '.log', '\$', 5) + self.command('echo "./run_mme --config-file /usr/local/etc/oai/mme.conf --set-virt-if" > ./my-mme.sh', '\$', 5) + self.command('chmod 755 ./my-mme.sh', '\$', 5) + self.command('sudo daemon --unsafe --name=mme_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/mme_' + self.testCase_id + '.log ./my-mme.sh', '\$', 5) + elif re.match('OAI', self.EPCType, re.IGNORECASE): + self.command('cd ' + self.EPCSourceCodePath, '\$', 5) + self.command('source oaienv', '\$', 5) + self.command('cd scripts', '\$', 5) + self.command('stdbuf -o0 hostname', '\$', 5) + result = re.search('hostname\\\\r\\\\n(?P[a-zA-Z0-9\-\_]+)\\\\r\\\\n', str(self.ssh.before)) + if result is None: + logging.debug('\u001B[1;37;41m Hostname Not Found! \u001B[0m') + sys.exit(1) + host_name = result.group('host_name') + self.command('echo ' + self.EPCPassword + ' | sudo -S ./run_mme 2>&1 | stdbuf -o0 tee -a mme_' + self.testCase_id + '.log &', 'MME app initialization complete', 100) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + self.command('cd /opt/ltebox/tools', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S ./start_mme', '\$', 5) + else: + logging.error('This option should not occur!') + self.close() + self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) + + def InitializeSPGW(self): + if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': + Usage() + sys.exit('Insufficient Parameter') + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + logging.debug('Using the OAI EPC Release 14 SPGW-CUPS') + self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f spgwc_' + self.testCase_id + '.log spgwu_' + self.testCase_id + '.log', '\$', 5) + self.command('echo "spgwc -c /usr/local/etc/oai/spgw_c.conf" > ./my-spgwc.sh', '\$', 5) + self.command('chmod 755 ./my-spgwc.sh', '\$', 5) + self.command('sudo daemon --unsafe --name=spgwc_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/spgwc_' + self.testCase_id + '.log ./my-spgwc.sh', '\$', 5) + time.sleep(5) + self.command('echo "spgwu -c /usr/local/etc/oai/spgw_u.conf" > ./my-spgwu.sh', '\$', 5) + self.command('chmod 755 ./my-spgwu.sh', '\$', 5) + self.command('sudo daemon --unsafe --name=spgwu_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/spgwu_' + self.testCase_id + '.log ./my-spgwu.sh', '\$', 5) + elif re.match('OAI', self.EPCType, re.IGNORECASE): + self.command('cd ' + self.EPCSourceCodePath, '\$', 5) + self.command('source oaienv', '\$', 5) + self.command('cd scripts', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S ./run_spgw 2>&1 | stdbuf -o0 tee -a spgw_' + self.testCase_id + '.log &', 'Initializing SPGW-APP task interface: DONE', 30) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + self.command('cd /opt/ltebox/tools', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S ./start_xGw', '\$', 5) + else: + logging.error('This option should not occur!') + self.close() + self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) + + def CheckFlexranCtrlInstallation(self): + if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '': + return + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('ls -ls /opt/flexran_rtc/*/rt_controller', '\$', 5) + result = re.search('/opt/flexran_rtc/build/rt_controller', str(self.ssh.before)) + if result is not None: + self.flexranCtrlInstalled = True + logging.debug('Flexran Controller is installed') + self.close() + + def InitializeFlexranCtrl(self): + if self.flexranCtrlInstalled == False: + return + if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '': + Usage() + sys.exit('Insufficient Parameter') + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('cd /opt/flexran_rtc', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f log/*.log', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S echo "build/rt_controller -c log_config/basic_log" > ./my-flexran-ctl.sh', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S chmod 755 ./my-flexran-ctl.sh', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S daemon --unsafe --name=flexran_rtc_daemon --chdir=/opt/flexran_rtc -o /opt/flexran_rtc/log/flexranctl_' + self.testCase_id + '.log ././my-flexran-ctl.sh', '\$', 5) + self.command('ps -aux | grep --color=never rt_controller', '\$', 5) + result = re.search('rt_controller -c ', str(self.ssh.before)) + if result is not None: + logging.debug('\u001B[1m Initialize FlexRan Controller Completed\u001B[0m') + self.flexranCtrlStarted = True + self.close() + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def InitializeeNB(self): + if self.eNB_serverId == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = self.eNBSourceCodePath + elif self.eNB_serverId == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + lSourcePath = self.eNB1SourceCodePath + elif self.eNB_serverId == '2': + lIpAddr = self.eNB2IPAddress + lUserName = self.eNB2UserName + lPassWord = self.eNB2Password + lSourcePath = self.eNB2SourceCodePath + if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': + Usage() + sys.exit('Insufficient Parameter') + check_eNB = False + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow(self.Initialize_eNB_args, 'KO', pStatus) + self.CreateHtmlTabFooter(False) + sys.exit(1) + # If tracer options is on, running tshark on EPC side and capture traffic b/ EPC and eNB + result = re.search('T_stdout', str(self.Initialize_eNB_args)) + if result is not None: + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('ip addr show | awk -f /tmp/active_net_interfaces.awk | egrep -v "lo|tun"', '\$', 5) + result = re.search('interfaceToUse=(?P[a-zA-Z0-9\-\_]+)done', str(self.ssh.before)) + if result is not None: + eth_interface = result.group('eth_interface') + logging.debug('\u001B[1m Launching tshark on interface ' + eth_interface + '\u001B[0m') + self.EPC_PcapFileName = 'enb_' + self.testCase_id + '_s1log.pcap' + self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f /tmp/' + self.EPC_PcapFileName, '\$', 5) + self.command('echo $USER; nohup sudo tshark -f "host ' + lIpAddr +'" -i ' + eth_interface + ' -w /tmp/' + self.EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', self.EPCUserName, 5) + self.close() + self.open(lIpAddr, lUserName, lPassWord) + self.command('cd ' + lSourcePath, '\$', 5) + # Initialize_eNB_args usually start with -O and followed by the location in repository + full_config_file = self.Initialize_eNB_args.replace('-O ','') + extra_options = '' + extIdx = full_config_file.find('.conf') + if (extIdx > 0): + extra_options = full_config_file[extIdx + 5:] + # if tracer options is on, compiling and running T Tracer + result = re.search('T_stdout', str(extra_options)) + if result is not None: + logging.debug('\u001B[1m Compiling and launching T Tracer\u001B[0m') + self.command('cd common/utils/T/tracer', '\$', 5) + self.command('make', '\$', 10) + self.command('echo $USER; nohup ./record -d ../T_messages.txt -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.raw -ON -off VCD -off HEAVY -off LEGACY_GROUP_TRACE -off LEGACY_GROUP_DEBUG > ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.log 2>&1 &', lUserName, 5) + self.command('cd ' + lSourcePath, '\$', 5) + full_config_file = full_config_file[:extIdx + 5] + config_path, config_file = os.path.split(full_config_file) + else: + sys.exit('Insufficient Parameter') + ci_full_config_file = config_path + '/ci-' + config_file + rruCheck = False + result = re.search('^rru|^rcc|^du.band', str(config_file)) + if result is not None: + rruCheck = True + # do not reset board twice in IF4.5 case + result = re.search('^rru|^enb|^du.band', str(config_file)) + if result is not None: + self.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 10) + result = re.search('type: b200', str(self.ssh.before)) + if result is not None: + logging.debug('Found a B2xx device --> resetting it') + self.command('echo ' + lPassWord + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10) + # Reloading FGPA bin firmware + self.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 15) + # Make a copy and adapt to EPC / eNB IP addresses + self.command('cp ' + full_config_file + ' ' + ci_full_config_file, '\$', 5) + self.command('sed -i -e \'s/CI_MME_IP_ADDR/' + self.EPCIPAddress + '/\' ' + ci_full_config_file, '\$', 2); + self.command('sed -i -e \'s/CI_ENB_IP_ADDR/' + lIpAddr + '/\' ' + ci_full_config_file, '\$', 2); + self.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2); + self.command('sed -i -e \'s/CI_RRU1_IP_ADDR/' + self.eNB1IPAddress + '/\' ' + ci_full_config_file, '\$', 2); + self.command('sed -i -e \'s/CI_RRU2_IP_ADDR/' + self.eNB2IPAddress + '/\' ' + ci_full_config_file, '\$', 2); + if self.flexranCtrlInstalled and self.flexranCtrlStarted: + self.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "yes";/\' ' + ci_full_config_file, '\$', 2); + else: + self.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "no";/\' ' + ci_full_config_file, '\$', 2); + # Launch eNB with the modified config file + self.command('source oaienv', '\$', 5) + self.command('cd cmake_targets', '\$', 5) + self.command('echo "ulimit -c unlimited && ./lte_build_oai/build/lte-softmodem -O ' + lSourcePath + '/' + ci_full_config_file + extra_options + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + self.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + self.command('chmod 775 ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + self.command('echo ' + lPassWord + ' | sudo -S rm -Rf enb_' + self.testCase_id + '.log', '\$', 5) + self.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=enb' + str(self.eNB_instance) + '_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + self.eNBLogFiles[int(self.eNB_instance)] = 'enb_' + self.testCase_id + '.log' + if extra_options != '': + self.eNBOptions[int(self.eNB_instance)] = extra_options + time.sleep(6) + doLoop = True + loopCounter = 10 + while (doLoop): + loopCounter = loopCounter - 1 + if (loopCounter == 0): + # In case of T tracer recording, we may need to kill it + result = re.search('T_stdout', str(self.Initialize_eNB_args)) + if result is not None: + self.command('killall --signal SIGKILL record', '\$', 5) + self.close() + doLoop = False + logging.error('\u001B[1;37;41m eNB logging system did not show got sync! \u001B[0m') + self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'KO', ALL_PROCESSES_OK) + # In case of T tracer recording, we need to kill tshark on EPC side + result = re.search('T_stdout', str(self.Initialize_eNB_args)) + if result is not None: + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + logging.debug('\u001B[1m Stopping tshark \u001B[0m') + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) + if self.EPC_PcapFileName != '': + time.sleep(0.5) + self.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 /tmp/' + self.EPC_PcapFileName, '\$', 5) + self.close() + time.sleep(1) + if self.EPC_PcapFileName != '': + copyin_res = self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + self.EPC_PcapFileName, '.') + if (copyin_res == 0): + self.copyout(lIpAddr, lUserName, lPassWord, self.EPC_PcapFileName, lSourcePath + '/cmake_targets/.') + self.prematureExit = True + return + else: + self.command('stdbuf -o0 cat enb_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync|Starting"', '\$', 4) + if rruCheck: + result = re.search('wait RUs', str(self.ssh.before)) + else: + result = re.search('got sync|Starting F1AP at CU', str(self.ssh.before)) + if result is None: + time.sleep(6) + else: + doLoop = False + self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'OK', ALL_PROCESSES_OK) + logging.debug('\u001B[1m Initialize eNB Completed\u001B[0m') + time.sleep(10) + + self.close() + + def InitializeUE_common(self, device_id, idx): + try: + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + if not self.ADBCentralized: + # Reboot UE + #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesRebootCmd[idx], '\$', 60) + # Wait + #time.sleep(60) + # Put in LTE-Mode only + #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode 11"\'', '\$', 60) + #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode1 11"\'', '\$', 60) + #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode2 11"\'', '\$', 60) + #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode3 11"\'', '\$', 60) + # enable data service + #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) + # we need to do radio on/off cycle to make sure of above changes + # airplane mode off // radio on + #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) + #time.sleep(10) + # airplane mode on // radio off + #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + + # normal procedure without reboot + # enable data service + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) + # airplane mode on // radio off + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + self.close() + return + # enable data service + self.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data enable"', '\$', 60) + + # The following commands are deprecated since we no longer work on Android 7+ + # self.command('stdbuf -o0 adb -s ' + device_id + ' shell settings put global airplane_mode_on 1', '\$', 10) + # self.command('stdbuf -o0 adb -s ' + device_id + ' shell am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true', '\$', 60) + # a dedicated script has to be installed inside the UE + # airplane mode on means call /data/local/tmp/off + if device_id == '84B7N16418004022': + self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) + else: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) + #airplane mode off means call /data/local/tmp/on + logging.debug('\u001B[1mUE (' + device_id + ') Initialize Completed\u001B[0m') + self.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def InitializeUE(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + multi_jobs = [] + i = 0 + for device_id in self.UEDevices: + p = Process(target = self.InitializeUE_common, args = (device_id,i,)) + p.daemon = True + p.start() + multi_jobs.append(p) + i += 1 + for job in multi_jobs: + job.join() + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def InitializeOAIUE(self): + if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) + if result is None: + check_eNB = True + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', pStatus) + self.CreateHtmlTabFooter(False) + sys.exit(1) + self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + # b2xx_fx3_utils reset procedure + self.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 10) + result = re.search('type: b200', str(self.ssh.before)) + if result is not None: + logging.debug('Found a B2xx device --> resetting it') + self.command('echo ' + self.UEPassword + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10) + # Reloading FGPA bin firmware + self.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 15) + else: + logging.debug('Did not find any B2xx device') + self.command('cd ' + self.UESourceCodePath, '\$', 5) + self.command('source oaienv', '\$', 5) + self.command('cd cmake_targets/lte_build_oai/build', '\$', 5) + result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) + # We may have to regenerate the .u* files + if result is None: + self.command('ls /tmp/*.sed', '\$', 5) + result = re.search('adapt_usim_parameters', str(self.ssh.before)) + if result is not None: + self.command('sed -f /tmp/adapt_usim_parameters.sed ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5) + else: + self.command('sed -e "s#93#92#" -e "s#8baf473f2f8fd09487cccbd7097c6862#fec86ba6eb707ed08905757b1bb44b8f#" -e "s#e734f8734007d6c5ce7a0508809e7e9c#C42449363BBAD02B66D16BC975D77CC1#" ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5) + self.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf .u*', '\$', 5) + self.command('echo ' + self.UEPassword + ' | sudo -S ../../../targets/bin/conf2uedata -c ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf -o .', '\$', 5) + # Launch UE with the modified config file + self.command('echo "ulimit -c unlimited && ./lte-uesoftmodem ' + self.Initialize_OAI_UE_args + '" > ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) + self.command('chmod 775 ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) + self.UELogFile = 'ue_' + self.testCase_id + '.log' + + # We are now looping several times to hope we really sync w/ an eNB + doOutterLoop = True + outterLoopCounter = 5 + gotSyncStatus = True + fullSyncStatus = True + while (doOutterLoop): + self.command('cd ' + self.UESourceCodePath + '/cmake_targets/lte_build_oai/build', '\$', 5) + self.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log', '\$', 5) + self.command('echo ' + self.UEPassword + ' | sudo -S -E daemon --inherit --unsafe --name=ue' + str(self.UE_instance) + '_daemon --chdir=' + self.UESourceCodePath + '/cmake_targets/lte_build_oai/build -o ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) + time.sleep(6) + self.command('cd ../..', '\$', 5) + doLoop = True + loopCounter = 10 + gotSyncStatus = True + # the 'got sync' message is for the UE threads synchronization + while (doLoop): + loopCounter = loopCounter - 1 + if (loopCounter == 0): + # Here should never occur + logging.error('"got sync" message never showed!') + gotSyncStatus = False + doLoop = False + continue + self.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4) + result = re.search('got sync', str(self.ssh.before)) + if result is None: + time.sleep(6) + else: + doLoop = False + logging.debug('Found "got sync" message!') + if gotSyncStatus == False: + # we certainly need to stop the lte-uesoftmodem process if it is still running! + self.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4) + result = re.search('lte-uesoftmodem', str(self.ssh.before)) + if result is not None: + self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT lte-uesoftmodem', '\$', 4) + time.sleep(3) + # We are now checking if sync w/ eNB DOES NOT OCCUR + # Usually during the cell synchronization stage, the UE returns with No cell synchronization message + doLoop = True + loopCounter = 10 + while (doLoop): + loopCounter = loopCounter - 1 + if (loopCounter == 0): + # Here we do have a great chance that the UE did cell-sync w/ eNB + doLoop = False + doOutterLoop = False + fullSyncStatus = True + continue + self.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4) + result = re.search('No cell synchronization found', str(self.ssh.before)) + if result is None: + time.sleep(6) + else: + doLoop = False + fullSyncStatus = False + logging.debug('Found: "No cell synchronization" message! --> try again') + time.sleep(6) + self.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4) + result = re.search('lte-uesoftmodem', str(self.ssh.before)) + if result is not None: + self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT lte-uesoftmodem', '\$', 4) + outterLoopCounter = outterLoopCounter - 1 + if (outterLoopCounter == 0): + doOutterLoop = False + + if fullSyncStatus and gotSyncStatus: + result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) + if result is None: + self.command('ifconfig oaitun_ue1', '\$', 4) + # ifconfig output is different between ubuntu 16 and ubuntu 18 + result = re.search('inet addr:1|inet 1', str(self.ssh.before)) + if result is not None: + logging.debug('\u001B[1m oaitun_ue1 interface is mounted and configured\u001B[0m') + tunnelInterfaceStatus = True + else: + logging.debug(str(self.ssh.before)) + logging.error('\u001B[1m oaitun_ue1 interface is either NOT mounted or NOT configured\u001B[0m') + tunnelInterfaceStatus = False + else: + tunnelInterfaceStatus = True + + self.close() + if fullSyncStatus and gotSyncStatus and tunnelInterfaceStatus: + self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE') + logging.debug('\u001B[1m Initialize OAI UE Completed\u001B[0m') + if (self.ADBIPAddress != 'none'): + self.UEDevices = [] + self.UEDevices.append('OAI-UE') + self.UEDevicesStatus = [] + self.UEDevicesStatus.append(UE_STATUS_DETACHED) + else: + self.htmlUEFailureMsg = 'oaitun_ue1 interface is either NOT mounted or NOT configured' + self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', OAI_UE_PROCESS_NO_TUNNEL_INTERFACE, 'OAI UE') + logging.error('\033[91mInitialize OAI UE Failed! \033[0m') + self.AutoTerminateUEandeNB() + + def checkDevTTYisUnlocked(self): + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + count = 0 + while count < 5: + self.command('echo ' + self.ADBPassword + ' | sudo -S lsof | grep ttyUSB0', '\$', 10) + result = re.search('picocom', str(self.ssh.before)) + if result is None: + count = 10 + else: + time.sleep(5) + count = count + 1 + self.close() + + def InitializeCatM(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + self.picocom_closure = True + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` + self.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) + self.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) + time.sleep(1) + # Calling twice AT to clear all buffers + self.command('AT', 'OK|ERROR', 5) + self.command('AT', 'OK', 5) + # Disabling the Radio + self.command('AT+CFUN=0', 'OK', 5) + logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') + # Checking if auto-attach is enabled + self.command('AT^AUTOATT?', 'OK', 5) + result = re.search('AUTOATT: (?P[0-9\-]+)', str(self.ssh.before)) + if result is not None: + if result.group('state') is not None: + autoAttachState = int(result.group('state')) + if autoAttachState is not None: + if autoAttachState == 0: + self.command('AT^AUTOATT=1', 'OK', 5) + logging.debug('\u001B[1m Auto-Attach enabled\u001B[0m') + else: + logging.debug('\u001B[1;37;41m Could not check Auto-Attach! \u001B[0m') + # Force closure of picocom but device might still be locked + self.close() + self.picocom_closure = False + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + self.checkDevTTYisUnlocked() + + def TerminateCatM(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + self.picocom_closure = True + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` + self.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) + self.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) + time.sleep(1) + # Calling twice AT to clear all buffers + self.command('AT', 'OK|ERROR', 5) + self.command('AT', 'OK', 5) + # Disabling the Radio + self.command('AT+CFUN=0', 'OK', 5) + logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') + self.close() + self.picocom_closure = False + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + self.checkDevTTYisUnlocked() + + def AttachCatM(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + self.picocom_closure = True + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` + self.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) + self.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) + time.sleep(1) + # Calling twice AT to clear all buffers + self.command('AT', 'OK|ERROR', 5) + self.command('AT', 'OK', 5) + # Enabling the Radio + self.command('AT+CFUN=1', 'SIMSTORE,READY', 5) + logging.debug('\u001B[1m Cellular Functionality enabled\u001B[0m') + time.sleep(4) + # We should check if we register + count = 0 + attach_cnt = 0 + attach_status = False + while count < 5: + self.command('AT+CEREG?', 'OK', 5) + result = re.search('CEREG: 2,(?P[0-9\-]+),', str(self.ssh.before)) + if result is not None: + mDataConnectionState = int(result.group('state')) + if mDataConnectionState is not None: + if mDataConnectionState == 1: + count = 10 + attach_status = True + result = re.search('CEREG: 2,1,"(?P[0-9A-Z]+)","(?P[0-9A-Z]+)"', str(self.ssh.before)) + if result is not None: + networky = result.group('networky') + networkz = result.group('networkz') + logging.debug('\u001B[1m CAT-M module attached to eNB (' + str(networky) + '/' + str(networkz) + ')\u001B[0m') + else: + logging.debug('\u001B[1m CAT-M module attached to eNB\u001B[0m') + else: + logging.debug('+CEREG: 2,' + str(mDataConnectionState)) + attach_cnt = attach_cnt + 1 + else: + logging.debug(str(self.ssh.before)) + attach_cnt = attach_cnt + 1 + count = count + 1 + time.sleep(1) + if attach_status: + self.command('AT+CESQ', 'OK', 5) + result = re.search('CESQ: 99,99,255,255,(?P[0-9]+),(?P[0-9]+)', str(self.ssh.before)) + if result is not None: + nRSRQ = int(result.group('rsrq')) + nRSRP = int(result.group('rsrp')) + if (nRSRQ is not None) and (nRSRP is not None): + logging.debug(' RSRQ = ' + str(-20+(nRSRQ/2)) + ' dB') + logging.debug(' RSRP = ' + str(-140+nRSRP) + ' dBm') + self.close() + self.picocom_closure = False + html_queue = SimpleQueue() + self.checkDevTTYisUnlocked() + if attach_status: + html_cell = '
CAT-M module Attachment Completed in ' + str(attach_cnt+4) + ' seconds'
+			if (nRSRQ is not None) and (nRSRP is not None):
+				html_cell += '\n   RSRQ = ' + str(-20+(nRSRQ/2)) + ' dB'
+				html_cell += '\n   RSRP = ' + str(-140+nRSRP) + ' dBm
' + else: + html_cell += '' + html_queue.put(html_cell) + self.CreateHtmlTestRowQueue('N/A', 'OK', 1, html_queue) + else: + logging.error('\u001B[1m CAT-M module Attachment Failed\u001B[0m') + html_cell = '
CAT-M module Attachment Failed
' + html_queue.put(html_cell) + self.CreateHtmlTestRowQueue('N/A', 'KO', 1, html_queue) + self.AutoTerminateUEandeNB() + + def PingCatM(self): + if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + check_eNB = True + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + self.AutoTerminateUEandeNB() + return + try: + statusQueue = SimpleQueue() + lock = Lock() + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('cd ' + self.EPCSourceCodePath, '\$', 5) + self.command('cd scripts', '\$', 5) + if re.match('OAI', self.EPCType, re.IGNORECASE): + logging.debug('Using the OAI EPC HSS: not implemented yet') + self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + self.CreateHtmlTabFooter(False) + sys.exit(1) + else: + self.command('egrep --color=never "Allocated ipv4 addr" /opt/ltebox/var/log/xGwLog.0', '\$', 5) + result = re.search('Allocated ipv4 addr: (?P[0-9\.]+) from Pool', str(self.ssh.before)) + if result is not None: + moduleIPAddr = result.group('ipaddr') + else: + self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + self.AutoTerminateUEandeNB() + return + ping_time = re.findall("-c (\d+)",str(self.ping_args)) + device_id = 'catm' + ping_status = self.command('stdbuf -o0 ping ' + self.ping_args + ' ' + str(moduleIPAddr) + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) + # TIMEOUT CASE + if ping_status < 0: + message = 'Ping with UE (' + str(moduleIPAddr) + ') crashed due to TIMEOUT!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.close() + self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) + return + result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', str(self.ssh.before)) + if result is None: + message = 'Packet Loss Not Found!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.close() + self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) + return + packetloss = result.group('packetloss') + if float(packetloss) == 100: + message = 'Packet Loss is 100%' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.close() + self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) + return + result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', str(self.ssh.before)) + if result is None: + message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.close() + self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) + return + rtt_min = result.group('rtt_min') + rtt_avg = result.group('rtt_avg') + rtt_max = result.group('rtt_max') + pal_msg = 'Packet Loss : ' + packetloss + '%' + min_msg = 'RTT(Min) : ' + rtt_min + ' ms' + avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms' + max_msg = 'RTT(Max) : ' + rtt_max + ' ms' + lock.acquire() + logging.debug('\u001B[1;37;44m ping result (' + moduleIPAddr + ') \u001B[0m') + logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') + qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg + packetLossOK = True + if packetloss is not None: + if float(packetloss) > float(self.ping_packetloss_threshold): + qMsg += '\nPacket Loss too high' + logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') + packetLossOK = False + elif float(packetloss) > 0: + qMsg += '\nPacket Loss is not 0%' + logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m') + lock.release() + self.close() + html_cell = '
CAT-M module\nIP Address  : ' + moduleIPAddr + '\n' + qMsg + '
' + statusQueue.put(html_cell) + if (packetLossOK): + self.CreateHtmlTestRowQueue(self.ping_args, 'OK', 1, statusQueue) + else: + self.CreateHtmlTestRowQueue(self.ping_args, 'KO', 1, statusQueue) + self.AutoTerminateUEandeNB() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def AttachUE_common(self, device_id, statusQueue, lock, idx): + try: + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + if self.ADBCentralized: + if device_id == '84B7N16418004022': + self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/on"', '\$', 60) + else: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60) + else: + # airplane mode off // radio on + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) + time.sleep(2) + max_count = 45 + count = max_count + while count > 0: + if self.ADBCentralized: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry" | grep -m 1 mDataConnectionState', '\$', 15) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\' | grep -m 1 mDataConnectionState', '\$', 60) + result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', str(self.ssh.before)) + if result is None: + logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m') + lock.acquire() + statusQueue.put(-1) + statusQueue.put(device_id) + statusQueue.put('mDataConnectionState Not Found!') + lock.release() + break + mDataConnectionState = int(result.group('state')) + if mDataConnectionState == 2: + logging.debug('\u001B[1mUE (' + device_id + ') Attach Completed\u001B[0m') + lock.acquire() + statusQueue.put(max_count - count) + statusQueue.put(device_id) + statusQueue.put('Attach Completed') + lock.release() + break + count = count - 1 + if count == 15 or count == 30: + logging.debug('\u001B[1;30;43m Retry UE (' + device_id + ') Flight Mode Off \u001B[0m') + if self.ADBCentralized: + if device_id == '84B7N16418004022': + self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) + else: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + time.sleep(0.5) + if self.ADBCentralized: + if device_id == '84B7N16418004022': + self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/on"', '\$', 60) + else: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) + time.sleep(0.5) + logging.debug('\u001B[1mWait UE (' + device_id + ') a second until mDataConnectionState=2 (' + str(max_count-count) + ' times)\u001B[0m') + time.sleep(1) + if count == 0: + logging.debug('\u001B[1;37;41m UE (' + device_id + ') Attach Failed \u001B[0m') + lock.acquire() + statusQueue.put(-1) + statusQueue.put(device_id) + statusQueue.put('Attach Failed') + lock.release() + self.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def AttachUE(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + check_eNB = True + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow('N/A', 'KO', pStatus) + self.AutoTerminateUEandeNB() + return + multi_jobs = [] + status_queue = SimpleQueue() + lock = Lock() + nb_ue_to_connect = 0 + for device_id in self.UEDevices: + if (self.nbMaxUEtoAttach == -1) or (nb_ue_to_connect < self.nbMaxUEtoAttach): + self.UEDevicesStatus[nb_ue_to_connect] = UE_STATUS_ATTACHING + p = Process(target = self.AttachUE_common, args = (device_id, status_queue, lock,nb_ue_to_connect,)) + p.daemon = True + p.start() + multi_jobs.append(p) + nb_ue_to_connect = nb_ue_to_connect + 1 + for job in multi_jobs: + job.join() + + if (status_queue.empty()): + self.CreateHtmlTestRow('N/A', 'KO', ALL_PROCESSES_OK) + self.AutoTerminateUEandeNB() + return + else: + attach_status = True + html_queue = SimpleQueue() + while (not status_queue.empty()): + count = status_queue.get() + if (count < 0): + attach_status = False + device_id = status_queue.get() + message = status_queue.get() + if (count < 0): + html_cell = '
UE (' + device_id + ')\n' + message + '
' + else: + html_cell = '
UE (' + device_id + ')\n' + message + ' in ' + str(count + 2) + ' seconds
' + html_queue.put(html_cell) + if (attach_status): + # cnt from index to object of a class + self.cnt = 0 + while self.cnt < len(self.UEDevices): + if self.UEDevicesStatus[self.cnt] == UE_STATUS_ATTACHING: + self.UEDevicesStatus[self.cnt] = UE_STATUS_ATTACHED + self.cnt += 1 + self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) + result = re.search('T_stdout', str(self.Initialize_eNB_args)) + if result is not None: + logging.debug('Waiting 5 seconds to fill up record file') + time.sleep(5) + else: + self.CreateHtmlTestRowQueue('N/A', 'KO', len(self.UEDevices), html_queue) + self.AutoTerminateUEandeNB() + + def DetachUE_common(self, device_id, idx): + try: + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + if self.ADBCentralized: + if device_id == '84B7N16418004022': + self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) + else: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + logging.debug('\u001B[1mUE (' + device_id + ') Detach Completed\u001B[0m') + self.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def DetachUE(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + check_eNB = True + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow('N/A', 'KO', pStatus) + self.AutoTerminateUEandeNB() + return + multi_jobs = [] + self.cnt = 0 + for device_id in self.UEDevices: + self.UEDevicesStatus[self.cnt] = UE_STATUS_DETACHING + p = Process(target = self.DetachUE_common, args = (device_id,self.cnt,)) + p.daemon = True + p.start() + multi_jobs.append(p) + self.cnt += 1 + for job in multi_jobs: + job.join() + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + result = re.search('T_stdout', str(self.Initialize_eNB_args)) + if result is not None: + logging.debug('Waiting 5 seconds to fill up record file') + time.sleep(5) + self.cnt = 0 + while self.cnt < len(self.UEDevices): + self.UEDevicesStatus[self.cnt] = UE_STATUS_DETACHED + self.cnt += 1 + + def RebootUE_common(self, device_id): + try: + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + previousmDataConnectionStates = [] + # Save mDataConnectionState + self.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) + self.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) + result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', str(self.ssh.before)) + if result is None: + logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m') + sys.exit(1) + previousmDataConnectionStates.append(int(result.group('state'))) + # Reboot UE + self.command('stdbuf -o0 adb -s ' + device_id + ' shell reboot', '\$', 10) + time.sleep(60) + previousmDataConnectionState = previousmDataConnectionStates.pop(0) + count = 180 + while count > 0: + count = count - 1 + self.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) + result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', str(self.ssh.before)) + if result is None: + mDataConnectionState = None + else: + mDataConnectionState = int(result.group('state')) + logging.debug('mDataConnectionState = ' + result.group('state')) + if mDataConnectionState is None or (previousmDataConnectionState == 2 and mDataConnectionState != 2): + logging.debug('\u001B[1mWait UE (' + device_id + ') a second until reboot completion (' + str(180-count) + ' times)\u001B[0m') + time.sleep(1) + else: + logging.debug('\u001B[1mUE (' + device_id + ') Reboot Completed\u001B[0m') + break + if count == 0: + logging.debug('\u001B[1;37;41m UE (' + device_id + ') Reboot Failed \u001B[0m') + sys.exit(1) + self.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def RebootUE(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + check_eNB = True + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow('N/A', 'KO', pStatus) + self.CreateHtmlTabFooter(False) + sys.exit(1) + multi_jobs = [] + for device_id in self.UEDevices: + p = Process(target = self.RebootUE_common, args = (device_id,)) + p.daemon = True + p.start() + multi_jobs.append(p) + for job in multi_jobs: + job.join() + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def DataDisableUE_common(self, device_id, idx): + try: + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # disable data service + if self.ADBCentralized: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data disable"', '\$', 60) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data disable"\'', '\$', 60) + logging.debug('\u001B[1mUE (' + device_id + ') Disabled Data Service\u001B[0m') + self.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def DataDisableUE(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + multi_jobs = [] + i = 0 + for device_id in self.UEDevices: + p = Process(target = self.DataDisableUE_common, args = (device_id,i,)) + p.daemon = True + p.start() + multi_jobs.append(p) + i += 1 + for job in multi_jobs: + job.join() + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def DataEnableUE_common(self, device_id, idx): + try: + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # enable data service + if self.ADBCentralized: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data enable"', '\$', 60) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) + logging.debug('\u001B[1mUE (' + device_id + ') Enabled Data Service\u001B[0m') + self.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def DataEnableUE(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + multi_jobs = [] + i = 0 + for device_id in self.UEDevices: + p = Process(target = self.DataEnableUE_common, args = (device_id,i,)) + p.daemon = True + p.start() + multi_jobs.append(p) + i += 1 + for job in multi_jobs: + job.join() + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def GetAllUEDevices(self, terminate_ue_flag): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + if self.ADBCentralized: + self.command('adb devices', '\$', 15) + self.UEDevices = re.findall("\\\\r\\\\n([A-Za-z0-9]+)\\\\tdevice",str(self.ssh.before)) + self.close() + else: + if (os.path.isfile('./phones_list.txt')): + os.remove('./phones_list.txt') + self.command('ls /etc/*/phones*.txt', '\$', 5) + result = re.search('/etc/ci/phones_list.txt', str(self.ssh.before)) + self.close() + if (result is not None) and (len(self.UEDevices) == 0): + self.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, '/etc/ci/phones_list.txt', '.') + if (os.path.isfile('./phones_list.txt')): + phone_list_file = open('./phones_list.txt', 'r') + for line in phone_list_file.readlines(): + line = line.strip() + result = re.search('^#', line) + if result is not None: + continue + comma_split = line.split(",") + self.UEDevices.append(comma_split[0]) + self.UEDevicesRemoteServer.append(comma_split[1]) + self.UEDevicesRemoteUser.append(comma_split[2]) + self.UEDevicesOffCmd.append(comma_split[3]) + self.UEDevicesOnCmd.append(comma_split[4]) + self.UEDevicesRebootCmd.append(comma_split[5]) + phone_list_file.close() + + if terminate_ue_flag == False: + if len(self.UEDevices) == 0: + logging.debug('\u001B[1;37;41m UE Not Found! \u001B[0m') + sys.exit(1) + if len(self.UEDevicesStatus) == 0: + self.cnt = 0 + while self.cnt < len(self.UEDevices): + self.UEDevicesStatus.append(UE_STATUS_DETACHED) + self.cnt += 1 + + def GetAllCatMDevices(self, terminate_ue_flag): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + if self.ADBCentralized: + self.command('lsusb | egrep "Future Technology Devices International, Ltd FT2232C" | sed -e "s#:.*##" -e "s# #_#g"', '\$', 15) + self.CatMDevices = re.findall("\\\\r\\\\n([A-Za-z0-9_]+)",str(self.ssh.before)) + else: + if (os.path.isfile('./modules_list.txt')): + os.remove('./modules_list.txt') + self.command('ls /etc/*/modules*.txt', '\$', 5) + result = re.search('/etc/ci/modules_list.txt', str(self.ssh.before)) + self.close() + if result is not None: + logging.debug('Found a module list file on ADB server') + if terminate_ue_flag == False: + if len(self.CatMDevices) == 0: + logging.debug('\u001B[1;37;41m CAT-M UE Not Found! \u001B[0m') + sys.exit(1) + self.close() + + def CheckUEStatus_common(self, lock, device_id, statusQueue, idx): + try: + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + if self.ADBCentralized: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry"', '\$', 15) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\'', '\$', 60) + result = re.search('mServiceState=(?P[0-9]+)', str(self.ssh.before)) + serviceState = 'Service State: UNKNOWN' + if result is not None: + lServiceState = int(result.group('serviceState')) + if lServiceState == 3: + serviceState = 'Service State: RADIO_POWERED_OFF' + if lServiceState == 1: + serviceState = 'Service State: OUT_OF_SERVICE' + if lServiceState == 0: + serviceState = 'Service State: IN_SERVICE' + if lServiceState == 2: + serviceState = 'Service State: EMERGENCY_ONLY' + result = re.search('mDataConnectionState=(?P[0-9]+)', str(self.ssh.before)) + dataConnectionState = 'Data State: UNKNOWN' + if result is not None: + lDataConnectionState = int(result.group('dataConnectionState')) + if lDataConnectionState == 0: + dataConnectionState = 'Data State: DISCONNECTED' + if lDataConnectionState == 1: + dataConnectionState = 'Data State: CONNECTING' + if lDataConnectionState == 2: + dataConnectionState = 'Data State: CONNECTED' + if lDataConnectionState == 3: + dataConnectionState = 'Data State: SUSPENDED' + result = re.search('mDataConnectionReason=(?P[0-9a-zA-Z_]+)', str(self.ssh.before)) + dataConnectionReason = 'Data Reason: UNKNOWN' + if result is not None: + dataConnectionReason = 'Data Reason: ' + result.group('dataConnectionReason') + lock.acquire() + logging.debug('\u001B[1;37;44m Status Check (' + str(device_id) + ') \u001B[0m') + logging.debug('\u001B[1;34m ' + serviceState + '\u001B[0m') + logging.debug('\u001B[1;34m ' + dataConnectionState + '\u001B[0m') + logging.debug('\u001B[1;34m ' + dataConnectionReason + '\u001B[0m') + statusQueue.put(0) + statusQueue.put(device_id) + qMsg = serviceState + '\n' + dataConnectionState + '\n' + dataConnectionReason + statusQueue.put(qMsg) + lock.release() + self.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def CheckStatusUE(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + check_eNB = True + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow('N/A', 'KO', pStatus) + self.CreateHtmlTabFooter(False) + sys.exit(1) + multi_jobs = [] + lock = Lock() + status_queue = SimpleQueue() + i = 0 + for device_id in self.UEDevices: + p = Process(target = self.CheckUEStatus_common, args = (lock,device_id,status_queue,i,)) + p.daemon = True + p.start() + multi_jobs.append(p) + i += 1 + for job in multi_jobs: + job.join() + if self.flexranCtrlInstalled and self.flexranCtrlStarted: + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('cd /opt/flexran_rtc', '\$', 5) + self.command('curl http://localhost:9999/stats | jq \'.\' > log/check_status_' + self.testCase_id + '.log 2>&1', '\$', 5) + self.command('cat log/check_status_' + self.testCase_id + '.log | jq \'.eNB_config[0].UE\' | grep -c rnti | sed -e "s#^#Nb Connected UE = #"', '\$', 5) + result = re.search('Nb Connected UE = (?P[0-9]+)', str(self.ssh.before)) + passStatus = True + if result is not None: + nb_ues = int(result.group('nb_ues')) + htmlOptions = 'Nb Connected UE(s) to eNB = ' + str(nb_ues) + logging.debug('\u001B[1;37;44m ' + htmlOptions + ' \u001B[0m') + if self.expectedNbOfConnectedUEs > -1: + if nb_ues != self.expectedNbOfConnectedUEs: + passStatus = False + else: + htmlOptions = 'N/A' + self.close() + else: + passStatus = True + htmlOptions = 'N/A' + + if (status_queue.empty()): + self.CreateHtmlTestRow(htmlOptions, 'KO', ALL_PROCESSES_OK) + self.AutoTerminateUEandeNB() + else: + check_status = True + html_queue = SimpleQueue() + while (not status_queue.empty()): + count = status_queue.get() + if (count < 0): + check_status = False + device_id = status_queue.get() + message = status_queue.get() + html_cell = '
UE (' + device_id + ')\n' + message + '
' + html_queue.put(html_cell) + if check_status and passStatus: + self.CreateHtmlTestRowQueue(htmlOptions, 'OK', len(self.UEDevices), html_queue) + else: + self.CreateHtmlTestRowQueue(htmlOptions, 'KO', len(self.UEDevices), html_queue) + self.AutoTerminateUEandeNB() + + def GetAllUEIPAddresses(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + ue_ip_status = 0 + self.UEIPAddresses = [] + if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): + if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + self.command('ifconfig oaitun_ue1', '\$', 4) + result = re.search('inet addr:(?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)|inet (?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)', str(self.ssh.before)) + if result is not None: + if result.group('ueipaddress') is not None: + UE_IPAddress = result.group('ueipaddress') + else: + UE_IPAddress = result.group('ueipaddress2') + logging.debug('\u001B[1mUE (' + self.UEDevices[0] + ') IP Address is ' + UE_IPAddress + '\u001B[0m') + self.UEIPAddresses.append(UE_IPAddress) + else: + logging.debug('\u001B[1;37;41m UE IP Address Not Found! \u001B[0m') + ue_ip_status -= 1 + self.close() + return ue_ip_status + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + idx = 0 + for device_id in self.UEDevices: + if self.UEDevicesStatus[idx] != UE_STATUS_ATTACHED: + idx += 1 + continue + count = 0 + while count < 4: + if self.ADBCentralized: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell "ip addr show | grep rmnet"', '\$', 15) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ip addr show | grep rmnet"\'', '\$', 60) + result = re.search('inet (?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\/[0-9]+[0-9a-zA-Z\.\s]+', str(self.ssh.before)) + if result is None: + logging.debug('\u001B[1;37;41m UE IP Address Not Found! \u001B[0m') + time.sleep(1) + count += 1 + else: + count = 10 + if count < 9: + ue_ip_status -= 1 + continue + UE_IPAddress = result.group('ueipaddress') + logging.debug('\u001B[1mUE (' + device_id + ') IP Address is ' + UE_IPAddress + '\u001B[0m') + for ueipaddress in self.UEIPAddresses: + if ueipaddress == UE_IPAddress: + logging.debug('\u001B[1mUE (' + device_id + ') IP Address ' + UE_IPAddress + ': has already been allocated to another device !' + '\u001B[0m') + ue_ip_status -= 1 + continue + self.UEIPAddresses.append(UE_IPAddress) + idx += 1 + self.close() + return ue_ip_status + + def ping_iperf_wrong_exit(self, lock, UE_IPAddress, device_id, statusQueue, message): + lock.acquire() + statusQueue.put(-1) + statusQueue.put(device_id) + statusQueue.put(UE_IPAddress) + statusQueue.put(message) + lock.release() + + def Ping_common(self, lock, UE_IPAddress, device_id, statusQueue): + try: + # Launch ping on the EPC side (true for ltebox and old open-air-cn) + # But for OAI-Rel14-CUPS, we launch from python executor + launchFromEpc = True + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + launchFromEpc = False + ping_time = re.findall("-c (\d+)",str(self.ping_args)) + + if launchFromEpc: + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('cd ' + self.EPCSourceCodePath, '\$', 5) + self.command('cd scripts', '\$', 5) + ping_status = self.command('stdbuf -o0 ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) + else: + cmd = 'ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 > ping_' + self.testCase_id + '_' + device_id + '.log' + message = cmd + '\n' + logging.debug(cmd) + ret = subprocess.run(cmd, shell=True) + ping_status = ret.returncode + self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'ping_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('cat ' + self.EPCSourceCodePath + '/scripts/ping_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + # TIMEOUT CASE + if ping_status < 0: + message = 'Ping with UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.close() + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) + return + result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', str(self.ssh.before)) + if result is None: + message = 'Packet Loss Not Found!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.close() + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) + return + packetloss = result.group('packetloss') + if float(packetloss) == 100: + message = 'Packet Loss is 100%' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.close() + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) + return + result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', str(self.ssh.before)) + if result is None: + message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.close() + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) + return + rtt_min = result.group('rtt_min') + rtt_avg = result.group('rtt_avg') + rtt_max = result.group('rtt_max') + pal_msg = 'Packet Loss : ' + packetloss + '%' + min_msg = 'RTT(Min) : ' + rtt_min + ' ms' + avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms' + max_msg = 'RTT(Max) : ' + rtt_max + ' ms' + lock.acquire() + logging.debug('\u001B[1;37;44m ping result (' + UE_IPAddress + ') \u001B[0m') + logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') + qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg + packetLossOK = True + if packetloss is not None: + if float(packetloss) > float(self.ping_packetloss_threshold): + qMsg += '\nPacket Loss too high' + logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') + packetLossOK = False + elif float(packetloss) > 0: + qMsg += '\nPacket Loss is not 0%' + logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m') + if (packetLossOK): + statusQueue.put(0) + else: + statusQueue.put(-1) + statusQueue.put(device_id) + statusQueue.put(UE_IPAddress) + statusQueue.put(qMsg) + lock.release() + self.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def PingNoS1_wrong_exit(self, qMsg): + html_queue = SimpleQueue() + html_cell = '
OAI UE ping result\n' + qMsg + '
' + html_queue.put(html_cell) + self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) + + def PingNoS1(self): + check_eNB = True + check_OAI_UE = True + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + self.AutoTerminateUEandeNB() + return + ping_from_eNB = re.search('oaitun_enb1', str(self.ping_args)) + if ping_from_eNB is not None: + if self.eNBIPAddress == '' or self.eNBUserName == '' or self.eNBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + else: + if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': + Usage() + sys.exit('Insufficient Parameter') + try: + if ping_from_eNB is not None: + self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) + self.command('cd ' + self.eNBSourceCodePath + '/cmake_targets/', '\$', 5) + else: + self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + self.command('cd ' + self.UESourceCodePath + '/cmake_targets/', '\$', 5) + self.command('cd cmake_targets', '\$', 5) + ping_time = re.findall("-c (\d+)",str(self.ping_args)) + ping_status = self.command('stdbuf -o0 ping ' + self.ping_args + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '.log', '\$', int(ping_time[0])*1.5) + # TIMEOUT CASE + if ping_status < 0: + message = 'Ping with OAI UE crashed due to TIMEOUT!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.PingNoS1_wrong_exit(message) + return + result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', str(self.ssh.before)) + if result is None: + message = 'Packet Loss Not Found!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.PingNoS1_wrong_exit(message) + return + packetloss = result.group('packetloss') + if float(packetloss) == 100: + message = 'Packet Loss is 100%' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.PingNoS1_wrong_exit(message) + return + result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', str(self.ssh.before)) + if result is None: + message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.PingNoS1_wrong_exit(message) + return + rtt_min = result.group('rtt_min') + rtt_avg = result.group('rtt_avg') + rtt_max = result.group('rtt_max') + pal_msg = 'Packet Loss : ' + packetloss + '%' + min_msg = 'RTT(Min) : ' + rtt_min + ' ms' + avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms' + max_msg = 'RTT(Max) : ' + rtt_max + ' ms' + logging.debug('\u001B[1;37;44m OAI UE ping result \u001B[0m') + logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') + qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg + packetLossOK = True + if packetloss is not None: + if float(packetloss) > float(self.ping_packetloss_threshold): + qMsg += '\nPacket Loss too high' + logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') + packetLossOK = False + elif float(packetloss) > 0: + qMsg += '\nPacket Loss is not 0%' + logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m') + self.close() + html_queue = SimpleQueue() + ip_addr = 'TBD' + html_cell = '
OAI UE ping result\n' + qMsg + '
' + html_queue.put(html_cell) + if packetLossOK: + self.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) + else: + self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) + + # copying on the EPC server for logCollection + if ping_from_eNB is not None: + copyin_res = self.copyin(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.eNBSourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') + else: + copyin_res = self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') + if (copyin_res == 0): + self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'ping_' + self.testCase_id + '.log', self.EPCSourceCodePath + '/scripts') + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def Ping(self): + result = re.search('noS1', str(self.Initialize_eNB_args)) + if result is not None: + self.PingNoS1() + return + if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + check_eNB = True + if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): + check_OAI_UE = True + else: + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + self.AutoTerminateUEandeNB() + return + ueIpStatus = self.GetAllUEIPAddresses() + if (ueIpStatus < 0): + self.CreateHtmlTestRow(self.ping_args, 'KO', UE_IP_ADDRESS_ISSUE) + self.AutoTerminateUEandeNB() + return + multi_jobs = [] + i = 0 + lock = Lock() + status_queue = SimpleQueue() + for UE_IPAddress in self.UEIPAddresses: + device_id = self.UEDevices[i] + p = Process(target = self.Ping_common, args = (lock,UE_IPAddress,device_id,status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + i = i + 1 + for job in multi_jobs: + job.join() + + if (status_queue.empty()): + self.CreateHtmlTestRow(self.ping_args, 'KO', ALL_PROCESSES_OK) + self.AutoTerminateUEandeNB() + else: + ping_status = True + html_queue = SimpleQueue() + while (not status_queue.empty()): + count = status_queue.get() + if (count < 0): + ping_status = False + device_id = status_queue.get() + ip_addr = status_queue.get() + message = status_queue.get() + html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' + html_queue.put(html_cell) + if (ping_status): + self.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) + else: + self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) + self.AutoTerminateUEandeNB() + + def Iperf_ComputeTime(self): + result = re.search('-t (?P\d+)', str(self.iperf_args)) + if result is None: + logging.debug('\u001B[1;37;41m Iperf time Not Found! \u001B[0m') + sys.exit(1) + return result.group('iperf_time') + + def Iperf_ComputeModifiedBW(self, idx, ue_num): + result = re.search('-b (?P[0-9\.]+)[KMG]', str(self.iperf_args)) + if result is None: + logging.debug('\u001B[1;37;41m Iperf bandwidth Not Found! \u001B[0m') + sys.exit(1) + iperf_bandwidth = result.group('iperf_bandwidth') + if self.iperf_profile == 'balanced': + iperf_bandwidth_new = float(iperf_bandwidth)/ue_num + if self.iperf_profile == 'single-ue': + iperf_bandwidth_new = float(iperf_bandwidth) + if self.iperf_profile == 'unbalanced': + # residual is 2% of max bw + residualBW = float(iperf_bandwidth) / 50 + if idx == 0: + iperf_bandwidth_new = float(iperf_bandwidth) - ((ue_num - 1) * residualBW) + else: + iperf_bandwidth_new = residualBW + iperf_bandwidth_str = '-b ' + iperf_bandwidth + iperf_bandwidth_str_new = '-b ' + ('%.2f' % iperf_bandwidth_new) + result = re.sub(iperf_bandwidth_str, iperf_bandwidth_str_new, str(self.iperf_args)) + if result is None: + logging.debug('\u001B[1;37;41m Calculate Iperf bandwidth Failed! \u001B[0m') + sys.exit(1) + return result + + def Iperf_analyzeV2TCPOutput(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): + self.command('awk -f /tmp/tcp_iperf_stats.awk /tmp/CI-eNB/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + result = re.search('Avg Bitrate : (?P[0-9\.]+ Mbits\/sec) Max Bitrate : (?P[0-9\.]+ Mbits\/sec) Min Bitrate : (?P[0-9\.]+ Mbits\/sec)', str(self.ssh.before)) + if result is not None: + avgbitrate = result.group('average') + maxbitrate = result.group('maximum') + minbitrate = result.group('minimum') + lock.acquire() + logging.debug('\u001B[1;37;44m TCP iperf result (' + UE_IPAddress + ') \u001B[0m') + msg = 'TCP Stats :\n' + if avgbitrate is not None: + logging.debug('\u001B[1;34m Avg Bitrate : ' + avgbitrate + '\u001B[0m') + msg += 'Avg Bitrate : ' + avgbitrate + '\n' + if maxbitrate is not None: + logging.debug('\u001B[1;34m Max Bitrate : ' + maxbitrate + '\u001B[0m') + msg += 'Max Bitrate : ' + maxbitrate + '\n' + if minbitrate is not None: + logging.debug('\u001B[1;34m Min Bitrate : ' + minbitrate + '\u001B[0m') + msg += 'Min Bitrate : ' + minbitrate + '\n' + statusQueue.put(0) + statusQueue.put(device_id) + statusQueue.put(UE_IPAddress) + statusQueue.put(msg) + lock.release() + return 0 + + def Iperf_analyzeV2Output(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): + result = re.search('-u', str(iperf_real_options)) + if result is None: + return self.Iperf_analyzeV2TCPOutput(lock, UE_IPAddress, device_id, statusQueue, iperf_real_options) + + result = re.search('Server Report:', str(self.ssh.before)) + if result is None: + result = re.search('read failed: Connection refused', str(self.ssh.before)) + if result is not None: + logging.debug('\u001B[1;37;41m Could not connect to iperf server! \u001B[0m') + else: + logging.debug('\u001B[1;37;41m Server Report and Connection refused Not Found! \u001B[0m') + return -1 + # Computing the requested bandwidth in float + result = re.search('-b (?P[0-9\.]+)[KMG]', str(iperf_real_options)) + if result is not None: + req_bandwidth = result.group('iperf_bandwidth') + req_bw = float(req_bandwidth) + result = re.search('-b [0-9\.]+K', str(iperf_real_options)) + if result is not None: + req_bandwidth = '%.1f Kbits/sec' % req_bw + req_bw = req_bw * 1000 + result = re.search('-b [0-9\.]+M', str(iperf_real_options)) + if result is not None: + req_bandwidth = '%.1f Mbits/sec' % req_bw + req_bw = req_bw * 1000000 + result = re.search('-b [0-9\.]+G', str(iperf_real_options)) + if result is not None: + req_bandwidth = '%.1f Gbits/sec' % req_bw + req_bw = req_bw * 1000000000 + + result = re.search('Server Report:\\\\r\\\\n(?:|\[ *\d+\].*) (?P[0-9\.]+ [KMG]bits\/sec) +(?P[0-9\.]+ ms) +(\d+\/..\d+) +(\((?P[0-9\.]+)%\))', str(self.ssh.before)) + if result is not None: + bitrate = result.group('bitrate') + packetloss = result.group('packetloss') + jitter = result.group('jitter') + lock.acquire() + logging.debug('\u001B[1;37;44m iperf result (' + UE_IPAddress + ') \u001B[0m') + iperfStatus = True + msg = 'Req Bitrate : ' + req_bandwidth + '\n' + logging.debug('\u001B[1;34m Req Bitrate : ' + req_bandwidth + '\u001B[0m') + if bitrate is not None: + msg += 'Bitrate : ' + bitrate + '\n' + logging.debug('\u001B[1;34m Bitrate : ' + bitrate + '\u001B[0m') + result = re.search('(?P[0-9\.]+) [KMG]bits/sec', str(bitrate)) + if result is not None: + actual_bw = float(str(result.group('real_bw'))) + result = re.search('[0-9\.]+ K', bitrate) + if result is not None: + actual_bw = actual_bw * 1000 + result = re.search('[0-9\.]+ M', bitrate) + if result is not None: + actual_bw = actual_bw * 1000000 + result = re.search('[0-9\.]+ G', bitrate) + if result is not None: + actual_bw = actual_bw * 1000000000 + br_loss = 100 * actual_bw / req_bw + bitperf = '%.2f ' % br_loss + msg += 'Bitrate Perf: ' + bitperf + '%\n' + logging.debug('\u001B[1;34m Bitrate Perf: ' + bitperf + '%\u001B[0m') + if packetloss is not None: + msg += 'Packet Loss : ' + packetloss + '%\n' + logging.debug('\u001B[1;34m Packet Loss : ' + packetloss + '%\u001B[0m') + if float(packetloss) > float(self.iperf_packetloss_threshold): + msg += 'Packet Loss too high!\n' + logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') + iperfStatus = False + if jitter is not None: + msg += 'Jitter : ' + jitter + '\n' + logging.debug('\u001B[1;34m Jitter : ' + jitter + '\u001B[0m') + if (iperfStatus): + statusQueue.put(0) + else: + statusQueue.put(-1) + statusQueue.put(device_id) + statusQueue.put(UE_IPAddress) + statusQueue.put(msg) + lock.release() + return 0 + else: + return -2 + + def Iperf_analyzeV2Server(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): + if (not os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not analyze from server log') + return + # Computing the requested bandwidth in float + result = re.search('-b (?P[0-9\.]+)[KMG]', str(iperf_real_options)) + if result is None: + logging.debug('Iperf bandwidth Not Found!') + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not compute Iperf bandwidth!') + return + else: + req_bandwidth = result.group('iperf_bandwidth') + req_bw = float(req_bandwidth) + result = re.search('-b [0-9\.]+K', str(iperf_real_options)) + if result is not None: + req_bandwidth = '%.1f Kbits/sec' % req_bw + req_bw = req_bw * 1000 + result = re.search('-b [0-9\.]+M', str(iperf_real_options)) + if result is not None: + req_bandwidth = '%.1f Mbits/sec' % req_bw + req_bw = req_bw * 1000000 + result = re.search('-b [0-9\.]+G', str(iperf_real_options)) + if result is not None: + req_bandwidth = '%.1f Gbits/sec' % req_bw + req_bw = req_bw * 1000000000 + + server_file = open('iperf_server_' + self.testCase_id + '_' + device_id + '.log', 'r') + br_sum = 0.0 + ji_sum = 0.0 + pl_sum = 0 + ps_sum = 0 + row_idx = 0 + for line in server_file.readlines(): + result = re.search('(?P[0-9\.]+ [KMG]bits\/sec) +(?P[0-9\.]+ ms) +(?P[0-9]+)/ +(?P[0-9]+)', str(line)) + if result is not None: + bitrate = result.group('bitrate') + jitter = result.group('jitter') + packetlost = result.group('lostPack') + packetsent = result.group('sentPack') + br = bitrate.split(' ') + ji = jitter.split(' ') + row_idx = row_idx + 1 + curr_br = float(br[0]) + pl_sum = pl_sum + int(packetlost) + ps_sum = ps_sum + int(packetsent) + if (br[1] == 'Kbits/sec'): + curr_br = curr_br * 1000 + if (br[1] == 'Mbits/sec'): + curr_br = curr_br * 1000 * 1000 + br_sum = curr_br + br_sum + ji_sum = float(ji[0]) + ji_sum + if (row_idx > 0): + br_sum = br_sum / row_idx + ji_sum = ji_sum / row_idx + br_loss = 100 * br_sum / req_bw + if (br_sum > 1000): + br_sum = br_sum / 1000 + if (br_sum > 1000): + br_sum = br_sum / 1000 + bitrate = '%.2f Mbits/sec' % br_sum + else: + bitrate = '%.2f Kbits/sec' % br_sum + else: + bitrate = '%.2f bits/sec' % br_sum + bitperf = '%.2f ' % br_loss + bitperf += '%' + jitter = '%.2f ms' % (ji_sum) + if (ps_sum > 0): + pl = float(100 * pl_sum / ps_sum) + packetloss = '%2.1f ' % (pl) + packetloss += '%' + else: + packetloss = 'unknown' + lock.acquire() + if (br_loss < 90): + statusQueue.put(1) + else: + statusQueue.put(0) + statusQueue.put(device_id) + statusQueue.put(UE_IPAddress) + req_msg = 'Req Bitrate : ' + req_bandwidth + bir_msg = 'Bitrate : ' + bitrate + brl_msg = 'Bitrate Perf: ' + bitperf + jit_msg = 'Jitter : ' + jitter + pal_msg = 'Packet Loss : ' + packetloss + statusQueue.put(req_msg + '\n' + bir_msg + '\n' + brl_msg + '\n' + jit_msg + '\n' + pal_msg + '\n') + logging.debug('\u001B[1;37;45m iperf result (' + UE_IPAddress + ') \u001B[0m') + logging.debug('\u001B[1;35m ' + req_msg + '\u001B[0m') + logging.debug('\u001B[1;35m ' + bir_msg + '\u001B[0m') + logging.debug('\u001B[1;35m ' + brl_msg + '\u001B[0m') + logging.debug('\u001B[1;35m ' + jit_msg + '\u001B[0m') + logging.debug('\u001B[1;35m ' + pal_msg + '\u001B[0m') + lock.release() + else: + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not analyze from server log') + + server_file.close() + + + def Iperf_analyzeV3Output(self, lock, UE_IPAddress, device_id, statusQueue): + result = re.search('(?P[0-9\.]+ [KMG]bits\/sec) +(?:|[0-9\.]+ ms +\d+\/\d+ \((?P[0-9\.]+)%\)) +(?:|receiver)\\\\r\\\\n(?:|\[ *\d+\] Sent \d+ datagrams)\\\\r\\\\niperf Done\.', str(self.ssh.before)) + if result is None: + result = re.search('(?Piperf: error - [a-zA-Z0-9 :]+)', str(self.ssh.before)) + lock.acquire() + statusQueue.put(-1) + statusQueue.put(device_id) + statusQueue.put(UE_IPAddress) + if result is not None: + logging.debug('\u001B[1;37;41m ' + result.group('error') + ' \u001B[0m') + statusQueue.put(result.group('error')) + else: + logging.debug('\u001B[1;37;41m Bitrate and/or Packet Loss Not Found! \u001B[0m') + statusQueue.put('Bitrate and/or Packet Loss Not Found!') + lock.release() + + bitrate = result.group('bitrate') + packetloss = result.group('packetloss') + lock.acquire() + logging.debug('\u001B[1;37;44m iperf result (' + UE_IPAddress + ') \u001B[0m') + logging.debug('\u001B[1;34m Bitrate : ' + bitrate + '\u001B[0m') + msg = 'Bitrate : ' + bitrate + '\n' + iperfStatus = True + if packetloss is not None: + logging.debug('\u001B[1;34m Packet Loss : ' + packetloss + '%\u001B[0m') + msg += 'Packet Loss : ' + packetloss + '%\n' + if float(packetloss) > float(self.iperf_packetloss_threshold): + logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') + msg += 'Packet Loss too high!\n' + iperfStatus = False + if (iperfStatus): + statusQueue.put(0) + else: + statusQueue.put(-1) + statusQueue.put(device_id) + statusQueue.put(UE_IPAddress) + statusQueue.put(msg) + lock.release() + + def Iperf_UL_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue): + udpIperf = True + result = re.search('-u', str(self.iperf_args)) + if result is None: + udpIperf = False + ipnumbers = UE_IPAddress.split('.') + if (len(ipnumbers) == 4): + ipnumbers[3] = '1' + EPC_Iperf_UE_IPAddress = ipnumbers[0] + '.' + ipnumbers[1] + '.' + ipnumbers[2] + '.' + ipnumbers[3] + + # Launch iperf server on EPC side (true for ltebox and old open-air-cn0 + # But for OAI-Rel14-CUPS, we launch from python executor and we are using its IP address as iperf client address + launchFromEpc = True + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + launchFromEpc = False + cmd = 'hostname -I' + ret = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, encoding='utf-8') + if ret.stdout is not None: + EPC_Iperf_UE_IPAddress = ret.stdout.strip() + port = 5001 + idx + if launchFromEpc: + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + if udpIperf: + self.command('echo $USER; nohup iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.EPCUserName, 5) + else: + self.command('echo $USER; nohup iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.EPCUserName, 5) + self.close() + else: + if self.ueIperfVersion == self.dummyIperfVersion: + prefix = '' + else: + prefix = '' + if self.ueIperfVersion == '2.0.5': + prefix = '/opt/iperf-2.0.5/bin/' + if udpIperf: + cmd = 'nohup ' + prefix + 'iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log 2>&1 &' + else: + cmd = 'nohup ' + prefix + 'iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log 2>&1 &' + logging.debug(cmd) + subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, encoding='utf-8') + time.sleep(0.5) + + # Launch iperf client on UE + if (device_id == 'OAI-UE'): + self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + self.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) + else: + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + iperf_time = self.Iperf_ComputeTime() + time.sleep(0.5) + + if udpIperf: + modified_options = self.Iperf_ComputeModifiedBW(idx, ue_num) + else: + modified_options = str(self.iperf_args) + modified_options = modified_options.replace('-R','') + time.sleep(0.5) + + self.command('rm -f iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + if (device_id == 'OAI-UE'): + iperf_status = self.command('iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + ' -B ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + else: + if self.ADBCentralized: + iperf_status = self.command('stdbuf -o0 adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '" 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + else: + iperf_status = self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '"\' 2>&1 > iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + self.command('fromdos -o iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + self.command('cat iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + # TIMEOUT Case + if iperf_status < 0: + self.close() + message = 'iperf on UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT !' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.close() + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) + return + clientStatus = self.Iperf_analyzeV2Output(lock, UE_IPAddress, device_id, statusQueue, modified_options) + self.close() + + # Kill iperf server on EPC side + if launchFromEpc: + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('killall --signal SIGKILL iperf', self.EPCUserName, 5) + self.close() + else: + cmd = 'killall --signal SIGKILL iperf' + logging.debug(cmd) + subprocess.run(cmd, shell=True) + time.sleep(1) + self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') + # in case of failure, retrieve server log + if (clientStatus == -1) or (clientStatus == -2): + if launchFromEpc: + time.sleep(1) + if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): + os.remove('iperf_server_' + self.testCase_id + '_' + device_id + '.log') + self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, self.EPCSourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) + # in case of OAI-UE + if (device_id == 'OAI-UE'): + self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_' + self.testCase_id + '_' + device_id + '.log', '.') + self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') + + def Iperf_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue): + try: + # Single-UE profile -- iperf only on one UE + if self.iperf_profile == 'single-ue' and idx != 0: + return + useIperf3 = False + udpIperf = True + + self.ueIperfVersion = '2.0.5' + if (device_id != 'OAI-UE'): + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # if by chance ADB server and EPC are on the same remote host, at least log collection will take care of it + self.command('if [ ! -d ' + self.EPCSourceCodePath + '/scripts ]; then mkdir -p ' + self.EPCSourceCodePath + '/scripts ; fi', '\$', 5) + self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + # Checking if iperf / iperf3 are installed + if self.ADBCentralized: + self.command('adb -s ' + device_id + ' shell "ls /data/local/tmp"', '\$', 5) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ls /data/local/tmp"\'', '\$', 60) + result = re.search('iperf3', str(self.ssh.before)) + if result is None: + result = re.search('iperf', str(self.ssh.before)) + if result is None: + message = 'Neither iperf nor iperf3 installed on UE!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.close() + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) + return + else: + if self.ADBCentralized: + self.command('adb -s ' + device_id + ' shell "/data/local/tmp/iperf --version"', '\$', 5) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf --version"\'', '\$', 60) + result = re.search('iperf version 2.0.5', str(self.ssh.before)) + if result is not None: + self.ueIperfVersion = '2.0.5' + result = re.search('iperf version 2.0.10', str(self.ssh.before)) + if result is not None: + self.ueIperfVersion = '2.0.10' + else: + useIperf3 = True + self.close() + else: + self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + self.command('iperf --version', '\$', 5) + result = re.search('iperf version 2.0.5', str(self.ssh.before)) + if result is not None: + self.ueIperfVersion = '2.0.5' + result = re.search('iperf version 2.0.10', str(self.ssh.before)) + if result is not None: + self.ueIperfVersion = '2.0.10' + self.close() + # in case of iperf, UL has its own function + if (not useIperf3): + result = re.search('-R', str(self.iperf_args)) + if result is not None: + self.Iperf_UL_common(lock, UE_IPAddress, device_id, idx, ue_num, statusQueue) + return + + # Launch the IPERF server on the UE side for DL + if (device_id == 'OAI-UE'): + self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + self.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) + self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + result = re.search('-u', str(self.iperf_args)) + if result is None: + self.command('echo $USER; nohup iperf -B ' + UE_IPAddress + ' -s -i 1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.UEUserName, 5) + udpIperf = False + else: + self.command('echo $USER; nohup iperf -B ' + UE_IPAddress + ' -u -s -i 1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.UEUserName, 5) + else: + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + if self.ADBCentralized: + if (useIperf3): + self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/iperf3 -s &', '\$', 5) + else: + self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + result = re.search('-u', str(self.iperf_args)) + if result is None: + self.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) + udpIperf = False + else: + self.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) + else: + self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + self.command('echo $USER; nohup ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" \' 2>&1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 60) + + time.sleep(0.5) + self.close() + + # Launch the IPERF client on the EPC side for DL (true for ltebox and old open-air-cn + # But for OAI-Rel14-CUPS, we launch from python executor + launchFromEpc = True + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + launchFromEpc = False + if launchFromEpc: + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + iperf_time = self.Iperf_ComputeTime() + time.sleep(0.5) + + if udpIperf: + modified_options = self.Iperf_ComputeModifiedBW(idx, ue_num) + else: + modified_options = str(self.iperf_args) + time.sleep(0.5) + + if launchFromEpc: + self.command('rm -f iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + else: + if (os.path.isfile('iperf_' + self.testCase_id + '_' + device_id + '.log')): + os.remove('iperf_' + self.testCase_id + '_' + device_id + '.log') + if (useIperf3): + self.command('stdbuf -o0 iperf3 -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + + clientStatus = 0 + self.Iperf_analyzeV3Output(lock, UE_IPAddress, device_id, statusQueue) + else: + if launchFromEpc: + iperf_status = self.command('stdbuf -o0 iperf -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + else: + if self.ueIperfVersion == self.dummyIperfVersion: + prefix = '' + else: + prefix = '' + if self.ueIperfVersion == '2.0.5': + prefix = '/opt/iperf-2.0.5/bin/' + cmd = prefix + 'iperf -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 > iperf_' + self.testCase_id + '_' + device_id + '.log' + message = cmd + '\n' + logging.debug(cmd) + ret = subprocess.run(cmd, shell=True) + iperf_status = ret.returncode + self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('cat ' + self.EPCSourceCodePath + '/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + if iperf_status < 0: + if launchFromEpc: + self.close() + message = 'iperf on UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT !' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) + return + clientStatus = self.Iperf_analyzeV2Output(lock, UE_IPAddress, device_id, statusQueue, modified_options) + self.close() + + # Kill the IPERF server that runs in background + if (device_id == 'OAI-UE'): + self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + self.command('killall iperf', '\$', 5) + else: + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + if self.ADBCentralized: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell ps | grep --color=never iperf | grep -v grep', '\$', 5) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ps" | grep --color=never iperf | grep -v grep\'', '\$', 60) + result = re.search('shell +(?P\d+)', str(self.ssh.before)) + if result is not None: + pid_iperf = result.group('pid') + if self.ADBCentralized: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell kill -KILL ' + pid_iperf, '\$', 5) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"\'', '\$', 60) + self.close() + # if the client report is absent, try to analyze the server log file + if (clientStatus == -1): + time.sleep(1) + if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): + os.remove('iperf_server_' + self.testCase_id + '_' + device_id + '.log') + if (device_id == 'OAI-UE'): + self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + else: + self.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, self.EPCSourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + self.command('fromdos -o iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) + + # in case of OAI UE: + if (device_id == 'OAI-UE'): + if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): + if not launchFromEpc: + self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') + else: + self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def IperfNoS1(self): + if self.eNBIPAddress == '' or self.eNBUserName == '' or self.eNBPassword == '' or self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': + Usage() + sys.exit('Insufficient Parameter') + check_eNB = True + check_OAI_UE = True + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) + self.AutoTerminateUEandeNB() + return + server_on_enb = re.search('-R', str(self.iperf_args)) + if server_on_enb is not None: + iServerIPAddr = self.eNBIPAddress + iServerUser = self.eNBUserName + iServerPasswd = self.eNBPassword + iClientIPAddr = self.UEIPAddress + iClientUser = self.UEUserName + iClientPasswd = self.UEPassword + else: + iServerIPAddr = self.UEIPAddress + iServerUser = self.UEUserName + iServerPasswd = self.UEPassword + iClientIPAddr = self.eNBIPAddress + iClientUser = self.eNBUserName + iClientPasswd = self.eNBPassword + # Starting the iperf server + self.open(iServerIPAddr, iServerUser, iServerPasswd) + # args SHALL be "-c client -u any" + # -c 10.0.1.2 -u -b 1M -t 30 -i 1 -fm -B 10.0.1.1 + # -B 10.0.1.1 -u -s -i 1 -fm + server_options = re.sub('-u.*$', '-u -s -i 1 -fm', str(self.iperf_args)) + server_options = server_options.replace('-c','-B') + self.command('rm -f /tmp/tmp_iperf_server_' + self.testCase_id + '.log', '\$', 5) + self.command('echo $USER; nohup iperf ' + server_options + ' > /tmp/tmp_iperf_server_' + self.testCase_id + '.log 2>&1 &', iServerUser, 5) + time.sleep(0.5) + self.close() + + # Starting the iperf client + modified_options = self.Iperf_ComputeModifiedBW(0, 1) + modified_options = modified_options.replace('-R','') + iperf_time = self.Iperf_ComputeTime() + self.open(iClientIPAddr, iClientUser, iClientPasswd) + self.command('rm -f /tmp/tmp_iperf_' + self.testCase_id + '.log', '\$', 5) + iperf_status = self.command('stdbuf -o0 iperf ' + modified_options + ' 2>&1 | stdbuf -o0 tee /tmp/tmp_iperf_' + self.testCase_id + '.log', '\$', int(iperf_time)*5.0) + status_queue = SimpleQueue() + lock = Lock() + if iperf_status < 0: + message = 'iperf on OAI UE crashed due to TIMEOUT !' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + clientStatus = -2 + else: + clientStatus = self.Iperf_analyzeV2Output(lock, '10.0.1.2', 'OAI-UE', status_queue, modified_options) + self.close() + + # Stopping the iperf server + self.open(iServerIPAddr, iServerUser, iServerPasswd) + self.command('killall --signal SIGKILL iperf', '\$', 5) + time.sleep(0.5) + self.close() + if (clientStatus == -1): + if (os.path.isfile('iperf_server_' + self.testCase_id + '.log')): + os.remove('iperf_server_' + self.testCase_id + '.log') + self.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log') + self.Iperf_analyzeV2Server(lock, '10.0.1.2', 'OAI-UE', status_queue, modified_options) + + # copying on the EPC server for logCollection + copyin_res = self.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log') + if (copyin_res == 0): + self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_OAI-UE.log', self.EPCSourceCodePath + '/scripts') + copyin_res = self.copyin(iClientIPAddr, iClientUser, iClientPasswd, '/tmp/tmp_iperf_' + self.testCase_id + '.log', 'iperf_' + self.testCase_id + '_OAI-UE.log') + if (copyin_res == 0): + self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_' + self.testCase_id + '_OAI-UE.log', self.EPCSourceCodePath + '/scripts') + iperf_noperf = False + if status_queue.empty(): + iperf_status = False + else: + iperf_status = True + html_queue = SimpleQueue() + while (not status_queue.empty()): + count = status_queue.get() + if (count < 0): + iperf_status = False + if (count > 0): + iperf_noperf = True + device_id = status_queue.get() + ip_addr = status_queue.get() + message = status_queue.get() + html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' + html_queue.put(html_cell) + if (iperf_noperf and iperf_status): + self.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) + elif (iperf_status): + self.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) + else: + self.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) + self.AutoTerminateUEandeNB() + + def Iperf(self): + result = re.search('noS1', str(self.Initialize_eNB_args)) + if result is not None: + self.IperfNoS1() + return + if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + check_eNB = True + if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): + check_OAI_UE = True + else: + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) + self.AutoTerminateUEandeNB() + return + ueIpStatus = self.GetAllUEIPAddresses() + if (ueIpStatus < 0): + self.CreateHtmlTestRow(self.iperf_args, 'KO', UE_IP_ADDRESS_ISSUE) + self.AutoTerminateUEandeNB() + return + + self.dummyIperfVersion = '2.0.10' + #cmd = 'iperf --version' + #logging.debug(cmd + '\n') + #iperfStdout = subprocess.check_output(cmd, shell=True, universal_newlines=True) + #result = re.search('iperf version 2.0.5', str(iperfStdout.strip())) + #if result is not None: + # dummyIperfVersion = '2.0.5' + #result = re.search('iperf version 2.0.10', str(iperfStdout.strip())) + #if result is not None: + # dummyIperfVersion = '2.0.10' + + multi_jobs = [] + i = 0 + ue_num = len(self.UEIPAddresses) + lock = Lock() + status_queue = SimpleQueue() + for UE_IPAddress in self.UEIPAddresses: + device_id = self.UEDevices[i] + p = Process(target = SSH.Iperf_common, args = (lock,UE_IPAddress,device_id,i,ue_num,status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + i = i + 1 + for job in multi_jobs: + job.join() + + if (status_queue.empty()): + self.CreateHtmlTestRow(self.iperf_args, 'KO', ALL_PROCESSES_OK) + self.AutoTerminateUEandeNB() + else: + iperf_status = True + iperf_noperf = False + html_queue = SimpleQueue() + while (not status_queue.empty()): + count = status_queue.get() + if (count < 0): + iperf_status = False + if (count > 0): + iperf_noperf = True + device_id = status_queue.get() + ip_addr = status_queue.get() + message = status_queue.get() + html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' + html_queue.put(html_cell) + if (iperf_noperf and iperf_status): + self.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) + elif (iperf_status): + self.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) + else: + self.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) + self.AutoTerminateUEandeNB() + + def CheckProcessExist(self, check_eNB, check_OAI_UE): + multi_jobs = [] + status_queue = SimpleQueue() + # in noS1 config, no need to check status from EPC + result = re.search('noS1', str(self.Initialize_eNB_args)) + if result is None: + p = Process(target = SSH.CheckHSSProcess, args = (status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + p = Process(target = SSH.CheckMMEProcess, args = (status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + p = Process(target = SSH.CheckSPGWProcess, args = (status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + else: + if (check_eNB == False) and (check_OAI_UE == False): + return 0 + if check_eNB: + p = Process(target = SSH.CheckeNBProcess, args = (status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + if check_OAI_UE: + p = Process(target = SSH.CheckOAIUEProcess, args = (status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + for job in multi_jobs: + job.join() + + if (status_queue.empty()): + return -15 + else: + result = 0 + while (not status_queue.empty()): + status = status_queue.get() + if (status < 0): + result = status + if result == ENB_PROCESS_FAILED: + fileCheck = re.search('enb_', str(self.eNBLogFiles[0])) + if fileCheck is not None: + self.copyin(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.eNBSourceCodePath + '/cmake_targets/' + self.eNBLogFiles[0], '.') + logStatus = self.AnalyzeLogFile_eNB(self.eNBLogFiles[0]) + if logStatus < 0: + result = logStatus + self.eNBLogFiles[0] = '' + if self.flexranCtrlInstalled and self.flexranCtrlStarted: + self.TerminateFlexranCtrl() + return result + + def CheckOAIUEProcessExist(self, initialize_OAI_UE_flag): + multi_jobs = [] + status_queue = SimpleQueue() + if initialize_OAI_UE_flag == False: + p = Process(target = SSH.CheckOAIUEProcess, args = (status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + for job in multi_jobs: + job.join() + + if (status_queue.empty()): + return -15 + else: + result = 0 + while (not status_queue.empty()): + status = status_queue.get() + if (status < 0): + result = status + if result == OAI_UE_PROCESS_FAILED: + fileCheck = re.search('ue_', str(self.UELogFile)) + if fileCheck is not None: + self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.') + logStatus = self.AnalyzeLogFile_UE(self.UELogFile) + if logStatus < 0: + result = logStatus + return result + + def CheckOAIUEProcess(self, status_queue): + try: + self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + self.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + result = re.search('lte-uesoftmodem', str(self.ssh.before)) + if result is None: + logging.debug('\u001B[1;37;41m OAI UE Process Not Found! \u001B[0m') + status_queue.put(OAI_UE_PROCESS_FAILED) + else: + status_queue.put(OAI_UE_PROCESS_OK) + self.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def CheckeNBProcess(self, status_queue): + try: + self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) + self.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + result = re.search('lte-softmodem', str(self.ssh.before)) + if result is None: + logging.debug('\u001B[1;37;41m eNB Process Not Found! \u001B[0m') + status_queue.put(ENB_PROCESS_FAILED) + else: + status_queue.put(ENB_PROCESS_OK) + self.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def CheckHSSProcess(self, status_queue): + try: + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('stdbuf -o0 ps -aux | grep --color=never hss | grep -v grep', '\$', 5) + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + result = re.search('oai_hss -j', str(self.ssh.before)) + elif re.match('OAI', self.EPCType, re.IGNORECASE): + result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + result = re.search('hss_sim s6as diam_hss', str(self.ssh.before)) + else: + logging.error('This should not happen!') + if result is None: + logging.debug('\u001B[1;37;41m HSS Process Not Found! \u001B[0m') + status_queue.put(HSS_PROCESS_FAILED) + else: + status_queue.put(HSS_PROCESS_OK) + self.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def CheckMMEProcess(self, status_queue): + try: + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('stdbuf -o0 ps -aux | grep --color=never mme | grep -v grep', '\$', 5) + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + result = re.search('mme -c', str(self.ssh.before)) + elif re.match('OAI', self.EPCType, re.IGNORECASE): + result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + result = re.search('mme', str(self.ssh.before)) + else: + logging.error('This should not happen!') + if result is None: + logging.debug('\u001B[1;37;41m MME Process Not Found! \u001B[0m') + status_queue.put(MME_PROCESS_FAILED) + else: + status_queue.put(MME_PROCESS_OK) + self.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def CheckSPGWProcess(self, status_queue): + try: + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + self.command('stdbuf -o0 ps -aux | grep --color=never spgw | grep -v grep', '\$', 5) + result = re.search('spgwu -c ', str(self.ssh.before)) + elif re.match('OAI', self.EPCType, re.IGNORECASE): + self.command('stdbuf -o0 ps -aux | grep --color=never spgw | grep -v grep', '\$', 5) + result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + self.command('stdbuf -o0 ps -aux | grep --color=never xGw | grep -v grep', '\$', 5) + result = re.search('xGw', str(self.ssh.before)) + else: + logging.error('This should not happen!') + if result is None: + logging.debug('\u001B[1;37;41m SPGW Process Not Found! \u001B[0m') + status_queue.put(SPGW_PROCESS_FAILED) + else: + status_queue.put(SPGW_PROCESS_OK) + self.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def AnalyzeLogFile_eNB(self, eNBlogFile): + if (not os.path.isfile('./' + eNBlogFile)): + return -1 + enb_log_file = open('./' + eNBlogFile, 'r') + exitSignalReceived = False + foundAssertion = False + msgAssertion = '' + msgLine = 0 + foundSegFault = False + foundRealTimeIssue = False + rrcSetupComplete = 0 + rrcReleaseRequest = 0 + rrcReconfigRequest = 0 + rrcReconfigComplete = 0 + rrcReestablishRequest = 0 + rrcReestablishComplete = 0 + rrcReestablishReject = 0 + rlcDiscardBuffer = 0 + rachCanceledProcedure = 0 + uciStatMsgCount = 0 + pdcpFailure = 0 + ulschFailure = 0 + cdrxActivationMessageCount = 0 + dropNotEnoughRBs = 0 + self.htmleNBFailureMsg = '' + isRRU = False + isSlave = False + slaveReceivesFrameResyncCmd = False + X2HO_state = X2_HO_REQ_STATE__IDLE + X2HO_inNbProcedures = 0 + X2HO_outNbProcedures = 0 + for line in enb_log_file.readlines(): + if X2HO_state == X2_HO_REQ_STATE__IDLE: + result = re.search('target eNB Receives X2 HO Req X2AP_HANDOVER_REQ', str(line)) + if result is not None: + X2HO_state = X2_HO_REQ_STATE__TARGET_RECEIVES_REQ + result = re.search('source eNB receives the X2 HO ACK X2AP_HANDOVER_REQ_ACK', str(line)) + if result is not None: + X2HO_state = X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK + if X2HO_state == X2_HO_REQ_STATE__TARGET_RECEIVES_REQ: + result = re.search('Received LTE_RRCConnectionReconfigurationComplete from UE', str(line)) + if result is not None: + X2HO_state = X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE + if X2HO_state == X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE: + result = re.search('issue rrc_eNB_send_PATH_SWITCH_REQ', str(line)) + if result is not None: + X2HO_state = X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ + if X2HO_state == X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ: + result = re.search('received path switch ack S1AP_PATH_SWITCH_REQ_ACK', str(line)) + if result is not None: + X2HO_state = X2_HO_REQ_STATE__IDLE + X2HO_inNbProcedures += 1 + if X2HO_state == X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK: + result = re.search('source eNB receives the X2 UE CONTEXT RELEASE X2AP_UE_CONTEXT_RELEASE', str(line)) + if result is not None: + X2HO_state = X2_HO_REQ_STATE__IDLE + X2HO_outNbProcedures += 1 + + if self.eNBOptions[int(self.eNB_instance)] != '': + res1 = re.search('max_rxgain (?P[0-9]+)', self.eNBOptions[int(self.eNB_instance)]) + res2 = re.search('max_rxgain (?P[0-9]+)', str(line)) + if res1 is not None and res2 is not None: + requested_option = int(res1.group('requested_option')) + applied_option = int(res2.group('applied_option')) + if requested_option == applied_option: + self.htmleNBFailureMsg += ' Command line option(s) correctly applied ' + self.eNBOptions[int(self.eNB_instance)] + '\n\n' + else: + self.htmleNBFailureMsg += ' Command line option(s) NOT applied ' + self.eNBOptions[int(self.eNB_instance)] + '\n\n' + result = re.search('Exiting OAI softmodem', str(line)) + if result is not None: + exitSignalReceived = True + result = re.search('[Ss]egmentation [Ff]ault', str(line)) + 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)) + if result is not None and not exitSignalReceived: + foundAssertion = True + result = re.search('LLL', str(line)) + if result is not None and not exitSignalReceived: + foundRealTimeIssue = True + if foundAssertion and (msgLine < 3): + msgLine += 1 + msgAssertion += str(line) + result = re.search('Setting function for RU', str(line)) + if result is not None: + isRRU = True + if isRRU: + result = re.search('RU 0 is_slave=yes', str(line)) + if result is not None: + isSlave = True + if isSlave: + result = re.search('Received RRU_frame_resynch command', str(line)) + if result is not None: + slaveReceivesFrameResyncCmd = True + result = re.search('LTE_RRCConnectionSetupComplete from UE', str(line)) + if result is not None: + rrcSetupComplete += 1 + result = re.search('Generate LTE_RRCConnectionRelease|Generate RRCConnectionRelease', str(line)) + if result is not None: + rrcReleaseRequest += 1 + result = re.search('Generate LTE_RRCConnectionReconfiguration', str(line)) + if result is not None: + rrcReconfigRequest += 1 + result = re.search('LTE_RRCConnectionReconfigurationComplete from UE rnti', str(line)) + if result is not None: + rrcReconfigComplete += 1 + result = re.search('LTE_RRCConnectionReestablishmentRequest', str(line)) + if result is not None: + rrcReestablishRequest += 1 + result = re.search('LTE_RRCConnectionReestablishmentComplete', str(line)) + if result is not None: + rrcReestablishComplete += 1 + result = re.search('LTE_RRCConnectionReestablishmentReject', str(line)) + if result is not None: + rrcReestablishReject += 1 + result = re.search('CDRX configuration activated after RRC Connection', str(line)) + if result is not None: + cdrxActivationMessageCount += 1 + result = re.search('uci->stat', str(line)) + if result is not None: + uciStatMsgCount += 1 + result = re.search('PDCP.*Out of Resources.*reason', str(line)) + if result is not None: + pdcpFailure += 1 + result = re.search('ULSCH in error in round', str(line)) + if result is not None: + ulschFailure += 1 + result = re.search('BAD all_segments_received', str(line)) + if result is not None: + rlcDiscardBuffer += 1 + 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: + statMsg = 'eNB showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + self.htmleNBFailureMsg += statMsg + '\n' + if pdcpFailure > 0: + statMsg = 'eNB showed ' + str(pdcpFailure) + ' "PDCP Out of Resources" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + self.htmleNBFailureMsg += statMsg + '\n' + if ulschFailure > 0: + 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') + self.htmleNBFailureMsg += rrcMsg + '\n' + if rrcReleaseRequest > 0: + rrcMsg = 'eNB requested ' + str(rrcReleaseRequest) + ' RRC Connection Release(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + if rrcReconfigRequest > 0 or rrcReconfigComplete > 0: + rrcMsg = 'eNB requested ' + str(rrcReconfigRequest) + ' RRC Connection Reconfiguration(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + rrcMsg = ' -- ' + str(rrcReconfigComplete) + ' were completed' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + if rrcReestablishRequest > 0 or rrcReestablishComplete > 0 or rrcReestablishReject > 0: + rrcMsg = 'eNB requested ' + str(rrcReestablishRequest) + ' RRC Connection Reestablishment(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + rrcMsg = ' -- ' + str(rrcReestablishComplete) + ' were completed' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + rrcMsg = ' -- ' + str(rrcReestablishReject) + ' were rejected' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + if X2HO_inNbProcedures > 0: + rrcMsg = 'eNB completed ' + str(X2HO_inNbProcedures) + ' X2 Handover Connection procedure(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + if X2HO_outNbProcedures > 0: + rrcMsg = 'eNB completed ' + str(X2HO_outNbProcedures) + ' X2 Handover Release procedure(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + if self.eNBOptions[int(self.eNB_instance)] != '': + res1 = re.search('drx_Config_present prSetup', self.eNBOptions[int(self.eNB_instance)]) + if res1 is not None: + if cdrxActivationMessageCount > 0: + rrcMsg = 'eNB activated the CDRX Configuration for ' + str(cdrxActivationMessageCount) + ' time(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + else: + rrcMsg = 'eNB did NOT ACTIVATE the CDRX Configuration' + logging.debug('\u001B[1;37;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + if rachCanceledProcedure > 0: + rachMsg = 'eNB cancelled ' + str(rachCanceledProcedure) + ' RA procedure(s)' + logging.debug('\u001B[1;30;43m ' + rachMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rachMsg + '\n' + if isRRU: + if isSlave: + if slaveReceivesFrameResyncCmd: + rruMsg = 'Slave RRU received the RRU_frame_resynch command from RAU' + logging.debug('\u001B[1;30;43m ' + rruMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rruMsg + '\n' + else: + rruMsg = 'Slave RRU DID NOT receive the RRU_frame_resynch command from RAU' + logging.debug('\u001B[1;37;41m ' + rruMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rruMsg + '\n' + self.prematureExit = True + return ENB_PROCESS_SLAVE_RRU_NOT_SYNCED + if foundSegFault: + logging.debug('\u001B[1;37;41m eNB ended with a Segmentation Fault! \u001B[0m') + return ENB_PROCESS_SEG_FAULT + if foundAssertion: + logging.debug('\u001B[1;37;41m eNB ended with an assertion! \u001B[0m') + self.htmleNBFailureMsg += msgAssertion + return ENB_PROCESS_ASSERTION + if foundRealTimeIssue: + logging.debug('\u001B[1;37;41m eNB faced real time issues! \u001B[0m') + self.htmleNBFailureMsg += 'eNB faced real time issues!\n' + #return ENB_PROCESS_REALTIME_ISSUE + if rlcDiscardBuffer > 0: + rlcMsg = 'eNB RLC discarded ' + str(rlcDiscardBuffer) + ' buffer(s)' + logging.debug('\u001B[1;37;41m ' + rlcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rlcMsg + '\n' + return ENB_PROCESS_REALTIME_ISSUE + return 0 + + def AnalyzeLogFile_UE(self, UElogFile): + if (not os.path.isfile('./' + UElogFile)): + return -1 + ue_log_file = open('./' + UElogFile, 'r') + exitSignalReceived = False + foundAssertion = False + msgAssertion = '' + msgLine = 0 + foundSegFault = False + foundRealTimeIssue = False + uciStatMsgCount = 0 + pdcpDataReqFailedCount = 0 + badDciCount = 0 + rrcConnectionRecfgComplete = 0 + no_cell_sync_found = False + mib_found = False + frequency_found = False + plmn_found = False + self.htmlUEFailureMsg = '' + for line in ue_log_file.readlines(): + result = re.search('Exiting OAI softmodem', str(line)) + if result is not None: + exitSignalReceived = True + result = re.search('System error|[Ss]egmentation [Ff]ault|======= Backtrace: =========|======= Memory map: ========', str(line)) + 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)) + if result is not None and not exitSignalReceived: + foundAssertion = True + result = re.search('LLL', str(line)) + if result is not None and not exitSignalReceived: + foundRealTimeIssue = True + if foundAssertion and (msgLine < 3): + msgLine += 1 + msgAssertion += str(line) + result = re.search('uci->stat', str(line)) + if result is not None and not exitSignalReceived: + uciStatMsgCount += 1 + result = re.search('PDCP data request failed', str(line)) + if result is not None and not exitSignalReceived: + pdcpDataReqFailedCount += 1 + result = re.search('bad DCI 1A', str(line)) + if result is not None and not exitSignalReceived: + badDciCount += 1 + result = re.search('Generating RRCConnectionReconfigurationComplete', str(line)) + if result is not None: + rrcConnectionRecfgComplete += 1 + # No cell synchronization found, abandoning + result = re.search('No cell synchronization found, abandoning', str(line)) + if result is not None: + no_cell_sync_found = True + result = re.search("MIB Information => ([a-zA-Z]{1,10}), ([a-zA-Z]{1,10}), NidCell (?P\d{1,3}), N_RB_DL (?P\d{1,3}), PHICH DURATION (?P\d), PHICH RESOURCE (?P.{1,4}), TX_ANT (?P\d)", str(line)) + if result is not None and (not mib_found): + try: + mibMsg = "MIB Information: " + result.group(1) + ', ' + result.group(2) + self.htmlUEFailureMsg += mibMsg + '\n' + logging.debug('\033[94m' + mibMsg + '\033[0m') + mibMsg = " nidcell = " + result.group('nidcell') + self.htmlUEFailureMsg += mibMsg + logging.debug('\033[94m' + mibMsg + '\033[0m') + mibMsg = " n_rb_dl = " + result.group('n_rb_dl') + self.htmlUEFailureMsg += mibMsg + '\n' + logging.debug('\033[94m' + mibMsg + '\033[0m') + mibMsg = " phich_duration = " + result.group('phich_duration') + self.htmlUEFailureMsg += mibMsg + logging.debug('\033[94m' + mibMsg + '\033[0m') + mibMsg = " phich_resource = " + result.group('phich_resource') + self.htmlUEFailureMsg += mibMsg + '\n' + logging.debug('\033[94m' + mibMsg + '\033[0m') + mibMsg = " tx_ant = " + result.group('tx_ant') + self.htmlUEFailureMsg += mibMsg + '\n' + logging.debug('\033[94m' + mibMsg + '\033[0m') + mib_found = True + except Exception as e: + logging.error('\033[91m' + "MIB marker was not found" + '\033[0m') + result = re.search("Measured Carrier Frequency (?P\d{1,15}) Hz", str(line)) + if result is not None and (not frequency_found): + try: + mibMsg = "Measured Carrier Frequency = " + result.group('measured_carrier_frequency') + ' Hz' + self.htmlUEFailureMsg += mibMsg + '\n' + logging.debug('\033[94m' + mibMsg + '\033[0m') + frequency_found = True + except Exception as e: + logging.error('\033[91m' + "Measured Carrier Frequency not found" + '\033[0m') + result = re.search("PLMN MCC (?P\d{1,3}), MNC (?P\d{1,3}), TAC", str(line)) + if result is not None and (not plmn_found): + try: + mibMsg = 'PLMN MCC = ' + result.group('mcc') + ' MNC = ' + result.group('mnc') + self.htmlUEFailureMsg += mibMsg + '\n' + logging.debug('\033[94m' + mibMsg + '\033[0m') + plmn_found = True + except Exception as e: + logging.error('\033[91m' + "PLMN not found" + '\033[0m') + result = re.search("Found (?P[\w,\s]{1,15}) \(name from internal table\)", str(line)) + if result is not None: + try: + mibMsg = "The operator is: " + result.group('operator') + self.htmlUEFailureMsg += mibMsg + '\n' + logging.debug('\033[94m' + mibMsg + '\033[0m') + except Exception as e: + logging.error('\033[91m' + "Operator name not found" + '\033[0m') + result = re.search("SIB5 InterFreqCarrierFreq element (.{1,4})/(.{1,4})", str(line)) + if result is not None: + try: + mibMsg = "SIB5 InterFreqCarrierFreq element " + result.group(1) + '/' + result.group(2) + self.htmlUEFailureMsg += mibMsg + ' -> ' + logging.debug('\033[94m' + mibMsg + '\033[0m') + except Exception as e: + logging.error('\033[91m' + "SIB5 InterFreqCarrierFreq element not found" + '\033[0m') + result = re.search("DL Carrier Frequency/ARFCN : (?P\d{1,15}/\d{1,4})", str(line)) + if result is not None: + try: + freq = result.group('carrier_frequency') + new_freq = re.sub('/[0-9]+','',freq) + float_freq = float(new_freq) / 1000000 + self.htmlUEFailureMsg += 'DL Freq: ' + ('%.1f' % float_freq) + ' MHz' + logging.debug('\033[94m' + " DL Carrier Frequency is: " + freq + '\033[0m') + except Exception as e: + logging.error('\033[91m' + " DL Carrier Frequency not found" + '\033[0m') + result = re.search("AllowedMeasBandwidth : (?P\d{1,7})", str(line)) + if result is not None: + try: + prb = result.group('allowed_bandwidth') + self.htmlUEFailureMsg += ' -- PRB: ' + prb + '\n' + logging.debug('\033[94m' + " AllowedMeasBandwidth: " + prb + '\033[0m') + except Exception as e: + logging.error('\033[91m' + " AllowedMeasBandwidth not found" + '\033[0m') + ue_log_file.close() + if rrcConnectionRecfgComplete > 0: + statMsg = 'UE connected to eNB (' + str(rrcConnectionRecfgComplete) + ' RRCConnectionReconfigurationComplete message(s) generated)' + logging.debug('\033[94m' + statMsg + '\033[0m') + self.htmlUEFailureMsg += statMsg + '\n' + if uciStatMsgCount > 0: + statMsg = 'UE showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + self.htmlUEFailureMsg += statMsg + '\n' + if pdcpDataReqFailedCount > 0: + statMsg = 'UE showed ' + str(pdcpDataReqFailedCount) + ' "PDCP data request failed" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + self.htmlUEFailureMsg += statMsg + '\n' + if badDciCount > 0: + statMsg = 'UE showed ' + str(badDciCount) + ' "bad DCI 1A" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + self.htmlUEFailureMsg += statMsg + '\n' + if foundSegFault: + logging.debug('\u001B[1;37;41m UE ended with a Segmentation Fault! \u001B[0m') + return ENB_PROCESS_SEG_FAULT + if foundAssertion: + logging.debug('\u001B[1;30;43m UE showed an assertion! \u001B[0m') + self.htmlUEFailureMsg += 'UE showed an assertion!\n' + if not mib_found or not frequency_found: + return OAI_UE_PROCESS_ASSERTION + if foundRealTimeIssue: + logging.debug('\u001B[1;37;41m UE faced real time issues! \u001B[0m') + self.htmlUEFailureMsg += 'UE faced real time issues!\n' + #return ENB_PROCESS_REALTIME_ISSUE + if no_cell_sync_found and not mib_found: + logging.debug('\u001B[1;37;41m UE could not synchronize ! \u001B[0m') + self.htmlUEFailureMsg += 'UE could not synchronize!\n' + return OAI_UE_PROCESS_COULD_NOT_SYNC + return 0 + + def TerminateeNB(self): + if self.eNB_serverId == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = self.eNBSourceCodePath + elif self.eNB_serverId == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + lSourcePath = self.eNB1SourceCodePath + elif self.eNB_serverId == '2': + lIpAddr = self.eNB2IPAddress + lUserName = self.eNB2UserName + lPassWord = self.eNB2Password + lSourcePath = self.eNB2SourceCodePath + if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': + Usage() + sys.exit('Insufficient Parameter') + self.open(lIpAddr, lUserName, lPassWord) + self.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) + self.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + result = re.search('lte-softmodem', str(self.ssh.before)) + if result is not None: + self.command('echo ' + lPassWord + ' | sudo -S daemon --name=enb' + str(self.eNB_instance) + '_daemon --stop', '\$', 5) + self.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGINT lte-softmodem || true', '\$', 5) + time.sleep(10) + self.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + result = re.search('lte-softmodem', str(self.ssh.before)) + if result is not None: + self.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGKILL lte-softmodem || true', '\$', 5) + time.sleep(5) + self.command('rm -f my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + self.close() + # If tracer options is on, stopping tshark on EPC side + result = re.search('T_stdout', str(self.Initialize_eNB_args)) + if result is not None: + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + logging.debug('\u001B[1m Stopping tshark \u001B[0m') + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) + time.sleep(1) + if self.EPC_PcapFileName != '': + self.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 /tmp/' + self.EPC_PcapFileName, '\$', 5) + self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + self.EPC_PcapFileName, '.') + self.copyout(lIpAddr, lUserName, lPassWord, self.EPC_PcapFileName, lSourcePath + '/cmake_targets/.') + self.close() + logging.debug('\u001B[1m Replaying RAW record file\u001B[0m') + self.open(lIpAddr, lUserName, lPassWord) + self.command('cd ' + lSourcePath + '/common/utils/T/tracer/', '\$', 5) + enbLogFile = self.eNBLogFiles[int(self.eNB_instance)] + raw_record_file = enbLogFile.replace('.log', '_record.raw') + replay_log_file = enbLogFile.replace('.log', '_replay.log') + extracted_txt_file = enbLogFile.replace('.log', '_extracted_messages.txt') + extracted_log_file = enbLogFile.replace('.log', '_extracted_messages.log') + self.command('./extract_config -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + extracted_txt_file, '\$', 5) + self.command('echo $USER; nohup ./replay -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + replay_log_file + ' 2>&1 &', lUserName, 5) + self.command('./textlog -d ' + lSourcePath + '/cmake_targets/' + extracted_txt_file + ' -no-gui -ON -full > ' + lSourcePath + '/cmake_targets/' + extracted_log_file, '\$', 5) + self.close() + self.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + extracted_log_file, '.') + logging.debug('\u001B[1m Analyzing eNB replay logfile \u001B[0m') + logStatus = self.AnalyzeLogFile_eNB(extracted_log_file) + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + self.eNBLogFiles[int(self.eNB_instance)] = '' + else: + analyzeFile = False + if self.eNBLogFiles[int(self.eNB_instance)] != '': + analyzeFile = True + fileToAnalyze = self.eNBLogFiles[int(self.eNB_instance)] + self.eNBLogFiles[int(self.eNB_instance)] = '' + if analyzeFile: + copyin_res = self.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + fileToAnalyze, '.') + if (copyin_res == -1): + logging.debug('\u001B[1;37;41m Could not copy eNB logfile to analyze it! \u001B[0m') + self.htmleNBFailureMsg = 'Could not copy eNB logfile to analyze it!' + self.CreateHtmlTestRow('N/A', 'KO', ENB_PROCESS_NOLOGFILE_TO_ANALYZE) + return + if self.eNB_serverId != '0': + self.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './' + fileToAnalyze, self.eNBSourceCodePath + '/cmake_targets/') + logging.debug('\u001B[1m Analyzing eNB logfile \u001B[0m ' + fileToAnalyze) + logStatus = self.AnalyzeLogFile_eNB(fileToAnalyze) + if (logStatus < 0): + self.CreateHtmlTestRow('N/A', 'KO', logStatus) + self.preamtureExit = True + return + else: + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + else: + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def TerminateHSS(self): + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT oai_hss || true', '\$', 5) + time.sleep(2) + self.command('stdbuf -o0 ps -aux | grep hss | grep -v grep', '\$', 5) + result = re.search('oai_hss -j', str(self.ssh.before)) + if result is not None: + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL oai_hss || true', '\$', 5) + self.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-hss.sh', '\$', 5) + elif re.match('OAI', self.EPCType, re.IGNORECASE): + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_hss oai_hss || true', '\$', 5) + time.sleep(2) + self.command('stdbuf -o0 ps -aux | grep hss | grep -v grep', '\$', 5) + result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) + if result is not None: + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_hss oai_hss || true', '\$', 5) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + self.command('cd ' + self.EPCSourceCodePath, '\$', 5) + self.command('cd scripts', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S daemon --name=simulated_hss --stop', '\$', 5) + time.sleep(1) + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL hss_sim', '\$', 5) + else: + logging.error('This should not happen!') + self.close() + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def TerminateMME(self): + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_mme mme || true', '\$', 5) + time.sleep(2) + self.command('stdbuf -o0 ps -aux | grep mme | grep -v grep', '\$', 5) + result = re.search('mme -c', str(self.ssh.before)) + if result is not None: + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_mme mme || true', '\$', 5) + self.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-mme.sh', '\$', 5) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + self.command('cd /opt/ltebox/tools', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S ./stop_mme', '\$', 5) + else: + logging.error('This should not happen!') + self.close() + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def TerminateSPGW(self): + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT spgwc spgwu || true', '\$', 5) + time.sleep(2) + self.command('stdbuf -o0 ps -aux | grep spgw | grep -v grep', '\$', 5) + result = re.search('spgwc -c |spgwu -c ', str(self.ssh.before)) + if result is not None: + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL spgwc spgwu || true', '\$', 5) + self.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-spgw*.sh', '\$', 5) + self.command('stdbuf -o0 ps -aux | grep tshark | grep -v grep', '\$', 5) + result = re.search('-w ', str(self.ssh.before)) + if result is not None: + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT tshark || true', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 ' + self.EPCSourceCodePath + '/scripts/*.pcap', '\$', 5) + elif re.match('OAI', self.EPCType, re.IGNORECASE): + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_spgw spgw || true', '\$', 5) + time.sleep(2) + self.command('stdbuf -o0 ps -aux | grep spgw | grep -v grep', '\$', 5) + result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) + if result is not None: + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_spgw spgw || true', '\$', 5) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + self.command('cd /opt/ltebox/tools', '\$', 5) + self.command('echo ' + self.EPCPassword + ' | sudo -S ./stop_xGw', '\$', 5) + else: + logging.error('This should not happen!') + self.close() + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def TerminateFlexranCtrl(self): + if self.flexranCtrlInstalled == False or self.flexranCtrlStarted == False: + return + if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '': + Usage() + sys.exit('Insufficient Parameter') + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('echo ' + self.EPCPassword + ' | sudo -S daemon --name=flexran_rtc_daemon --stop', '\$', 5) + time.sleep(1) + self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL rt_controller', '\$', 5) + time.sleep(1) + self.close() + self.flexranCtrlStarted = False + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def TerminateUE_common(self, device_id, idx): + try: + self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # back in airplane mode on (ie radio off) + if self.ADBCentralized: + if device_id == '84B7N16418004022': + self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) + else: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + logging.debug('\u001B[1mUE (' + device_id + ') Detach Completed\u001B[0m') + + if self.ADBCentralized: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell "ps | grep --color=never iperf | grep -v grep"', '\$', 5) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ps | grep --color=never iperf | grep -v grep"\'', '\$', 60) + result = re.search('shell +(?P\d+)', str(self.ssh.before)) + if result is not None: + pid_iperf = result.group('pid') + if self.ADBCentralized: + self.command('stdbuf -o0 adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"', '\$', 5) + else: + self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"\'', '\$', 60) + self.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def TerminateUE(self): + terminate_ue_flag = True + self.GetAllUEDevices(terminate_ue_flag) + multi_jobs = [] + i = 0 + for device_id in self.UEDevices: + p = Process(target= SSH.TerminateUE_common, args = (device_id,i,)) + p.daemon = True + p.start() + multi_jobs.append(p) + i += 1 + for job in multi_jobs: + job.join() + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def TerminateOAIUE(self): + self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + self.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) + self.command('ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + result = re.search('lte-uesoftmodem', str(self.ssh.before)) + if result is not None: + self.command('echo ' + self.UEPassword + ' | sudo -S daemon --name=ue' + str(self.UE_instance) + '_daemon --stop', '\$', 5) + self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGINT lte-uesoftmodem || true', '\$', 5) + time.sleep(10) + self.command('ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + result = re.search('lte-uesoftmodem', str(self.ssh.before)) + if result is not None: + self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGKILL lte-uesoftmodem || true', '\$', 5) + time.sleep(5) + self.command('rm -f my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) + self.close() + result = re.search('ue_', str(self.UELogFile)) + if result is not None: + copyin_res = self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.') + if (copyin_res == -1): + logging.debug('\u001B[1;37;41m Could not copy UE logfile to analyze it! \u001B[0m') + self.htmlUEFailureMsg = 'Could not copy UE logfile to analyze it!' + self.CreateHtmlTestRow('N/A', 'KO', OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE, 'UE') + self.UELogFile = '' + return + logging.debug('\u001B[1m Analyzing UE logfile \u001B[0m') + logStatus = self.AnalyzeLogFile_UE(self.UELogFile) + result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) + if result is not None: + ueAction = 'Sniffing' + else: + ueAction = 'Connection' + if (logStatus < 0): + logging.debug('\u001B[1m' + ueAction + ' Failed \u001B[0m') + self.htmlUEFailureMsg = '' + ueAction + ' Failed\n' + self.htmlUEFailureMsg + self.CreateHtmlTestRow('N/A', 'KO', logStatus, 'UE') + # In case of sniffing on commercial eNBs we have random results + # Not an error then + if (logStatus != OAI_UE_PROCESS_COULD_NOT_SYNC) or (ueAction != 'Sniffing'): + self.Initialize_OAI_UE_args = '' + self.AutoTerminateUEandeNB() + else: + logging.debug('\u001B[1m' + ueAction + ' Completed \u001B[0m') + self.htmlUEFailureMsg = '' + ueAction + ' Completed\n' + self.htmlUEFailureMsg + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + self.UELogFile = '' + else: + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def AutoTerminateUEandeNB(self): + if (self.ADBIPAddress != 'none'): + self.testCase_id = 'AUTO-KILL-UE' + self.desc = 'Automatic Termination of UE' + self.ShowTestID() + self.TerminateUE() + if (self.Initialize_OAI_UE_args != ''): + self.testCase_id = 'AUTO-KILL-UE' + self.desc = 'Automatic Termination of UE' + self.ShowTestID() + self.TerminateOAIUE() + if (self.Initialize_eNB_args != ''): + self.testCase_id = 'AUTO-KILL-eNB' + self.desc = 'Automatic Termination of eNB' + self.ShowTestID() + self.eNB_instance = '0' + self.TerminateeNB() + if self.flexranCtrlInstalled and self.flexranCtrlStarted: + self.testCase_id = 'AUTO-KILL-flexran-ctl' + self.desc = 'Automatic Termination of FlexRan CTL' + self.ShowTestID() + self.TerminateFlexranCtrl() + self.prematureExit = True + + def IdleSleep(self): + time.sleep(self.idle_sleep_time) + self.CreateHtmlTestRow(str(self.idle_sleep_time) + ' sec', 'OK', ALL_PROCESSES_OK) + + def X2_Status(self, idx, fileName): + cmd = "curl --silent http://" + self.EPCIPAddress + ":9999/stats | jq '.' > " + fileName + message = cmd + '\n' + logging.debug(cmd) + subprocess.run(cmd, shell=True) + if idx == 0: + cmd = "jq '.mac_stats | length' " + fileName + strNbEnbs = subprocess.check_output(cmd, shell=True, universal_newlines=True) + self.x2NbENBs = int(strNbEnbs.strip()) + self.cnt = 0 + while self.cnt < self.x2NbENBs: + cmd = "jq '.mac_stats[" + str(self.cnt) + "].bs_id' " + fileName + bs_id = subprocess.check_output(cmd, shell=True, universal_newlines=True) + self.x2ENBBsIds[idx].append(bs_id.strip()) + cmd = "jq '.mac_stats[" + str(self.cnt) + "].ue_mac_stats | length' " + fileName + stNbUEs = subprocess.check_output(cmd, shell=True, universal_newlines=True) + nbUEs = int(stNbUEs.strip()) + ueIdx = 0 + self.x2ENBConnectedUEs[idx].append([]) + while ueIdx < nbUEs: + cmd = "jq '.mac_stats[" + str(self.cnt) + "].ue_mac_stats[" + str(ueIdx) + "].rnti' " + fileName + rnti = subprocess.check_output(cmd, shell=True, universal_newlines=True) + self.x2ENBConnectedUEs[idx][self.cnt].append(rnti.strip()) + ueIdx += 1 + self.cnt += 1 + + msg = "FlexRan Controller is connected to " + str(self.x2NbENBs) + " eNB(s)" + logging.debug(msg) + message += msg + '\n' + self.cnt = 0 + while self.cnt < self.x2NbENBs: + msg = " -- eNB: " + str(self.x2ENBBsIds[idx][self.cnt]) + " is connected to " + str(len(self.x2ENBConnectedUEs[idx][self.cnt])) + " UE(s)" + logging.debug(msg) + message += msg + '\n' + ueIdx = 0 + while ueIdx < len(self.x2ENBConnectedUEs[idx][self.cnt]): + msg = " -- UE rnti: " + str(self.x2ENBConnectedUEs[idx][self.cnt][ueIdx]) + logging.debug(msg) + message += msg + '\n' + ueIdx += 1 + self.cnt += 1 + return message + + def Perform_X2_Handover(self): + html_queue = SimpleQueue() + fullMessage = '
'
+		msg = 'Doing X2 Handover w/ option ' + self.x2_ho_options
+		logging.debug(msg)
+		fullMessage += msg + '\n'
+		if self.x2_ho_options == 'network':
+			if self.flexranCtrlInstalled and self.flexranCtrlStarted:
+				self.x2ENBBsIds = []
+				self.x2ENBConnectedUEs = []
+				self.x2ENBBsIds.append([])
+				self.x2ENBBsIds.append([])
+				self.x2ENBConnectedUEs.append([])
+				self.x2ENBConnectedUEs.append([])
+				fullMessage += self.X2_Status(0, self.testCase_id + '_pre_ho.json') 
+
+				msg = "Activating the X2 Net control on each eNB"
+				logging.debug(msg)
+				fullMessage += msg + '\n'
+				eNB_cnt = self.x2NbENBs
+				self.cnt = 0
+				while self.cnt < eNB_cnt:
+					cmd = "curl -XPOST http://" + self.EPCIPAddress + ":9999/rrc/x2_ho_net_control/enb/" + str(self.x2ENBBsIds[0][self.cnt]) + "/1"
+					logging.debug(cmd)
+					fullMessage += cmd + '\n'
+					subprocess.run(cmd, shell=True)
+					self.cnt += 1
+				# Waiting for the activation to be active
+				time.sleep(10)
+				msg = "Switching UE(s) from eNB to eNB"
+				logging.debug(msg)
+				fullMessage += msg + '\n'
+				self.cnt = 0
+				while self.cnt < eNB_cnt:
+					ueIdx = 0
+					while ueIdx < len(self.x2ENBConnectedUEs[0][self.cnt]):
+						cmd = "curl -XPOST http://" + self.EPCIPAddress + ":9999/rrc/ho/senb/" + str(self.x2ENBBsIds[0][self.cnt]) + "/ue/" + str(self.x2ENBConnectedUEs[0][cnt][ueIdx]) + "/tenb/" + str(self.x2ENBBsIds[0][eNB_cnt - cnt - 1])
+						logging.debug(cmd)
+						fullMessage += cmd + '\n'
+						subprocess.run(cmd, shell=True)
+						ueIdx += 1
+					self.cnt += 1
+				time.sleep(10)
+				# check
+				logging.debug("Checking the Status after X2 Handover")
+				fullMessage += self.X2_Status(1, self.testCase_id + '_post_ho.json') 
+				self.cnt = 0
+				x2Status = True
+				while self.cnt < eNB_cnt:
+					if len(self.x2ENBConnectedUEs[0][self.cnt]) == len(self.x2ENBConnectedUEs[1][cnt]):
+						x2Status = False
+					self.cnt += 1
+				if x2Status:
+					msg = "X2 Handover was successful"
+					logging.debug(msg)
+					fullMessage += msg + '
' + html_queue.put(fullMessage) + self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) + else: + msg = "X2 Handover FAILED" + logging.error(msg) + fullMessage += msg + '' + html_queue.put(fullMessage) + self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) + else: + self.CreateHtmlTestRow('Cannot perform requested X2 Handover', 'KO', ALL_PROCESSES_OK) + + def LogCollectBuild(self): + if (self.eNBIPAddress != '' and self.eNBUserName != '' and self.eNBPassword != ''): + IPAddress = self.eNBIPAddress + UserName = self.eNBUserName + Password = self.eNBPassword + SourceCodePath = self.eNBSourceCodePath + elif (self.UEIPAddress != '' and self.UEUserName != '' and self.UEPassword != ''): + IPAddress = self.UEIPAddress + UserName = self.UEUserName + Password = self.UEPassword + SourceCodePath = self.UESourceCodePath + else: + sys.exit('Insufficient Parameter') + self.open(IPAddress, UserName, Password) + self.command('cd ' + SourceCodePath, '\$', 5) + self.command('cd cmake_targets', '\$', 5) + self.command('rm -f build.log.zip', '\$', 5) + self.command('zip build.log.zip build_log_*/*', '\$', 60) + self.close() + + def LogCollecteNB(self): + self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) + self.command('cd ' + self.eNBSourceCodePath, '\$', 5) + self.command('cd cmake_targets', '\$', 5) + self.command('echo ' + self.eNBPassword + ' | sudo -S rm -f enb.log.zip', '\$', 5) + self.command('echo ' + self.eNBPassword + ' | sudo -S zip enb.log.zip enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 60) + self.command('echo ' + self.eNBPassword + ' | sudo -S rm enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 5) + self.close() + + def LogCollectPing(self): + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('cd ' + self.EPCSourceCodePath, '\$', 5) + self.command('cd scripts', '\$', 5) + self.command('rm -f ping.log.zip', '\$', 5) + self.command('zip ping.log.zip ping*.log', '\$', 60) + self.command('rm ping*.log', '\$', 5) + self.close() + + def LogCollectIperf(self): + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('cd ' + self.EPCSourceCodePath, '\$', 5) + self.command('cd scripts', '\$', 5) + self.command('rm -f iperf.log.zip', '\$', 5) + self.command('zip iperf.log.zip iperf*.log', '\$', 60) + self.command('rm iperf*.log', '\$', 5) + self.close() + + def LogCollectHSS(self): + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + self.command('rm -f hss.log.zip', '\$', 5) + if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + self.command('zip hss.log.zip hss*.log', '\$', 60) + self.command('echo ' + self.EPCPassword + ' | sudo -S rm hss*.log', '\$', 5) + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + self.command('zip hss.log.zip logs/hss*.* *.pcap', '\$', 60) + self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f logs/hss*.* *.pcap', '\$', 5) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + self.command('cp /opt/hss_sim0609/hss.log .', '\$', 60) + self.command('zip hss.log.zip hss.log', '\$', 60) + else: + logging.error('This option should not occur!') + self.close() + + def LogCollectMME(self): + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + self.command('rm -f mme.log.zip', '\$', 5) + if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + self.command('zip mme.log.zip mme*.log', '\$', 60) + self.command('echo ' + self.EPCPassword + ' | sudo -S rm mme*.log', '\$', 5) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + self.command('cp /opt/ltebox/var/log/*Log.0 .', '\$', 5) + self.command('zip mme.log.zip mmeLog.0 s1apcLog.0 s1apsLog.0 s11cLog.0 libLog.0 s1apCodecLog.0', '\$', 60) + else: + logging.error('This option should not occur!') + self.close() + + def LogCollectSPGW(self): + self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + self.command('rm -f spgw.log.zip', '\$', 5) + if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + self.command('zip spgw.log.zip spgw*.log', '\$', 60) + self.command('echo ' + self.EPCPassword + ' | sudo -S rm spgw*.log', '\$', 5) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + self.command('cp /opt/ltebox/var/log/xGwLog.0 .', '\$', 5) + self.command('zip spgw.log.zip xGwLog.0', '\$', 60) + else: + logging.error('This option should not occur!') + self.close() + + def LogCollectOAIUE(self): + self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + self.command('cd ' + self.UESourceCodePath, '\$', 5) + self.command('cd cmake_targets', '\$', 5) + self.command('echo ' + self.UEPassword + ' | sudo -S rm -f ue.log.zip', '\$', 5) + self.command('echo ' + self.UEPassword + ' | sudo -S zip ue.log.zip ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 60) + self.command('echo ' + self.UEPassword + ' | sudo -S rm ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 5) + self.close() + + def RetrieveSystemVersion(self, machine): + if self.eNBIPAddress == 'none' or self.UEIPAddress == 'none': + self.OsVersion = 'Ubuntu 16.04.5 LTS' + self.KernelVersion = '4.15.0-45-generic' + self.UhdVersion = '3.13.0.1-0' + self.UsrpBoard = 'B210' + self.CpuNb = '4' + self.CpuModel = 'Intel(R) Core(TM) i5-6200U' + self.CpuMHz = '2399.996 MHz' + return 0 + if machine == 'eNB': + if self.eNBIPAddress != '' and self.eNBUserName != '' and self.eNBPassword != '': + IPAddress = self.eNBIPAddress + UserName = self.eNBUserName + Password = self.eNBPassword + else: + return -1 + if machine == 'UE': + if self.UEIPAddress != '' and self.UEUserName != '' and self.UEPassword != '': + IPAddress = self.UEIPAddress + UserName = self.UEUserName + Password = self.UEPassword + else: + return -1 + + self.open(IPAddress, UserName, Password) + self.command('lsb_release -a', '\$', 5) + result = re.search('Description:\\\\t(?P[a-zA-Z0-9\-\_\.\ ]+)', str(self.ssh.before)) + if result is not None: + self.OsVersion = result.group('os_type') + logging.debug('OS is: ' + self.OsVersion) + self.command('uname -r', '\$', 5) + result = re.search('uname -r\\\\r\\\\n(?P[a-zA-Z0-9\-\_\.]+)', str(self.ssh.before)) + if result is not None: + self.KernelVersion = result.group('kernel_version') + logging.debug('Kernel Version is: ' + self.KernelVersion) + self.command('dpkg --list | egrep --color=never libuhd003', '\$', 5) + result = re.search('libuhd003:amd64 *(?P[0-9\.]+)', str(self.ssh.before)) + if result is not None: + self.UhdVersion = result.group('uhd_version') + logging.debug('UHD Version is: ' + self.UhdVersion) + self.command('echo ' + Password + ' | sudo -S uhd_find_devices', '\$', 15) + result = re.search('product: (?P[0-9A-Za-z]+)\\\\r\\\\n', str(self.ssh.before)) + if result is not None: + self.UsrpBoard = result.group('usrp_board') + logging.debug('USRP Board is: ' + self.UsrpBoard) + self.command('lscpu', '\$', 5) + result = re.search('CPU\(s\): *(?P[0-9]+).*Model name: *(?P[a-zA-Z0-9\-\_\.\ \(\)]+).*CPU MHz: *(?P[0-9\.]+)', str(self.ssh.before)) + if result is not None: + self.CpuNb = result.group('nb_cpus') + logging.debug('nb_cpus: ' + self.CpuNb) + self.CpuModel = result.group('model') + logging.debug('model: ' + self.CpuModel) + self.CpuMHz = result.group('cpu_mhz') + ' MHz' + logging.debug('cpu_mhz: ' + self.CpuMHz) + self.close() + +#----------------------------------------------------------- +# HTML Reporting.... +#----------------------------------------------------------- + def CreateHtmlHeader(self): + if (not self.htmlHeaderCreated): + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + logging.debug('\u001B[1m Creating HTML header \u001B[0m') + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + self.htmlFile = open('test_results.html', 'w') + self.htmlFile.write('\n') + self.htmlFile.write('\n') + self.htmlFile.write('\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Test Results for TEMPLATE_JOB_NAME job build #TEMPLATE_BUILD_ID\n') + self.htmlFile.write('\n') + self.htmlFile.write('
\n') + self.htmlFile.write('
\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write('
\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Job Summary -- Job: TEMPLATE_JOB_NAME -- Build-ID: TEMPLATE_BUILD_ID\n') + self.htmlFile.write('
\n') + self.htmlFile.write('
\n') + self.htmlFile.write('
TEMPLATE_STAGE_NAME
\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (self.ranAllowMerge): + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (self.ranAllowMerge): + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (self.ranAllowMerge): + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if self.ranAllowMerge != '': + commit_message = subprocess.check_output("git log -n1 --pretty=format:\"%s\" " + self.ranCommitID, shell=True, universal_newlines=True) + commit_message = commit_message.strip() + self.htmlFile.write(' \n') + if (self.ranAllowMerge): + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (self.ranAllowMerge): + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (self.ranTargetBranch == ''): + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write('
Build Start Time (UTC) TEMPLATE_BUILD_TIME
GIT Repository ' + self.ranRepository + '
Job Trigger Merge-RequestPush to Branch
Source Branch Branch' + self.ranBranch + '
Source Commit ID Commit ID ' + self.ranCommitID + '
Source Commit Message Commit Message ' + commit_message + '
Target Branch develop' + self.ranTargetBranch + '
\n') + + if (self.ADBIPAddress != 'none'): + terminate_ue_flag = True + self.GetAllUEDevices(terminate_ue_flag) + self.GetAllCatMDevices(terminate_ue_flag) + self.htmlUEConnected = len(self.UEDevices) + self.htmlFile.write('

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

\n') + self.htmlFile.write('

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

\n') + else: + self.UEDevices.append('OAI-UE') + self.htmlUEConnected = len(self.UEDevices) + self.htmlFile.write('

' + str(len(self.UEDevices)) + ' OAI UE(s) is(are) connected to CI bench

\n') + self.htmlFile.write('
\n') + self.htmlFile.write(' \n') + self.htmlFile.write('
\n') + self.htmlFile.close() + + def CreateHtmlTabHeader(self): + if (not self.htmlHeaderCreated): + if (not os.path.isfile('test_results.html')): + self.CreateHtmlHeader() + self.htmlFile = open('test_results.html', 'a') + if (self.nbTestXMLfiles == 1): + self.htmlFile.write('
\n') + self.htmlFile.write('

Test Summary for ' + self.testXMLfiles[0] + '

\n') + else: + self.htmlFile.write('
\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (self.htmlUEConnected == -1): + terminate_ue_flag = True + if (self.ADBIPAddress != 'none'): + self.GetAllUEDevices(terminate_ue_flag) + self.GetAllCatMDevices(terminate_ue_flag) + else: + self.UEDevices.append('OAI-UE') + self.htmlUEConnected = len(self.UEDevices) + + i = 0 + while (i < self.htmlUEConnected): + self.htmlFile.write(' \n') + i += 1 + self.htmlFile.write(' \n') + self.htmlHeaderCreated = True + + def CreateHtmlTabFooter(self, passStatus): + if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if passStatus: + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write('
Relative Time (ms)Test IdTest DescTest OptionsTest StatusUE' + str(i) + ' Status
Final Tab StatusPASS FAIL
\n') + self.htmlFile.write('
\n') + self.htmlFile.close() + time.sleep(1) + if passStatus: + cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__//' test_results.html" + subprocess.run(cmd, shell=True) + else: + cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__/<\/span>/' test_results.html" + subprocess.run(cmd, shell=True) + self.htmlFooterCreated = False + + def CreateHtmlFooter(self, passStatus): + if (os.path.isfile('test_results.html')): + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + logging.debug('\u001B[1m Creating HTML footer \u001B[0m') + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + + self.htmlFile = open('test_results.html', 'a') + self.htmlFile.write('
\n') + self.htmlFile.write('

\n') + self.htmlFile.write(' \n') + + machines = [ 'eNB', 'UE' ] + for machine in machines: + res = self.RetrieveSystemVersion(machine) + if res == -1: + continue + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if passStatus: + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write('
' + str(machine) + ' Server Characteristics
OS Version' + self.OsVersion + 'Kernel Version' + self.KernelVersion + 'UHD Version' + self.UhdVersion + 'USRP Board' + self.UsrpBoard + '
Nb CPUs' + self.CpuNb + 'CPU Model Name' + self.CpuModel + 'CPU Frequency' + self.CpuMHz + '
Final StatusPASS FAIL
\n') + self.htmlFile.write('

\n') + self.htmlFile.write('
End of Test Report -- Copyright 2018 OpenAirInterface. All Rights Reserved.
\n') + self.htmlFile.write('
\n') + self.htmlFile.write('\n') + self.htmlFile.close() + + def CreateHtmlTestRow(self, options, status, processesStatus, machine='eNB'): + if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): + currentTime = int(round(time.time() * 1000)) - self.startTime + self.htmlFile.write(' \n') + self.htmlFile.write(' ' + format(currentTime / 1000, '.1f') + '\n') + self.htmlFile.write(' ' + self.testCase_id + '\n') + self.htmlFile.write(' ' + self.desc + '\n') + self.htmlFile.write(' ' + str(options) + '\n') + if (str(status) == 'OK'): + self.htmlFile.write(' ' + str(status) + '\n') + elif (str(status) == 'KO'): + if (processesStatus == 0): + self.htmlFile.write(' ' + str(status) + '\n') + elif (processesStatus == ENB_PROCESS_FAILED): + self.htmlFile.write(' KO - eNB process not found\n') + elif (processesStatus == OAI_UE_PROCESS_FAILED): + self.htmlFile.write(' KO - OAI UE process not found\n') + elif (processesStatus == ENB_PROCESS_SEG_FAULT): + self.htmlFile.write(' KO - ' + machine + ' process ended in Segmentation Fault\n') + elif (processesStatus == ENB_PROCESS_ASSERTION) or (processesStatus == OAI_UE_PROCESS_ASSERTION): + self.htmlFile.write(' KO - ' + machine + ' process ended in Assertion\n') + elif (processesStatus == ENB_PROCESS_REALTIME_ISSUE): + self.htmlFile.write(' KO - ' + machine + ' process faced Real Time issue(s)\n') + elif (processesStatus == ENB_PROCESS_NOLOGFILE_TO_ANALYZE) or (processesStatus == OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE): + self.htmlFile.write(' OK?\n') + elif (processesStatus == ENB_PROCESS_SLAVE_RRU_NOT_SYNCED): + self.htmlFile.write(' KO - ' + machine + ' Slave RRU could not synch\n') + elif (processesStatus == OAI_UE_PROCESS_COULD_NOT_SYNC): + self.htmlFile.write(' KO - UE could not sync\n') + elif (processesStatus == HSS_PROCESS_FAILED): + self.htmlFile.write(' KO - HSS process not found\n') + elif (processesStatus == MME_PROCESS_FAILED): + self.htmlFile.write(' KO - MME process not found\n') + elif (processesStatus == SPGW_PROCESS_FAILED): + self.htmlFile.write(' KO - SPGW process not found\n') + elif (processesStatus == UE_IP_ADDRESS_ISSUE): + self.htmlFile.write(' KO - Could not retrieve UE IP address\n') + else: + self.htmlFile.write(' ' + str(status) + '\n') + else: + self.htmlFile.write(' ' + str(status) + '\n') + if (len(str(self.htmleNBFailureMsg)) > 2): + cellBgColor = 'white' + result = re.search('ended with|faced real time issues', self.htmleNBFailureMsg) + if result is not None: + cellBgColor = 'red' + else: + result = re.search('showed|Reestablishment|Could not copy eNB logfile', self.htmleNBFailureMsg) + if result is not None: + cellBgColor = 'orange' + self.htmlFile.write('
' + self.htmleNBFailureMsg + '
\n') + self.htmleNBFailureMsg = '' + elif (len(str(self.htmlUEFailureMsg)) > 2): + cellBgColor = 'white' + result = re.search('ended with|faced real time issues', self.htmlUEFailureMsg) + if result is not None: + cellBgColor = 'red' + else: + result = re.search('showed|Could not copy UE logfile|oaitun_ue1 interface is either NOT mounted or NOT configured', self.htmlUEFailureMsg) + if result is not None: + cellBgColor = 'orange' + self.htmlFile.write('
' + self.htmlUEFailureMsg + '
\n') + self.htmlUEFailureMsg = '' + else: + i = 0 + while (i < self.htmlUEConnected): + self.htmlFile.write(' -\n') + i += 1 + self.htmlFile.write(' \n') + + def CreateHtmlTestRowQueue(self, options, status, ue_status, ue_queue): + if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): + currentTime = int(round(time.time() * 1000)) - self.startTime + addOrangeBK = False + self.htmlFile.write(' \n') + self.htmlFile.write(' ' + format(currentTime / 1000, '.1f') + '\n') + self.htmlFile.write(' ' + self.testCase_id + '\n') + self.htmlFile.write(' ' + self.desc + '\n') + self.htmlFile.write(' ' + str(options) + '\n') + if (str(status) == 'OK'): + self.htmlFile.write(' ' + str(status) + '\n') + elif (str(status) == 'KO'): + self.htmlFile.write(' ' + str(status) + '\n') + else: + addOrangeBK = True + self.htmlFile.write(' ' + str(status) + '\n') + i = 0 + while (i < self.htmlUEConnected): + if (i < ue_status): + if (not ue_queue.empty()): + if (addOrangeBK): + self.htmlFile.write(' ' + str(ue_queue.get()).replace('white', 'orange') + '\n') + else: + self.htmlFile.write(' ' + str(ue_queue.get()) + '\n') + else: + self.htmlFile.write(' -\n') + else: + self.htmlFile.write(' -\n') + i += 1 + self.htmlFile.write(' \n') + +#----------------------------------------------------------- +# ShowTestID() +#----------------------------------------------------------- + def ShowTestID(self): + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + logging.debug('\u001B[1mTest ID:' + self.testCase_id + '\u001B[0m') + logging.debug('\u001B[1m' + self.desc + '\u001B[0m') + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + +#----------------------------------------------------------- +# Usage() +#----------------------------------------------------------- +def Usage(): + print('----------------------------------------------------------------------------------------------------------------------') + print('main.py Ver:' + Version) + print('----------------------------------------------------------------------------------------------------------------------') + print('Usage: python main.py [options]') + print(' --help Show this help.') + print(' --mode=[Mode]') + print(' TesteNB') + print(' InitiateHtml, FinalizeHtml') + print(' TerminateeNB, TerminateUE, TerminateHSS, TerminateMME, TerminateSPGW') + print(' LogCollectBuild, LogCollecteNB, LogCollectHSS, LogCollectMME, LogCollectSPGW, LogCollectPing, LogCollectIperf') + print('---------------------------------------------------------------------------------------------------- Git Options --') + print(' --ranRepository=[OAI RAN Repository URL]') + print(' --ranBranch=[OAI RAN Repository Branch]') + print(' --ranCommitID=[OAI RAN Repository Commit SHA-1]') + print(' --ranAllowMerge=[Allow Merge Request (with target branch) (true or false)]') + print(' --ranTargetBranch=[Target Branch in case of a Merge Request]') + print('--------------------------------------------------------------------------------------------- eNB Server Options --') + print(' --eNBIPAddress=[eNB\'s IP Address]') + print(' --eNBUserName=[eNB\'s Login User Name]') + print(' --eNBPassword=[eNB\'s Login Password]') + print(' --eNBSourceCodePath=[eNB\'s Source Code Path]') + print('------------------------------------------------------------------------------------------ OAI UE Server Options --') + print(' --UEIPAddress=[UE\'s IP Address]') + print(' --UEUserName=[UE\'s Login User Name]') + print(' --UEPassword=[UE\'s Login Password]') + print(' --UESourceCodePath=[UE\'s Source Code Path]') + print('--------------------------------------------------------------------------------------------- EPC Server Options --') + print(' --EPCIPAddress=[EPC\'s IP Address]') + print(' --EPCUserName=[EPC\'s Login User Name]') + print(' --EPCPassword=[EPC\'s Login Password]') + print(' --EPCSourceCodePath=[EPC\'s Source Code Path]') + print(' --EPCType=[EPC\'s Type: OAI or ltebox or OAI-Rel14-CUPS]') + print('--------------------------------------------------------------------------------------------- ABD Server Options --') + print(' --ADBIPAddress=[ADB\'s IP Address]') + print(' --ADBUserName=[ADB\'s Login User Name]') + print(' --ADBPassword=[ADB\'s Login Password]') + print('----------------------------------------------------------------------------------------------------------------------') + print(' --XMLTestFile=[XML Test File to be run]') + print('----------------------------------------------------------------------------------------------------------------------') + +def CheckClassValidity(action,id): + if action != 'Build_eNB' and action != 'WaitEndBuild_eNB' and action != 'Initialize_eNB' and action != 'Terminate_eNB' and action != 'Initialize_UE' and action != 'Terminate_UE' and action != 'Attach_UE' and action != 'Detach_UE' and action != 'Build_OAI_UE' and action != 'Initialize_OAI_UE' and action != 'Terminate_OAI_UE' and action != 'DataDisable_UE' and action != 'DataEnable_UE' and action != 'CheckStatusUE' and action != 'Ping' and action != 'Iperf' and action != 'Reboot_UE' and action != 'Initialize_FlexranCtrl' and action != 'Terminate_FlexranCtrl' and action != 'Initialize_HSS' and action != 'Terminate_HSS' and action != 'Initialize_MME' and action != 'Terminate_MME' and action != 'Initialize_SPGW' and action != 'Terminate_SPGW' and action != 'Initialize_CatM_module' and action != 'Terminate_CatM_module' and action != 'Attach_CatM_module' and action != 'Detach_CatM_module' and action != 'Ping_CatM_module' and action != 'IdleSleep' and action != 'Perform_X2_Handover': + logging.debug('ERROR: test-case ' + id + ' has wrong class ' + action) + return False + return True + +def GetParametersFromXML(action): + if action == 'Build_eNB': + SSH.Build_eNB_args = test.findtext('Build_eNB_args') + SSH.eNB_instance = test.findtext('eNB_instance') + if (SSH.eNB_instance is None): + SSH.eNB_instance = '0' + SSH.eNB_serverId = test.findtext('eNB_serverId') + if (SSH.eNB_serverId is None): + SSH.eNB_serverId = '0' + xmlBgBuildField = test.findtext('backgroundBuild') + if (xmlBgBuildField is None): + SSH.backgroundBuild = False + else: + if re.match('true', xmlBgBuildField, re.IGNORECASE): + SSH.backgroundBuild = True + else: + SSH.backgroundBuild = False + + if action == 'WaitEndBuild_eNB': + SSH.Build_eNB_args = test.findtext('Build_eNB_args') + SSH.eNB_instance = test.findtext('eNB_instance') + if (SSH.eNB_instance is None): + SSH.eNB_instance = '0' + SSH.eNB_serverId = test.findtext('eNB_serverId') + if (SSH.eNB_serverId is None): + SSH.eNB_serverId = '0' + + if action == 'Initialize_eNB': + SSH.Initialize_eNB_args = test.findtext('Initialize_eNB_args') + SSH.eNB_instance = test.findtext('eNB_instance') + if (SSH.eNB_instance is None): + SSH.eNB_instance = '0' + SSH.eNB_serverId = test.findtext('eNB_serverId') + if (SSH.eNB_serverId is None): + SSH.eNB_serverId = '0' + + if action == 'Terminate_eNB': + SSH.eNB_instance = test.findtext('eNB_instance') + if (SSH.eNB_instance is None): + SSH.eNB_instance = '0' + SSH.eNB_serverId = test.findtext('eNB_serverId') + if (SSH.eNB_serverId is None): + SSH.eNB_serverId = '0' + + if action == 'Attach_UE': + nbMaxUEtoAttach = test.findtext('nbMaxUEtoAttach') + if (nbMaxUEtoAttach is None): + SSH.nbMaxUEtoAttach = -1 + else: + SSH.nbMaxUEtoAttach = int(nbMaxUEtoAttach) + + if action == 'CheckStatusUE': + expectedNBUE = test.findtext('expectedNbOfConnectedUEs') + if (expectedNBUE is None): + SSH.expectedNbOfConnectedUEs = -1 + else: + SSH.expectedNbOfConnectedUEs = int(expectedNBUE) + + if action == 'Build_OAI_UE': + SSH.Build_OAI_UE_args = test.findtext('Build_OAI_UE_args') + + if action == 'Initialize_OAI_UE': + SSH.Initialize_OAI_UE_args = test.findtext('Initialize_OAI_UE_args') + SSH.UE_instance = test.findtext('UE_instance') + if (SSH.UE_instance is None): + SSH.UE_instance = '0' + + if action == 'Terminate_OAI_UE': + SSH.eNB_instance = test.findtext('UE_instance') + if (SSH.UE_instance is None): + SSH.UE_instance = '0' + + if action == 'Ping' or action == 'Ping_CatM_module': + SSH.ping_args = test.findtext('ping_args') + SSH.ping_packetloss_threshold = test.findtext('ping_packetloss_threshold') + + if action == 'Iperf': + SSH.iperf_args = test.findtext('iperf_args') + SSH.iperf_packetloss_threshold = test.findtext('iperf_packetloss_threshold') + SSH.iperf_profile = test.findtext('iperf_profile') + if (SSH.iperf_profile is None): + SSH.iperf_profile = 'balanced' + else: + if SSH.iperf_profile != 'balanced' and SSH.iperf_profile != 'unbalanced' and SSH.iperf_profile != 'single-ue': + logging.debug('ERROR: test-case has wrong profile ' + SSH.iperf_profile) + SSH.iperf_profile = 'balanced' + + if action == 'IdleSleep': + string_field = test.findtext('idle_sleep_time_in_sec') + if (string_field is None): + SSH.idle_sleep_time = 5 + else: + SSH.idle_sleep_time = int(string_field) + + if action == 'Perform_X2_Handover': + string_field = test.findtext('x2_ho_options') + if (string_field is None): + SSH.x2_ho_options = 'network' + else: + if string_field != 'network': + logging.error('ERROR: test-case has wrong option ' + string_field) + SSH.x2_ho_options = 'network' + else: + SSH.x2_ho_options = string_field + + +#check if given test is in list +#it is in list if one of the strings in 'list' is at the beginning of 'test' +def test_in_list(test, list): + for check in list: + check=check.replace('+','') + if (test.startswith(check)): + return True + return False + +def receive_signal(signum, frame): + sys.exit(1) + +#----------------------------------------------------------- +# Parameter Check +#----------------------------------------------------------- +mode = '' +SSH = SSHConnection() + +argvs = sys.argv +argc = len(argvs) +cwd = os.getcwd() + +while len(argvs) > 1: + myArgv = argvs.pop(1) # 0th is this file's name + if re.match('^\-\-help$', myArgv, re.IGNORECASE): + Usage() + sys.exit(0) + elif re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE) + mode = matchReg.group(1) + elif re.match('^\-\-eNBRepository=(.+)$|^\-\-ranRepository(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE) + else: + matchReg = re.match('^\-\-ranRepository=(.+)$', myArgv, re.IGNORECASE) + SSH.ranRepository = matchReg.group(1) + elif re.match('^\-\-eNB_AllowMerge=(.+)$|^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE) + else: + matchReg = re.match('^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE) + doMerge = matchReg.group(1) + if ((doMerge == 'true') or (doMerge == 'True')): + SSH.ranAllowMerge = True + elif re.match('^\-\-eNBBranch=(.+)$|^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE) + else: + matchReg = re.match('^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE) + SSH.ranBranch = matchReg.group(1) + elif re.match('^\-\-eNBCommitID=(.*)$|^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE) + else: + matchReg = re.match('^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE) + SSH.ranCommitID = matchReg.group(1) + elif re.match('^\-\-eNBTargetBranch=(.*)$|^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE) + else: + matchReg = re.match('^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE) + SSH.ranTargetBranch = matchReg.group(1) + elif re.match('^\-\-eNBIPAddress=(.+)$|^\-\-eNB[1-2]IPAddress=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE) + SSH.eNBIPAddress = matchReg.group(1) + elif re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE) + SSH.eNB1IPAddress = matchReg.group(1) + elif re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE) + SSH.eNB2IPAddress = matchReg.group(1) + elif re.match('^\-\-eNBUserName=(.+)$|^\-\-eNB[1-2]UserName=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE) + SSH.eNBUserName = matchReg.group(1) + elif re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE) + SSH.eNB1UserName = matchReg.group(1) + elif re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE) + SSH.eNB2UserName = matchReg.group(1) + elif re.match('^\-\-eNBPassword=(.+)$|^\-\-eNB[1-2]Password=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE) + SSH.eNBPassword = matchReg.group(1) + elif re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE) + SSH.eNB1Password = matchReg.group(1) + elif re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE) + SSH.eNB2Password = matchReg.group(1) + elif re.match('^\-\-eNBSourceCodePath=(.+)$|^\-\-eNB[1-2]SourceCodePath=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE) + SSH.eNBSourceCodePath = matchReg.group(1) + elif re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE) + SSH.eNB1SourceCodePath = matchReg.group(1) + elif re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE) + SSH.eNB2SourceCodePath = matchReg.group(1) + elif re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE) + SSH.EPCIPAddress = matchReg.group(1) + elif re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE) + SSH.EPCBranch = matchReg.group(1) + elif re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE) + SSH.EPCUserName = matchReg.group(1) + elif re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE) + SSH.EPCPassword = matchReg.group(1) + elif re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE) + SSH.EPCSourceCodePath = matchReg.group(1) + elif re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE) + if re.match('OAI', matchReg.group(1), re.IGNORECASE) or re.match('ltebox', matchReg.group(1), re.IGNORECASE) or re.match('OAI-Rel14-CUPS', matchReg.group(1), re.IGNORECASE): + SSH.EPCType = matchReg.group(1) + else: + sys.exit('Invalid EPC Type: ' + matchReg.group(1) + ' -- (should be OAI or ltebox or OAI-Rel14-CUPS)') + elif re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE) + SSH.ADBIPAddress = matchReg.group(1) + elif re.match('^\-\-ADBUserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-ADBUserName=(.+)$', myArgv, re.IGNORECASE) + SSH.ADBUserName = matchReg.group(1) + elif re.match('^\-\-ADBType=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-ADBType=(.+)$', myArgv, re.IGNORECASE) + if re.match('centralized', matchReg.group(1), re.IGNORECASE) or re.match('distributed', matchReg.group(1), re.IGNORECASE): + if re.match('distributed', matchReg.group(1), re.IGNORECASE): + SSH.ADBCentralized = False + else: + SSH.ADBCentralized = True + else: + sys.exit('Invalid ADB Type: ' + matchReg.group(1) + ' -- (should be centralized or distributed)') + elif re.match('^\-\-ADBPassword=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-ADBPassword=(.+)$', myArgv, re.IGNORECASE) + SSH.ADBPassword = matchReg.group(1) + elif re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE) + SSH.testXMLfiles.append(matchReg.group(1)) + SSH.nbTestXMLfiles += 1 + elif re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE) + SSH.UEIPAddress = matchReg.group(1) + elif re.match('^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE) + SSH.UEUserName = matchReg.group(1) + elif re.match('^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE) + SSH.UEPassword = matchReg.group(1) + elif re.match('^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE) + SSH.UESourceCodePath = matchReg.group(1) + elif re.match('^\-\-finalStatus=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-finalStatus=(.+)$', myArgv, re.IGNORECASE) + finalStatus = matchReg.group(1) + if ((finalStatus == 'true') or (finalStatus == 'True')): + SSH.finalStatus = True + else: + Usage() + sys.exit('Invalid Parameter: ' + myArgv) + +if re.match('^TerminateeNB$', mode, re.IGNORECASE): + if SSH.eNBIPAddress == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + SSH.eNB_serverId = '0' + SSH.eNB_instance = '0' + SSH.eNBSourceCodePath = '/tmp/' + SSH.TerminateeNB() +elif re.match('^TerminateUE$', mode, re.IGNORECASE): + if (SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == ''): + Usage() + sys.exit('Insufficient Parameter') + signal.signal(signal.SIGUSR1, receive_signal) + SSH.TerminateUE() +elif re.match('^TerminateOAIUE$', mode, re.IGNORECASE): + if SSH.UEIPAddress == '' or SSH.UEUserName == '' or SSH.UEPassword == '': + Usage() + sys.exit('Insufficient Parameter') + signal.signal(signal.SIGUSR1, receive_signal) + SSH.TerminateOAIUE() +elif re.match('^TerminateHSS$', mode, re.IGNORECASE): + if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + SSH.TerminateHSS() +elif re.match('^TerminateMME$', mode, re.IGNORECASE): + if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + SSH.TerminateMME() +elif re.match('^TerminateSPGW$', mode, re.IGNORECASE): + if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + SSH.TerminateSPGW() +elif re.match('^LogCollectBuild$', mode, re.IGNORECASE): + if (SSH.eNBIPAddress == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '' or SSH.eNBSourceCodePath == '') and (SSH.UEIPAddress == '' or SSH.UEUserName == '' or SSH.UEPassword == '' or SSH.UESourceCodePath == ''): + Usage() + sys.exit('Insufficient Parameter') + SSH.LogCollectBuild() +elif re.match('^LogCollecteNB$', mode, re.IGNORECASE): + if SSH.eNBIPAddress == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '' or SSH.eNBSourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + SSH.LogCollecteNB() +elif re.match('^LogCollectHSS$', mode, re.IGNORECASE): + if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + SSH.LogCollectHSS() +elif re.match('^LogCollectMME$', mode, re.IGNORECASE): + if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + SSH.LogCollectMME() +elif re.match('^LogCollectSPGW$', mode, re.IGNORECASE): + if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + SSH.LogCollectSPGW() +elif re.match('^LogCollectPing$', mode, re.IGNORECASE): + if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCSourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + SSH.LogCollectPing() +elif re.match('^LogCollectIperf$', mode, re.IGNORECASE): + if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCSourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + SSH.LogCollectIperf() +elif re.match('^LogCollectOAIUE$', mode, re.IGNORECASE): + if SSH.UEIPAddress == '' or SSH.UEUserName == '' or SSH.UEPassword == '' or SSH.UESourceCodePath == '': + Usage() + sys.exit('Insufficient Parameter') + SSH.LogCollectOAIUE() +elif re.match('^InitiateHtml$', mode, re.IGNORECASE): + if (SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == ''): + Usage() + sys.exit('Insufficient Parameter') + count = 0 + foundCount = 0 + while (count < SSH.nbTestXMLfiles): + xml_test_file = cwd + "/" + SSH.testXMLfiles[count] + xml_test_file = sys.path[0] + "/" + SSH.testXMLfiles[count] + if (os.path.isfile(xml_test_file)): + xmlTree = ET.parse(xml_test_file) + xmlRoot = xmlTree.getroot() + SSH.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count))) + SSH.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-' + str(count))) + SSH.htmlTabIcons.append(xmlRoot.findtext('htmlTabIcon',default='info-sign')) + foundCount += 1 + count += 1 + if foundCount != SSH.nbTestXMLfiles: + SSH.nbTestXMLfiles = foundCount + SSH.CreateHtmlHeader() +elif re.match('^FinalizeHtml$', mode, re.IGNORECASE): + SSH.CreateHtmlFooter(SSH.finalStatus) +elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re.IGNORECASE): + if re.match('^TesteNB$', mode, re.IGNORECASE): + if SSH.eNBIPAddress == '' or SSH.ranRepository == '' or SSH.ranBranch == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '' or SSH.eNBSourceCodePath == '' or SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '' or SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == '': + Usage() + sys.exit('Insufficient Parameter') + + if (SSH.EPCIPAddress != '') and (SSH.EPCIPAddress != 'none'): + SSH.copyout(SSH.EPCIPAddress, SSH.EPCUserName, SSH.EPCPassword, cwd + "/tcp_iperf_stats.awk", "/tmp") + SSH.copyout(SSH.EPCIPAddress, SSH.EPCUserName, SSH.EPCPassword, cwd + "/active_net_interfaces.awk", "/tmp") + else: + if SSH.UEIPAddress == '' or SSH.ranRepository == '' or SSH.ranBranch == '' or SSH.UEUserName == '' or SSH.UEPassword == '' or SSH.UESourceCodePath == '': + Usage() + sys.exit('UE: Insufficient Parameter') + + #read test_case_list.xml file + # if no parameters for XML file, use default value + if (SSH.nbTestXMLfiles != 1): + xml_test_file = cwd + "/test_case_list.xml" + else: + xml_test_file = cwd + "/" + SSH.testXMLfiles[0] + + xmlTree = ET.parse(xml_test_file) + xmlRoot = xmlTree.getroot() + + exclusion_tests=xmlRoot.findtext('TestCaseExclusionList',default='') + requested_tests=xmlRoot.findtext('TestCaseRequestedList',default='') + if (SSH.nbTestXMLfiles == 1): + SSH.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-0')) + SSH.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-0')) + repeatCount = xmlRoot.findtext('repeatCount',default='1') + SSH.repeatCounts.append(int(repeatCount)) + all_tests=xmlRoot.findall('testCase') + + exclusion_tests=exclusion_tests.split() + requested_tests=requested_tests.split() + + #check that exclusion tests are well formatted + #(6 digits or less than 6 digits followed by +) + for test in exclusion_tests: + if (not re.match('^[0-9]{6}$', test) and + not re.match('^[0-9]{1,5}\+$', test)): + logging.debug('ERROR: exclusion test is invalidly formatted: ' + test) + sys.exit(1) + else: + logging.debug(test) + + #check that requested tests are well formatted + #(6 digits or less than 6 digits followed by +) + #be verbose + for test in requested_tests: + if (re.match('^[0-9]{6}$', test) or + re.match('^[0-9]{1,5}\+$', test)): + logging.debug('INFO: test group/case requested: ' + test) + else: + logging.debug('ERROR: requested test is invalidly formatted: ' + test) + sys.exit(1) + if (SSH.EPCIPAddress != '') and (SSH.EPCIPAddress != 'none'): + SSH.CheckFlexranCtrlInstallation() + + #get the list of tests to be done + todo_tests=[] + for test in requested_tests: + if (test_in_list(test, exclusion_tests)): + logging.debug('INFO: test will be skipped: ' + test) + else: + #logging.debug('INFO: test will be run: ' + test) + todo_tests.append(test) + + signal.signal(signal.SIGUSR1, receive_signal) + + SSH.CreateHtmlTabHeader() + + self.cnt = 0 + SSH.prematureExit = True + SSH.startTime = int(round(time.time() * 1000)) + while self.cnt < SSH.repeatCounts[0] and SSH.prematureExit: + SSH.prematureExit = False + for test_case_id in todo_tests: + if SSH.prematureExit: + break + for test in all_tests: + if SSH.prematureExit: + break + id = test.get('id') + if test_case_id != id: + continue + SSH.testCase_id = id + SSH.desc = test.findtext('desc') + action = test.findtext('class') + if (CheckClassValidity(action, id) == False): + continue + SSH.ShowTestID() + GetParametersFromXML(action) + if action == 'Initialize_UE' or action == 'Attach_UE' or action == 'Detach_UE' or action == 'Ping' or action == 'Iperf' or action == 'Reboot_UE' or action == 'DataDisable_UE' or action == 'DataEnable_UE' or action == 'CheckStatusUE': + if (SSH.ADBIPAddress != 'none'): + terminate_ue_flag = False + SSH.GetAllUEDevices(terminate_ue_flag) + if action == 'Build_eNB': + SSH.BuildeNB() + elif action == 'WaitEndBuild_eNB': + SSH.WaitBuildeNBisFinished() + elif action == 'Initialize_eNB': + SSH.InitializeeNB() + elif action == 'Terminate_eNB': + SSH.TerminateeNB() + elif action == 'Initialize_UE': + SSH.InitializeUE() + elif action == 'Terminate_UE': + SSH.TerminateUE() + elif action == 'Attach_UE': + SSH.AttachUE() + elif action == 'Detach_UE': + SSH.DetachUE() + elif action == 'DataDisable_UE': + SSH.DataDisableUE() + elif action == 'DataEnable_UE': + SSH.DataEnableUE() + elif action == 'CheckStatusUE': + SSH.CheckStatusUE() + elif action == 'Build_OAI_UE': + SSH.BuildOAIUE() + elif action == 'Initialize_OAI_UE': + SSH.InitializeOAIUE() + elif action == 'Terminate_OAI_UE': + SSH.TerminateOAIUE() + elif action == 'Initialize_CatM_module': + SSH.InitializeCatM() + elif action == 'Terminate_CatM_module': + SSH.TerminateCatM() + elif action == 'Attach_CatM_module': + SSH.AttachCatM() + elif action == 'Detach_CatM_module': + SSH.TerminateCatM() + elif action == 'Ping_CatM_module': + SSH.PingCatM() + elif action == 'Ping': + SSH.Ping() + elif action == 'Iperf': + SSH.Iperf() + elif action == 'Reboot_UE': + SSH.RebootUE() + elif action == 'Initialize_HSS': + SSH.InitializeHSS() + elif action == 'Terminate_HSS': + SSH.TerminateHSS() + elif action == 'Initialize_MME': + SSH.InitializeMME() + elif action == 'Terminate_MME': + SSH.TerminateMME() + elif action == 'Initialize_SPGW': + SSH.InitializeSPGW() + elif action == 'Terminate_SPGW': + SSH.TerminateSPGW() + elif action == 'Initialize_FlexranCtrl': + SSH.InitializeFlexranCtrl() + elif action == 'Terminate_FlexranCtrl': + SSH.TerminateFlexranCtrl() + elif action == 'IdleSleep': + SSH.IdleSleep() + elif action == 'Perform_X2_Handover': + SSH.Perform_X2_Handover() + else: + sys.exit('Invalid action') + self.cnt += 1 + if self.cnt == SSH.repeatCounts[0] and SSH.prematureExit: + logging.debug('Testsuite failed ' + str(self.cnt) + ' time(s)') + SSH.CreateHtmlTabFooter(False) + sys.exit('Failed Scenario') + else: + logging.info('Testsuite passed after ' + str(self.cnt) + ' time(s)') + SSH.CreateHtmlTabFooter(True) +else: + Usage() + sys.exit('Invalid mode') +sys.exit(0) From 28eb2d61bb2c55caad713b0af2d2ec88116464f5 Mon Sep 17 00:00:00 2001 From: Gabriele Perrone Date: Mon, 9 Dec 2019 22:04:22 +0100 Subject: [PATCH 070/240] fixing self.cnt to SSH.cnt mistake --- ci-scripts/main-index-to-class.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ci-scripts/main-index-to-class.py b/ci-scripts/main-index-to-class.py index 04a31302ae..e782d30ae0 100644 --- a/ci-scripts/main-index-to-class.py +++ b/ci-scripts/main-index-to-class.py @@ -4816,10 +4816,10 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re SSH.CreateHtmlTabHeader() - self.cnt = 0 + SSH.cnt = 0 SSH.prematureExit = True SSH.startTime = int(round(time.time() * 1000)) - while self.cnt < SSH.repeatCounts[0] and SSH.prematureExit: + while SSH.cnt < SSH.repeatCounts[0] and SSH.prematureExit: SSH.prematureExit = False for test_case_id in todo_tests: if SSH.prematureExit: @@ -4907,13 +4907,13 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re SSH.Perform_X2_Handover() else: sys.exit('Invalid action') - self.cnt += 1 - if self.cnt == SSH.repeatCounts[0] and SSH.prematureExit: - logging.debug('Testsuite failed ' + str(self.cnt) + ' time(s)') + SSH.cnt += 1 + if SSH.cnt == SSH.repeatCounts[0] and SSH.prematureExit: + logging.debug('Testsuite failed ' + str(SSH.cnt) + ' time(s)') SSH.CreateHtmlTabFooter(False) sys.exit('Failed Scenario') else: - logging.info('Testsuite passed after ' + str(self.cnt) + ' time(s)') + logging.info('Testsuite passed after ' + str(SSH.cnt) + ' time(s)') SSH.CreateHtmlTabFooter(True) else: Usage() From 581e46f1d3d447dc3af86ff0305ba9133a84fb3a Mon Sep 17 00:00:00 2001 From: Gabriele Perrone Date: Wed, 11 Dec 2019 14:28:14 +0100 Subject: [PATCH 071/240] introduced a class object FailRepeatCnt in place of a static counter --- ci-scripts/main-index-to-class.py | 98 +++++++++++++++---------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/ci-scripts/main-index-to-class.py b/ci-scripts/main-index-to-class.py index e782d30ae0..68b9558740 100644 --- a/ci-scripts/main-index-to-class.py +++ b/ci-scripts/main-index-to-class.py @@ -93,7 +93,7 @@ logging.basicConfig( #----------------------------------------------------------- class SSHConnection(): def __init__(self): - self.cnt = 0 # cnt from index to object of a class + self.FailReportCnt = 0 # FailReportCnt was an index inside the SSH instantiation (called "cnt"), now it becomes an object self.prematureExit = False self.ranRepository = '' self.ranBranch = '' @@ -1433,11 +1433,11 @@ class SSHConnection(): html_queue.put(html_cell) if (attach_status): # cnt from index to object of a class - self.cnt = 0 - while self.cnt < len(self.UEDevices): - if self.UEDevicesStatus[self.cnt] == UE_STATUS_ATTACHING: - self.UEDevicesStatus[self.cnt] = UE_STATUS_ATTACHED - self.cnt += 1 + cnt = 0 + while cnt < len(self.UEDevices): + if self.UEDevicesStatus[cnt] == UE_STATUS_ATTACHING: + self.UEDevicesStatus[cnt] = UE_STATUS_ATTACHED + cnt += 1 self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) result = re.search('T_stdout', str(self.Initialize_eNB_args)) if result is not None: @@ -1474,14 +1474,14 @@ class SSHConnection(): self.AutoTerminateUEandeNB() return multi_jobs = [] - self.cnt = 0 + cnt = 0 for device_id in self.UEDevices: - self.UEDevicesStatus[self.cnt] = UE_STATUS_DETACHING - p = Process(target = self.DetachUE_common, args = (device_id,self.cnt,)) + self.UEDevicesStatus[cnt] = UE_STATUS_DETACHING + p = Process(target = self.DetachUE_common, args = (device_id,cnt,)) p.daemon = True p.start() multi_jobs.append(p) - self.cnt += 1 + cnt += 1 for job in multi_jobs: job.join() self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) @@ -1489,10 +1489,10 @@ class SSHConnection(): if result is not None: logging.debug('Waiting 5 seconds to fill up record file') time.sleep(5) - self.cnt = 0 - while self.cnt < len(self.UEDevices): - self.UEDevicesStatus[self.cnt] = UE_STATUS_DETACHED - self.cnt += 1 + cnt = 0 + while cnt < len(self.UEDevices): + self.UEDevicesStatus[cnt] = UE_STATUS_DETACHED + cnt += 1 def RebootUE_common(self, device_id): try: @@ -1650,10 +1650,10 @@ class SSHConnection(): logging.debug('\u001B[1;37;41m UE Not Found! \u001B[0m') sys.exit(1) if len(self.UEDevicesStatus) == 0: - self.cnt = 0 - while self.cnt < len(self.UEDevices): + cnt = 0 + while cnt < len(self.UEDevices): self.UEDevicesStatus.append(UE_STATUS_DETACHED) - self.cnt += 1 + cnt += 1 def GetAllCatMDevices(self, terminate_ue_flag): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': @@ -3735,38 +3735,38 @@ class SSHConnection(): cmd = "jq '.mac_stats | length' " + fileName strNbEnbs = subprocess.check_output(cmd, shell=True, universal_newlines=True) self.x2NbENBs = int(strNbEnbs.strip()) - self.cnt = 0 - while self.cnt < self.x2NbENBs: - cmd = "jq '.mac_stats[" + str(self.cnt) + "].bs_id' " + fileName + cnt = 0 + while cnt < self.x2NbENBs: + cmd = "jq '.mac_stats[" + str(cnt) + "].bs_id' " + fileName bs_id = subprocess.check_output(cmd, shell=True, universal_newlines=True) self.x2ENBBsIds[idx].append(bs_id.strip()) - cmd = "jq '.mac_stats[" + str(self.cnt) + "].ue_mac_stats | length' " + fileName + cmd = "jq '.mac_stats[" + str(cnt) + "].ue_mac_stats | length' " + fileName stNbUEs = subprocess.check_output(cmd, shell=True, universal_newlines=True) nbUEs = int(stNbUEs.strip()) ueIdx = 0 self.x2ENBConnectedUEs[idx].append([]) while ueIdx < nbUEs: - cmd = "jq '.mac_stats[" + str(self.cnt) + "].ue_mac_stats[" + str(ueIdx) + "].rnti' " + fileName + cmd = "jq '.mac_stats[" + str(cnt) + "].ue_mac_stats[" + str(ueIdx) + "].rnti' " + fileName rnti = subprocess.check_output(cmd, shell=True, universal_newlines=True) - self.x2ENBConnectedUEs[idx][self.cnt].append(rnti.strip()) + self.x2ENBConnectedUEs[idx][cnt].append(rnti.strip()) ueIdx += 1 - self.cnt += 1 + cnt += 1 msg = "FlexRan Controller is connected to " + str(self.x2NbENBs) + " eNB(s)" logging.debug(msg) message += msg + '\n' - self.cnt = 0 - while self.cnt < self.x2NbENBs: - msg = " -- eNB: " + str(self.x2ENBBsIds[idx][self.cnt]) + " is connected to " + str(len(self.x2ENBConnectedUEs[idx][self.cnt])) + " UE(s)" + cnt = 0 + while cnt < self.x2NbENBs: + msg = " -- eNB: " + str(self.x2ENBBsIds[idx][cnt]) + " is connected to " + str(len(self.x2ENBConnectedUEs[idx][self.cnt])) + " UE(s)" logging.debug(msg) message += msg + '\n' ueIdx = 0 - while ueIdx < len(self.x2ENBConnectedUEs[idx][self.cnt]): - msg = " -- UE rnti: " + str(self.x2ENBConnectedUEs[idx][self.cnt][ueIdx]) + while ueIdx < len(self.x2ENBConnectedUEs[idx][cnt]): + msg = " -- UE rnti: " + str(self.x2ENBConnectedUEs[idx][cnt][ueIdx]) logging.debug(msg) message += msg + '\n' ueIdx += 1 - self.cnt += 1 + cnt += 1 return message def Perform_X2_Handover(self): @@ -3789,38 +3789,38 @@ class SSHConnection(): logging.debug(msg) fullMessage += msg + '\n' eNB_cnt = self.x2NbENBs - self.cnt = 0 - while self.cnt < eNB_cnt: - cmd = "curl -XPOST http://" + self.EPCIPAddress + ":9999/rrc/x2_ho_net_control/enb/" + str(self.x2ENBBsIds[0][self.cnt]) + "/1" + cnt = 0 + while cnt < eNB_cnt: + cmd = "curl -XPOST http://" + self.EPCIPAddress + ":9999/rrc/x2_ho_net_control/enb/" + str(self.x2ENBBsIds[0][cnt]) + "/1" logging.debug(cmd) fullMessage += cmd + '\n' subprocess.run(cmd, shell=True) - self.cnt += 1 + cnt += 1 # Waiting for the activation to be active time.sleep(10) msg = "Switching UE(s) from eNB to eNB" logging.debug(msg) fullMessage += msg + '\n' - self.cnt = 0 - while self.cnt < eNB_cnt: + cnt = 0 + while cnt < eNB_cnt: ueIdx = 0 - while ueIdx < len(self.x2ENBConnectedUEs[0][self.cnt]): - cmd = "curl -XPOST http://" + self.EPCIPAddress + ":9999/rrc/ho/senb/" + str(self.x2ENBBsIds[0][self.cnt]) + "/ue/" + str(self.x2ENBConnectedUEs[0][cnt][ueIdx]) + "/tenb/" + str(self.x2ENBBsIds[0][eNB_cnt - cnt - 1]) + while ueIdx < len(self.x2ENBConnectedUEs[0][cnt]): + cmd = "curl -XPOST http://" + self.EPCIPAddress + ":9999/rrc/ho/senb/" + str(self.x2ENBBsIds[0][cnt]) + "/ue/" + str(self.x2ENBConnectedUEs[0][cnt][ueIdx]) + "/tenb/" + str(self.x2ENBBsIds[0][eNB_cnt - cnt - 1]) logging.debug(cmd) fullMessage += cmd + '\n' subprocess.run(cmd, shell=True) ueIdx += 1 - self.cnt += 1 + cnt += 1 time.sleep(10) # check logging.debug("Checking the Status after X2 Handover") fullMessage += self.X2_Status(1, self.testCase_id + '_post_ho.json') - self.cnt = 0 + cnt = 0 x2Status = True - while self.cnt < eNB_cnt: - if len(self.x2ENBConnectedUEs[0][self.cnt]) == len(self.x2ENBConnectedUEs[1][cnt]): + while cnt < eNB_cnt: + if len(self.x2ENBConnectedUEs[0][cnt]) == len(self.x2ENBConnectedUEs[1][cnt]): x2Status = False - self.cnt += 1 + cnt += 1 if x2Status: msg = "X2 Handover was successful" logging.debug(msg) @@ -4816,10 +4816,10 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re SSH.CreateHtmlTabHeader() - SSH.cnt = 0 + SSH.FailReportCnt = 0 SSH.prematureExit = True SSH.startTime = int(round(time.time() * 1000)) - while SSH.cnt < SSH.repeatCounts[0] and SSH.prematureExit: + while SSH.FailReportCnt < SSH.repeatCounts[0] and SSH.prematureExit: SSH.prematureExit = False for test_case_id in todo_tests: if SSH.prematureExit: @@ -4907,13 +4907,13 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re SSH.Perform_X2_Handover() else: sys.exit('Invalid action') - SSH.cnt += 1 - if SSH.cnt == SSH.repeatCounts[0] and SSH.prematureExit: - logging.debug('Testsuite failed ' + str(SSH.cnt) + ' time(s)') + SSH.FailReportCnt += 1 + if SSH.FailReportCnt == SSH.repeatCounts[0] and SSH.prematureExit: + logging.debug('Testsuite failed ' + str(SSH.FailReportCnt) + ' time(s)') SSH.CreateHtmlTabFooter(False) sys.exit('Failed Scenario') else: - logging.info('Testsuite passed after ' + str(SSH.cnt) + ' time(s)') + logging.info('Testsuite passed after ' + str(SSH.FailReportCnt) + ' time(s)') SSH.CreateHtmlTabFooter(True) else: Usage() From ed6559ffa970503b5dcac77ec340457bf1b006f3 Mon Sep 17 00:00:00 2001 From: laurent Date: Thu, 12 Dec 2019 10:37:53 +0100 Subject: [PATCH 072/240] add CU measurement: whole CPU active time per subframe --- executables/main-fs6.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index 0dbd9a3b45..ab57bc611d 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -1408,6 +1408,7 @@ void UL_du_fs6(RU_t *ru, L1_rxtx_proc_t *proc) { } void DL_cu_fs6(RU_t *ru, L1_rxtx_proc_t *proc, uint64_t DuClock, uint64_t startCycle) { + initRefTimes(CUprocessing); // Fixme: datamodel issue PHY_VARS_eNB *eNB = RC.eNB[0][0]; pthread_mutex_lock(&eNB->UL_INFO_mutex); @@ -1429,6 +1430,7 @@ void DL_cu_fs6(RU_t *ru, L1_rxtx_proc_t *proc, uint64_t DuClock, uint64_t start hDL(bufferZone)->DuClock=DuClock; hDL(bufferZone)->CuSpentMicroSec=(rdtsc()-startCycle)/(cpuf*1000); + updateTimesReset(startCycle, &CUprocessing, 1000, true,"CU entire processing from recv to send"); sendSubFrame(&sockFS6, bufferZone, sizeof(fs6_dl_t), CTsentCUv0 ); return; } From ae3a540f40d80119abd6770d851ddc7f811b3fd2 Mon Sep 17 00:00:00 2001 From: projetstc <> Date: Mon, 16 Dec 2019 11:37:51 +0100 Subject: [PATCH 073/240] scope autoscale --- openair1/PHY/TOOLS/lte_phy_scope.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/openair1/PHY/TOOLS/lte_phy_scope.c b/openair1/PHY/TOOLS/lte_phy_scope.c index 3ac1676983..c5111957e9 100644 --- a/openair1/PHY/TOOLS/lte_phy_scope.c +++ b/openair1/PHY/TOOLS/lte_phy_scope.c @@ -325,12 +325,18 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, // PUSCH I/Q of MF Output if (pusch_comp!=NULL) { ind=0; + int range=80*1000*1000; for (k=0; ksymbols_per_tti; k++) { for (i=0; i<12*frame_parms->N_RB_UL; i++) { - I[ind] = pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i]; - Q[ind] = pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i+1]; - ind++; + if ( pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i] > -range && + pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i] < range && + pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i+1] > -range && + pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i+1] < range ) { + I[ind] = pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i]; + Q[ind] = pusch_comp[(2*frame_parms->N_RB_UL*12*k)+2*i+1]; + ind++; + } } } From 091be33b629e69e66598be17b93cb619c0a47da6 Mon Sep 17 00:00:00 2001 From: Gabriele Perrone Date: Mon, 16 Dec 2019 15:59:54 +0100 Subject: [PATCH 074/240] main.py mods: coloured rows between retries and variable cnt become an object (FailReportCnt) --- ci-scripts/main.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index bac3599150..78c0d1fc99 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -93,6 +93,7 @@ logging.basicConfig( #----------------------------------------------------------- class SSHConnection(): def __init__(self): + self.FailReportCnt = 0 self.prematureExit = False self.ranRepository = '' self.ranBranch = '' @@ -4213,6 +4214,12 @@ class SSHConnection(): self.htmlFile.write('\n') self.htmlFile.close() + def CreateHtmlRetrySeparator(self): + if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): + self.htmlFile.write(' \n') + self.htmlFile.write(' Try Run #' + str(self.FailReportCnt) + '\n') + self.htmlFile.write(' \n') + def CreateHtmlTestRow(self, options, status, processesStatus, machine='eNB'): if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): currentTime = int(round(time.time() * 1000)) - self.startTime @@ -4814,11 +4821,13 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re SSH.CreateHtmlTabHeader() - cnt = 0 + SSH.FailReportCnt = 0 SSH.prematureExit = True SSH.startTime = int(round(time.time() * 1000)) - while cnt < SSH.repeatCounts[0] and SSH.prematureExit: + while SSH.FailReportCnt < SSH.repeatCounts[0] and SSH.prematureExit: SSH.prematureExit = False + # At every iteratin of the retry loop, a separator will be added + SSH.CreateHtmlRetrySeparator() for test_case_id in todo_tests: if SSH.prematureExit: break @@ -4905,13 +4914,13 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re SSH.Perform_X2_Handover() else: sys.exit('Invalid action') - cnt += 1 - if cnt == SSH.repeatCounts[0] and SSH.prematureExit: - logging.debug('Testsuite failed ' + str(cnt) + ' time(s)') + SSH.FailReportCnt += 1 + if SSH.FailReportCnt == SSH.repeatCounts[0] and SSH.prematureExit: + logging.debug('Testsuite failed ' + str(SSH.FailReportCnt) + ' time(s)') SSH.CreateHtmlTabFooter(False) sys.exit('Failed Scenario') else: - logging.info('Testsuite passed after ' + str(cnt) + ' time(s)') + logging.info('Testsuite passed after ' + str(SSH.FailReportCnt) + ' time(s)') SSH.CreateHtmlTabFooter(True) else: Usage() From 4d57f1bda8b4e068c70c1f4c9d208278117bea89 Mon Sep 17 00:00:00 2001 From: Gabriele Perrone Date: Tue, 7 Jan 2020 14:43:49 +0100 Subject: [PATCH 075/240] class name changed from SSH to CiTestObj --- ci-scripts/main.py | 420 ++++++++++++++++++++++----------------------- 1 file changed, 210 insertions(+), 210 deletions(-) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 78c0d1fc99..bb0e92a23f 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -91,7 +91,7 @@ logging.basicConfig( #----------------------------------------------------------- # Class Declaration #----------------------------------------------------------- -class SSHConnection(): +class OaiCiTest(): def __init__(self): self.FailReportCnt = 0 self.prematureExit = False @@ -230,7 +230,7 @@ class SSHConnection(): if connect_status: pass else: - sys.exit('SSH Connection Failed') + sys.exit('CiTestObj.Connection Failed') def command(self, commandline, expectedline, timeout): logging.debug(commandline) @@ -2810,7 +2810,7 @@ class SSHConnection(): status_queue = SimpleQueue() for UE_IPAddress in self.UEIPAddresses: device_id = self.UEDevices[i] - p = Process(target = SSH.Iperf_common, args = (lock,UE_IPAddress,device_id,i,ue_num,status_queue,)) + p = Process(target = CiTestObj.Iperf_common, args = (lock,UE_IPAddress,device_id,i,ue_num,status_queue,)) p.daemon = True p.start() multi_jobs.append(p) @@ -2850,15 +2850,15 @@ class SSHConnection(): # in noS1 config, no need to check status from EPC result = re.search('noS1', str(self.Initialize_eNB_args)) if result is None: - p = Process(target = SSH.CheckHSSProcess, args = (status_queue,)) + p = Process(target = CiTestObj.CheckHSSProcess, args = (status_queue,)) p.daemon = True p.start() multi_jobs.append(p) - p = Process(target = SSH.CheckMMEProcess, args = (status_queue,)) + p = Process(target = CiTestObj.CheckMMEProcess, args = (status_queue,)) p.daemon = True p.start() multi_jobs.append(p) - p = Process(target = SSH.CheckSPGWProcess, args = (status_queue,)) + p = Process(target = CiTestObj.CheckSPGWProcess, args = (status_queue,)) p.daemon = True p.start() multi_jobs.append(p) @@ -2866,12 +2866,12 @@ class SSHConnection(): if (check_eNB == False) and (check_OAI_UE == False): return 0 if check_eNB: - p = Process(target = SSH.CheckeNBProcess, args = (status_queue,)) + p = Process(target = CiTestObj.CheckeNBProcess, args = (status_queue,)) p.daemon = True p.start() multi_jobs.append(p) if check_OAI_UE: - p = Process(target = SSH.CheckOAIUEProcess, args = (status_queue,)) + p = Process(target = CiTestObj.CheckOAIUEProcess, args = (status_queue,)) p.daemon = True p.start() multi_jobs.append(p) @@ -2902,7 +2902,7 @@ class SSHConnection(): multi_jobs = [] status_queue = SimpleQueue() if initialize_OAI_UE_flag == False: - p = Process(target = SSH.CheckOAIUEProcess, args = (status_queue,)) + p = Process(target = CiTestObj.CheckOAIUEProcess, args = (status_queue,)) p.daemon = True p.start() multi_jobs.append(p) @@ -3639,7 +3639,7 @@ class SSHConnection(): multi_jobs = [] i = 0 for device_id in self.UEDevices: - p = Process(target= SSH.TerminateUE_common, args = (device_id,i,)) + p = Process(target= CiTestObj.TerminateUE_common, args = (device_id,i,)) p.daemon = True p.start() multi_jobs.append(p) @@ -4382,108 +4382,108 @@ def CheckClassValidity(action,id): def GetParametersFromXML(action): if action == 'Build_eNB': - SSH.Build_eNB_args = test.findtext('Build_eNB_args') - SSH.eNB_instance = test.findtext('eNB_instance') - if (SSH.eNB_instance is None): - SSH.eNB_instance = '0' - SSH.eNB_serverId = test.findtext('eNB_serverId') - if (SSH.eNB_serverId is None): - SSH.eNB_serverId = '0' + CiTestObj.Build_eNB_args = test.findtext('Build_eNB_args') + CiTestObj.eNB_instance = test.findtext('eNB_instance') + if (CiTestObj.eNB_instance is None): + CiTestObj.eNB_instance = '0' + CiTestObj.eNB_serverId = test.findtext('eNB_serverId') + if (CiTestObj.eNB_serverId is None): + CiTestObj.eNB_serverId = '0' xmlBgBuildField = test.findtext('backgroundBuild') if (xmlBgBuildField is None): - SSH.backgroundBuild = False + CiTestObj.backgroundBuild = False else: if re.match('true', xmlBgBuildField, re.IGNORECASE): - SSH.backgroundBuild = True + CiTestObj.backgroundBuild = True else: - SSH.backgroundBuild = False + CiTestObj.backgroundBuild = False if action == 'WaitEndBuild_eNB': - SSH.Build_eNB_args = test.findtext('Build_eNB_args') - SSH.eNB_instance = test.findtext('eNB_instance') - if (SSH.eNB_instance is None): - SSH.eNB_instance = '0' - SSH.eNB_serverId = test.findtext('eNB_serverId') - if (SSH.eNB_serverId is None): - SSH.eNB_serverId = '0' + CiTestObj.Build_eNB_args = test.findtext('Build_eNB_args') + CiTestObj.eNB_instance = test.findtext('eNB_instance') + if (CiTestObj.eNB_instance is None): + CiTestObj.eNB_instance = '0' + CiTestObj.eNB_serverId = test.findtext('eNB_serverId') + if (CiTestObj.eNB_serverId is None): + CiTestObj.eNB_serverId = '0' if action == 'Initialize_eNB': - SSH.Initialize_eNB_args = test.findtext('Initialize_eNB_args') - SSH.eNB_instance = test.findtext('eNB_instance') - if (SSH.eNB_instance is None): - SSH.eNB_instance = '0' - SSH.eNB_serverId = test.findtext('eNB_serverId') - if (SSH.eNB_serverId is None): - SSH.eNB_serverId = '0' + CiTestObj.Initialize_eNB_args = test.findtext('Initialize_eNB_args') + CiTestObj.eNB_instance = test.findtext('eNB_instance') + if (CiTestObj.eNB_instance is None): + CiTestObj.eNB_instance = '0' + CiTestObj.eNB_serverId = test.findtext('eNB_serverId') + if (CiTestObj.eNB_serverId is None): + CiTestObj.eNB_serverId = '0' if action == 'Terminate_eNB': - SSH.eNB_instance = test.findtext('eNB_instance') - if (SSH.eNB_instance is None): - SSH.eNB_instance = '0' - SSH.eNB_serverId = test.findtext('eNB_serverId') - if (SSH.eNB_serverId is None): - SSH.eNB_serverId = '0' + CiTestObj.eNB_instance = test.findtext('eNB_instance') + if (CiTestObj.eNB_instance is None): + CiTestObj.eNB_instance = '0' + CiTestObj.eNB_serverId = test.findtext('eNB_serverId') + if (CiTestObj.eNB_serverId is None): + CiTestObj.eNB_serverId = '0' if action == 'Attach_UE': nbMaxUEtoAttach = test.findtext('nbMaxUEtoAttach') if (nbMaxUEtoAttach is None): - SSH.nbMaxUEtoAttach = -1 + CiTestObj.nbMaxUEtoAttach = -1 else: - SSH.nbMaxUEtoAttach = int(nbMaxUEtoAttach) + CiTestObj.nbMaxUEtoAttach = int(nbMaxUEtoAttach) if action == 'CheckStatusUE': expectedNBUE = test.findtext('expectedNbOfConnectedUEs') if (expectedNBUE is None): - SSH.expectedNbOfConnectedUEs = -1 + CiTestObj.expectedNbOfConnectedUEs = -1 else: - SSH.expectedNbOfConnectedUEs = int(expectedNBUE) + CiTestObj.expectedNbOfConnectedUEs = int(expectedNBUE) if action == 'Build_OAI_UE': - SSH.Build_OAI_UE_args = test.findtext('Build_OAI_UE_args') + CiTestObj.Build_OAI_UE_args = test.findtext('Build_OAI_UE_args') if action == 'Initialize_OAI_UE': - SSH.Initialize_OAI_UE_args = test.findtext('Initialize_OAI_UE_args') - SSH.UE_instance = test.findtext('UE_instance') - if (SSH.UE_instance is None): - SSH.UE_instance = '0' + CiTestObj.Initialize_OAI_UE_args = test.findtext('Initialize_OAI_UE_args') + CiTestObj.UE_instance = test.findtext('UE_instance') + if (CiTestObj.UE_instance is None): + CiTestObj.UE_instance = '0' if action == 'Terminate_OAI_UE': - SSH.eNB_instance = test.findtext('UE_instance') - if (SSH.UE_instance is None): - SSH.UE_instance = '0' + CiTestObj.eNB_instance = test.findtext('UE_instance') + if (CiTestObj.UE_instance is None): + CiTestObj.UE_instance = '0' if action == 'Ping' or action == 'Ping_CatM_module': - SSH.ping_args = test.findtext('ping_args') - SSH.ping_packetloss_threshold = test.findtext('ping_packetloss_threshold') + CiTestObj.ping_args = test.findtext('ping_args') + CiTestObj.ping_packetloss_threshold = test.findtext('ping_packetloss_threshold') if action == 'Iperf': - SSH.iperf_args = test.findtext('iperf_args') - SSH.iperf_packetloss_threshold = test.findtext('iperf_packetloss_threshold') - SSH.iperf_profile = test.findtext('iperf_profile') - if (SSH.iperf_profile is None): - SSH.iperf_profile = 'balanced' + CiTestObj.iperf_args = test.findtext('iperf_args') + CiTestObj.iperf_packetloss_threshold = test.findtext('iperf_packetloss_threshold') + CiTestObj.iperf_profile = test.findtext('iperf_profile') + if (CiTestObj.iperf_profile is None): + CiTestObj.iperf_profile = 'balanced' else: - if SSH.iperf_profile != 'balanced' and SSH.iperf_profile != 'unbalanced' and SSH.iperf_profile != 'single-ue': - logging.debug('ERROR: test-case has wrong profile ' + SSH.iperf_profile) - SSH.iperf_profile = 'balanced' + if CiTestObj.iperf_profile != 'balanced' and CiTestObj.iperf_profile != 'unbalanced' and CiTestObj.iperf_profile != 'single-ue': + logging.debug('ERROR: test-case has wrong profile ' + CiTestObj.iperf_profile) + CiTestObj.iperf_profile = 'balanced' if action == 'IdleSleep': string_field = test.findtext('idle_sleep_time_in_sec') if (string_field is None): - SSH.idle_sleep_time = 5 + CiTestObj.idle_sleep_time = 5 else: - SSH.idle_sleep_time = int(string_field) + CiTestObj.idle_sleep_time = int(string_field) if action == 'Perform_X2_Handover': string_field = test.findtext('x2_ho_options') if (string_field is None): - SSH.x2_ho_options = 'network' + CiTestObj.x2_ho_options = 'network' else: if string_field != 'network': logging.error('ERROR: test-case has wrong option ' + string_field) - SSH.x2_ho_options = 'network' + CiTestObj.x2_ho_options = 'network' else: - SSH.x2_ho_options = string_field + CiTestObj.x2_ho_options = string_field #check if given test is in list @@ -4502,7 +4502,7 @@ def receive_signal(signum, frame): # Parameter Check #----------------------------------------------------------- mode = '' -SSH = SSHConnection() +CiTestObj = OaiCiTest() argvs = sys.argv argc = len(argvs) @@ -4521,7 +4521,7 @@ while len(argvs) > 1: matchReg = re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE) else: matchReg = re.match('^\-\-ranRepository=(.+)$', myArgv, re.IGNORECASE) - SSH.ranRepository = matchReg.group(1) + CiTestObj.ranRepository = matchReg.group(1) elif re.match('^\-\-eNB_AllowMerge=(.+)$|^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE) @@ -4529,257 +4529,257 @@ while len(argvs) > 1: matchReg = re.match('^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE) doMerge = matchReg.group(1) if ((doMerge == 'true') or (doMerge == 'True')): - SSH.ranAllowMerge = True + CiTestObj.ranAllowMerge = True elif re.match('^\-\-eNBBranch=(.+)$|^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE) else: matchReg = re.match('^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE) - SSH.ranBranch = matchReg.group(1) + CiTestObj.ranBranch = matchReg.group(1) elif re.match('^\-\-eNBCommitID=(.*)$|^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE) else: matchReg = re.match('^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE) - SSH.ranCommitID = matchReg.group(1) + CiTestObj.ranCommitID = matchReg.group(1) elif re.match('^\-\-eNBTargetBranch=(.*)$|^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE) else: matchReg = re.match('^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE) - SSH.ranTargetBranch = matchReg.group(1) + CiTestObj.ranTargetBranch = matchReg.group(1) elif re.match('^\-\-eNBIPAddress=(.+)$|^\-\-eNB[1-2]IPAddress=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE) - SSH.eNBIPAddress = matchReg.group(1) + CiTestObj.eNBIPAddress = matchReg.group(1) elif re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB1IPAddress = matchReg.group(1) + CiTestObj.eNB1IPAddress = matchReg.group(1) elif re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB2IPAddress = matchReg.group(1) + CiTestObj.eNB2IPAddress = matchReg.group(1) elif re.match('^\-\-eNBUserName=(.+)$|^\-\-eNB[1-2]UserName=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE) - SSH.eNBUserName = matchReg.group(1) + CiTestObj.eNBUserName = matchReg.group(1) elif re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB1UserName = matchReg.group(1) + CiTestObj.eNB1UserName = matchReg.group(1) elif re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB2UserName = matchReg.group(1) + CiTestObj.eNB2UserName = matchReg.group(1) elif re.match('^\-\-eNBPassword=(.+)$|^\-\-eNB[1-2]Password=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE) - SSH.eNBPassword = matchReg.group(1) + CiTestObj.eNBPassword = matchReg.group(1) elif re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB1Password = matchReg.group(1) + CiTestObj.eNB1Password = matchReg.group(1) elif re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB2Password = matchReg.group(1) + CiTestObj.eNB2Password = matchReg.group(1) elif re.match('^\-\-eNBSourceCodePath=(.+)$|^\-\-eNB[1-2]SourceCodePath=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE) - SSH.eNBSourceCodePath = matchReg.group(1) + CiTestObj.eNBSourceCodePath = matchReg.group(1) elif re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB1SourceCodePath = matchReg.group(1) + CiTestObj.eNB1SourceCodePath = matchReg.group(1) elif re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB2SourceCodePath = matchReg.group(1) + CiTestObj.eNB2SourceCodePath = matchReg.group(1) elif re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE) - SSH.EPCIPAddress = matchReg.group(1) + CiTestObj.EPCIPAddress = matchReg.group(1) elif re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE) - SSH.EPCBranch = matchReg.group(1) + CiTestObj.EPCBranch = matchReg.group(1) elif re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE) - SSH.EPCUserName = matchReg.group(1) + CiTestObj.EPCUserName = matchReg.group(1) elif re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE) - SSH.EPCPassword = matchReg.group(1) + CiTestObj.EPCPassword = matchReg.group(1) elif re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE) - SSH.EPCSourceCodePath = matchReg.group(1) + CiTestObj.EPCSourceCodePath = matchReg.group(1) elif re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE) if re.match('OAI', matchReg.group(1), re.IGNORECASE) or re.match('ltebox', matchReg.group(1), re.IGNORECASE) or re.match('OAI-Rel14-CUPS', matchReg.group(1), re.IGNORECASE): - SSH.EPCType = matchReg.group(1) + CiTestObj.EPCType = matchReg.group(1) else: sys.exit('Invalid EPC Type: ' + matchReg.group(1) + ' -- (should be OAI or ltebox or OAI-Rel14-CUPS)') elif re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE) - SSH.ADBIPAddress = matchReg.group(1) + CiTestObj.ADBIPAddress = matchReg.group(1) elif re.match('^\-\-ADBUserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-ADBUserName=(.+)$', myArgv, re.IGNORECASE) - SSH.ADBUserName = matchReg.group(1) + CiTestObj.ADBUserName = matchReg.group(1) elif re.match('^\-\-ADBType=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-ADBType=(.+)$', myArgv, re.IGNORECASE) if re.match('centralized', matchReg.group(1), re.IGNORECASE) or re.match('distributed', matchReg.group(1), re.IGNORECASE): if re.match('distributed', matchReg.group(1), re.IGNORECASE): - SSH.ADBCentralized = False + CiTestObj.ADBCentralized = False else: - SSH.ADBCentralized = True + CiTestObj.ADBCentralized = True else: sys.exit('Invalid ADB Type: ' + matchReg.group(1) + ' -- (should be centralized or distributed)') elif re.match('^\-\-ADBPassword=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-ADBPassword=(.+)$', myArgv, re.IGNORECASE) - SSH.ADBPassword = matchReg.group(1) + CiTestObj.ADBPassword = matchReg.group(1) elif re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE) - SSH.testXMLfiles.append(matchReg.group(1)) - SSH.nbTestXMLfiles += 1 + CiTestObj.testXMLfiles.append(matchReg.group(1)) + CiTestObj.nbTestXMLfiles += 1 elif re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE) - SSH.UEIPAddress = matchReg.group(1) + CiTestObj.UEIPAddress = matchReg.group(1) elif re.match('^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE) - SSH.UEUserName = matchReg.group(1) + CiTestObj.UEUserName = matchReg.group(1) elif re.match('^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE) - SSH.UEPassword = matchReg.group(1) + CiTestObj.UEPassword = matchReg.group(1) elif re.match('^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE) - SSH.UESourceCodePath = matchReg.group(1) + CiTestObj.UESourceCodePath = matchReg.group(1) elif re.match('^\-\-finalStatus=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-finalStatus=(.+)$', myArgv, re.IGNORECASE) finalStatus = matchReg.group(1) if ((finalStatus == 'true') or (finalStatus == 'True')): - SSH.finalStatus = True + CiTestObj.finalStatus = True else: Usage() sys.exit('Invalid Parameter: ' + myArgv) if re.match('^TerminateeNB$', mode, re.IGNORECASE): - if SSH.eNBIPAddress == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '': + if CiTestObj.eNBIPAddress == '' or CiTestObj.eNBUserName == '' or CiTestObj.eNBPassword == '': Usage() sys.exit('Insufficient Parameter') - SSH.eNB_serverId = '0' - SSH.eNB_instance = '0' - SSH.eNBSourceCodePath = '/tmp/' - SSH.TerminateeNB() + CiTestObj.eNB_serverId = '0' + CiTestObj.eNB_instance = '0' + CiTestObj.eNBSourceCodePath = '/tmp/' + CiTestObj.TerminateeNB() elif re.match('^TerminateUE$', mode, re.IGNORECASE): - if (SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == ''): + if (CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == ''): Usage() sys.exit('Insufficient Parameter') signal.signal(signal.SIGUSR1, receive_signal) - SSH.TerminateUE() + CiTestObj.TerminateUE() elif re.match('^TerminateOAIUE$', mode, re.IGNORECASE): - if SSH.UEIPAddress == '' or SSH.UEUserName == '' or SSH.UEPassword == '': + if CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '': Usage() sys.exit('Insufficient Parameter') signal.signal(signal.SIGUSR1, receive_signal) - SSH.TerminateOAIUE() + CiTestObj.TerminateOAIUE() elif re.match('^TerminateHSS$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': + if CiTestObj.EPCIPAddress == '' or CiTestObj.EPCUserName == '' or CiTestObj.EPCPassword == '' or CiTestObj.EPCType == '' or CiTestObj.EPCSourceCodePath == '': Usage() sys.exit('Insufficient Parameter') - SSH.TerminateHSS() + CiTestObj.TerminateHSS() elif re.match('^TerminateMME$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': + if CiTestObj.EPCIPAddress == '' or CiTestObj.EPCUserName == '' or CiTestObj.EPCPassword == '' or CiTestObj.EPCType == '' or CiTestObj.EPCSourceCodePath == '': Usage() sys.exit('Insufficient Parameter') - SSH.TerminateMME() + CiTestObj.TerminateMME() elif re.match('^TerminateSPGW$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': + if CiTestObj.EPCIPAddress == '' or CiTestObj.EPCUserName == '' or CiTestObj.EPCPassword == '' or CiTestObj.EPCType == '' or CiTestObj.EPCSourceCodePath == '': Usage() sys.exit('Insufficient Parameter') - SSH.TerminateSPGW() + CiTestObj.TerminateSPGW() elif re.match('^LogCollectBuild$', mode, re.IGNORECASE): - if (SSH.eNBIPAddress == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '' or SSH.eNBSourceCodePath == '') and (SSH.UEIPAddress == '' or SSH.UEUserName == '' or SSH.UEPassword == '' or SSH.UESourceCodePath == ''): + if (CiTestObj.eNBIPAddress == '' or CiTestObj.eNBUserName == '' or CiTestObj.eNBPassword == '' or CiTestObj.eNBSourceCodePath == '') and (CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == ''): Usage() sys.exit('Insufficient Parameter') - SSH.LogCollectBuild() + CiTestObj.LogCollectBuild() elif re.match('^LogCollecteNB$', mode, re.IGNORECASE): - if SSH.eNBIPAddress == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '' or SSH.eNBSourceCodePath == '': + if CiTestObj.eNBIPAddress == '' or CiTestObj.eNBUserName == '' or CiTestObj.eNBPassword == '' or CiTestObj.eNBSourceCodePath == '': Usage() sys.exit('Insufficient Parameter') - SSH.LogCollecteNB() + CiTestObj.LogCollecteNB() elif re.match('^LogCollectHSS$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': + if CiTestObj.EPCIPAddress == '' or CiTestObj.EPCUserName == '' or CiTestObj.EPCPassword == '' or CiTestObj.EPCType == '' or CiTestObj.EPCSourceCodePath == '': Usage() sys.exit('Insufficient Parameter') - SSH.LogCollectHSS() + CiTestObj.LogCollectHSS() elif re.match('^LogCollectMME$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': + if CiTestObj.EPCIPAddress == '' or CiTestObj.EPCUserName == '' or CiTestObj.EPCPassword == '' or CiTestObj.EPCType == '' or CiTestObj.EPCSourceCodePath == '': Usage() sys.exit('Insufficient Parameter') - SSH.LogCollectMME() + CiTestObj.LogCollectMME() elif re.match('^LogCollectSPGW$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': + if CiTestObj.EPCIPAddress == '' or CiTestObj.EPCUserName == '' or CiTestObj.EPCPassword == '' or CiTestObj.EPCType == '' or CiTestObj.EPCSourceCodePath == '': Usage() sys.exit('Insufficient Parameter') - SSH.LogCollectSPGW() + CiTestObj.LogCollectSPGW() elif re.match('^LogCollectPing$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCSourceCodePath == '': + if CiTestObj.EPCIPAddress == '' or CiTestObj.EPCUserName == '' or CiTestObj.EPCPassword == '' or CiTestObj.EPCSourceCodePath == '': Usage() sys.exit('Insufficient Parameter') - SSH.LogCollectPing() + CiTestObj.LogCollectPing() elif re.match('^LogCollectIperf$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCSourceCodePath == '': + if CiTestObj.EPCIPAddress == '' or CiTestObj.EPCUserName == '' or CiTestObj.EPCPassword == '' or CiTestObj.EPCSourceCodePath == '': Usage() sys.exit('Insufficient Parameter') - SSH.LogCollectIperf() + CiTestObj.LogCollectIperf() elif re.match('^LogCollectOAIUE$', mode, re.IGNORECASE): - if SSH.UEIPAddress == '' or SSH.UEUserName == '' or SSH.UEPassword == '' or SSH.UESourceCodePath == '': + if CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == '': Usage() sys.exit('Insufficient Parameter') - SSH.LogCollectOAIUE() + CiTestObj.LogCollectOAIUE() elif re.match('^InitiateHtml$', mode, re.IGNORECASE): - if (SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == ''): + if (CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == ''): Usage() sys.exit('Insufficient Parameter') count = 0 foundCount = 0 - while (count < SSH.nbTestXMLfiles): - xml_test_file = cwd + "/" + SSH.testXMLfiles[count] - xml_test_file = sys.path[0] + "/" + SSH.testXMLfiles[count] + while (count < CiTestObj.nbTestXMLfiles): + xml_test_file = cwd + "/" + CiTestObj.testXMLfiles[count] + xml_test_file = sys.path[0] + "/" + CiTestObj.testXMLfiles[count] if (os.path.isfile(xml_test_file)): xmlTree = ET.parse(xml_test_file) xmlRoot = xmlTree.getroot() - SSH.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count))) - SSH.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-' + str(count))) - SSH.htmlTabIcons.append(xmlRoot.findtext('htmlTabIcon',default='info-sign')) + CiTestObj.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count))) + CiTestObj.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-' + str(count))) + CiTestObj.htmlTabIcons.append(xmlRoot.findtext('htmlTabIcon',default='info-sign')) foundCount += 1 count += 1 - if foundCount != SSH.nbTestXMLfiles: - SSH.nbTestXMLfiles = foundCount - SSH.CreateHtmlHeader() + if foundCount != CiTestObj.nbTestXMLfiles: + CiTestObj.nbTestXMLfiles = foundCount + CiTestObj.CreateHtmlHeader() elif re.match('^FinalizeHtml$', mode, re.IGNORECASE): - SSH.CreateHtmlFooter(SSH.finalStatus) + CiTestObj.CreateHtmlFooter(CiTestObj.finalStatus) elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re.IGNORECASE): if re.match('^TesteNB$', mode, re.IGNORECASE): - if SSH.eNBIPAddress == '' or SSH.ranRepository == '' or SSH.ranBranch == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '' or SSH.eNBSourceCodePath == '' or SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '' or SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == '': + if CiTestObj.eNBIPAddress == '' or CiTestObj.ranRepository == '' or CiTestObj.ranBranch == '' or CiTestObj.eNBUserName == '' or CiTestObj.eNBPassword == '' or CiTestObj.eNBSourceCodePath == '' or CiTestObj.EPCIPAddress == '' or CiTestObj.EPCUserName == '' or CiTestObj.EPCPassword == '' or CiTestObj.EPCType == '' or CiTestObj.EPCSourceCodePath == '' or CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == '': Usage() sys.exit('Insufficient Parameter') - if (SSH.EPCIPAddress != '') and (SSH.EPCIPAddress != 'none'): - SSH.copyout(SSH.EPCIPAddress, SSH.EPCUserName, SSH.EPCPassword, cwd + "/tcp_iperf_stats.awk", "/tmp") - SSH.copyout(SSH.EPCIPAddress, SSH.EPCUserName, SSH.EPCPassword, cwd + "/active_net_interfaces.awk", "/tmp") + if (CiTestObj.EPCIPAddress != '') and (CiTestObj.EPCIPAddress != 'none'): + CiTestObj.copyout(CiTestObj.EPCIPAddress, CiTestObj.EPCUserName, CiTestObj.EPCPassword, cwd + "/tcp_iperf_stats.awk", "/tmp") + CiTestObj.copyout(CiTestObj.EPCIPAddress, CiTestObj.EPCUserName, CiTestObj.EPCPassword, cwd + "/active_net_interfaces.awk", "/tmp") else: - if SSH.UEIPAddress == '' or SSH.ranRepository == '' or SSH.ranBranch == '' or SSH.UEUserName == '' or SSH.UEPassword == '' or SSH.UESourceCodePath == '': + if CiTestObj.UEIPAddress == '' or CiTestObj.ranRepository == '' or CiTestObj.ranBranch == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == '': Usage() sys.exit('UE: Insufficient Parameter') #read test_case_list.xml file # if no parameters for XML file, use default value - if (SSH.nbTestXMLfiles != 1): + if (CiTestObj.nbTestXMLfiles != 1): xml_test_file = cwd + "/test_case_list.xml" else: - xml_test_file = cwd + "/" + SSH.testXMLfiles[0] + xml_test_file = cwd + "/" + CiTestObj.testXMLfiles[0] xmlTree = ET.parse(xml_test_file) xmlRoot = xmlTree.getroot() exclusion_tests=xmlRoot.findtext('TestCaseExclusionList',default='') requested_tests=xmlRoot.findtext('TestCaseRequestedList',default='') - if (SSH.nbTestXMLfiles == 1): - SSH.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-0')) - SSH.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-0')) + if (CiTestObj.nbTestXMLfiles == 1): + CiTestObj.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-0')) + CiTestObj.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-0')) repeatCount = xmlRoot.findtext('repeatCount',default='1') - SSH.repeatCounts.append(int(repeatCount)) + CiTestObj.repeatCounts.append(int(repeatCount)) all_tests=xmlRoot.findall('testCase') exclusion_tests=exclusion_tests.split() @@ -4805,8 +4805,8 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re else: logging.debug('ERROR: requested test is invalidly formatted: ' + test) sys.exit(1) - if (SSH.EPCIPAddress != '') and (SSH.EPCIPAddress != 'none'): - SSH.CheckFlexranCtrlInstallation() + if (CiTestObj.EPCIPAddress != '') and (CiTestObj.EPCIPAddress != 'none'): + CiTestObj.CheckFlexranCtrlInstallation() #get the list of tests to be done todo_tests=[] @@ -4819,109 +4819,109 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re signal.signal(signal.SIGUSR1, receive_signal) - SSH.CreateHtmlTabHeader() + CiTestObj.CreateHtmlTabHeader() - SSH.FailReportCnt = 0 - SSH.prematureExit = True - SSH.startTime = int(round(time.time() * 1000)) - while SSH.FailReportCnt < SSH.repeatCounts[0] and SSH.prematureExit: - SSH.prematureExit = False + CiTestObj.FailReportCnt = 0 + CiTestObj.prematureExit = True + CiTestObj.startTime = int(round(time.time() * 1000)) + while CiTestObj.FailReportCnt < CiTestObj.repeatCounts[0] and CiTestObj.prematureExit: + CiTestObj.prematureExit = False # At every iteratin of the retry loop, a separator will be added - SSH.CreateHtmlRetrySeparator() + CiTestObj.CreateHtmlRetrySeparator() for test_case_id in todo_tests: - if SSH.prematureExit: + if CiTestObj.prematureExit: break for test in all_tests: - if SSH.prematureExit: + if CiTestObj.prematureExit: break id = test.get('id') if test_case_id != id: continue - SSH.testCase_id = id - SSH.desc = test.findtext('desc') + CiTestObj.testCase_id = id + CiTestObj.desc = test.findtext('desc') action = test.findtext('class') if (CheckClassValidity(action, id) == False): continue - SSH.ShowTestID() + CiTestObj.ShowTestID() GetParametersFromXML(action) if action == 'Initialize_UE' or action == 'Attach_UE' or action == 'Detach_UE' or action == 'Ping' or action == 'Iperf' or action == 'Reboot_UE' or action == 'DataDisable_UE' or action == 'DataEnable_UE' or action == 'CheckStatusUE': - if (SSH.ADBIPAddress != 'none'): + if (CiTestObj.ADBIPAddress != 'none'): terminate_ue_flag = False - SSH.GetAllUEDevices(terminate_ue_flag) + CiTestObj.GetAllUEDevices(terminate_ue_flag) if action == 'Build_eNB': - SSH.BuildeNB() + CiTestObj.BuildeNB() elif action == 'WaitEndBuild_eNB': - SSH.WaitBuildeNBisFinished() + CiTestObj.WaitBuildeNBisFinished() elif action == 'Initialize_eNB': - SSH.InitializeeNB() + CiTestObj.InitializeeNB() elif action == 'Terminate_eNB': - SSH.TerminateeNB() + CiTestObj.TerminateeNB() elif action == 'Initialize_UE': - SSH.InitializeUE() + CiTestObj.InitializeUE() elif action == 'Terminate_UE': - SSH.TerminateUE() + CiTestObj.TerminateUE() elif action == 'Attach_UE': - SSH.AttachUE() + CiTestObj.AttachUE() elif action == 'Detach_UE': - SSH.DetachUE() + CiTestObj.DetachUE() elif action == 'DataDisable_UE': - SSH.DataDisableUE() + CiTestObj.DataDisableUE() elif action == 'DataEnable_UE': - SSH.DataEnableUE() + CiTestObj.DataEnableUE() elif action == 'CheckStatusUE': - SSH.CheckStatusUE() + CiTestObj.CheckStatusUE() elif action == 'Build_OAI_UE': - SSH.BuildOAIUE() + CiTestObj.BuildOAIUE() elif action == 'Initialize_OAI_UE': - SSH.InitializeOAIUE() + CiTestObj.InitializeOAIUE() elif action == 'Terminate_OAI_UE': - SSH.TerminateOAIUE() + CiTestObj.TerminateOAIUE() elif action == 'Initialize_CatM_module': - SSH.InitializeCatM() + CiTestObj.InitializeCatM() elif action == 'Terminate_CatM_module': - SSH.TerminateCatM() + CiTestObj.TerminateCatM() elif action == 'Attach_CatM_module': - SSH.AttachCatM() + CiTestObj.AttachCatM() elif action == 'Detach_CatM_module': - SSH.TerminateCatM() + CiTestObj.TerminateCatM() elif action == 'Ping_CatM_module': - SSH.PingCatM() + CiTestObj.PingCatM() elif action == 'Ping': - SSH.Ping() + CiTestObj.Ping() elif action == 'Iperf': - SSH.Iperf() + CiTestObj.Iperf() elif action == 'Reboot_UE': - SSH.RebootUE() + CiTestObj.RebootUE() elif action == 'Initialize_HSS': - SSH.InitializeHSS() + CiTestObj.InitializeHSS() elif action == 'Terminate_HSS': - SSH.TerminateHSS() + CiTestObj.TerminateHSS() elif action == 'Initialize_MME': - SSH.InitializeMME() + CiTestObj.InitializeMME() elif action == 'Terminate_MME': - SSH.TerminateMME() + CiTestObj.TerminateMME() elif action == 'Initialize_SPGW': - SSH.InitializeSPGW() + CiTestObj.InitializeSPGW() elif action == 'Terminate_SPGW': - SSH.TerminateSPGW() + CiTestObj.TerminateSPGW() elif action == 'Initialize_FlexranCtrl': - SSH.InitializeFlexranCtrl() + CiTestObj.InitializeFlexranCtrl() elif action == 'Terminate_FlexranCtrl': - SSH.TerminateFlexranCtrl() + CiTestObj.TerminateFlexranCtrl() elif action == 'IdleSleep': - SSH.IdleSleep() + CiTestObj.IdleSleep() elif action == 'Perform_X2_Handover': - SSH.Perform_X2_Handover() + CiTestObj.Perform_X2_Handover() else: sys.exit('Invalid action') - SSH.FailReportCnt += 1 - if SSH.FailReportCnt == SSH.repeatCounts[0] and SSH.prematureExit: - logging.debug('Testsuite failed ' + str(SSH.FailReportCnt) + ' time(s)') - SSH.CreateHtmlTabFooter(False) + CiTestObj.FailReportCnt += 1 + if CiTestObj.FailReportCnt == CiTestObj.repeatCounts[0] and CiTestObj.prematureExit: + logging.debug('Testsuite failed ' + str(CiTestObj.FailReportCnt) + ' time(s)') + CiTestObj.CreateHtmlTabFooter(False) sys.exit('Failed Scenario') else: - logging.info('Testsuite passed after ' + str(SSH.FailReportCnt) + ' time(s)') - SSH.CreateHtmlTabFooter(True) + logging.info('Testsuite passed after ' + str(CiTestObj.FailReportCnt) + ' time(s)') + CiTestObj.CreateHtmlTabFooter(True) else: Usage() sys.exit('Invalid mode') From 8f476a99044195fae635b92a14528de05963fc1d Mon Sep 17 00:00:00 2001 From: Gabriele Perrone Date: Fri, 10 Jan 2020 14:14:08 +0100 Subject: [PATCH 076/240] creating a file sshconnection.py with class SSHConnection (methods: open, command, close, copyin, copyout); and modifying main.py to import this file and call the SSHConnection class from the new file --- ci-scripts/main.py | 1218 ++++++++++++++++++----------------- ci-scripts/sshconnection.py | 167 +++++ 2 files changed, 777 insertions(+), 608 deletions(-) create mode 100644 ci-scripts/sshconnection.py diff --git a/ci-scripts/main.py b/ci-scripts/main.py index bb0e92a23f..dfbde89c45 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -87,6 +87,7 @@ logging.basicConfig( level=logging.DEBUG, format="[%(asctime)s] %(name)s:%(levelname)s: %(message)s" ) +import sshconnection.py #----------------------------------------------------------- # Class Declaration @@ -212,10 +213,10 @@ class OaiCiTest(): logging.debug('self.sshresponse = ' + str(self.sshresponse)) elif self.sshresponse == 2: # Checking if we are really on the remote client defined by its IP address - self.command('stdbuf -o0 ifconfig | egrep --color=never "inet addr:|inet "', '\$', 5) + SSH.command('stdbuf -o0 ifconfig | egrep --color=never "inet addr:|inet "', '\$', 5) result = re.search(str(ipaddress), str(self.ssh.before)) if result is None: - self.close() + SSH.close() else: count = 10 connect_status = True @@ -369,29 +370,29 @@ class OaiCiTest(): if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': Usage() sys.exit('Insufficient Parameter') - self.open(lIpAddr, lUserName, lPassWord) - self.command('mkdir -p ' + lSourcePath, '\$', 5) - self.command('cd ' + lSourcePath, '\$', 5) - self.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + self.ranRepository + ' .; else stdbuf -o0 git fetch; fi', '\$', 600) + SSH.open(lIpAddr, lUserName, lPassWord) + SSH.command('mkdir -p ' + lSourcePath, '\$', 5) + SSH.command('cd ' + lSourcePath, '\$', 5) + SSH.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + self.ranRepository + ' .; else stdbuf -o0 git fetch; fi', '\$', 600) # Raphael: here add a check if git clone or git fetch went smoothly - self.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) - self.command('git config user.name "OAI Jenkins"', '\$', 5) + SSH.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) + SSH.command('git config user.name "OAI Jenkins"', '\$', 5) # Checking the BUILD INFO file if not self.backgroundBuild: - self.command('ls *.txt', '\$', 5) + SSH.command('ls *.txt', '\$', 5) result = re.search('LAST_BUILD_INFO', str(self.ssh.before)) if result is not None: mismatch = False - self.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) result = re.search(self.ranCommitID, str(self.ssh.before)) if result is None: mismatch = True - self.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) if (self.ranAllowMerge): result = re.search('YES', str(self.ssh.before)) if result is None: mismatch = True - self.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) if self.ranTargetBranch == '': result = re.search('develop', str(self.ssh.before)) else: @@ -403,37 +404,37 @@ class OaiCiTest(): if result is None: mismatch = True if not mismatch: - self.close() + SSH.close() self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) return - self.command('echo ' + lPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30) + SSH.command('echo ' + lPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30) # if the commit ID is provided use it to point to it if self.ranCommitID != '': - self.command('git checkout -f ' + self.ranCommitID, '\$', 5) + SSH.command('git checkout -f ' + self.ranCommitID, '\$', 5) # if the branch is not develop, then it is a merge request and we need to do # the potential merge. Note that merge conflicts should already been checked earlier if (self.ranAllowMerge): if self.ranTargetBranch == '': if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'): - self.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) + SSH.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) else: logging.debug('Merging with the target branch: ' + self.ranTargetBranch) - self.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5) - self.command('source oaienv', '\$', 5) - self.command('cd cmake_targets', '\$', 5) - self.command('mkdir -p log', '\$', 5) - self.command('chmod 777 log', '\$', 5) + SSH.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5) + SSH.command('source oaienv', '\$', 5) + SSH.command('cd cmake_targets', '\$', 5) + SSH.command('mkdir -p log', '\$', 5) + SSH.command('chmod 777 log', '\$', 5) # no need to remove in log (git clean did the trick) if self.backgroundBuild: - self.command('echo "./build_oai ' + self.Build_eNB_args + '" > ./my-lte-softmodem-build.sh', '\$', 5) - self.command('chmod 775 ./my-lte-softmodem-build.sh', '\$', 5) - self.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=build_enb_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/compile_oai_enb.log ./my-lte-softmodem-build.sh', '\$', 5) - self.close() + SSH.command('echo "./build_oai ' + self.Build_eNB_args + '" > ./my-lte-softmodem-build.sh', '\$', 5) + SSH.command('chmod 775 ./my-lte-softmodem-build.sh', '\$', 5) + SSH.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=build_enb_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/compile_oai_enb.log ./my-lte-softmodem-build.sh', '\$', 5) + SSH.close() self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) self.backgroundBuildTestId[int(self.eNB_instance)] = self.testCase_id return - self.command('stdbuf -o0 ./build_oai ' + self.Build_eNB_args + ' 2>&1 | stdbuf -o0 tee compile_oai_enb.log', 'Bypassing the Tests|build have failed', 1500) + SSH.command('stdbuf -o0 ./build_oai ' + self.Build_eNB_args + ' 2>&1 | stdbuf -o0 tee compile_oai_enb.log', 'Bypassing the Tests|build have failed', 1500) self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.testCase_id) def WaitBuildeNBisFinished(self): @@ -455,11 +456,11 @@ class OaiCiTest(): if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': Usage() sys.exit('Insufficient Parameter') - self.open(lIpAddr, lUserName, lPassWord) + SSH.open(lIpAddr, lUserName, lPassWord) count = 40 buildOAIprocess = True while (count > 0) and buildOAIprocess: - self.command('ps aux | grep --color=never build_ | grep -v grep', '\$', 3) + SSH.command('ps aux | grep --color=never build_ | grep -v grep', '\$', 3) result = re.search('build_oai', str(self.ssh.before)) if result is None: buildOAIprocess = False @@ -469,46 +470,46 @@ class OaiCiTest(): self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.backgroundBuildTestId[int(self.eNB_instance)]) def checkBuildeNB(self, lIpAddr, lUserName, lPassWord, lSourcePath, testcaseId): - self.command('cd ' + lSourcePath + '/cmake_targets', '\$', 3) - self.command('ls lte_build_oai/build', '\$', 3) - self.command('ls lte_build_oai/build', '\$', 3) + SSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 3) + SSH.command('ls lte_build_oai/build', '\$', 3) + SSH.command('ls lte_build_oai/build', '\$', 3) buildStatus = True result = re.search('lte-softmodem', str(self.ssh.before)) if result is None: buildStatus = False else: # Generating a BUILD INFO file - self.command('echo "SRC_BRANCH: ' + self.ranBranch + '" > ../LAST_BUILD_INFO.txt', '\$', 2) - self.command('echo "SRC_COMMIT: ' + self.ranCommitID + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('echo "SRC_BRANCH: ' + self.ranBranch + '" > ../LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('echo "SRC_COMMIT: ' + self.ranCommitID + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) if (self.ranAllowMerge): - self.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2) if self.ranTargetBranch == '': - self.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2) else: - self.command('echo "TGT_BRANCH: ' + self.ranTargetBranch + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('echo "TGT_BRANCH: ' + self.ranTargetBranch + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) else: - self.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) - self.command('mkdir -p build_log_' + testcaseId, '\$', 5) - self.command('mv log/* ' + 'build_log_' + testcaseId, '\$', 5) - self.command('mv compile_oai_enb.log ' + 'build_log_' + testcaseId, '\$', 5) + SSH.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('mkdir -p build_log_' + testcaseId, '\$', 5) + SSH.command('mv log/* ' + 'build_log_' + testcaseId, '\$', 5) + SSH.command('mv compile_oai_enb.log ' + 'build_log_' + testcaseId, '\$', 5) if self.eNB_serverId != '0': - self.command('cd cmake_targets', '\$', 5) - self.command('if [ -e tmp_build' + testcaseId + '.zip ]; then rm -f tmp_build' + testcaseId + '.zip; fi', '\$', 5) - self.command('zip -r -qq tmp_build' + testcaseId + '.zip build_log_' + testcaseId, '\$', 5) - self.close() + SSH.command('cd cmake_targets', '\$', 5) + SSH.command('if [ -e tmp_build' + testcaseId + '.zip ]; then rm -f tmp_build' + testcaseId + '.zip; fi', '\$', 5) + SSH.command('zip -r -qq tmp_build' + testcaseId + '.zip build_log_' + testcaseId, '\$', 5) + SSH.close() if (os.path.isfile('./tmp_build' + testcaseId + '.zip')): os.remove('./tmp_build' + testcaseId + '.zip') - self.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/tmp_build' + testcaseId + '.zip', '.') + SSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/tmp_build' + testcaseId + '.zip', '.') if (os.path.isfile('./tmp_build' + testcaseId + '.zip')): - self.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './tmp_build' + testcaseId + '.zip', self.eNBSourceCodePath + '/cmake_targets/.') + SSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './tmp_build' + testcaseId + '.zip', self.eNBSourceCodePath + '/cmake_targets/.') os.remove('./tmp_build' + testcaseId + '.zip') - self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) - self.command('cd ' + self.eNBSourceCodePath + '/cmake_targets', '\$', 5) - self.command('unzip -qq -DD tmp_build' + testcaseId + '.zip', '\$', 5) - self.command('rm -f tmp_build' + testcaseId + '.zip', '\$', 5) - self.close() + SSH.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) + SSH.command('cd ' + self.eNBSourceCodePath + '/cmake_targets', '\$', 5) + SSH.command('unzip -qq -DD tmp_build' + testcaseId + '.zip', '\$', 5) + SSH.command('rm -f tmp_build' + testcaseId + '.zip', '\$', 5) + SSH.close() else: - self.close() + SSH.close() if buildStatus: self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) @@ -522,27 +523,27 @@ class OaiCiTest(): if self.UEIPAddress == '' or self.ranRepository == '' or self.ranBranch == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': Usage() sys.exit('Insufficient Parameter') - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('mkdir -p ' + self.UESourceCodePath, '\$', 5) - self.command('cd ' + self.UESourceCodePath, '\$', 5) - self.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + self.ranRepository + ' .; else stdbuf -o0 git fetch; fi', '\$', 600) + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('mkdir -p ' + self.UESourceCodePath, '\$', 5) + SSH.command('cd ' + self.UESourceCodePath, '\$', 5) + SSH.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + self.ranRepository + ' .; else stdbuf -o0 git fetch; fi', '\$', 600) # here add a check if git clone or git fetch went smoothly - self.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) - self.command('git config user.name "OAI Jenkins"', '\$', 5) - self.command('ls *.txt', '\$', 5) + SSH.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) + SSH.command('git config user.name "OAI Jenkins"', '\$', 5) + SSH.command('ls *.txt', '\$', 5) result = re.search('LAST_BUILD_INFO', str(self.ssh.before)) if result is not None: mismatch = False - self.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) result = re.search(self.ranCommitID, str(self.ssh.before)) if result is None: mismatch = True - self.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) if (self.ranAllowMerge): result = re.search('YES', str(self.ssh.before)) if result is None: mismatch = True - self.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) if self.ranTargetBranch == '': result = re.search('develop', str(self.ssh.before)) else: @@ -554,54 +555,54 @@ class OaiCiTest(): if result is None: mismatch = True if not mismatch: - self.close() + SSH.close() self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) return - self.command('echo ' + self.UEPassword + ' | sudo -S git clean -x -d -ff', '\$', 30) + SSH.command('echo ' + self.UEPassword + ' | sudo -S git clean -x -d -ff', '\$', 30) # if the commit ID is provided use it to point to it if self.ranCommitID != '': - self.command('git checkout -f ' + self.ranCommitID, '\$', 5) + SSH.command('git checkout -f ' + self.ranCommitID, '\$', 5) # if the branch is not develop, then it is a merge request and we need to do # the potential merge. Note that merge conflicts should already been checked earlier if (self.ranAllowMerge): if self.ranTargetBranch == '': if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'): - self.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) + SSH.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) else: logging.debug('Merging with the target branch: ' + self.ranTargetBranch) - self.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5) - self.command('source oaienv', '\$', 5) - self.command('cd cmake_targets', '\$', 5) - self.command('mkdir -p log', '\$', 5) - self.command('chmod 777 log', '\$', 5) + SSH.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5) + SSH.command('source oaienv', '\$', 5) + SSH.command('cd cmake_targets', '\$', 5) + SSH.command('mkdir -p log', '\$', 5) + SSH.command('chmod 777 log', '\$', 5) # no need to remove in log (git clean did the trick) - self.command('stdbuf -o0 ./build_oai ' + self.Build_OAI_UE_args + ' 2>&1 | stdbuf -o0 tee compile_oai_ue.log', 'Bypassing the Tests|build have failed', 600) - self.command('ls lte_build_oai/build', '\$', 3) - self.command('ls lte_build_oai/build', '\$', 3) + SSH.command('stdbuf -o0 ./build_oai ' + self.Build_OAI_UE_args + ' 2>&1 | stdbuf -o0 tee compile_oai_ue.log', 'Bypassing the Tests|build have failed', 600) + SSH.command('ls lte_build_oai/build', '\$', 3) + SSH.command('ls lte_build_oai/build', '\$', 3) buildStatus = True result = re.search('lte-uesoftmodem', str(self.ssh.before)) if result is None: buildStatus = False - self.command('mkdir -p build_log_' + self.testCase_id, '\$', 5) - self.command('mv log/* ' + 'build_log_' + self.testCase_id, '\$', 5) - self.command('mv compile_oai_ue.log ' + 'build_log_' + self.testCase_id, '\$', 5) + SSH.command('mkdir -p build_log_' + self.testCase_id, '\$', 5) + SSH.command('mv log/* ' + 'build_log_' + self.testCase_id, '\$', 5) + SSH.command('mv compile_oai_ue.log ' + 'build_log_' + self.testCase_id, '\$', 5) if buildStatus: # Generating a BUILD INFO file - self.command('echo "SRC_BRANCH: ' + self.ranBranch + '" > ../LAST_BUILD_INFO.txt', '\$', 2) - self.command('echo "SRC_COMMIT: ' + self.ranCommitID + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('echo "SRC_BRANCH: ' + self.ranBranch + '" > ../LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('echo "SRC_COMMIT: ' + self.ranCommitID + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) if (self.ranAllowMerge): - self.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2) if self.ranTargetBranch == '': - self.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2) else: - self.command('echo "TGT_BRANCH: ' + self.ranTargetBranch + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('echo "TGT_BRANCH: ' + self.ranTargetBranch + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) else: - self.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) - self.close() + SSH.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) + SSH.close() self.CreateHtmlTestRow(self.Build_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE') else: - self.close() + SSH.close() logging.error('\u001B[1m Building OAI UE Failed\u001B[0m') self.CreateHtmlTestRow(self.Build_OAI_UE_args, 'KO', ALL_PROCESSES_OK, 'OAI UE') self.CreateHtmlTabFooter(False) @@ -611,107 +612,107 @@ class OaiCiTest(): if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': Usage() sys.exit('Insufficient Parameter') - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): logging.debug('Using the OAI EPC Release 14 Cassandra-based HSS') - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + SSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) logging.debug('\u001B[1m Launching tshark on all interfaces \u001B[0m') EPC_PcapFileName = 'epc_' + self.testCase_id + '.pcap' - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f ' + EPC_PcapFileName, '\$', 5) - self.command('echo $USER; nohup sudo tshark -f "tcp port not 22 and port not 53" -i any -w ' + self.EPCSourceCodePath + '/scripts/' + EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', self.EPCUserName, 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S mkdir -p logs', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f hss_' + self.testCase_id + '.log logs/hss*.*', '\$', 5) - self.command('echo "oai_hss -j /usr/local/etc/oai/hss_rel14.json" > ./my-hss.sh', '\$', 5) - self.command('chmod 755 ./my-hss.sh', '\$', 5) - self.command('sudo daemon --unsafe --name=hss_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/hss_' + self.testCase_id + '.log ./my-hss.sh', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f ' + EPC_PcapFileName, '\$', 5) + SSH.command('echo $USER; nohup sudo tshark -f "tcp port not 22 and port not 53" -i any -w ' + self.EPCSourceCodePath + '/scripts/' + EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', self.EPCUserName, 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S mkdir -p logs', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f hss_' + self.testCase_id + '.log logs/hss*.*', '\$', 5) + SSH.command('echo "oai_hss -j /usr/local/etc/oai/hss_rel14.json" > ./my-hss.sh', '\$', 5) + SSH.command('chmod 755 ./my-hss.sh', '\$', 5) + SSH.command('sudo daemon --unsafe --name=hss_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/hss_' + self.testCase_id + '.log ./my-hss.sh', '\$', 5) elif re.match('OAI', self.EPCType, re.IGNORECASE): logging.debug('Using the OAI EPC HSS') - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('source oaienv', '\$', 5) - self.command('cd scripts', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S ./run_hss 2>&1 | stdbuf -o0 awk \'{ print strftime("[%Y/%m/%d %H:%M:%S] ",systime()) $0 }\' | stdbuf -o0 tee -a hss_' + self.testCase_id + '.log &', 'Core state: 2 -> 3', 35) + SSH.command('cd ' + self.EPCSourceCodePath, '\$', 5) + SSH.command('source oaienv', '\$', 5) + SSH.command('cd scripts', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S ./run_hss 2>&1 | stdbuf -o0 awk \'{ print strftime("[%Y/%m/%d %H:%M:%S] ",systime()) $0 }\' | stdbuf -o0 tee -a hss_' + self.testCase_id + '.log &', 'Core state: 2 -> 3', 35) elif re.match('ltebox', self.EPCType, re.IGNORECASE): logging.debug('Using the ltebox simulated HSS') - self.command('if [ -d ' + self.EPCSourceCodePath + '/scripts ]; then echo ' + self.eNBPassword + ' | sudo -S rm -Rf ' + self.EPCSourceCodePath + '/scripts ; fi', '\$', 5) - self.command('mkdir -p ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('cd /opt/hss_sim0609', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f hss.log daemon.log', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S echo "Starting sudo session" && sudo daemon --unsafe --name=simulated_hss --chdir=/opt/hss_sim0609 ./starthss_real ', '\$', 5) + SSH.command('if [ -d ' + self.EPCSourceCodePath + '/scripts ]; then echo ' + self.eNBPassword + ' | sudo -S rm -Rf ' + self.EPCSourceCodePath + '/scripts ; fi', '\$', 5) + SSH.command('mkdir -p ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + SSH.command('cd /opt/hss_sim0609', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f hss.log daemon.log', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S echo "Starting sudo session" && sudo daemon --unsafe --name=simulated_hss --chdir=/opt/hss_sim0609 ./starthss_real ', '\$', 5) else: logging.error('This option should not occur!') - self.close() + SSH.close() self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) def InitializeMME(self): if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': Usage() sys.exit('Insufficient Parameter') - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): logging.debug('Using the OAI EPC Release 14 MME') - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f mme_' + self.testCase_id + '.log', '\$', 5) - self.command('echo "./run_mme --config-file /usr/local/etc/oai/mme.conf --set-virt-if" > ./my-mme.sh', '\$', 5) - self.command('chmod 755 ./my-mme.sh', '\$', 5) - self.command('sudo daemon --unsafe --name=mme_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/mme_' + self.testCase_id + '.log ./my-mme.sh', '\$', 5) + SSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f mme_' + self.testCase_id + '.log', '\$', 5) + SSH.command('echo "./run_mme --config-file /usr/local/etc/oai/mme.conf --set-virt-if" > ./my-mme.sh', '\$', 5) + SSH.command('chmod 755 ./my-mme.sh', '\$', 5) + SSH.command('sudo daemon --unsafe --name=mme_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/mme_' + self.testCase_id + '.log ./my-mme.sh', '\$', 5) elif re.match('OAI', self.EPCType, re.IGNORECASE): - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('source oaienv', '\$', 5) - self.command('cd scripts', '\$', 5) - self.command('stdbuf -o0 hostname', '\$', 5) + SSH.command('cd ' + self.EPCSourceCodePath, '\$', 5) + SSH.command('source oaienv', '\$', 5) + SSH.command('cd scripts', '\$', 5) + SSH.command('stdbuf -o0 hostname', '\$', 5) result = re.search('hostname\\\\r\\\\n(?P[a-zA-Z0-9\-\_]+)\\\\r\\\\n', str(self.ssh.before)) if result is None: logging.debug('\u001B[1;37;41m Hostname Not Found! \u001B[0m') sys.exit(1) host_name = result.group('host_name') - self.command('echo ' + self.EPCPassword + ' | sudo -S ./run_mme 2>&1 | stdbuf -o0 tee -a mme_' + self.testCase_id + '.log &', 'MME app initialization complete', 100) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S ./run_mme 2>&1 | stdbuf -o0 tee -a mme_' + self.testCase_id + '.log &', 'MME app initialization complete', 100) elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cd /opt/ltebox/tools', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S ./start_mme', '\$', 5) + SSH.command('cd /opt/ltebox/tools', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S ./start_mme', '\$', 5) else: logging.error('This option should not occur!') - self.close() + SSH.close() self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) def InitializeSPGW(self): if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': Usage() sys.exit('Insufficient Parameter') - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): logging.debug('Using the OAI EPC Release 14 SPGW-CUPS') - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f spgwc_' + self.testCase_id + '.log spgwu_' + self.testCase_id + '.log', '\$', 5) - self.command('echo "spgwc -c /usr/local/etc/oai/spgw_c.conf" > ./my-spgwc.sh', '\$', 5) - self.command('chmod 755 ./my-spgwc.sh', '\$', 5) - self.command('sudo daemon --unsafe --name=spgwc_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/spgwc_' + self.testCase_id + '.log ./my-spgwc.sh', '\$', 5) + SSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f spgwc_' + self.testCase_id + '.log spgwu_' + self.testCase_id + '.log', '\$', 5) + SSH.command('echo "spgwc -c /usr/local/etc/oai/spgw_c.conf" > ./my-spgwc.sh', '\$', 5) + SSH.command('chmod 755 ./my-spgwc.sh', '\$', 5) + SSH.command('sudo daemon --unsafe --name=spgwc_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/spgwc_' + self.testCase_id + '.log ./my-spgwc.sh', '\$', 5) time.sleep(5) - self.command('echo "spgwu -c /usr/local/etc/oai/spgw_u.conf" > ./my-spgwu.sh', '\$', 5) - self.command('chmod 755 ./my-spgwu.sh', '\$', 5) - self.command('sudo daemon --unsafe --name=spgwu_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/spgwu_' + self.testCase_id + '.log ./my-spgwu.sh', '\$', 5) + SSH.command('echo "spgwu -c /usr/local/etc/oai/spgw_u.conf" > ./my-spgwu.sh', '\$', 5) + SSH.command('chmod 755 ./my-spgwu.sh', '\$', 5) + SSH.command('sudo daemon --unsafe --name=spgwu_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/spgwu_' + self.testCase_id + '.log ./my-spgwu.sh', '\$', 5) elif re.match('OAI', self.EPCType, re.IGNORECASE): - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('source oaienv', '\$', 5) - self.command('cd scripts', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S ./run_spgw 2>&1 | stdbuf -o0 tee -a spgw_' + self.testCase_id + '.log &', 'Initializing SPGW-APP task interface: DONE', 30) + SSH.command('cd ' + self.EPCSourceCodePath, '\$', 5) + SSH.command('source oaienv', '\$', 5) + SSH.command('cd scripts', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S ./run_spgw 2>&1 | stdbuf -o0 tee -a spgw_' + self.testCase_id + '.log &', 'Initializing SPGW-APP task interface: DONE', 30) elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cd /opt/ltebox/tools', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S ./start_xGw', '\$', 5) + SSH.command('cd /opt/ltebox/tools', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S ./start_xGw', '\$', 5) else: logging.error('This option should not occur!') - self.close() + SSH.close() self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) def CheckFlexranCtrlInstallation(self): if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '': return - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('ls -ls /opt/flexran_rtc/*/rt_controller', '\$', 5) + SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.command('ls -ls /opt/flexran_rtc/*/rt_controller', '\$', 5) result = re.search('/opt/flexran_rtc/build/rt_controller', str(self.ssh.before)) if result is not None: self.flexranCtrlInstalled = True logging.debug('Flexran Controller is installed') - self.close() + SSH.close() def InitializeFlexranCtrl(self): if self.flexranCtrlInstalled == False: @@ -719,18 +720,18 @@ class OaiCiTest(): if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '': Usage() sys.exit('Insufficient Parameter') - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd /opt/flexran_rtc', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f log/*.log', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S echo "build/rt_controller -c log_config/basic_log" > ./my-flexran-ctl.sh', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S chmod 755 ./my-flexran-ctl.sh', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S daemon --unsafe --name=flexran_rtc_daemon --chdir=/opt/flexran_rtc -o /opt/flexran_rtc/log/flexranctl_' + self.testCase_id + '.log ././my-flexran-ctl.sh', '\$', 5) - self.command('ps -aux | grep --color=never rt_controller', '\$', 5) + SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.command('cd /opt/flexran_rtc', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f log/*.log', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S echo "build/rt_controller -c log_config/basic_log" > ./my-flexran-ctl.sh', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S chmod 755 ./my-flexran-ctl.sh', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S daemon --unsafe --name=flexran_rtc_daemon --chdir=/opt/flexran_rtc -o /opt/flexran_rtc/log/flexranctl_' + self.testCase_id + '.log ././my-flexran-ctl.sh', '\$', 5) + SSH.command('ps -aux | grep --color=never rt_controller', '\$', 5) result = re.search('rt_controller -c ', str(self.ssh.before)) if result is not None: logging.debug('\u001B[1m Initialize FlexRan Controller Completed\u001B[0m') self.flexranCtrlStarted = True - self.close() + SSH.close() self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) def InitializeeNB(self): @@ -762,18 +763,18 @@ class OaiCiTest(): # If tracer options is on, running tshark on EPC side and capture traffic b/ EPC and eNB result = re.search('T_stdout', str(self.Initialize_eNB_args)) if result is not None: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('ip addr show | awk -f /tmp/active_net_interfaces.awk | egrep -v "lo|tun"', '\$', 5) + SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.command('ip addr show | awk -f /tmp/active_net_interfaces.awk | egrep -v "lo|tun"', '\$', 5) result = re.search('interfaceToUse=(?P[a-zA-Z0-9\-\_]+)done', str(self.ssh.before)) if result is not None: eth_interface = result.group('eth_interface') logging.debug('\u001B[1m Launching tshark on interface ' + eth_interface + '\u001B[0m') self.EPC_PcapFileName = 'enb_' + self.testCase_id + '_s1log.pcap' - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f /tmp/' + self.EPC_PcapFileName, '\$', 5) - self.command('echo $USER; nohup sudo tshark -f "host ' + lIpAddr +'" -i ' + eth_interface + ' -w /tmp/' + self.EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', self.EPCUserName, 5) - self.close() - self.open(lIpAddr, lUserName, lPassWord) - self.command('cd ' + lSourcePath, '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f /tmp/' + self.EPC_PcapFileName, '\$', 5) + SSH.command('echo $USER; nohup sudo tshark -f "host ' + lIpAddr +'" -i ' + eth_interface + ' -w /tmp/' + self.EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', self.EPCUserName, 5) + SSH.close() + SSH.open(lIpAddr, lUserName, lPassWord) + SSH.command('cd ' + lSourcePath, '\$', 5) # Initialize_eNB_args usually start with -O and followed by the location in repository full_config_file = self.Initialize_eNB_args.replace('-O ','') extra_options = '' @@ -784,10 +785,10 @@ class OaiCiTest(): result = re.search('T_stdout', str(extra_options)) if result is not None: logging.debug('\u001B[1m Compiling and launching T Tracer\u001B[0m') - self.command('cd common/utils/T/tracer', '\$', 5) - self.command('make', '\$', 10) - self.command('echo $USER; nohup ./record -d ../T_messages.txt -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.raw -ON -off VCD -off HEAVY -off LEGACY_GROUP_TRACE -off LEGACY_GROUP_DEBUG > ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.log 2>&1 &', lUserName, 5) - self.command('cd ' + lSourcePath, '\$', 5) + SSH.command('cd common/utils/T/tracer', '\$', 5) + SSH.command('make', '\$', 10) + SSH.command('echo $USER; nohup ./record -d ../T_messages.txt -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.raw -ON -off VCD -off HEAVY -off LEGACY_GROUP_TRACE -off LEGACY_GROUP_DEBUG > ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.log 2>&1 &', lUserName, 5) + SSH.command('cd ' + lSourcePath, '\$', 5) full_config_file = full_config_file[:extIdx + 5] config_path, config_file = os.path.split(full_config_file) else: @@ -800,32 +801,32 @@ class OaiCiTest(): # do not reset board twice in IF4.5 case result = re.search('^rru|^enb|^du.band', str(config_file)) if result is not None: - self.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 10) + SSH.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 10) result = re.search('type: b200', str(self.ssh.before)) if result is not None: logging.debug('Found a B2xx device --> resetting it') - self.command('echo ' + lPassWord + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10) + SSH.command('echo ' + lPassWord + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10) # Reloading FGPA bin firmware - self.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 15) + SSH.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 15) # Make a copy and adapt to EPC / eNB IP addresses - self.command('cp ' + full_config_file + ' ' + ci_full_config_file, '\$', 5) - self.command('sed -i -e \'s/CI_MME_IP_ADDR/' + self.EPCIPAddress + '/\' ' + ci_full_config_file, '\$', 2); - self.command('sed -i -e \'s/CI_ENB_IP_ADDR/' + lIpAddr + '/\' ' + ci_full_config_file, '\$', 2); - self.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2); - self.command('sed -i -e \'s/CI_RRU1_IP_ADDR/' + self.eNB1IPAddress + '/\' ' + ci_full_config_file, '\$', 2); - self.command('sed -i -e \'s/CI_RRU2_IP_ADDR/' + self.eNB2IPAddress + '/\' ' + ci_full_config_file, '\$', 2); + SSH.command('cp ' + full_config_file + ' ' + ci_full_config_file, '\$', 5) + SSH.command('sed -i -e \'s/CI_MME_IP_ADDR/' + self.EPCIPAddress + '/\' ' + ci_full_config_file, '\$', 2); + SSH.command('sed -i -e \'s/CI_ENB_IP_ADDR/' + lIpAddr + '/\' ' + ci_full_config_file, '\$', 2); + SSH.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2); + SSH.command('sed -i -e \'s/CI_RRU1_IP_ADDR/' + self.eNB1IPAddress + '/\' ' + ci_full_config_file, '\$', 2); + SSH.command('sed -i -e \'s/CI_RRU2_IP_ADDR/' + self.eNB2IPAddress + '/\' ' + ci_full_config_file, '\$', 2); if self.flexranCtrlInstalled and self.flexranCtrlStarted: - self.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "yes";/\' ' + ci_full_config_file, '\$', 2); + SSH.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "yes";/\' ' + ci_full_config_file, '\$', 2); else: - self.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "no";/\' ' + ci_full_config_file, '\$', 2); + SSH.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "no";/\' ' + ci_full_config_file, '\$', 2); # Launch eNB with the modified config file - self.command('source oaienv', '\$', 5) - self.command('cd cmake_targets', '\$', 5) - self.command('echo "ulimit -c unlimited && ./lte_build_oai/build/lte-softmodem -O ' + lSourcePath + '/' + ci_full_config_file + extra_options + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - self.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - self.command('chmod 775 ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - self.command('echo ' + lPassWord + ' | sudo -S rm -Rf enb_' + self.testCase_id + '.log', '\$', 5) - self.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=enb' + str(self.eNB_instance) + '_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + SSH.command('source oaienv', '\$', 5) + SSH.command('cd cmake_targets', '\$', 5) + SSH.command('echo "ulimit -c unlimited && ./lte_build_oai/build/lte-softmodem -O ' + lSourcePath + '/' + ci_full_config_file + extra_options + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + SSH.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + SSH.command('chmod 775 ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + SSH.command('echo ' + lPassWord + ' | sudo -S rm -Rf enb_' + self.testCase_id + '.log', '\$', 5) + SSH.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=enb' + str(self.eNB_instance) + '_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) self.eNBLogFiles[int(self.eNB_instance)] = 'enb_' + self.testCase_id + '.log' if extra_options != '': self.eNBOptions[int(self.eNB_instance)] = extra_options @@ -838,30 +839,30 @@ class OaiCiTest(): # In case of T tracer recording, we may need to kill it result = re.search('T_stdout', str(self.Initialize_eNB_args)) if result is not None: - self.command('killall --signal SIGKILL record', '\$', 5) - self.close() + SSH.command('killall --signal SIGKILL record', '\$', 5) + SSH.close() doLoop = False logging.error('\u001B[1;37;41m eNB logging system did not show got sync! \u001B[0m') self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'KO', ALL_PROCESSES_OK) # In case of T tracer recording, we need to kill tshark on EPC side result = re.search('T_stdout', str(self.Initialize_eNB_args)) if result is not None: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) logging.debug('\u001B[1m Stopping tshark \u001B[0m') - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) if self.EPC_PcapFileName != '': time.sleep(0.5) - self.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 /tmp/' + self.EPC_PcapFileName, '\$', 5) - self.close() + SSH.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 /tmp/' + self.EPC_PcapFileName, '\$', 5) + SSH.close() time.sleep(1) if self.EPC_PcapFileName != '': - copyin_res = self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + self.EPC_PcapFileName, '.') + copyin_res = SSH.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + self.EPC_PcapFileName, '.') if (copyin_res == 0): - self.copyout(lIpAddr, lUserName, lPassWord, self.EPC_PcapFileName, lSourcePath + '/cmake_targets/.') + SSH.copyout(lIpAddr, lUserName, lPassWord, self.EPC_PcapFileName, lSourcePath + '/cmake_targets/.') self.prematureExit = True return else: - self.command('stdbuf -o0 cat enb_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync|Starting"', '\$', 4) + SSH.command('stdbuf -o0 cat enb_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync|Starting"', '\$', 4) if rruCheck: result = re.search('wait RUs', str(self.ssh.before)) else: @@ -874,52 +875,52 @@ class OaiCiTest(): logging.debug('\u001B[1m Initialize eNB Completed\u001B[0m') time.sleep(10) - self.close() + SSH.close() def InitializeUE_common(self, device_id, idx): try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) if not self.ADBCentralized: # Reboot UE - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesRebootCmd[idx], '\$', 60) + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesRebootCmd[idx], '\$', 60) # Wait #time.sleep(60) # Put in LTE-Mode only - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode 11"\'', '\$', 60) - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode1 11"\'', '\$', 60) - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode2 11"\'', '\$', 60) - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode3 11"\'', '\$', 60) + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode 11"\'', '\$', 60) + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode1 11"\'', '\$', 60) + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode2 11"\'', '\$', 60) + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode3 11"\'', '\$', 60) # enable data service - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) # we need to do radio on/off cycle to make sure of above changes # airplane mode off // radio on - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) #time.sleep(10) # airplane mode on // radio off - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) # normal procedure without reboot # enable data service - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) # airplane mode on // radio off - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) - self.close() + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + SSH.close() return # enable data service - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data enable"', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data enable"', '\$', 60) # The following commands are deprecated since we no longer work on Android 7+ - # self.command('stdbuf -o0 adb -s ' + device_id + ' shell settings put global airplane_mode_on 1', '\$', 10) - # self.command('stdbuf -o0 adb -s ' + device_id + ' shell am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true', '\$', 60) + # SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell settings put global airplane_mode_on 1', '\$', 10) + # SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true', '\$', 60) # a dedicated script has to be installed inside the UE # airplane mode on means call /data/local/tmp/off if device_id == '84B7N16418004022': - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) else: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) #airplane mode off means call /data/local/tmp/on logging.debug('\u001B[1mUE (' + device_id + ') Initialize Completed\u001B[0m') - self.close() + SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) @@ -952,34 +953,34 @@ class OaiCiTest(): self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', pStatus) self.CreateHtmlTabFooter(False) sys.exit(1) - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) # b2xx_fx3_utils reset procedure - self.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 10) + SSH.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 10) result = re.search('type: b200', str(self.ssh.before)) if result is not None: logging.debug('Found a B2xx device --> resetting it') - self.command('echo ' + self.UEPassword + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10) + SSH.command('echo ' + self.UEPassword + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10) # Reloading FGPA bin firmware - self.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 15) + SSH.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 15) else: logging.debug('Did not find any B2xx device') - self.command('cd ' + self.UESourceCodePath, '\$', 5) - self.command('source oaienv', '\$', 5) - self.command('cd cmake_targets/lte_build_oai/build', '\$', 5) + SSH.command('cd ' + self.UESourceCodePath, '\$', 5) + SSH.command('source oaienv', '\$', 5) + SSH.command('cd cmake_targets/lte_build_oai/build', '\$', 5) result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) # We may have to regenerate the .u* files if result is None: - self.command('ls /tmp/*.sed', '\$', 5) + SSH.command('ls /tmp/*.sed', '\$', 5) result = re.search('adapt_usim_parameters', str(self.ssh.before)) if result is not None: - self.command('sed -f /tmp/adapt_usim_parameters.sed ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5) + SSH.command('sed -f /tmp/adapt_usim_parameters.sed ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5) else: - self.command('sed -e "s#93#92#" -e "s#8baf473f2f8fd09487cccbd7097c6862#fec86ba6eb707ed08905757b1bb44b8f#" -e "s#e734f8734007d6c5ce7a0508809e7e9c#C42449363BBAD02B66D16BC975D77CC1#" ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5) - self.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf .u*', '\$', 5) - self.command('echo ' + self.UEPassword + ' | sudo -S ../../../targets/bin/conf2uedata -c ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf -o .', '\$', 5) + SSH.command('sed -e "s#93#92#" -e "s#8baf473f2f8fd09487cccbd7097c6862#fec86ba6eb707ed08905757b1bb44b8f#" -e "s#e734f8734007d6c5ce7a0508809e7e9c#C42449363BBAD02B66D16BC975D77CC1#" ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf .u*', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S ../../../targets/bin/conf2uedata -c ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf -o .', '\$', 5) # Launch UE with the modified config file - self.command('echo "ulimit -c unlimited && ./lte-uesoftmodem ' + self.Initialize_OAI_UE_args + '" > ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) - self.command('chmod 775 ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) + SSH.command('echo "ulimit -c unlimited && ./lte-uesoftmodem ' + self.Initialize_OAI_UE_args + '" > ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) + SSH.command('chmod 775 ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) self.UELogFile = 'ue_' + self.testCase_id + '.log' # We are now looping several times to hope we really sync w/ an eNB @@ -988,11 +989,11 @@ class OaiCiTest(): gotSyncStatus = True fullSyncStatus = True while (doOutterLoop): - self.command('cd ' + self.UESourceCodePath + '/cmake_targets/lte_build_oai/build', '\$', 5) - self.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log', '\$', 5) - self.command('echo ' + self.UEPassword + ' | sudo -S -E daemon --inherit --unsafe --name=ue' + str(self.UE_instance) + '_daemon --chdir=' + self.UESourceCodePath + '/cmake_targets/lte_build_oai/build -o ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) + SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets/lte_build_oai/build', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S -E daemon --inherit --unsafe --name=ue' + str(self.UE_instance) + '_daemon --chdir=' + self.UESourceCodePath + '/cmake_targets/lte_build_oai/build -o ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) time.sleep(6) - self.command('cd ../..', '\$', 5) + SSH.command('cd ../..', '\$', 5) doLoop = True loopCounter = 10 gotSyncStatus = True @@ -1005,7 +1006,7 @@ class OaiCiTest(): gotSyncStatus = False doLoop = False continue - self.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4) + SSH.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4) result = re.search('got sync', str(self.ssh.before)) if result is None: time.sleep(6) @@ -1014,10 +1015,10 @@ class OaiCiTest(): logging.debug('Found "got sync" message!') if gotSyncStatus == False: # we certainly need to stop the lte-uesoftmodem process if it is still running! - self.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4) + SSH.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4) result = re.search('lte-uesoftmodem', str(self.ssh.before)) if result is not None: - self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT lte-uesoftmodem', '\$', 4) + SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT lte-uesoftmodem', '\$', 4) time.sleep(3) # We are now checking if sync w/ eNB DOES NOT OCCUR # Usually during the cell synchronization stage, the UE returns with No cell synchronization message @@ -1031,7 +1032,7 @@ class OaiCiTest(): doOutterLoop = False fullSyncStatus = True continue - self.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4) + SSH.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4) result = re.search('No cell synchronization found', str(self.ssh.before)) if result is None: time.sleep(6) @@ -1040,10 +1041,10 @@ class OaiCiTest(): fullSyncStatus = False logging.debug('Found: "No cell synchronization" message! --> try again') time.sleep(6) - self.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4) + SSH.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4) result = re.search('lte-uesoftmodem', str(self.ssh.before)) if result is not None: - self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT lte-uesoftmodem', '\$', 4) + SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT lte-uesoftmodem', '\$', 4) outterLoopCounter = outterLoopCounter - 1 if (outterLoopCounter == 0): doOutterLoop = False @@ -1051,7 +1052,7 @@ class OaiCiTest(): if fullSyncStatus and gotSyncStatus: result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) if result is None: - self.command('ifconfig oaitun_ue1', '\$', 4) + SSH.command('ifconfig oaitun_ue1', '\$', 4) # ifconfig output is different between ubuntu 16 and ubuntu 18 result = re.search('inet addr:1|inet 1', str(self.ssh.before)) if result is not None: @@ -1064,7 +1065,7 @@ class OaiCiTest(): else: tunnelInterfaceStatus = True - self.close() + SSH.close() if fullSyncStatus and gotSyncStatus and tunnelInterfaceStatus: self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE') logging.debug('\u001B[1m Initialize OAI UE Completed\u001B[0m') @@ -1080,48 +1081,48 @@ class OaiCiTest(): self.AutoTerminateUEandeNB() def checkDevTTYisUnlocked(self): - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) count = 0 while count < 5: - self.command('echo ' + self.ADBPassword + ' | sudo -S lsof | grep ttyUSB0', '\$', 10) + SSH.command('echo ' + self.ADBPassword + ' | sudo -S lsof | grep ttyUSB0', '\$', 10) result = re.search('picocom', str(self.ssh.before)) if result is None: count = 10 else: time.sleep(5) count = count + 1 - self.close() + SSH.close() def InitializeCatM(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': Usage() sys.exit('Insufficient Parameter') self.picocom_closure = True - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` - self.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) - self.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) + SSH.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) + SSH.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) time.sleep(1) # Calling twice AT to clear all buffers - self.command('AT', 'OK|ERROR', 5) - self.command('AT', 'OK', 5) + SSH.command('AT', 'OK|ERROR', 5) + SSH.command('AT', 'OK', 5) # Disabling the Radio - self.command('AT+CFUN=0', 'OK', 5) + SSH.command('AT+CFUN=0', 'OK', 5) logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') # Checking if auto-attach is enabled - self.command('AT^AUTOATT?', 'OK', 5) + SSH.command('AT^AUTOATT?', 'OK', 5) result = re.search('AUTOATT: (?P[0-9\-]+)', str(self.ssh.before)) if result is not None: if result.group('state') is not None: autoAttachState = int(result.group('state')) if autoAttachState is not None: if autoAttachState == 0: - self.command('AT^AUTOATT=1', 'OK', 5) + SSH.command('AT^AUTOATT=1', 'OK', 5) logging.debug('\u001B[1m Auto-Attach enabled\u001B[0m') else: logging.debug('\u001B[1;37;41m Could not check Auto-Attach! \u001B[0m') # Force closure of picocom but device might still be locked - self.close() + SSH.close() self.picocom_closure = False self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) self.checkDevTTYisUnlocked() @@ -1131,18 +1132,18 @@ class OaiCiTest(): Usage() sys.exit('Insufficient Parameter') self.picocom_closure = True - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` - self.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) - self.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) + SSH.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) + SSH.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) time.sleep(1) # Calling twice AT to clear all buffers - self.command('AT', 'OK|ERROR', 5) - self.command('AT', 'OK', 5) + SSH.command('AT', 'OK|ERROR', 5) + SSH.command('AT', 'OK', 5) # Disabling the Radio - self.command('AT+CFUN=0', 'OK', 5) + SSH.command('AT+CFUN=0', 'OK', 5) logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') - self.close() + SSH.close() self.picocom_closure = False self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) self.checkDevTTYisUnlocked() @@ -1152,16 +1153,16 @@ class OaiCiTest(): Usage() sys.exit('Insufficient Parameter') self.picocom_closure = True - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` - self.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) - self.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) + SSH.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) + SSH.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) time.sleep(1) # Calling twice AT to clear all buffers - self.command('AT', 'OK|ERROR', 5) - self.command('AT', 'OK', 5) + SSH.command('AT', 'OK|ERROR', 5) + SSH.command('AT', 'OK', 5) # Enabling the Radio - self.command('AT+CFUN=1', 'SIMSTORE,READY', 5) + SSH.command('AT+CFUN=1', 'SIMSTORE,READY', 5) logging.debug('\u001B[1m Cellular Functionality enabled\u001B[0m') time.sleep(4) # We should check if we register @@ -1169,7 +1170,7 @@ class OaiCiTest(): attach_cnt = 0 attach_status = False while count < 5: - self.command('AT+CEREG?', 'OK', 5) + SSH.command('AT+CEREG?', 'OK', 5) result = re.search('CEREG: 2,(?P[0-9\-]+),', str(self.ssh.before)) if result is not None: mDataConnectionState = int(result.group('state')) @@ -1193,7 +1194,7 @@ class OaiCiTest(): count = count + 1 time.sleep(1) if attach_status: - self.command('AT+CESQ', 'OK', 5) + SSH.command('AT+CESQ', 'OK', 5) result = re.search('CESQ: 99,99,255,255,(?P[0-9]+),(?P[0-9]+)', str(self.ssh.before)) if result is not None: nRSRQ = int(result.group('rsrq')) @@ -1201,7 +1202,7 @@ class OaiCiTest(): if (nRSRQ is not None) and (nRSRP is not None): logging.debug(' RSRQ = ' + str(-20+(nRSRQ/2)) + ' dB') logging.debug(' RSRP = ' + str(-140+nRSRP) + ' dBm') - self.close() + SSH.close() self.picocom_closure = False html_queue = SimpleQueue() self.checkDevTTYisUnlocked() @@ -1235,16 +1236,16 @@ class OaiCiTest(): try: statusQueue = SimpleQueue() lock = Lock() - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('cd scripts', '\$', 5) + SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.command('cd ' + self.EPCSourceCodePath, '\$', 5) + SSH.command('cd scripts', '\$', 5) if re.match('OAI', self.EPCType, re.IGNORECASE): logging.debug('Using the OAI EPC HSS: not implemented yet') self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) self.CreateHtmlTabFooter(False) sys.exit(1) else: - self.command('egrep --color=never "Allocated ipv4 addr" /opt/ltebox/var/log/xGwLog.0', '\$', 5) + SSH.command('egrep --color=never "Allocated ipv4 addr" /opt/ltebox/var/log/xGwLog.0', '\$', 5) result = re.search('Allocated ipv4 addr: (?P[0-9\.]+) from Pool', str(self.ssh.before)) if result is not None: moduleIPAddr = result.group('ipaddr') @@ -1254,33 +1255,33 @@ class OaiCiTest(): return ping_time = re.findall("-c (\d+)",str(self.ping_args)) device_id = 'catm' - ping_status = self.command('stdbuf -o0 ping ' + self.ping_args + ' ' + str(moduleIPAddr) + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) + ping_status = SSH.command('stdbuf -o0 ping ' + self.ping_args + ' ' + str(moduleIPAddr) + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) # TIMEOUT CASE if ping_status < 0: message = 'Ping with UE (' + str(moduleIPAddr) + ') crashed due to TIMEOUT!' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() + SSH.close() self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) return result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', str(self.ssh.before)) if result is None: message = 'Packet Loss Not Found!' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() + SSH.close() self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) return packetloss = result.group('packetloss') if float(packetloss) == 100: message = 'Packet Loss is 100%' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() + SSH.close() self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) return result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', str(self.ssh.before)) if result is None: message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() + SSH.close() self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) return rtt_min = result.group('rtt_min') @@ -1307,7 +1308,7 @@ class OaiCiTest(): qMsg += '\nPacket Loss is not 0%' logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m') lock.release() - self.close() + SSH.close() html_cell = '
CAT-M module\nIP Address  : ' + moduleIPAddr + '\n' + qMsg + '
' statusQueue.put(html_cell) if (packetLossOK): @@ -1320,23 +1321,23 @@ class OaiCiTest(): def AttachUE_common(self, device_id, statusQueue, lock, idx): try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) if self.ADBCentralized: if device_id == '84B7N16418004022': - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/on"', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/on"', '\$', 60) else: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60) else: # airplane mode off // radio on - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) time.sleep(2) max_count = 45 count = max_count while count > 0: if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry" | grep -m 1 mDataConnectionState', '\$', 15) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry" | grep -m 1 mDataConnectionState', '\$', 15) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\' | grep -m 1 mDataConnectionState', '\$', 60) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\' | grep -m 1 mDataConnectionState', '\$', 60) result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', str(self.ssh.before)) if result is None: logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m') @@ -1360,19 +1361,19 @@ class OaiCiTest(): logging.debug('\u001B[1;30;43m Retry UE (' + device_id + ') Flight Mode Off \u001B[0m') if self.ADBCentralized: if device_id == '84B7N16418004022': - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) else: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) time.sleep(0.5) if self.ADBCentralized: if device_id == '84B7N16418004022': - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/on"', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/on"', '\$', 60) else: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) time.sleep(0.5) logging.debug('\u001B[1mWait UE (' + device_id + ') a second until mDataConnectionState=2 (' + str(max_count-count) + ' times)\u001B[0m') time.sleep(1) @@ -1383,7 +1384,7 @@ class OaiCiTest(): statusQueue.put(device_id) statusQueue.put('Attach Failed') lock.release() - self.close() + SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) @@ -1448,16 +1449,16 @@ class OaiCiTest(): def DetachUE_common(self, device_id, idx): try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) if self.ADBCentralized: if device_id == '84B7N16418004022': - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) else: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) logging.debug('\u001B[1mUE (' + device_id + ') Detach Completed\u001B[0m') - self.close() + SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) @@ -1495,24 +1496,24 @@ class OaiCiTest(): def RebootUE_common(self, device_id): try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) previousmDataConnectionStates = [] # Save mDataConnectionState - self.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) - self.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', str(self.ssh.before)) if result is None: logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m') sys.exit(1) previousmDataConnectionStates.append(int(result.group('state'))) # Reboot UE - self.command('stdbuf -o0 adb -s ' + device_id + ' shell reboot', '\$', 10) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell reboot', '\$', 10) time.sleep(60) previousmDataConnectionState = previousmDataConnectionStates.pop(0) count = 180 while count > 0: count = count - 1 - self.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', str(self.ssh.before)) if result is None: mDataConnectionState = None @@ -1528,7 +1529,7 @@ class OaiCiTest(): if count == 0: logging.debug('\u001B[1;37;41m UE (' + device_id + ') Reboot Failed \u001B[0m') sys.exit(1) - self.close() + SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) @@ -1555,14 +1556,14 @@ class OaiCiTest(): def DataDisableUE_common(self, device_id, idx): try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) # disable data service if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data disable"', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data disable"', '\$', 60) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data disable"\'', '\$', 60) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data disable"\'', '\$', 60) logging.debug('\u001B[1mUE (' + device_id + ') Disabled Data Service\u001B[0m') - self.close() + SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) @@ -1584,14 +1585,14 @@ class OaiCiTest(): def DataEnableUE_common(self, device_id, idx): try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) # enable data service if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data enable"', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data enable"', '\$', 60) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) logging.debug('\u001B[1mUE (' + device_id + ') Enabled Data Service\u001B[0m') - self.close() + SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) @@ -1615,19 +1616,19 @@ class OaiCiTest(): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': Usage() sys.exit('Insufficient Parameter') - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) if self.ADBCentralized: - self.command('adb devices', '\$', 15) + SSH.command('adb devices', '\$', 15) self.UEDevices = re.findall("\\\\r\\\\n([A-Za-z0-9]+)\\\\tdevice",str(self.ssh.before)) - self.close() + SSH.close() else: if (os.path.isfile('./phones_list.txt')): os.remove('./phones_list.txt') - self.command('ls /etc/*/phones*.txt', '\$', 5) + SSH.command('ls /etc/*/phones*.txt', '\$', 5) result = re.search('/etc/ci/phones_list.txt', str(self.ssh.before)) - self.close() + SSH.close() if (result is not None) and (len(self.UEDevices) == 0): - self.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, '/etc/ci/phones_list.txt', '.') + SSH.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, '/etc/ci/phones_list.txt', '.') if (os.path.isfile('./phones_list.txt')): phone_list_file = open('./phones_list.txt', 'r') for line in phone_list_file.readlines(): @@ -1658,31 +1659,31 @@ class OaiCiTest(): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': Usage() sys.exit('Insufficient Parameter') - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) if self.ADBCentralized: - self.command('lsusb | egrep "Future Technology Devices International, Ltd FT2232C" | sed -e "s#:.*##" -e "s# #_#g"', '\$', 15) + SSH.command('lsusb | egrep "Future Technology Devices International, Ltd FT2232C" | sed -e "s#:.*##" -e "s# #_#g"', '\$', 15) self.CatMDevices = re.findall("\\\\r\\\\n([A-Za-z0-9_]+)",str(self.ssh.before)) else: if (os.path.isfile('./modules_list.txt')): os.remove('./modules_list.txt') - self.command('ls /etc/*/modules*.txt', '\$', 5) + SSH.command('ls /etc/*/modules*.txt', '\$', 5) result = re.search('/etc/ci/modules_list.txt', str(self.ssh.before)) - self.close() + SSH.close() if result is not None: logging.debug('Found a module list file on ADB server') if terminate_ue_flag == False: if len(self.CatMDevices) == 0: logging.debug('\u001B[1;37;41m CAT-M UE Not Found! \u001B[0m') sys.exit(1) - self.close() + SSH.close() def CheckUEStatus_common(self, lock, device_id, statusQueue, idx): try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry"', '\$', 15) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry"', '\$', 15) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\'', '\$', 60) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\'', '\$', 60) result = re.search('mServiceState=(?P[0-9]+)', str(self.ssh.before)) serviceState = 'Service State: UNKNOWN' if result is not None: @@ -1721,7 +1722,7 @@ class OaiCiTest(): qMsg = serviceState + '\n' + dataConnectionState + '\n' + dataConnectionReason statusQueue.put(qMsg) lock.release() - self.close() + SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) @@ -1749,10 +1750,10 @@ class OaiCiTest(): for job in multi_jobs: job.join() if self.flexranCtrlInstalled and self.flexranCtrlStarted: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd /opt/flexran_rtc', '\$', 5) - self.command('curl http://localhost:9999/stats | jq \'.\' > log/check_status_' + self.testCase_id + '.log 2>&1', '\$', 5) - self.command('cat log/check_status_' + self.testCase_id + '.log | jq \'.eNB_config[0].UE\' | grep -c rnti | sed -e "s#^#Nb Connected UE = #"', '\$', 5) + SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.command('cd /opt/flexran_rtc', '\$', 5) + SSH.command('curl http://localhost:9999/stats | jq \'.\' > log/check_status_' + self.testCase_id + '.log 2>&1', '\$', 5) + SSH.command('cat log/check_status_' + self.testCase_id + '.log | jq \'.eNB_config[0].UE\' | grep -c rnti | sed -e "s#^#Nb Connected UE = #"', '\$', 5) result = re.search('Nb Connected UE = (?P[0-9]+)', str(self.ssh.before)) passStatus = True if result is not None: @@ -1764,7 +1765,7 @@ class OaiCiTest(): passStatus = False else: htmlOptions = 'N/A' - self.close() + SSH.close() else: passStatus = True htmlOptions = 'N/A' @@ -1799,8 +1800,8 @@ class OaiCiTest(): if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': Usage() sys.exit('Insufficient Parameter') - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('ifconfig oaitun_ue1', '\$', 4) + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('ifconfig oaitun_ue1', '\$', 4) result = re.search('inet addr:(?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)|inet (?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)', str(self.ssh.before)) if result is not None: if result.group('ueipaddress') is not None: @@ -1812,9 +1813,9 @@ class OaiCiTest(): else: logging.debug('\u001B[1;37;41m UE IP Address Not Found! \u001B[0m') ue_ip_status -= 1 - self.close() + SSH.close() return ue_ip_status - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) idx = 0 for device_id in self.UEDevices: if self.UEDevicesStatus[idx] != UE_STATUS_ATTACHED: @@ -1823,9 +1824,9 @@ class OaiCiTest(): count = 0 while count < 4: if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "ip addr show | grep rmnet"', '\$', 15) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "ip addr show | grep rmnet"', '\$', 15) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ip addr show | grep rmnet"\'', '\$', 60) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ip addr show | grep rmnet"\'', '\$', 60) result = re.search('inet (?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\/[0-9]+[0-9a-zA-Z\.\s]+', str(self.ssh.before)) if result is None: logging.debug('\u001B[1;37;41m UE IP Address Not Found! \u001B[0m') @@ -1845,7 +1846,7 @@ class OaiCiTest(): continue self.UEIPAddresses.append(UE_IPAddress) idx += 1 - self.close() + SSH.close() return ue_ip_status def ping_iperf_wrong_exit(self, lock, UE_IPAddress, device_id, statusQueue, message): @@ -1866,45 +1867,45 @@ class OaiCiTest(): ping_time = re.findall("-c (\d+)",str(self.ping_args)) if launchFromEpc: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('cd scripts', '\$', 5) - ping_status = self.command('stdbuf -o0 ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) + SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.command('cd ' + self.EPCSourceCodePath, '\$', 5) + SSH.command('cd scripts', '\$', 5) + ping_status = SSH.command('stdbuf -o0 ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) else: cmd = 'ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 > ping_' + self.testCase_id + '_' + device_id + '.log' message = cmd + '\n' logging.debug(cmd) ret = subprocess.run(cmd, shell=True) ping_status = ret.returncode - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'ping_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cat ' + self.EPCSourceCodePath + '/scripts/ping_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'ping_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') + SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.command('cat ' + self.EPCSourceCodePath + '/scripts/ping_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) # TIMEOUT CASE if ping_status < 0: message = 'Ping with UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT!' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() + SSH.close() self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) return result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', str(self.ssh.before)) if result is None: message = 'Packet Loss Not Found!' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() + SSH.close() self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) return packetloss = result.group('packetloss') if float(packetloss) == 100: message = 'Packet Loss is 100%' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() + SSH.close() self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) return result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', str(self.ssh.before)) if result is None: message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() + SSH.close() self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) return rtt_min = result.group('rtt_min') @@ -1938,7 +1939,7 @@ class OaiCiTest(): statusQueue.put(UE_IPAddress) statusQueue.put(qMsg) lock.release() - self.close() + SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) @@ -1967,14 +1968,14 @@ class OaiCiTest(): sys.exit('Insufficient Parameter') try: if ping_from_eNB is not None: - self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) - self.command('cd ' + self.eNBSourceCodePath + '/cmake_targets/', '\$', 5) + SSH.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) + SSH.command('cd ' + self.eNBSourceCodePath + '/cmake_targets/', '\$', 5) else: - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('cd ' + self.UESourceCodePath + '/cmake_targets/', '\$', 5) - self.command('cd cmake_targets', '\$', 5) + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets/', '\$', 5) + SSH.command('cd cmake_targets', '\$', 5) ping_time = re.findall("-c (\d+)",str(self.ping_args)) - ping_status = self.command('stdbuf -o0 ping ' + self.ping_args + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '.log', '\$', int(ping_time[0])*1.5) + ping_status = SSH.command('stdbuf -o0 ping ' + self.ping_args + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '.log', '\$', int(ping_time[0])*1.5) # TIMEOUT CASE if ping_status < 0: message = 'Ping with OAI UE crashed due to TIMEOUT!' @@ -2021,7 +2022,7 @@ class OaiCiTest(): elif float(packetloss) > 0: qMsg += '\nPacket Loss is not 0%' logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m') - self.close() + SSH.close() html_queue = SimpleQueue() ip_addr = 'TBD' html_cell = '
OAI UE ping result\n' + qMsg + '
' @@ -2033,11 +2034,11 @@ class OaiCiTest(): # copying on the EPC server for logCollection if ping_from_eNB is not None: - copyin_res = self.copyin(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.eNBSourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') + copyin_res = SSH.copyin(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.eNBSourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') else: - copyin_res = self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') + copyin_res = SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') if (copyin_res == 0): - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'ping_' + self.testCase_id + '.log', self.EPCSourceCodePath + '/scripts') + SSH.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'ping_' + self.testCase_id + '.log', self.EPCSourceCodePath + '/scripts') except: os.kill(os.getppid(),signal.SIGUSR1) @@ -2132,7 +2133,7 @@ class OaiCiTest(): return result def Iperf_analyzeV2TCPOutput(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): - self.command('awk -f /tmp/tcp_iperf_stats.awk /tmp/CI-eNB/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.command('awk -f /tmp/tcp_iperf_stats.awk /tmp/CI-eNB/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) result = re.search('Avg Bitrate : (?P[0-9\.]+ Mbits\/sec) Max Bitrate : (?P[0-9\.]+ Mbits\/sec) Min Bitrate : (?P[0-9\.]+ Mbits\/sec)', str(self.ssh.before)) if result is not None: avgbitrate = result.group('average') @@ -2398,14 +2399,14 @@ class OaiCiTest(): EPC_Iperf_UE_IPAddress = ret.stdout.strip() port = 5001 + idx if launchFromEpc: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) if udpIperf: - self.command('echo $USER; nohup iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.EPCUserName, 5) + SSH.command('echo $USER; nohup iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.EPCUserName, 5) else: - self.command('echo $USER; nohup iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.EPCUserName, 5) - self.close() + SSH.command('echo $USER; nohup iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.EPCUserName, 5) + SSH.close() else: if self.ueIperfVersion == self.dummyIperfVersion: prefix = '' @@ -2423,11 +2424,11 @@ class OaiCiTest(): # Launch iperf client on UE if (device_id == 'OAI-UE'): - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) else: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) iperf_time = self.Iperf_ComputeTime() time.sleep(0.5) @@ -2438,50 +2439,50 @@ class OaiCiTest(): modified_options = modified_options.replace('-R','') time.sleep(0.5) - self.command('rm -f iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.command('rm -f iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) if (device_id == 'OAI-UE'): - iperf_status = self.command('iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + ' -B ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + iperf_status = SSH.command('iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + ' -B ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) else: if self.ADBCentralized: - iperf_status = self.command('stdbuf -o0 adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '" 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + iperf_status = SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '" 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) else: - iperf_status = self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '"\' 2>&1 > iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) - self.command('fromdos -o iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - self.command('cat iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + iperf_status = SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '"\' 2>&1 > iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + SSH.command('fromdos -o iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.command('cat iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) # TIMEOUT Case if iperf_status < 0: - self.close() + SSH.close() message = 'iperf on UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT !' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() + SSH.close() self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) return clientStatus = self.Iperf_analyzeV2Output(lock, UE_IPAddress, device_id, statusQueue, modified_options) - self.close() + SSH.close() # Kill iperf server on EPC side if launchFromEpc: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('killall --signal SIGKILL iperf', self.EPCUserName, 5) - self.close() + SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.command('killall --signal SIGKILL iperf', self.EPCUserName, 5) + SSH.close() else: cmd = 'killall --signal SIGKILL iperf' logging.debug(cmd) subprocess.run(cmd, shell=True) time.sleep(1) - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') + SSH.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') # in case of failure, retrieve server log if (clientStatus == -1) or (clientStatus == -2): if launchFromEpc: time.sleep(1) if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): os.remove('iperf_server_' + self.testCase_id + '_' + device_id + '.log') - self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, self.EPCSourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + SSH.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, self.EPCSourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) # in case of OAI-UE if (device_id == 'OAI-UE'): - self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_' + self.testCase_id + '_' + device_id + '.log', '.') - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') + SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_' + self.testCase_id + '_' + device_id + '.log', '.') + SSH.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') def Iperf_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue): try: @@ -2493,29 +2494,29 @@ class OaiCiTest(): self.ueIperfVersion = '2.0.5' if (device_id != 'OAI-UE'): - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) # if by chance ADB server and EPC are on the same remote host, at least log collection will take care of it - self.command('if [ ! -d ' + self.EPCSourceCodePath + '/scripts ]; then mkdir -p ' + self.EPCSourceCodePath + '/scripts ; fi', '\$', 5) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + SSH.command('if [ ! -d ' + self.EPCSourceCodePath + '/scripts ]; then mkdir -p ' + self.EPCSourceCodePath + '/scripts ; fi', '\$', 5) + SSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) # Checking if iperf / iperf3 are installed if self.ADBCentralized: - self.command('adb -s ' + device_id + ' shell "ls /data/local/tmp"', '\$', 5) + SSH.command('adb -s ' + device_id + ' shell "ls /data/local/tmp"', '\$', 5) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ls /data/local/tmp"\'', '\$', 60) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ls /data/local/tmp"\'', '\$', 60) result = re.search('iperf3', str(self.ssh.before)) if result is None: result = re.search('iperf', str(self.ssh.before)) if result is None: message = 'Neither iperf nor iperf3 installed on UE!' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() + SSH.close() self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) return else: if self.ADBCentralized: - self.command('adb -s ' + device_id + ' shell "/data/local/tmp/iperf --version"', '\$', 5) + SSH.command('adb -s ' + device_id + ' shell "/data/local/tmp/iperf --version"', '\$', 5) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf --version"\'', '\$', 60) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf --version"\'', '\$', 60) result = re.search('iperf version 2.0.5', str(self.ssh.before)) if result is not None: self.ueIperfVersion = '2.0.5' @@ -2524,17 +2525,17 @@ class OaiCiTest(): self.ueIperfVersion = '2.0.10' else: useIperf3 = True - self.close() + SSH.close() else: - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('iperf --version', '\$', 5) + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('iperf --version', '\$', 5) result = re.search('iperf version 2.0.5', str(self.ssh.before)) if result is not None: self.ueIperfVersion = '2.0.5' result = re.search('iperf version 2.0.10', str(self.ssh.before)) if result is not None: self.ueIperfVersion = '2.0.10' - self.close() + SSH.close() # in case of iperf, UL has its own function if (not useIperf3): result = re.search('-R', str(self.iperf_args)) @@ -2544,35 +2545,35 @@ class OaiCiTest(): # Launch the IPERF server on the UE side for DL if (device_id == 'OAI-UE'): - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) - self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) + SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) result = re.search('-u', str(self.iperf_args)) if result is None: - self.command('echo $USER; nohup iperf -B ' + UE_IPAddress + ' -s -i 1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.UEUserName, 5) + SSH.command('echo $USER; nohup iperf -B ' + UE_IPAddress + ' -s -i 1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.UEUserName, 5) udpIperf = False else: - self.command('echo $USER; nohup iperf -B ' + UE_IPAddress + ' -u -s -i 1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.UEUserName, 5) + SSH.command('echo $USER; nohup iperf -B ' + UE_IPAddress + ' -u -s -i 1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.UEUserName, 5) else: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) if self.ADBCentralized: if (useIperf3): - self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/iperf3 -s &', '\$', 5) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/iperf3 -s &', '\$', 5) else: - self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) result = re.search('-u', str(self.iperf_args)) if result is None: - self.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) + SSH.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) udpIperf = False else: - self.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) + SSH.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) else: - self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - self.command('echo $USER; nohup ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" \' 2>&1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 60) + SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.command('echo $USER; nohup ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" \' 2>&1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 60) time.sleep(0.5) - self.close() + SSH.close() # Launch the IPERF client on the EPC side for DL (true for ltebox and old open-air-cn # But for OAI-Rel14-CUPS, we launch from python executor @@ -2580,8 +2581,8 @@ class OaiCiTest(): if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): launchFromEpc = False if launchFromEpc: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) iperf_time = self.Iperf_ComputeTime() time.sleep(0.5) @@ -2592,18 +2593,18 @@ class OaiCiTest(): time.sleep(0.5) if launchFromEpc: - self.command('rm -f iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.command('rm -f iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) else: if (os.path.isfile('iperf_' + self.testCase_id + '_' + device_id + '.log')): os.remove('iperf_' + self.testCase_id + '_' + device_id + '.log') if (useIperf3): - self.command('stdbuf -o0 iperf3 -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + SSH.command('stdbuf -o0 iperf3 -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) clientStatus = 0 self.Iperf_analyzeV3Output(lock, UE_IPAddress, device_id, statusQueue) else: if launchFromEpc: - iperf_status = self.command('stdbuf -o0 iperf -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + iperf_status = SSH.command('stdbuf -o0 iperf -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) else: if self.ueIperfVersion == self.dummyIperfVersion: prefix = '' @@ -2616,57 +2617,57 @@ class OaiCiTest(): logging.debug(cmd) ret = subprocess.run(cmd, shell=True) iperf_status = ret.returncode - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cat ' + self.EPCSourceCodePath + '/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') + SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.command('cat ' + self.EPCSourceCodePath + '/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) if iperf_status < 0: if launchFromEpc: - self.close() + SSH.close() message = 'iperf on UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT !' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) return clientStatus = self.Iperf_analyzeV2Output(lock, UE_IPAddress, device_id, statusQueue, modified_options) - self.close() + SSH.close() # Kill the IPERF server that runs in background if (device_id == 'OAI-UE'): - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('killall iperf', '\$', 5) + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('killall iperf', '\$', 5) else: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell ps | grep --color=never iperf | grep -v grep', '\$', 5) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell ps | grep --color=never iperf | grep -v grep', '\$', 5) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ps" | grep --color=never iperf | grep -v grep\'', '\$', 60) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ps" | grep --color=never iperf | grep -v grep\'', '\$', 60) result = re.search('shell +(?P\d+)', str(self.ssh.before)) if result is not None: pid_iperf = result.group('pid') if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell kill -KILL ' + pid_iperf, '\$', 5) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell kill -KILL ' + pid_iperf, '\$', 5) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"\'', '\$', 60) - self.close() + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"\'', '\$', 60) + SSH.close() # if the client report is absent, try to analyze the server log file if (clientStatus == -1): time.sleep(1) if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): os.remove('iperf_server_' + self.testCase_id + '_' + device_id + '.log') if (device_id == 'OAI-UE'): - self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') else: - self.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, self.EPCSourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') - self.command('fromdos -o iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, self.EPCSourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + SSH.command('fromdos -o iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) # in case of OAI UE: if (device_id == 'OAI-UE'): if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): if not launchFromEpc: - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') + SSH.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') else: - self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') + SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + SSH.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') except: os.kill(os.getppid(),signal.SIGUSR1) @@ -2697,24 +2698,24 @@ class OaiCiTest(): iClientUser = self.eNBUserName iClientPasswd = self.eNBPassword # Starting the iperf server - self.open(iServerIPAddr, iServerUser, iServerPasswd) + SSH.open(iServerIPAddr, iServerUser, iServerPasswd) # args SHALL be "-c client -u any" # -c 10.0.1.2 -u -b 1M -t 30 -i 1 -fm -B 10.0.1.1 # -B 10.0.1.1 -u -s -i 1 -fm server_options = re.sub('-u.*$', '-u -s -i 1 -fm', str(self.iperf_args)) server_options = server_options.replace('-c','-B') - self.command('rm -f /tmp/tmp_iperf_server_' + self.testCase_id + '.log', '\$', 5) - self.command('echo $USER; nohup iperf ' + server_options + ' > /tmp/tmp_iperf_server_' + self.testCase_id + '.log 2>&1 &', iServerUser, 5) + SSH.command('rm -f /tmp/tmp_iperf_server_' + self.testCase_id + '.log', '\$', 5) + SSH.command('echo $USER; nohup iperf ' + server_options + ' > /tmp/tmp_iperf_server_' + self.testCase_id + '.log 2>&1 &', iServerUser, 5) time.sleep(0.5) - self.close() + SSH.close() # Starting the iperf client modified_options = self.Iperf_ComputeModifiedBW(0, 1) modified_options = modified_options.replace('-R','') iperf_time = self.Iperf_ComputeTime() - self.open(iClientIPAddr, iClientUser, iClientPasswd) - self.command('rm -f /tmp/tmp_iperf_' + self.testCase_id + '.log', '\$', 5) - iperf_status = self.command('stdbuf -o0 iperf ' + modified_options + ' 2>&1 | stdbuf -o0 tee /tmp/tmp_iperf_' + self.testCase_id + '.log', '\$', int(iperf_time)*5.0) + SSH.open(iClientIPAddr, iClientUser, iClientPasswd) + SSH.command('rm -f /tmp/tmp_iperf_' + self.testCase_id + '.log', '\$', 5) + iperf_status = SSH.command('stdbuf -o0 iperf ' + modified_options + ' 2>&1 | stdbuf -o0 tee /tmp/tmp_iperf_' + self.testCase_id + '.log', '\$', int(iperf_time)*5.0) status_queue = SimpleQueue() lock = Lock() if iperf_status < 0: @@ -2723,26 +2724,26 @@ class OaiCiTest(): clientStatus = -2 else: clientStatus = self.Iperf_analyzeV2Output(lock, '10.0.1.2', 'OAI-UE', status_queue, modified_options) - self.close() + SSH.close() # Stopping the iperf server - self.open(iServerIPAddr, iServerUser, iServerPasswd) - self.command('killall --signal SIGKILL iperf', '\$', 5) + SSH.open(iServerIPAddr, iServerUser, iServerPasswd) + SSH.command('killall --signal SIGKILL iperf', '\$', 5) time.sleep(0.5) - self.close() + SSH.close() if (clientStatus == -1): if (os.path.isfile('iperf_server_' + self.testCase_id + '.log')): os.remove('iperf_server_' + self.testCase_id + '.log') - self.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log') + SSH.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log') self.Iperf_analyzeV2Server(lock, '10.0.1.2', 'OAI-UE', status_queue, modified_options) # copying on the EPC server for logCollection - copyin_res = self.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log') + copyin_res = SSH.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log') if (copyin_res == 0): - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_OAI-UE.log', self.EPCSourceCodePath + '/scripts') - copyin_res = self.copyin(iClientIPAddr, iClientUser, iClientPasswd, '/tmp/tmp_iperf_' + self.testCase_id + '.log', 'iperf_' + self.testCase_id + '_OAI-UE.log') + SSH.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_OAI-UE.log', self.EPCSourceCodePath + '/scripts') + copyin_res = SSH.copyin(iClientIPAddr, iClientUser, iClientPasswd, '/tmp/tmp_iperf_' + self.testCase_id + '.log', 'iperf_' + self.testCase_id + '_OAI-UE.log') if (copyin_res == 0): - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_' + self.testCase_id + '_OAI-UE.log', self.EPCSourceCodePath + '/scripts') + SSH.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_' + self.testCase_id + '_OAI-UE.log', self.EPCSourceCodePath + '/scripts') iperf_noperf = False if status_queue.empty(): iperf_status = False @@ -2889,7 +2890,7 @@ class OaiCiTest(): if result == ENB_PROCESS_FAILED: fileCheck = re.search('enb_', str(self.eNBLogFiles[0])) if fileCheck is not None: - self.copyin(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.eNBSourceCodePath + '/cmake_targets/' + self.eNBLogFiles[0], '.') + SSH.copyin(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.eNBSourceCodePath + '/cmake_targets/' + self.eNBLogFiles[0], '.') logStatus = self.AnalyzeLogFile_eNB(self.eNBLogFiles[0]) if logStatus < 0: result = logStatus @@ -2920,7 +2921,7 @@ class OaiCiTest(): if result == OAI_UE_PROCESS_FAILED: fileCheck = re.search('ue_', str(self.UELogFile)) if fileCheck is not None: - self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.') + SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.') logStatus = self.AnalyzeLogFile_UE(self.UELogFile) if logStatus < 0: result = logStatus @@ -2928,36 +2929,36 @@ class OaiCiTest(): def CheckOAIUEProcess(self, status_queue): try: - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) result = re.search('lte-uesoftmodem', str(self.ssh.before)) if result is None: logging.debug('\u001B[1;37;41m OAI UE Process Not Found! \u001B[0m') status_queue.put(OAI_UE_PROCESS_FAILED) else: status_queue.put(OAI_UE_PROCESS_OK) - self.close() + SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) def CheckeNBProcess(self, status_queue): try: - self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) - self.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + SSH.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) + SSH.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) result = re.search('lte-softmodem', str(self.ssh.before)) if result is None: logging.debug('\u001B[1;37;41m eNB Process Not Found! \u001B[0m') status_queue.put(ENB_PROCESS_FAILED) else: status_queue.put(ENB_PROCESS_OK) - self.close() + SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) def CheckHSSProcess(self, status_queue): try: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('stdbuf -o0 ps -aux | grep --color=never hss | grep -v grep', '\$', 5) + SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.command('stdbuf -o0 ps -aux | grep --color=never hss | grep -v grep', '\$', 5) if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): result = re.search('oai_hss -j', str(self.ssh.before)) elif re.match('OAI', self.EPCType, re.IGNORECASE): @@ -2971,14 +2972,14 @@ class OaiCiTest(): status_queue.put(HSS_PROCESS_FAILED) else: status_queue.put(HSS_PROCESS_OK) - self.close() + SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) def CheckMMEProcess(self, status_queue): try: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('stdbuf -o0 ps -aux | grep --color=never mme | grep -v grep', '\$', 5) + SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.command('stdbuf -o0 ps -aux | grep --color=never mme | grep -v grep', '\$', 5) if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): result = re.search('mme -c', str(self.ssh.before)) elif re.match('OAI', self.EPCType, re.IGNORECASE): @@ -2992,21 +2993,21 @@ class OaiCiTest(): status_queue.put(MME_PROCESS_FAILED) else: status_queue.put(MME_PROCESS_OK) - self.close() + SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) def CheckSPGWProcess(self, status_queue): try: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('stdbuf -o0 ps -aux | grep --color=never spgw | grep -v grep', '\$', 5) + SSH.command('stdbuf -o0 ps -aux | grep --color=never spgw | grep -v grep', '\$', 5) result = re.search('spgwu -c ', str(self.ssh.before)) elif re.match('OAI', self.EPCType, re.IGNORECASE): - self.command('stdbuf -o0 ps -aux | grep --color=never spgw | grep -v grep', '\$', 5) + SSH.command('stdbuf -o0 ps -aux | grep --color=never spgw | grep -v grep', '\$', 5) result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('stdbuf -o0 ps -aux | grep --color=never xGw | grep -v grep', '\$', 5) + SSH.command('stdbuf -o0 ps -aux | grep --color=never xGw | grep -v grep', '\$', 5) result = re.search('xGw', str(self.ssh.before)) else: logging.error('This should not happen!') @@ -3015,7 +3016,7 @@ class OaiCiTest(): status_queue.put(SPGW_PROCESS_FAILED) else: status_queue.put(SPGW_PROCESS_OK) - self.close() + SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) @@ -3444,46 +3445,46 @@ class OaiCiTest(): if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': Usage() sys.exit('Insufficient Parameter') - self.open(lIpAddr, lUserName, lPassWord) - self.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) - self.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + SSH.open(lIpAddr, lUserName, lPassWord) + SSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) + SSH.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) result = re.search('lte-softmodem', str(self.ssh.before)) if result is not None: - self.command('echo ' + lPassWord + ' | sudo -S daemon --name=enb' + str(self.eNB_instance) + '_daemon --stop', '\$', 5) - self.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGINT lte-softmodem || true', '\$', 5) + SSH.command('echo ' + lPassWord + ' | sudo -S daemon --name=enb' + str(self.eNB_instance) + '_daemon --stop', '\$', 5) + SSH.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGINT lte-softmodem || true', '\$', 5) time.sleep(10) - self.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + SSH.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) result = re.search('lte-softmodem', str(self.ssh.before)) if result is not None: - self.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGKILL lte-softmodem || true', '\$', 5) + SSH.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGKILL lte-softmodem || true', '\$', 5) time.sleep(5) - self.command('rm -f my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - self.close() + SSH.command('rm -f my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + SSH.close() # If tracer options is on, stopping tshark on EPC side result = re.search('T_stdout', str(self.Initialize_eNB_args)) if result is not None: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) logging.debug('\u001B[1m Stopping tshark \u001B[0m') - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) time.sleep(1) if self.EPC_PcapFileName != '': - self.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 /tmp/' + self.EPC_PcapFileName, '\$', 5) - self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + self.EPC_PcapFileName, '.') - self.copyout(lIpAddr, lUserName, lPassWord, self.EPC_PcapFileName, lSourcePath + '/cmake_targets/.') - self.close() + SSH.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 /tmp/' + self.EPC_PcapFileName, '\$', 5) + SSH.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + self.EPC_PcapFileName, '.') + SSH.copyout(lIpAddr, lUserName, lPassWord, self.EPC_PcapFileName, lSourcePath + '/cmake_targets/.') + SSH.close() logging.debug('\u001B[1m Replaying RAW record file\u001B[0m') - self.open(lIpAddr, lUserName, lPassWord) - self.command('cd ' + lSourcePath + '/common/utils/T/tracer/', '\$', 5) + SSH.open(lIpAddr, lUserName, lPassWord) + SSH.command('cd ' + lSourcePath + '/common/utils/T/tracer/', '\$', 5) enbLogFile = self.eNBLogFiles[int(self.eNB_instance)] raw_record_file = enbLogFile.replace('.log', '_record.raw') replay_log_file = enbLogFile.replace('.log', '_replay.log') extracted_txt_file = enbLogFile.replace('.log', '_extracted_messages.txt') extracted_log_file = enbLogFile.replace('.log', '_extracted_messages.log') - self.command('./extract_config -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + extracted_txt_file, '\$', 5) - self.command('echo $USER; nohup ./replay -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + replay_log_file + ' 2>&1 &', lUserName, 5) - self.command('./textlog -d ' + lSourcePath + '/cmake_targets/' + extracted_txt_file + ' -no-gui -ON -full > ' + lSourcePath + '/cmake_targets/' + extracted_log_file, '\$', 5) - self.close() - self.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + extracted_log_file, '.') + SSH.command('./extract_config -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + extracted_txt_file, '\$', 5) + SSH.command('echo $USER; nohup ./replay -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + replay_log_file + ' 2>&1 &', lUserName, 5) + SSH.command('./textlog -d ' + lSourcePath + '/cmake_targets/' + extracted_txt_file + ' -no-gui -ON -full > ' + lSourcePath + '/cmake_targets/' + extracted_log_file, '\$', 5) + SSH.close() + SSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + extracted_log_file, '.') logging.debug('\u001B[1m Analyzing eNB replay logfile \u001B[0m') logStatus = self.AnalyzeLogFile_eNB(extracted_log_file) self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) @@ -3495,14 +3496,14 @@ class OaiCiTest(): fileToAnalyze = self.eNBLogFiles[int(self.eNB_instance)] self.eNBLogFiles[int(self.eNB_instance)] = '' if analyzeFile: - copyin_res = self.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + fileToAnalyze, '.') + copyin_res = SSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + fileToAnalyze, '.') if (copyin_res == -1): logging.debug('\u001B[1;37;41m Could not copy eNB logfile to analyze it! \u001B[0m') self.htmleNBFailureMsg = 'Could not copy eNB logfile to analyze it!' self.CreateHtmlTestRow('N/A', 'KO', ENB_PROCESS_NOLOGFILE_TO_ANALYZE) return if self.eNB_serverId != '0': - self.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './' + fileToAnalyze, self.eNBSourceCodePath + '/cmake_targets/') + SSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './' + fileToAnalyze, self.eNBSourceCodePath + '/cmake_targets/') logging.debug('\u001B[1m Analyzing eNB logfile \u001B[0m ' + fileToAnalyze) logStatus = self.AnalyzeLogFile_eNB(fileToAnalyze) if (logStatus < 0): @@ -3515,79 +3516,79 @@ class OaiCiTest(): self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) def TerminateHSS(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT oai_hss || true', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT oai_hss || true', '\$', 5) time.sleep(2) - self.command('stdbuf -o0 ps -aux | grep hss | grep -v grep', '\$', 5) + SSH.command('stdbuf -o0 ps -aux | grep hss | grep -v grep', '\$', 5) result = re.search('oai_hss -j', str(self.ssh.before)) if result is not None: - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL oai_hss || true', '\$', 5) - self.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-hss.sh', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL oai_hss || true', '\$', 5) + SSH.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-hss.sh', '\$', 5) elif re.match('OAI', self.EPCType, re.IGNORECASE): - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_hss oai_hss || true', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_hss oai_hss || true', '\$', 5) time.sleep(2) - self.command('stdbuf -o0 ps -aux | grep hss | grep -v grep', '\$', 5) + SSH.command('stdbuf -o0 ps -aux | grep hss | grep -v grep', '\$', 5) result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) if result is not None: - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_hss oai_hss || true', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_hss oai_hss || true', '\$', 5) elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('cd scripts', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S daemon --name=simulated_hss --stop', '\$', 5) + SSH.command('cd ' + self.EPCSourceCodePath, '\$', 5) + SSH.command('cd scripts', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S daemon --name=simulated_hss --stop', '\$', 5) time.sleep(1) - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL hss_sim', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL hss_sim', '\$', 5) else: logging.error('This should not happen!') - self.close() + SSH.close() self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) def TerminateMME(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_mme mme || true', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_mme mme || true', '\$', 5) time.sleep(2) - self.command('stdbuf -o0 ps -aux | grep mme | grep -v grep', '\$', 5) + SSH.command('stdbuf -o0 ps -aux | grep mme | grep -v grep', '\$', 5) result = re.search('mme -c', str(self.ssh.before)) if result is not None: - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_mme mme || true', '\$', 5) - self.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-mme.sh', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_mme mme || true', '\$', 5) + SSH.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-mme.sh', '\$', 5) elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cd /opt/ltebox/tools', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S ./stop_mme', '\$', 5) + SSH.command('cd /opt/ltebox/tools', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S ./stop_mme', '\$', 5) else: logging.error('This should not happen!') - self.close() + SSH.close() self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) def TerminateSPGW(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT spgwc spgwu || true', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT spgwc spgwu || true', '\$', 5) time.sleep(2) - self.command('stdbuf -o0 ps -aux | grep spgw | grep -v grep', '\$', 5) + SSH.command('stdbuf -o0 ps -aux | grep spgw | grep -v grep', '\$', 5) result = re.search('spgwc -c |spgwu -c ', str(self.ssh.before)) if result is not None: - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL spgwc spgwu || true', '\$', 5) - self.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-spgw*.sh', '\$', 5) - self.command('stdbuf -o0 ps -aux | grep tshark | grep -v grep', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL spgwc spgwu || true', '\$', 5) + SSH.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-spgw*.sh', '\$', 5) + SSH.command('stdbuf -o0 ps -aux | grep tshark | grep -v grep', '\$', 5) result = re.search('-w ', str(self.ssh.before)) if result is not None: - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT tshark || true', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 ' + self.EPCSourceCodePath + '/scripts/*.pcap', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT tshark || true', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 ' + self.EPCSourceCodePath + '/scripts/*.pcap', '\$', 5) elif re.match('OAI', self.EPCType, re.IGNORECASE): - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_spgw spgw || true', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_spgw spgw || true', '\$', 5) time.sleep(2) - self.command('stdbuf -o0 ps -aux | grep spgw | grep -v grep', '\$', 5) + SSH.command('stdbuf -o0 ps -aux | grep spgw | grep -v grep', '\$', 5) result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) if result is not None: - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_spgw spgw || true', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_spgw spgw || true', '\$', 5) elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cd /opt/ltebox/tools', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S ./stop_xGw', '\$', 5) + SSH.command('cd /opt/ltebox/tools', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S ./stop_xGw', '\$', 5) else: logging.error('This should not happen!') - self.close() + SSH.close() self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) def TerminateFlexranCtrl(self): @@ -3596,40 +3597,40 @@ class OaiCiTest(): if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '': Usage() sys.exit('Insufficient Parameter') - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('echo ' + self.EPCPassword + ' | sudo -S daemon --name=flexran_rtc_daemon --stop', '\$', 5) + SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S daemon --name=flexran_rtc_daemon --stop', '\$', 5) time.sleep(1) - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL rt_controller', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL rt_controller', '\$', 5) time.sleep(1) - self.close() + SSH.close() self.flexranCtrlStarted = False self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) def TerminateUE_common(self, device_id, idx): try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) # back in airplane mode on (ie radio off) if self.ADBCentralized: if device_id == '84B7N16418004022': - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) else: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) logging.debug('\u001B[1mUE (' + device_id + ') Detach Completed\u001B[0m') if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "ps | grep --color=never iperf | grep -v grep"', '\$', 5) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "ps | grep --color=never iperf | grep -v grep"', '\$', 5) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ps | grep --color=never iperf | grep -v grep"\'', '\$', 60) + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ps | grep --color=never iperf | grep -v grep"\'', '\$', 60) result = re.search('shell +(?P\d+)', str(self.ssh.before)) if result is not None: pid_iperf = result.group('pid') if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"', '\$', 5) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"', '\$', 5) else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"\'', '\$', 60) - self.close() + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"\'', '\$', 60) + SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) @@ -3649,24 +3650,24 @@ class OaiCiTest(): self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) def TerminateOAIUE(self): - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) - self.command('ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) + SSH.command('ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) result = re.search('lte-uesoftmodem', str(self.ssh.before)) if result is not None: - self.command('echo ' + self.UEPassword + ' | sudo -S daemon --name=ue' + str(self.UE_instance) + '_daemon --stop', '\$', 5) - self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGINT lte-uesoftmodem || true', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S daemon --name=ue' + str(self.UE_instance) + '_daemon --stop', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGINT lte-uesoftmodem || true', '\$', 5) time.sleep(10) - self.command('ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + SSH.command('ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) result = re.search('lte-uesoftmodem', str(self.ssh.before)) if result is not None: - self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGKILL lte-uesoftmodem || true', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGKILL lte-uesoftmodem || true', '\$', 5) time.sleep(5) - self.command('rm -f my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) - self.close() + SSH.command('rm -f my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) + SSH.close() result = re.search('ue_', str(self.UELogFile)) if result is not None: - copyin_res = self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.') + copyin_res = SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.') if (copyin_res == -1): logging.debug('\u001B[1;37;41m Could not copy UE logfile to analyze it! \u001B[0m') self.htmlUEFailureMsg = 'Could not copy UE logfile to analyze it!' @@ -3848,93 +3849,93 @@ class OaiCiTest(): SourceCodePath = self.UESourceCodePath else: sys.exit('Insufficient Parameter') - self.open(IPAddress, UserName, Password) - self.command('cd ' + SourceCodePath, '\$', 5) - self.command('cd cmake_targets', '\$', 5) - self.command('rm -f build.log.zip', '\$', 5) - self.command('zip build.log.zip build_log_*/*', '\$', 60) - self.close() + SSH.open(IPAddress, UserName, Password) + SSH.command('cd ' + SourceCodePath, '\$', 5) + SSH.command('cd cmake_targets', '\$', 5) + SSH.command('rm -f build.log.zip', '\$', 5) + SSH.command('zip build.log.zip build_log_*/*', '\$', 60) + SSH.close() def LogCollecteNB(self): - self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) - self.command('cd ' + self.eNBSourceCodePath, '\$', 5) - self.command('cd cmake_targets', '\$', 5) - self.command('echo ' + self.eNBPassword + ' | sudo -S rm -f enb.log.zip', '\$', 5) - self.command('echo ' + self.eNBPassword + ' | sudo -S zip enb.log.zip enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 60) - self.command('echo ' + self.eNBPassword + ' | sudo -S rm enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 5) - self.close() + SSH.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) + SSH.command('cd ' + self.eNBSourceCodePath, '\$', 5) + SSH.command('cd cmake_targets', '\$', 5) + SSH.command('echo ' + self.eNBPassword + ' | sudo -S rm -f enb.log.zip', '\$', 5) + SSH.command('echo ' + self.eNBPassword + ' | sudo -S zip enb.log.zip enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 60) + SSH.command('echo ' + self.eNBPassword + ' | sudo -S rm enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 5) + SSH.close() def LogCollectPing(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('cd scripts', '\$', 5) - self.command('rm -f ping.log.zip', '\$', 5) - self.command('zip ping.log.zip ping*.log', '\$', 60) - self.command('rm ping*.log', '\$', 5) - self.close() + SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.command('cd ' + self.EPCSourceCodePath, '\$', 5) + SSH.command('cd scripts', '\$', 5) + SSH.command('rm -f ping.log.zip', '\$', 5) + SSH.command('zip ping.log.zip ping*.log', '\$', 60) + SSH.command('rm ping*.log', '\$', 5) + SSH.close() def LogCollectIperf(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('cd scripts', '\$', 5) - self.command('rm -f iperf.log.zip', '\$', 5) - self.command('zip iperf.log.zip iperf*.log', '\$', 60) - self.command('rm iperf*.log', '\$', 5) - self.close() + SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.command('cd ' + self.EPCSourceCodePath, '\$', 5) + SSH.command('cd scripts', '\$', 5) + SSH.command('rm -f iperf.log.zip', '\$', 5) + SSH.command('zip iperf.log.zip iperf*.log', '\$', 60) + SSH.command('rm iperf*.log', '\$', 5) + SSH.close() def LogCollectHSS(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('rm -f hss.log.zip', '\$', 5) + SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + SSH.command('rm -f hss.log.zip', '\$', 5) if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('zip hss.log.zip hss*.log', '\$', 60) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm hss*.log', '\$', 5) + SSH.command('zip hss.log.zip hss*.log', '\$', 60) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S rm hss*.log', '\$', 5) if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('zip hss.log.zip logs/hss*.* *.pcap', '\$', 60) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f logs/hss*.* *.pcap', '\$', 5) + SSH.command('zip hss.log.zip logs/hss*.* *.pcap', '\$', 60) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f logs/hss*.* *.pcap', '\$', 5) elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cp /opt/hss_sim0609/hss.log .', '\$', 60) - self.command('zip hss.log.zip hss.log', '\$', 60) + SSH.command('cp /opt/hss_sim0609/hss.log .', '\$', 60) + SSH.command('zip hss.log.zip hss.log', '\$', 60) else: logging.error('This option should not occur!') - self.close() + SSH.close() def LogCollectMME(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('rm -f mme.log.zip', '\$', 5) + SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + SSH.command('rm -f mme.log.zip', '\$', 5) if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('zip mme.log.zip mme*.log', '\$', 60) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm mme*.log', '\$', 5) + SSH.command('zip mme.log.zip mme*.log', '\$', 60) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S rm mme*.log', '\$', 5) elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cp /opt/ltebox/var/log/*Log.0 .', '\$', 5) - self.command('zip mme.log.zip mmeLog.0 s1apcLog.0 s1apsLog.0 s11cLog.0 libLog.0 s1apCodecLog.0', '\$', 60) + SSH.command('cp /opt/ltebox/var/log/*Log.0 .', '\$', 5) + SSH.command('zip mme.log.zip mmeLog.0 s1apcLog.0 s1apsLog.0 s11cLog.0 libLog.0 s1apCodecLog.0', '\$', 60) else: logging.error('This option should not occur!') - self.close() + SSH.close() def LogCollectSPGW(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('rm -f spgw.log.zip', '\$', 5) + SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + SSH.command('rm -f spgw.log.zip', '\$', 5) if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('zip spgw.log.zip spgw*.log', '\$', 60) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm spgw*.log', '\$', 5) + SSH.command('zip spgw.log.zip spgw*.log', '\$', 60) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S rm spgw*.log', '\$', 5) elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cp /opt/ltebox/var/log/xGwLog.0 .', '\$', 5) - self.command('zip spgw.log.zip xGwLog.0', '\$', 60) + SSH.command('cp /opt/ltebox/var/log/xGwLog.0 .', '\$', 5) + SSH.command('zip spgw.log.zip xGwLog.0', '\$', 60) else: logging.error('This option should not occur!') - self.close() + SSH.close() def LogCollectOAIUE(self): - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('cd ' + self.UESourceCodePath, '\$', 5) - self.command('cd cmake_targets', '\$', 5) - self.command('echo ' + self.UEPassword + ' | sudo -S rm -f ue.log.zip', '\$', 5) - self.command('echo ' + self.UEPassword + ' | sudo -S zip ue.log.zip ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 60) - self.command('echo ' + self.UEPassword + ' | sudo -S rm ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 5) - self.close() + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('cd ' + self.UESourceCodePath, '\$', 5) + SSH.command('cd cmake_targets', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -f ue.log.zip', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S zip ue.log.zip ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 60) + SSH.command('echo ' + self.UEPassword + ' | sudo -S rm ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 5) + SSH.close() def RetrieveSystemVersion(self, machine): if self.eNBIPAddress == 'none' or self.UEIPAddress == 'none': @@ -3961,28 +3962,28 @@ class OaiCiTest(): else: return -1 - self.open(IPAddress, UserName, Password) - self.command('lsb_release -a', '\$', 5) + SSH.open(IPAddress, UserName, Password) + SSH.command('lsb_release -a', '\$', 5) result = re.search('Description:\\\\t(?P[a-zA-Z0-9\-\_\.\ ]+)', str(self.ssh.before)) if result is not None: self.OsVersion = result.group('os_type') logging.debug('OS is: ' + self.OsVersion) - self.command('uname -r', '\$', 5) + SSH.command('uname -r', '\$', 5) result = re.search('uname -r\\\\r\\\\n(?P[a-zA-Z0-9\-\_\.]+)', str(self.ssh.before)) if result is not None: self.KernelVersion = result.group('kernel_version') logging.debug('Kernel Version is: ' + self.KernelVersion) - self.command('dpkg --list | egrep --color=never libuhd003', '\$', 5) + SSH.command('dpkg --list | egrep --color=never libuhd003', '\$', 5) result = re.search('libuhd003:amd64 *(?P[0-9\.]+)', str(self.ssh.before)) if result is not None: self.UhdVersion = result.group('uhd_version') logging.debug('UHD Version is: ' + self.UhdVersion) - self.command('echo ' + Password + ' | sudo -S uhd_find_devices', '\$', 15) + SSH.command('echo ' + Password + ' | sudo -S uhd_find_devices', '\$', 15) result = re.search('product: (?P[0-9A-Za-z]+)\\\\r\\\\n', str(self.ssh.before)) if result is not None: self.UsrpBoard = result.group('usrp_board') logging.debug('USRP Board is: ' + self.UsrpBoard) - self.command('lscpu', '\$', 5) + SSH.command('lscpu', '\$', 5) result = re.search('CPU\(s\): *(?P[0-9]+).*Model name: *(?P[a-zA-Z0-9\-\_\.\ \(\)]+).*CPU MHz: *(?P[0-9\.]+)', str(self.ssh.before)) if result is not None: self.CpuNb = result.group('nb_cpus') @@ -3991,7 +3992,7 @@ class OaiCiTest(): logging.debug('model: ' + self.CpuModel) self.CpuMHz = result.group('cpu_mhz') + ' MHz' logging.debug('cpu_mhz: ' + self.CpuMHz) - self.close() + SSH.close() #----------------------------------------------------------- # HTML Reporting.... @@ -4503,6 +4504,7 @@ def receive_signal(signum, frame): #----------------------------------------------------------- mode = '' CiTestObj = OaiCiTest() +SSH = SSHConnection() argvs = sys.argv argc = len(argvs) diff --git a/ci-scripts/sshconnection.py b/ci-scripts/sshconnection.py new file mode 100644 index 0000000000..b74fa14f58 --- /dev/null +++ b/ci-scripts/sshconnection.py @@ -0,0 +1,167 @@ +#----------------------------------------------------------- +# Class Declaration +#----------------------------------------------------------- +class SSHConnection(): + def __init__(self): + def open(self, ipaddress, username, password): + count = 0 + connect_status = False + while count < 4: + self.ssh = pexpect.spawn('ssh', [username + '@' + ipaddress], timeout = 5) + self.sshresponse = self.ssh.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', 'Last login', pexpect.EOF, pexpect.TIMEOUT]) + if self.sshresponse == 0: + self.ssh.sendline('yes') + self.ssh.expect('password:') + self.ssh.sendline(password) + self.sshresponse = self.ssh.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if self.sshresponse == 0: + count = 10 + connect_status = True + else: + logging.debug('self.sshresponse = ' + str(self.sshresponse)) + elif self.sshresponse == 1: + self.ssh.sendline(password) + self.sshresponse = self.ssh.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if self.sshresponse == 0: + count = 10 + connect_status = True + else: + logging.debug('self.sshresponse = ' + str(self.sshresponse)) + elif self.sshresponse == 2: + # Checking if we are really on the remote client defined by its IP address + self.command('stdbuf -o0 ifconfig | egrep --color=never "inet addr:|inet "', '\$', 5) + result = re.search(str(ipaddress), str(self.ssh.before)) + if result is None: + self.close() + else: + count = 10 + connect_status = True + else: + # debug output + logging.debug(str(self.ssh.before)) + logging.debug('self.sshresponse = ' + str(self.sshresponse)) + # adding a tempo when failure + if not connect_status: + time.sleep(1) + count += 1 + if connect_status: + pass + else: + sys.exit('CiTestObj.Connection Failed') + + + def command(self, commandline, expectedline, timeout): + logging.debug(commandline) + self.ssh.timeout = timeout + self.ssh.sendline(commandline) + self.sshresponse = self.ssh.expect([expectedline, pexpect.EOF, pexpect.TIMEOUT]) + if self.sshresponse == 0: + return 0 + elif self.sshresponse == 1: + logging.debug('\u001B[1;37;41m Unexpected EOF \u001B[0m') + logging.debug('Expected Line : ' + expectedline) + sys.exit(self.sshresponse) + elif self.sshresponse == 2: + logging.debug('\u001B[1;37;41m Unexpected TIMEOUT \u001B[0m') + logging.debug('Expected Line : ' + expectedline) + result = re.search('ping |iperf |picocom', str(commandline)) + if result is None: + logging.debug(str(self.ssh.before)) + sys.exit(self.sshresponse) + else: + return -1 + else: + logging.debug('\u001B[1;37;41m Unexpected Others \u001B[0m') + logging.debug('Expected Line : ' + expectedline) + sys.exit(self.sshresponse) + + def close(self): + self.ssh.timeout = 5 + self.ssh.sendline('exit') + self.sshresponse = self.ssh.expect([pexpect.EOF, pexpect.TIMEOUT]) + if self.sshresponse == 0: + pass + elif self.sshresponse == 1: + if not self.picocom_closure: + logging.debug('\u001B[1;37;41m Unexpected TIMEOUT during closing\u001B[0m') + else: + logging.debug('\u001B[1;37;41m Unexpected Others during closing\u001B[0m') + + def copyin(self, ipaddress, username, password, source, destination): + count = 0 + copy_status = False + logging.debug('scp '+ username + '@' + ipaddress + ':' + source + ' ' + destination) + while count < 10: + scp_spawn = pexpect.spawn('scp '+ username + '@' + ipaddress + ':' + source + ' ' + destination, timeout = 100) + scp_response = scp_spawn.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if scp_response == 0: + scp_spawn.sendline('yes') + scp_spawn.expect('password:') + scp_spawn.sendline(password) + scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if scp_response == 0: + count = 10 + copy_status = True + else: + logging.debug('1 - scp_response = ' + str(scp_response)) + elif scp_response == 1: + scp_spawn.sendline(password) + scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if scp_response == 0 or scp_response == 3: + count = 10 + copy_status = True + else: + logging.debug('2 - scp_response = ' + str(scp_response)) + elif scp_response == 2: + count = 10 + copy_status = True + else: + logging.debug('3 - scp_response = ' + str(scp_response)) + # adding a tempo when failure + if not copy_status: + time.sleep(1) + count += 1 + if copy_status: + return 0 + else: + return -1 + + def copyout(self, ipaddress, username, password, source, destination): + count = 0 + copy_status = False + logging.debug('scp ' + source + ' ' + username + '@' + ipaddress + ':' + destination) + while count < 4: + scp_spawn = pexpect.spawn('scp ' + source + ' ' + username + '@' + ipaddress + ':' + destination, timeout = 100) + scp_response = scp_spawn.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if scp_response == 0: + scp_spawn.sendline('yes') + scp_spawn.expect('password:') + scp_spawn.sendline(password) + scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if scp_response == 0: + count = 10 + copy_status = True + else: + logging.debug('1 - scp_response = ' + str(scp_response)) + elif scp_response == 1: + scp_spawn.sendline(password) + scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) + if scp_response == 0 or scp_response == 3: + count = 10 + copy_status = True + else: + logging.debug('2 - scp_response = ' + str(scp_response)) + elif scp_response == 2: + count = 10 + copy_status = True + else: + logging.debug('3 - scp_response = ' + str(scp_response)) + # adding a tempo when failure + if not copy_status: + time.sleep(1) + count += 1 + if copy_status: + pass + else: + sys.exit('SCP failed') + From ba9786dfeab199fb4546506ca9f2aef41130adbe Mon Sep 17 00:00:00 2001 From: Gabriele Perrone Date: Mon, 13 Jan 2020 15:12:33 +0100 Subject: [PATCH 077/240] review of modified main.py and sshconnection.py --- ci-scripts/main.py | 202 +++++++++--------- ci-scripts/pMain.sh | 9 + ci-scripts/sshconnection.py | 10 + .../xml_files/enb_usrp210_band7_epc_start.xml | 54 +++++ 4 files changed, 175 insertions(+), 100 deletions(-) create mode 100755 ci-scripts/pMain.sh create mode 100644 ci-scripts/xml_files/enb_usrp210_band7_epc_start.xml diff --git a/ci-scripts/main.py b/ci-scripts/main.py index dfbde89c45..9b332313bb 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -87,7 +87,6 @@ logging.basicConfig( level=logging.DEBUG, format="[%(asctime)s] %(name)s:%(levelname)s: %(message)s" ) -import sshconnection.py #----------------------------------------------------------- # Class Declaration @@ -214,7 +213,7 @@ class OaiCiTest(): elif self.sshresponse == 2: # Checking if we are really on the remote client defined by its IP address SSH.command('stdbuf -o0 ifconfig | egrep --color=never "inet addr:|inet "', '\$', 5) - result = re.search(str(ipaddress), str(self.ssh.before)) + result = re.search(str(ipaddress), SSH.getBefore()) if result is None: SSH.close() else: @@ -222,7 +221,7 @@ class OaiCiTest(): connect_status = True else: # debug output - logging.debug(str(self.ssh.before)) + logging.debug(SSH.getBefore()) logging.debug('self.sshresponse = ' + str(self.sshresponse)) # adding a tempo when failure if not connect_status: @@ -249,7 +248,7 @@ class OaiCiTest(): logging.debug('Expected Line : ' + expectedline) result = re.search('ping |iperf |picocom', str(commandline)) if result is None: - logging.debug(str(self.ssh.before)) + logging.debug(SSH.getBefore()) sys.exit(self.sshresponse) else: return -1 @@ -380,27 +379,27 @@ class OaiCiTest(): # Checking the BUILD INFO file if not self.backgroundBuild: SSH.command('ls *.txt', '\$', 5) - result = re.search('LAST_BUILD_INFO', str(self.ssh.before)) + result = re.search('LAST_BUILD_INFO', SSH.getBefore()) if result is not None: mismatch = False SSH.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) - result = re.search(self.ranCommitID, str(self.ssh.before)) + result = re.search(self.ranCommitID, SSH.getBefore()) if result is None: mismatch = True SSH.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) if (self.ranAllowMerge): - result = re.search('YES', str(self.ssh.before)) + result = re.search('YES', SSH.getBefore()) if result is None: mismatch = True SSH.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) if self.ranTargetBranch == '': - result = re.search('develop', str(self.ssh.before)) + result = re.search('develop', SSH.getBefore()) else: - result = re.search(self.ranTargetBranch, str(self.ssh.before)) + result = re.search(self.ranTargetBranch, SSH.getBefore()) if result is None: mismatch = True else: - result = re.search('NO', str(self.ssh.before)) + result = re.search('NO', SSH.getBefore()) if result is None: mismatch = True if not mismatch: @@ -461,7 +460,7 @@ class OaiCiTest(): buildOAIprocess = True while (count > 0) and buildOAIprocess: SSH.command('ps aux | grep --color=never build_ | grep -v grep', '\$', 3) - result = re.search('build_oai', str(self.ssh.before)) + result = re.search('build_oai', SSH.getBefore()) if result is None: buildOAIprocess = False else: @@ -474,7 +473,7 @@ class OaiCiTest(): SSH.command('ls lte_build_oai/build', '\$', 3) SSH.command('ls lte_build_oai/build', '\$', 3) buildStatus = True - result = re.search('lte-softmodem', str(self.ssh.before)) + result = re.search('lte-softmodem', SSH.getBefore()) if result is None: buildStatus = False else: @@ -531,27 +530,27 @@ class OaiCiTest(): SSH.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) SSH.command('git config user.name "OAI Jenkins"', '\$', 5) SSH.command('ls *.txt', '\$', 5) - result = re.search('LAST_BUILD_INFO', str(self.ssh.before)) + result = re.search('LAST_BUILD_INFO', SSH.getBefore()) if result is not None: mismatch = False SSH.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) - result = re.search(self.ranCommitID, str(self.ssh.before)) + result = re.search(self.ranCommitID, SSH.getBefore()) if result is None: mismatch = True SSH.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) if (self.ranAllowMerge): - result = re.search('YES', str(self.ssh.before)) + result = re.search('YES', SSH.getBefore()) if result is None: mismatch = True SSH.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) if self.ranTargetBranch == '': - result = re.search('develop', str(self.ssh.before)) + result = re.search('develop', SSH.getBefore()) else: - result = re.search(self.ranTargetBranch, str(self.ssh.before)) + result = re.search(self.ranTargetBranch, SSH.getBefore()) if result is None: mismatch = True else: - result = re.search('NO', str(self.ssh.before)) + result = re.search('NO', SSH.getBefore()) if result is None: mismatch = True if not mismatch: @@ -581,7 +580,7 @@ class OaiCiTest(): SSH.command('ls lte_build_oai/build', '\$', 3) SSH.command('ls lte_build_oai/build', '\$', 3) buildStatus = True - result = re.search('lte-uesoftmodem', str(self.ssh.before)) + result = re.search('lte-uesoftmodem', SSH.getBefore()) if result is None: buildStatus = False SSH.command('mkdir -p build_log_' + self.testCase_id, '\$', 5) @@ -660,7 +659,7 @@ class OaiCiTest(): SSH.command('source oaienv', '\$', 5) SSH.command('cd scripts', '\$', 5) SSH.command('stdbuf -o0 hostname', '\$', 5) - result = re.search('hostname\\\\r\\\\n(?P[a-zA-Z0-9\-\_]+)\\\\r\\\\n', str(self.ssh.before)) + result = re.search('hostname\\\\r\\\\n(?P[a-zA-Z0-9\-\_]+)\\\\r\\\\n', SSH.getBefore()) if result is None: logging.debug('\u001B[1;37;41m Hostname Not Found! \u001B[0m') sys.exit(1) @@ -708,7 +707,7 @@ class OaiCiTest(): return SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) SSH.command('ls -ls /opt/flexran_rtc/*/rt_controller', '\$', 5) - result = re.search('/opt/flexran_rtc/build/rt_controller', str(self.ssh.before)) + result = re.search('/opt/flexran_rtc/build/rt_controller', SSH.getBefore()) if result is not None: self.flexranCtrlInstalled = True logging.debug('Flexran Controller is installed') @@ -727,7 +726,7 @@ class OaiCiTest(): SSH.command('echo ' + self.EPCPassword + ' | sudo -S chmod 755 ./my-flexran-ctl.sh', '\$', 5) SSH.command('echo ' + self.EPCPassword + ' | sudo -S daemon --unsafe --name=flexran_rtc_daemon --chdir=/opt/flexran_rtc -o /opt/flexran_rtc/log/flexranctl_' + self.testCase_id + '.log ././my-flexran-ctl.sh', '\$', 5) SSH.command('ps -aux | grep --color=never rt_controller', '\$', 5) - result = re.search('rt_controller -c ', str(self.ssh.before)) + result = re.search('rt_controller -c ', SSH.getBefore()) if result is not None: logging.debug('\u001B[1m Initialize FlexRan Controller Completed\u001B[0m') self.flexranCtrlStarted = True @@ -765,7 +764,7 @@ class OaiCiTest(): if result is not None: SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) SSH.command('ip addr show | awk -f /tmp/active_net_interfaces.awk | egrep -v "lo|tun"', '\$', 5) - result = re.search('interfaceToUse=(?P[a-zA-Z0-9\-\_]+)done', str(self.ssh.before)) + result = re.search('interfaceToUse=(?P[a-zA-Z0-9\-\_]+)done', SSH.getBefore()) if result is not None: eth_interface = result.group('eth_interface') logging.debug('\u001B[1m Launching tshark on interface ' + eth_interface + '\u001B[0m') @@ -802,7 +801,7 @@ class OaiCiTest(): result = re.search('^rru|^enb|^du.band', str(config_file)) if result is not None: SSH.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 10) - result = re.search('type: b200', str(self.ssh.before)) + result = re.search('type: b200', SSH.getBefore()) if result is not None: logging.debug('Found a B2xx device --> resetting it') SSH.command('echo ' + lPassWord + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10) @@ -864,9 +863,9 @@ class OaiCiTest(): else: SSH.command('stdbuf -o0 cat enb_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync|Starting"', '\$', 4) if rruCheck: - result = re.search('wait RUs', str(self.ssh.before)) + result = re.search('wait RUs', SSH.getBefore()) else: - result = re.search('got sync|Starting F1AP at CU', str(self.ssh.before)) + result = re.search('got sync|Starting F1AP at CU', SSH.getBefore()) if result is None: time.sleep(6) else: @@ -956,7 +955,7 @@ class OaiCiTest(): SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) # b2xx_fx3_utils reset procedure SSH.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 10) - result = re.search('type: b200', str(self.ssh.before)) + result = re.search('type: b200', SSH.getBefore()) if result is not None: logging.debug('Found a B2xx device --> resetting it') SSH.command('echo ' + self.UEPassword + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10) @@ -971,7 +970,7 @@ class OaiCiTest(): # We may have to regenerate the .u* files if result is None: SSH.command('ls /tmp/*.sed', '\$', 5) - result = re.search('adapt_usim_parameters', str(self.ssh.before)) + result = re.search('adapt_usim_parameters', SSH.getBefore()) if result is not None: SSH.command('sed -f /tmp/adapt_usim_parameters.sed ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5) else: @@ -1007,7 +1006,7 @@ class OaiCiTest(): doLoop = False continue SSH.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4) - result = re.search('got sync', str(self.ssh.before)) + result = re.search('got sync', SSH.getBefore()) if result is None: time.sleep(6) else: @@ -1016,7 +1015,7 @@ class OaiCiTest(): if gotSyncStatus == False: # we certainly need to stop the lte-uesoftmodem process if it is still running! SSH.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4) - result = re.search('lte-uesoftmodem', str(self.ssh.before)) + result = re.search('lte-uesoftmodem', SSH.getBefore()) if result is not None: SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT lte-uesoftmodem', '\$', 4) time.sleep(3) @@ -1033,7 +1032,7 @@ class OaiCiTest(): fullSyncStatus = True continue SSH.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4) - result = re.search('No cell synchronization found', str(self.ssh.before)) + result = re.search('No cell synchronization found', SSH.getBefore()) if result is None: time.sleep(6) else: @@ -1042,7 +1041,7 @@ class OaiCiTest(): logging.debug('Found: "No cell synchronization" message! --> try again') time.sleep(6) SSH.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4) - result = re.search('lte-uesoftmodem', str(self.ssh.before)) + result = re.search('lte-uesoftmodem', SSH.getBefore()) if result is not None: SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT lte-uesoftmodem', '\$', 4) outterLoopCounter = outterLoopCounter - 1 @@ -1054,12 +1053,12 @@ class OaiCiTest(): if result is None: SSH.command('ifconfig oaitun_ue1', '\$', 4) # ifconfig output is different between ubuntu 16 and ubuntu 18 - result = re.search('inet addr:1|inet 1', str(self.ssh.before)) + result = re.search('inet addr:1|inet 1', SSH.getBefore()) if result is not None: logging.debug('\u001B[1m oaitun_ue1 interface is mounted and configured\u001B[0m') tunnelInterfaceStatus = True else: - logging.debug(str(self.ssh.before)) + logging.debug(SSH.getBefore()) logging.error('\u001B[1m oaitun_ue1 interface is either NOT mounted or NOT configured\u001B[0m') tunnelInterfaceStatus = False else: @@ -1085,7 +1084,7 @@ class OaiCiTest(): count = 0 while count < 5: SSH.command('echo ' + self.ADBPassword + ' | sudo -S lsof | grep ttyUSB0', '\$', 10) - result = re.search('picocom', str(self.ssh.before)) + result = re.search('picocom', SSH.getBefore()) if result is None: count = 10 else: @@ -1111,7 +1110,7 @@ class OaiCiTest(): logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') # Checking if auto-attach is enabled SSH.command('AT^AUTOATT?', 'OK', 5) - result = re.search('AUTOATT: (?P[0-9\-]+)', str(self.ssh.before)) + result = re.search('AUTOATT: (?P[0-9\-]+)', SSH.getBefore()) if result is not None: if result.group('state') is not None: autoAttachState = int(result.group('state')) @@ -1171,14 +1170,14 @@ class OaiCiTest(): attach_status = False while count < 5: SSH.command('AT+CEREG?', 'OK', 5) - result = re.search('CEREG: 2,(?P[0-9\-]+),', str(self.ssh.before)) + result = re.search('CEREG: 2,(?P[0-9\-]+),', SSH.getBefore()) if result is not None: mDataConnectionState = int(result.group('state')) if mDataConnectionState is not None: if mDataConnectionState == 1: count = 10 attach_status = True - result = re.search('CEREG: 2,1,"(?P[0-9A-Z]+)","(?P[0-9A-Z]+)"', str(self.ssh.before)) + result = re.search('CEREG: 2,1,"(?P[0-9A-Z]+)","(?P[0-9A-Z]+)"', SSH.getBefore()) if result is not None: networky = result.group('networky') networkz = result.group('networkz') @@ -1189,13 +1188,13 @@ class OaiCiTest(): logging.debug('+CEREG: 2,' + str(mDataConnectionState)) attach_cnt = attach_cnt + 1 else: - logging.debug(str(self.ssh.before)) + logging.debug(SSH.getBefore()) attach_cnt = attach_cnt + 1 count = count + 1 time.sleep(1) if attach_status: SSH.command('AT+CESQ', 'OK', 5) - result = re.search('CESQ: 99,99,255,255,(?P[0-9]+),(?P[0-9]+)', str(self.ssh.before)) + result = re.search('CESQ: 99,99,255,255,(?P[0-9]+),(?P[0-9]+)', SSH.getBefore()) if result is not None: nRSRQ = int(result.group('rsrq')) nRSRP = int(result.group('rsrp')) @@ -1246,7 +1245,7 @@ class OaiCiTest(): sys.exit(1) else: SSH.command('egrep --color=never "Allocated ipv4 addr" /opt/ltebox/var/log/xGwLog.0', '\$', 5) - result = re.search('Allocated ipv4 addr: (?P[0-9\.]+) from Pool', str(self.ssh.before)) + result = re.search('Allocated ipv4 addr: (?P[0-9\.]+) from Pool', SSH.getBefore()) if result is not None: moduleIPAddr = result.group('ipaddr') else: @@ -1263,7 +1262,7 @@ class OaiCiTest(): SSH.close() self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) return - result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', str(self.ssh.before)) + result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', SSH.getBefore()) if result is None: message = 'Packet Loss Not Found!' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') @@ -1277,7 +1276,7 @@ class OaiCiTest(): SSH.close() self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) return - result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', str(self.ssh.before)) + result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', SSH.getBefore()) if result is None: message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') @@ -1338,7 +1337,7 @@ class OaiCiTest(): SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry" | grep -m 1 mDataConnectionState', '\$', 15) else: SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\' | grep -m 1 mDataConnectionState', '\$', 60) - result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', str(self.ssh.before)) + result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', SSH.getBefore()) if result is None: logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m') lock.acquire() @@ -1501,7 +1500,7 @@ class OaiCiTest(): # Save mDataConnectionState SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) - result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', str(self.ssh.before)) + result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', SSH.getBefore()) if result is None: logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m') sys.exit(1) @@ -1514,7 +1513,7 @@ class OaiCiTest(): while count > 0: count = count - 1 SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) - result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', str(self.ssh.before)) + result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', SSH.getBefore()) if result is None: mDataConnectionState = None else: @@ -1619,13 +1618,14 @@ class OaiCiTest(): SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) if self.ADBCentralized: SSH.command('adb devices', '\$', 15) - self.UEDevices = re.findall("\\\\r\\\\n([A-Za-z0-9]+)\\\\tdevice",str(self.ssh.before)) + #self.UEDevices = re.findall("\\\\r\\\\n([A-Za-z0-9]+)\\\\tdevice",SSH.getBefore()) + self.UEDevices = re.findall("\\\\r\\\\n([A-Za-z0-9]+)\\\\tdevice",SSH.getBefore()) SSH.close() else: if (os.path.isfile('./phones_list.txt')): os.remove('./phones_list.txt') SSH.command('ls /etc/*/phones*.txt', '\$', 5) - result = re.search('/etc/ci/phones_list.txt', str(self.ssh.before)) + result = re.search('/etc/ci/phones_list.txt', SSH.getBefore()) SSH.close() if (result is not None) and (len(self.UEDevices) == 0): SSH.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, '/etc/ci/phones_list.txt', '.') @@ -1662,12 +1662,13 @@ class OaiCiTest(): SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) if self.ADBCentralized: SSH.command('lsusb | egrep "Future Technology Devices International, Ltd FT2232C" | sed -e "s#:.*##" -e "s# #_#g"', '\$', 15) - self.CatMDevices = re.findall("\\\\r\\\\n([A-Za-z0-9_]+)",str(self.ssh.before)) + #self.CatMDevices = re.findall("\\\\r\\\\n([A-Za-z0-9_]+)",SSH.getBefore()) + self.CatMDevices = re.findall("\\\\r\\\\n([A-Za-z0-9_]+)",SSH.getBefore()) else: if (os.path.isfile('./modules_list.txt')): os.remove('./modules_list.txt') SSH.command('ls /etc/*/modules*.txt', '\$', 5) - result = re.search('/etc/ci/modules_list.txt', str(self.ssh.before)) + result = re.search('/etc/ci/modules_list.txt', SSH.getBefore()) SSH.close() if result is not None: logging.debug('Found a module list file on ADB server') @@ -1684,7 +1685,7 @@ class OaiCiTest(): SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry"', '\$', 15) else: SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\'', '\$', 60) - result = re.search('mServiceState=(?P[0-9]+)', str(self.ssh.before)) + result = re.search('mServiceState=(?P[0-9]+)', SSH.getBefore()) serviceState = 'Service State: UNKNOWN' if result is not None: lServiceState = int(result.group('serviceState')) @@ -1696,7 +1697,7 @@ class OaiCiTest(): serviceState = 'Service State: IN_SERVICE' if lServiceState == 2: serviceState = 'Service State: EMERGENCY_ONLY' - result = re.search('mDataConnectionState=(?P[0-9]+)', str(self.ssh.before)) + result = re.search('mDataConnectionState=(?P[0-9]+)', SSH.getBefore()) dataConnectionState = 'Data State: UNKNOWN' if result is not None: lDataConnectionState = int(result.group('dataConnectionState')) @@ -1708,7 +1709,7 @@ class OaiCiTest(): dataConnectionState = 'Data State: CONNECTED' if lDataConnectionState == 3: dataConnectionState = 'Data State: SUSPENDED' - result = re.search('mDataConnectionReason=(?P[0-9a-zA-Z_]+)', str(self.ssh.before)) + result = re.search('mDataConnectionReason=(?P[0-9a-zA-Z_]+)', SSH.getBefore()) dataConnectionReason = 'Data Reason: UNKNOWN' if result is not None: dataConnectionReason = 'Data Reason: ' + result.group('dataConnectionReason') @@ -1754,7 +1755,7 @@ class OaiCiTest(): SSH.command('cd /opt/flexran_rtc', '\$', 5) SSH.command('curl http://localhost:9999/stats | jq \'.\' > log/check_status_' + self.testCase_id + '.log 2>&1', '\$', 5) SSH.command('cat log/check_status_' + self.testCase_id + '.log | jq \'.eNB_config[0].UE\' | grep -c rnti | sed -e "s#^#Nb Connected UE = #"', '\$', 5) - result = re.search('Nb Connected UE = (?P[0-9]+)', str(self.ssh.before)) + result = re.search('Nb Connected UE = (?P[0-9]+)', SSH.getBefore()) passStatus = True if result is not None: nb_ues = int(result.group('nb_ues')) @@ -1802,7 +1803,7 @@ class OaiCiTest(): sys.exit('Insufficient Parameter') SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) SSH.command('ifconfig oaitun_ue1', '\$', 4) - result = re.search('inet addr:(?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)|inet (?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)', str(self.ssh.before)) + result = re.search('inet addr:(?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)|inet (?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)', SSH.getBefore()) if result is not None: if result.group('ueipaddress') is not None: UE_IPAddress = result.group('ueipaddress') @@ -1827,7 +1828,7 @@ class OaiCiTest(): SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "ip addr show | grep rmnet"', '\$', 15) else: SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ip addr show | grep rmnet"\'', '\$', 60) - result = re.search('inet (?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\/[0-9]+[0-9a-zA-Z\.\s]+', str(self.ssh.before)) + result = re.search('inet (?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\/[0-9]+[0-9a-zA-Z\.\s]+', SSH.getBefore()) if result is None: logging.debug('\u001B[1;37;41m UE IP Address Not Found! \u001B[0m') time.sleep(1) @@ -1887,7 +1888,7 @@ class OaiCiTest(): SSH.close() self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) return - result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', str(self.ssh.before)) + result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', SSH.getBefore()) if result is None: message = 'Packet Loss Not Found!' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') @@ -1901,7 +1902,7 @@ class OaiCiTest(): SSH.close() self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) return - result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', str(self.ssh.before)) + result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', SSH.getBefore()) if result is None: message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') @@ -1982,7 +1983,7 @@ class OaiCiTest(): logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') self.PingNoS1_wrong_exit(message) return - result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', str(self.ssh.before)) + result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', SSH.getBefore()) if result is None: message = 'Packet Loss Not Found!' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') @@ -1994,7 +1995,7 @@ class OaiCiTest(): logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') self.PingNoS1_wrong_exit(message) return - result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', str(self.ssh.before)) + result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', SSH.getBefore()) if result is None: message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') @@ -2134,7 +2135,7 @@ class OaiCiTest(): def Iperf_analyzeV2TCPOutput(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): SSH.command('awk -f /tmp/tcp_iperf_stats.awk /tmp/CI-eNB/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - result = re.search('Avg Bitrate : (?P[0-9\.]+ Mbits\/sec) Max Bitrate : (?P[0-9\.]+ Mbits\/sec) Min Bitrate : (?P[0-9\.]+ Mbits\/sec)', str(self.ssh.before)) + result = re.search('Avg Bitrate : (?P[0-9\.]+ Mbits\/sec) Max Bitrate : (?P[0-9\.]+ Mbits\/sec) Min Bitrate : (?P[0-9\.]+ Mbits\/sec)', SSH.getBefore()) if result is not None: avgbitrate = result.group('average') maxbitrate = result.group('maximum') @@ -2163,9 +2164,9 @@ class OaiCiTest(): if result is None: return self.Iperf_analyzeV2TCPOutput(lock, UE_IPAddress, device_id, statusQueue, iperf_real_options) - result = re.search('Server Report:', str(self.ssh.before)) + result = re.search('Server Report:', SSH.getBefore()) if result is None: - result = re.search('read failed: Connection refused', str(self.ssh.before)) + result = re.search('read failed: Connection refused', SSH.getBefore()) if result is not None: logging.debug('\u001B[1;37;41m Could not connect to iperf server! \u001B[0m') else: @@ -2189,7 +2190,7 @@ class OaiCiTest(): req_bandwidth = '%.1f Gbits/sec' % req_bw req_bw = req_bw * 1000000000 - result = re.search('Server Report:\\\\r\\\\n(?:|\[ *\d+\].*) (?P[0-9\.]+ [KMG]bits\/sec) +(?P[0-9\.]+ ms) +(\d+\/..\d+) +(\((?P[0-9\.]+)%\))', str(self.ssh.before)) + result = re.search('Server Report:\\\\r\\\\n(?:|\[ *\d+\].*) (?P[0-9\.]+ [KMG]bits\/sec) +(?P[0-9\.]+ ms) +(\d+\/..\d+) +(\((?P[0-9\.]+)%\))', SSH.getBefore()) if result is not None: bitrate = result.group('bitrate') packetloss = result.group('packetloss') @@ -2340,9 +2341,9 @@ class OaiCiTest(): def Iperf_analyzeV3Output(self, lock, UE_IPAddress, device_id, statusQueue): - result = re.search('(?P[0-9\.]+ [KMG]bits\/sec) +(?:|[0-9\.]+ ms +\d+\/\d+ \((?P[0-9\.]+)%\)) +(?:|receiver)\\\\r\\\\n(?:|\[ *\d+\] Sent \d+ datagrams)\\\\r\\\\niperf Done\.', str(self.ssh.before)) + result = re.search('(?P[0-9\.]+ [KMG]bits\/sec) +(?:|[0-9\.]+ ms +\d+\/\d+ \((?P[0-9\.]+)%\)) +(?:|receiver)\\\\r\\\\n(?:|\[ *\d+\] Sent \d+ datagrams)\\\\r\\\\niperf Done\.', SSH.getBefore()) if result is None: - result = re.search('(?Piperf: error - [a-zA-Z0-9 :]+)', str(self.ssh.before)) + result = re.search('(?Piperf: error - [a-zA-Z0-9 :]+)', SSH.getBefore()) lock.acquire() statusQueue.put(-1) statusQueue.put(device_id) @@ -2503,9 +2504,9 @@ class OaiCiTest(): SSH.command('adb -s ' + device_id + ' shell "ls /data/local/tmp"', '\$', 5) else: SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ls /data/local/tmp"\'', '\$', 60) - result = re.search('iperf3', str(self.ssh.before)) + result = re.search('iperf3', SSH.getBefore()) if result is None: - result = re.search('iperf', str(self.ssh.before)) + result = re.search('iperf', SSH.getBefore()) if result is None: message = 'Neither iperf nor iperf3 installed on UE!' logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') @@ -2517,10 +2518,10 @@ class OaiCiTest(): SSH.command('adb -s ' + device_id + ' shell "/data/local/tmp/iperf --version"', '\$', 5) else: SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf --version"\'', '\$', 60) - result = re.search('iperf version 2.0.5', str(self.ssh.before)) + result = re.search('iperf version 2.0.5', SSH.getBefore()) if result is not None: self.ueIperfVersion = '2.0.5' - result = re.search('iperf version 2.0.10', str(self.ssh.before)) + result = re.search('iperf version 2.0.10', SSH.getBefore()) if result is not None: self.ueIperfVersion = '2.0.10' else: @@ -2529,10 +2530,10 @@ class OaiCiTest(): else: SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) SSH.command('iperf --version', '\$', 5) - result = re.search('iperf version 2.0.5', str(self.ssh.before)) + result = re.search('iperf version 2.0.5', SSH.getBefore()) if result is not None: self.ueIperfVersion = '2.0.5' - result = re.search('iperf version 2.0.10', str(self.ssh.before)) + result = re.search('iperf version 2.0.10', SSH.getBefore()) if result is not None: self.ueIperfVersion = '2.0.10' SSH.close() @@ -2640,7 +2641,7 @@ class OaiCiTest(): SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell ps | grep --color=never iperf | grep -v grep', '\$', 5) else: SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ps" | grep --color=never iperf | grep -v grep\'', '\$', 60) - result = re.search('shell +(?P\d+)', str(self.ssh.before)) + result = re.search('shell +(?P\d+)', SSH.getBefore()) if result is not None: pid_iperf = result.group('pid') if self.ADBCentralized: @@ -2931,7 +2932,7 @@ class OaiCiTest(): try: SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) SSH.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('lte-uesoftmodem', str(self.ssh.before)) + result = re.search('lte-uesoftmodem', SSH.getBefore()) if result is None: logging.debug('\u001B[1;37;41m OAI UE Process Not Found! \u001B[0m') status_queue.put(OAI_UE_PROCESS_FAILED) @@ -2945,7 +2946,7 @@ class OaiCiTest(): try: SSH.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) SSH.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('lte-softmodem', str(self.ssh.before)) + result = re.search('lte-softmodem', SSH.getBefore()) if result is None: logging.debug('\u001B[1;37;41m eNB Process Not Found! \u001B[0m') status_queue.put(ENB_PROCESS_FAILED) @@ -2960,11 +2961,11 @@ class OaiCiTest(): SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) SSH.command('stdbuf -o0 ps -aux | grep --color=never hss | grep -v grep', '\$', 5) if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - result = re.search('oai_hss -j', str(self.ssh.before)) + result = re.search('oai_hss -j', SSH.getBefore()) elif re.match('OAI', self.EPCType, re.IGNORECASE): - result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) + result = re.search('\/bin\/bash .\/run_', SSH.getBefore()) elif re.match('ltebox', self.EPCType, re.IGNORECASE): - result = re.search('hss_sim s6as diam_hss', str(self.ssh.before)) + result = re.search('hss_sim s6as diam_hss', SSH.getBefore()) else: logging.error('This should not happen!') if result is None: @@ -2981,11 +2982,11 @@ class OaiCiTest(): SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) SSH.command('stdbuf -o0 ps -aux | grep --color=never mme | grep -v grep', '\$', 5) if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - result = re.search('mme -c', str(self.ssh.before)) + result = re.search('mme -c', SSH.getBefore()) elif re.match('OAI', self.EPCType, re.IGNORECASE): - result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) + result = re.search('\/bin\/bash .\/run_', SSH.getBefore()) elif re.match('ltebox', self.EPCType, re.IGNORECASE): - result = re.search('mme', str(self.ssh.before)) + result = re.search('mme', SSH.getBefore()) else: logging.error('This should not happen!') if result is None: @@ -3002,13 +3003,13 @@ class OaiCiTest(): SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): SSH.command('stdbuf -o0 ps -aux | grep --color=never spgw | grep -v grep', '\$', 5) - result = re.search('spgwu -c ', str(self.ssh.before)) + result = re.search('spgwu -c ', SSH.getBefore()) elif re.match('OAI', self.EPCType, re.IGNORECASE): SSH.command('stdbuf -o0 ps -aux | grep --color=never spgw | grep -v grep', '\$', 5) - result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) + result = re.search('\/bin\/bash .\/run_', SSH.getBefore()) elif re.match('ltebox', self.EPCType, re.IGNORECASE): SSH.command('stdbuf -o0 ps -aux | grep --color=never xGw | grep -v grep', '\$', 5) - result = re.search('xGw', str(self.ssh.before)) + result = re.search('xGw', SSH.getBefore()) else: logging.error('This should not happen!') if result is None: @@ -3448,13 +3449,13 @@ class OaiCiTest(): SSH.open(lIpAddr, lUserName, lPassWord) SSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) SSH.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('lte-softmodem', str(self.ssh.before)) + result = re.search('lte-softmodem', SSH.getBefore()) if result is not None: SSH.command('echo ' + lPassWord + ' | sudo -S daemon --name=enb' + str(self.eNB_instance) + '_daemon --stop', '\$', 5) SSH.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGINT lte-softmodem || true', '\$', 5) time.sleep(10) SSH.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('lte-softmodem', str(self.ssh.before)) + result = re.search('lte-softmodem', SSH.getBefore()) if result is not None: SSH.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGKILL lte-softmodem || true', '\$', 5) time.sleep(5) @@ -3521,7 +3522,7 @@ class OaiCiTest(): SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT oai_hss || true', '\$', 5) time.sleep(2) SSH.command('stdbuf -o0 ps -aux | grep hss | grep -v grep', '\$', 5) - result = re.search('oai_hss -j', str(self.ssh.before)) + result = re.search('oai_hss -j', SSH.getBefore()) if result is not None: SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL oai_hss || true', '\$', 5) SSH.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-hss.sh', '\$', 5) @@ -3529,7 +3530,7 @@ class OaiCiTest(): SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_hss oai_hss || true', '\$', 5) time.sleep(2) SSH.command('stdbuf -o0 ps -aux | grep hss | grep -v grep', '\$', 5) - result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) + result = re.search('\/bin\/bash .\/run_', SSH.getBefore()) if result is not None: SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_hss oai_hss || true', '\$', 5) elif re.match('ltebox', self.EPCType, re.IGNORECASE): @@ -3549,7 +3550,7 @@ class OaiCiTest(): SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_mme mme || true', '\$', 5) time.sleep(2) SSH.command('stdbuf -o0 ps -aux | grep mme | grep -v grep', '\$', 5) - result = re.search('mme -c', str(self.ssh.before)) + result = re.search('mme -c', SSH.getBefore()) if result is not None: SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_mme mme || true', '\$', 5) SSH.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-mme.sh', '\$', 5) @@ -3567,12 +3568,12 @@ class OaiCiTest(): SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT spgwc spgwu || true', '\$', 5) time.sleep(2) SSH.command('stdbuf -o0 ps -aux | grep spgw | grep -v grep', '\$', 5) - result = re.search('spgwc -c |spgwu -c ', str(self.ssh.before)) + result = re.search('spgwc -c |spgwu -c ', SSH.getBefore()) if result is not None: SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL spgwc spgwu || true', '\$', 5) SSH.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-spgw*.sh', '\$', 5) SSH.command('stdbuf -o0 ps -aux | grep tshark | grep -v grep', '\$', 5) - result = re.search('-w ', str(self.ssh.before)) + result = re.search('-w ', SSH.getBefore()) if result is not None: SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT tshark || true', '\$', 5) SSH.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 ' + self.EPCSourceCodePath + '/scripts/*.pcap', '\$', 5) @@ -3580,7 +3581,7 @@ class OaiCiTest(): SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_spgw spgw || true', '\$', 5) time.sleep(2) SSH.command('stdbuf -o0 ps -aux | grep spgw | grep -v grep', '\$', 5) - result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) + result = re.search('\/bin\/bash .\/run_', SSH.getBefore()) if result is not None: SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_spgw spgw || true', '\$', 5) elif re.match('ltebox', self.EPCType, re.IGNORECASE): @@ -3623,7 +3624,7 @@ class OaiCiTest(): SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "ps | grep --color=never iperf | grep -v grep"', '\$', 5) else: SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ps | grep --color=never iperf | grep -v grep"\'', '\$', 60) - result = re.search('shell +(?P\d+)', str(self.ssh.before)) + result = re.search('shell +(?P\d+)', SSH.getBefore()) if result is not None: pid_iperf = result.group('pid') if self.ADBCentralized: @@ -3653,13 +3654,13 @@ class OaiCiTest(): SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) SSH.command('ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('lte-uesoftmodem', str(self.ssh.before)) + result = re.search('lte-uesoftmodem', SSH.getBefore()) if result is not None: SSH.command('echo ' + self.UEPassword + ' | sudo -S daemon --name=ue' + str(self.UE_instance) + '_daemon --stop', '\$', 5) SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGINT lte-uesoftmodem || true', '\$', 5) time.sleep(10) SSH.command('ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('lte-uesoftmodem', str(self.ssh.before)) + result = re.search('lte-uesoftmodem', SSH.getBefore()) if result is not None: SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGKILL lte-uesoftmodem || true', '\$', 5) time.sleep(5) @@ -3964,27 +3965,27 @@ class OaiCiTest(): SSH.open(IPAddress, UserName, Password) SSH.command('lsb_release -a', '\$', 5) - result = re.search('Description:\\\\t(?P[a-zA-Z0-9\-\_\.\ ]+)', str(self.ssh.before)) + result = re.search('Description:\\\\t(?P[a-zA-Z0-9\-\_\.\ ]+)', SSH.getBefore()) if result is not None: self.OsVersion = result.group('os_type') logging.debug('OS is: ' + self.OsVersion) SSH.command('uname -r', '\$', 5) - result = re.search('uname -r\\\\r\\\\n(?P[a-zA-Z0-9\-\_\.]+)', str(self.ssh.before)) + result = re.search('uname -r\\\\r\\\\n(?P[a-zA-Z0-9\-\_\.]+)', SSH.getBefore()) if result is not None: self.KernelVersion = result.group('kernel_version') logging.debug('Kernel Version is: ' + self.KernelVersion) SSH.command('dpkg --list | egrep --color=never libuhd003', '\$', 5) - result = re.search('libuhd003:amd64 *(?P[0-9\.]+)', str(self.ssh.before)) + result = re.search('libuhd003:amd64 *(?P[0-9\.]+)', SSH.getBefore()) if result is not None: self.UhdVersion = result.group('uhd_version') logging.debug('UHD Version is: ' + self.UhdVersion) SSH.command('echo ' + Password + ' | sudo -S uhd_find_devices', '\$', 15) - result = re.search('product: (?P[0-9A-Za-z]+)\\\\r\\\\n', str(self.ssh.before)) + result = re.search('product: (?P[0-9A-Za-z]+)\\\\r\\\\n', SSH.getBefore()) if result is not None: self.UsrpBoard = result.group('usrp_board') logging.debug('USRP Board is: ' + self.UsrpBoard) SSH.command('lscpu', '\$', 5) - result = re.search('CPU\(s\): *(?P[0-9]+).*Model name: *(?P[a-zA-Z0-9\-\_\.\ \(\)]+).*CPU MHz: *(?P[0-9\.]+)', str(self.ssh.before)) + result = re.search('CPU\(s\): *(?P[0-9]+).*Model name: *(?P[a-zA-Z0-9\-\_\.\ \(\)]+).*CPU MHz: *(?P[0-9\.]+)', SSH.getBefore()) if result is not None: self.CpuNb = result.group('nb_cpus') logging.debug('nb_cpus: ' + self.CpuNb) @@ -4504,6 +4505,7 @@ def receive_signal(signum, frame): #----------------------------------------------------------- mode = '' CiTestObj = OaiCiTest() +from sshconnection import * SSH = SSHConnection() argvs = sys.argv diff --git a/ci-scripts/pMain.sh b/ci-scripts/pMain.sh new file mode 100755 index 0000000000..7708e349b4 --- /dev/null +++ b/ci-scripts/pMain.sh @@ -0,0 +1,9 @@ +python3 main.py --mode=InitiateHtml --ranRepository=https://gitlab.eurecom.fr/oai/openairinterface5g --ranBranch=develop --ranCommitID=424bf5c53e879af7d66aaa50e0cd969eeb570dbd --ranAllowMerge=false --ranTargetBranch=develop --ADBIPAddress=192.168.12.240 --ADBUserName=bourdon --ADBPassword=linux --XMLTestFile=xml_files/dummy_build.xml --XMLTestFile=xml_files/dummy_ltebox_start.xml --XMLTestFile=xml_files/dummy_enb_test.xml --XMLTestFile=xml_files/dummy_ltebox_stop.xml +python3 main.py --mode=TesteNB --ranRepository=https://gitlab.eurecom.fr/oai/openairinterface5g --ranBranch=develop --ranCommitID=424bf5c53e879af7d66aaa50e0cd969eeb570dbd --ranAllowMerge=false --ranTargetBranch=develop --eNBIPAddress=192.168.12.161 --eNBUserName=acilius --eNBPassword=linux --eNBSourceCodePath=/tmp/CI-gabriele --EPCIPAddress=192.168.12.240 --EPCType=ltebox --EPCUserName=bourdon --EPCPassword=linux --EPCSourceCodePath=/tmp/CI-eNB --ADBIPAddress=192.168.12.240 --ADBUserName=bourdon --ADBPassword=linux --XMLTestFile=xml_files/dummy_build.xml + +python3 main.py --mode=TesteNB --ranRepository=https://gitlab.eurecom.fr/oai/openairinterface5g --ranBranch=develop --ranCommitID=424bf5c53e879af7d66aaa50e0cd969eeb570dbd --ranAllowMerge=false --ranTargetBranch=develop --eNBIPAddress=192.168.12.161 --eNBUserName=acilius --eNBPassword=linux --eNBSourceCodePath=/tmp/CI-gabriele --EPCIPAddress=192.168.12.240 --EPCType=ltebox --EPCUserName=bourdon --EPCPassword=linux --EPCSourceCodePath=/tmp/CI-eNB --ADBIPAddress=192.168.12.240 --ADBUserName=bourdon --ADBPassword=linux --XMLTestFile=xml_files/dummy_ltebox_start.xml + +python3 main.py --mode=TesteNB --ranRepository=https://gitlab.eurecom.fr/oai/openairinterface5g --ranBranch=develop --ranCommitID=424bf5c53e879af7d66aaa50e0cd969eeb570dbd --ranAllowMerge=false --ranTargetBranch=develop --eNBIPAddress=192.168.12.161 --eNBUserName=acilius --eNBPassword=linux --eNBSourceCodePath=/tmp/CI-gabriele --EPCIPAddress=192.168.12.240 --EPCType=ltebox --EPCUserName=bourdon --EPCPassword=linux --EPCSourceCodePath=/tmp/CI-eNB --ADBIPAddress=192.168.12.240 --ADBUserName=bourdon --ADBPassword=linux --XMLTestFile=xml_files/dummy_enb_test.xml +python3 main.py --mode=TesteNB --ranRepository=https://gitlab.eurecom.fr/oai/openairinterface5g --ranBranch=develop --ranCommitID=424bf5c53e879af7d66aaa50e0cd969eeb570dbd --ranAllowMerge=false --ranTargetBranch=develop --eNBIPAddress=192.168.12.161 --eNBUserName=acilius --eNBPassword=linux --eNBSourceCodePath=/tmp/CI-gabriele --EPCIPAddress=192.168.12.240 --EPCType=ltebox --EPCUserName=bourdon --EPCPassword=linux --EPCSourceCodePath=/tmp/CI-eNB --ADBIPAddress=192.168.12.240 --ADBUserName=bourdon --ADBPassword=linux --XMLTestFile=xml_files/dummy_ltebox_stop.xml +python3 main.py --mode=FinalizeHtml --finalStatus=true --eNBIPAddress=192.168.12.161 --eNBUserName=acilius --eNBPassword=linux + diff --git a/ci-scripts/sshconnection.py b/ci-scripts/sshconnection.py index b74fa14f58..d10edf360b 100644 --- a/ci-scripts/sshconnection.py +++ b/ci-scripts/sshconnection.py @@ -1,8 +1,16 @@ +#----------------------------------------------------------- +# Import +#----------------------------------------------------------- +import pexpect # pexpect +import logging + #----------------------------------------------------------- # Class Declaration #----------------------------------------------------------- class SSHConnection(): def __init__(self): + self.ssh = '' + def open(self, ipaddress, username, password): count = 0 connect_status = False @@ -165,3 +173,5 @@ class SSHConnection(): else: sys.exit('SCP failed') + def getBefore(self): + return str(self.ssh.before) diff --git a/ci-scripts/xml_files/enb_usrp210_band7_epc_start.xml b/ci-scripts/xml_files/enb_usrp210_band7_epc_start.xml new file mode 100644 index 0000000000..3f982f0446 --- /dev/null +++ b/ci-scripts/xml_files/enb_usrp210_band7_epc_start.xml @@ -0,0 +1,54 @@ + + + epc-start + EPC-Start + log-in + + 010101 + 050101 060101 070101 + + + + + Build_eNB + Build eNB (USRP) + -w USRP -c --eNB + + + + Initialize_HSS + Initialize HSS + + + + Initialize_MME + Initialize MME + + + + Initialize_SPGW + Initialize SPGW + + + From ec258105f63fcb6ee2f7dc7ae9bb228e64ab26f1 Mon Sep 17 00:00:00 2001 From: Gabriele Perrone Date: Tue, 14 Jan 2020 14:52:57 +0100 Subject: [PATCH 078/240] Removed the old ssh commands from orignal implementaion location FIx missing replacement --- ci-scripts/main.py | 165 +----------------- ci-scripts/pMain.sh | 9 - .../xml_files/enb_usrp210_band7_epc_start.xml | 54 ------ 3 files changed, 2 insertions(+), 226 deletions(-) delete mode 100755 ci-scripts/pMain.sh delete mode 100644 ci-scripts/xml_files/enb_usrp210_band7_epc_start.xml diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 9b332313bb..5d66ab9ee8 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -186,167 +186,6 @@ class OaiCiTest(): self.expectedNbOfConnectedUEs = 0 self.startTime = 0 - def open(self, ipaddress, username, password): - count = 0 - connect_status = False - while count < 4: - self.ssh = pexpect.spawn('ssh', [username + '@' + ipaddress], timeout = 5) - self.sshresponse = self.ssh.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', 'Last login', pexpect.EOF, pexpect.TIMEOUT]) - if self.sshresponse == 0: - self.ssh.sendline('yes') - self.ssh.expect('password:') - self.ssh.sendline(password) - self.sshresponse = self.ssh.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if self.sshresponse == 0: - count = 10 - connect_status = True - else: - logging.debug('self.sshresponse = ' + str(self.sshresponse)) - elif self.sshresponse == 1: - self.ssh.sendline(password) - self.sshresponse = self.ssh.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if self.sshresponse == 0: - count = 10 - connect_status = True - else: - logging.debug('self.sshresponse = ' + str(self.sshresponse)) - elif self.sshresponse == 2: - # Checking if we are really on the remote client defined by its IP address - SSH.command('stdbuf -o0 ifconfig | egrep --color=never "inet addr:|inet "', '\$', 5) - result = re.search(str(ipaddress), SSH.getBefore()) - if result is None: - SSH.close() - else: - count = 10 - connect_status = True - else: - # debug output - logging.debug(SSH.getBefore()) - logging.debug('self.sshresponse = ' + str(self.sshresponse)) - # adding a tempo when failure - if not connect_status: - time.sleep(1) - count += 1 - if connect_status: - pass - else: - sys.exit('CiTestObj.Connection Failed') - - def command(self, commandline, expectedline, timeout): - logging.debug(commandline) - self.ssh.timeout = timeout - self.ssh.sendline(commandline) - self.sshresponse = self.ssh.expect([expectedline, pexpect.EOF, pexpect.TIMEOUT]) - if self.sshresponse == 0: - return 0 - elif self.sshresponse == 1: - logging.debug('\u001B[1;37;41m Unexpected EOF \u001B[0m') - logging.debug('Expected Line : ' + expectedline) - sys.exit(self.sshresponse) - elif self.sshresponse == 2: - logging.debug('\u001B[1;37;41m Unexpected TIMEOUT \u001B[0m') - logging.debug('Expected Line : ' + expectedline) - result = re.search('ping |iperf |picocom', str(commandline)) - if result is None: - logging.debug(SSH.getBefore()) - sys.exit(self.sshresponse) - else: - return -1 - else: - logging.debug('\u001B[1;37;41m Unexpected Others \u001B[0m') - logging.debug('Expected Line : ' + expectedline) - sys.exit(self.sshresponse) - - def close(self): - self.ssh.timeout = 5 - self.ssh.sendline('exit') - self.sshresponse = self.ssh.expect([pexpect.EOF, pexpect.TIMEOUT]) - if self.sshresponse == 0: - pass - elif self.sshresponse == 1: - if not self.picocom_closure: - logging.debug('\u001B[1;37;41m Unexpected TIMEOUT during closing\u001B[0m') - else: - logging.debug('\u001B[1;37;41m Unexpected Others during closing\u001B[0m') - - def copyin(self, ipaddress, username, password, source, destination): - count = 0 - copy_status = False - logging.debug('scp '+ username + '@' + ipaddress + ':' + source + ' ' + destination) - while count < 10: - scp_spawn = pexpect.spawn('scp '+ username + '@' + ipaddress + ':' + source + ' ' + destination, timeout = 100) - scp_response = scp_spawn.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0: - scp_spawn.sendline('yes') - scp_spawn.expect('password:') - scp_spawn.sendline(password) - scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0: - count = 10 - copy_status = True - else: - logging.debug('1 - scp_response = ' + str(scp_response)) - elif scp_response == 1: - scp_spawn.sendline(password) - scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0 or scp_response == 3: - count = 10 - copy_status = True - else: - logging.debug('2 - scp_response = ' + str(scp_response)) - elif scp_response == 2: - count = 10 - copy_status = True - else: - logging.debug('3 - scp_response = ' + str(scp_response)) - # adding a tempo when failure - if not copy_status: - time.sleep(1) - count += 1 - if copy_status: - return 0 - else: - return -1 - - def copyout(self, ipaddress, username, password, source, destination): - count = 0 - copy_status = False - logging.debug('scp ' + source + ' ' + username + '@' + ipaddress + ':' + destination) - while count < 4: - scp_spawn = pexpect.spawn('scp ' + source + ' ' + username + '@' + ipaddress + ':' + destination, timeout = 100) - scp_response = scp_spawn.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0: - scp_spawn.sendline('yes') - scp_spawn.expect('password:') - scp_spawn.sendline(password) - scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0: - count = 10 - copy_status = True - else: - logging.debug('1 - scp_response = ' + str(scp_response)) - elif scp_response == 1: - scp_spawn.sendline(password) - scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0 or scp_response == 3: - count = 10 - copy_status = True - else: - logging.debug('2 - scp_response = ' + str(scp_response)) - elif scp_response == 2: - count = 10 - copy_status = True - else: - logging.debug('3 - scp_response = ' + str(scp_response)) - # adding a tempo when failure - if not copy_status: - time.sleep(1) - count += 1 - if copy_status: - pass - else: - sys.exit('SCP failed') - def BuildeNB(self): if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': Usage() @@ -4760,8 +4599,8 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re sys.exit('Insufficient Parameter') if (CiTestObj.EPCIPAddress != '') and (CiTestObj.EPCIPAddress != 'none'): - CiTestObj.copyout(CiTestObj.EPCIPAddress, CiTestObj.EPCUserName, CiTestObj.EPCPassword, cwd + "/tcp_iperf_stats.awk", "/tmp") - CiTestObj.copyout(CiTestObj.EPCIPAddress, CiTestObj.EPCUserName, CiTestObj.EPCPassword, cwd + "/active_net_interfaces.awk", "/tmp") + SSH.copyout(CiTestObj.EPCIPAddress, CiTestObj.EPCUserName, CiTestObj.EPCPassword, cwd + "/tcp_iperf_stats.awk", "/tmp") + SSH.copyout(CiTestObj.EPCIPAddress, CiTestObj.EPCUserName, CiTestObj.EPCPassword, cwd + "/active_net_interfaces.awk", "/tmp") else: if CiTestObj.UEIPAddress == '' or CiTestObj.ranRepository == '' or CiTestObj.ranBranch == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == '': Usage() diff --git a/ci-scripts/pMain.sh b/ci-scripts/pMain.sh deleted file mode 100755 index 7708e349b4..0000000000 --- a/ci-scripts/pMain.sh +++ /dev/null @@ -1,9 +0,0 @@ -python3 main.py --mode=InitiateHtml --ranRepository=https://gitlab.eurecom.fr/oai/openairinterface5g --ranBranch=develop --ranCommitID=424bf5c53e879af7d66aaa50e0cd969eeb570dbd --ranAllowMerge=false --ranTargetBranch=develop --ADBIPAddress=192.168.12.240 --ADBUserName=bourdon --ADBPassword=linux --XMLTestFile=xml_files/dummy_build.xml --XMLTestFile=xml_files/dummy_ltebox_start.xml --XMLTestFile=xml_files/dummy_enb_test.xml --XMLTestFile=xml_files/dummy_ltebox_stop.xml -python3 main.py --mode=TesteNB --ranRepository=https://gitlab.eurecom.fr/oai/openairinterface5g --ranBranch=develop --ranCommitID=424bf5c53e879af7d66aaa50e0cd969eeb570dbd --ranAllowMerge=false --ranTargetBranch=develop --eNBIPAddress=192.168.12.161 --eNBUserName=acilius --eNBPassword=linux --eNBSourceCodePath=/tmp/CI-gabriele --EPCIPAddress=192.168.12.240 --EPCType=ltebox --EPCUserName=bourdon --EPCPassword=linux --EPCSourceCodePath=/tmp/CI-eNB --ADBIPAddress=192.168.12.240 --ADBUserName=bourdon --ADBPassword=linux --XMLTestFile=xml_files/dummy_build.xml - -python3 main.py --mode=TesteNB --ranRepository=https://gitlab.eurecom.fr/oai/openairinterface5g --ranBranch=develop --ranCommitID=424bf5c53e879af7d66aaa50e0cd969eeb570dbd --ranAllowMerge=false --ranTargetBranch=develop --eNBIPAddress=192.168.12.161 --eNBUserName=acilius --eNBPassword=linux --eNBSourceCodePath=/tmp/CI-gabriele --EPCIPAddress=192.168.12.240 --EPCType=ltebox --EPCUserName=bourdon --EPCPassword=linux --EPCSourceCodePath=/tmp/CI-eNB --ADBIPAddress=192.168.12.240 --ADBUserName=bourdon --ADBPassword=linux --XMLTestFile=xml_files/dummy_ltebox_start.xml - -python3 main.py --mode=TesteNB --ranRepository=https://gitlab.eurecom.fr/oai/openairinterface5g --ranBranch=develop --ranCommitID=424bf5c53e879af7d66aaa50e0cd969eeb570dbd --ranAllowMerge=false --ranTargetBranch=develop --eNBIPAddress=192.168.12.161 --eNBUserName=acilius --eNBPassword=linux --eNBSourceCodePath=/tmp/CI-gabriele --EPCIPAddress=192.168.12.240 --EPCType=ltebox --EPCUserName=bourdon --EPCPassword=linux --EPCSourceCodePath=/tmp/CI-eNB --ADBIPAddress=192.168.12.240 --ADBUserName=bourdon --ADBPassword=linux --XMLTestFile=xml_files/dummy_enb_test.xml -python3 main.py --mode=TesteNB --ranRepository=https://gitlab.eurecom.fr/oai/openairinterface5g --ranBranch=develop --ranCommitID=424bf5c53e879af7d66aaa50e0cd969eeb570dbd --ranAllowMerge=false --ranTargetBranch=develop --eNBIPAddress=192.168.12.161 --eNBUserName=acilius --eNBPassword=linux --eNBSourceCodePath=/tmp/CI-gabriele --EPCIPAddress=192.168.12.240 --EPCType=ltebox --EPCUserName=bourdon --EPCPassword=linux --EPCSourceCodePath=/tmp/CI-eNB --ADBIPAddress=192.168.12.240 --ADBUserName=bourdon --ADBPassword=linux --XMLTestFile=xml_files/dummy_ltebox_stop.xml -python3 main.py --mode=FinalizeHtml --finalStatus=true --eNBIPAddress=192.168.12.161 --eNBUserName=acilius --eNBPassword=linux - diff --git a/ci-scripts/xml_files/enb_usrp210_band7_epc_start.xml b/ci-scripts/xml_files/enb_usrp210_band7_epc_start.xml deleted file mode 100644 index 3f982f0446..0000000000 --- a/ci-scripts/xml_files/enb_usrp210_band7_epc_start.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - epc-start - EPC-Start - log-in - - 010101 - 050101 060101 070101 - - - - - Build_eNB - Build eNB (USRP) - -w USRP -c --eNB - - - - Initialize_HSS - Initialize HSS - - - - Initialize_MME - Initialize MME - - - - Initialize_SPGW - Initialize SPGW - - - From 5d1f16c3e92908000249d89b084cc821084a8414 Mon Sep 17 00:00:00 2001 From: Gabriele Perrone Date: Tue, 14 Jan 2020 14:54:53 +0100 Subject: [PATCH 079/240] fix gitignore file --- ci-scripts/.gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ci-scripts/.gitignore b/ci-scripts/.gitignore index d77a672c0c..dc5e7c7476 100644 --- a/ci-scripts/.gitignore +++ b/ci-scripts/.gitignore @@ -5,3 +5,5 @@ iperf_*.* phones_list.txt modules_list.txt test_results*.html +pMain* +__pycache__ From b104c26212baa92c1e033011ded767cdd3784381 Mon Sep 17 00:00:00 2001 From: Gabriele Perrone Date: Tue, 14 Jan 2020 15:25:21 +0100 Subject: [PATCH 080/240] overwriting config file mnc with the proper mnc (93) --- ci-scripts/xml_files/enb_usrp210_band7_test_05mhz_tm1.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 3b07ed4950..6bc60b113a 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 @@ -108,7 +108,7 @@ Initialize_eNB Initialize eNB (FDD/Band7/5MHz) - -O ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf + -O ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf --eNBs.[0].plmn_list.[0].mnc 93 From 0235b8c0e7b359795ab38b32bdd83efbda01318b Mon Sep 17 00:00:00 2001 From: Gabriele Perrone Date: Tue, 21 Jan 2020 13:50:44 +0100 Subject: [PATCH 081/240] CI: first draft of separating EPC functions Signed-off-by: Gabriele Perrone --- ci-scripts/constants.py | 71 +++++++++ ci-scripts/epc.py | 330 +++++++++++++++++++++++++++++++++++++++ ci-scripts/helpreadme.py | 51 ++++++ ci-scripts/main.py | 296 ++++++++++++++++++----------------- 4 files changed, 603 insertions(+), 145 deletions(-) create mode 100644 ci-scripts/constants.py create mode 100644 ci-scripts/epc.py create mode 100644 ci-scripts/helpreadme.py diff --git a/ci-scripts/constants.py b/ci-scripts/constants.py new file mode 100644 index 0000000000..f07fd81b43 --- /dev/null +++ b/ci-scripts/constants.py @@ -0,0 +1,71 @@ + +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (the "License"); you may not use this file +# * except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.openairinterface.org/?page_id=698 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# Python for CI of OAI-eNB + COTS-UE +# +# Required Python Version +# Python 3.x +# +# Required Python Package +# pexpect +#--------------------------------------------------------------------- + +#----------------------------------------------------------- +# Version +#----------------------------------------------------------- +Version = '0.1' + +#----------------------------------------------------------- +# Constants +#----------------------------------------------------------- +ALL_PROCESSES_OK = 0 +ENB_PROCESS_FAILED = -1 +ENB_PROCESS_OK = +1 +ENB_PROCESS_SEG_FAULT = -11 +ENB_PROCESS_ASSERTION = -12 +ENB_PROCESS_REALTIME_ISSUE = -13 +ENB_PROCESS_NOLOGFILE_TO_ANALYZE = -14 +ENB_PROCESS_SLAVE_RRU_NOT_SYNCED = -15 +HSS_PROCESS_FAILED = -2 +HSS_PROCESS_OK = +2 +MME_PROCESS_FAILED = -3 +MME_PROCESS_OK = +3 +SPGW_PROCESS_FAILED = -4 +SPGW_PROCESS_OK = +4 +UE_IP_ADDRESS_ISSUE = -5 +OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE = -20 +OAI_UE_PROCESS_COULD_NOT_SYNC = -21 +OAI_UE_PROCESS_ASSERTION = -22 +OAI_UE_PROCESS_FAILED = -23 +OAI_UE_PROCESS_NO_TUNNEL_INTERFACE = -24 +OAI_UE_PROCESS_OK = +6 + +UE_STATUS_DETACHED = 0 +UE_STATUS_DETACHING = 1 +UE_STATUS_ATTACHING = 2 +UE_STATUS_ATTACHED = 3 + +X2_HO_REQ_STATE__IDLE = 0 +X2_HO_REQ_STATE__TARGET_RECEIVES_REQ = 1 +X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE = 2 +X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ = 3 +X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK = 10 + diff --git a/ci-scripts/epc.py b/ci-scripts/epc.py new file mode 100644 index 0000000000..3ebb3cfb04 --- /dev/null +++ b/ci-scripts/epc.py @@ -0,0 +1,330 @@ +#----------------------------------------------------------- +# Import +#----------------------------------------------------------- +import sys # arg +import re # reg +import logging +import os +import time +from multiprocessing import Process, Lock, SimpleQueue + +#----------------------------------------------------------- +# OAI Testing modules +#----------------------------------------------------------- +import sshconnection as SSH +#from sshconnection import SSHConnection as SSH +import helpreadme as HELP +import constants as CONST + +#----------------------------------------------------------- +# Class Declaration +#----------------------------------------------------------- +class EPCManagement(): + def __init__(self): + self.EPCIPAddress = '' + self.EPCUserName = '' + self.EPCPassword = '' + self.EPCSourceCodePath = '' + self.EPCType = '' + self.EPC_PcapFileName = '' + + def InitializeHSS(self): + if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': + HELP.GenericHelp() + HELP.EPCSrvHelp(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, self.EPCSourceCodePath, self.EPCType) + sys.exit('Insufficient EPC Parameters') + #mySSH = SSH() + mySSH = SSH.SSHConnection() + mySSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + logging.debug('Using the OAI EPC Release 14 Cassandra-based HSS') + mySSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + logging.debug('\u001B[1m Launching tshark on all interfaces \u001B[0m') + EPC_PcapFileName = 'epc_' + self.testCase_id + '.pcap' + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f ' + EPC_PcapFileName, '\$', 5) + mySSH.command('echo $USER; nohup sudo tshark -f "tcp port not 22 and port not 53" -i any -w ' + self.EPCSourceCodePath + '/scripts/' + EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', self.EPCUserName, 5) + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S mkdir -p logs', '\$', 5) + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f hss_' + self.testCase_id + '.log logs/hss*.*', '\$', 5) + mySSH.command('echo "oai_hss -j /usr/local/etc/oai/hss_rel14.json" > ./my-hss.sh', '\$', 5) + mySSH.command('chmod 755 ./my-hss.sh', '\$', 5) + mySSH.command('sudo daemon --unsafe --name=hss_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/hss_' + self.testCase_id + '.log ./my-hss.sh', '\$', 5) + elif re.match('OAI', self.EPCType, re.IGNORECASE): + logging.debug('Using the OAI EPC HSS') + mySSH.command('cd ' + self.EPCSourceCodePath, '\$', 5) + mySSH.command('source oaienv', '\$', 5) + mySSH.command('cd scripts', '\$', 5) + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S ./run_hss 2>&1 | stdbuf -o0 awk \'{ print strftime("[%Y/%m/%d %H:%M:%S] ",systime()) $0 }\' | stdbuf -o0 tee -a hss_' + self.testCase_id + '.log &', 'Core state: 2 -> 3', 35) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + logging.debug('Using the ltebox simulated HSS') + mySSH.command('if [ -d ' + self.EPCSourceCodePath + '/scripts ]; then echo ' + self.EPCPassword + ' | sudo -S rm -Rf ' + self.EPCSourceCodePath + '/scripts ; fi', '\$', 5) + mySSH.command('mkdir -p ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + mySSH.command('cd /opt/hss_sim0609', '\$', 5) + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f hss.log daemon.log', '\$', 5) + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S echo "Starting sudo session" && sudo daemon --unsafe --name=simulated_hss --chdir=/opt/hss_sim0609 ./starthss_real ', '\$', 5) + else: + logging.error('This option should not occur!') + mySSH.close() + #self.CreateHtmlTestRow(self.EPCType, 'OK', CONST.ALL_PROCESSES_OK) + + def InitializeMME(self): + if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': + HELP.GenericHelp() + HELP.EPCSrvHelp(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, self.EPCSourceCodePath, self.EPCType) + sys.exit('Insufficient EPC Parameters') + mySSH = SSH.SSHConnection() + mySSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + logging.debug('Using the OAI EPC Release 14 MME') + mySSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f mme_' + self.testCase_id + '.log', '\$', 5) + mySSH.command('echo "./run_mme --config-file /usr/local/etc/oai/mme.conf --set-virt-if" > ./my-mme.sh', '\$', 5) + mySSH.command('chmod 755 ./my-mme.sh', '\$', 5) + mySSH.command('sudo daemon --unsafe --name=mme_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/mme_' + self.testCase_id + '.log ./my-mme.sh', '\$', 5) + elif re.match('OAI', self.EPCType, re.IGNORECASE): + mySSH.command('cd ' + self.EPCSourceCodePath, '\$', 5) + mySSH.command('source oaienv', '\$', 5) + mySSH.command('cd scripts', '\$', 5) + mySSH.command('stdbuf -o0 hostname', '\$', 5) + result = re.search('hostname\\\\r\\\\n(?P[a-zA-Z0-9\-\_]+)\\\\r\\\\n', mySSH.getBefore()) + if result is None: + logging.debug('\u001B[1;37;41m Hostname Not Found! \u001B[0m') + sys.exit(1) + host_name = result.group('host_name') + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S ./run_mme 2>&1 | stdbuf -o0 tee -a mme_' + self.testCase_id + '.log &', 'MME app initialization complete', 100) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + mySSH.command('cd /opt/ltebox/tools', '\$', 5) + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S ./start_mme', '\$', 5) + else: + logging.error('This option should not occur!') + mySSH.close() + #self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) + + def InitializeSPGW(self): + if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': + HELP.GenericHelp() + HELP.EPCSrvHelp(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, self.EPCSourceCodePath, self.EPCType) + sys.exit('Insufficient EPC Parameters') + mySSH = SSH.SSHConnection() + mySSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + logging.debug('Using the OAI EPC Release 14 SPGW-CUPS') + mySSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f spgwc_' + self.testCase_id + '.log spgwu_' + self.testCase_id + '.log', '\$', 5) + mySSH.command('echo "spgwc -c /usr/local/etc/oai/spgw_c.conf" > ./my-spgwc.sh', '\$', 5) + mySSH.command('chmod 755 ./my-spgwc.sh', '\$', 5) + mySSH.command('sudo daemon --unsafe --name=spgwc_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/spgwc_' + self.testCase_id + '.log ./my-spgwc.sh', '\$', 5) + time.sleep(5) + mySSH.command('echo "spgwu -c /usr/local/etc/oai/spgw_u.conf" > ./my-spgwu.sh', '\$', 5) + mySSH.command('chmod 755 ./my-spgwu.sh', '\$', 5) + mySSH.command('sudo daemon --unsafe --name=spgwu_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/spgwu_' + self.testCase_id + '.log ./my-spgwu.sh', '\$', 5) + elif re.match('OAI', self.EPCType, re.IGNORECASE): + mySSH.command('cd ' + self.EPCSourceCodePath, '\$', 5) + mySSH.command('source oaienv', '\$', 5) + mySSH.command('cd scripts', '\$', 5) + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S ./run_spgw 2>&1 | stdbuf -o0 tee -a spgw_' + self.testCase_id + '.log &', 'Initializing SPGW-APP task interface: DONE', 30) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + mySSH.command('cd /opt/ltebox/tools', '\$', 5) + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S ./start_xGw', '\$', 5) + else: + logging.error('This option should not occur!') + mySSH.close() + #self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) + + + def CheckHSSProcess(self, status_queue): + try: + mySSH = SSH.SSHConnection() + mySSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + mySSH.command('stdbuf -o0 ps -aux | grep --color=never hss | grep -v grep', '\$', 5) + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + result = re.search('oai_hss -j', mySSH.getBefore()) + elif re.match('OAI', self.EPCType, re.IGNORECASE): + result = re.search('\/bin\/bash .\/run_', mySSH.getBefore()) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + result = re.search('hss_sim s6as diam_hss', mySSH.getBefore()) + else: + logging.error('This should not happen!') + if result is None: + logging.debug('\u001B[1;37;41m HSS Process Not Found! \u001B[0m') + status_queue.put(CONST.HSS_PROCESS_FAILED) + else: + status_queue.put(CONST.HSS_PROCESS_OK) + mySSH.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def CheckMMEProcess(self, status_queue): + try: + mySSH = SSH.SSHConnection() + mySSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + mySSH.command('stdbuf -o0 ps -aux | grep --color=never mme | grep -v grep', '\$', 5) + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + result = re.search('mme -c', mySSH.getBefore()) + elif re.match('OAI', self.EPCType, re.IGNORECASE): + result = re.search('\/bin\/bash .\/run_', mySSH.getBefore()) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + result = re.search('mme', mySSH.getBefore()) + else: + logging.error('This should not happen!') + if result is None: + logging.debug('\u001B[1;37;41m MME Process Not Found! \u001B[0m') + status_queue.put(CONST.MME_PROCESS_FAILED) + else: + status_queue.put(CONST.MME_PROCESS_OK) + mySSH.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def CheckSPGWProcess(self, status_queue): + try: + mySSH = SSH.SSHConnection() + mySSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + mySSH.command('stdbuf -o0 ps -aux | grep --color=never spgw | grep -v grep', '\$', 5) + result = re.search('spgwu -c ', mySSH.getBefore()) + elif re.match('OAI', self.EPCType, re.IGNORECASE): + mySSH.command('stdbuf -o0 ps -aux | grep --color=never spgw | grep -v grep', '\$', 5) + result = re.search('\/bin\/bash .\/run_', mySSH.getBefore()) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + mySSH.command('stdbuf -o0 ps -aux | grep --color=never xGw | grep -v grep', '\$', 5) + result = re.search('xGw', mySSH.getBefore()) + else: + logging.error('This should not happen!') + if result is None: + logging.debug('\u001B[1;37;41m SPGW Process Not Found! \u001B[0m') + status_queue.put(CONST.SPGW_PROCESS_FAILED) + else: + status_queue.put(CONST.SPGW_PROCESS_OK) + mySSH.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + + def TerminateHSS(self): + mySSH = SSH.SSHConnection() + mySSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT oai_hss || true', '\$', 5) + time.sleep(2) + mySSH.command('stdbuf -o0 ps -aux | grep hss | grep -v grep', '\$', 5) + result = re.search('oai_hss -j', mySSH.getBefore()) + if result is not None: + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL oai_hss || true', '\$', 5) + mySSH.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-hss.sh', '\$', 5) + elif re.match('OAI', self.EPCType, re.IGNORECASE): + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_hss oai_hss || true', '\$', 5) + time.sleep(2) + mySSH.command('stdbuf -o0 ps -aux | grep hss | grep -v grep', '\$', 5) + result = re.search('\/bin\/bash .\/run_', mySSH.getBefore()) + if result is not None: + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_hss oai_hss || true', '\$', 5) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + mySSH.command('cd ' + self.EPCSourceCodePath, '\$', 5) + mySSH.command('cd scripts', '\$', 5) + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S daemon --name=simulated_hss --stop', '\$', 5) + time.sleep(1) + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL hss_sim', '\$', 5) + else: + logging.error('This should not happen!') + mySSH.close() + #self.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + + def TerminateMME(self): + mySSH = SSH.SSHConnection() + mySSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_mme mme || true', '\$', 5) + time.sleep(2) + mySSH.command('stdbuf -o0 ps -aux | grep mme | grep -v grep', '\$', 5) + result = re.search('mme -c', mySSH.getBefore()) + if result is not None: + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_mme mme || true', '\$', 5) + mySSH.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-mme.sh', '\$', 5) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + mySSH.command('cd /opt/ltebox/tools', '\$', 5) + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S ./stop_mme', '\$', 5) + else: + logging.error('This should not happen!') + mySSH.close() + #self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def TerminateSPGW(self): + mySSH = SSH.SSHConnection() + mySSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT spgwc spgwu || true', '\$', 5) + time.sleep(2) + mySSH.command('stdbuf -o0 ps -aux | grep spgw | grep -v grep', '\$', 5) + result = re.search('spgwc -c |spgwu -c ', mySSH.getBefore()) + if result is not None: + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL spgwc spgwu || true', '\$', 5) + mySSH.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-spgw*.sh', '\$', 5) + mySSH.command('stdbuf -o0 ps -aux | grep tshark | grep -v grep', '\$', 5) + result = re.search('-w ', mySSH.getBefore()) + if result is not None: + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT tshark || true', '\$', 5) + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 ' + self.EPCSourceCodePath + '/scripts/*.pcap', '\$', 5) + elif re.match('OAI', self.EPCType, re.IGNORECASE): + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_spgw spgw || true', '\$', 5) + time.sleep(2) + mySSH.command('stdbuf -o0 ps -aux | grep spgw | grep -v grep', '\$', 5) + result = re.search('\/bin\/bash .\/run_', mySSH.getBefore()) + if result is not None: + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_spgw spgw || true', '\$', 5) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + mySSH.command('cd /opt/ltebox/tools', '\$', 5) + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S ./stop_xGw', '\$', 5) + else: + logging.error('This should not happen!') + mySSH.close() + #self.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + + + def LogCollectHSS(self): + mySSH = SSH.SSHConnection() + mySSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + mySSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + mySSH.command('rm -f hss.log.zip', '\$', 5) + if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + mySSH.command('zip hss.log.zip hss*.log', '\$', 60) + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S rm hss*.log', '\$', 5) + if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + mySSH.command('zip hss.log.zip logs/hss*.* *.pcap', '\$', 60) + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f logs/hss*.* *.pcap', '\$', 5) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + mySSH.command('cp /opt/hss_sim0609/hss.log .', '\$', 60) + mySSH.command('zip hss.log.zip hss.log', '\$', 60) + else: + logging.error('This option should not occur!') + mySSH.close() + + def LogCollectMME(self): + mySSH = SSH.SSHConnection() + mySSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + mySSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + mySSH.command('rm -f mme.log.zip', '\$', 5) + if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + mySSH.command('zip mme.log.zip mme*.log', '\$', 60) + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S rm mme*.log', '\$', 5) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + mySSH.command('cp /opt/ltebox/var/log/*Log.0 .', '\$', 5) + mySSH.command('zip mme.log.zip mmeLog.0 s1apcLog.0 s1apsLog.0 s11cLog.0 libLog.0 s1apCodecLog.0', '\$', 60) + else: + logging.error('This option should not occur!') + mySSH.close() + + def LogCollectSPGW(self): + mySSH = SSH.SSHConnection() + mySSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + mySSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + mySSH.command('rm -f spgw.log.zip', '\$', 5) + if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + mySSH.command('zip spgw.log.zip spgw*.log', '\$', 60) + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S rm spgw*.log', '\$', 5) + elif re.match('ltebox', self.EPCType, re.IGNORECASE): + mySSH.command('cp /opt/ltebox/var/log/xGwLog.0 .', '\$', 5) + mySSH.command('zip spgw.log.zip xGwLog.0', '\$', 60) + else: + logging.error('This option should not occur!') + mySSH.close() + diff --git a/ci-scripts/helpreadme.py b/ci-scripts/helpreadme.py new file mode 100644 index 0000000000..ed4fc5ecec --- /dev/null +++ b/ci-scripts/helpreadme.py @@ -0,0 +1,51 @@ +#----------------------------------------------------------- +# Functions Declaration +#----------------------------------------------------------- + +def GenericHelp(): + print('----------------------------------------------------------------------------------------------------------------------') + print('main.py Ver: 0.1') + print('----------------------------------------------------------------------------------------------------------------------') + print('Usage: python main.py [options]') + print(' --help Show this help.') + print(' --mode=[Mode]') + print(' TesteNB') + print(' InitiateHtml, FinalizeHtml') + print(' TerminateeNB, TerminateUE, TerminateHSS, TerminateMME, TerminateSPGW') + print(' LogCollectBuild, LogCollecteNB, LogCollectHSS, LogCollectMME, LogCollectSPGW, LogCollectPing, LogCollectIperf') + +def GitSrvHelp(repository,branch,commit,mergeallow,targetbranch): + print(' --ranRepository=[OAI RAN Repository URL] -- ' + repository) + print(' --ranBranch=[OAI RAN Repository Branch] -- ' + branch) + print(' --ranCommitID=[OAI RAN Repository Commit SHA-1] -- ' + commit) + print(' --ranAllowMerge=[Allow Merge Request (with target branch) (true or false)] -- ' + mergeallow) + print(' --ranTargetBranch=[Target Branch in case of a Merge Request] -- ' + targetbranch) + +def eNBSrvHelp(ipaddr, username, password, sourcepath): + print(' --eNBIPAddress=[eNB\'s IP Address] -- ' + ipaddr) + print(' --eNBUserName=[eNB\'s Login User Name] -- ' + username) + print(' --eNBPassword=[eNB\'s Login Password] -- ' + password) + print(' --eNBSourceCodePath=[eNB\'s Source Code Path] -- ' + sourcepath) + +def OAIUESrvHelp(ipaddr, username, password, sourcepath): + print(' --UEIPAddress=[UE\'s IP Address] -- ' + ipaddr) + print(' --UEUserName=[UE\'s Login User Name] -- ' + username) + print(' --UEPassword=[UE\'s Login Password] -- ' + password) + print(' --UESourceCodePath=[UE\'s Source Code Path] -- ' + sourcepath) + +def EPCSrvHelp(ipaddr, username, password, sourcepath, epctype): + print(' --EPCIPAddress=[EPC\'s IP Address] -- ' + ipaddr) + print(' --EPCUserName=[EPC\'s Login User Name] -- ' + username) + print(' --EPCPassword=[EPC\'s Login Password] -- ' + password) + print(' --EPCSourceCodePath=[EPC\'s Source Code Path] -- ' + sourcepath) + print(' --EPCType=[EPC\'s Type: OAI or ltebox or OAI-Rel14-CUPS] -- ' + epctype) + +def ADBSrvHelp(ipaddr, username, password): + print(' --ADBIPAddress=[ADB\'s IP Address] -- ' + ipaddr) + print(' --ADBUserName=[ADB\'s Login User Name] -- ' + username) + print(' --ADBPassword=[ADB\'s Login Password] -- ' + password) + +def XmlHelp(filename): + print(' --XMLTestFile=[XML Test File to be run] -- ' + filename) + print(' Note: multiple xml files can be specified (--XMLFile=File1 ... --XMLTestFile=FileN) when HTML headers are created ("InitiateHtml" mode)') + diff --git a/ci-scripts/main.py b/ci-scripts/main.py index d3a700899f..1b1cd4efce 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -1,4 +1,4 @@ -# /* + # * 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. @@ -104,9 +104,9 @@ class OaiCiTest(): self.eNBUserName = '' self.eNBPassword = '' self.eNBSourceCodePath = '' - self.EPCIPAddress = '' - self.EPCUserName = '' - self.EPCPassword = '' + #self.EPCIPAddress = '' + #self.EPCUserName = '' + #self.EPCPassword = '' self.eNB1IPAddress = '' self.eNB1UserName = '' self.eNB1Password = '' @@ -115,9 +115,9 @@ class OaiCiTest(): self.eNB2UserName = '' self.eNB2Password = '' self.eNB2SourceCodePath = '' - self.EPCSourceCodePath = '' - self.EPCType = '' - self.EPC_PcapFileName = '' + #self.EPCSourceCodePath = '' + #self.EPCType = '' + #self.EPC_PcapFileName = '' self.ADBIPAddress = '' self.ADBUserName = '' self.ADBPassword = '' @@ -450,45 +450,45 @@ class OaiCiTest(): sys.exit(1) def InitializeHSS(self): - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': + if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCSourceCodePath == '' or EPC.EPCType == '': Usage() sys.exit('Insufficient Parameter') - SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) + if re.match('OAI-Rel14-CUPS', EPC.EPCType, re.IGNORECASE): logging.debug('Using the OAI EPC Release 14 Cassandra-based HSS') - SSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + SSH.command('cd ' + EPC.EPCSourceCodePath + '/scripts', '\$', 5) logging.debug('\u001B[1m Launching tshark on all interfaces \u001B[0m') EPC_PcapFileName = 'epc_' + self.testCase_id + '.pcap' - SSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f ' + EPC_PcapFileName, '\$', 5) - SSH.command('echo $USER; nohup sudo tshark -f "tcp port not 22 and port not 53" -i any -w ' + self.EPCSourceCodePath + '/scripts/' + EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', self.EPCUserName, 5) - SSH.command('echo ' + self.EPCPassword + ' | sudo -S mkdir -p logs', '\$', 5) - SSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f hss_' + self.testCase_id + '.log logs/hss*.*', '\$', 5) + SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S rm -f ' + EPC_PcapFileName, '\$', 5) + SSH.command('echo $USER; nohup sudo tshark -f "tcp port not 22 and port not 53" -i any -w ' + EPC.EPCSourceCodePath + '/scripts/' + EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', EPC.EPCUserName, 5) + SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S mkdir -p logs', '\$', 5) + SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S rm -f hss_' + self.testCase_id + '.log logs/hss*.*', '\$', 5) SSH.command('echo "oai_hss -j /usr/local/etc/oai/hss_rel14.json" > ./my-hss.sh', '\$', 5) SSH.command('chmod 755 ./my-hss.sh', '\$', 5) - SSH.command('sudo daemon --unsafe --name=hss_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/hss_' + self.testCase_id + '.log ./my-hss.sh', '\$', 5) - elif re.match('OAI', self.EPCType, re.IGNORECASE): + SSH.command('sudo daemon --unsafe --name=hss_daemon --chdir=' + EPC.EPCSourceCodePath + '/scripts -o ' + EPC.EPCSourceCodePath + '/scripts/hss_' + self.testCase_id + '.log ./my-hss.sh', '\$', 5) + elif re.match('OAI', EPC.EPCType, re.IGNORECASE): logging.debug('Using the OAI EPC HSS') - SSH.command('cd ' + self.EPCSourceCodePath, '\$', 5) + SSH.command('cd ' + EPC.EPCSourceCodePath, '\$', 5) SSH.command('source oaienv', '\$', 5) SSH.command('cd scripts', '\$', 5) - SSH.command('echo ' + self.EPCPassword + ' | sudo -S ./run_hss 2>&1 | stdbuf -o0 awk \'{ print strftime("[%Y/%m/%d %H:%M:%S] ",systime()) $0 }\' | stdbuf -o0 tee -a hss_' + self.testCase_id + '.log &', 'Core state: 2 -> 3', 35) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): + SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S ./run_hss 2>&1 | stdbuf -o0 awk \'{ print strftime("[%Y/%m/%d %H:%M:%S] ",systime()) $0 }\' | stdbuf -o0 tee -a hss_' + self.testCase_id + '.log &', 'Core state: 2 -> 3', 35) + elif re.match('ltebox', EPC.EPCType, re.IGNORECASE): logging.debug('Using the ltebox simulated HSS') - SSH.command('if [ -d ' + self.EPCSourceCodePath + '/scripts ]; then echo ' + self.eNBPassword + ' | sudo -S rm -Rf ' + self.EPCSourceCodePath + '/scripts ; fi', '\$', 5) - SSH.command('mkdir -p ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + SSH.command('if [ -d ' + EPC.EPCSourceCodePath + '/scripts ]; then echo ' + self.eNBPassword + ' | sudo -S rm -Rf ' + EPC.EPCSourceCodePath + '/scripts ; fi', '\$', 5) + SSH.command('mkdir -p ' + EPC.EPCSourceCodePath + '/scripts', '\$', 5) SSH.command('cd /opt/hss_sim0609', '\$', 5) - SSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f hss.log daemon.log', '\$', 5) - SSH.command('echo ' + self.EPCPassword + ' | sudo -S echo "Starting sudo session" && sudo daemon --unsafe --name=simulated_hss --chdir=/opt/hss_sim0609 ./starthss_real ', '\$', 5) + SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S rm -f hss.log daemon.log', '\$', 5) + SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S echo "Starting sudo session" && sudo daemon --unsafe --name=simulated_hss --chdir=/opt/hss_sim0609 ./starthss_real ', '\$', 5) else: logging.error('This option should not occur!') SSH.close() - self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) + self.CreateHtmlTestRow(EPC.EPCType, 'OK', ALL_PROCESSES_OK) def InitializeMME(self): - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': + if self.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCSourceCodePath == '' or EPC.EPCType == '': Usage() sys.exit('Insufficient Parameter') - SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.open(self.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): logging.debug('Using the OAI EPC Release 14 MME') SSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) @@ -516,10 +516,10 @@ class OaiCiTest(): self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) def InitializeSPGW(self): - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': + if self.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCSourceCodePath == '' or EPC.EPCType == '': Usage() sys.exit('Insufficient Parameter') - SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.open(self.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): logging.debug('Using the OAI EPC Release 14 SPGW-CUPS') SSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) @@ -545,9 +545,9 @@ class OaiCiTest(): self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) def CheckFlexranCtrlInstallation(self): - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '': + if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '': return - SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) SSH.command('ls -ls /opt/flexran_rtc/*/rt_controller', '\$', 5) result = re.search('/opt/flexran_rtc/build/rt_controller', SSH.getBefore()) if result is not None: @@ -558,15 +558,15 @@ class OaiCiTest(): def InitializeFlexranCtrl(self): if self.flexranCtrlInstalled == False: return - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '': + if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '': Usage() sys.exit('Insufficient Parameter') - SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) SSH.command('cd /opt/flexran_rtc', '\$', 5) - SSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f log/*.log', '\$', 5) - SSH.command('echo ' + self.EPCPassword + ' | sudo -S echo "build/rt_controller -c log_config/basic_log" > ./my-flexran-ctl.sh', '\$', 5) - SSH.command('echo ' + self.EPCPassword + ' | sudo -S chmod 755 ./my-flexran-ctl.sh', '\$', 5) - SSH.command('echo ' + self.EPCPassword + ' | sudo -S daemon --unsafe --name=flexran_rtc_daemon --chdir=/opt/flexran_rtc -o /opt/flexran_rtc/log/flexranctl_' + self.testCase_id + '.log ././my-flexran-ctl.sh', '\$', 5) + SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S rm -f log/*.log', '\$', 5) + SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S echo "build/rt_controller -c log_config/basic_log" > ./my-flexran-ctl.sh', '\$', 5) + SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S chmod 755 ./my-flexran-ctl.sh', '\$', 5) + SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S daemon --unsafe --name=flexran_rtc_daemon --chdir=/opt/flexran_rtc -o /opt/flexran_rtc/log/flexranctl_' + self.testCase_id + '.log ././my-flexran-ctl.sh', '\$', 5) SSH.command('ps -aux | grep --color=never rt_controller', '\$', 5) result = re.search('rt_controller -c ', SSH.getBefore()) if result is not None: @@ -604,15 +604,15 @@ class OaiCiTest(): # If tracer options is on, running tshark on EPC side and capture traffic b/ EPC and eNB result = re.search('T_stdout', str(self.Initialize_eNB_args)) if result is not None: - SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) SSH.command('ip addr show | awk -f /tmp/active_net_interfaces.awk | egrep -v "lo|tun"', '\$', 5) result = re.search('interfaceToUse=(?P[a-zA-Z0-9\-\_]+)done', SSH.getBefore()) if result is not None: eth_interface = result.group('eth_interface') logging.debug('\u001B[1m Launching tshark on interface ' + eth_interface + '\u001B[0m') - self.EPC_PcapFileName = 'enb_' + self.testCase_id + '_s1log.pcap' - SSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f /tmp/' + self.EPC_PcapFileName, '\$', 5) - SSH.command('echo $USER; nohup sudo tshark -f "host ' + lIpAddr +'" -i ' + eth_interface + ' -w /tmp/' + self.EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', self.EPCUserName, 5) + EPC.EPC_PcapFileName = 'enb_' + self.testCase_id + '_s1log.pcap' + SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S rm -f /tmp/' + EPC.EPC_PcapFileName , '\$', 5) + SSH.command('echo $USER; nohup sudo tshark -f "host ' + lIpAddr +'" -i ' + eth_interface + ' -w /tmp/' + EPC.EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', EPC.EPCUserName, 5) SSH.close() SSH.open(lIpAddr, lUserName, lPassWord) SSH.command('cd ' + lSourcePath, '\$', 5) @@ -651,7 +651,7 @@ class OaiCiTest(): SSH.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 60) # Make a copy and adapt to EPC / eNB IP addresses SSH.command('cp ' + full_config_file + ' ' + ci_full_config_file, '\$', 5) - SSH.command('sed -i -e \'s/CI_MME_IP_ADDR/' + self.EPCIPAddress + '/\' ' + ci_full_config_file, '\$', 2); + SSH.command('sed -i -e \'s/CI_MME_IP_ADDR/' + EPC.EPCIPAddress + '/\' ' + ci_full_config_file, '\$', 2); SSH.command('sed -i -e \'s/CI_ENB_IP_ADDR/' + lIpAddr + '/\' ' + ci_full_config_file, '\$', 2); SSH.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2); SSH.command('sed -i -e \'s/CI_RRU1_IP_ADDR/' + self.eNB1IPAddress + '/\' ' + ci_full_config_file, '\$', 2); @@ -700,18 +700,18 @@ class OaiCiTest(): # In case of T tracer recording, we need to kill tshark on EPC side result = re.search('T_stdout', str(self.Initialize_eNB_args)) if result is not None: - SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) logging.debug('\u001B[1m Stopping tshark \u001B[0m') - SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) - if self.EPC_PcapFileName != '': + SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) + if EPC.EPC_PcapFileName != '': time.sleep(0.5) - SSH.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 /tmp/' + self.EPC_PcapFileName, '\$', 5) + SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S chmod 666 /tmp/' + EPC.EPC_PcapFileName , '\$', 5) SSH.close() time.sleep(1) - if self.EPC_PcapFileName != '': - copyin_res = SSH.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + self.EPC_PcapFileName, '.') + if EPC.EPC_PcapFileName != '': + copyin_res = SSH.copyin(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword, '/tmp/' + EPC.EPC_PcapFileName , '.') if (copyin_res == 0): - SSH.copyout(lIpAddr, lUserName, lPassWord, self.EPC_PcapFileName, lSourcePath + '/cmake_targets/.') + SSH.copyout(lIpAddr, lUserName, lPassWord, EPC.EPC_PcapFileName , lSourcePath + '/cmake_targets/.') self.prematureExit = True return else: @@ -1106,7 +1106,7 @@ class OaiCiTest(): self.AutoTerminateUEandeNB() def PingCatM(self): - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '': + if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCSourceCodePath == '': Usage() sys.exit('Insufficient Parameter') check_eNB = True @@ -1119,10 +1119,10 @@ class OaiCiTest(): try: statusQueue = SimpleQueue() lock = Lock() - SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - SSH.command('cd ' + self.EPCSourceCodePath, '\$', 5) + SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) + SSH.command('cd ' + EPC.EPCSourceCodePath, '\$', 5) SSH.command('cd scripts', '\$', 5) - if re.match('OAI', self.EPCType, re.IGNORECASE): + if re.match('OAI', EPC.EPCType, re.IGNORECASE): logging.debug('Using the OAI EPC HSS: not implemented yet') self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) self.CreateHtmlTabFooter(False) @@ -1635,7 +1635,7 @@ class OaiCiTest(): for job in multi_jobs: job.join() if self.flexranCtrlInstalled and self.flexranCtrlStarted: - SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) SSH.command('cd /opt/flexran_rtc', '\$', 5) SSH.command('curl http://localhost:9999/stats | jq \'.\' > log/check_status_' + self.testCase_id + '.log 2>&1', '\$', 5) SSH.command('cat log/check_status_' + self.testCase_id + '.log | jq \'.eNB_config[0].UE\' | grep -c rnti | sed -e "s#^#Nb Connected UE = #"', '\$', 5) @@ -1747,13 +1747,13 @@ class OaiCiTest(): # Launch ping on the EPC side (true for ltebox and old open-air-cn) # But for OAI-Rel14-CUPS, we launch from python executor launchFromEpc = True - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + if re.match('OAI-Rel14-CUPS', EPC.EPCType, re.IGNORECASE): launchFromEpc = False ping_time = re.findall("-c (\d+)",str(self.ping_args)) if launchFromEpc: - SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - SSH.command('cd ' + self.EPCSourceCodePath, '\$', 5) + SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) + SSH.command('cd ' + EPC.EPCSourceCodePath, '\$', 5) SSH.command('cd scripts', '\$', 5) ping_status = SSH.command('stdbuf -o0 ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) else: @@ -1762,9 +1762,9 @@ class OaiCiTest(): logging.debug(cmd) ret = subprocess.run(cmd, shell=True) ping_status = ret.returncode - SSH.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'ping_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') - SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - SSH.command('cat ' + self.EPCSourceCodePath + '/scripts/ping_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.copyout(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword, 'ping_' + self.testCase_id + '_' + device_id + '.log', EPC.EPCSourceCodePath + '/scripts') + SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) + SSH.command('cat ' + EPC.EPCSourceCodePath + '/scripts/ping_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) # TIMEOUT CASE if ping_status < 0: message = 'Ping with UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT!' @@ -1923,7 +1923,7 @@ class OaiCiTest(): else: copyin_res = SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') if (copyin_res == 0): - SSH.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'ping_' + self.testCase_id + '.log', self.EPCSourceCodePath + '/scripts') + SSH.copyout(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword, 'ping_' + self.testCase_id + '.log', EPC.EPCSourceCodePath + '/scripts') except: os.kill(os.getppid(),signal.SIGUSR1) @@ -1932,7 +1932,7 @@ class OaiCiTest(): if result is not None: self.PingNoS1() return - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '': + if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCSourceCodePath == '': Usage() sys.exit('Insufficient Parameter') check_eNB = True @@ -2276,7 +2276,7 @@ class OaiCiTest(): # Launch iperf server on EPC side (true for ltebox and old open-air-cn0 # But for OAI-Rel14-CUPS, we launch from python executor and we are using its IP address as iperf client address launchFromEpc = True - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + if re.match('OAI-Rel14-CUPS', EPC.EPCType, re.IGNORECASE): launchFromEpc = False cmd = 'hostname -I' ret = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, encoding='utf-8') @@ -2284,13 +2284,13 @@ class OaiCiTest(): EPC_Iperf_UE_IPAddress = ret.stdout.strip() port = 5001 + idx if launchFromEpc: - SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - SSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) + SSH.command('cd ' + EPC.EPCSourceCodePath + '/scripts', '\$', 5) SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) if udpIperf: - SSH.command('echo $USER; nohup iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.EPCUserName, 5) + SSH.command('echo $USER; nohup iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', EPC.EPCUserName, 5) else: - SSH.command('echo $USER; nohup iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.EPCUserName, 5) + SSH.command('echo $USER; nohup iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', EPC.EPCUserName, 5) SSH.close() else: if self.ueIperfVersion == self.dummyIperfVersion: @@ -2313,7 +2313,7 @@ class OaiCiTest(): SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) else: SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - SSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + SSH.command('cd ' + EPC.EPCSourceCodePath + '/scripts', '\$', 5) iperf_time = self.Iperf_ComputeTime() time.sleep(0.5) @@ -2347,27 +2347,27 @@ class OaiCiTest(): # Kill iperf server on EPC side if launchFromEpc: - SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - SSH.command('killall --signal SIGKILL iperf', self.EPCUserName, 5) + SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) + SSH.command('killall --signal SIGKILL iperf', EPC.EPCUserName, 5) SSH.close() else: cmd = 'killall --signal SIGKILL iperf' logging.debug(cmd) subprocess.run(cmd, shell=True) time.sleep(1) - SSH.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') + SSH.copyout(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.EPCSourceCodePath + '/scripts') # in case of failure, retrieve server log if (clientStatus == -1) or (clientStatus == -2): if launchFromEpc: time.sleep(1) if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): os.remove('iperf_server_' + self.testCase_id + '_' + device_id + '.log') - SSH.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, self.EPCSourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + SSH.copyin(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword, EPC.EPCSourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) # in case of OAI-UE if (device_id == 'OAI-UE'): SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_' + self.testCase_id + '_' + device_id + '.log', '.') - SSH.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') + SSH.copyout(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword, 'iperf_' + self.testCase_id + '_' + device_id + '.log', EPC.EPCSourceCodePath + '/scripts') def Iperf_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue): try: @@ -2381,8 +2381,8 @@ class OaiCiTest(): if (device_id != 'OAI-UE'): SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) # if by chance ADB server and EPC are on the same remote host, at least log collection will take care of it - SSH.command('if [ ! -d ' + self.EPCSourceCodePath + '/scripts ]; then mkdir -p ' + self.EPCSourceCodePath + '/scripts ; fi', '\$', 5) - SSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + SSH.command('if [ ! -d ' + EPC.EPCSourceCodePath + '/scripts ]; then mkdir -p ' + self.EPCSourceCodePath + '/scripts ; fi', '\$', 5) + SSH.command('cd ' + EPC.EPCSourceCodePath + '/scripts', '\$', 5) # Checking if iperf / iperf3 are installed if self.ADBCentralized: SSH.command('adb -s ' + device_id + ' shell "ls /data/local/tmp"', '\$', 5) @@ -2441,7 +2441,7 @@ class OaiCiTest(): SSH.command('echo $USER; nohup iperf -B ' + UE_IPAddress + ' -u -s -i 1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.UEUserName, 5) else: SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - SSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + SSH.command('cd ' + EPC.EPCSourceCodePath + '/scripts', '\$', 5) if self.ADBCentralized: if (useIperf3): SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/iperf3 -s &', '\$', 5) @@ -2463,11 +2463,11 @@ class OaiCiTest(): # Launch the IPERF client on the EPC side for DL (true for ltebox and old open-air-cn # But for OAI-Rel14-CUPS, we launch from python executor launchFromEpc = True - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): + if re.match('OAI-Rel14-CUPS', EPC.EPCType, re.IGNORECASE): launchFromEpc = False if launchFromEpc: - SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - SSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) + SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) + SSH.command('cd ' + EPC.EPCSourceCodePath + '/scripts', '\$', 5) iperf_time = self.Iperf_ComputeTime() time.sleep(0.5) @@ -2502,9 +2502,9 @@ class OaiCiTest(): logging.debug(cmd) ret = subprocess.run(cmd, shell=True) iperf_status = ret.returncode - SSH.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') - SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - SSH.command('cat ' + self.EPCSourceCodePath + '/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.copyout(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword, 'iperf_' + self.testCase_id + '_' + device_id + '.log', EPC.EPCSourceCodePath + '/scripts') + SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) + SSH.command('cat ' + EPC.EPCSourceCodePath + '/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) if iperf_status < 0: if launchFromEpc: SSH.close() @@ -2541,7 +2541,7 @@ class OaiCiTest(): if (device_id == 'OAI-UE'): SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') else: - SSH.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, self.EPCSourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + SSH.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, EPC.EPCSourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') SSH.command('fromdos -o iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) @@ -2549,10 +2549,10 @@ class OaiCiTest(): if (device_id == 'OAI-UE'): if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): if not launchFromEpc: - SSH.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') + SSH.copyout(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.EPCSourceCodePath + '/scripts') else: SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') - SSH.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') + SSH.copyout(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.EPCSourceCodePath + '/scripts') except: os.kill(os.getppid(),signal.SIGUSR1) @@ -2636,10 +2636,10 @@ class OaiCiTest(): if (clientStatus == -1): copyin_res = SSH.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log') if (copyin_res == 0): - SSH.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_OAI-UE.log', self.EPCSourceCodePath + '/scripts') + SSH.copyout(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword, 'iperf_server_' + self.testCase_id + '_OAI-UE.log', EPC.EPCSourceCodePath + '/scripts') copyin_res = SSH.copyin(iClientIPAddr, iClientUser, iClientPasswd, '/tmp/tmp_iperf_' + self.testCase_id + '.log', 'iperf_' + self.testCase_id + '_OAI-UE.log') if (copyin_res == 0): - SSH.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_' + self.testCase_id + '_OAI-UE.log', self.EPCSourceCodePath + '/scripts') + SSH.copyout(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword, 'iperf_' + self.testCase_id + '_OAI-UE.log', EPC.EPCSourceCodePath + '/scripts') iperf_noperf = False if status_queue.empty(): iperf_status = False @@ -2670,7 +2670,7 @@ class OaiCiTest(): if result is not None: self.IperfNoS1() return - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCSourceCodePath == '' or self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': Usage() sys.exit('Insufficient Parameter') check_eNB = True @@ -2747,15 +2747,15 @@ class OaiCiTest(): # in noS1 config, no need to check status from EPC result = re.search('noS1', str(self.Initialize_eNB_args)) if result is None: - p = Process(target = CiTestObj.CheckHSSProcess, args = (status_queue,)) + p = Process(target = EPC.CheckHSSProcess, args = (status_queue,)) p.daemon = True p.start() multi_jobs.append(p) - p = Process(target = CiTestObj.CheckMMEProcess, args = (status_queue,)) + p = Process(target = EPC.CheckMMEProcess, args = (status_queue,)) p.daemon = True p.start() multi_jobs.append(p) - p = Process(target = CiTestObj.CheckSPGWProcess, args = (status_queue,)) + p = Process(target = EPC.CheckSPGWProcess, args = (status_queue,)) p.daemon = True p.start() multi_jobs.append(p) @@ -2870,7 +2870,7 @@ class OaiCiTest(): def CheckHSSProcess(self, status_queue): try: - SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.open(self.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) SSH.command('stdbuf -o0 ps -aux | grep --color=never hss | grep -v grep', '\$', 5) if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): result = re.search('oai_hss -j', SSH.getBefore()) @@ -2891,7 +2891,7 @@ class OaiCiTest(): def CheckMMEProcess(self, status_queue): try: - SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.open(self.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) SSH.command('stdbuf -o0 ps -aux | grep --color=never mme | grep -v grep', '\$', 5) if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): result = re.search('mme -c', SSH.getBefore()) @@ -2912,7 +2912,7 @@ class OaiCiTest(): def CheckSPGWProcess(self, status_queue): try: - SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.open(self.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): SSH.command('stdbuf -o0 ps -aux | grep --color=never spgw | grep -v grep', '\$', 5) result = re.search('spgwu -c ', SSH.getBefore()) @@ -3399,14 +3399,14 @@ class OaiCiTest(): # If tracer options is on, stopping tshark on EPC side result = re.search('T_stdout', str(self.Initialize_eNB_args)) if result is not None: - SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) logging.debug('\u001B[1m Stopping tshark \u001B[0m') - SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) + SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) time.sleep(1) - if self.EPC_PcapFileName != '': - SSH.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 /tmp/' + self.EPC_PcapFileName, '\$', 5) - SSH.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + self.EPC_PcapFileName, '.') - SSH.copyout(lIpAddr, lUserName, lPassWord, self.EPC_PcapFileName, lSourcePath + '/cmake_targets/.') + if EPC.EPC_PcapFileName != '': + SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S chmod 666 /tmp/' + EPC.EPC_PcapFileName , '\$', 5) + SSH.copyin(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword, '/tmp/' + EPC.EPC_PcapFileName , '.') + SSH.copyout(lIpAddr, lUserName, lPassWord, EPC.EPC_PcapFileName , lSourcePath + '/cmake_targets/.') SSH.close() logging.debug('\u001B[1m Replaying RAW record file\u001B[0m') SSH.open(lIpAddr, lUserName, lPassWord) @@ -3456,7 +3456,7 @@ class OaiCiTest(): self.eNBstatuses[int(self.eNB_instance)] = -1 def TerminateHSS(self): - SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.open(self.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT oai_hss || true', '\$', 5) time.sleep(2) @@ -3484,7 +3484,7 @@ class OaiCiTest(): self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) def TerminateMME(self): - SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.open(self.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_mme mme || true', '\$', 5) time.sleep(2) @@ -3502,7 +3502,7 @@ class OaiCiTest(): self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) def TerminateSPGW(self): - SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.open(self.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT spgwc spgwu || true', '\$', 5) time.sleep(2) @@ -3515,7 +3515,7 @@ class OaiCiTest(): result = re.search('-w ', SSH.getBefore()) if result is not None: SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT tshark || true', '\$', 5) - SSH.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 ' + self.EPCSourceCodePath + '/scripts/*.pcap', '\$', 5) + SSH.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 ' + EPC.EPCSourceCodePath + '/scripts/*.pcap', '\$', 5) elif re.match('OAI', self.EPCType, re.IGNORECASE): SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_spgw spgw || true', '\$', 5) time.sleep(2) @@ -3534,13 +3534,13 @@ class OaiCiTest(): def TerminateFlexranCtrl(self): if self.flexranCtrlInstalled == False or self.flexranCtrlStarted == False: return - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '': + if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '': Usage() sys.exit('Insufficient Parameter') - SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - SSH.command('echo ' + self.EPCPassword + ' | sudo -S daemon --name=flexran_rtc_daemon --stop', '\$', 5) + SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) + SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S daemon --name=flexran_rtc_daemon --stop', '\$', 5) time.sleep(1) - SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL rt_controller', '\$', 5) + SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S killall --signal SIGKILL rt_controller', '\$', 5) time.sleep(1) SSH.close() self.flexranCtrlStarted = False @@ -3667,7 +3667,7 @@ class OaiCiTest(): self.CreateHtmlTestRow(str(self.idle_sleep_time) + ' sec', 'OK', ALL_PROCESSES_OK) def X2_Status(self, idx, fileName): - cmd = "curl --silent http://" + self.EPCIPAddress + ":9999/stats | jq '.' > " + fileName + cmd = "curl --silent http://" + EPC.EPCIPAddress + ":9999/stats | jq '.' > " + fileName message = cmd + '\n' logging.debug(cmd) subprocess.run(cmd, shell=True) @@ -3731,7 +3731,7 @@ class OaiCiTest(): eNB_cnt = self.x2NbENBs cnt = 0 while cnt < eNB_cnt: - cmd = "curl -XPOST http://" + self.EPCIPAddress + ":9999/rrc/x2_ho_net_control/enb/" + str(self.x2ENBBsIds[0][cnt]) + "/1" + cmd = "curl -XPOST http://" + EPC.EPCIPAddress + ":9999/rrc/x2_ho_net_control/enb/" + str(self.x2ENBBsIds[0][cnt]) + "/1" logging.debug(cmd) fullMessage += cmd + '\n' subprocess.run(cmd, shell=True) @@ -3745,7 +3745,7 @@ class OaiCiTest(): while cnt < eNB_cnt: ueIdx = 0 while ueIdx < len(self.x2ENBConnectedUEs[0][cnt]): - cmd = "curl -XPOST http://" + self.EPCIPAddress + ":9999/rrc/ho/senb/" + str(self.x2ENBBsIds[0][cnt]) + "/ue/" + str(self.x2ENBConnectedUEs[0][cnt][ueIdx]) + "/tenb/" + str(self.x2ENBBsIds[0][eNB_cnt - cnt - 1]) + cmd = "curl -XPOST http://" + EPC.EPCIPAddress + ":9999/rrc/ho/senb/" + str(self.x2ENBBsIds[0][cnt]) + "/ue/" + str(self.x2ENBConnectedUEs[0][cnt][ueIdx]) + "/tenb/" + str(self.x2ENBBsIds[0][eNB_cnt - cnt - 1]) logging.debug(cmd) fullMessage += cmd + '\n' subprocess.run(cmd, shell=True) @@ -3806,8 +3806,8 @@ class OaiCiTest(): SSH.close() def LogCollectPing(self): - SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - SSH.command('cd ' + self.EPCSourceCodePath, '\$', 5) + SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) + SSH.command('cd ' + EPC.EPCSourceCodePath, '\$', 5) SSH.command('cd scripts', '\$', 5) SSH.command('rm -f ping.log.zip', '\$', 5) SSH.command('zip ping.log.zip ping*.log', '\$', 60) @@ -3815,8 +3815,8 @@ class OaiCiTest(): SSH.close() def LogCollectIperf(self): - SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - SSH.command('cd ' + self.EPCSourceCodePath, '\$', 5) + SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) + SSH.command('cd ' + EPC.EPCSourceCodePath, '\$', 5) SSH.command('cd scripts', '\$', 5) SSH.command('rm -f iperf.log.zip', '\$', 5) SSH.command('zip iperf.log.zip iperf*.log', '\$', 60) @@ -3824,7 +3824,7 @@ class OaiCiTest(): SSH.close() def LogCollectHSS(self): - SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.open(self.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) SSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) SSH.command('rm -f hss.log.zip', '\$', 5) if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): @@ -3841,7 +3841,7 @@ class OaiCiTest(): SSH.close() def LogCollectMME(self): - SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.open(self.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) SSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) SSH.command('rm -f mme.log.zip', '\$', 5) if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): @@ -3855,7 +3855,7 @@ class OaiCiTest(): SSH.close() def LogCollectSPGW(self): - SSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + SSH.open(self.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) SSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) SSH.command('rm -f spgw.log.zip', '\$', 5) if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): @@ -4451,8 +4451,14 @@ def receive_signal(signum, frame): #----------------------------------------------------------- mode = '' CiTestObj = OaiCiTest() + from sshconnection import * +from epc import * +from helpreadme import * SSH = SSHConnection() +EPC = EPCManagement() +#HELP = HelpReadme() +#HELP.GenericHelp() argvs = sys.argv argc = len(argvs) @@ -4540,23 +4546,23 @@ while len(argvs) > 1: CiTestObj.eNB2SourceCodePath = matchReg.group(1) elif re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.EPCIPAddress = matchReg.group(1) + EPC.EPCIPAddress = matchReg.group(1) elif re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE) CiTestObj.EPCBranch = matchReg.group(1) elif re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.EPCUserName = matchReg.group(1) + EPC.EPCUserName = matchReg.group(1) elif re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.EPCPassword = matchReg.group(1) + EPC.EPCPassword = matchReg.group(1) elif re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.EPCSourceCodePath = matchReg.group(1) + EPC.EPCSourceCodePath = matchReg.group(1) elif re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE) if re.match('OAI', matchReg.group(1), re.IGNORECASE) or re.match('ltebox', matchReg.group(1), re.IGNORECASE) or re.match('OAI-Rel14-CUPS', matchReg.group(1), re.IGNORECASE): - CiTestObj.EPCType = matchReg.group(1) + EPC.EPCType = matchReg.group(1) else: sys.exit('Invalid EPC Type: ' + matchReg.group(1) + ' -- (should be OAI or ltebox or OAI-Rel14-CUPS)') elif re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE): @@ -4623,17 +4629,17 @@ elif re.match('^TerminateOAIUE$', mode, re.IGNORECASE): signal.signal(signal.SIGUSR1, receive_signal) CiTestObj.TerminateOAIUE() elif re.match('^TerminateHSS$', mode, re.IGNORECASE): - if CiTestObj.EPCIPAddress == '' or CiTestObj.EPCUserName == '' or CiTestObj.EPCPassword == '' or CiTestObj.EPCType == '' or CiTestObj.EPCSourceCodePath == '': + if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCType == '' or EPC.EPCSourceCodePath == '': Usage() sys.exit('Insufficient Parameter') CiTestObj.TerminateHSS() elif re.match('^TerminateMME$', mode, re.IGNORECASE): - if CiTestObj.EPCIPAddress == '' or CiTestObj.EPCUserName == '' or CiTestObj.EPCPassword == '' or CiTestObj.EPCType == '' or CiTestObj.EPCSourceCodePath == '': + if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCType == '' or EPC.EPCSourceCodePath == '': Usage() sys.exit('Insufficient Parameter') CiTestObj.TerminateMME() elif re.match('^TerminateSPGW$', mode, re.IGNORECASE): - if CiTestObj.EPCIPAddress == '' or CiTestObj.EPCUserName == '' or CiTestObj.EPCPassword == '' or CiTestObj.EPCType == '' or CiTestObj.EPCSourceCodePath == '': + if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCType == '' or EPC.EPCSourceCodePath == '': Usage() sys.exit('Insufficient Parameter') CiTestObj.TerminateSPGW() @@ -4648,27 +4654,27 @@ elif re.match('^LogCollecteNB$', mode, re.IGNORECASE): sys.exit('Insufficient Parameter') CiTestObj.LogCollecteNB() elif re.match('^LogCollectHSS$', mode, re.IGNORECASE): - if CiTestObj.EPCIPAddress == '' or CiTestObj.EPCUserName == '' or CiTestObj.EPCPassword == '' or CiTestObj.EPCType == '' or CiTestObj.EPCSourceCodePath == '': + if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCType == '' or EPC.EPCSourceCodePath == '': Usage() sys.exit('Insufficient Parameter') - CiTestObj.LogCollectHSS() + EPC.LogCollectHSS() elif re.match('^LogCollectMME$', mode, re.IGNORECASE): - if CiTestObj.EPCIPAddress == '' or CiTestObj.EPCUserName == '' or CiTestObj.EPCPassword == '' or CiTestObj.EPCType == '' or CiTestObj.EPCSourceCodePath == '': + if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCType == '' or EPC.EPCSourceCodePath == '': Usage() sys.exit('Insufficient Parameter') - CiTestObj.LogCollectMME() + EPC.LogCollectMME() elif re.match('^LogCollectSPGW$', mode, re.IGNORECASE): - if CiTestObj.EPCIPAddress == '' or CiTestObj.EPCUserName == '' or CiTestObj.EPCPassword == '' or CiTestObj.EPCType == '' or CiTestObj.EPCSourceCodePath == '': + if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCType == '' or EPC.EPCSourceCodePath == '': Usage() sys.exit('Insufficient Parameter') - CiTestObj.LogCollectSPGW() + EPC.LogCollectSPGW() elif re.match('^LogCollectPing$', mode, re.IGNORECASE): - if CiTestObj.EPCIPAddress == '' or CiTestObj.EPCUserName == '' or CiTestObj.EPCPassword == '' or CiTestObj.EPCSourceCodePath == '': + if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCSourceCodePath == '': Usage() sys.exit('Insufficient Parameter') CiTestObj.LogCollectPing() elif re.match('^LogCollectIperf$', mode, re.IGNORECASE): - if CiTestObj.EPCIPAddress == '' or CiTestObj.EPCUserName == '' or CiTestObj.EPCPassword == '' or CiTestObj.EPCSourceCodePath == '': + if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCSourceCodePath == '': Usage() sys.exit('Insufficient Parameter') CiTestObj.LogCollectIperf() @@ -4701,13 +4707,13 @@ elif re.match('^FinalizeHtml$', mode, re.IGNORECASE): CiTestObj.CreateHtmlFooter(CiTestObj.finalStatus) elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re.IGNORECASE): if re.match('^TesteNB$', mode, re.IGNORECASE): - if CiTestObj.eNBIPAddress == '' or CiTestObj.ranRepository == '' or CiTestObj.ranBranch == '' or CiTestObj.eNBUserName == '' or CiTestObj.eNBPassword == '' or CiTestObj.eNBSourceCodePath == '' or CiTestObj.EPCIPAddress == '' or CiTestObj.EPCUserName == '' or CiTestObj.EPCPassword == '' or CiTestObj.EPCType == '' or CiTestObj.EPCSourceCodePath == '' or CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == '': + if CiTestObj.eNBIPAddress == '' or CiTestObj.ranRepository == '' or CiTestObj.ranBranch == '' or CiTestObj.eNBUserName == '' or CiTestObj.eNBPassword == '' or CiTestObj.eNBSourceCodePath == '' or EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCType == '' or EPC.EPCSourceCodePath == '' or CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == '': Usage() sys.exit('Insufficient Parameter') - if (CiTestObj.EPCIPAddress != '') and (CiTestObj.EPCIPAddress != 'none'): - SSH.copyout(CiTestObj.EPCIPAddress, CiTestObj.EPCUserName, CiTestObj.EPCPassword, cwd + "/tcp_iperf_stats.awk", "/tmp") - SSH.copyout(CiTestObj.EPCIPAddress, CiTestObj.EPCUserName, CiTestObj.EPCPassword, cwd + "/active_net_interfaces.awk", "/tmp") + if (EPC.EPCIPAddress != '') and (EPC.EPCIPAddress != 'none'): + SSH.copyout(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword, cwd + "/tcp_iperf_stats.awk", "/tmp") + SSH.copyout(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword, cwd + "/active_net_interfaces.awk", "/tmp") else: if CiTestObj.UEIPAddress == '' or CiTestObj.ranRepository == '' or CiTestObj.ranBranch == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == '': Usage() @@ -4755,7 +4761,7 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re else: logging.debug('ERROR: requested test is invalidly formatted: ' + test) sys.exit(1) - if (CiTestObj.EPCIPAddress != '') and (CiTestObj.EPCIPAddress != 'none'): + if (EPC.EPCIPAddress != '') and (EPC.EPCIPAddress != 'none'): CiTestObj.CheckFlexranCtrlInstallation() #get the list of tests to be done @@ -4843,17 +4849,17 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re elif action == 'Reboot_UE': CiTestObj.RebootUE() elif action == 'Initialize_HSS': - CiTestObj.InitializeHSS() + EPC.InitializeHSS() elif action == 'Terminate_HSS': - CiTestObj.TerminateHSS() + EPC.TerminateHSS() elif action == 'Initialize_MME': - CiTestObj.InitializeMME() + EPC.InitializeMME() elif action == 'Terminate_MME': - CiTestObj.TerminateMME() + EPC.TerminateMME() elif action == 'Initialize_SPGW': - CiTestObj.InitializeSPGW() + EPC.InitializeSPGW() elif action == 'Terminate_SPGW': - CiTestObj.TerminateSPGW() + EPC.TerminateSPGW() elif action == 'Initialize_FlexranCtrl': CiTestObj.InitializeFlexranCtrl() elif action == 'Terminate_FlexranCtrl': From 3f546cb48acfd9406ec7924d832e6d3322bb7d81 Mon Sep 17 00:00:00 2001 From: Gabriele Perrone Date: Thu, 23 Jan 2020 10:41:49 +0100 Subject: [PATCH 082/240] minor changes to epc.py, helpreadme.py, main.py to complete the export of EPC functions from main --- ci-scripts/epc.py | 6 +++--- ci-scripts/helpreadme.py | 4 ++-- ci-scripts/main.py | 16 ++++++++-------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/ci-scripts/epc.py b/ci-scripts/epc.py index 3ebb3cfb04..258cd2e09b 100644 --- a/ci-scripts/epc.py +++ b/ci-scripts/epc.py @@ -30,7 +30,7 @@ class EPCManagement(): def InitializeHSS(self): if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': - HELP.GenericHelp() + HELP.GenericHelp(Version) HELP.EPCSrvHelp(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, self.EPCSourceCodePath, self.EPCType) sys.exit('Insufficient EPC Parameters') #mySSH = SSH() @@ -68,7 +68,7 @@ class EPCManagement(): def InitializeMME(self): if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': - HELP.GenericHelp() + HELP.GenericHelp(Version) HELP.EPCSrvHelp(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, self.EPCSourceCodePath, self.EPCType) sys.exit('Insufficient EPC Parameters') mySSH = SSH.SSHConnection() @@ -101,7 +101,7 @@ class EPCManagement(): def InitializeSPGW(self): if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': - HELP.GenericHelp() + HELP.GenericHelp(Version) HELP.EPCSrvHelp(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, self.EPCSourceCodePath, self.EPCType) sys.exit('Insufficient EPC Parameters') mySSH = SSH.SSHConnection() diff --git a/ci-scripts/helpreadme.py b/ci-scripts/helpreadme.py index ed4fc5ecec..fba2c40698 100644 --- a/ci-scripts/helpreadme.py +++ b/ci-scripts/helpreadme.py @@ -2,9 +2,9 @@ # Functions Declaration #----------------------------------------------------------- -def GenericHelp(): +def GenericHelp(vers): print('----------------------------------------------------------------------------------------------------------------------') - print('main.py Ver: 0.1') + print('main.py Ver: ' + vers) print('----------------------------------------------------------------------------------------------------------------------') print('Usage: python main.py [options]') print(' --help Show this help.') diff --git a/ci-scripts/main.py b/ci-scripts/main.py index fa3a5ce7f7..9740017542 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -486,7 +486,7 @@ class OaiCiTest(): self.CreateHtmlTestRow(self.Build_OAI_UE_args, 'KO', ALL_PROCESSES_OK, 'OAI UE') self.CreateHtmlTabFooter(False) sys.exit(1) - + """ def InitializeHSS(self): if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCSourceCodePath == '' or EPC.EPCType == '': Usage() @@ -581,7 +581,7 @@ class OaiCiTest(): logging.error('This option should not occur!') SSH.close() self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) - + """ def CheckFlexranCtrlInstallation(self): if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '': return @@ -2934,7 +2934,7 @@ class OaiCiTest(): SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) - + """ def CheckHSSProcess(self, status_queue): try: SSH.open(self.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) @@ -2999,7 +2999,7 @@ class OaiCiTest(): SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) - + """ def AnalyzeLogFile_eNB(self, eNBlogFile): if (not os.path.isfile('./' + eNBlogFile)): return -1 @@ -3603,7 +3603,7 @@ class OaiCiTest(): self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) self.eNBmbmsEnables[int(self.eNB_instance)] = False self.eNBstatuses[int(self.eNB_instance)] = -1 - + """ def TerminateHSS(self): SSH.open(self.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): @@ -3679,7 +3679,7 @@ class OaiCiTest(): logging.error('This should not happen!') SSH.close() self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - + """ def TerminateFlexranCtrl(self): if self.flexranCtrlInstalled == False or self.flexranCtrlStarted == False: return @@ -3975,7 +3975,7 @@ class OaiCiTest(): SSH.command('zip iperf.log.zip iperf*.log', '\$', 60) SSH.command('rm iperf*.log', '\$', 5) SSH.close() - + """ def LogCollectHSS(self): SSH.open(self.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) SSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) @@ -4020,7 +4020,7 @@ class OaiCiTest(): else: logging.error('This option should not occur!') SSH.close() - + """ def LogCollectOAIUE(self): SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) SSH.command('cd ' + self.UESourceCodePath, '\$', 5) From 92811568728f8c1c1708dc53ac554bea35489e57 Mon Sep 17 00:00:00 2001 From: Gabriele Perrone Date: Mon, 27 Jan 2020 11:45:03 +0100 Subject: [PATCH 083/240] rework of the help from embedded Usage() function to external helpreadme.py file --- ci-scripts/epc.py | 25 ++ ci-scripts/helpreadme.py | 2 +- ci-scripts/main.py | 612 ++++++++++----------------------------- 3 files changed, 171 insertions(+), 468 deletions(-) diff --git a/ci-scripts/epc.py b/ci-scripts/epc.py index 258cd2e09b..58a0958d4b 100644 --- a/ci-scripts/epc.py +++ b/ci-scripts/epc.py @@ -28,6 +28,31 @@ class EPCManagement(): self.EPCType = '' self.EPC_PcapFileName = '' + def SetIPAddress(self, ipaddress): + self.EPCIPAddress = ipaddress + def GetIPAddress(self): + return self.EPCIPAddress + def SetUserName(self, username): + self.EPCUserName = username + def GetUserName(self): + return self.EPCUserName + def SetPassword(self, password): + self.EPCPassword = password + def GetPassword(self): + return self.EPCPassword + def SetSourceCodePath(self, sourcecodepath): + self.EPCSourceCodePath = sourcecodepath + def GetSourceCodePath(self): + return self.EPCSourceCodePath + def SetType(self, typ): + self.EPCType = typ + def GetType(self): + return self.EPCType + def Set_PcapFileName(self, pcapfn): + self.PcapFileName = pcapfn + def Get_PcapFileName(self): + return self.PcapFileName + def InitializeHSS(self): if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': HELP.GenericHelp(Version) diff --git a/ci-scripts/helpreadme.py b/ci-scripts/helpreadme.py index fba2c40698..294454e270 100644 --- a/ci-scripts/helpreadme.py +++ b/ci-scripts/helpreadme.py @@ -6,7 +6,7 @@ def GenericHelp(vers): print('----------------------------------------------------------------------------------------------------------------------') print('main.py Ver: ' + vers) print('----------------------------------------------------------------------------------------------------------------------') - print('Usage: python main.py [options]') + print('python main.py [options]') print(' --help Show this help.') print(' --mode=[Mode]') print(' TesteNB') diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 9740017542..c9da55041c 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -1,4 +1,4 @@ -#/* + # * 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. @@ -195,7 +195,7 @@ class OaiCiTest(): def BuildeNB(self): if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') if self.eNB_serverId == '0': lIpAddr = self.eNBIPAddress @@ -213,7 +213,7 @@ class OaiCiTest(): lPassWord = self.eNB2Password lSourcePath = self.eNB2SourceCodePath if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') SSH.open(lIpAddr, lUserName, lPassWord) # Check if we build an 5G-NR gNB or an LTE eNB @@ -314,7 +314,7 @@ class OaiCiTest(): lPassWord = self.eNB2Password lSourcePath = self.eNB2SourceCodePath if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') SSH.open(lIpAddr, lUserName, lPassWord) count = 40 @@ -386,7 +386,7 @@ class OaiCiTest(): def BuildOAIUE(self): if self.UEIPAddress == '' or self.ranRepository == '' or self.ranBranch == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) result = re.search('--nrUE', self.Build_OAI_UE_args) @@ -486,106 +486,11 @@ class OaiCiTest(): self.CreateHtmlTestRow(self.Build_OAI_UE_args, 'KO', ALL_PROCESSES_OK, 'OAI UE') self.CreateHtmlTabFooter(False) sys.exit(1) - """ - def InitializeHSS(self): - if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCSourceCodePath == '' or EPC.EPCType == '': - Usage() - sys.exit('Insufficient Parameter') - SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) - if re.match('OAI-Rel14-CUPS', EPC.EPCType, re.IGNORECASE): - logging.debug('Using the OAI EPC Release 14 Cassandra-based HSS') - SSH.command('cd ' + EPC.EPCSourceCodePath + '/scripts', '\$', 5) - logging.debug('\u001B[1m Launching tshark on all interfaces \u001B[0m') - EPC_PcapFileName = 'epc_' + self.testCase_id + '.pcap' - SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S rm -f ' + EPC_PcapFileName, '\$', 5) - SSH.command('echo $USER; nohup sudo tshark -f "tcp port not 22 and port not 53" -i any -w ' + EPC.EPCSourceCodePath + '/scripts/' + EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', EPC.EPCUserName, 5) - SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S mkdir -p logs', '\$', 5) - SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S rm -f hss_' + self.testCase_id + '.log logs/hss*.*', '\$', 5) - SSH.command('echo "oai_hss -j /usr/local/etc/oai/hss_rel14.json" > ./my-hss.sh', '\$', 5) - SSH.command('chmod 755 ./my-hss.sh', '\$', 5) - SSH.command('sudo daemon --unsafe --name=hss_daemon --chdir=' + EPC.EPCSourceCodePath + '/scripts -o ' + EPC.EPCSourceCodePath + '/scripts/hss_' + self.testCase_id + '.log ./my-hss.sh', '\$', 5) - elif re.match('OAI', EPC.EPCType, re.IGNORECASE): - logging.debug('Using the OAI EPC HSS') - SSH.command('cd ' + EPC.EPCSourceCodePath, '\$', 5) - SSH.command('source oaienv', '\$', 5) - SSH.command('cd scripts', '\$', 5) - SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S ./run_hss 2>&1 | stdbuf -o0 awk \'{ print strftime("[%Y/%m/%d %H:%M:%S] ",systime()) $0 }\' | stdbuf -o0 tee -a hss_' + self.testCase_id + '.log &', 'Core state: 2 -> 3', 35) - elif re.match('ltebox', EPC.EPCType, re.IGNORECASE): - logging.debug('Using the ltebox simulated HSS') - SSH.command('if [ -d ' + EPC.EPCSourceCodePath + '/scripts ]; then echo ' + self.eNBPassword + ' | sudo -S rm -Rf ' + EPC.EPCSourceCodePath + '/scripts ; fi', '\$', 5) - SSH.command('mkdir -p ' + EPC.EPCSourceCodePath + '/scripts', '\$', 5) - SSH.command('cd /opt/hss_sim0609', '\$', 5) - SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S rm -f hss.log daemon.log', '\$', 5) - SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S echo "Starting sudo session" && sudo daemon --unsafe --name=simulated_hss --chdir=/opt/hss_sim0609 ./starthss_real ', '\$', 5) - else: - logging.error('This option should not occur!') - SSH.close() - self.CreateHtmlTestRow(EPC.EPCType, 'OK', ALL_PROCESSES_OK) - - def InitializeMME(self): - if self.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCSourceCodePath == '' or EPC.EPCType == '': - Usage() - sys.exit('Insufficient Parameter') - SSH.open(self.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - logging.debug('Using the OAI EPC Release 14 MME') - SSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - SSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f mme_' + self.testCase_id + '.log', '\$', 5) - SSH.command('echo "./run_mme --config-file /usr/local/etc/oai/mme.conf --set-virt-if" > ./my-mme.sh', '\$', 5) - SSH.command('chmod 755 ./my-mme.sh', '\$', 5) - SSH.command('sudo daemon --unsafe --name=mme_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/mme_' + self.testCase_id + '.log ./my-mme.sh', '\$', 5) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - SSH.command('cd ' + self.EPCSourceCodePath, '\$', 5) - SSH.command('source oaienv', '\$', 5) - SSH.command('cd scripts', '\$', 5) - SSH.command('stdbuf -o0 hostname', '\$', 5) - result = re.search('hostname\\\\r\\\\n(?P[a-zA-Z0-9\-\_]+)\\\\r\\\\n', SSH.getBefore()) - if result is None: - logging.debug('\u001B[1;37;41m Hostname Not Found! \u001B[0m') - sys.exit(1) - host_name = result.group('host_name') - SSH.command('echo ' + self.EPCPassword + ' | sudo -S ./run_mme 2>&1 | stdbuf -o0 tee -a mme_' + self.testCase_id + '.log &', 'MME app initialization complete', 100) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - SSH.command('cd /opt/ltebox/tools', '\$', 5) - SSH.command('echo ' + self.EPCPassword + ' | sudo -S ./start_mme', '\$', 5) - else: - logging.error('This option should not occur!') - SSH.close() - self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) - - def InitializeSPGW(self): - if self.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCSourceCodePath == '' or EPC.EPCType == '': - Usage() - sys.exit('Insufficient Parameter') - SSH.open(self.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - logging.debug('Using the OAI EPC Release 14 SPGW-CUPS') - SSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - SSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f spgwc_' + self.testCase_id + '.log spgwu_' + self.testCase_id + '.log', '\$', 5) - SSH.command('echo "spgwc -c /usr/local/etc/oai/spgw_c.conf" > ./my-spgwc.sh', '\$', 5) - SSH.command('chmod 755 ./my-spgwc.sh', '\$', 5) - SSH.command('sudo daemon --unsafe --name=spgwc_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/spgwc_' + self.testCase_id + '.log ./my-spgwc.sh', '\$', 5) - time.sleep(5) - SSH.command('echo "spgwu -c /usr/local/etc/oai/spgw_u.conf" > ./my-spgwu.sh', '\$', 5) - SSH.command('chmod 755 ./my-spgwu.sh', '\$', 5) - SSH.command('sudo daemon --unsafe --name=spgwu_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/spgwu_' + self.testCase_id + '.log ./my-spgwu.sh', '\$', 5) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - SSH.command('cd ' + self.EPCSourceCodePath, '\$', 5) - SSH.command('source oaienv', '\$', 5) - SSH.command('cd scripts', '\$', 5) - SSH.command('echo ' + self.EPCPassword + ' | sudo -S ./run_spgw 2>&1 | stdbuf -o0 tee -a spgw_' + self.testCase_id + '.log &', 'Initializing SPGW-APP task interface: DONE', 30) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - SSH.command('cd /opt/ltebox/tools', '\$', 5) - SSH.command('echo ' + self.EPCPassword + ' | sudo -S ./start_xGw', '\$', 5) - else: - logging.error('This option should not occur!') - SSH.close() - self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) - """ + def CheckFlexranCtrlInstallation(self): - if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '': + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '': return - SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) SSH.command('ls -ls /opt/flexran_rtc/*/rt_controller', '\$', 5) result = re.search('/opt/flexran_rtc/build/rt_controller', SSH.getBefore()) if result is not None: @@ -596,15 +501,15 @@ class OaiCiTest(): def InitializeFlexranCtrl(self): if self.flexranCtrlInstalled == False: return - if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '': - Usage() + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '': + GenericHelp(Version) sys.exit('Insufficient Parameter') - SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) SSH.command('cd /opt/flexran_rtc', '\$', 5) - SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S rm -f log/*.log', '\$', 5) - SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S echo "build/rt_controller -c log_config/basic_log" > ./my-flexran-ctl.sh', '\$', 5) - SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S chmod 755 ./my-flexran-ctl.sh', '\$', 5) - SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S daemon --unsafe --name=flexran_rtc_daemon --chdir=/opt/flexran_rtc -o /opt/flexran_rtc/log/flexranctl_' + self.testCase_id + '.log ././my-flexran-ctl.sh', '\$', 5) + SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S rm -f log/*.log', '\$', 5) + SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S echo "build/rt_controller -c log_config/basic_log" > ./my-flexran-ctl.sh', '\$', 5) + SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S chmod 755 ./my-flexran-ctl.sh', '\$', 5) + SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S daemon --unsafe --name=flexran_rtc_daemon --chdir=/opt/flexran_rtc -o /opt/flexran_rtc/log/flexranctl_' + self.testCase_id + '.log ././my-flexran-ctl.sh', '\$', 5) SSH.command('ps -aux | grep --color=never rt_controller', '\$', 5) result = re.search('rt_controller -c ', SSH.getBefore()) if result is not None: @@ -630,7 +535,7 @@ class OaiCiTest(): lPassWord = self.eNB2Password lSourcePath = self.eNB2SourceCodePath if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') check_eNB = False check_OAI_UE = False @@ -642,15 +547,15 @@ class OaiCiTest(): # If tracer options is on, running tshark on EPC side and capture traffic b/ EPC and eNB result = re.search('T_stdout', str(self.Initialize_eNB_args)) if result is not None: - SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) SSH.command('ip addr show | awk -f /tmp/active_net_interfaces.awk | egrep -v "lo|tun"', '\$', 5) result = re.search('interfaceToUse=(?P[a-zA-Z0-9\-\_]+)done', SSH.getBefore()) if result is not None: eth_interface = result.group('eth_interface') logging.debug('\u001B[1m Launching tshark on interface ' + eth_interface + '\u001B[0m') EPC.EPC_PcapFileName = 'enb_' + self.testCase_id + '_s1log.pcap' - SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S rm -f /tmp/' + EPC.EPC_PcapFileName , '\$', 5) - SSH.command('echo $USER; nohup sudo tshark -f "host ' + lIpAddr +'" -i ' + eth_interface + ' -w /tmp/' + EPC.EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', EPC.EPCUserName, 5) + SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S rm -f /tmp/' + EPC.EPC_PcapFileName , '\$', 5) + SSH.command('echo $USER; nohup sudo tshark -f "host ' + lIpAddr +'" -i ' + eth_interface + ' -w /tmp/' + EPC.EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', EPC.GetUserName(), 5) SSH.close() SSH.open(lIpAddr, lUserName, lPassWord) SSH.command('cd ' + lSourcePath, '\$', 5) @@ -689,7 +594,7 @@ class OaiCiTest(): SSH.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 60) # Make a copy and adapt to EPC / eNB IP addresses SSH.command('cp ' + full_config_file + ' ' + ci_full_config_file, '\$', 5) - SSH.command('sed -i -e \'s/CI_MME_IP_ADDR/' + EPC.EPCIPAddress + '/\' ' + ci_full_config_file, '\$', 2); + SSH.command('sed -i -e \'s/CI_MME_IP_ADDR/' + EPC.GetIPAddress() + '/\' ' + ci_full_config_file, '\$', 2); SSH.command('sed -i -e \'s/CI_ENB_IP_ADDR/' + lIpAddr + '/\' ' + ci_full_config_file, '\$', 2); SSH.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2); SSH.command('sed -i -e \'s/CI_RRU1_IP_ADDR/' + self.eNB1IPAddress + '/\' ' + ci_full_config_file, '\$', 2); @@ -742,16 +647,16 @@ class OaiCiTest(): # In case of T tracer recording, we need to kill tshark on EPC side result = re.search('T_stdout', str(self.Initialize_eNB_args)) if result is not None: - SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) logging.debug('\u001B[1m Stopping tshark \u001B[0m') - SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) + SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) if EPC.EPC_PcapFileName != '': time.sleep(0.5) - SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S chmod 666 /tmp/' + EPC.EPC_PcapFileName , '\$', 5) + SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S chmod 666 /tmp/' + EPC.EPC_PcapFileName , '\$', 5) SSH.close() time.sleep(1) if EPC.EPC_PcapFileName != '': - copyin_res = SSH.copyin(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword, '/tmp/' + EPC.EPC_PcapFileName , '.') + copyin_res = SSH.copyin(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), '/tmp/' + EPC.EPC_PcapFileName , '.') if (copyin_res == 0): SSH.copyout(lIpAddr, lUserName, lPassWord, EPC.EPC_PcapFileName , lSourcePath + '/cmake_targets/.') self.prematureExit = True @@ -840,7 +745,7 @@ class OaiCiTest(): def InitializeUE(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') multi_jobs = [] i = 0 @@ -856,7 +761,7 @@ class OaiCiTest(): def InitializeOAIUE(self): if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') if self.air_interface == 'lte': result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) @@ -1045,7 +950,7 @@ class OaiCiTest(): def InitializeCatM(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') self.picocom_closure = True SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) @@ -1079,7 +984,7 @@ class OaiCiTest(): def TerminateCatM(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') self.picocom_closure = True SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) @@ -1100,7 +1005,7 @@ class OaiCiTest(): def AttachCatM(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') self.picocom_closure = True SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) @@ -1173,8 +1078,8 @@ class OaiCiTest(): self.AutoTerminateUEandeNB() def PingCatM(self): - if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCSourceCodePath == '': - Usage() + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '': + GenericHelp(Version) sys.exit('Insufficient Parameter') check_eNB = True check_OAI_UE = False @@ -1186,10 +1091,10 @@ class OaiCiTest(): try: statusQueue = SimpleQueue() lock = Lock() - SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) - SSH.command('cd ' + EPC.EPCSourceCodePath, '\$', 5) + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('cd ' + EPC.GetSourceCodePath(), '\$', 5) SSH.command('cd scripts', '\$', 5) - if re.match('OAI', EPC.EPCType, re.IGNORECASE): + if re.match('OAI', EPC.GetType(), re.IGNORECASE): logging.debug('Using the OAI EPC HSS: not implemented yet') self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) self.CreateHtmlTabFooter(False) @@ -1340,7 +1245,7 @@ class OaiCiTest(): def AttachUE(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') check_eNB = True check_OAI_UE = False @@ -1414,7 +1319,7 @@ class OaiCiTest(): def DetachUE(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') check_eNB = True check_OAI_UE = False @@ -1485,7 +1390,7 @@ class OaiCiTest(): def RebootUE(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') check_eNB = True check_OAI_UE = False @@ -1519,7 +1424,7 @@ class OaiCiTest(): def DataDisableUE(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') multi_jobs = [] i = 0 @@ -1548,7 +1453,7 @@ class OaiCiTest(): def DataEnableUE(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') multi_jobs = [] i = 0 @@ -1564,7 +1469,7 @@ class OaiCiTest(): def GetAllUEDevices(self, terminate_ue_flag): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) if self.ADBCentralized: @@ -1608,7 +1513,7 @@ class OaiCiTest(): def GetAllCatMDevices(self, terminate_ue_flag): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) if self.ADBCentralized: @@ -1680,7 +1585,7 @@ class OaiCiTest(): def CheckStatusUE(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') check_eNB = True check_OAI_UE = False @@ -1702,7 +1607,7 @@ class OaiCiTest(): for job in multi_jobs: job.join() if self.flexranCtrlInstalled and self.flexranCtrlStarted: - SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) SSH.command('cd /opt/flexran_rtc', '\$', 5) SSH.command('curl http://localhost:9999/stats | jq \'.\' > log/check_status_' + self.testCase_id + '.log 2>&1', '\$', 5) SSH.command('cat log/check_status_' + self.testCase_id + '.log | jq \'.eNB_config[0].UE\' | grep -c rnti | sed -e "s#^#Nb Connected UE = #"', '\$', 5) @@ -1744,13 +1649,13 @@ class OaiCiTest(): def GetAllUEIPAddresses(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') ue_ip_status = 0 self.UEIPAddresses = [] if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) SSH.command('ifconfig oaitun_ue1', '\$', 4) @@ -1814,13 +1719,13 @@ class OaiCiTest(): # Launch ping on the EPC side (true for ltebox and old open-air-cn) # But for OAI-Rel14-CUPS, we launch from python executor launchFromEpc = True - if re.match('OAI-Rel14-CUPS', EPC.EPCType, re.IGNORECASE): + if re.match('OAI-Rel14-CUPS', EPC.GetType(), re.IGNORECASE): launchFromEpc = False ping_time = re.findall("-c (\d+)",str(self.ping_args)) if launchFromEpc: - SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) - SSH.command('cd ' + EPC.EPCSourceCodePath, '\$', 5) + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('cd ' + EPC.GetSourceCodePath(), '\$', 5) SSH.command('cd scripts', '\$', 5) ping_status = SSH.command('stdbuf -o0 ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) else: @@ -1829,9 +1734,9 @@ class OaiCiTest(): logging.debug(cmd) ret = subprocess.run(cmd, shell=True) ping_status = ret.returncode - SSH.copyout(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword, 'ping_' + self.testCase_id + '_' + device_id + '.log', EPC.EPCSourceCodePath + '/scripts') - SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) - SSH.command('cat ' + EPC.EPCSourceCodePath + '/scripts/ping_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'ping_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('cat ' + EPC.GetSourceCodePath() + '/scripts/ping_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) # TIMEOUT CASE if ping_status < 0: message = 'Ping with UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT!' @@ -1912,11 +1817,11 @@ class OaiCiTest(): ping_from_eNB = re.search('oaitun_enb1', str(self.ping_args)) if ping_from_eNB is not None: if self.eNBIPAddress == '' or self.eNBUserName == '' or self.eNBPassword == '': - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') else: if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') try: if ping_from_eNB is not None: @@ -1989,7 +1894,7 @@ class OaiCiTest(): else: copyin_res = SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') if (copyin_res == 0): - SSH.copyout(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword, 'ping_' + self.testCase_id + '.log', EPC.EPCSourceCodePath + '/scripts') + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'ping_' + self.testCase_id + '.log', EPC.GetSourceCodePath() + '/scripts') except: os.kill(os.getppid(),signal.SIGUSR1) @@ -1998,8 +1903,8 @@ class OaiCiTest(): if result is not None: self.PingNoS1() return - if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCSourceCodePath == '': - Usage() + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '': + GenericHelp(Version) sys.exit('Insufficient Parameter') check_eNB = True if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): @@ -2342,7 +2247,7 @@ class OaiCiTest(): # Launch iperf server on EPC side (true for ltebox and old open-air-cn0 # But for OAI-Rel14-CUPS, we launch from python executor and we are using its IP address as iperf client address launchFromEpc = True - if re.match('OAI-Rel14-CUPS', EPC.EPCType, re.IGNORECASE): + if re.match('OAI-Rel14-CUPS', EPC.GetType(), re.IGNORECASE): launchFromEpc = False cmd = 'hostname -I' ret = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, encoding='utf-8') @@ -2350,13 +2255,13 @@ class OaiCiTest(): EPC_Iperf_UE_IPAddress = ret.stdout.strip() port = 5001 + idx if launchFromEpc: - SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) - SSH.command('cd ' + EPC.EPCSourceCodePath + '/scripts', '\$', 5) + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) if udpIperf: - SSH.command('echo $USER; nohup iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', EPC.EPCUserName, 5) + SSH.command('echo $USER; nohup iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', EPC.GetUserName(), 5) else: - SSH.command('echo $USER; nohup iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', EPC.EPCUserName, 5) + SSH.command('echo $USER; nohup iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', EPC.GetUserName(), 5) SSH.close() else: if self.ueIperfVersion == self.dummyIperfVersion: @@ -2379,7 +2284,7 @@ class OaiCiTest(): SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) else: SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - SSH.command('cd ' + EPC.EPCSourceCodePath + '/scripts', '\$', 5) + SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) iperf_time = self.Iperf_ComputeTime() time.sleep(0.5) @@ -2413,27 +2318,27 @@ class OaiCiTest(): # Kill iperf server on EPC side if launchFromEpc: - SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) - SSH.command('killall --signal SIGKILL iperf', EPC.EPCUserName, 5) + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('killall --signal SIGKILL iperf', EPC.GetUserName(), 5) SSH.close() else: cmd = 'killall --signal SIGKILL iperf' logging.debug(cmd) subprocess.run(cmd, shell=True) time.sleep(1) - SSH.copyout(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.EPCSourceCodePath + '/scripts') + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') # in case of failure, retrieve server log if (clientStatus == -1) or (clientStatus == -2): if launchFromEpc: time.sleep(1) if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): os.remove('iperf_server_' + self.testCase_id + '_' + device_id + '.log') - SSH.copyin(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword, EPC.EPCSourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + SSH.copyin(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), EPC.GetSourceCodePath() + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) # in case of OAI-UE if (device_id == 'OAI-UE'): SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_' + self.testCase_id + '_' + device_id + '.log', '.') - SSH.copyout(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword, 'iperf_' + self.testCase_id + '_' + device_id + '.log', EPC.EPCSourceCodePath + '/scripts') + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') def Iperf_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue): try: @@ -2447,8 +2352,8 @@ class OaiCiTest(): if (device_id != 'OAI-UE'): SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) # if by chance ADB server and EPC are on the same remote host, at least log collection will take care of it - SSH.command('if [ ! -d ' + EPC.EPCSourceCodePath + '/scripts ]; then mkdir -p ' + self.EPCSourceCodePath + '/scripts ; fi', '\$', 5) - SSH.command('cd ' + EPC.EPCSourceCodePath + '/scripts', '\$', 5) + SSH.command('if [ ! -d ' + EPC.GetSourceCodePath() + '/scripts ]; then mkdir -p ' + self.EPCSourceCodePath + '/scripts ; fi', '\$', 5) + SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) # Checking if iperf / iperf3 are installed if self.ADBCentralized: SSH.command('adb -s ' + device_id + ' shell "ls /data/local/tmp"', '\$', 5) @@ -2507,7 +2412,7 @@ class OaiCiTest(): SSH.command('echo $USER; nohup iperf -B ' + UE_IPAddress + ' -u -s -i 1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.UEUserName, 5) else: SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - SSH.command('cd ' + EPC.EPCSourceCodePath + '/scripts', '\$', 5) + SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) if self.ADBCentralized: if (useIperf3): SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/iperf3 -s &', '\$', 5) @@ -2529,11 +2434,11 @@ class OaiCiTest(): # Launch the IPERF client on the EPC side for DL (true for ltebox and old open-air-cn # But for OAI-Rel14-CUPS, we launch from python executor launchFromEpc = True - if re.match('OAI-Rel14-CUPS', EPC.EPCType, re.IGNORECASE): + if re.match('OAI-Rel14-CUPS', EPC.GetType(), re.IGNORECASE): launchFromEpc = False if launchFromEpc: - SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) - SSH.command('cd ' + EPC.EPCSourceCodePath + '/scripts', '\$', 5) + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) iperf_time = self.Iperf_ComputeTime() time.sleep(0.5) @@ -2568,9 +2473,9 @@ class OaiCiTest(): logging.debug(cmd) ret = subprocess.run(cmd, shell=True) iperf_status = ret.returncode - SSH.copyout(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword, 'iperf_' + self.testCase_id + '_' + device_id + '.log', EPC.EPCSourceCodePath + '/scripts') - SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) - SSH.command('cat ' + EPC.EPCSourceCodePath + '/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('cat ' + EPC.GetSourceCodePath() + '/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) if iperf_status < 0: if launchFromEpc: SSH.close() @@ -2607,7 +2512,7 @@ class OaiCiTest(): if (device_id == 'OAI-UE'): SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') else: - SSH.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, EPC.EPCSourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + SSH.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, EPC.GetSourceCodePath() + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') SSH.command('fromdos -o iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) @@ -2615,16 +2520,16 @@ class OaiCiTest(): if (device_id == 'OAI-UE'): if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): if not launchFromEpc: - SSH.copyout(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.EPCSourceCodePath + '/scripts') + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') else: SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') - SSH.copyout(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.EPCSourceCodePath + '/scripts') + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') except: os.kill(os.getppid(),signal.SIGUSR1) def IperfNoS1(self): if self.eNBIPAddress == '' or self.eNBUserName == '' or self.eNBPassword == '' or self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') check_eNB = True check_OAI_UE = True @@ -2702,10 +2607,10 @@ class OaiCiTest(): if (clientStatus == -1): copyin_res = SSH.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log') if (copyin_res == 0): - SSH.copyout(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword, 'iperf_server_' + self.testCase_id + '_OAI-UE.log', EPC.EPCSourceCodePath + '/scripts') + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_server_' + self.testCase_id + '_OAI-UE.log', EPC.GetSourceCodePath() + '/scripts') copyin_res = SSH.copyin(iClientIPAddr, iClientUser, iClientPasswd, '/tmp/tmp_iperf_' + self.testCase_id + '.log', 'iperf_' + self.testCase_id + '_OAI-UE.log') if (copyin_res == 0): - SSH.copyout(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword, 'iperf_' + self.testCase_id + '_OAI-UE.log', EPC.EPCSourceCodePath + '/scripts') + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_' + self.testCase_id + '_OAI-UE.log', EPC.GetSourceCodePath() + '/scripts') iperf_noperf = False if status_queue.empty(): iperf_status = False @@ -2736,8 +2641,8 @@ class OaiCiTest(): if result is not None: self.IperfNoS1() return - if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCSourceCodePath == '' or self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '' or self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + GenericHelp(Version) sys.exit('Insufficient Parameter') check_eNB = True if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): @@ -2934,72 +2839,7 @@ class OaiCiTest(): SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) - """ - def CheckHSSProcess(self, status_queue): - try: - SSH.open(self.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) - SSH.command('stdbuf -o0 ps -aux | grep --color=never hss | grep -v grep', '\$', 5) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - result = re.search('oai_hss -j', SSH.getBefore()) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - result = re.search('\/bin\/bash .\/run_', SSH.getBefore()) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - result = re.search('hss_sim s6as diam_hss', SSH.getBefore()) - else: - logging.error('This should not happen!') - if result is None: - logging.debug('\u001B[1;37;41m HSS Process Not Found! \u001B[0m') - status_queue.put(HSS_PROCESS_FAILED) - else: - status_queue.put(HSS_PROCESS_OK) - SSH.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def CheckMMEProcess(self, status_queue): - try: - SSH.open(self.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) - SSH.command('stdbuf -o0 ps -aux | grep --color=never mme | grep -v grep', '\$', 5) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - result = re.search('mme -c', SSH.getBefore()) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - result = re.search('\/bin\/bash .\/run_', SSH.getBefore()) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - result = re.search('mme', SSH.getBefore()) - else: - logging.error('This should not happen!') - if result is None: - logging.debug('\u001B[1;37;41m MME Process Not Found! \u001B[0m') - status_queue.put(MME_PROCESS_FAILED) - else: - status_queue.put(MME_PROCESS_OK) - SSH.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def CheckSPGWProcess(self, status_queue): - try: - SSH.open(self.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - SSH.command('stdbuf -o0 ps -aux | grep --color=never spgw | grep -v grep', '\$', 5) - result = re.search('spgwu -c ', SSH.getBefore()) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - SSH.command('stdbuf -o0 ps -aux | grep --color=never spgw | grep -v grep', '\$', 5) - result = re.search('\/bin\/bash .\/run_', SSH.getBefore()) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - SSH.command('stdbuf -o0 ps -aux | grep --color=never xGw | grep -v grep', '\$', 5) - result = re.search('xGw', SSH.getBefore()) - else: - logging.error('This should not happen!') - if result is None: - logging.debug('\u001B[1;37;41m SPGW Process Not Found! \u001B[0m') - status_queue.put(SPGW_PROCESS_FAILED) - else: - status_queue.put(SPGW_PROCESS_OK) - SSH.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - """ + def AnalyzeLogFile_eNB(self, eNBlogFile): if (not os.path.isfile('./' + eNBlogFile)): return -1 @@ -3524,7 +3364,7 @@ class OaiCiTest(): lPassWord = self.eNB2Password lSourcePath = self.eNB2SourceCodePath if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') SSH.open(lIpAddr, lUserName, lPassWord) SSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) @@ -3548,13 +3388,13 @@ class OaiCiTest(): # If tracer options is on, stopping tshark on EPC side result = re.search('T_stdout', str(self.Initialize_eNB_args)) if result is not None: - SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) logging.debug('\u001B[1m Stopping tshark \u001B[0m') - SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) + SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) time.sleep(1) if EPC.EPC_PcapFileName != '': - SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S chmod 666 /tmp/' + EPC.EPC_PcapFileName , '\$', 5) - SSH.copyin(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword, '/tmp/' + EPC.EPC_PcapFileName , '.') + SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S chmod 666 /tmp/' + EPC.EPC_PcapFileName , '\$', 5) + SSH.copyin(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), '/tmp/' + EPC.EPC_PcapFileName , '.') SSH.copyout(lIpAddr, lUserName, lPassWord, EPC.EPC_PcapFileName , lSourcePath + '/cmake_targets/.') SSH.close() logging.debug('\u001B[1m Replaying RAW record file\u001B[0m') @@ -3603,93 +3443,17 @@ class OaiCiTest(): self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) self.eNBmbmsEnables[int(self.eNB_instance)] = False self.eNBstatuses[int(self.eNB_instance)] = -1 - """ - def TerminateHSS(self): - SSH.open(self.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT oai_hss || true', '\$', 5) - time.sleep(2) - SSH.command('stdbuf -o0 ps -aux | grep hss | grep -v grep', '\$', 5) - result = re.search('oai_hss -j', SSH.getBefore()) - if result is not None: - SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL oai_hss || true', '\$', 5) - SSH.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-hss.sh', '\$', 5) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_hss oai_hss || true', '\$', 5) - time.sleep(2) - SSH.command('stdbuf -o0 ps -aux | grep hss | grep -v grep', '\$', 5) - result = re.search('\/bin\/bash .\/run_', SSH.getBefore()) - if result is not None: - SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_hss oai_hss || true', '\$', 5) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - SSH.command('cd ' + self.EPCSourceCodePath, '\$', 5) - SSH.command('cd scripts', '\$', 5) - SSH.command('echo ' + self.EPCPassword + ' | sudo -S daemon --name=simulated_hss --stop', '\$', 5) - time.sleep(1) - SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL hss_sim', '\$', 5) - else: - logging.error('This should not happen!') - SSH.close() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def TerminateMME(self): - SSH.open(self.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) - if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_mme mme || true', '\$', 5) - time.sleep(2) - SSH.command('stdbuf -o0 ps -aux | grep mme | grep -v grep', '\$', 5) - result = re.search('mme -c', SSH.getBefore()) - if result is not None: - SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_mme mme || true', '\$', 5) - SSH.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-mme.sh', '\$', 5) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - SSH.command('cd /opt/ltebox/tools', '\$', 5) - SSH.command('echo ' + self.EPCPassword + ' | sudo -S ./stop_mme', '\$', 5) - else: - logging.error('This should not happen!') - SSH.close() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def TerminateSPGW(self): - SSH.open(self.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT spgwc spgwu || true', '\$', 5) - time.sleep(2) - SSH.command('stdbuf -o0 ps -aux | grep spgw | grep -v grep', '\$', 5) - result = re.search('spgwc -c |spgwu -c ', SSH.getBefore()) - if result is not None: - SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL spgwc spgwu || true', '\$', 5) - SSH.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-spgw*.sh', '\$', 5) - SSH.command('stdbuf -o0 ps -aux | grep tshark | grep -v grep', '\$', 5) - result = re.search('-w ', SSH.getBefore()) - if result is not None: - SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT tshark || true', '\$', 5) - SSH.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 ' + EPC.EPCSourceCodePath + '/scripts/*.pcap', '\$', 5) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_spgw spgw || true', '\$', 5) - time.sleep(2) - SSH.command('stdbuf -o0 ps -aux | grep spgw | grep -v grep', '\$', 5) - result = re.search('\/bin\/bash .\/run_', SSH.getBefore()) - if result is not None: - SSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_spgw spgw || true', '\$', 5) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - SSH.command('cd /opt/ltebox/tools', '\$', 5) - SSH.command('echo ' + self.EPCPassword + ' | sudo -S ./stop_xGw', '\$', 5) - else: - logging.error('This should not happen!') - SSH.close() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - """ + def TerminateFlexranCtrl(self): if self.flexranCtrlInstalled == False or self.flexranCtrlStarted == False: return - if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '': - Usage() + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '': + GenericHelp(Version) sys.exit('Insufficient Parameter') - SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) - SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S daemon --name=flexran_rtc_daemon --stop', '\$', 5) + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S daemon --name=flexran_rtc_daemon --stop', '\$', 5) time.sleep(1) - SSH.command('echo ' + EPC.EPCPassword + ' | sudo -S killall --signal SIGKILL rt_controller', '\$', 5) + SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S killall --signal SIGKILL rt_controller', '\$', 5) time.sleep(1) SSH.close() self.flexranCtrlStarted = False @@ -3820,7 +3584,7 @@ class OaiCiTest(): self.CreateHtmlTestRow(str(self.idle_sleep_time) + ' sec', 'OK', ALL_PROCESSES_OK) def X2_Status(self, idx, fileName): - cmd = "curl --silent http://" + EPC.EPCIPAddress + ":9999/stats | jq '.' > " + fileName + cmd = "curl --silent http://" + EPC.GetIPAddress() + ":9999/stats | jq '.' > " + fileName message = cmd + '\n' logging.debug(cmd) subprocess.run(cmd, shell=True) @@ -3884,7 +3648,7 @@ class OaiCiTest(): eNB_cnt = self.x2NbENBs cnt = 0 while cnt < eNB_cnt: - cmd = "curl -XPOST http://" + EPC.EPCIPAddress + ":9999/rrc/x2_ho_net_control/enb/" + str(self.x2ENBBsIds[0][cnt]) + "/1" + cmd = "curl -XPOST http://" + EPC.GetIPAddress() + ":9999/rrc/x2_ho_net_control/enb/" + str(self.x2ENBBsIds[0][cnt]) + "/1" logging.debug(cmd) fullMessage += cmd + '\n' subprocess.run(cmd, shell=True) @@ -3898,7 +3662,7 @@ class OaiCiTest(): while cnt < eNB_cnt: ueIdx = 0 while ueIdx < len(self.x2ENBConnectedUEs[0][cnt]): - cmd = "curl -XPOST http://" + EPC.EPCIPAddress + ":9999/rrc/ho/senb/" + str(self.x2ENBBsIds[0][cnt]) + "/ue/" + str(self.x2ENBConnectedUEs[0][cnt][ueIdx]) + "/tenb/" + str(self.x2ENBBsIds[0][eNB_cnt - cnt - 1]) + cmd = "curl -XPOST http://" + EPC.GetIPAddress() + ":9999/rrc/ho/senb/" + str(self.x2ENBBsIds[0][cnt]) + "/ue/" + str(self.x2ENBConnectedUEs[0][cnt][ueIdx]) + "/tenb/" + str(self.x2ENBBsIds[0][eNB_cnt - cnt - 1]) logging.debug(cmd) fullMessage += cmd + '\n' subprocess.run(cmd, shell=True) @@ -3959,8 +3723,8 @@ class OaiCiTest(): SSH.close() def LogCollectPing(self): - SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) - SSH.command('cd ' + EPC.EPCSourceCodePath, '\$', 5) + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('cd ' + EPC.GetSourceCodePath(), '\$', 5) SSH.command('cd scripts', '\$', 5) SSH.command('rm -f ping.log.zip', '\$', 5) SSH.command('zip ping.log.zip ping*.log', '\$', 60) @@ -3968,59 +3732,14 @@ class OaiCiTest(): SSH.close() def LogCollectIperf(self): - SSH.open(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) - SSH.command('cd ' + EPC.EPCSourceCodePath, '\$', 5) + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('cd ' + EPC.GetSourceCodePath(), '\$', 5) SSH.command('cd scripts', '\$', 5) SSH.command('rm -f iperf.log.zip', '\$', 5) SSH.command('zip iperf.log.zip iperf*.log', '\$', 60) SSH.command('rm iperf*.log', '\$', 5) SSH.close() - """ - def LogCollectHSS(self): - SSH.open(self.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) - SSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - SSH.command('rm -f hss.log.zip', '\$', 5) - if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - SSH.command('zip hss.log.zip hss*.log', '\$', 60) - SSH.command('echo ' + self.EPCPassword + ' | sudo -S rm hss*.log', '\$', 5) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - SSH.command('zip hss.log.zip logs/hss*.* *.pcap', '\$', 60) - SSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f logs/hss*.* *.pcap', '\$', 5) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - SSH.command('cp /opt/hss_sim0609/hss.log .', '\$', 60) - SSH.command('zip hss.log.zip hss.log', '\$', 60) - else: - logging.error('This option should not occur!') - SSH.close() - - def LogCollectMME(self): - SSH.open(self.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) - SSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - SSH.command('rm -f mme.log.zip', '\$', 5) - if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - SSH.command('zip mme.log.zip mme*.log', '\$', 60) - SSH.command('echo ' + self.EPCPassword + ' | sudo -S rm mme*.log', '\$', 5) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - SSH.command('cp /opt/ltebox/var/log/*Log.0 .', '\$', 5) - SSH.command('zip mme.log.zip mmeLog.0 s1apcLog.0 s1apsLog.0 s11cLog.0 libLog.0 s1apCodecLog.0', '\$', 60) - else: - logging.error('This option should not occur!') - SSH.close() - - def LogCollectSPGW(self): - SSH.open(self.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword) - SSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - SSH.command('rm -f spgw.log.zip', '\$', 5) - if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - SSH.command('zip spgw.log.zip spgw*.log', '\$', 60) - SSH.command('echo ' + self.EPCPassword + ' | sudo -S rm spgw*.log', '\$', 5) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - SSH.command('cp /opt/ltebox/var/log/xGwLog.0 .', '\$', 5) - SSH.command('zip spgw.log.zip xGwLog.0', '\$', 60) - else: - logging.error('This option should not occur!') - SSH.close() - """ + def LogCollectOAIUE(self): SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) SSH.command('cd ' + self.UESourceCodePath, '\$', 5) @@ -4448,50 +4167,6 @@ class OaiCiTest(): logging.debug('\u001B[1m' + self.desc + '\u001B[0m') logging.debug('\u001B[1m----------------------------------------\u001B[0m') -#----------------------------------------------------------- -# Usage() -#----------------------------------------------------------- -def Usage(): - print('----------------------------------------------------------------------------------------------------------------------') - print('main.py Ver:' + Version) - print('----------------------------------------------------------------------------------------------------------------------') - print('Usage: python main.py [options]') - print(' --help Show this help.') - print(' --mode=[Mode]') - print(' TesteNB') - print(' InitiateHtml, FinalizeHtml') - print(' TerminateeNB, TerminateUE, TerminateHSS, TerminateMME, TerminateSPGW') - print(' LogCollectBuild, LogCollecteNB, LogCollectHSS, LogCollectMME, LogCollectSPGW, LogCollectPing, LogCollectIperf') - print('---------------------------------------------------------------------------------------------------- Git Options --') - print(' --ranRepository=[OAI RAN Repository URL]') - print(' --ranBranch=[OAI RAN Repository Branch]') - print(' --ranCommitID=[OAI RAN Repository Commit SHA-1]') - print(' --ranAllowMerge=[Allow Merge Request (with target branch) (true or false)]') - print(' --ranTargetBranch=[Target Branch in case of a Merge Request]') - print('--------------------------------------------------------------------------------------------- eNB Server Options --') - print(' --eNBIPAddress=[eNB\'s IP Address]') - print(' --eNBUserName=[eNB\'s Login User Name]') - print(' --eNBPassword=[eNB\'s Login Password]') - print(' --eNBSourceCodePath=[eNB\'s Source Code Path]') - print('------------------------------------------------------------------------------------------ OAI UE Server Options --') - print(' --UEIPAddress=[UE\'s IP Address]') - print(' --UEUserName=[UE\'s Login User Name]') - print(' --UEPassword=[UE\'s Login Password]') - print(' --UESourceCodePath=[UE\'s Source Code Path]') - print('--------------------------------------------------------------------------------------------- EPC Server Options --') - print(' --EPCIPAddress=[EPC\'s IP Address]') - print(' --EPCUserName=[EPC\'s Login User Name]') - print(' --EPCPassword=[EPC\'s Login Password]') - print(' --EPCSourceCodePath=[EPC\'s Source Code Path]') - print(' --EPCType=[EPC\'s Type: OAI or ltebox or OAI-Rel14-CUPS]') - print('--------------------------------------------------------------------------------------------- ABD Server Options --') - print(' --ADBIPAddress=[ADB\'s IP Address]') - print(' --ADBUserName=[ADB\'s Login User Name]') - print(' --ADBPassword=[ADB\'s Login Password]') - print('----------------------------------------------------------------------------------------------------------------------') - print(' --XMLTestFile=[XML Test File to be run]') - print('----------------------------------------------------------------------------------------------------------------------') - def CheckClassValidity(action,id): if action != 'Build_eNB' and action != 'WaitEndBuild_eNB' and action != 'Initialize_eNB' and action != 'Terminate_eNB' and action != 'Initialize_UE' and action != 'Terminate_UE' and action != 'Attach_UE' and action != 'Detach_UE' and action != 'Build_OAI_UE' and action != 'Initialize_OAI_UE' and action != 'Terminate_OAI_UE' and action != 'DataDisable_UE' and action != 'DataEnable_UE' and action != 'CheckStatusUE' and action != 'Ping' and action != 'Iperf' and action != 'Reboot_UE' and action != 'Initialize_FlexranCtrl' and action != 'Terminate_FlexranCtrl' and action != 'Initialize_HSS' and action != 'Terminate_HSS' and action != 'Initialize_MME' and action != 'Terminate_MME' and action != 'Initialize_SPGW' and action != 'Terminate_SPGW' and action != 'Initialize_CatM_module' and action != 'Terminate_CatM_module' and action != 'Attach_CatM_module' and action != 'Detach_CatM_module' and action != 'Ping_CatM_module' and action != 'IdleSleep' and action != 'Perform_X2_Handover': logging.debug('ERROR: test-case ' + id + ' has wrong class ' + action) @@ -4672,7 +4347,7 @@ cwd = os.getcwd() while len(argvs) > 1: myArgv = argvs.pop(1) # 0th is this file's name if re.match('^\-\-help$', myArgv, re.IGNORECASE): - Usage() + GenericHelp(Version) sys.exit(0) elif re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE) @@ -4751,23 +4426,23 @@ while len(argvs) > 1: CiTestObj.eNB2SourceCodePath = matchReg.group(1) elif re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE) - EPC.EPCIPAddress = matchReg.group(1) + EPC.SetIPAddress(matchReg.group(1)) elif re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE) CiTestObj.EPCBranch = matchReg.group(1) elif re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE) - EPC.EPCUserName = matchReg.group(1) + EPC.SetUserName(matchReg.group(1)) elif re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE) - EPC.EPCPassword = matchReg.group(1) + EPC.SetPassword(matchReg.group(1)) elif re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE) - EPC.EPCSourceCodePath = matchReg.group(1) + EPC.SetSourceCodePath(matchReg.group(1)) elif re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE) if re.match('OAI', matchReg.group(1), re.IGNORECASE) or re.match('ltebox', matchReg.group(1), re.IGNORECASE) or re.match('OAI-Rel14-CUPS', matchReg.group(1), re.IGNORECASE): - EPC.EPCType = matchReg.group(1) + EPC.SetType(matchReg.group(1)) else: sys.exit('Invalid EPC Type: ' + matchReg.group(1) + ' -- (should be OAI or ltebox or OAI-Rel14-CUPS)') elif re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE): @@ -4810,12 +4485,12 @@ while len(argvs) > 1: if ((finalStatus == 'true') or (finalStatus == 'True')): CiTestObj.finalStatus = True else: - Usage() + GenericHelp(Version) sys.exit('Invalid Parameter: ' + myArgv) if re.match('^TerminateeNB$', mode, re.IGNORECASE): if CiTestObj.eNBIPAddress == '' or CiTestObj.eNBUserName == '' or CiTestObj.eNBPassword == '': - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') CiTestObj.eNB_serverId = '0' CiTestObj.eNB_instance = '0' @@ -4823,74 +4498,74 @@ if re.match('^TerminateeNB$', mode, re.IGNORECASE): CiTestObj.TerminateeNB() elif re.match('^TerminateUE$', mode, re.IGNORECASE): if (CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == ''): - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') signal.signal(signal.SIGUSR1, receive_signal) CiTestObj.TerminateUE() elif re.match('^TerminateOAIUE$', mode, re.IGNORECASE): if CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '': - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') signal.signal(signal.SIGUSR1, receive_signal) CiTestObj.TerminateOAIUE() elif re.match('^TerminateHSS$', mode, re.IGNORECASE): - if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCType == '' or EPC.EPCSourceCodePath == '': - Usage() + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + GenericHelp(Version) sys.exit('Insufficient Parameter') CiTestObj.TerminateHSS() elif re.match('^TerminateMME$', mode, re.IGNORECASE): - if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCType == '' or EPC.EPCSourceCodePath == '': - Usage() + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + GenericHelp(Version) sys.exit('Insufficient Parameter') CiTestObj.TerminateMME() elif re.match('^TerminateSPGW$', mode, re.IGNORECASE): - if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCType == '' or EPC.EPCSourceCodePath == '': - Usage() + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + GenericHelp(Version) sys.exit('Insufficient Parameter') CiTestObj.TerminateSPGW() elif re.match('^LogCollectBuild$', mode, re.IGNORECASE): if (CiTestObj.eNBIPAddress == '' or CiTestObj.eNBUserName == '' or CiTestObj.eNBPassword == '' or CiTestObj.eNBSourceCodePath == '') and (CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == ''): - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') CiTestObj.LogCollectBuild() elif re.match('^LogCollecteNB$', mode, re.IGNORECASE): if CiTestObj.eNBIPAddress == '' or CiTestObj.eNBUserName == '' or CiTestObj.eNBPassword == '' or CiTestObj.eNBSourceCodePath == '': - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') CiTestObj.LogCollecteNB() elif re.match('^LogCollectHSS$', mode, re.IGNORECASE): - if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCType == '' or EPC.EPCSourceCodePath == '': - Usage() + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + GenericHelp(Version) sys.exit('Insufficient Parameter') EPC.LogCollectHSS() elif re.match('^LogCollectMME$', mode, re.IGNORECASE): - if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCType == '' or EPC.EPCSourceCodePath == '': - Usage() + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + GenericHelp(Version) sys.exit('Insufficient Parameter') EPC.LogCollectMME() elif re.match('^LogCollectSPGW$', mode, re.IGNORECASE): - if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCType == '' or EPC.EPCSourceCodePath == '': - Usage() + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + GenericHelp(Version) sys.exit('Insufficient Parameter') EPC.LogCollectSPGW() elif re.match('^LogCollectPing$', mode, re.IGNORECASE): - if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCSourceCodePath == '': - Usage() + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '': + GenericHelp(Version) sys.exit('Insufficient Parameter') CiTestObj.LogCollectPing() elif re.match('^LogCollectIperf$', mode, re.IGNORECASE): - if EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCSourceCodePath == '': - Usage() + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '': + GenericHelp(Version) sys.exit('Insufficient Parameter') CiTestObj.LogCollectIperf() elif re.match('^LogCollectOAIUE$', mode, re.IGNORECASE): if CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == '': - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') CiTestObj.LogCollectOAIUE() elif re.match('^InitiateHtml$', mode, re.IGNORECASE): if (CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == ''): - Usage() + GenericHelp(Version) sys.exit('Insufficient Parameter') count = 0 foundCount = 0 @@ -4915,16 +4590,19 @@ elif re.match('^FinalizeHtml$', mode, re.IGNORECASE): CiTestObj.CreateHtmlFooter(CiTestObj.finalStatus) elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re.IGNORECASE): if re.match('^TesteNB$', mode, re.IGNORECASE): - if CiTestObj.eNBIPAddress == '' or CiTestObj.ranRepository == '' or CiTestObj.ranBranch == '' or CiTestObj.eNBUserName == '' or CiTestObj.eNBPassword == '' or CiTestObj.eNBSourceCodePath == '' or EPC.EPCIPAddress == '' or EPC.EPCUserName == '' or EPC.EPCPassword == '' or EPC.EPCType == '' or EPC.EPCSourceCodePath == '' or CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == '': - Usage() + if CiTestObj.eNBIPAddress == '' or CiTestObj.ranRepository == '' or CiTestObj.ranBranch == '' or CiTestObj.eNBUserName == '' or CiTestObj.eNBPassword == '' or CiTestObj.eNBSourceCodePath == '' or EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '' or CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == '': + GenericHelp(Version) + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '' or EPC.GetType() == '': + EPCSrvHelp(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), EPC.GetSourceCodePath(), EPC.GetType()) + # Gabriele: other if conditions relevant to eNB etc. to be added sys.exit('Insufficient Parameter') - if (EPC.EPCIPAddress != '') and (EPC.EPCIPAddress != 'none'): - SSH.copyout(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword, cwd + "/tcp_iperf_stats.awk", "/tmp") - SSH.copyout(EPC.EPCIPAddress, EPC.EPCUserName, EPC.EPCPassword, cwd + "/active_net_interfaces.awk", "/tmp") + if (EPC.GetIPAddress() != '') and (EPC.GetIPAddress() != 'none'): + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), cwd + "/tcp_iperf_stats.awk", "/tmp") + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), cwd + "/active_net_interfaces.awk", "/tmp") else: if CiTestObj.UEIPAddress == '' or CiTestObj.ranRepository == '' or CiTestObj.ranBranch == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == '': - Usage() + GenericHelp(Version) sys.exit('UE: Insufficient Parameter') #read test_case_list.xml file @@ -4969,7 +4647,7 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re else: logging.debug('ERROR: requested test is invalidly formatted: ' + test) sys.exit(1) - if (EPC.EPCIPAddress != '') and (EPC.EPCIPAddress != 'none'): + if (EPC.GetIPAddress() != '') and (EPC.GetIPAddress() != 'none'): CiTestObj.CheckFlexranCtrlInstallation() #get the list of tests to be done @@ -5087,6 +4765,6 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re logging.info('Testsuite passed after ' + str(CiTestObj.FailReportCnt) + ' time(s)') CiTestObj.CreateHtmlTabFooter(True) else: - Usage() + GenericHelp(Version) sys.exit('Invalid mode') sys.exit(0) From 10b046f5b8c0110b69c37c60fdb0daebeb4ec27a Mon Sep 17 00:00:00 2001 From: laurent Date: Mon, 3 Feb 2020 15:25:50 +0100 Subject: [PATCH 084/240] merge continue: take develop latest commits, fix compilation for test tools --- openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c | 2 +- openair1/PHY/LTE_TRANSPORT/pucch.c | 2 +- openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c | 2 +- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 2 +- openair1/PHY/NR_UE_TRANSPORT/nr_prach.c | 2 +- openair1/PHY/TOOLS/tools_defs.h | 8 ++++++++ openair1/SCHED_NR_UE/phy_frame_config_nr.c | 2 +- openair1/SIMULATION/LTE_PHY/dlsim.c | 6 +++--- openair1/SIMULATION/LTE_PHY/ulsim.c | 2 +- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 2 +- openair2/LAYER2/RLC/rlc.h | 4 ++-- 11 files changed, 21 insertions(+), 13 deletions(-) diff --git a/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c b/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c index 2e4f3e6036..880c056578 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_ue_measurements.c @@ -1029,7 +1029,7 @@ void lte_ue_measurements(PHY_VARS_UE *ue, int N_RB_DL = frame_parms->N_RB_DL; - int rank_tm3_tm4; + int rank_tm3_tm4=-1; ue->measurements.nb_antennas_rx = frame_parms->nb_antennas_rx; diff --git a/openair1/PHY/LTE_TRANSPORT/pucch.c b/openair1/PHY/LTE_TRANSPORT/pucch.c index 8c19f44d2f..e3f741629c 100644 --- a/openair1/PHY/LTE_TRANSPORT/pucch.c +++ b/openair1/PHY/LTE_TRANSPORT/pucch.c @@ -180,7 +180,7 @@ uint16_t pucchfmt3_ChannelEstimation( int16_t SubCarrierDeMapData[NB_ANTENNAS_RX uint16_t n3_pucch_array[NUMBER_OF_UE_MAX], uint8_t ncs_cell[20][7] ) { uint32_t aa, symNo, k, slotNo, sym, i, j; - int16_t np, np_n, ip_ind; + int16_t np, np_n, ip_ind=-1; //int16_t npucch_sf; int16_t calctmp[2]; int16_t BsCshData[NB_ANTENNAS_RX][D_NSYM1SF][D_NSC1RB][2]; diff --git a/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c b/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c index 49fa484c26..a1b7898a2d 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/prach_ue.c @@ -65,7 +65,7 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1 uint16_t *prach_root_sequence_map; uint16_t preamble_offset,preamble_shift; uint16_t preamble_index0,n_shift_ra,n_shift_ra_bar; - uint16_t d_start,numshift; + uint16_t d_start=-1,numshift; uint8_t prach_fmt = get_prach_fmt(prach_ConfigIndex,frame_type); //uint8_t Nsp=2; //uint8_t f_ra,t1_ra; diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index 69077f0276..0fabf8c639 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -2070,7 +2070,7 @@ uint16_t nr_dci_format_size (PHY_VARS_NR_UE *ue, dl_res_alloc_type_1 = 1; } - uint8_t n_bits_freq_dom_res_assign_dl=0,n_dl_RGB_tmp; + uint8_t n_bits_freq_dom_res_assign_dl=0,n_dl_RGB_tmp=-1; if (dl_res_alloc_type_0 == 1) { // implementation of Table 5.1.2.2.1-1 TC 38.214 subclause 6.1.2.2.1 // config1: PDSCH-Config IE contains rbg-Size ENUMERATED {config1, config2} diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c index f4f4ac8926..d7a0aaeca6 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c @@ -585,7 +585,7 @@ int32_t generate_nr_prach( PHY_VARS_NR_UE *ue, uint8_t eNB_id, uint8_t subframe, uint16_t *prach_root_sequence_map; uint16_t preamble_offset,preamble_shift; uint16_t preamble_index0,n_shift_ra,n_shift_ra_bar; - uint16_t d_start,numshift; + uint16_t d_start=-1,numshift; uint16_t prach_fmt = get_nr_prach_fmt(prach_ConfigIndex); //uint8_t Nsp=2; diff --git a/openair1/PHY/TOOLS/tools_defs.h b/openair1/PHY/TOOLS/tools_defs.h index 57f5a782de..5ba956fd39 100644 --- a/openair1/PHY/TOOLS/tools_defs.h +++ b/openair1/PHY/TOOLS/tools_defs.h @@ -29,6 +29,10 @@ */ +#ifdef __cplusplus +extern "C" { +#endif + #include #include "PHY/sse_intrin.h" @@ -428,4 +432,8 @@ double interp(double x, double *xs, double *ys, int count); int write_output(const char *fname,const char *vname,void *data,int length,int dec,char format); +#ifdef __cplusplus +} +#endif + #endif //__PHY_TOOLS_DEFS__H__ diff --git a/openair1/SCHED_NR_UE/phy_frame_config_nr.c b/openair1/SCHED_NR_UE/phy_frame_config_nr.c index fc1c459ba4..e93eb09b8e 100644 --- a/openair1/SCHED_NR_UE/phy_frame_config_nr.c +++ b/openair1/SCHED_NR_UE/phy_frame_config_nr.c @@ -135,7 +135,7 @@ int set_tdd_config_nr(NR_DL_FRAME_PARMS *frame_parms, int dl_UL_TransmissionPeri void add_tdd_dedicated_configuration_nr(NR_DL_FRAME_PARMS *frame_parms, int slotIndex, int nrofDownlinkSymbols, int nrofUplinkSymbols) { TDD_UL_DL_SlotConfig_t *p_TDD_UL_DL_ConfigDedicated = frame_parms->p_TDD_UL_DL_ConfigDedicated; - TDD_UL_DL_SlotConfig_t *p_previous_TDD_UL_DL_ConfigDedicated; + TDD_UL_DL_SlotConfig_t *p_previous_TDD_UL_DL_ConfigDedicated=NULL; int next = 0; while (p_TDD_UL_DL_ConfigDedicated != NULL) { diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index 6706b0f912..a47a174702 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -515,7 +515,7 @@ int main(int argc, char **argv) { char fname[32],vname[32]; FILE *bler_fd; char bler_fname[256]; - FILE *time_meas_fd; + FILE *time_meas_fd=NULL; char time_meas_fname[256]; // FILE *tikz_fd; // char tikz_fname[256]; @@ -1446,7 +1446,7 @@ int main(int argc, char **argv) { sched_resp.subframe=subframe; sched_resp.frame=proc_eNB->frame_tx; eNB->abstraction_flag=0; - schedule_response(&sched_resp); + schedule_response(&sched_resp, proc_eNB); phy_procedures_eNB_TX(eNB,proc_eNB,1); if (uncoded_ber_bit == NULL) { @@ -1480,7 +1480,7 @@ int main(int argc, char **argv) { TX_req.tx_request_body.number_of_pdus=0; proc_eNB->subframe_tx = subframe+1; sched_resp.subframe=subframe+1; - schedule_response(&sched_resp); + schedule_response(&sched_resp, proc_eNB); phy_procedures_eNB_TX(eNB,proc_eNB,0); ru->proc.tti_tx=(subframe+1)%10; feptx_prec(ru,proc_eNB->frame_tx,subframe+1); diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c index 91592f8ed5..0459109a7c 100644 --- a/openair1/SIMULATION/LTE_PHY/ulsim.c +++ b/openair1/SIMULATION/LTE_PHY/ulsim.c @@ -995,7 +995,7 @@ int main(int argc, char **argv) { srs_flag); sched_resp.subframe=(subframe+6)%10; sched_resp.frame=(1024+eNB->proc.frame_rx+((subframe<4)?-1:0))&1023; - schedule_response(&sched_resp); + schedule_response(&sched_resp, proc_rxtx); ///////////////////// if (abstx) { diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 579f5c6928..59dc1b06c9 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -2067,7 +2067,7 @@ void nr_ue_send_sdu(module_id_t module_idP, if (opt_enabled) { trace_pdu(DIRECTION_DOWNLINK, pduP, pdu_len, module_idP, WS_C_RNTI, - (int) UE_mac_inst[module_idP].cs_RNTI, frameP, ttiP, 0, 0); //subframeP + *UE_mac_inst[module_idP].cs_RNTI, frameP, ttiP, 0, 0); //subframeP LOG_D(OPT, "[UE %d][DLSCH] Frame %d trace pdu for rnti %p with size %d\n", module_idP, frameP, UE_mac_inst[module_idP].cs_RNTI, pdu_len); } diff --git a/openair2/LAYER2/RLC/rlc.h b/openair2/LAYER2/RLC/rlc.h index dfdf527123..b337bcac7e 100644 --- a/openair2/LAYER2/RLC/rlc.h +++ b/openair2/LAYER2/RLC/rlc.h @@ -137,7 +137,7 @@ void (*rlc_rrc_data_ind)( const protocol_ctxt_t *const ctxtP, const rb_id_t rb_idP, const sdu_size_t sdu_sizeP, - const uint8_t *const sduP); + const uint8_t *const sduP) __attribute__ ((aligned(32))); void (*rlc_rrc_data_conf)( const protocol_ctxt_t *const ctxtP, @@ -250,7 +250,7 @@ logical_chan_id_t rlc_mbms_rbid2lcid_eNB[MAX_eNB][NB_RB_MBMS_MAX]; (((hash_key_t)(sESSION_ID)) << 37) | \ (((hash_key_t)(0x0000000000000001)) << 63)) -hash_table_t *rlc_coll_p; +hash_table_t *rlc_coll_p __attribute__ ((aligned(32))); /*! \fn tbs_size_t mac_rlc_serialize_tb (char* bufferP, list_t transport_blocksP) * \brief Serialize a list of transport blocks coming from RLC in order to be processed by MAC. From 255d32389ca51888955457e06d48e89fde8e6498 Mon Sep 17 00:00:00 2001 From: laurent Date: Thu, 6 Feb 2020 11:01:54 +0100 Subject: [PATCH 085/240] real time ok in monolithic cases, phy test tools fixed --- cmake_targets/CMakeLists.txt | 4 +++- common/utils/threadPool/thread-pool.h | 6 +++--- .../nfapi/public_inc/nfapi_nr_interface_scf.h | 1 + openair1/SIMULATION/LTE_PHY/dlsim.c | 4 ++++ openair1/SIMULATION/LTE_PHY/ulsim.c | 4 ++++ targets/RT/USER/lte-softmodem.c | 14 ++++++++++++-- 6 files changed, 27 insertions(+), 6 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index d45f655561..e2c58033d2 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -186,7 +186,7 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath -Wl,${CMAKE_CU # these changes are related to hardcoded path to include .h files set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -g3 -DMALLOC_CHECK_=3") set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS} -g3 -DMALLOC_CHECK_=3 -Og") -set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -Og") +set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -O3") set(GIT_BRANCH "UNKNOWN") set(GIT_COMMIT_HASH "UNKNOWN") @@ -2449,6 +2449,7 @@ add_executable(lte-softmodem ${OPENAIR_TARGETS}/RT/USER/ru_control.c ${OPENAIR_TARGETS}/RT/USER/lte-softmodem.c ${OPENAIR_TARGETS}/RT/USER/lte-softmodem-common.c + ${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c ${OPENAIR2_DIR}/ENB_APP/NB_IoT_interface.c ${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c ${OPENAIR_TARGETS}/COMMON/create_tasks.c @@ -2828,6 +2829,7 @@ foreach(myExe dlsim dlsim_tm7 ulsim pbchsim scansim mbmssim pdcchsim pucchsim pr add_executable(${myExe} ${OPENAIR1_DIR}/SIMULATION/LTE_PHY/${myExe}.c + ${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c ${OPENAIR_DIR}/common/utils/backtrace.c ${OPENAIR_DIR}/common/utils/system.c ${XFORMS_SOURCE} diff --git a/common/utils/threadPool/thread-pool.h b/common/utils/threadPool/thread-pool.h index 9a2681a828..1b59fb1589 100644 --- a/common/utils/threadPool/thread-pool.h +++ b/common/utils/threadPool/thread-pool.h @@ -217,11 +217,11 @@ static inline void pushTpool(tpool_t *t, notifiedFIFO_elt_t *msg) { static inline notifiedFIFO_elt_t *pullTpool(notifiedFIFO_t *responseFifo, tpool_t *t) { notifiedFIFO_elt_t *msg= pullNotifiedFIFO(responseFifo); - + AssertFatal(t->traceFd, "Thread pool used while not initialized"); if (t->measurePerf) msg->returnTime=rdtsc(); - if (t->traceFd >= 0) + if (t->traceFd > 0) if(write(t->traceFd, msg, sizeof(*msg))); return msg; @@ -229,7 +229,7 @@ static inline notifiedFIFO_elt_t *pullTpool(notifiedFIFO_t *responseFifo, tpool_ static inline notifiedFIFO_elt_t *tryPullTpool(notifiedFIFO_t *responseFifo, tpool_t *t) { notifiedFIFO_elt_t *msg= pollNotifiedFIFO(responseFifo); - + AssertFatal(t->traceFd, "Thread pool used while not initialized"); if (msg == NULL) return NULL; diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h index 1eea6474f3..408da13718 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h @@ -11,6 +11,7 @@ #include "stddef.h" #include "nfapi_interface.h" +#include #define NFAPI_NR_MAX_NB_CCE_AGGREGATION_LEVELS 5 #define NFAPI_NR_MAX_NB_TCI_STATES_PDCCH 64 diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index a47a174702..d8ac505d14 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -1266,6 +1266,10 @@ int main(int argc, char **argv) { } L1_rxtx_proc_t *proc_eNB = &eNB->proc.L1_proc; + initTpool("n", &proc_eNB->threadPool, true); + initNotifiedFIFO(&proc_eNB->respEncode); + initNotifiedFIFO(&proc_eNB->respDecode); + proc_eNB->frame_tx=0; if (input_fd==NULL) { diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c index 0459109a7c..34237771aa 100644 --- a/openair1/SIMULATION/LTE_PHY/ulsim.c +++ b/openair1/SIMULATION/LTE_PHY/ulsim.c @@ -793,6 +793,10 @@ int main(int argc, char **argv) { proc_rxtx_ue->frame_rx = (subframe<4)?(proc_rxtx->frame_tx-1):(proc_rxtx->frame_tx); proc_rxtx_ue->subframe_tx = proc_rxtx->subframe_rx; proc_rxtx_ue->subframe_rx = (proc_rxtx->subframe_tx+6)%10; + initTpool("n", &proc_rxtx->threadPool, true); + initNotifiedFIFO(&proc_rxtx->respEncode); + initNotifiedFIFO(&proc_rxtx->respDecode); + printf("Init UL hopping UE\n"); init_ul_hopping(&UE->frame_parms); printf("Init UL hopping eNB\n"); diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 737b7d02b4..a06797ee4b 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -665,9 +665,19 @@ int main ( int argc, char **argv ) if (RC.nb_L1_inst > 0) { printf("Initializing eNB threads single_thread_flag:%d wait_for_sync:%d\n", get_softmodem_params()->single_thread_flag,get_softmodem_params()->wait_for_sync); init_eNB(get_softmodem_params()->single_thread_flag,get_softmodem_params()->wait_for_sync); - // for (inst=0;instproc.L1_proc; + if ( strlen(get_softmodem_params()->threadPoolConfig) > 0 ) + initTpool(get_softmodem_params()->threadPoolConfig, &L1proc->threadPool, true); + else + initTpool("n", &L1proc->threadPool, true); + initNotifiedFIFO(&L1proc->respEncode); + initNotifiedFIFO(&L1proc->respDecode); + } + + } printf("wait_eNBs()\n"); From ee7300f102392d5a6f28206f12fbb5fd43279cb4 Mon Sep 17 00:00:00 2001 From: Gabriele Perrone Date: Thu, 13 Feb 2020 15:11:48 +0100 Subject: [PATCH 086/240] experiment of export of enb classes from main.py to enb.py --- ci-scripts/epc.py | 4 +- ci-scripts/main_enb.py | 4780 +++++++++++++++++++++++++++++++++++ ci-scripts/ran.py | 765 ++++++ ci-scripts/sshconnection.py | 3 +- 4 files changed, 5549 insertions(+), 3 deletions(-) create mode 100644 ci-scripts/main_enb.py create mode 100644 ci-scripts/ran.py diff --git a/ci-scripts/epc.py b/ci-scripts/epc.py index 58a0958d4b..91d722a72f 100644 --- a/ci-scripts/epc.py +++ b/ci-scripts/epc.py @@ -66,8 +66,8 @@ class EPCManagement(): mySSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) logging.debug('\u001B[1m Launching tshark on all interfaces \u001B[0m') EPC_PcapFileName = 'epc_' + self.testCase_id + '.pcap' - mySSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f ' + EPC_PcapFileName, '\$', 5) - mySSH.command('echo $USER; nohup sudo tshark -f "tcp port not 22 and port not 53" -i any -w ' + self.EPCSourceCodePath + '/scripts/' + EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', self.EPCUserName, 5) + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f ' + self.EPC_PcapFileName, '\$', 5) + mySSH.command('echo $USER; nohup sudo tshark -f "tcp port not 22 and port not 53" -i any -w ' + self.EPCSourceCodePath + '/scripts/' + self.EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', self.EPCUserName, 5) mySSH.command('echo ' + self.EPCPassword + ' | sudo -S mkdir -p logs', '\$', 5) mySSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f hss_' + self.testCase_id + '.log logs/hss*.*', '\$', 5) mySSH.command('echo "oai_hss -j /usr/local/etc/oai/hss_rel14.json" > ./my-hss.sh', '\$', 5) diff --git a/ci-scripts/main_enb.py b/ci-scripts/main_enb.py new file mode 100644 index 0000000000..e8c530a70b --- /dev/null +++ b/ci-scripts/main_enb.py @@ -0,0 +1,4780 @@ + +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (the "License"); you may not use this file +# * except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.openairinterface.org/?page_id=698 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# Python for CI of OAI-eNB + COTS-UE +# +# Required Python Version +# Python 3.x +# +# Required Python Package +# pexpect +#--------------------------------------------------------------------- + +#----------------------------------------------------------- +# Version +#----------------------------------------------------------- +Version = '0.1' + +#----------------------------------------------------------- +# Constants +#----------------------------------------------------------- +ALL_PROCESSES_OK = 0 +ENB_PROCESS_FAILED = -1 +ENB_PROCESS_OK = +1 +ENB_PROCESS_SEG_FAULT = -11 +ENB_PROCESS_ASSERTION = -12 +ENB_PROCESS_REALTIME_ISSUE = -13 +ENB_PROCESS_NOLOGFILE_TO_ANALYZE = -14 +ENB_PROCESS_SLAVE_RRU_NOT_SYNCED = -15 +HSS_PROCESS_FAILED = -2 +HSS_PROCESS_OK = +2 +MME_PROCESS_FAILED = -3 +MME_PROCESS_OK = +3 +SPGW_PROCESS_FAILED = -4 +SPGW_PROCESS_OK = +4 +UE_IP_ADDRESS_ISSUE = -5 +OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE = -20 +OAI_UE_PROCESS_COULD_NOT_SYNC = -21 +OAI_UE_PROCESS_ASSERTION = -22 +OAI_UE_PROCESS_FAILED = -23 +OAI_UE_PROCESS_NO_TUNNEL_INTERFACE = -24 +OAI_UE_PROCESS_SEG_FAULT = -25 +OAI_UE_PROCESS_OK = +6 + +UE_STATUS_DETACHED = 0 +UE_STATUS_DETACHING = 1 +UE_STATUS_ATTACHING = 2 +UE_STATUS_ATTACHED = 3 + +X2_HO_REQ_STATE__IDLE = 0 +X2_HO_REQ_STATE__TARGET_RECEIVES_REQ = 1 +X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE = 2 +X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ = 3 +X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK = 10 + +#----------------------------------------------------------- +# Import +#----------------------------------------------------------- +import sys # arg +import re # reg +import pexpect # pexpect +import time # sleep +import os +import subprocess +import xml.etree.ElementTree as ET +import logging +import datetime +import signal +from multiprocessing import Process, Lock, SimpleQueue +logging.basicConfig( + level=logging.DEBUG, + format="[%(asctime)s] %(name)s:%(levelname)s: %(message)s" +) + +#----------------------------------------------------------- +# Class Declaration +#----------------------------------------------------------- +class OaiCiTest(): + def __init__(self): + self.FailReportCnt = 0 + self.prematureExit = False + #self.ranRepository = '' + #self.ranBranch = '' + #RAN.GetranAllowMerge() = False + #self.ranCommitID = '' + #RAN.GetranTargetBranch() = '' + #self.eNBIPAddress = '' + #self.eNBUserName = '' + #self.eNBPassword = '' + #RAN.GeteNBSourceCodePath() = '' + #self.EPCIPAddress = '' + #self.EPCUserName = '' + #self.EPCPassword = '' + #self.eNB1IPAddress = '' + #self.eNB1UserName = '' + #self.eNB1Password = '' + #self.eNB1SourceCodePath = '' + #self.eNB2IPAddress = '' + #self.eNB2UserName = '' + #self.eNB2Password = '' + #self.eNB2SourceCodePath = '' + #self.EPCSourceCodePath = '' + #self.EPCType = '' + #self.EPC_PcapFileName = '' + self.ADBIPAddress = '' + self.ADBUserName = '' + self.ADBPassword = '' + self.ADBCentralized = True + self.testCase_id = '' + self.testXMLfiles = [] + self.nbTestXMLfiles = 0 + self.desc = '' + #RAN.GetBuild_eNB_args() = '' + #self.backgroundBuild = False + #self.backgroundBuildTestId = ['', '', ''] + #self.Build_eNB_forced_workspace_cleanup = False + #RAN.GetInitialize_eNB_args() = '' + self.air_interface = 'lte' + #self.eNB_instance = '' + #self.eNB_serverId = '' + #self.eNBLogFiles = ['', '', ''] + #self.eNBOptions = ['', '', ''] + #self.eNBmbmsEnables = [False, False, False] + #self.eNBstatuses = [-1, -1, -1] + self.ping_args = '' + self.ping_packetloss_threshold = '' + self.iperf_args = '' + self.iperf_packetloss_threshold = '' + self.iperf_profile = '' + self.iperf_options = '' + self.nbMaxUEtoAttach = -1 + self.UEDevices = [] + self.UEDevicesStatus = [] + self.UEDevicesRemoteServer = [] + self.UEDevicesRemoteUser = [] + self.UEDevicesOffCmd = [] + self.UEDevicesOnCmd = [] + self.UEDevicesRebootCmd = [] + self.CatMDevices = [] + self.UEIPAddresses = [] + self.htmlFile = '' + self.htmlHeaderCreated = False + self.htmlFooterCreated = False + self.htmlUEConnected = -1 + self.htmleNBFailureMsg = '' + self.htmlUEFailureMsg = '' + self.picocom_closure = False + self.idle_sleep_time = 0 + self.x2_ho_options = 'network' + self.x2NbENBs = 0 + self.x2ENBBsIds = [] + self.x2ENBConnectedUEs = [] + self.htmlTabRefs = [] + self.htmlTabNames = [] + self.htmlTabIcons = [] + self.repeatCounts = [] + self.finalStatus = False + self.OsVersion = '' + self.KernelVersion = '' + self.UhdVersion = '' + self.UsrpBoard = '' + self.CpuNb = '' + self.CpuModel = '' + self.CpuMHz = '' + self.UEIPAddress = '' + self.UEUserName = '' + self.UEPassword = '' + self.UE_instance = '' + self.UESourceCodePath = '' + self.UELogFile = '' + self.Build_OAI_UE_args = '' + self.Initialize_OAI_UE_args = '' + self.clean_repository = True + self.flexranCtrlInstalled = False + self.flexranCtrlStarted = False + self.expectedNbOfConnectedUEs = 0 + self.startTime = 0 +''' + def BuildeNB(self): + if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + if self.eNB_serverId == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = RAN.GeteNBSourceCodePath() + elif self.eNB_serverId == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + lSourcePath = self.eNB1SourceCodePath + elif self.eNB_serverId == '2': + lIpAddr = self.eNB2IPAddress + lUserName = self.eNB2UserName + lPassWord = self.eNB2Password + lSourcePath = self.eNB2SourceCodePath + if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + SSH.open(lIpAddr, lUserName, lPassWord) + # Check if we build an 5G-NR gNB or an LTE eNB + result = re.search('--gNB', RAN.GetBuild_eNB_args()) + if result is not None: + self.air_interface = 'nr' + else: + self.air_interface = 'lte' + # Worakround for some servers, we need to erase completely the workspace + if self.Build_eNB_forced_workspace_cleanup: + SSH.command('echo ' + lPassWord + ' | sudo -S rm -Rf ' + lSourcePath, '\$', 15) + # on RedHat/CentOS .git extension is mandatory + result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository) + if result is not None: + full_ran_repo_name = self.ranRepository + else: + full_ran_repo_name = self.ranRepository + '.git' + SSH.command('mkdir -p ' + lSourcePath, '\$', 5) + SSH.command('cd ' + lSourcePath, '\$', 5) + SSH.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + full_ran_repo_name + ' .; else stdbuf -o0 git fetch --prune; fi', '\$', 600) + # Raphael: here add a check if git clone or git fetch went smoothly + SSH.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) + SSH.command('git config user.name "OAI Jenkins"', '\$', 5) + # Checking the BUILD INFO file + if not self.backgroundBuild: + SSH.command('ls *.txt', '\$', 5) + result = re.search('LAST_BUILD_INFO', SSH.getBefore()) + if result is not None: + mismatch = False + SSH.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) + result = re.search(self.ranCommitID, SSH.getBefore()) + if result is None: + mismatch = True + SSH.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) + if (RAN.GetranAllowMerge()): + result = re.search('YES', SSH.getBefore()) + if result is None: + mismatch = True + SSH.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) + if RAN.GetranTargetBranch() == '': + result = re.search('develop', SSH.getBefore()) + else: + result = re.search(RAN.GetranTargetBranch(), SSH.getBefore()) + if result is None: + mismatch = True + else: + result = re.search('NO', SSH.getBefore()) + if result is None: + mismatch = True + if not mismatch: + SSH.close() + self.CreateHtmlTestRow(RAN.GetBuild_eNB_args(), 'OK', ALL_PROCESSES_OK) + return + + SSH.command('echo ' + lPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30) + # if the commit ID is provided use it to point to it + if self.ranCommitID != '': + SSH.command('git checkout -f ' + self.ranCommitID, '\$', 5) + # if the branch is not develop, then it is a merge request and we need to do + # the potential merge. Note that merge conflicts should already been checked earlier + if (RAN.GetranAllowMerge()): + if RAN.GetranTargetBranch() == '': + if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'): + SSH.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) + else: + logging.debug('Merging with the target branch: ' + RAN.GetranTargetBranch()) + SSH.command('git merge --ff origin/' + RAN.GetranTargetBranch() + ' -m "Temporary merge for CI"', '\$', 5) + SSH.command('source oaienv', '\$', 5) + SSH.command('cd cmake_targets', '\$', 5) + SSH.command('mkdir -p log', '\$', 5) + SSH.command('chmod 777 log', '\$', 5) + # no need to remove in log (git clean did the trick) + if self.backgroundBuild: + SSH.command('echo "./build_oai ' + RAN.GetBuild_eNB_args() + '" > ./my-lte-softmodem-build.sh', '\$', 5) + SSH.command('chmod 775 ./my-lte-softmodem-build.sh', '\$', 5) + SSH.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=build_enb_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/compile_oai_enb.log ./my-lte-softmodem-build.sh', '\$', 5) + SSH.close() + self.CreateHtmlTestRow(RAN.GetBuild_eNB_args(), 'OK', ALL_PROCESSES_OK) + self.backgroundBuildTestId[int(self.eNB_instance)] = self.testCase_id + return + SSH.command('stdbuf -o0 ./build_oai ' + RAN.GetBuild_eNB_args() + ' 2>&1 | stdbuf -o0 tee compile_oai_enb.log', 'Bypassing the Tests|build have failed', 1500) + self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.testCase_id) + + def WaitBuildeNBisFinished(self): + if self.eNB_serverId == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = RAN.GeteNBSourceCodePath() + elif self.eNB_serverId == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + lSourcePath = self.eNB1SourceCodePath + elif self.eNB_serverId == '2': + lIpAddr = self.eNB2IPAddress + lUserName = self.eNB2UserName + lPassWord = self.eNB2Password + lSourcePath = self.eNB2SourceCodePath + if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + SSH.open(lIpAddr, lUserName, lPassWord) + count = 40 + buildOAIprocess = True + while (count > 0) and buildOAIprocess: + SSH.command('ps aux | grep --color=never build_ | grep -v grep', '\$', 3) + result = re.search('build_oai', SSH.getBefore()) + if result is None: + buildOAIprocess = False + else: + count -= 1 + time.sleep(30) + self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.backgroundBuildTestId[int(self.eNB_instance)]) + + def checkBuildeNB(self, lIpAddr, lUserName, lPassWord, lSourcePath, testcaseId): + SSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 3) + SSH.command('ls ran_build/build', '\$', 3) + SSH.command('ls ran_build/build', '\$', 3) + if self.air_interface == 'nr': + nodeB_prefix = 'g' + else: + nodeB_prefix = 'e' + buildStatus = True + result = re.search(self.air_interface + '-softmodem', SSH.getBefore()) + if result is None: + buildStatus = False + else: + # Generating a BUILD INFO file + SSH.command('echo "SRC_BRANCH: ' + self.ranBranch + '" > ../LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('echo "SRC_COMMIT: ' + self.ranCommitID + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) + if (RAN.GetranAllowMerge()): + SSH.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2) + if RAN.GetranTargetBranch() == '': + SSH.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2) + else: + SSH.command('echo "TGT_BRANCH: ' + RAN.GetranTargetBranch() + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) + else: + SSH.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('mkdir -p build_log_' + testcaseId, '\$', 5) + SSH.command('mv log/* ' + 'build_log_' + testcaseId, '\$', 5) + SSH.command('mv compile_oai_enb.log ' + 'build_log_' + testcaseId, '\$', 5) + if self.eNB_serverId != '0': + SSH.command('cd cmake_targets', '\$', 5) + SSH.command('if [ -e tmp_build' + testcaseId + '.zip ]; then rm -f tmp_build' + testcaseId + '.zip; fi', '\$', 5) + SSH.command('zip -r -qq tmp_build' + testcaseId + '.zip build_log_' + testcaseId, '\$', 5) + SSH.close() + if (os.path.isfile('./tmp_build' + testcaseId + '.zip')): + os.remove('./tmp_build' + testcaseId + '.zip') + SSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/tmp_build' + testcaseId + '.zip', '.') + if (os.path.isfile('./tmp_build' + testcaseId + '.zip')): + SSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './tmp_build' + testcaseId + '.zip', RAN.GeteNBSourceCodePath() + '/cmake_targets/.') + os.remove('./tmp_build' + testcaseId + '.zip') + SSH.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) + SSH.command('cd ' + RAN.GeteNBSourceCodePath() + '/cmake_targets', '\$', 5) + SSH.command('unzip -qq -DD tmp_build' + testcaseId + '.zip', '\$', 5) + SSH.command('rm -f tmp_build' + testcaseId + '.zip', '\$', 5) + SSH.close() + else: + SSH.close() + + if buildStatus: + logging.info('\u001B[1m Building OAI ' + nodeB_prefix + 'NB Pass\u001B[0m') + self.CreateHtmlTestRow(RAN.GetBuild_eNB_args(), 'OK', ALL_PROCESSES_OK) + else: + logging.error('\u001B[1m Building OAI ' + nodeB_prefix + 'NB Failed\u001B[0m') + self.CreateHtmlTestRow(RAN.GetBuild_eNB_args(), 'KO', ALL_PROCESSES_OK) + self.CreateHtmlTabFooter(False) + sys.exit(1) +''' + def BuildOAIUE(self): + if self.UEIPAddress == '' or RAN.GetranRepository() == '' or RAN.GetranBranch() == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + result = re.search('--nrUE', self.Build_OAI_UE_args) + if result is not None: + RAN.Setair_interface() = 'nr' + ue_prefix = 'NR ' + else: + RAN.Setair_interface() = 'lte' + ue_prefix = '' + result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', RAN.GetranRepository()) + if result is not None: + full_ran_repo_name = RAN.GetranRepository() + else: + full_ran_repo_name = RAN.GetranRepository() + '.git' + SSH.command('mkdir -p ' + self.UESourceCodePath, '\$', 5) + SSH.command('cd ' + self.UESourceCodePath, '\$', 5) + SSH.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + full_ran_repo_name + ' .; else stdbuf -o0 git fetch --prune; fi', '\$', 600) + # here add a check if git clone or git fetch went smoothly + SSH.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) + SSH.command('git config user.name "OAI Jenkins"', '\$', 5) + if self.clean_repository: + SSH.command('ls *.txt', '\$', 5) + result = re.search('LAST_BUILD_INFO', SSH.getBefore()) + if result is not None: + mismatch = False + SSH.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) + result = re.search(RAN.GetranCommitID(), SSH.getBefore()) + if result is None: + mismatch = True + SSH.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) + if (RAN.GetranAllowMerge()): + result = re.search('YES', SSH.getBefore()) + if result is None: + mismatch = True + SSH.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) + if RAN.GetranTargetBranch() == '': + result = re.search('develop', SSH.getBefore()) + else: + result = re.search(RAN.GetranTargetBranch(), SSH.getBefore()) + if result is None: + mismatch = True + else: + result = re.search('NO', SSH.getBefore()) + if result is None: + mismatch = True + if not mismatch: + SSH.close() + self.CreateHtmlTestRow(RAN.GetBuild_eNB_args(), 'OK', ALL_PROCESSES_OK) + return + + SSH.command('echo ' + self.UEPassword + ' | sudo -S git clean -x -d -ff', '\$', 30) + + # if the commit ID is provided use it to point to it + if RAN.GetranCommitID() != '': + SSH.command('git checkout -f ' + RAN.GetranCommitID(), '\$', 5) + # if the branch is not develop, then it is a merge request and we need to do + # the potential merge. Note that merge conflicts should already been checked earlier + if (RAN.GetranAllowMerge()): + if RAN.GetranTargetBranch() == '': + if (RAN.GetranBranch() != 'develop') and (RAN.GetranBranch() != 'origin/develop'): + SSH.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) + else: + logging.debug('Merging with the target branch: ' + RAN.GetranTargetBranch()) + SSH.command('git merge --ff origin/' + RAN.GetranTargetBranch() + ' -m "Temporary merge for CI"', '\$', 5) + SSH.command('source oaienv', '\$', 5) + SSH.command('cd cmake_targets', '\$', 5) + SSH.command('mkdir -p log', '\$', 5) + SSH.command('chmod 777 log', '\$', 5) + # no need to remove in log (git clean did the trick) + SSH.command('stdbuf -o0 ./build_oai ' + self.Build_OAI_UE_args + ' 2>&1 | stdbuf -o0 tee compile_oai_ue.log', 'Bypassing the Tests|build have failed', 600) + SSH.command('ls ran_build/build', '\$', 3) + SSH.command('ls ran_build/build', '\$', 3) + buildStatus = True + result = re.search(RAN.Getair_interface() + '-uesoftmodem', SSH.getBefore()) + if result is None: + buildStatus = False + SSH.command('mkdir -p build_log_' + self.testCase_id, '\$', 5) + SSH.command('mv log/* ' + 'build_log_' + self.testCase_id, '\$', 5) + SSH.command('mv compile_oai_ue.log ' + 'build_log_' + self.testCase_id, '\$', 5) + if buildStatus: + # Generating a BUILD INFO file + SSH.command('echo "SRC_BRANCH: ' + RAN.GetranBranch() + '" > ../LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('echo "SRC_COMMIT: ' + RAN.GetranCommitID() + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) + if (RAN.GetranAllowMerge): + SSH.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2) + if RAN.GetranTargetBranch() == '': + SSH.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2) + else: + SSH.command('echo "TGT_BRANCH: ' + RAN.GetranTargetBranch() + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) + else: + SSH.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) + SSH.close() + self.CreateHtmlTestRow(self.Build_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE') + else: + SSH.close() + logging.error('\u001B[1m Building OAI UE Failed\u001B[0m') + self.CreateHtmlTestRow(self.Build_OAI_UE_args, 'KO', ALL_PROCESSES_OK, 'OAI UE') + self.CreateHtmlTabFooter(False) + sys.exit(1) + + def CheckFlexranCtrlInstallation(self): + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '': + return + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('ls -ls /opt/flexran_rtc/*/rt_controller', '\$', 5) + result = re.search('/opt/flexran_rtc/build/rt_controller', SSH.getBefore()) + if result is not None: + self.flexranCtrlInstalled = True + logging.debug('Flexran Controller is installed') + SSH.close() + + def InitializeFlexranCtrl(self): + if self.flexranCtrlInstalled == False: + return + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('cd /opt/flexran_rtc', '\$', 5) + SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S rm -f log/*.log', '\$', 5) + SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S echo "build/rt_controller -c log_config/basic_log" > ./my-flexran-ctl.sh', '\$', 5) + SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S chmod 755 ./my-flexran-ctl.sh', '\$', 5) + SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S daemon --unsafe --name=flexran_rtc_daemon --chdir=/opt/flexran_rtc -o /opt/flexran_rtc/log/flexranctl_' + self.testCase_id + '.log ././my-flexran-ctl.sh', '\$', 5) + SSH.command('ps -aux | grep --color=never rt_controller', '\$', 5) + result = re.search('rt_controller -c ', SSH.getBefore()) + if result is not None: + logging.debug('\u001B[1m Initialize FlexRan Controller Completed\u001B[0m') + self.flexranCtrlStarted = True + SSH.close() + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) +''' + def InitializeeNB(self): + if self.eNB_serverId == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = RAN.GeteNBSourceCodePath() + elif self.eNB_serverId == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + lSourcePath = self.eNB1SourceCodePath + elif self.eNB_serverId == '2': + lIpAddr = self.eNB2IPAddress + lUserName = self.eNB2UserName + lPassWord = self.eNB2Password + lSourcePath = self.eNB2SourceCodePath + if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + check_eNB = False + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow(RAN.GetInitialize_eNB_args(), 'KO', pStatus) + self.CreateHtmlTabFooter(False) + sys.exit(1) + # If tracer options is on, running tshark on EPC side and capture traffic b/ EPC and eNB + result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args())) + if result is not None: + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('ip addr show | awk -f /tmp/active_net_interfaces.awk | egrep -v "lo|tun"', '\$', 5) + result = re.search('interfaceToUse=(?P[a-zA-Z0-9\-\_]+)done', SSH.getBefore()) + if result is not None: + eth_interface = result.group('eth_interface') + logging.debug('\u001B[1m Launching tshark on interface ' + eth_interface + '\u001B[0m') + EPC.EPC_PcapFileName = 'enb_' + self.testCase_id + '_s1log.pcap' + SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S rm -f /tmp/' + EPC.EPC_PcapFileName , '\$', 5) + SSH.command('echo $USER; nohup sudo tshark -f "host ' + lIpAddr +'" -i ' + eth_interface + ' -w /tmp/' + EPC.EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', EPC.GetUserName(), 5) + SSH.close() + SSH.open(lIpAddr, lUserName, lPassWord) + SSH.command('cd ' + lSourcePath, '\$', 5) + # Initialize_eNB_args usually start with -O and followed by the location in repository + full_config_file = RAN.GetInitialize_eNB_args().replace('-O ','') + extra_options = '' + extIdx = full_config_file.find('.conf') + if (extIdx > 0): + extra_options = full_config_file[extIdx + 5:] + # if tracer options is on, compiling and running T Tracer + result = re.search('T_stdout', str(extra_options)) + if result is not None: + logging.debug('\u001B[1m Compiling and launching T Tracer\u001B[0m') + SSH.command('cd common/utils/T/tracer', '\$', 5) + SSH.command('make', '\$', 10) + SSH.command('echo $USER; nohup ./record -d ../T_messages.txt -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.raw -ON -off VCD -off HEAVY -off LEGACY_GROUP_TRACE -off LEGACY_GROUP_DEBUG > ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.log 2>&1 &', lUserName, 5) + SSH.command('cd ' + lSourcePath, '\$', 5) + full_config_file = full_config_file[:extIdx + 5] + config_path, config_file = os.path.split(full_config_file) + else: + sys.exit('Insufficient Parameter') + ci_full_config_file = config_path + '/ci-' + config_file + rruCheck = False + result = re.search('^rru|^rcc|^du.band', str(config_file)) + if result is not None: + rruCheck = True + # do not reset board twice in IF4.5 case + result = re.search('^rru|^enb|^du.band', str(config_file)) + if result is not None: + SSH.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 60) + result = re.search('type: b200', SSH.getBefore()) + if result is not None: + logging.debug('Found a B2xx device --> resetting it') + SSH.command('echo ' + lPassWord + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10) + # Reloading FGPA bin firmware + SSH.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 60) + # Make a copy and adapt to EPC / eNB IP addresses + SSH.command('cp ' + full_config_file + ' ' + ci_full_config_file, '\$', 5) + SSH.command('sed -i -e \'s/CI_MME_IP_ADDR/' + EPC.GetIPAddress() + '/\' ' + ci_full_config_file, '\$', 2); + SSH.command('sed -i -e \'s/CI_ENB_IP_ADDR/' + lIpAddr + '/\' ' + ci_full_config_file, '\$', 2); + SSH.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2); + SSH.command('sed -i -e \'s/CI_RRU1_IP_ADDR/' + self.eNB1IPAddress + '/\' ' + ci_full_config_file, '\$', 2); + SSH.command('sed -i -e \'s/CI_RRU2_IP_ADDR/' + self.eNB2IPAddress + '/\' ' + ci_full_config_file, '\$', 2); + if self.flexranCtrlInstalled and self.flexranCtrlStarted: + SSH.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "yes";/\' ' + ci_full_config_file, '\$', 2); + else: + SSH.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "no";/\' ' + ci_full_config_file, '\$', 2); + self.eNBmbmsEnables[int(self.eNB_instance)] = False + SSH.command('grep enable_enb_m2 ' + ci_full_config_file, '\$', 2); + result = re.search('yes', SSH.getBefore()) + if result is not None: + self.eNBmbmsEnables[int(self.eNB_instance)] = True + logging.debug('\u001B[1m MBMS is enabled on this eNB\u001B[0m') + result = re.search('noS1', str(RAN.GetInitialize_eNB_args())) + eNBinNoS1 = False + if result is not None: + eNBinNoS1 = True + logging.debug('\u001B[1m eNB is in noS1 configuration \u001B[0m') + # Launch eNB with the modified config file + SSH.command('source oaienv', '\$', 5) + SSH.command('cd cmake_targets', '\$', 5) + SSH.command('echo "ulimit -c unlimited && ./ran_build/build/' + self.air_interface + '-softmodem -O ' + lSourcePath + '/' + ci_full_config_file + extra_options + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + SSH.command('chmod 775 ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + SSH.command('echo ' + lPassWord + ' | sudo -S rm -Rf enb_' + self.testCase_id + '.log', '\$', 5) + SSH.command('hostnamectl','\$', 5) + result = re.search('CentOS Linux 7', SSH.getBefore()) + if result is not None: + SSH.command('echo $USER; nohup sudo ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh > ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log 2>&1 &', lUserName, 10) + else: + SSH.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=enb' + str(self.eNB_instance) + '_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + self.eNBLogFiles[int(self.eNB_instance)] = 'enb_' + self.testCase_id + '.log' + if extra_options != '': + self.eNBOptions[int(self.eNB_instance)] = extra_options + time.sleep(6) + doLoop = True + loopCounter = 20 + enbDidSync = False + while (doLoop): + loopCounter = loopCounter - 1 + if (loopCounter == 0): + # In case of T tracer recording, we may need to kill it + result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args())) + if result is not None: + SSH.command('killall --signal SIGKILL record', '\$', 5) + SSH.close() + doLoop = False + logging.error('\u001B[1;37;41m eNB logging system did not show got sync! \u001B[0m') + self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'KO', ALL_PROCESSES_OK) + # In case of T tracer recording, we need to kill tshark on EPC side + result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args())) + if result is not None: + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + logging.debug('\u001B[1m Stopping tshark \u001B[0m') + SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) + if EPC.EPC_PcapFileName != '': + time.sleep(0.5) + SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S chmod 666 /tmp/' + EPC.EPC_PcapFileName , '\$', 5) + SSH.close() + time.sleep(1) + if EPC.EPC_PcapFileName != '': + copyin_res = SSH.copyin(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), '/tmp/' + EPC.EPC_PcapFileName , '.') + if (copyin_res == 0): + SSH.copyout(lIpAddr, lUserName, lPassWord, EPC.EPC_PcapFileName , lSourcePath + '/cmake_targets/.') + self.prematureExit = True + return + else: + SSH.command('stdbuf -o0 cat enb_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync|Starting"', '\$', 4) + if rruCheck: + result = re.search('wait RUs', SSH.getBefore()) + else: + result = re.search('got sync|Starting F1AP at CU', SSH.getBefore()) + if result is None: + time.sleep(6) + else: + doLoop = False + enbDidSync = True + time.sleep(10) + + if enbDidSync and eNBinNoS1: + SSH.command('ifconfig oaitun_enb1', '\$', 4) + SSH.command('ifconfig oaitun_enb1', '\$', 4) + result = re.search('inet addr:1|inet 1', SSH.getBefore()) + if result is not None: + logging.debug('\u001B[1m oaitun_enb1 interface is mounted and configured\u001B[0m') + else: + logging.error('\u001B[1m oaitun_enb1 interface is either NOT mounted or NOT configured\u001B[0m') + if self.eNBmbmsEnables[int(self.eNB_instance)]: + SSH.command('ifconfig oaitun_enm1', '\$', 4) + result = re.search('inet addr', SSH.getBefore()) + if result is not None: + logging.debug('\u001B[1m oaitun_enm1 interface is mounted and configured\u001B[0m') + else: + logging.error('\u001B[1m oaitun_enm1 interface is either NOT mounted or NOT configured\u001B[0m') + if enbDidSync: + self.eNBstatuses[int(self.eNB_instance)] = int(self.eNB_serverId) + + SSH.close() + self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'OK', ALL_PROCESSES_OK) + logging.debug('\u001B[1m Initialize eNB Completed\u001B[0m') +''' + def InitializeUE_common(self, device_id, idx): + try: + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + if not self.ADBCentralized: + # Reboot UE + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesRebootCmd[idx], '\$', 60) + # Wait + #time.sleep(60) + # Put in LTE-Mode only + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode 11"\'', '\$', 60) + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode1 11"\'', '\$', 60) + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode2 11"\'', '\$', 60) + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode3 11"\'', '\$', 60) + # enable data service + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) + # we need to do radio on/off cycle to make sure of above changes + # airplane mode off // radio on + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) + #time.sleep(10) + # airplane mode on // radio off + #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + + # normal procedure without reboot + # enable data service + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) + # airplane mode on // radio off + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + SSH.close() + return + # enable data service + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data enable"', '\$', 60) + + # The following commands are deprecated since we no longer work on Android 7+ + # SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell settings put global airplane_mode_on 1', '\$', 10) + # SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true', '\$', 60) + # a dedicated script has to be installed inside the UE + # airplane mode on means call /data/local/tmp/off + if device_id == '84B7N16418004022': + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) + else: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) + #airplane mode off means call /data/local/tmp/on + logging.debug('\u001B[1mUE (' + device_id + ') Initialize Completed\u001B[0m') + SSH.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def InitializeUE(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + multi_jobs = [] + i = 0 + for device_id in self.UEDevices: + p = Process(target = self.InitializeUE_common, args = (device_id,i,)) + p.daemon = True + p.start() + multi_jobs.append(p) + i += 1 + for job in multi_jobs: + job.join() + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def InitializeOAIUE(self): + if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + if RAN.Getair_interface() == 'lte': + result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) + if result is None: + check_eNB = True + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', pStatus) + self.CreateHtmlTabFooter(False) + sys.exit(1) + UE_prefix = '' + else: + UE_prefix = 'NR ' + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + # b2xx_fx3_utils reset procedure + SSH.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 60) + result = re.search('type: b200', SSH.getBefore()) + if result is not None: + logging.debug('Found a B2xx device --> resetting it') + SSH.command('echo ' + self.UEPassword + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10) + # Reloading FGPA bin firmware + SSH.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 30) + result = re.search('type: n3xx', SSH.getBefore()) + if result is not None: + logging.debug('Found a N3xx device --> resetting it') + SSH.command('cd ' + self.UESourceCodePath, '\$', 5) + # Initialize_OAI_UE_args usually start with -C and followed by the location in repository + SSH.command('source oaienv', '\$', 5) + SSH.command('cd cmake_targets/ran_build/build', '\$', 5) + if RAN.Getair_interface() == 'lte': + result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) + # We may have to regenerate the .u* files + if result is None: + SSH.command('ls /tmp/*.sed', '\$', 5) + result = re.search('adapt_usim_parameters', SSH.getBefore()) + if result is not None: + SSH.command('sed -f /tmp/adapt_usim_parameters.sed ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5) + else: + SSH.command('sed -e "s#93#92#" -e "s#8baf473f2f8fd09487cccbd7097c6862#fec86ba6eb707ed08905757b1bb44b8f#" -e "s#e734f8734007d6c5ce7a0508809e7e9c#C42449363BBAD02B66D16BC975D77CC1#" ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf .u*', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S ../../../targets/bin/conf2uedata -c ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf -o .', '\$', 5) + SSH.command('echo "ulimit -c unlimited && ./'+ RAN.Getair_interface() +'-uesoftmodem ' + self.Initialize_OAI_UE_args + '" > ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) + SSH.command('chmod 775 ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log', '\$', 5) + self.UELogFile = 'ue_' + self.testCase_id + '.log' + + # We are now looping several times to hope we really sync w/ an eNB + doOutterLoop = True + outterLoopCounter = 5 + gotSyncStatus = True + fullSyncStatus = True + while (doOutterLoop): + SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets/ran_build/build', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log', '\$', 5) + #use nohup instead of daemon + #SSH.command('echo ' + self.UEPassword + ' | sudo -S -E daemon --inherit --unsafe --name=ue' + str(self.UE_instance) + '_daemon --chdir=' + self.UESourceCodePath + '/cmake_targets/ran_build/build -o ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) + SSH.command('echo $USER; nohup sudo ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh' + ' > ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log ' + ' 2>&1 &', self.UEUserName, 5) + time.sleep(6) + SSH.command('cd ../..', '\$', 5) + doLoop = True + loopCounter = 10 + gotSyncStatus = True + # the 'got sync' message is for the UE threads synchronization + while (doLoop): + loopCounter = loopCounter - 1 + if (loopCounter == 0): + # Here should never occur + logging.error('"got sync" message never showed!') + gotSyncStatus = False + doLoop = False + continue + SSH.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4) + if RAN.Getair_interface() == 'nr': + result = re.search('Starting sync detection', SSH.getBefore()) + else: + result = re.search('got sync', SSH.getBefore()) + if result is None: + time.sleep(10) + else: + doLoop = False + logging.debug('Found "got sync" message!') + if gotSyncStatus == False: + # we certainly need to stop the lte-uesoftmodem process if it is still running! + SSH.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4) + result = re.search('-uesoftmodem', SSH.getBefore()) + if result is not None: + SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT -r *-uesoftmodem', '\$', 4) + time.sleep(3) + continue + if RAN.Getair_interface() == 'nr': + fullSyncStatus = True + doOutterLoop = False + else: + # We are now checking if sync w/ eNB DOES NOT OCCUR + # Usually during the cell synchronization stage, the UE returns with No cell synchronization message + doLoop = True + loopCounter = 10 + while (doLoop): + loopCounter = loopCounter - 1 + if (loopCounter == 0): + # Here we do have a great chance that the UE did cell-sync w/ eNB + doLoop = False + doOutterLoop = False + fullSyncStatus = True + continue + SSH.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4) + result = re.search('No cell synchronization found', SSH.getBefore()) + if result is None: + time.sleep(6) + else: + doLoop = False + fullSyncStatus = False + logging.debug('Found: "No cell synchronization" message! --> try again') + time.sleep(6) + SSH.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4) + result = re.search('lte-uesoftmodem', SSH.getBefore()) + if result is not None: + SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT lte-uesoftmodem', '\$', 4) + outterLoopCounter = outterLoopCounter - 1 + if (outterLoopCounter == 0): + doOutterLoop = False + + if fullSyncStatus and gotSyncStatus and RAN.Getair_interface() == 'lte': + result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) + if result is None: + SSH.command('ifconfig oaitun_ue1', '\$', 4) + SSH.command('ifconfig oaitun_ue1', '\$', 4) + # ifconfig output is different between ubuntu 16 and ubuntu 18 + result = re.search('inet addr:1|inet 1', SSH.getBefore()) + if result is not None: + logging.debug('\u001B[1m oaitun_ue1 interface is mounted and configured\u001B[0m') + tunnelInterfaceStatus = True + else: + logging.debug(SSH.getBefore()) + logging.error('\u001B[1m oaitun_ue1 interface is either NOT mounted or NOT configured\u001B[0m') + tunnelInterfaceStatus = False + if RAN.GeteNBmbmsEnables[0]: + self.command('ifconfig oaitun_uem1', '\$', 4) + result = re.search('inet addr', SSH.getBefore()) + if result is not None: + logging.debug('\u001B[1m oaitun_uem1 interface is mounted and configured\u001B[0m') + tunnelInterfaceStatus = tunnelInterfaceStatus and True + else: + logging.error('\u001B[1m oaitun_uem1 interface is either NOT mounted or NOT configured\u001B[0m') + tunnelInterfaceStatus = False + else: + tunnelInterfaceStatus = True + else: + tunnelInterfaceStatus = True + + SSH.close() + if fullSyncStatus and gotSyncStatus and tunnelInterfaceStatus: + self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE') + logging.debug('\u001B[1m Initialize OAI UE Completed\u001B[0m') + if (self.ADBIPAddress != 'none'): + self.UEDevices = [] + self.UEDevices.append('OAI-UE') + self.UEDevicesStatus = [] + self.UEDevicesStatus.append(UE_STATUS_DETACHED) + else: + if RAN.Getair_interface() == 'lte': + if RAN.GeteNBmbmsEnables[0]: + self.htmlUEFailureMsg = 'oaitun_ue1/oaitun_uem1 interfaces are either NOT mounted or NOT configured' + else: + self.htmlUEFailureMsg = 'oaitun_ue1 interface is either NOT mounted or NOT configured' + self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', OAI_UE_PROCESS_NO_TUNNEL_INTERFACE, 'OAI UE') + else: + self.htmlUEFailureMsg = 'nr-uesoftmodem did NOT synced' + self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', OAI_UE_PROCESS_COULD_NOT_SYNC, 'OAI UE') + logging.error('\033[91mInitialize OAI UE Failed! \033[0m') + self.AutoTerminateUEandeNB() + + def checkDevTTYisUnlocked(self): + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + count = 0 + while count < 5: + SSH.command('echo ' + self.ADBPassword + ' | sudo -S lsof | grep ttyUSB0', '\$', 10) + result = re.search('picocom', SSH.getBefore()) + if result is None: + count = 10 + else: + time.sleep(5) + count = count + 1 + SSH.close() + + def InitializeCatM(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + self.picocom_closure = True + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` + SSH.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) + SSH.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) + time.sleep(1) + # Calling twice AT to clear all buffers + SSH.command('AT', 'OK|ERROR', 5) + SSH.command('AT', 'OK', 5) + # Doing a power cycle + self.command('AT^RESET', 'SIMSTORE,READY', 15) + self.command('AT', 'OK|ERROR', 5) + self.command('AT', 'OK', 5) + self.command('ATE1', 'OK', 5) + # Disabling the Radio + SSH.command('AT+CFUN=0', 'OK', 5) + logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') + # Checking if auto-attach is enabled + SSH.command('AT^AUTOATT?', 'OK', 5) + result = re.search('AUTOATT: (?P[0-9\-]+)', SSH.getBefore()) + if result is not None: + if result.group('state') is not None: + autoAttachState = int(result.group('state')) + if autoAttachState is not None: + if autoAttachState == 0: + SSH.command('AT^AUTOATT=1', 'OK', 5) + logging.debug('\u001B[1m Auto-Attach enabled\u001B[0m') + else: + logging.debug('\u001B[1;37;41m Could not check Auto-Attach! \u001B[0m') + # Force closure of picocom but device might still be locked + SSH.close() + self.picocom_closure = False + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + self.checkDevTTYisUnlocked() + + def TerminateCatM(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + self.picocom_closure = True + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` + SSH.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) + SSH.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) + time.sleep(1) + # Calling twice AT to clear all buffers + SSH.command('AT', 'OK|ERROR', 5) + SSH.command('AT', 'OK', 5) + # Disabling the Radio + SSH.command('AT+CFUN=0', 'OK', 5) + logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') + SSH.close() + self.picocom_closure = False + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + self.checkDevTTYisUnlocked() + + def AttachCatM(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + self.picocom_closure = True + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` + SSH.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) + SSH.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) + time.sleep(1) + # Calling twice AT to clear all buffers + SSH.command('AT', 'OK|ERROR', 5) + SSH.command('AT', 'OK', 5) + # Enabling the Radio + SSH.command('AT+CFUN=1', 'SIMSTORE,READY', 5) + logging.debug('\u001B[1m Cellular Functionality enabled\u001B[0m') + time.sleep(4) + # We should check if we register + count = 0 + attach_cnt = 0 + attach_status = False + while count < 5: + SSH.command('AT+CEREG?', 'OK', 5) + result = re.search('CEREG: 2,(?P[0-9\-]+),', SSH.getBefore()) + if result is not None: + mDataConnectionState = int(result.group('state')) + if mDataConnectionState is not None: + if mDataConnectionState == 1: + count = 10 + attach_status = True + result = re.search('CEREG: 2,1,"(?P[0-9A-Z]+)","(?P[0-9A-Z]+)"', SSH.getBefore()) + if result is not None: + networky = result.group('networky') + networkz = result.group('networkz') + logging.debug('\u001B[1m CAT-M module attached to eNB (' + str(networky) + '/' + str(networkz) + ')\u001B[0m') + else: + logging.debug('\u001B[1m CAT-M module attached to eNB\u001B[0m') + else: + logging.debug('+CEREG: 2,' + str(mDataConnectionState)) + attach_cnt = attach_cnt + 1 + else: + logging.debug(SSH.getBefore()) + attach_cnt = attach_cnt + 1 + count = count + 1 + time.sleep(1) + if attach_status: + SSH.command('AT+CESQ', 'OK', 5) + result = re.search('CESQ: 99,99,255,255,(?P[0-9]+),(?P[0-9]+)', SSH.getBefore()) + if result is not None: + nRSRQ = int(result.group('rsrq')) + nRSRP = int(result.group('rsrp')) + if (nRSRQ is not None) and (nRSRP is not None): + logging.debug(' RSRQ = ' + str(-20+(nRSRQ/2)) + ' dB') + logging.debug(' RSRP = ' + str(-140+nRSRP) + ' dBm') + SSH.close() + self.picocom_closure = False + html_queue = SimpleQueue() + self.checkDevTTYisUnlocked() + if attach_status: + html_cell = '
CAT-M module Attachment Completed in ' + str(attach_cnt+4) + ' seconds'
+			if (nRSRQ is not None) and (nRSRP is not None):
+				html_cell += '\n   RSRQ = ' + str(-20+(nRSRQ/2)) + ' dB'
+				html_cell += '\n   RSRP = ' + str(-140+nRSRP) + ' dBm
' + else: + html_cell += '' + html_queue.put(html_cell) + self.CreateHtmlTestRowQueue('N/A', 'OK', 1, html_queue) + else: + logging.error('\u001B[1m CAT-M module Attachment Failed\u001B[0m') + html_cell = '
CAT-M module Attachment Failed
' + html_queue.put(html_cell) + self.CreateHtmlTestRowQueue('N/A', 'KO', 1, html_queue) + self.AutoTerminateUEandeNB() + + def PingCatM(self): + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + check_eNB = True + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + self.AutoTerminateUEandeNB() + return + try: + statusQueue = SimpleQueue() + lock = Lock() + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('cd ' + EPC.GetSourceCodePath(), '\$', 5) + SSH.command('cd scripts', '\$', 5) + if re.match('OAI', EPC.GetType(), re.IGNORECASE): + logging.debug('Using the OAI EPC HSS: not implemented yet') + self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + self.CreateHtmlTabFooter(False) + sys.exit(1) + else: + SSH.command('egrep --color=never "Allocated ipv4 addr" /opt/ltebox/var/log/xGwLog.0', '\$', 5) + result = re.search('Allocated ipv4 addr: (?P[0-9\.]+) from Pool', SSH.getBefore()) + if result is not None: + moduleIPAddr = result.group('ipaddr') + else: + self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + self.AutoTerminateUEandeNB() + return + ping_time = re.findall("-c (\d+)",str(self.ping_args)) + device_id = 'catm' + ping_status = SSH.command('stdbuf -o0 ping ' + self.ping_args + ' ' + str(moduleIPAddr) + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) + # TIMEOUT CASE + if ping_status < 0: + message = 'Ping with UE (' + str(moduleIPAddr) + ') crashed due to TIMEOUT!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + SSH.close() + self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) + return + result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', SSH.getBefore()) + if result is None: + message = 'Packet Loss Not Found!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + SSH.close() + self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) + return + packetloss = result.group('packetloss') + if float(packetloss) == 100: + message = 'Packet Loss is 100%' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + SSH.close() + self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) + return + result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', SSH.getBefore()) + if result is None: + message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + SSH.close() + self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) + return + rtt_min = result.group('rtt_min') + rtt_avg = result.group('rtt_avg') + rtt_max = result.group('rtt_max') + pal_msg = 'Packet Loss : ' + packetloss + '%' + min_msg = 'RTT(Min) : ' + rtt_min + ' ms' + avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms' + max_msg = 'RTT(Max) : ' + rtt_max + ' ms' + lock.acquire() + logging.debug('\u001B[1;37;44m ping result (' + moduleIPAddr + ') \u001B[0m') + logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') + qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg + packetLossOK = True + if packetloss is not None: + if float(packetloss) > float(self.ping_packetloss_threshold): + qMsg += '\nPacket Loss too high' + logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') + packetLossOK = False + elif float(packetloss) > 0: + qMsg += '\nPacket Loss is not 0%' + logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m') + lock.release() + SSH.close() + html_cell = '
CAT-M module\nIP Address  : ' + moduleIPAddr + '\n' + qMsg + '
' + statusQueue.put(html_cell) + if (packetLossOK): + self.CreateHtmlTestRowQueue(self.ping_args, 'OK', 1, statusQueue) + else: + self.CreateHtmlTestRowQueue(self.ping_args, 'KO', 1, statusQueue) + self.AutoTerminateUEandeNB() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def AttachUE_common(self, device_id, statusQueue, lock, idx): + try: + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + if self.ADBCentralized: + if device_id == '84B7N16418004022': + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/on"', '\$', 60) + else: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60) + else: + # airplane mode off // radio on + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) + time.sleep(2) + max_count = 45 + count = max_count + while count > 0: + if self.ADBCentralized: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry" | grep -m 1 mDataConnectionState', '\$', 15) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\' | grep -m 1 mDataConnectionState', '\$', 60) + result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', SSH.getBefore()) + if result is None: + logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m') + lock.acquire() + statusQueue.put(-1) + statusQueue.put(device_id) + statusQueue.put('mDataConnectionState Not Found!') + lock.release() + break + mDataConnectionState = int(result.group('state')) + if mDataConnectionState == 2: + logging.debug('\u001B[1mUE (' + device_id + ') Attach Completed\u001B[0m') + lock.acquire() + statusQueue.put(max_count - count) + statusQueue.put(device_id) + statusQueue.put('Attach Completed') + lock.release() + break + count = count - 1 + if count == 15 or count == 30: + logging.debug('\u001B[1;30;43m Retry UE (' + device_id + ') Flight Mode Off \u001B[0m') + if self.ADBCentralized: + if device_id == '84B7N16418004022': + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) + else: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + time.sleep(0.5) + if self.ADBCentralized: + if device_id == '84B7N16418004022': + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/on"', '\$', 60) + else: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) + time.sleep(0.5) + logging.debug('\u001B[1mWait UE (' + device_id + ') a second until mDataConnectionState=2 (' + str(max_count-count) + ' times)\u001B[0m') + time.sleep(1) + if count == 0: + logging.debug('\u001B[1;37;41m UE (' + device_id + ') Attach Failed \u001B[0m') + lock.acquire() + statusQueue.put(-1) + statusQueue.put(device_id) + statusQueue.put('Attach Failed') + lock.release() + SSH.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def AttachUE(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + check_eNB = True + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow('N/A', 'KO', pStatus) + self.AutoTerminateUEandeNB() + return + multi_jobs = [] + status_queue = SimpleQueue() + lock = Lock() + nb_ue_to_connect = 0 + for device_id in self.UEDevices: + if (self.nbMaxUEtoAttach == -1) or (nb_ue_to_connect < self.nbMaxUEtoAttach): + self.UEDevicesStatus[nb_ue_to_connect] = UE_STATUS_ATTACHING + p = Process(target = self.AttachUE_common, args = (device_id, status_queue, lock,nb_ue_to_connect,)) + p.daemon = True + p.start() + multi_jobs.append(p) + nb_ue_to_connect = nb_ue_to_connect + 1 + for job in multi_jobs: + job.join() + + if (status_queue.empty()): + self.CreateHtmlTestRow('N/A', 'KO', ALL_PROCESSES_OK) + self.AutoTerminateUEandeNB() + return + else: + attach_status = True + html_queue = SimpleQueue() + while (not status_queue.empty()): + count = status_queue.get() + if (count < 0): + attach_status = False + device_id = status_queue.get() + message = status_queue.get() + if (count < 0): + html_cell = '
UE (' + device_id + ')\n' + message + '
' + else: + html_cell = '
UE (' + device_id + ')\n' + message + ' in ' + str(count + 2) + ' seconds
' + html_queue.put(html_cell) + if (attach_status): + cnt = 0 + while cnt < len(self.UEDevices): + if self.UEDevicesStatus[cnt] == UE_STATUS_ATTACHING: + self.UEDevicesStatus[cnt] = UE_STATUS_ATTACHED + cnt += 1 + self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) + result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args())) + if result is not None: + logging.debug('Waiting 5 seconds to fill up record file') + time.sleep(5) + else: + self.CreateHtmlTestRowQueue('N/A', 'KO', len(self.UEDevices), html_queue) + self.AutoTerminateUEandeNB() + + def DetachUE_common(self, device_id, idx): + try: + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + if self.ADBCentralized: + if device_id == '84B7N16418004022': + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) + else: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + logging.debug('\u001B[1mUE (' + device_id + ') Detach Completed\u001B[0m') + SSH.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def DetachUE(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + check_eNB = True + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow('N/A', 'KO', pStatus) + self.AutoTerminateUEandeNB() + return + multi_jobs = [] + cnt = 0 + for device_id in self.UEDevices: + self.UEDevicesStatus[cnt] = UE_STATUS_DETACHING + p = Process(target = self.DetachUE_common, args = (device_id,cnt,)) + p.daemon = True + p.start() + multi_jobs.append(p) + cnt += 1 + for job in multi_jobs: + job.join() + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args())) + if result is not None: + logging.debug('Waiting 5 seconds to fill up record file') + time.sleep(5) + cnt = 0 + while cnt < len(self.UEDevices): + self.UEDevicesStatus[cnt] = UE_STATUS_DETACHED + cnt += 1 + + def RebootUE_common(self, device_id): + try: + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + previousmDataConnectionStates = [] + # Save mDataConnectionState + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) + result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', SSH.getBefore()) + if result is None: + logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m') + sys.exit(1) + previousmDataConnectionStates.append(int(result.group('state'))) + # Reboot UE + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell reboot', '\$', 10) + time.sleep(60) + previousmDataConnectionState = previousmDataConnectionStates.pop(0) + count = 180 + while count > 0: + count = count - 1 + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) + result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', SSH.getBefore()) + if result is None: + mDataConnectionState = None + else: + mDataConnectionState = int(result.group('state')) + logging.debug('mDataConnectionState = ' + result.group('state')) + if mDataConnectionState is None or (previousmDataConnectionState == 2 and mDataConnectionState != 2): + logging.debug('\u001B[1mWait UE (' + device_id + ') a second until reboot completion (' + str(180-count) + ' times)\u001B[0m') + time.sleep(1) + else: + logging.debug('\u001B[1mUE (' + device_id + ') Reboot Completed\u001B[0m') + break + if count == 0: + logging.debug('\u001B[1;37;41m UE (' + device_id + ') Reboot Failed \u001B[0m') + sys.exit(1) + SSH.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def RebootUE(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + check_eNB = True + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow('N/A', 'KO', pStatus) + self.CreateHtmlTabFooter(False) + sys.exit(1) + multi_jobs = [] + for device_id in self.UEDevices: + p = Process(target = self.RebootUE_common, args = (device_id,)) + p.daemon = True + p.start() + multi_jobs.append(p) + for job in multi_jobs: + job.join() + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def DataDisableUE_common(self, device_id, idx): + try: + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # disable data service + if self.ADBCentralized: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data disable"', '\$', 60) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data disable"\'', '\$', 60) + logging.debug('\u001B[1mUE (' + device_id + ') Disabled Data Service\u001B[0m') + SSH.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def DataDisableUE(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + multi_jobs = [] + i = 0 + for device_id in self.UEDevices: + p = Process(target = self.DataDisableUE_common, args = (device_id,i,)) + p.daemon = True + p.start() + multi_jobs.append(p) + i += 1 + for job in multi_jobs: + job.join() + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def DataEnableUE_common(self, device_id, idx): + try: + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # enable data service + if self.ADBCentralized: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data enable"', '\$', 60) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) + logging.debug('\u001B[1mUE (' + device_id + ') Enabled Data Service\u001B[0m') + SSH.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def DataEnableUE(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + multi_jobs = [] + i = 0 + for device_id in self.UEDevices: + p = Process(target = self.DataEnableUE_common, args = (device_id,i,)) + p.daemon = True + p.start() + multi_jobs.append(p) + i += 1 + for job in multi_jobs: + job.join() + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def GetAllUEDevices(self, terminate_ue_flag): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + if self.ADBCentralized: + SSH.command('adb devices', '\$', 15) + #self.UEDevices = re.findall("\\\\r\\\\n([A-Za-z0-9]+)\\\\tdevice",SSH.getBefore()) + self.UEDevices = re.findall("\\\\r\\\\n([A-Za-z0-9]+)\\\\tdevice",SSH.getBefore()) + SSH.close() + else: + if (os.path.isfile('./phones_list.txt')): + os.remove('./phones_list.txt') + SSH.command('ls /etc/*/phones*.txt', '\$', 5) + result = re.search('/etc/ci/phones_list.txt', SSH.getBefore()) + SSH.close() + if (result is not None) and (len(self.UEDevices) == 0): + SSH.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, '/etc/ci/phones_list.txt', '.') + if (os.path.isfile('./phones_list.txt')): + phone_list_file = open('./phones_list.txt', 'r') + for line in phone_list_file.readlines(): + line = line.strip() + result = re.search('^#', line) + if result is not None: + continue + comma_split = line.split(",") + self.UEDevices.append(comma_split[0]) + self.UEDevicesRemoteServer.append(comma_split[1]) + self.UEDevicesRemoteUser.append(comma_split[2]) + self.UEDevicesOffCmd.append(comma_split[3]) + self.UEDevicesOnCmd.append(comma_split[4]) + self.UEDevicesRebootCmd.append(comma_split[5]) + phone_list_file.close() + + if terminate_ue_flag == False: + if len(self.UEDevices) == 0: + logging.debug('\u001B[1;37;41m UE Not Found! \u001B[0m') + sys.exit(1) + if len(self.UEDevicesStatus) == 0: + cnt = 0 + while cnt < len(self.UEDevices): + self.UEDevicesStatus.append(UE_STATUS_DETACHED) + cnt += 1 + + def GetAllCatMDevices(self, terminate_ue_flag): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + if self.ADBCentralized: + SSH.command('lsusb | egrep "Future Technology Devices International, Ltd FT2232C" | sed -e "s#:.*##" -e "s# #_#g"', '\$', 15) + #self.CatMDevices = re.findall("\\\\r\\\\n([A-Za-z0-9_]+)",SSH.getBefore()) + self.CatMDevices = re.findall("\\\\r\\\\n([A-Za-z0-9_]+)",SSH.getBefore()) + else: + if (os.path.isfile('./modules_list.txt')): + os.remove('./modules_list.txt') + SSH.command('ls /etc/*/modules*.txt', '\$', 5) + result = re.search('/etc/ci/modules_list.txt', SSH.getBefore()) + SSH.close() + if result is not None: + logging.debug('Found a module list file on ADB server') + if terminate_ue_flag == False: + if len(self.CatMDevices) == 0: + logging.debug('\u001B[1;37;41m CAT-M UE Not Found! \u001B[0m') + sys.exit(1) + SSH.close() + + def CheckUEStatus_common(self, lock, device_id, statusQueue, idx): + try: + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + if self.ADBCentralized: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry"', '\$', 15) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\'', '\$', 60) + result = re.search('mServiceState=(?P[0-9]+)', SSH.getBefore()) + serviceState = 'Service State: UNKNOWN' + if result is not None: + lServiceState = int(result.group('serviceState')) + if lServiceState == 3: + serviceState = 'Service State: RADIO_POWERED_OFF' + if lServiceState == 1: + serviceState = 'Service State: OUT_OF_SERVICE' + if lServiceState == 0: + serviceState = 'Service State: IN_SERVICE' + if lServiceState == 2: + serviceState = 'Service State: EMERGENCY_ONLY' + result = re.search('mDataConnectionState=(?P[0-9]+)', SSH.getBefore()) + dataConnectionState = 'Data State: UNKNOWN' + if result is not None: + lDataConnectionState = int(result.group('dataConnectionState')) + if lDataConnectionState == 0: + dataConnectionState = 'Data State: DISCONNECTED' + if lDataConnectionState == 1: + dataConnectionState = 'Data State: CONNECTING' + if lDataConnectionState == 2: + dataConnectionState = 'Data State: CONNECTED' + if lDataConnectionState == 3: + dataConnectionState = 'Data State: SUSPENDED' + result = re.search('mDataConnectionReason=(?P[0-9a-zA-Z_]+)', SSH.getBefore()) + dataConnectionReason = 'Data Reason: UNKNOWN' + if result is not None: + dataConnectionReason = 'Data Reason: ' + result.group('dataConnectionReason') + lock.acquire() + logging.debug('\u001B[1;37;44m Status Check (' + str(device_id) + ') \u001B[0m') + logging.debug('\u001B[1;34m ' + serviceState + '\u001B[0m') + logging.debug('\u001B[1;34m ' + dataConnectionState + '\u001B[0m') + logging.debug('\u001B[1;34m ' + dataConnectionReason + '\u001B[0m') + statusQueue.put(0) + statusQueue.put(device_id) + qMsg = serviceState + '\n' + dataConnectionState + '\n' + dataConnectionReason + statusQueue.put(qMsg) + lock.release() + SSH.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def CheckStatusUE(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + check_eNB = True + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow('N/A', 'KO', pStatus) + self.CreateHtmlTabFooter(False) + sys.exit(1) + multi_jobs = [] + lock = Lock() + status_queue = SimpleQueue() + i = 0 + for device_id in self.UEDevices: + p = Process(target = self.CheckUEStatus_common, args = (lock,device_id,status_queue,i,)) + p.daemon = True + p.start() + multi_jobs.append(p) + i += 1 + for job in multi_jobs: + job.join() + if self.flexranCtrlInstalled and self.flexranCtrlStarted: + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('cd /opt/flexran_rtc', '\$', 5) + SSH.command('curl http://localhost:9999/stats | jq \'.\' > log/check_status_' + self.testCase_id + '.log 2>&1', '\$', 5) + SSH.command('cat log/check_status_' + self.testCase_id + '.log | jq \'.eNB_config[0].UE\' | grep -c rnti | sed -e "s#^#Nb Connected UE = #"', '\$', 5) + result = re.search('Nb Connected UE = (?P[0-9]+)', SSH.getBefore()) + passStatus = True + if result is not None: + nb_ues = int(result.group('nb_ues')) + htmlOptions = 'Nb Connected UE(s) to eNB = ' + str(nb_ues) + logging.debug('\u001B[1;37;44m ' + htmlOptions + ' \u001B[0m') + if self.expectedNbOfConnectedUEs > -1: + if nb_ues != self.expectedNbOfConnectedUEs: + passStatus = False + else: + htmlOptions = 'N/A' + SSH.close() + else: + passStatus = True + htmlOptions = 'N/A' + + if (status_queue.empty()): + self.CreateHtmlTestRow(htmlOptions, 'KO', ALL_PROCESSES_OK) + self.AutoTerminateUEandeNB() + else: + check_status = True + html_queue = SimpleQueue() + while (not status_queue.empty()): + count = status_queue.get() + if (count < 0): + check_status = False + device_id = status_queue.get() + message = status_queue.get() + html_cell = '
UE (' + device_id + ')\n' + message + '
' + html_queue.put(html_cell) + if check_status and passStatus: + self.CreateHtmlTestRowQueue(htmlOptions, 'OK', len(self.UEDevices), html_queue) + else: + self.CreateHtmlTestRowQueue(htmlOptions, 'KO', len(self.UEDevices), html_queue) + self.AutoTerminateUEandeNB() + + def GetAllUEIPAddresses(self): + if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + ue_ip_status = 0 + self.UEIPAddresses = [] + if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): + if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('ifconfig oaitun_ue1', '\$', 4) + result = re.search('inet addr:(?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)|inet (?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)', SSH.getBefore()) + if result is not None: + if result.group('ueipaddress') is not None: + UE_IPAddress = result.group('ueipaddress') + else: + UE_IPAddress = result.group('ueipaddress2') + logging.debug('\u001B[1mUE (' + self.UEDevices[0] + ') IP Address is ' + UE_IPAddress + '\u001B[0m') + self.UEIPAddresses.append(UE_IPAddress) + else: + logging.debug('\u001B[1;37;41m UE IP Address Not Found! \u001B[0m') + ue_ip_status -= 1 + SSH.close() + return ue_ip_status + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + idx = 0 + for device_id in self.UEDevices: + if self.UEDevicesStatus[idx] != UE_STATUS_ATTACHED: + idx += 1 + continue + count = 0 + while count < 4: + if self.ADBCentralized: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "ip addr show | grep rmnet"', '\$', 15) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ip addr show | grep rmnet"\'', '\$', 60) + result = re.search('inet (?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\/[0-9]+[0-9a-zA-Z\.\s]+', SSH.getBefore()) + if result is None: + logging.debug('\u001B[1;37;41m UE IP Address Not Found! \u001B[0m') + time.sleep(1) + count += 1 + else: + count = 10 + if count < 9: + ue_ip_status -= 1 + continue + UE_IPAddress = result.group('ueipaddress') + logging.debug('\u001B[1mUE (' + device_id + ') IP Address is ' + UE_IPAddress + '\u001B[0m') + for ueipaddress in self.UEIPAddresses: + if ueipaddress == UE_IPAddress: + logging.debug('\u001B[1mUE (' + device_id + ') IP Address ' + UE_IPAddress + ': has already been allocated to another device !' + '\u001B[0m') + ue_ip_status -= 1 + continue + self.UEIPAddresses.append(UE_IPAddress) + idx += 1 + SSH.close() + return ue_ip_status + + def ping_iperf_wrong_exit(self, lock, UE_IPAddress, device_id, statusQueue, message): + lock.acquire() + statusQueue.put(-1) + statusQueue.put(device_id) + statusQueue.put(UE_IPAddress) + statusQueue.put(message) + lock.release() + + def Ping_common(self, lock, UE_IPAddress, device_id, statusQueue): + try: + # Launch ping on the EPC side (true for ltebox and old open-air-cn) + # But for OAI-Rel14-CUPS, we launch from python executor + launchFromEpc = True + if re.match('OAI-Rel14-CUPS', EPC.GetType(), re.IGNORECASE): + launchFromEpc = False + ping_time = re.findall("-c (\d+)",str(self.ping_args)) + + if launchFromEpc: + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('cd ' + EPC.GetSourceCodePath(), '\$', 5) + SSH.command('cd scripts', '\$', 5) + ping_status = SSH.command('stdbuf -o0 ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) + else: + cmd = 'ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 > ping_' + self.testCase_id + '_' + device_id + '.log' + message = cmd + '\n' + logging.debug(cmd) + ret = subprocess.run(cmd, shell=True) + ping_status = ret.returncode + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'ping_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('cat ' + EPC.GetSourceCodePath() + '/scripts/ping_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + # TIMEOUT CASE + if ping_status < 0: + message = 'Ping with UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + SSH.close() + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) + return + result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', SSH.getBefore()) + if result is None: + message = 'Packet Loss Not Found!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + SSH.close() + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) + return + packetloss = result.group('packetloss') + if float(packetloss) == 100: + message = 'Packet Loss is 100%' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + SSH.close() + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) + return + result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', SSH.getBefore()) + if result is None: + message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + SSH.close() + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) + return + rtt_min = result.group('rtt_min') + rtt_avg = result.group('rtt_avg') + rtt_max = result.group('rtt_max') + pal_msg = 'Packet Loss : ' + packetloss + '%' + min_msg = 'RTT(Min) : ' + rtt_min + ' ms' + avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms' + max_msg = 'RTT(Max) : ' + rtt_max + ' ms' + lock.acquire() + logging.debug('\u001B[1;37;44m ping result (' + UE_IPAddress + ') \u001B[0m') + logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') + qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg + packetLossOK = True + if packetloss is not None: + if float(packetloss) > float(self.ping_packetloss_threshold): + qMsg += '\nPacket Loss too high' + logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') + packetLossOK = False + elif float(packetloss) > 0: + qMsg += '\nPacket Loss is not 0%' + logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m') + if (packetLossOK): + statusQueue.put(0) + else: + statusQueue.put(-1) + statusQueue.put(device_id) + statusQueue.put(UE_IPAddress) + statusQueue.put(qMsg) + lock.release() + SSH.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def PingNoS1_wrong_exit(self, qMsg): + html_queue = SimpleQueue() + html_cell = '
OAI UE ping result\n' + qMsg + '
' + html_queue.put(html_cell) + self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) + + def PingNoS1(self): + check_eNB = True + check_OAI_UE = True + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + self.AutoTerminateUEandeNB() + return + ping_from_eNB = re.search('oaitun_enb1', str(self.ping_args)) + if ping_from_eNB is not None: + if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + else: + if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + try: + if ping_from_eNB is not None: + SSH.open(RAN.GeteNBIPAddress, RAN.GeteNBUserName, RAN.GeteNBPassword) + SSH.command('cd ' + RAN.GeteNBSourceCodePath() + '/cmake_targets/', '\$', 5) + else: + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets/', '\$', 5) + ping_time = re.findall("-c (\d+)",str(self.ping_args)) + ping_status = SSH.command('stdbuf -o0 ping ' + self.ping_args + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '.log', '\$', int(ping_time[0])*1.5) + # TIMEOUT CASE + if ping_status < 0: + message = 'Ping with OAI UE crashed due to TIMEOUT!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.PingNoS1_wrong_exit(message) + return + result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', SSH.getBefore()) + if result is None: + message = 'Packet Loss Not Found!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.PingNoS1_wrong_exit(message) + return + packetloss = result.group('packetloss') + if float(packetloss) == 100: + message = 'Packet Loss is 100%' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.PingNoS1_wrong_exit(message) + return + result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', SSH.getBefore()) + if result is None: + message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.PingNoS1_wrong_exit(message) + return + rtt_min = result.group('rtt_min') + rtt_avg = result.group('rtt_avg') + rtt_max = result.group('rtt_max') + pal_msg = 'Packet Loss : ' + packetloss + '%' + min_msg = 'RTT(Min) : ' + rtt_min + ' ms' + avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms' + max_msg = 'RTT(Max) : ' + rtt_max + ' ms' + logging.debug('\u001B[1;37;44m OAI UE ping result \u001B[0m') + logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') + logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') + qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg + packetLossOK = True + if packetloss is not None: + if float(packetloss) > float(self.ping_packetloss_threshold): + qMsg += '\nPacket Loss too high' + logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') + packetLossOK = False + elif float(packetloss) > 0: + qMsg += '\nPacket Loss is not 0%' + logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m') + SSH.close() + html_queue = SimpleQueue() + ip_addr = 'TBD' + html_cell = '
OAI UE ping result\n' + qMsg + '
' + html_queue.put(html_cell) + if packetLossOK: + self.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) + else: + self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) + + # copying on the EPC server for logCollection + if ping_from_eNB is not None: + copyin_res = SSH.copyin(RAN.GeteNBIPAddress, RAN.GeteNBUserName, RAN.GeteNBPassword, RAN.GeteNBSourceCodePath() + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') + else: + copyin_res = SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') + if (copyin_res == 0): + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'ping_' + self.testCase_id + '.log', EPC.GetSourceCodePath() + '/scripts') + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def Ping(self): + result = re.search('noS1', str(RAN.GetInitialize_eNB_args())) + if result is not None: + self.PingNoS1() + return + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + check_eNB = True + if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): + check_OAI_UE = True + else: + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + self.AutoTerminateUEandeNB() + return + ueIpStatus = self.GetAllUEIPAddresses() + if (ueIpStatus < 0): + self.CreateHtmlTestRow(self.ping_args, 'KO', UE_IP_ADDRESS_ISSUE) + self.AutoTerminateUEandeNB() + return + multi_jobs = [] + i = 0 + lock = Lock() + status_queue = SimpleQueue() + for UE_IPAddress in self.UEIPAddresses: + device_id = self.UEDevices[i] + p = Process(target = self.Ping_common, args = (lock,UE_IPAddress,device_id,status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + i = i + 1 + for job in multi_jobs: + job.join() + + if (status_queue.empty()): + self.CreateHtmlTestRow(self.ping_args, 'KO', ALL_PROCESSES_OK) + self.AutoTerminateUEandeNB() + else: + ping_status = True + html_queue = SimpleQueue() + while (not status_queue.empty()): + count = status_queue.get() + if (count < 0): + ping_status = False + device_id = status_queue.get() + ip_addr = status_queue.get() + message = status_queue.get() + html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' + html_queue.put(html_cell) + if (ping_status): + self.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) + else: + self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) + self.AutoTerminateUEandeNB() + + def Iperf_ComputeTime(self): + result = re.search('-t (?P\d+)', str(self.iperf_args)) + if result is None: + logging.debug('\u001B[1;37;41m Iperf time Not Found! \u001B[0m') + sys.exit(1) + return result.group('iperf_time') + + def Iperf_ComputeModifiedBW(self, idx, ue_num): + result = re.search('-b (?P[0-9\.]+)[KMG]', str(self.iperf_args)) + if result is None: + logging.debug('\u001B[1;37;41m Iperf bandwidth Not Found! \u001B[0m') + sys.exit(1) + iperf_bandwidth = result.group('iperf_bandwidth') + if self.iperf_profile == 'balanced': + iperf_bandwidth_new = float(iperf_bandwidth)/ue_num + if self.iperf_profile == 'single-ue': + iperf_bandwidth_new = float(iperf_bandwidth) + if self.iperf_profile == 'unbalanced': + # residual is 2% of max bw + residualBW = float(iperf_bandwidth) / 50 + if idx == 0: + iperf_bandwidth_new = float(iperf_bandwidth) - ((ue_num - 1) * residualBW) + else: + iperf_bandwidth_new = residualBW + iperf_bandwidth_str = '-b ' + iperf_bandwidth + iperf_bandwidth_str_new = '-b ' + ('%.2f' % iperf_bandwidth_new) + result = re.sub(iperf_bandwidth_str, iperf_bandwidth_str_new, str(self.iperf_args)) + if result is None: + logging.debug('\u001B[1;37;41m Calculate Iperf bandwidth Failed! \u001B[0m') + sys.exit(1) + return result + + def Iperf_analyzeV2TCPOutput(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): + SSH.command('awk -f /tmp/tcp_iperf_stats.awk /tmp/CI-eNB/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + result = re.search('Avg Bitrate : (?P[0-9\.]+ Mbits\/sec) Max Bitrate : (?P[0-9\.]+ Mbits\/sec) Min Bitrate : (?P[0-9\.]+ Mbits\/sec)', SSH.getBefore()) + if result is not None: + avgbitrate = result.group('average') + maxbitrate = result.group('maximum') + minbitrate = result.group('minimum') + lock.acquire() + logging.debug('\u001B[1;37;44m TCP iperf result (' + UE_IPAddress + ') \u001B[0m') + msg = 'TCP Stats :\n' + if avgbitrate is not None: + logging.debug('\u001B[1;34m Avg Bitrate : ' + avgbitrate + '\u001B[0m') + msg += 'Avg Bitrate : ' + avgbitrate + '\n' + if maxbitrate is not None: + logging.debug('\u001B[1;34m Max Bitrate : ' + maxbitrate + '\u001B[0m') + msg += 'Max Bitrate : ' + maxbitrate + '\n' + if minbitrate is not None: + logging.debug('\u001B[1;34m Min Bitrate : ' + minbitrate + '\u001B[0m') + msg += 'Min Bitrate : ' + minbitrate + '\n' + statusQueue.put(0) + statusQueue.put(device_id) + statusQueue.put(UE_IPAddress) + statusQueue.put(msg) + lock.release() + return 0 + + def Iperf_analyzeV2Output(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): + result = re.search('-u', str(iperf_real_options)) + if result is None: + return self.Iperf_analyzeV2TCPOutput(lock, UE_IPAddress, device_id, statusQueue, iperf_real_options) + + result = re.search('Server Report:', SSH.getBefore()) + if result is None: + result = re.search('read failed: Connection refused', SSH.getBefore()) + if result is not None: + logging.debug('\u001B[1;37;41m Could not connect to iperf server! \u001B[0m') + else: + logging.debug('\u001B[1;37;41m Server Report and Connection refused Not Found! \u001B[0m') + return -1 + # Computing the requested bandwidth in float + result = re.search('-b (?P[0-9\.]+)[KMG]', str(iperf_real_options)) + if result is not None: + req_bandwidth = result.group('iperf_bandwidth') + req_bw = float(req_bandwidth) + result = re.search('-b [0-9\.]+K', str(iperf_real_options)) + if result is not None: + req_bandwidth = '%.1f Kbits/sec' % req_bw + req_bw = req_bw * 1000 + result = re.search('-b [0-9\.]+M', str(iperf_real_options)) + if result is not None: + req_bandwidth = '%.1f Mbits/sec' % req_bw + req_bw = req_bw * 1000000 + result = re.search('-b [0-9\.]+G', str(iperf_real_options)) + if result is not None: + req_bandwidth = '%.1f Gbits/sec' % req_bw + req_bw = req_bw * 1000000000 + + result = re.search('Server Report:\\\\r\\\\n(?:|\[ *\d+\].*) (?P[0-9\.]+ [KMG]bits\/sec) +(?P[0-9\.]+ ms) +(\d+\/..\d+) +(\((?P[0-9\.]+)%\))', SSH.getBefore()) + if result is not None: + bitrate = result.group('bitrate') + packetloss = result.group('packetloss') + jitter = result.group('jitter') + lock.acquire() + logging.debug('\u001B[1;37;44m iperf result (' + UE_IPAddress + ') \u001B[0m') + iperfStatus = True + msg = 'Req Bitrate : ' + req_bandwidth + '\n' + logging.debug('\u001B[1;34m Req Bitrate : ' + req_bandwidth + '\u001B[0m') + if bitrate is not None: + msg += 'Bitrate : ' + bitrate + '\n' + logging.debug('\u001B[1;34m Bitrate : ' + bitrate + '\u001B[0m') + result = re.search('(?P[0-9\.]+) [KMG]bits/sec', str(bitrate)) + if result is not None: + actual_bw = float(str(result.group('real_bw'))) + result = re.search('[0-9\.]+ K', bitrate) + if result is not None: + actual_bw = actual_bw * 1000 + result = re.search('[0-9\.]+ M', bitrate) + if result is not None: + actual_bw = actual_bw * 1000000 + result = re.search('[0-9\.]+ G', bitrate) + if result is not None: + actual_bw = actual_bw * 1000000000 + br_loss = 100 * actual_bw / req_bw + bitperf = '%.2f ' % br_loss + msg += 'Bitrate Perf: ' + bitperf + '%\n' + logging.debug('\u001B[1;34m Bitrate Perf: ' + bitperf + '%\u001B[0m') + if packetloss is not None: + msg += 'Packet Loss : ' + packetloss + '%\n' + logging.debug('\u001B[1;34m Packet Loss : ' + packetloss + '%\u001B[0m') + if float(packetloss) > float(self.iperf_packetloss_threshold): + msg += 'Packet Loss too high!\n' + logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') + iperfStatus = False + if jitter is not None: + msg += 'Jitter : ' + jitter + '\n' + logging.debug('\u001B[1;34m Jitter : ' + jitter + '\u001B[0m') + if (iperfStatus): + statusQueue.put(0) + else: + statusQueue.put(-1) + statusQueue.put(device_id) + statusQueue.put(UE_IPAddress) + statusQueue.put(msg) + lock.release() + return 0 + else: + return -2 + + def Iperf_analyzeV2Server(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): + if (not os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not analyze from server log') + return + # Computing the requested bandwidth in float + result = re.search('-b (?P[0-9\.]+)[KMG]', str(iperf_real_options)) + if result is None: + logging.debug('Iperf bandwidth Not Found!') + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not compute Iperf bandwidth!') + return + else: + req_bandwidth = result.group('iperf_bandwidth') + req_bw = float(req_bandwidth) + result = re.search('-b [0-9\.]+K', str(iperf_real_options)) + if result is not None: + req_bandwidth = '%.1f Kbits/sec' % req_bw + req_bw = req_bw * 1000 + result = re.search('-b [0-9\.]+M', str(iperf_real_options)) + if result is not None: + req_bandwidth = '%.1f Mbits/sec' % req_bw + req_bw = req_bw * 1000000 + result = re.search('-b [0-9\.]+G', str(iperf_real_options)) + if result is not None: + req_bandwidth = '%.1f Gbits/sec' % req_bw + req_bw = req_bw * 1000000000 + + server_file = open('iperf_server_' + self.testCase_id + '_' + device_id + '.log', 'r') + br_sum = 0.0 + ji_sum = 0.0 + pl_sum = 0 + ps_sum = 0 + row_idx = 0 + for line in server_file.readlines(): + result = re.search('(?P[0-9\.]+ [KMG]bits\/sec) +(?P[0-9\.]+ ms) +(?P[0-9]+)/ +(?P[0-9]+)', str(line)) + if result is not None: + bitrate = result.group('bitrate') + jitter = result.group('jitter') + packetlost = result.group('lostPack') + packetsent = result.group('sentPack') + br = bitrate.split(' ') + ji = jitter.split(' ') + row_idx = row_idx + 1 + curr_br = float(br[0]) + pl_sum = pl_sum + int(packetlost) + ps_sum = ps_sum + int(packetsent) + if (br[1] == 'Kbits/sec'): + curr_br = curr_br * 1000 + if (br[1] == 'Mbits/sec'): + curr_br = curr_br * 1000 * 1000 + br_sum = curr_br + br_sum + ji_sum = float(ji[0]) + ji_sum + if (row_idx > 0): + br_sum = br_sum / row_idx + ji_sum = ji_sum / row_idx + br_loss = 100 * br_sum / req_bw + if (br_sum > 1000): + br_sum = br_sum / 1000 + if (br_sum > 1000): + br_sum = br_sum / 1000 + bitrate = '%.2f Mbits/sec' % br_sum + else: + bitrate = '%.2f Kbits/sec' % br_sum + else: + bitrate = '%.2f bits/sec' % br_sum + bitperf = '%.2f ' % br_loss + bitperf += '%' + jitter = '%.2f ms' % (ji_sum) + if (ps_sum > 0): + pl = float(100 * pl_sum / ps_sum) + packetloss = '%2.1f ' % (pl) + packetloss += '%' + else: + packetloss = 'unknown' + lock.acquire() + if (br_loss < 90): + statusQueue.put(1) + else: + statusQueue.put(0) + statusQueue.put(device_id) + statusQueue.put(UE_IPAddress) + req_msg = 'Req Bitrate : ' + req_bandwidth + bir_msg = 'Bitrate : ' + bitrate + brl_msg = 'Bitrate Perf: ' + bitperf + jit_msg = 'Jitter : ' + jitter + pal_msg = 'Packet Loss : ' + packetloss + statusQueue.put(req_msg + '\n' + bir_msg + '\n' + brl_msg + '\n' + jit_msg + '\n' + pal_msg + '\n') + logging.debug('\u001B[1;37;45m iperf result (' + UE_IPAddress + ') \u001B[0m') + logging.debug('\u001B[1;35m ' + req_msg + '\u001B[0m') + logging.debug('\u001B[1;35m ' + bir_msg + '\u001B[0m') + logging.debug('\u001B[1;35m ' + brl_msg + '\u001B[0m') + logging.debug('\u001B[1;35m ' + jit_msg + '\u001B[0m') + logging.debug('\u001B[1;35m ' + pal_msg + '\u001B[0m') + lock.release() + else: + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not analyze from server log') + + server_file.close() + + + def Iperf_analyzeV3Output(self, lock, UE_IPAddress, device_id, statusQueue): + result = re.search('(?P[0-9\.]+ [KMG]bits\/sec) +(?:|[0-9\.]+ ms +\d+\/\d+ \((?P[0-9\.]+)%\)) +(?:|receiver)\\\\r\\\\n(?:|\[ *\d+\] Sent \d+ datagrams)\\\\r\\\\niperf Done\.', SSH.getBefore()) + if result is None: + result = re.search('(?Piperf: error - [a-zA-Z0-9 :]+)', SSH.getBefore()) + lock.acquire() + statusQueue.put(-1) + statusQueue.put(device_id) + statusQueue.put(UE_IPAddress) + if result is not None: + logging.debug('\u001B[1;37;41m ' + result.group('error') + ' \u001B[0m') + statusQueue.put(result.group('error')) + else: + logging.debug('\u001B[1;37;41m Bitrate and/or Packet Loss Not Found! \u001B[0m') + statusQueue.put('Bitrate and/or Packet Loss Not Found!') + lock.release() + + bitrate = result.group('bitrate') + packetloss = result.group('packetloss') + lock.acquire() + logging.debug('\u001B[1;37;44m iperf result (' + UE_IPAddress + ') \u001B[0m') + logging.debug('\u001B[1;34m Bitrate : ' + bitrate + '\u001B[0m') + msg = 'Bitrate : ' + bitrate + '\n' + iperfStatus = True + if packetloss is not None: + logging.debug('\u001B[1;34m Packet Loss : ' + packetloss + '%\u001B[0m') + msg += 'Packet Loss : ' + packetloss + '%\n' + if float(packetloss) > float(self.iperf_packetloss_threshold): + logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') + msg += 'Packet Loss too high!\n' + iperfStatus = False + if (iperfStatus): + statusQueue.put(0) + else: + statusQueue.put(-1) + statusQueue.put(device_id) + statusQueue.put(UE_IPAddress) + statusQueue.put(msg) + lock.release() + + def Iperf_UL_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue): + udpIperf = True + result = re.search('-u', str(self.iperf_args)) + if result is None: + udpIperf = False + ipnumbers = UE_IPAddress.split('.') + if (len(ipnumbers) == 4): + ipnumbers[3] = '1' + EPC_Iperf_UE_IPAddress = ipnumbers[0] + '.' + ipnumbers[1] + '.' + ipnumbers[2] + '.' + ipnumbers[3] + + # Launch iperf server on EPC side (true for ltebox and old open-air-cn0 + # But for OAI-Rel14-CUPS, we launch from python executor and we are using its IP address as iperf client address + launchFromEpc = True + if re.match('OAI-Rel14-CUPS', EPC.GetType(), re.IGNORECASE): + launchFromEpc = False + cmd = 'hostname -I' + ret = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, encoding='utf-8') + if ret.stdout is not None: + EPC_Iperf_UE_IPAddress = ret.stdout.strip() + port = 5001 + idx + if launchFromEpc: + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) + SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + if udpIperf: + SSH.command('echo $USER; nohup iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', EPC.GetUserName(), 5) + else: + SSH.command('echo $USER; nohup iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', EPC.GetUserName(), 5) + SSH.close() + else: + if self.ueIperfVersion == self.dummyIperfVersion: + prefix = '' + else: + prefix = '' + if self.ueIperfVersion == '2.0.5': + prefix = '/opt/iperf-2.0.5/bin/' + if udpIperf: + cmd = 'nohup ' + prefix + 'iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log 2>&1 &' + else: + cmd = 'nohup ' + prefix + 'iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log 2>&1 &' + logging.debug(cmd) + subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, encoding='utf-8') + time.sleep(0.5) + + # Launch iperf client on UE + if (device_id == 'OAI-UE'): + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) + else: + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) + iperf_time = self.Iperf_ComputeTime() + time.sleep(0.5) + + if udpIperf: + modified_options = self.Iperf_ComputeModifiedBW(idx, ue_num) + else: + modified_options = str(self.iperf_args) + modified_options = modified_options.replace('-R','') + time.sleep(0.5) + + SSH.command('rm -f iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + if (device_id == 'OAI-UE'): + iperf_status = SSH.command('iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + ' -B ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + else: + if self.ADBCentralized: + iperf_status = SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '" 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + else: + iperf_status = SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '"\' 2>&1 > iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + SSH.command('fromdos -o iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.command('cat iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + # TIMEOUT Case + if iperf_status < 0: + SSH.close() + message = 'iperf on UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT !' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + SSH.close() + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) + return + clientStatus = self.Iperf_analyzeV2Output(lock, UE_IPAddress, device_id, statusQueue, modified_options) + SSH.close() + + # Kill iperf server on EPC side + if launchFromEpc: + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('killall --signal SIGKILL iperf', EPC.GetUserName(), 5) + SSH.close() + else: + cmd = 'killall --signal SIGKILL iperf' + logging.debug(cmd) + subprocess.run(cmd, shell=True) + time.sleep(1) + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') + # in case of failure, retrieve server log + if (clientStatus == -1) or (clientStatus == -2): + if launchFromEpc: + time.sleep(1) + if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): + os.remove('iperf_server_' + self.testCase_id + '_' + device_id + '.log') + SSH.copyin(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), EPC.GetSourceCodePath() + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) + # in case of OAI-UE + if (device_id == 'OAI-UE'): + SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_' + self.testCase_id + '_' + device_id + '.log', '.') + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') + + def Iperf_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue): + try: + # Single-UE profile -- iperf only on one UE + if self.iperf_profile == 'single-ue' and idx != 0: + return + useIperf3 = False + udpIperf = True + + self.ueIperfVersion = '2.0.5' + if (device_id != 'OAI-UE'): + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # if by chance ADB server and EPC are on the same remote host, at least log collection will take care of it + SSH.command('if [ ! -d ' + EPC.GetSourceCodePath() + '/scripts ]; then mkdir -p ' + self.EPCSourceCodePath + '/scripts ; fi', '\$', 5) + SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) + # Checking if iperf / iperf3 are installed + if self.ADBCentralized: + SSH.command('adb -s ' + device_id + ' shell "ls /data/local/tmp"', '\$', 5) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ls /data/local/tmp"\'', '\$', 60) + result = re.search('iperf3', SSH.getBefore()) + if result is None: + result = re.search('iperf', SSH.getBefore()) + if result is None: + message = 'Neither iperf nor iperf3 installed on UE!' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + SSH.close() + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) + return + else: + if self.ADBCentralized: + SSH.command('adb -s ' + device_id + ' shell "/data/local/tmp/iperf --version"', '\$', 5) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf --version"\'', '\$', 60) + result = re.search('iperf version 2.0.5', SSH.getBefore()) + if result is not None: + self.ueIperfVersion = '2.0.5' + result = re.search('iperf version 2.0.10', SSH.getBefore()) + if result is not None: + self.ueIperfVersion = '2.0.10' + else: + useIperf3 = True + SSH.close() + else: + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('iperf --version', '\$', 5) + result = re.search('iperf version 2.0.5', SSH.getBefore()) + if result is not None: + self.ueIperfVersion = '2.0.5' + result = re.search('iperf version 2.0.10', SSH.getBefore()) + if result is not None: + self.ueIperfVersion = '2.0.10' + SSH.close() + # in case of iperf, UL has its own function + if (not useIperf3): + result = re.search('-R', str(self.iperf_args)) + if result is not None: + self.Iperf_UL_common(lock, UE_IPAddress, device_id, idx, ue_num, statusQueue) + return + + # Launch the IPERF server on the UE side for DL + if (device_id == 'OAI-UE'): + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) + SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + result = re.search('-u', str(self.iperf_args)) + if result is None: + SSH.command('echo $USER; nohup iperf -B ' + UE_IPAddress + ' -s -i 1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.UEUserName, 5) + udpIperf = False + else: + SSH.command('echo $USER; nohup iperf -B ' + UE_IPAddress + ' -u -s -i 1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.UEUserName, 5) + else: + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) + if self.ADBCentralized: + if (useIperf3): + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/iperf3 -s &', '\$', 5) + else: + SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + result = re.search('-u', str(self.iperf_args)) + if result is None: + SSH.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) + udpIperf = False + else: + SSH.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) + else: + SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + SSH.command('echo $USER; nohup ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" \' 2>&1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 60) + + time.sleep(0.5) + SSH.close() + + # Launch the IPERF client on the EPC side for DL (true for ltebox and old open-air-cn + # But for OAI-Rel14-CUPS, we launch from python executor + launchFromEpc = True + if re.match('OAI-Rel14-CUPS', EPC.GetType(), re.IGNORECASE): + launchFromEpc = False + if launchFromEpc: + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) + iperf_time = self.Iperf_ComputeTime() + time.sleep(0.5) + + if udpIperf: + modified_options = self.Iperf_ComputeModifiedBW(idx, ue_num) + else: + modified_options = str(self.iperf_args) + time.sleep(0.5) + + if launchFromEpc: + SSH.command('rm -f iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + else: + if (os.path.isfile('iperf_' + self.testCase_id + '_' + device_id + '.log')): + os.remove('iperf_' + self.testCase_id + '_' + device_id + '.log') + if (useIperf3): + SSH.command('stdbuf -o0 iperf3 -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + + clientStatus = 0 + self.Iperf_analyzeV3Output(lock, UE_IPAddress, device_id, statusQueue) + else: + if launchFromEpc: + iperf_status = SSH.command('stdbuf -o0 iperf -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) + else: + if self.ueIperfVersion == self.dummyIperfVersion: + prefix = '' + else: + prefix = '' + if self.ueIperfVersion == '2.0.5': + prefix = '/opt/iperf-2.0.5/bin/' + cmd = prefix + 'iperf -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 > iperf_' + self.testCase_id + '_' + device_id + '.log' + message = cmd + '\n' + logging.debug(cmd) + ret = subprocess.run(cmd, shell=True) + iperf_status = ret.returncode + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('cat ' + EPC.GetSourceCodePath() + '/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + if iperf_status < 0: + if launchFromEpc: + SSH.close() + message = 'iperf on UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT !' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) + return + clientStatus = self.Iperf_analyzeV2Output(lock, UE_IPAddress, device_id, statusQueue, modified_options) + SSH.close() + + # Kill the IPERF server that runs in background + if (device_id == 'OAI-UE'): + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('killall iperf', '\$', 5) + else: + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + if self.ADBCentralized: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell ps | grep --color=never iperf | grep -v grep', '\$', 5) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ps" | grep --color=never iperf | grep -v grep\'', '\$', 60) + result = re.search('shell +(?P\d+)', SSH.getBefore()) + if result is not None: + pid_iperf = result.group('pid') + if self.ADBCentralized: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell kill -KILL ' + pid_iperf, '\$', 5) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"\'', '\$', 60) + SSH.close() + # if the client report is absent, try to analyze the server log file + if (clientStatus == -1): + time.sleep(1) + if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): + os.remove('iperf_server_' + self.testCase_id + '_' + device_id + '.log') + if (device_id == 'OAI-UE'): + SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + else: + SSH.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, EPC.GetSourceCodePath() + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + SSH.command('fromdos -o iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + # fromdos has to be called on the python executor not on ADB server + cmd = 'fromdos -o iperf_server_' + self.testCase_id + '_' + device_id + '.log' + subprocess.run(cmd, shell=True) + self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) + + # in case of OAI UE: + if (device_id == 'OAI-UE'): + if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): + if not launchFromEpc: + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') + else: + SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def IperfNoS1(self): + if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + check_eNB = True + check_OAI_UE = True + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) + self.AutoTerminateUEandeNB() + return + server_on_enb = re.search('-R', str(self.iperf_args)) + if server_on_enb is not None: + iServerIPAddr = RAN.GeteNBIPAddress + iServerUser = RAN.GeteNBUserName + iServerPasswd = RAN.GeteNBPassword + iClientIPAddr = self.UEIPAddress + iClientUser = self.UEUserName + iClientPasswd = self.UEPassword + else: + iServerIPAddr = self.UEIPAddress + iServerUser = self.UEUserName + iServerPasswd = self.UEPassword + iClientIPAddr = RAN.GeteNBIPAddress + iClientUser = RAN.GeteNBUserName + iClientPasswd = RAN.GeteNBPassword + if self.iperf_options != 'sink': + # Starting the iperf server + SSH.open(iServerIPAddr, iServerUser, iServerPasswd) + # args SHALL be "-c client -u any" + # -c 10.0.1.2 -u -b 1M -t 30 -i 1 -fm -B 10.0.1.1 + # -B 10.0.1.1 -u -s -i 1 -fm + server_options = re.sub('-u.*$', '-u -s -i 1 -fm', str(self.iperf_args)) + server_options = server_options.replace('-c','-B') + SSH.command('rm -f /tmp/tmp_iperf_server_' + self.testCase_id + '.log', '\$', 5) + SSH.command('echo $USER; nohup iperf ' + server_options + ' > /tmp/tmp_iperf_server_' + self.testCase_id + '.log 2>&1 &', iServerUser, 5) + time.sleep(0.5) + SSH.close() + + # Starting the iperf client + modified_options = self.Iperf_ComputeModifiedBW(0, 1) + modified_options = modified_options.replace('-R','') + iperf_time = self.Iperf_ComputeTime() + SSH.open(iClientIPAddr, iClientUser, iClientPasswd) + SSH.command('rm -f /tmp/tmp_iperf_' + self.testCase_id + '.log', '\$', 5) + iperf_status = SSH.command('stdbuf -o0 iperf ' + modified_options + ' 2>&1 | stdbuf -o0 tee /tmp/tmp_iperf_' + self.testCase_id + '.log', '\$', int(iperf_time)*5.0) + status_queue = SimpleQueue() + lock = Lock() + if iperf_status < 0: + message = 'iperf on OAI UE crashed due to TIMEOUT !' + logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') + clientStatus = -2 + else: + if self.iperf_options == 'sink': + clientStatus = 0 + status_queue.put(0) + status_queue.put('OAI-UE') + status_queue.put('10.0.1.2') + status_queue.put('Sink Test : no check') + else: + clientStatus = self.Iperf_analyzeV2Output(lock, '10.0.1.2', 'OAI-UE', status_queue, modified_options) + SSH.close() + + # Stopping the iperf server + if self.iperf_options != 'sink': + SSH.open(iServerIPAddr, iServerUser, iServerPasswd) + SSH.command('killall --signal SIGKILL iperf', '\$', 5) + time.sleep(0.5) + SSH.close() + + if (clientStatus == -1): + if (os.path.isfile('iperf_server_' + self.testCase_id + '.log')): + os.remove('iperf_server_' + self.testCase_id + '.log') + SSH.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log') + self.Iperf_analyzeV2Server(lock, '10.0.1.2', 'OAI-UE', status_queue, modified_options) + + # copying on the EPC server for logCollection + if (clientStatus == -1): + copyin_res = SSH.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log') + if (copyin_res == 0): + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_server_' + self.testCase_id + '_OAI-UE.log', EPC.GetSourceCodePath() + '/scripts') + copyin_res = SSH.copyin(iClientIPAddr, iClientUser, iClientPasswd, '/tmp/tmp_iperf_' + self.testCase_id + '.log', 'iperf_' + self.testCase_id + '_OAI-UE.log') + if (copyin_res == 0): + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_' + self.testCase_id + '_OAI-UE.log', EPC.GetSourceCodePath() + '/scripts') + iperf_noperf = False + if status_queue.empty(): + iperf_status = False + else: + iperf_status = True + html_queue = SimpleQueue() + while (not status_queue.empty()): + count = status_queue.get() + if (count < 0): + iperf_status = False + if (count > 0): + iperf_noperf = True + device_id = status_queue.get() + ip_addr = status_queue.get() + message = status_queue.get() + html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' + html_queue.put(html_cell) + if (iperf_noperf and iperf_status): + self.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) + elif (iperf_status): + self.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) + else: + self.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) + self.AutoTerminateUEandeNB() + + def Iperf(self): + result = re.search('noS1', str(RAN.GetInitialize_eNB_args())) + if result is not None: + self.IperfNoS1() + return + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '' or self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + check_eNB = True + if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): + check_OAI_UE = True + else: + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) + self.AutoTerminateUEandeNB() + return + ueIpStatus = self.GetAllUEIPAddresses() + if (ueIpStatus < 0): + self.CreateHtmlTestRow(self.iperf_args, 'KO', UE_IP_ADDRESS_ISSUE) + self.AutoTerminateUEandeNB() + return + + self.dummyIperfVersion = '2.0.10' + #cmd = 'iperf --version' + #logging.debug(cmd + '\n') + #iperfStdout = subprocess.check_output(cmd, shell=True, universal_newlines=True) + #result = re.search('iperf version 2.0.5', str(iperfStdout.strip())) + #if result is not None: + # dummyIperfVersion = '2.0.5' + #result = re.search('iperf version 2.0.10', str(iperfStdout.strip())) + #if result is not None: + # dummyIperfVersion = '2.0.10' + + multi_jobs = [] + i = 0 + ue_num = len(self.UEIPAddresses) + lock = Lock() + status_queue = SimpleQueue() + for UE_IPAddress in self.UEIPAddresses: + device_id = self.UEDevices[i] + p = Process(target = CiTestObj.Iperf_common, args = (lock,UE_IPAddress,device_id,i,ue_num,status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + i = i + 1 + for job in multi_jobs: + job.join() + + if (status_queue.empty()): + self.CreateHtmlTestRow(self.iperf_args, 'KO', ALL_PROCESSES_OK) + self.AutoTerminateUEandeNB() + else: + iperf_status = True + iperf_noperf = False + html_queue = SimpleQueue() + while (not status_queue.empty()): + count = status_queue.get() + if (count < 0): + iperf_status = False + if (count > 0): + iperf_noperf = True + device_id = status_queue.get() + ip_addr = status_queue.get() + message = status_queue.get() + html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' + html_queue.put(html_cell) + if (iperf_noperf and iperf_status): + self.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) + elif (iperf_status): + self.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) + else: + self.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) + self.AutoTerminateUEandeNB() + + def CheckProcessExist(self, check_eNB, check_OAI_UE): + multi_jobs = [] + status_queue = SimpleQueue() + # in noS1 config, no need to check status from EPC + # in gNB also currently no need to check + result = re.search('noS1|band78', str(RAN.GetInitialize_eNB_args())) + if result is None: + p = Process(target = EPC.CheckHSSProcess, args = (status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + p = Process(target = EPC.CheckMMEProcess, args = (status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + p = Process(target = EPC.CheckSPGWProcess, args = (status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + else: + if (check_eNB == False) and (check_OAI_UE == False): + return 0 + if check_eNB: + p = Process(target = CiTestObj.CheckeNBProcess, args = (status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + if check_OAI_UE: + p = Process(target = CiTestObj.CheckOAIUEProcess, args = (status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + for job in multi_jobs: + job.join() + + if (status_queue.empty()): + return -15 + else: + result = 0 + while (not status_queue.empty()): + status = status_queue.get() + if (status < 0): + result = status + if result == ENB_PROCESS_FAILED: + fileCheck = re.search('enb_', str(RAN.GeteNBLogFiles[0])) + if fileCheck is not None: + SSH.copyin(RAN.GeteNBIPAddress, RAN.GeteNBUserName, RAN.GeteNBPassword, RAN.GeteNBSourceCodePath() + '/cmake_targets/' + RAN.GeteNBLogFiles[0], '.') + logStatus = self.AnalyzeLogFile_eNB(RAN.GeteNBLogFiles[0]) + if logStatus < 0: + result = logStatus + RAN.SeteNBLogFiles[0] = '' + if self.flexranCtrlInstalled and self.flexranCtrlStarted: + self.TerminateFlexranCtrl() + return result + + def CheckOAIUEProcessExist(self, initialize_OAI_UE_flag): + multi_jobs = [] + status_queue = SimpleQueue() + if initialize_OAI_UE_flag == False: + p = Process(target = CiTestObj.CheckOAIUEProcess, args = (status_queue,)) + p.daemon = True + p.start() + multi_jobs.append(p) + for job in multi_jobs: + job.join() + + if (status_queue.empty()): + return -15 + else: + result = 0 + while (not status_queue.empty()): + status = status_queue.get() + if (status < 0): + result = status + if result == OAI_UE_PROCESS_FAILED: + fileCheck = re.search('ue_', str(self.UELogFile)) + if fileCheck is not None: + SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.') + logStatus = self.AnalyzeLogFile_UE(self.UELogFile) + if logStatus < 0: + result = logStatus + return result + + def CheckOAIUEProcess(self, status_queue): + try: + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('stdbuf -o0 ps -aux | grep --color=never ' + RAN.Getair_interface() + '-uesoftmodem | grep -v grep', '\$', 5) + result = re.search(RAN.Getair_interface() + '-uesoftmodem', SSH.getBefore()) + if result is None: + logging.debug('\u001B[1;37;41m OAI UE Process Not Found! \u001B[0m') + status_queue.put(OAI_UE_PROCESS_FAILED) + else: + status_queue.put(OAI_UE_PROCESS_OK) + SSH.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) +''' + def CheckeNBProcess(self, status_queue): + try: + # At least the instance 0 SHALL be on! + if self.eNBstatuses[0] == 0: + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + elif self.eNBstatuses[0] == 1: + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + elif self.eNBstatuses[0] == 2: + lIpAddr = self.eNB2IPAddress + lUserName = self.eNB2UserName + lPassWord = self.eNB2Password + else: + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + SSH.open(lIpAddr, lUserName, lPassWord) + SSH.command('stdbuf -o0 ps -aux | grep --color=never ' + self.air_interface + '-softmodem | grep -v grep', '\$', 5) + result = re.search(self.air_interface + '-softmodem', SSH.getBefore()) + if result is None: + logging.debug('\u001B[1;37;41m eNB Process Not Found! \u001B[0m') + status_queue.put(ENB_PROCESS_FAILED) + else: + status_queue.put(ENB_PROCESS_OK) + SSH.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) +''' + def AnalyzeLogFile_eNB(self, eNBlogFile): + if (not os.path.isfile('./' + eNBlogFile)): + return -1 + enb_log_file = open('./' + eNBlogFile, 'r') + exitSignalReceived = False + foundAssertion = False + msgAssertion = '' + msgLine = 0 + foundSegFault = False + foundRealTimeIssue = False + rrcSetupComplete = 0 + rrcReleaseRequest = 0 + rrcReconfigRequest = 0 + rrcReconfigComplete = 0 + rrcReestablishRequest = 0 + rrcReestablishComplete = 0 + rrcReestablishReject = 0 + rlcDiscardBuffer = 0 + rachCanceledProcedure = 0 + uciStatMsgCount = 0 + pdcpFailure = 0 + ulschFailure = 0 + cdrxActivationMessageCount = 0 + dropNotEnoughRBs = 0 + mbmsRequestMsg = 0 + self.htmleNBFailureMsg = '' + isRRU = False + isSlave = False + slaveReceivesFrameResyncCmd = False + X2HO_state = X2_HO_REQ_STATE__IDLE + X2HO_inNbProcedures = 0 + X2HO_outNbProcedures = 0 + for line in enb_log_file.readlines(): + if X2HO_state == X2_HO_REQ_STATE__IDLE: + result = re.search('target eNB Receives X2 HO Req X2AP_HANDOVER_REQ', str(line)) + if result is not None: + X2HO_state = X2_HO_REQ_STATE__TARGET_RECEIVES_REQ + result = re.search('source eNB receives the X2 HO ACK X2AP_HANDOVER_REQ_ACK', str(line)) + if result is not None: + X2HO_state = X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK + if X2HO_state == X2_HO_REQ_STATE__TARGET_RECEIVES_REQ: + result = re.search('Received LTE_RRCConnectionReconfigurationComplete from UE', str(line)) + if result is not None: + X2HO_state = X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE + if X2HO_state == X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE: + result = re.search('issue rrc_eNB_send_PATH_SWITCH_REQ', str(line)) + if result is not None: + X2HO_state = X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ + if X2HO_state == X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ: + result = re.search('received path switch ack S1AP_PATH_SWITCH_REQ_ACK', str(line)) + if result is not None: + X2HO_state = X2_HO_REQ_STATE__IDLE + X2HO_inNbProcedures += 1 + if X2HO_state == X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK: + result = re.search('source eNB receives the X2 UE CONTEXT RELEASE X2AP_UE_CONTEXT_RELEASE', str(line)) + if result is not None: + X2HO_state = X2_HO_REQ_STATE__IDLE + X2HO_outNbProcedures += 1 + + if RAN.SeteNBOptions[int(RAN.GeteNB_instance())] != '': + res1 = re.search('max_rxgain (?P[0-9]+)', RAN.GeteNBOptions[int(RAN.GeteNB_instance())]) + res2 = re.search('max_rxgain (?P[0-9]+)', str(line)) + if res1 is not None and res2 is not None: + requested_option = int(res1.group('requested_option')) + applied_option = int(res2.group('applied_option')) + if requested_option == applied_option: + self.htmleNBFailureMsg += ' Command line option(s) correctly applied ' + RAN.GeteNBOptions[int(RAN.GeteNB_instance())] + '\n\n' + else: + self.htmleNBFailureMsg += ' Command line option(s) NOT applied ' + RAN.GeteNBOptions[int(RAN.GeteNB_instance())] + '\n\n' + result = re.search('Exiting OAI softmodem', str(line)) + if result is not None: + exitSignalReceived = True + result = re.search('[Ss]egmentation [Ff]ault', str(line)) + 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('./ran_build/build/lte-softmodem', str(line)) + if result is not None and not exitSignalReceived: + foundSegFault = True + result = re.search('[Aa]ssertion', str(line)) + if result is not None and not exitSignalReceived: + foundAssertion = True + result = re.search('LLL', str(line)) + if result is not None and not exitSignalReceived: + foundRealTimeIssue = True + if foundAssertion and (msgLine < 3): + msgLine += 1 + msgAssertion += str(line) + result = re.search('Setting function for RU', str(line)) + if result is not None: + isRRU = True + if isRRU: + result = re.search('RU 0 is_slave=yes', str(line)) + if result is not None: + isSlave = True + if isSlave: + result = re.search('Received RRU_frame_resynch command', str(line)) + if result is not None: + slaveReceivesFrameResyncCmd = True + result = re.search('LTE_RRCConnectionSetupComplete from UE', str(line)) + if result is not None: + rrcSetupComplete += 1 + result = re.search('Generate LTE_RRCConnectionRelease|Generate RRCConnectionRelease', str(line)) + if result is not None: + rrcReleaseRequest += 1 + result = re.search('Generate LTE_RRCConnectionReconfiguration', str(line)) + if result is not None: + rrcReconfigRequest += 1 + result = re.search('LTE_RRCConnectionReconfigurationComplete from UE rnti', str(line)) + if result is not None: + rrcReconfigComplete += 1 + result = re.search('LTE_RRCConnectionReestablishmentRequest', str(line)) + if result is not None: + rrcReestablishRequest += 1 + result = re.search('LTE_RRCConnectionReestablishmentComplete', str(line)) + if result is not None: + rrcReestablishComplete += 1 + result = re.search('LTE_RRCConnectionReestablishmentReject', str(line)) + if result is not None: + rrcReestablishReject += 1 + result = re.search('CDRX configuration activated after RRC Connection', str(line)) + if result is not None: + cdrxActivationMessageCount += 1 + result = re.search('uci->stat', str(line)) + if result is not None: + uciStatMsgCount += 1 + result = re.search('PDCP.*Out of Resources.*reason', str(line)) + if result is not None: + pdcpFailure += 1 + result = re.search('ULSCH in error in round', str(line)) + if result is not None: + ulschFailure += 1 + result = re.search('BAD all_segments_received', str(line)) + if result is not None: + rlcDiscardBuffer += 1 + 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 + if RAN.GeteNBmbmsEnables[int(RAN.GeteNB_instance())]: + result = re.search('MBMS USER-PLANE.*Requesting.*bytes from RLC', str(line)) + if result is not None: + mbmsRequestMsg += 1 + enb_log_file.close() + logging.debug(' File analysis completed') + self.htmleNBFailureMsg = '' + if RAN.Getair_interface() == 'lte': + nodeB_prefix = 'e' + else: + nodeB_prefix = 'g' + if uciStatMsgCount > 0: + statMsg = nodeB_prefix + 'NB showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + self.htmleNBFailureMsg += statMsg + '\n' + if pdcpFailure > 0: + statMsg = nodeB_prefix + 'NB showed ' + str(pdcpFailure) + ' "PDCP Out of Resources" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + self.htmleNBFailureMsg += statMsg + '\n' + if ulschFailure > 0: + statMsg = nodeB_prefix + 'NB 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 = nodeB_prefix + 'NB completed ' + str(rrcSetupComplete) + ' RRC Connection Setup(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + rrcMsg = ' -- ' + str(rrcSetupComplete) + ' were completed' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + if rrcReleaseRequest > 0: + rrcMsg = nodeB_prefix + 'NB requested ' + str(rrcReleaseRequest) + ' RRC Connection Release(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + if rrcReconfigRequest > 0 or rrcReconfigComplete > 0: + rrcMsg = nodeB_prefix + 'NB requested ' + str(rrcReconfigRequest) + ' RRC Connection Reconfiguration(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + rrcMsg = ' -- ' + str(rrcReconfigComplete) + ' were completed' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + if rrcReestablishRequest > 0 or rrcReestablishComplete > 0 or rrcReestablishReject > 0: + rrcMsg = nodeB_prefix + 'NB requested ' + str(rrcReestablishRequest) + ' RRC Connection Reestablishment(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + rrcMsg = ' -- ' + str(rrcReestablishComplete) + ' were completed' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + rrcMsg = ' -- ' + str(rrcReestablishReject) + ' were rejected' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + if RAN.GeteNBmbmsEnables[int(RAN.GeteNB_instance())]: + if mbmsRequestMsg > 0: + rrcMsg = 'eNB requested ' + str(mbmsRequestMsg) + ' times the RLC for MBMS USER-PLANE' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + if X2HO_inNbProcedures > 0: + rrcMsg = 'eNB completed ' + str(X2HO_inNbProcedures) + ' X2 Handover Connection procedure(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + if X2HO_outNbProcedures > 0: + rrcMsg = 'eNB completed ' + str(X2HO_outNbProcedures) + ' X2 Handover Release procedure(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + if RAN.SeteNBOptions[int(RAN.GeteNB_instance())] != '': + res1 = re.search('drx_Config_present prSetup', RAN.GeteNBOptions[int(RAN.GeteNB_instance())]) + if res1 is not None: + if cdrxActivationMessageCount > 0: + rrcMsg = 'eNB activated the CDRX Configuration for ' + str(cdrxActivationMessageCount) + ' time(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + else: + rrcMsg = 'eNB did NOT ACTIVATE the CDRX Configuration' + logging.debug('\u001B[1;37;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + if rachCanceledProcedure > 0: + rachMsg = nodeB_prefix + 'NB cancelled ' + str(rachCanceledProcedure) + ' RA procedure(s)' + logging.debug('\u001B[1;30;43m ' + rachMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rachMsg + '\n' + if isRRU: + if isSlave: + if slaveReceivesFrameResyncCmd: + rruMsg = 'Slave RRU received the RRU_frame_resynch command from RAU' + logging.debug('\u001B[1;30;43m ' + rruMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rruMsg + '\n' + else: + rruMsg = 'Slave RRU DID NOT receive the RRU_frame_resynch command from RAU' + logging.debug('\u001B[1;37;41m ' + rruMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rruMsg + '\n' + self.prematureExit = True + return ENB_PROCESS_SLAVE_RRU_NOT_SYNCED + if foundSegFault: + logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB ended with a Segmentation Fault! \u001B[0m') + return ENB_PROCESS_SEG_FAULT + if foundAssertion: + logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB ended with an assertion! \u001B[0m') + self.htmleNBFailureMsg += msgAssertion + return ENB_PROCESS_ASSERTION + if foundRealTimeIssue: + logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB faced real time issues! \u001B[0m') + self.htmleNBFailureMsg += nodeB_prefix + 'NB faced real time issues!\n' + #return ENB_PROCESS_REALTIME_ISSUE + if rlcDiscardBuffer > 0: + rlcMsg = nodeB_prefix + 'NB RLC discarded ' + str(rlcDiscardBuffer) + ' buffer(s)' + logging.debug('\u001B[1;37;41m ' + rlcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rlcMsg + '\n' + return ENB_PROCESS_REALTIME_ISSUE + return 0 + + def AnalyzeLogFile_UE(self, UElogFile): + if (not os.path.isfile('./' + UElogFile)): + return -1 + ue_log_file = open('./' + UElogFile, 'r') + exitSignalReceived = False + foundAssertion = False + msgAssertion = '' + msgLine = 0 + foundSegFault = False + foundRealTimeIssue = False + uciStatMsgCount = 0 + pdcpDataReqFailedCount = 0 + badDciCount = 0 + f1aRetransmissionCount = 0 + fatalErrorCount = 0 + macBsrTimerExpiredCount = 0 + rrcConnectionRecfgComplete = 0 + no_cell_sync_found = False + mib_found = False + frequency_found = False + plmn_found = False + nrUEFlag = False + nrDecodeMib = 0 + nrFoundDCI = 0 + nrCRCOK = 0 + mbms_messages = 0 + self.htmlUEFailureMsg = '' + for line in ue_log_file.readlines(): + result = re.search('nr_synchro_time', str(line)) + if result is not None: + nrUEFlag = True + if nrUEFlag: + result = re.search('decode mib', str(line)) + if result is not None: + nrDecodeMib += 1 + result = re.search('found 1 DCIs', str(line)) + if result is not None: + nrFoundDCI += 1 + result = re.search('CRC OK', str(line)) + if result is not None: + nrCRCOK += 1 + result = re.search('Exiting OAI softmodem', str(line)) + if result is not None: + exitSignalReceived = True + result = re.search('System error|[Ss]egmentation [Ff]ault|======= Backtrace: =========|======= Memory map: ========', str(line)) + 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)) + if result is not None and not exitSignalReceived: + foundAssertion = True + result = re.search('LLL', str(line)) + if result is not None and not exitSignalReceived: + foundRealTimeIssue = True + if foundAssertion and (msgLine < 3): + msgLine += 1 + msgAssertion += str(line) + result = re.search('uci->stat', str(line)) + if result is not None and not exitSignalReceived: + uciStatMsgCount += 1 + result = re.search('PDCP data request failed', str(line)) + if result is not None and not exitSignalReceived: + pdcpDataReqFailedCount += 1 + result = re.search('bad DCI 1', str(line)) + if result is not None and not exitSignalReceived: + badDciCount += 1 + result = re.search('Format1A Retransmission but TBS are different', str(line)) + if result is not None and not exitSignalReceived: + f1aRetransmissionCount += 1 + result = re.search('FATAL ERROR', str(line)) + if result is not None and not exitSignalReceived: + fatalErrorCount += 1 + result = re.search('MAC BSR Triggered ReTxBSR Timer expiry', str(line)) + if result is not None and not exitSignalReceived: + macBsrTimerExpiredCount += 1 + result = re.search('Generating RRCConnectionReconfigurationComplete', str(line)) + if result is not None: + rrcConnectionRecfgComplete += 1 + # No cell synchronization found, abandoning + result = re.search('No cell synchronization found, abandoning', str(line)) + if result is not None: + no_cell_sync_found = True + if RAN.GeteNBmbmsEnables[0]: + result = re.search('TRIED TO PUSH MBMS DATA', str(line)) + if result is not None: + mbms_messages += 1 + result = re.search("MIB Information => ([a-zA-Z]{1,10}), ([a-zA-Z]{1,10}), NidCell (?P\d{1,3}), N_RB_DL (?P\d{1,3}), PHICH DURATION (?P\d), PHICH RESOURCE (?P.{1,4}), TX_ANT (?P\d)", str(line)) + if result is not None and (not mib_found): + try: + mibMsg = "MIB Information: " + result.group(1) + ', ' + result.group(2) + self.htmlUEFailureMsg += mibMsg + '\n' + logging.debug('\033[94m' + mibMsg + '\033[0m') + mibMsg = " nidcell = " + result.group('nidcell') + self.htmlUEFailureMsg += mibMsg + logging.debug('\033[94m' + mibMsg + '\033[0m') + mibMsg = " n_rb_dl = " + result.group('n_rb_dl') + self.htmlUEFailureMsg += mibMsg + '\n' + logging.debug('\033[94m' + mibMsg + '\033[0m') + mibMsg = " phich_duration = " + result.group('phich_duration') + self.htmlUEFailureMsg += mibMsg + logging.debug('\033[94m' + mibMsg + '\033[0m') + mibMsg = " phich_resource = " + result.group('phich_resource') + self.htmlUEFailureMsg += mibMsg + '\n' + logging.debug('\033[94m' + mibMsg + '\033[0m') + mibMsg = " tx_ant = " + result.group('tx_ant') + self.htmlUEFailureMsg += mibMsg + '\n' + logging.debug('\033[94m' + mibMsg + '\033[0m') + mib_found = True + except Exception as e: + logging.error('\033[91m' + "MIB marker was not found" + '\033[0m') + result = re.search("Measured Carrier Frequency (?P\d{1,15}) Hz", str(line)) + if result is not None and (not frequency_found): + try: + mibMsg = "Measured Carrier Frequency = " + result.group('measured_carrier_frequency') + ' Hz' + self.htmlUEFailureMsg += mibMsg + '\n' + logging.debug('\033[94m' + mibMsg + '\033[0m') + frequency_found = True + except Exception as e: + logging.error('\033[91m' + "Measured Carrier Frequency not found" + '\033[0m') + result = re.search("PLMN MCC (?P\d{1,3}), MNC (?P\d{1,3}), TAC", str(line)) + if result is not None and (not plmn_found): + try: + mibMsg = 'PLMN MCC = ' + result.group('mcc') + ' MNC = ' + result.group('mnc') + self.htmlUEFailureMsg += mibMsg + '\n' + logging.debug('\033[94m' + mibMsg + '\033[0m') + plmn_found = True + except Exception as e: + logging.error('\033[91m' + "PLMN not found" + '\033[0m') + result = re.search("Found (?P[\w,\s]{1,15}) \(name from internal table\)", str(line)) + if result is not None: + try: + mibMsg = "The operator is: " + result.group('operator') + self.htmlUEFailureMsg += mibMsg + '\n' + logging.debug('\033[94m' + mibMsg + '\033[0m') + except Exception as e: + logging.error('\033[91m' + "Operator name not found" + '\033[0m') + result = re.search("SIB5 InterFreqCarrierFreq element (.{1,4})/(.{1,4})", str(line)) + if result is not None: + try: + mibMsg = "SIB5 InterFreqCarrierFreq element " + result.group(1) + '/' + result.group(2) + self.htmlUEFailureMsg += mibMsg + ' -> ' + logging.debug('\033[94m' + mibMsg + '\033[0m') + except Exception as e: + logging.error('\033[91m' + "SIB5 InterFreqCarrierFreq element not found" + '\033[0m') + result = re.search("DL Carrier Frequency/ARFCN : (?P\d{1,15}/\d{1,4})", str(line)) + if result is not None: + try: + freq = result.group('carrier_frequency') + new_freq = re.sub('/[0-9]+','',freq) + float_freq = float(new_freq) / 1000000 + self.htmlUEFailureMsg += 'DL Freq: ' + ('%.1f' % float_freq) + ' MHz' + logging.debug('\033[94m' + " DL Carrier Frequency is: " + freq + '\033[0m') + except Exception as e: + logging.error('\033[91m' + " DL Carrier Frequency not found" + '\033[0m') + result = re.search("AllowedMeasBandwidth : (?P\d{1,7})", str(line)) + if result is not None: + try: + prb = result.group('allowed_bandwidth') + self.htmlUEFailureMsg += ' -- PRB: ' + prb + '\n' + logging.debug('\033[94m' + " AllowedMeasBandwidth: " + prb + '\033[0m') + except Exception as e: + logging.error('\033[91m' + " AllowedMeasBandwidth not found" + '\033[0m') + ue_log_file.close() + if rrcConnectionRecfgComplete > 0: + statMsg = 'UE connected to eNB (' + str(rrcConnectionRecfgComplete) + ' RRCConnectionReconfigurationComplete message(s) generated)' + logging.debug('\033[94m' + statMsg + '\033[0m') + self.htmlUEFailureMsg += statMsg + '\n' + if nrUEFlag: + if nrDecodeMib > 0: + statMsg = 'UE showed ' + str(nrDecodeMib) + ' MIB decode message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + self.htmlUEFailureMsg += statMsg + '\n' + if nrFoundDCI > 0: + statMsg = 'UE showed ' + str(nrFoundDCI) + ' DCI found message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + self.htmlUEFailureMsg += statMsg + '\n' + if nrCRCOK > 0: + statMsg = 'UE showed ' + str(nrCRCOK) + ' PDSCH decoding message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + self.htmlUEFailureMsg += statMsg + '\n' + if not frequency_found: + statMsg = 'NR-UE could NOT synch!' + logging.error('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + self.htmlUEFailureMsg += statMsg + '\n' + if uciStatMsgCount > 0: + statMsg = 'UE showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + self.htmlUEFailureMsg += statMsg + '\n' + if pdcpDataReqFailedCount > 0: + statMsg = 'UE showed ' + str(pdcpDataReqFailedCount) + ' "PDCP data request failed" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + self.htmlUEFailureMsg += statMsg + '\n' + if badDciCount > 0: + statMsg = 'UE showed ' + str(badDciCount) + ' "bad DCI 1(A)" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + self.htmlUEFailureMsg += statMsg + '\n' + if f1aRetransmissionCount > 0: + statMsg = 'UE showed ' + str(f1aRetransmissionCount) + ' "Format1A Retransmission but TBS are different" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + self.htmlUEFailureMsg += statMsg + '\n' + if fatalErrorCount > 0: + statMsg = 'UE showed ' + str(fatalErrorCount) + ' "FATAL ERROR:" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + self.htmlUEFailureMsg += statMsg + '\n' + if macBsrTimerExpiredCount > 0: + statMsg = 'UE showed ' + str(fatalErrorCount) + ' "MAC BSR Triggered ReTxBSR Timer expiry" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + self.htmlUEFailureMsg += statMsg + '\n' + if RAN.GeteNBmbmsEnables[0]: + if mbms_messages > 0: + statMsg = 'UE showed ' + str(mbms_messages) + ' "TRIED TO PUSH MBMS DATA" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + else: + statMsg = 'UE did NOT SHOW "TRIED TO PUSH MBMS DATA" message(s)' + logging.debug('\u001B[1;30;41m ' + statMsg + ' \u001B[0m') + self.htmlUEFailureMsg += statMsg + '\n' + if foundSegFault: + logging.debug('\u001B[1;37;41m UE ended with a Segmentation Fault! \u001B[0m') + if not nrUEFlag: + return OAI_UE_PROCESS_SEG_FAULT + else: + if not frequency_found: + return OAI_UE_PROCESS_SEG_FAULT + if foundAssertion: + logging.debug('\u001B[1;30;43m UE showed an assertion! \u001B[0m') + self.htmlUEFailureMsg += 'UE showed an assertion!\n' + if not nrUEFlag: + if not mib_found or not frequency_found: + return OAI_UE_PROCESS_ASSERTION + else: + if not frequency_found: + return OAI_UE_PROCESS_ASSERTION + if foundRealTimeIssue: + logging.debug('\u001B[1;37;41m UE faced real time issues! \u001B[0m') + self.htmlUEFailureMsg += 'UE faced real time issues!\n' + #return ENB_PROCESS_REALTIME_ISSUE + if nrUEFlag: + if not frequency_found: + return OAI_UE_PROCESS_COULD_NOT_SYNC + else: + if no_cell_sync_found and not mib_found: + logging.debug('\u001B[1;37;41m UE could not synchronize ! \u001B[0m') + self.htmlUEFailureMsg += 'UE could not synchronize!\n' + return OAI_UE_PROCESS_COULD_NOT_SYNC + return 0 +''' + def TerminateeNB(self): + if self.eNB_serverId == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = RAN.GeteNBSourceCodePath() + elif self.eNB_serverId == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + lSourcePath = self.eNB1SourceCodePath + elif self.eNB_serverId == '2': + lIpAddr = self.eNB2IPAddress + lUserName = self.eNB2UserName + lPassWord = self.eNB2Password + lSourcePath = self.eNB2SourceCodePath + if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + SSH.open(lIpAddr, lUserName, lPassWord) + SSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) + if self.air_interface == 'lte': + nodeB_prefix = 'e' + else: + nodeB_prefix = 'g' + SSH.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + result = re.search('-softmodem', SSH.getBefore()) + if result is not None: + SSH.command('echo ' + lPassWord + ' | sudo -S daemon --name=enb' + str(self.eNB_instance) + '_daemon --stop', '\$', 5) + SSH.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGINT -r .*-softmodem || true', '\$', 5) + time.sleep(10) + SSH.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + result = re.search('-softmodem', SSH.getBefore()) + if result is not None: + SSH.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGKILL -r .*-softmodem || true', '\$', 5) + time.sleep(5) + SSH.command('rm -f my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + SSH.close() + # If tracer options is on, stopping tshark on EPC side + result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args())) + if result is not None: + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + logging.debug('\u001B[1m Stopping tshark \u001B[0m') + SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) + time.sleep(1) + if EPC.EPC_PcapFileName != '': + SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S chmod 666 /tmp/' + EPC.EPC_PcapFileName , '\$', 5) + SSH.copyin(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), '/tmp/' + EPC.EPC_PcapFileName , '.') + SSH.copyout(lIpAddr, lUserName, lPassWord, EPC.EPC_PcapFileName , lSourcePath + '/cmake_targets/.') + SSH.close() + logging.debug('\u001B[1m Replaying RAW record file\u001B[0m') + SSH.open(lIpAddr, lUserName, lPassWord) + SSH.command('cd ' + lSourcePath + '/common/utils/T/tracer/', '\$', 5) + enbLogFile = self.eNBLogFiles[int(self.eNB_instance)] + raw_record_file = enbLogFile.replace('.log', '_record.raw') + replay_log_file = enbLogFile.replace('.log', '_replay.log') + extracted_txt_file = enbLogFile.replace('.log', '_extracted_messages.txt') + extracted_log_file = enbLogFile.replace('.log', '_extracted_messages.log') + SSH.command('./extract_config -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + extracted_txt_file, '\$', 5) + SSH.command('echo $USER; nohup ./replay -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + replay_log_file + ' 2>&1 &', lUserName, 5) + SSH.command('./textlog -d ' + lSourcePath + '/cmake_targets/' + extracted_txt_file + ' -no-gui -ON -full > ' + lSourcePath + '/cmake_targets/' + extracted_log_file, '\$', 5) + SSH.close() + SSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + extracted_log_file, '.') + logging.debug('\u001B[1m Analyzing eNB replay logfile \u001B[0m') + logStatus = self.AnalyzeLogFile_eNB(extracted_log_file) + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + self.eNBLogFiles[int(self.eNB_instance)] = '' + else: + analyzeFile = False + if self.eNBLogFiles[int(self.eNB_instance)] != '': + analyzeFile = True + fileToAnalyze = self.eNBLogFiles[int(self.eNB_instance)] + self.eNBLogFiles[int(self.eNB_instance)] = '' + if analyzeFile: + copyin_res = SSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + fileToAnalyze, '.') + if (copyin_res == -1): + logging.debug('\u001B[1;37;41m Could not copy ' + nodeB_prefix + 'NB logfile to analyze it! \u001B[0m') + self.htmleNBFailureMsg = 'Could not copy ' + nodeB_prefix + 'NB logfile to analyze it!' + self.CreateHtmlTestRow('N/A', 'KO', ENB_PROCESS_NOLOGFILE_TO_ANALYZE) + self.eNBmbmsEnables[int(self.eNB_instance)] = False + return + if self.eNB_serverId != '0': + SSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './' + fileToAnalyze, RAN.GeteNBSourceCodePath() + '/cmake_targets/') + logging.debug('\u001B[1m Analyzing ' + nodeB_prefix + 'NB logfile \u001B[0m ' + fileToAnalyze) + logStatus = self.AnalyzeLogFile_eNB(fileToAnalyze) + if (logStatus < 0): + self.CreateHtmlTestRow('N/A', 'KO', logStatus) + self.preamtureExit = True + self.eNBmbmsEnables[int(self.eNB_instance)] = False + return + else: + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + else: + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + self.eNBmbmsEnables[int(self.eNB_instance)] = False + self.eNBstatuses[int(self.eNB_instance)] = -1 +''' + def TerminateFlexranCtrl(self): + if self.flexranCtrlInstalled == False or self.flexranCtrlStarted == False: + return + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S daemon --name=flexran_rtc_daemon --stop', '\$', 5) + time.sleep(1) + SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S killall --signal SIGKILL rt_controller', '\$', 5) + time.sleep(1) + SSH.close() + self.flexranCtrlStarted = False + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def TerminateUE_common(self, device_id, idx): + try: + SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) + # back in airplane mode on (ie radio off) + if self.ADBCentralized: + if device_id == '84B7N16418004022': + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) + else: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) + logging.debug('\u001B[1mUE (' + device_id + ') Detach Completed\u001B[0m') + + if self.ADBCentralized: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "ps | grep --color=never iperf | grep -v grep"', '\$', 5) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ps | grep --color=never iperf | grep -v grep"\'', '\$', 60) + result = re.search('shell +(?P\d+)', SSH.getBefore()) + if result is not None: + pid_iperf = result.group('pid') + if self.ADBCentralized: + SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"', '\$', 5) + else: + SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"\'', '\$', 60) + SSH.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + def TerminateUE(self): + terminate_ue_flag = True + self.GetAllUEDevices(terminate_ue_flag) + multi_jobs = [] + i = 0 + for device_id in self.UEDevices: + p = Process(target= CiTestObj.TerminateUE_common, args = (device_id,i,)) + p.daemon = True + p.start() + multi_jobs.append(p) + i += 1 + for job in multi_jobs: + job.join() + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def TerminateOAIUE(self): + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) + SSH.command('ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + result = re.search('-uesoftmodem', SSH.getBefore()) + if result is not None: + SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGINT -r .*-uesoftmodem || true', '\$', 5) + time.sleep(10) + SSH.command('ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + result = re.search('-uesoftmodem', SSH.getBefore()) + if result is not None: + SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGKILL -r .*-uesoftmodem || true', '\$', 5) + time.sleep(5) + SSH.command('rm -f my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) + SSH.close() + result = re.search('ue_', str(self.UELogFile)) + if result is not None: + copyin_res = SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.') + if (copyin_res == -1): + logging.debug('\u001B[1;37;41m Could not copy UE logfile to analyze it! \u001B[0m') + self.htmlUEFailureMsg = 'Could not copy UE logfile to analyze it!' + self.CreateHtmlTestRow('N/A', 'KO', OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE, 'UE') + self.UELogFile = '' + return + logging.debug('\u001B[1m Analyzing UE logfile \u001B[0m') + logStatus = self.AnalyzeLogFile_UE(self.UELogFile) + result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) + if result is not None: + ueAction = 'Sniffing' + else: + ueAction = 'Connection' + if (logStatus < 0): + logging.debug('\u001B[1m' + ueAction + ' Failed \u001B[0m') + self.htmlUEFailureMsg = '' + ueAction + ' Failed\n' + self.htmlUEFailureMsg + self.CreateHtmlTestRow('N/A', 'KO', logStatus, 'UE') + if RAN.Getair_interface() == 'lte': + # In case of sniffing on commercial eNBs we have random results + # Not an error then + if (logStatus != OAI_UE_PROCESS_COULD_NOT_SYNC) or (ueAction != 'Sniffing'): + self.Initialize_OAI_UE_args = '' + self.AutoTerminateUEandeNB() + else: + if (logStatus == OAI_UE_PROCESS_COULD_NOT_SYNC): + self.Initialize_OAI_UE_args = '' + self.AutoTerminateUEandeNB() + else: + logging.debug('\u001B[1m' + ueAction + ' Completed \u001B[0m') + self.htmlUEFailureMsg = '' + ueAction + ' Completed\n' + self.htmlUEFailureMsg + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + self.UELogFile = '' + else: + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + + def AutoTerminateUEandeNB(self): + if (self.ADBIPAddress != 'none'): + self.testCase_id = 'AUTO-KILL-UE' + self.desc = 'Automatic Termination of UE' + self.ShowTestID() + self.TerminateUE() + if (self.Initialize_OAI_UE_args != ''): + self.testCase_id = 'AUTO-KILL-UE' + self.desc = 'Automatic Termination of UE' + self.ShowTestID() + self.TerminateOAIUE() + if (RAN.GetInitialize_eNB_args() != ''): + self.testCase_id = 'AUTO-KILL-eNB' + self.desc = 'Automatic Termination of eNB' + self.ShowTestID() + RAN.SeteNB_instance() = '0' + self.TerminateeNB() + if self.flexranCtrlInstalled and self.flexranCtrlStarted: + self.testCase_id = 'AUTO-KILL-flexran-ctl' + self.desc = 'Automatic Termination of FlexRan CTL' + self.ShowTestID() + self.TerminateFlexranCtrl() + self.prematureExit = True + + def IdleSleep(self): + time.sleep(self.idle_sleep_time) + self.CreateHtmlTestRow(str(self.idle_sleep_time) + ' sec', 'OK', ALL_PROCESSES_OK) + + def X2_Status(self, idx, fileName): + cmd = "curl --silent http://" + EPC.GetIPAddress() + ":9999/stats | jq '.' > " + fileName + message = cmd + '\n' + logging.debug(cmd) + subprocess.run(cmd, shell=True) + if idx == 0: + cmd = "jq '.mac_stats | length' " + fileName + strNbEnbs = subprocess.check_output(cmd, shell=True, universal_newlines=True) + self.x2NbENBs = int(strNbEnbs.strip()) + cnt = 0 + while cnt < self.x2NbENBs: + cmd = "jq '.mac_stats[" + str(cnt) + "].bs_id' " + fileName + bs_id = subprocess.check_output(cmd, shell=True, universal_newlines=True) + self.x2ENBBsIds[idx].append(bs_id.strip()) + cmd = "jq '.mac_stats[" + str(cnt) + "].ue_mac_stats | length' " + fileName + stNbUEs = subprocess.check_output(cmd, shell=True, universal_newlines=True) + nbUEs = int(stNbUEs.strip()) + ueIdx = 0 + self.x2ENBConnectedUEs[idx].append([]) + while ueIdx < nbUEs: + cmd = "jq '.mac_stats[" + str(cnt) + "].ue_mac_stats[" + str(ueIdx) + "].rnti' " + fileName + rnti = subprocess.check_output(cmd, shell=True, universal_newlines=True) + self.x2ENBConnectedUEs[idx][cnt].append(rnti.strip()) + ueIdx += 1 + cnt += 1 + + msg = "FlexRan Controller is connected to " + str(self.x2NbENBs) + " eNB(s)" + logging.debug(msg) + message += msg + '\n' + cnt = 0 + while cnt < self.x2NbENBs: + msg = " -- eNB: " + str(self.x2ENBBsIds[idx][cnt]) + " is connected to " + str(len(self.x2ENBConnectedUEs[idx][cnt])) + " UE(s)" + logging.debug(msg) + message += msg + '\n' + ueIdx = 0 + while ueIdx < len(self.x2ENBConnectedUEs[idx][cnt]): + msg = " -- UE rnti: " + str(self.x2ENBConnectedUEs[idx][cnt][ueIdx]) + logging.debug(msg) + message += msg + '\n' + ueIdx += 1 + cnt += 1 + return message + + def Perform_X2_Handover(self): + html_queue = SimpleQueue() + fullMessage = '
'
+		msg = 'Doing X2 Handover w/ option ' + self.x2_ho_options
+		logging.debug(msg)
+		fullMessage += msg + '\n'
+		if self.x2_ho_options == 'network':
+			if self.flexranCtrlInstalled and self.flexranCtrlStarted:
+				self.x2ENBBsIds = []
+				self.x2ENBConnectedUEs = []
+				self.x2ENBBsIds.append([])
+				self.x2ENBBsIds.append([])
+				self.x2ENBConnectedUEs.append([])
+				self.x2ENBConnectedUEs.append([])
+				fullMessage += self.X2_Status(0, self.testCase_id + '_pre_ho.json') 
+
+				msg = "Activating the X2 Net control on each eNB"
+				logging.debug(msg)
+				fullMessage += msg + '\n'
+				eNB_cnt = self.x2NbENBs
+				cnt = 0
+				while cnt < eNB_cnt:
+					cmd = "curl -XPOST http://" + EPC.GetIPAddress() + ":9999/rrc/x2_ho_net_control/enb/" + str(self.x2ENBBsIds[0][cnt]) + "/1"
+					logging.debug(cmd)
+					fullMessage += cmd + '\n'
+					subprocess.run(cmd, shell=True)
+					cnt += 1
+				# Waiting for the activation to be active
+				time.sleep(10)
+				msg = "Switching UE(s) from eNB to eNB"
+				logging.debug(msg)
+				fullMessage += msg + '\n'
+				cnt = 0
+				while cnt < eNB_cnt:
+					ueIdx = 0
+					while ueIdx < len(self.x2ENBConnectedUEs[0][cnt]):
+						cmd = "curl -XPOST http://" + EPC.GetIPAddress() + ":9999/rrc/ho/senb/" + str(self.x2ENBBsIds[0][cnt]) + "/ue/" + str(self.x2ENBConnectedUEs[0][cnt][ueIdx]) + "/tenb/" + str(self.x2ENBBsIds[0][eNB_cnt - cnt - 1])
+						logging.debug(cmd)
+						fullMessage += cmd + '\n'
+						subprocess.run(cmd, shell=True)
+						ueIdx += 1
+					cnt += 1
+				time.sleep(10)
+				# check
+				logging.debug("Checking the Status after X2 Handover")
+				fullMessage += self.X2_Status(1, self.testCase_id + '_post_ho.json') 
+				cnt = 0
+				x2Status = True
+				while cnt < eNB_cnt:
+					if len(self.x2ENBConnectedUEs[0][cnt]) == len(self.x2ENBConnectedUEs[1][cnt]):
+						x2Status = False
+					cnt += 1
+				if x2Status:
+					msg = "X2 Handover was successful"
+					logging.debug(msg)
+					fullMessage += msg + '
' + html_queue.put(fullMessage) + self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) + else: + msg = "X2 Handover FAILED" + logging.error(msg) + fullMessage += msg + '' + html_queue.put(fullMessage) + self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) + else: + self.CreateHtmlTestRow('Cannot perform requested X2 Handover', 'KO', ALL_PROCESSES_OK) + + def LogCollectBuild(self): + if (RAN.GeteNBIPAddress() != '' and RAN.GeteNBUserName() != '' and RAN.GeteNBPassword() != ''): + IPAddress = RAN.GeteNBIPAddress + UserName = RAN.GeteNBUserName + Password = RAN.GeteNBPassword + SourceCodePath = RAN.GeteNBSourceCodePath() + elif (self.UEIPAddress != '' and self.UEUserName != '' and self.UEPassword != ''): + IPAddress = self.UEIPAddress + UserName = self.UEUserName + Password = self.UEPassword + SourceCodePath = self.UESourceCodePath + else: + sys.exit('Insufficient Parameter') + SSH.open(IPAddress, UserName, Password) + SSH.command('cd ' + SourceCodePath, '\$', 5) + SSH.command('cd cmake_targets', '\$', 5) + SSH.command('rm -f build.log.zip', '\$', 5) + SSH.command('zip build.log.zip build_log_*/*', '\$', 60) + SSH.close() +''' + def LogCollecteNB(self): + SSH.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) + SSH.command('cd ' + RAN.GeteNBSourceCodePath(), '\$', 5) + SSH.command('cd cmake_targets', '\$', 5) + SSH.command('echo ' + self.eNBPassword + ' | sudo -S rm -f enb.log.zip', '\$', 5) + SSH.command('echo ' + self.eNBPassword + ' | sudo -S zip enb.log.zip enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 60) + SSH.command('echo ' + self.eNBPassword + ' | sudo -S rm enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 5) + SSH.close() +''' + def LogCollectPing(self): + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('cd ' + EPC.GetSourceCodePath(), '\$', 5) + SSH.command('cd scripts', '\$', 5) + SSH.command('rm -f ping.log.zip', '\$', 5) + SSH.command('zip ping.log.zip ping*.log', '\$', 60) + SSH.command('rm ping*.log', '\$', 5) + SSH.close() + + def LogCollectIperf(self): + SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + SSH.command('cd ' + EPC.GetSourceCodePath(), '\$', 5) + SSH.command('cd scripts', '\$', 5) + SSH.command('rm -f iperf.log.zip', '\$', 5) + SSH.command('zip iperf.log.zip iperf*.log', '\$', 60) + SSH.command('rm iperf*.log', '\$', 5) + SSH.close() + + def LogCollectOAIUE(self): + SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) + SSH.command('cd ' + self.UESourceCodePath, '\$', 5) + SSH.command('cd cmake_targets', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -f ue.log.zip', '\$', 5) + SSH.command('echo ' + self.UEPassword + ' | sudo -S zip ue.log.zip ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 60) + SSH.command('echo ' + self.UEPassword + ' | sudo -S rm ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 5) + SSH.close() + + def RetrieveSystemVersion(self, machine): + if RAN.GeteNBIPAddress() == 'none' or self.UEIPAddress == 'none': + self.OsVersion = 'Ubuntu 16.04.5 LTS' + self.KernelVersion = '4.15.0-45-generic' + self.UhdVersion = '3.13.0.1-0' + self.UsrpBoard = 'B210' + self.CpuNb = '4' + self.CpuModel = 'Intel(R) Core(TM) i5-6200U' + self.CpuMHz = '2399.996 MHz' + return 0 + if machine == 'eNB': + if RAN.GeteNBIPAddress() != '' and RAN.GeteNBUserName() != '' and RAN.GeteNBPassword() != '': + IPAddress = RAN.GeteNBIPAddress + UserName = RAN.GeteNBUserName + Password = RAN.GeteNBPassword + else: + return -1 + if machine == 'UE': + if self.UEIPAddress != '' and self.UEUserName != '' and self.UEPassword != '': + IPAddress = self.UEIPAddress + UserName = self.UEUserName + Password = self.UEPassword + else: + return -1 + + SSH.open(IPAddress, UserName, Password) + SSH.command('lsb_release -a', '\$', 5) + result = re.search('Description:\\\\t(?P[a-zA-Z0-9\-\_\.\ ]+)', SSH.getBefore()) + if result is not None: + self.OsVersion = result.group('os_type') + logging.debug('OS is: ' + self.OsVersion) + else: + SSH.command('hostnamectl', '\$', 5) + result = re.search('Operating System: (?P[a-zA-Z0-9\-\_\.\ ]+)', SSH.getBefore()) + if result is not None: + self.OsVersion = result.group('os_type') + if self.OsVersion == 'CentOS Linux 7 ': + SSH.command('cat /etc/redhat-release', '\$', 5) + result = re.search('CentOS Linux release (?P[0-9\.]+)', SSH.getBefore()) + if result is not None: + self.OsVersion = self.OsVersion.replace('7 ', result.group('os_version')) + logging.debug('OS is: ' + self.OsVersion) + SSH.command('uname -r', '\$', 5) + result = re.search('uname -r\\\\r\\\\n(?P[a-zA-Z0-9\-\_\.]+)', SSH.getBefore()) + if result is not None: + self.KernelVersion = result.group('kernel_version') + logging.debug('Kernel Version is: ' + self.KernelVersion) + SSH.command('dpkg --list | egrep --color=never libuhd003', '\$', 5) + result = re.search('libuhd003:amd64 *(?P[0-9\.]+)', SSH.getBefore()) + if result is not None: + self.UhdVersion = result.group('uhd_version') + logging.debug('UHD Version is: ' + self.UhdVersion) + else: + SSH.command('uhd_config_info --version', '\$', 5) + result = re.search('UHD (?P[a-zA-Z0-9\.\-]+)', SSH.getBefore()) + if result is not None: + self.UhdVersion = result.group('uhd_version') + logging.debug('UHD Version is: ' + self.UhdVersion) + SSH.command('echo ' + Password + ' | sudo -S uhd_find_devices', '\$', 30) + usrp_boards = re.findall('product: ([0-9A-Za-z]+)\\\\r\\\\n', SSH.getBefore()) + count = 0 + for board in usrp_boards: + if count == 0: + self.UsrpBoard = board + else: + self.UsrpBoard += ',' + board + count += 1 + if count > 0: + logging.debug('USRP Board(s) : ' + self.UsrpBoard) + SSH.command('lscpu', '\$', 5) + result = re.search('CPU\(s\): *(?P[0-9]+).*Model name: *(?P[a-zA-Z0-9\-\_\.\ \(\)]+).*CPU MHz: *(?P[0-9\.]+)', SSH.getBefore()) + if result is not None: + self.CpuNb = result.group('nb_cpus') + logging.debug('nb_cpus: ' + self.CpuNb) + self.CpuModel = result.group('model') + logging.debug('model: ' + self.CpuModel) + self.CpuMHz = result.group('cpu_mhz') + ' MHz' + logging.debug('cpu_mhz: ' + self.CpuMHz) + SSH.close() + +#----------------------------------------------------------- +# HTML Reporting.... +#----------------------------------------------------------- + def CreateHtmlHeader(self): + if (not self.htmlHeaderCreated): + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + logging.debug('\u001B[1m Creating HTML header \u001B[0m') + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + self.htmlFile = open('test_results.html', 'w') + self.htmlFile.write('\n') + self.htmlFile.write('\n') + self.htmlFile.write('\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Test Results for TEMPLATE_JOB_NAME job build #TEMPLATE_BUILD_ID\n') + self.htmlFile.write('\n') + self.htmlFile.write('
\n') + self.htmlFile.write('
\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write('
\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Job Summary -- Job: TEMPLATE_JOB_NAME -- Build-ID: TEMPLATE_BUILD_ID\n') + self.htmlFile.write('
\n') + self.htmlFile.write('
\n') + self.htmlFile.write('
TEMPLATE_STAGE_NAME
\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (RAN.GetranAllowMerge): + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (RAN.GetranAllowMerge): + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (RAN.GetranAllowMerge): + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if RAN.GetranAllowMerge() != '': + commit_message = subprocess.check_output("git log -n1 --pretty=format:\"%s\" " + RAN.GetranCommitID, shell=True, universal_newlines=True) + commit_message = commit_message.strip() + self.htmlFile.write(' \n') + if (RAN.GetranAllowMerge): + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (RAN.GetranAllowMerge): + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (RAN.GetranTargetBranch() == ''): + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write('
Build Start Time (UTC) TEMPLATE_BUILD_TIME
GIT Repository ' + RAN.GetranRepository() + '
Job Trigger Merge-RequestPush to Branch
Source Branch Branch' + RAN.GetranBranch() + '
Source Commit ID Commit ID ' + RAN.GetranCommitID() + '
Source Commit Message Commit Message ' + commit_message + '
Target Branch develop' + RAN.GetranTargetBranch() + '
\n') + + if (self.ADBIPAddress != 'none'): + terminate_ue_flag = True + self.GetAllUEDevices(terminate_ue_flag) + self.GetAllCatMDevices(terminate_ue_flag) + self.htmlUEConnected = len(self.UEDevices) + self.htmlFile.write('

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

\n') + self.htmlFile.write('

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

\n') + else: + self.UEDevices.append('OAI-UE') + self.htmlUEConnected = len(self.UEDevices) + self.htmlFile.write('

' + str(len(self.UEDevices)) + ' OAI UE(s) is(are) connected to CI bench

\n') + self.htmlFile.write('
\n') + self.htmlFile.write(' \n') + self.htmlFile.write('
\n') + self.htmlFile.close() + + def CreateHtmlTabHeader(self): + if (not self.htmlHeaderCreated): + if (not os.path.isfile('test_results.html')): + self.CreateHtmlHeader() + self.htmlFile = open('test_results.html', 'a') + if (self.nbTestXMLfiles == 1): + self.htmlFile.write('
\n') + self.htmlFile.write('

Test Summary for ' + self.testXMLfiles[0] + '

\n') + else: + self.htmlFile.write('
\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (self.htmlUEConnected == -1): + terminate_ue_flag = True + if (self.ADBIPAddress != 'none'): + self.GetAllUEDevices(terminate_ue_flag) + self.GetAllCatMDevices(terminate_ue_flag) + else: + self.UEDevices.append('OAI-UE') + self.htmlUEConnected = len(self.UEDevices) + + i = 0 + while (i < self.htmlUEConnected): + self.htmlFile.write(' \n') + i += 1 + self.htmlFile.write(' \n') + self.htmlHeaderCreated = True + + def CreateHtmlTabFooter(self, passStatus): + if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if passStatus: + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write('
Relative Time (ms)Test IdTest DescTest OptionsTest StatusUE' + str(i) + ' Status
Final Tab StatusPASS FAIL
\n') + self.htmlFile.write('
\n') + self.htmlFile.close() + time.sleep(1) + if passStatus: + cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__//' test_results.html" + subprocess.run(cmd, shell=True) + else: + cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__/<\/span>/' test_results.html" + subprocess.run(cmd, shell=True) + self.htmlFooterCreated = False + + def CreateHtmlFooter(self, passStatus): + if (os.path.isfile('test_results.html')): + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + logging.debug('\u001B[1m Creating HTML footer \u001B[0m') + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + + self.htmlFile = open('test_results.html', 'a') + self.htmlFile.write('
\n') + self.htmlFile.write('

\n') + self.htmlFile.write(' \n') + + machines = [ 'eNB', 'UE' ] + for machine in machines: + res = self.RetrieveSystemVersion(machine) + if res == -1: + continue + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if passStatus: + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write('
' + str(machine) + ' Server Characteristics
OS Version' + self.OsVersion + 'Kernel Version' + self.KernelVersion + 'UHD Version' + self.UhdVersion + 'USRP Board' + self.UsrpBoard + '
Nb CPUs' + self.CpuNb + 'CPU Model Name' + self.CpuModel + 'CPU Frequency' + self.CpuMHz + '
Final StatusPASS FAIL
\n') + self.htmlFile.write('

\n') + self.htmlFile.write('
End of Test Report -- Copyright 2018 OpenAirInterface. All Rights Reserved.
\n') + self.htmlFile.write('
\n') + self.htmlFile.write('\n') + self.htmlFile.close() + + def CreateHtmlRetrySeparator(self): + if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): + self.htmlFile.write(' \n') + self.htmlFile.write(' Try Run #' + str(self.FailReportCnt) + '\n') + self.htmlFile.write(' \n') + + def CreateHtmlTestRow(self, options, status, processesStatus, machine='eNB'): + if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): + currentTime = int(round(time.time() * 1000)) - self.startTime + self.htmlFile.write(' \n') + self.htmlFile.write(' ' + format(currentTime / 1000, '.1f') + '\n') + self.htmlFile.write(' ' + self.testCase_id + '\n') + self.htmlFile.write(' ' + self.desc + '\n') + self.htmlFile.write(' ' + str(options) + '\n') + if (str(status) == 'OK'): + self.htmlFile.write(' ' + str(status) + '\n') + elif (str(status) == 'KO'): + if (processesStatus == 0): + self.htmlFile.write(' ' + str(status) + '\n') + elif (processesStatus == ENB_PROCESS_FAILED): + self.htmlFile.write(' KO - eNB process not found\n') + elif (processesStatus == OAI_UE_PROCESS_FAILED): + self.htmlFile.write(' KO - OAI UE process not found\n') + elif (processesStatus == ENB_PROCESS_SEG_FAULT) or (processesStatus == OAI_UE_PROCESS_SEG_FAULT): + self.htmlFile.write(' KO - ' + machine + ' process ended in Segmentation Fault\n') + elif (processesStatus == ENB_PROCESS_ASSERTION) or (processesStatus == OAI_UE_PROCESS_ASSERTION): + self.htmlFile.write(' KO - ' + machine + ' process ended in Assertion\n') + elif (processesStatus == ENB_PROCESS_REALTIME_ISSUE): + self.htmlFile.write(' KO - ' + machine + ' process faced Real Time issue(s)\n') + elif (processesStatus == ENB_PROCESS_NOLOGFILE_TO_ANALYZE) or (processesStatus == OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE): + self.htmlFile.write(' OK?\n') + elif (processesStatus == ENB_PROCESS_SLAVE_RRU_NOT_SYNCED): + self.htmlFile.write(' KO - ' + machine + ' Slave RRU could not synch\n') + elif (processesStatus == OAI_UE_PROCESS_COULD_NOT_SYNC): + self.htmlFile.write(' KO - UE could not sync\n') + elif (processesStatus == HSS_PROCESS_FAILED): + self.htmlFile.write(' KO - HSS process not found\n') + elif (processesStatus == MME_PROCESS_FAILED): + self.htmlFile.write(' KO - MME process not found\n') + elif (processesStatus == SPGW_PROCESS_FAILED): + self.htmlFile.write(' KO - SPGW process not found\n') + elif (processesStatus == UE_IP_ADDRESS_ISSUE): + self.htmlFile.write(' KO - Could not retrieve UE IP address\n') + else: + self.htmlFile.write(' ' + str(status) + '\n') + else: + self.htmlFile.write(' ' + str(status) + '\n') + if (len(str(self.htmleNBFailureMsg)) > 2): + cellBgColor = 'white' + result = re.search('ended with|faced real time issues', self.htmleNBFailureMsg) + if result is not None: + cellBgColor = 'red' + else: + result = re.search('showed|Reestablishment|Could not copy eNB logfile', self.htmleNBFailureMsg) + if result is not None: + cellBgColor = 'orange' + self.htmlFile.write('
' + self.htmleNBFailureMsg + '
\n') + self.htmleNBFailureMsg = '' + elif (len(str(self.htmlUEFailureMsg)) > 2): + cellBgColor = 'white' + result = re.search('ended with|faced real time issues', self.htmlUEFailureMsg) + if result is not None: + cellBgColor = 'red' + else: + result = re.search('showed|Could not copy UE logfile|oaitun_ue1 interface is either NOT mounted or NOT configured', self.htmlUEFailureMsg) + if result is not None: + cellBgColor = 'orange' + self.htmlFile.write('
' + self.htmlUEFailureMsg + '
\n') + self.htmlUEFailureMsg = '' + else: + i = 0 + while (i < self.htmlUEConnected): + self.htmlFile.write(' -\n') + i += 1 + self.htmlFile.write(' \n') + + def CreateHtmlTestRowQueue(self, options, status, ue_status, ue_queue): + if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): + currentTime = int(round(time.time() * 1000)) - self.startTime + addOrangeBK = False + self.htmlFile.write(' \n') + self.htmlFile.write(' ' + format(currentTime / 1000, '.1f') + '\n') + self.htmlFile.write(' ' + self.testCase_id + '\n') + self.htmlFile.write(' ' + self.desc + '\n') + self.htmlFile.write(' ' + str(options) + '\n') + if (str(status) == 'OK'): + self.htmlFile.write(' ' + str(status) + '\n') + elif (str(status) == 'KO'): + self.htmlFile.write(' ' + str(status) + '\n') + else: + addOrangeBK = True + self.htmlFile.write(' ' + str(status) + '\n') + i = 0 + while (i < self.htmlUEConnected): + if (i < ue_status): + if (not ue_queue.empty()): + if (addOrangeBK): + self.htmlFile.write(' ' + str(ue_queue.get()).replace('white', 'orange') + '\n') + else: + self.htmlFile.write(' ' + str(ue_queue.get()) + '\n') + else: + self.htmlFile.write(' -\n') + else: + self.htmlFile.write(' -\n') + i += 1 + self.htmlFile.write(' \n') + +#----------------------------------------------------------- +# ShowTestID() +#----------------------------------------------------------- + def ShowTestID(self): + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + logging.debug('\u001B[1mTest ID:' + self.testCase_id + '\u001B[0m') + logging.debug('\u001B[1m' + self.desc + '\u001B[0m') + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + +def CheckClassValidity(action,id): + if action != 'Build_eNB' and action != 'WaitEndBuild_eNB' and action != 'Initialize_eNB' and action != 'Terminate_eNB' and action != 'Initialize_UE' and action != 'Terminate_UE' and action != 'Attach_UE' and action != 'Detach_UE' and action != 'Build_OAI_UE' and action != 'Initialize_OAI_UE' and action != 'Terminate_OAI_UE' and action != 'DataDisable_UE' and action != 'DataEnable_UE' and action != 'CheckStatusUE' and action != 'Ping' and action != 'Iperf' and action != 'Reboot_UE' and action != 'Initialize_FlexranCtrl' and action != 'Terminate_FlexranCtrl' and action != 'Initialize_HSS' and action != 'Terminate_HSS' and action != 'Initialize_MME' and action != 'Terminate_MME' and action != 'Initialize_SPGW' and action != 'Terminate_SPGW' and action != 'Initialize_CatM_module' and action != 'Terminate_CatM_module' and action != 'Attach_CatM_module' and action != 'Detach_CatM_module' and action != 'Ping_CatM_module' and action != 'IdleSleep' and action != 'Perform_X2_Handover': + logging.debug('ERROR: test-case ' + id + ' has wrong class ' + action) + return False + return True + +def GetParametersFromXML(action): + if action == 'Build_eNB': + RAN.SetBuild_eNB_args() = test.findtext('Build_eNB_args') + forced_workspace_cleanup = test.findtext('forced_workspace_cleanup') + if (forced_workspace_cleanup is None): + RAN.SetBuild_eNB_forced_workspace_cleanup() = False + else: + if re.match('true', forced_workspace_cleanup, re.IGNORECASE): + RAN.SetBuild_eNB_forced_workspace_cleanup() = True + else: + RAN.SetBuild_eNB_forced_workspace_cleanup() = False + RAN.SeteNB_instance() = test.findtext('eNB_instance') + if (RAN.GeteNB_instance() is None): + RAN.SeteNB_instance() = '0' + CiTestObj.eNB_serverId = test.findtext('eNB_serverId') + if (CiTestObj.eNB_serverId is None): + CiTestObj.eNB_serverId = '0' + xmlBgBuildField = test.findtext('backgroundBuild') + if (xmlBgBuildField is None): + RAN.SetbackgroundBuild() = False + else: + if re.match('true', xmlBgBuildField, re.IGNORECASE): + RAN.SetbackgroundBuild() = True + else: + RAN.SetbackgroundBuild() = False + + if action == 'WaitEndBuild_eNB': + RAN.SetBuild_eNB_args() = test.findtext('Build_eNB_args') + RAN.SeteNB_instance() = test.findtext('eNB_instance') + if (RAN.GeteNB_instance() is None): + RAN.SeteNB_instance() = '0' + CiTestObj.eNB_serverId = test.findtext('eNB_serverId') + if (CiTestObj.eNB_serverId is None): + CiTestObj.eNB_serverId = '0' + + if action == 'Initialize_eNB': + RAN.SetInitialize_eNB_args() = test.findtext('Initialize_eNB_args') + RAN.SeteNB_instance() = test.findtext('eNB_instance') + if (RAN.GeteNB_instance() is None): + RAN.SeteNB_instance = '0' + CiTestObj.eNB_serverId = test.findtext('eNB_serverId') + if (CiTestObj.eNB_serverId is None): + CiTestObj.eNB_serverId = '0' + CiTestObj.air_interface = test.findtext('air_interface') + if (CiTestObj.air_interface is None): + CiTestObj.air_interface = 'lte' + else: + CiTestObj.air_interface = CiTestObj.air_interface.lower() + + if action == 'Terminate_eNB': + RAN.SeteNB_instance() = test.findtext('eNB_instance') + if (RAN.GeteNB_instance() is None): + RAN.SeteNB_instance() = '0' + CiTestObj.eNB_serverId = test.findtext('eNB_serverId') + if (CiTestObj.eNB_serverId is None): + CiTestObj.eNB_serverId = '0' + CiTestObj.air_interface = test.findtext('air_interface') + if (CiTestObj.air_interface is None): + CiTestObj.air_interface = 'lte' + else: + CiTestObj.air_interface = CiTestObj.air_interface.lower() + + if action == 'Attach_UE': + nbMaxUEtoAttach = test.findtext('nbMaxUEtoAttach') + if (nbMaxUEtoAttach is None): + CiTestObj.nbMaxUEtoAttach = -1 + else: + CiTestObj.nbMaxUEtoAttach = int(nbMaxUEtoAttach) + + if action == 'CheckStatusUE': + expectedNBUE = test.findtext('expectedNbOfConnectedUEs') + if (expectedNBUE is None): + CiTestObj.expectedNbOfConnectedUEs = -1 + else: + CiTestObj.expectedNbOfConnectedUEs = int(expectedNBUE) + + if action == 'Build_OAI_UE': + CiTestObj.Build_OAI_UE_args = test.findtext('Build_OAI_UE_args') + CiTestObj.clean_repository = test.findtext('clean_repository') + if (CiTestObj.clean_repository == 'false'): + CiTestObj.clean_repository = False + else: + CiTestObj.clean_repository = True + + if action == 'Initialize_OAI_UE': + CiTestObj.Initialize_OAI_UE_args = test.findtext('Initialize_OAI_UE_args') + CiTestObj.UE_instance = test.findtext('UE_instance') + if (CiTestObj.UE_instance is None): + CiTestObj.UE_instance = '0' + CiTestObj.air_interface = test.findtext('air_interface') + if (CiTestObj.air_interface is None): + CiTestObj.air_interface = 'lte' + else: + CiTestObj.air_interface = SSH.air_interface.lower() + + if action == 'Terminate_OAI_UE': + RAN.SeteNB_instance = test.findtext('UE_instance') + if (CiTestObj.UE_instance is None): + CiTestObj.UE_instance = '0' + + if action == 'Ping' or action == 'Ping_CatM_module': + CiTestObj.ping_args = test.findtext('ping_args') + CiTestObj.ping_packetloss_threshold = test.findtext('ping_packetloss_threshold') + + if action == 'Iperf': + CiTestObj.iperf_args = test.findtext('iperf_args') + CiTestObj.iperf_packetloss_threshold = test.findtext('iperf_packetloss_threshold') + CiTestObj.iperf_profile = test.findtext('iperf_profile') + if (CiTestObj.iperf_profile is None): + CiTestObj.iperf_profile = 'balanced' + else: + if CiTestObj.iperf_profile != 'balanced' and CiTestObj.iperf_profile != 'unbalanced' and CiTestObj.iperf_profile != 'single-ue': + logging.debug('ERROR: test-case has wrong profile ' + CiTestObj.iperf_profile) + CiTestObj.iperf_profile = 'balanced' + CiTestObj.iperf_options = test.findtext('iperf_options') + if (CiTestObj.iperf_options is None): + CiTestObj.iperf_options = 'check' + else: + if CiTestObj.iperf_options != 'check' and CiTestObj.iperf_options != 'sink': + logging.debug('ERROR: test-case has wrong option ' + CiTestObj.iperf_options) + CiTestObj.iperf_options = 'check' + + if action == 'IdleSleep': + string_field = test.findtext('idle_sleep_time_in_sec') + if (string_field is None): + CiTestObj.idle_sleep_time = 5 + else: + CiTestObj.idle_sleep_time = int(string_field) + + if action == 'Perform_X2_Handover': + string_field = test.findtext('x2_ho_options') + if (string_field is None): + CiTestObj.x2_ho_options = 'network' + else: + if string_field != 'network': + logging.error('ERROR: test-case has wrong option ' + string_field) + CiTestObj.x2_ho_options = 'network' + else: + CiTestObj.x2_ho_options = string_field + + +#check if given test is in list +#it is in list if one of the strings in 'list' is at the beginning of 'test' +def test_in_list(test, list): + for check in list: + check=check.replace('+','') + if (test.startswith(check)): + return True + return False + +def receive_signal(signum, frame): + sys.exit(1) + +#----------------------------------------------------------- +# Parameter Check +#----------------------------------------------------------- +mode = '' +CiTestObj = OaiCiTest() + +from sshconnection import * +from epc import * +from helpreadme import * +from enb import * +SSH = SSHConnection() +EPC = EPCManagement() +RAN = RANManagement() +#HELP = HelpReadme() +#HELP.GenericHelp() + +argvs = sys.argv +argc = len(argvs) +cwd = os.getcwd() + +while len(argvs) > 1: + myArgv = argvs.pop(1) # 0th is this file's name + if re.match('^\-\-help$', myArgv, re.IGNORECASE): + GenericHelp(Version) + sys.exit(0) + elif re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE) + mode = matchReg.group(1) + elif re.match('^\-\-eNBRepository=(.+)$|^\-\-ranRepository(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE) + else: + matchReg = re.match('^\-\-ranRepository=(.+)$', myArgv, re.IGNORECASE) + RAN.SetranRepository() = matchReg.group(1) + elif re.match('^\-\-eNB_AllowMerge=(.+)$|^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE) + else: + matchReg = re.match('^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE) + doMerge = matchReg.group(1) + if ((doMerge == 'true') or (doMerge == 'True')): + RAN.SetranAllowMerge() = True + elif re.match('^\-\-eNBBranch=(.+)$|^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE) + else: + matchReg = re.match('^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE) + RAN.SetranBranch() = matchReg.group(1) + elif re.match('^\-\-eNBCommitID=(.*)$|^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE) + else: + matchReg = re.match('^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE) + RAN.SetranCommitID() = matchReg.group(1) + elif re.match('^\-\-eNBTargetBranch=(.*)$|^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE) + else: + matchReg = re.match('^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE) + RAN.SetranTargetBranch() = matchReg.group(1) + elif re.match('^\-\-eNBIPAddress=(.+)$|^\-\-eNB[1-2]IPAddress=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE) + RAN.SeteNBIPAddress() = matchReg.group(1) + elif re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE) + RAN.SeteNB1IPAddress() = matchReg.group(1) + elif re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE) + RAN.SeteNB2IPAddress() = matchReg.group(1) + elif re.match('^\-\-eNBUserName=(.+)$|^\-\-eNB[1-2]UserName=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE) + RAN.SeteNBUserName() = matchReg.group(1) + elif re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE) + RAN.SeteNB1UserName() = matchReg.group(1) + elif re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE) + RAN.SeteNB2UserName() = matchReg.group(1) + elif re.match('^\-\-eNBPassword=(.+)$|^\-\-eNB[1-2]Password=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE) + RAN.SeteNBPassword() = matchReg.group(1) + elif re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE) + RAN.SeteNB1Password() = matchReg.group(1) + elif re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE) + RAN.SeteNB2Password() = matchReg.group(1) + elif re.match('^\-\-eNBSourceCodePath=(.+)$|^\-\-eNB[1-2]SourceCodePath=(.+)$', myArgv, re.IGNORECASE): + if re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE) + RAN.SeteNBSourceCodePath() = matchReg.group(1) + elif re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE) + RAN.SeteNB1SourceCodePath() = matchReg.group(1) + elif re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE) + RAN.SeteNB2SourceCodePath() = matchReg.group(1) + elif re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE) + EPC.SetIPAddress(matchReg.group(1)) + elif re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE) + CiTestObj.EPCBranch = matchReg.group(1) + elif re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE) + EPC.SetUserName(matchReg.group(1)) + elif re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE) + EPC.SetPassword(matchReg.group(1)) + elif re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE) + EPC.SetSourceCodePath(matchReg.group(1)) + elif re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE) + if re.match('OAI', matchReg.group(1), re.IGNORECASE) or re.match('ltebox', matchReg.group(1), re.IGNORECASE) or re.match('OAI-Rel14-CUPS', matchReg.group(1), re.IGNORECASE): + EPC.SetType(matchReg.group(1)) + else: + sys.exit('Invalid EPC Type: ' + matchReg.group(1) + ' -- (should be OAI or ltebox or OAI-Rel14-CUPS)') + elif re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE) + CiTestObj.ADBIPAddress = matchReg.group(1) + elif re.match('^\-\-ADBUserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-ADBUserName=(.+)$', myArgv, re.IGNORECASE) + CiTestObj.ADBUserName = matchReg.group(1) + elif re.match('^\-\-ADBType=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-ADBType=(.+)$', myArgv, re.IGNORECASE) + if re.match('centralized', matchReg.group(1), re.IGNORECASE) or re.match('distributed', matchReg.group(1), re.IGNORECASE): + if re.match('distributed', matchReg.group(1), re.IGNORECASE): + CiTestObj.ADBCentralized = False + else: + CiTestObj.ADBCentralized = True + else: + sys.exit('Invalid ADB Type: ' + matchReg.group(1) + ' -- (should be centralized or distributed)') + elif re.match('^\-\-ADBPassword=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-ADBPassword=(.+)$', myArgv, re.IGNORECASE) + CiTestObj.ADBPassword = matchReg.group(1) + elif re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE) + CiTestObj.testXMLfiles.append(matchReg.group(1)) + CiTestObj.nbTestXMLfiles += 1 + elif re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE) + CiTestObj.UEIPAddress = matchReg.group(1) + elif re.match('^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE) + CiTestObj.UEUserName = matchReg.group(1) + elif re.match('^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE) + CiTestObj.UEPassword = matchReg.group(1) + elif re.match('^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE) + CiTestObj.UESourceCodePath = matchReg.group(1) + elif re.match('^\-\-finalStatus=(.+)$', myArgv, re.IGNORECASE): + matchReg = re.match('^\-\-finalStatus=(.+)$', myArgv, re.IGNORECASE) + finalStatus = matchReg.group(1) + if ((finalStatus == 'true') or (finalStatus == 'True')): + CiTestObj.finalStatus = True + else: + GenericHelp(Version) + sys.exit('Invalid Parameter: ' + myArgv) + +if re.match('^TerminateeNB$', mode, re.IGNORECASE): + if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + CiTestObj.eNB_serverId = '0' + RAN.SeteNB_instance = '0' + RAN.GeteNBSourceCodePath() = '/tmp/' + CiTestObj.TerminateeNB() +elif re.match('^TerminateUE$', mode, re.IGNORECASE): + if (CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == ''): + GenericHelp(Version) + sys.exit('Insufficient Parameter') + signal.signal(signal.SIGUSR1, receive_signal) + CiTestObj.TerminateUE() +elif re.match('^TerminateOAIUE$', mode, re.IGNORECASE): + if CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + signal.signal(signal.SIGUSR1, receive_signal) + CiTestObj.TerminateOAIUE() +elif re.match('^TerminateHSS$', mode, re.IGNORECASE): + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + CiTestObj.TerminateHSS() +elif re.match('^TerminateMME$', mode, re.IGNORECASE): + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + CiTestObj.TerminateMME() +elif re.match('^TerminateSPGW$', mode, re.IGNORECASE): + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + CiTestObj.TerminateSPGW() +elif re.match('^LogCollectBuild$', mode, re.IGNORECASE): + if (RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '') and (CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == ''): + GenericHelp(Version) + sys.exit('Insufficient Parameter') + CiTestObj.LogCollectBuild() +elif re.match('^LogCollecteNB$', mode, re.IGNORECASE): + if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + CiTestObj.LogCollecteNB() +elif re.match('^LogCollectHSS$', mode, re.IGNORECASE): + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + EPC.LogCollectHSS() +elif re.match('^LogCollectMME$', mode, re.IGNORECASE): + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + EPC.LogCollectMME() +elif re.match('^LogCollectSPGW$', mode, re.IGNORECASE): + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + EPC.LogCollectSPGW() +elif re.match('^LogCollectPing$', mode, re.IGNORECASE): + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + CiTestObj.LogCollectPing() +elif re.match('^LogCollectIperf$', mode, re.IGNORECASE): + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + CiTestObj.LogCollectIperf() +elif re.match('^LogCollectOAIUE$', mode, re.IGNORECASE): + if CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + CiTestObj.LogCollectOAIUE() +elif re.match('^InitiateHtml$', mode, re.IGNORECASE): + if (CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == ''): + GenericHelp(Version) + sys.exit('Insufficient Parameter') + count = 0 + foundCount = 0 + while (count < CiTestObj.nbTestXMLfiles): + #xml_test_file = cwd + "/" + CiTestObj.testXMLfiles[count] + xml_test_file = sys.path[0] + "/" + CiTestObj.testXMLfiles[count] + if (os.path.isfile(xml_test_file)): + try: + xmlTree = ET.parse(xml_test_file) + except: + print("Error while parsing file: " + xml_test_file) + xmlRoot = xmlTree.getroot() + CiTestObj.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count))) + CiTestObj.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-' + str(count))) + CiTestObj.htmlTabIcons.append(xmlRoot.findtext('htmlTabIcon',default='info-sign')) + foundCount += 1 + count += 1 + if foundCount != CiTestObj.nbTestXMLfiles: + CiTestObj.nbTestXMLfiles = foundCount + CiTestObj.CreateHtmlHeader() +elif re.match('^FinalizeHtml$', mode, re.IGNORECASE): + CiTestObj.CreateHtmlFooter(CiTestObj.finalStatus) +elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re.IGNORECASE): + if re.match('^TesteNB$', mode, re.IGNORECASE): + if RAN.GeteNBIPAddress() == '' or RAN.GetranRepository() == '' or RAN.GetranBranch() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '' or EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '' or CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == '': + GenericHelp(Version) + if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '' or EPC.GetType() == '': + EPCSrvHelp(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), EPC.GetSourceCodePath(), EPC.GetType()) + # Gabriele: other if conditions relevant to eNB etc. to be added + sys.exit('Insufficient Parameter') + + if (EPC.GetIPAddress() != '') and (EPC.GetIPAddress() != 'none'): + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), cwd + "/tcp_iperf_stats.awk", "/tmp") + SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), cwd + "/active_net_interfaces.awk", "/tmp") + else: + if CiTestObj.UEIPAddress == '' or RAN.GetranRepository() == '' or RAN.GetranBranch() == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == '': + GenericHelp(Version) + sys.exit('UE: Insufficient Parameter') + + #read test_case_list.xml file + # if no parameters for XML file, use default value + if (CiTestObj.nbTestXMLfiles != 1): + xml_test_file = cwd + "/test_case_list.xml" + else: + xml_test_file = cwd + "/" + CiTestObj.testXMLfiles[0] + + xmlTree = ET.parse(xml_test_file) + xmlRoot = xmlTree.getroot() + + exclusion_tests=xmlRoot.findtext('TestCaseExclusionList',default='') + requested_tests=xmlRoot.findtext('TestCaseRequestedList',default='') + if (CiTestObj.nbTestXMLfiles == 1): + CiTestObj.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-0')) + CiTestObj.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-0')) + repeatCount = xmlRoot.findtext('repeatCount',default='1') + CiTestObj.repeatCounts.append(int(repeatCount)) + all_tests=xmlRoot.findall('testCase') + + exclusion_tests=exclusion_tests.split() + requested_tests=requested_tests.split() + + #check that exclusion tests are well formatted + #(6 digits or less than 6 digits followed by +) + for test in exclusion_tests: + if (not re.match('^[0-9]{6}$', test) and + not re.match('^[0-9]{1,5}\+$', test)): + logging.debug('ERROR: exclusion test is invalidly formatted: ' + test) + sys.exit(1) + else: + logging.debug(test) + + #check that requested tests are well formatted + #(6 digits or less than 6 digits followed by +) + #be verbose + for test in requested_tests: + if (re.match('^[0-9]{6}$', test) or + re.match('^[0-9]{1,5}\+$', test)): + logging.debug('INFO: test group/case requested: ' + test) + else: + logging.debug('ERROR: requested test is invalidly formatted: ' + test) + sys.exit(1) + if (EPC.GetIPAddress() != '') and (EPC.GetIPAddress() != 'none'): + CiTestObj.CheckFlexranCtrlInstallation() + + #get the list of tests to be done + todo_tests=[] + for test in requested_tests: + if (test_in_list(test, exclusion_tests)): + logging.debug('INFO: test will be skipped: ' + test) + else: + #logging.debug('INFO: test will be run: ' + test) + todo_tests.append(test) + + signal.signal(signal.SIGUSR1, receive_signal) + + CiTestObj.CreateHtmlTabHeader() + + CiTestObj.FailReportCnt = 0 + CiTestObj.prematureExit = True + CiTestObj.startTime = int(round(time.time() * 1000)) + while CiTestObj.FailReportCnt < CiTestObj.repeatCounts[0] and CiTestObj.prematureExit: + CiTestObj.prematureExit = False + # At every iteratin of the retry loop, a separator will be added + CiTestObj.CreateHtmlRetrySeparator() + for test_case_id in todo_tests: + if CiTestObj.prematureExit: + break + for test in all_tests: + if CiTestObj.prematureExit: + break + id = test.get('id') + if test_case_id != id: + continue + CiTestObj.testCase_id = id + CiTestObj.desc = test.findtext('desc') + action = test.findtext('class') + if (CheckClassValidity(action, id) == False): + continue + CiTestObj.ShowTestID() + GetParametersFromXML(action) + if action == 'Initialize_UE' or action == 'Attach_UE' or action == 'Detach_UE' or action == 'Ping' or action == 'Iperf' or action == 'Reboot_UE' or action == 'DataDisable_UE' or action == 'DataEnable_UE' or action == 'CheckStatusUE': + if (CiTestObj.ADBIPAddress != 'none'): + terminate_ue_flag = False + CiTestObj.GetAllUEDevices(terminate_ue_flag) + if action == 'Build_eNB': + RAN.BuildeNB() + elif action == 'WaitEndBuild_eNB': + RAN.WaitBuildeNBisFinished() + elif action == 'Initialize_eNB': + RAN.InitializeeNB() + elif action == 'Terminate_eNB': + RAN.TerminateeNB() + elif action == 'Initialize_UE': + CiTestObj.InitializeUE() + elif action == 'Terminate_UE': + CiTestObj.TerminateUE() + elif action == 'Attach_UE': + CiTestObj.AttachUE() + elif action == 'Detach_UE': + CiTestObj.DetachUE() + elif action == 'DataDisable_UE': + CiTestObj.DataDisableUE() + elif action == 'DataEnable_UE': + CiTestObj.DataEnableUE() + elif action == 'CheckStatusUE': + CiTestObj.CheckStatusUE() + elif action == 'Build_OAI_UE': + CiTestObj.BuildOAIUE() + elif action == 'Initialize_OAI_UE': + CiTestObj.InitializeOAIUE() + elif action == 'Terminate_OAI_UE': + CiTestObj.TerminateOAIUE() + elif action == 'Initialize_CatM_module': + CiTestObj.InitializeCatM() + elif action == 'Terminate_CatM_module': + CiTestObj.TerminateCatM() + elif action == 'Attach_CatM_module': + CiTestObj.AttachCatM() + elif action == 'Detach_CatM_module': + CiTestObj.TerminateCatM() + elif action == 'Ping_CatM_module': + CiTestObj.PingCatM() + elif action == 'Ping': + CiTestObj.Ping() + elif action == 'Iperf': + CiTestObj.Iperf() + elif action == 'Reboot_UE': + CiTestObj.RebootUE() + elif action == 'Initialize_HSS': + EPC.InitializeHSS() + elif action == 'Terminate_HSS': + EPC.TerminateHSS() + elif action == 'Initialize_MME': + EPC.InitializeMME() + elif action == 'Terminate_MME': + EPC.TerminateMME() + elif action == 'Initialize_SPGW': + EPC.InitializeSPGW() + elif action == 'Terminate_SPGW': + EPC.TerminateSPGW() + elif action == 'Initialize_FlexranCtrl': + CiTestObj.InitializeFlexranCtrl() + elif action == 'Terminate_FlexranCtrl': + CiTestObj.TerminateFlexranCtrl() + elif action == 'IdleSleep': + CiTestObj.IdleSleep() + elif action == 'Perform_X2_Handover': + CiTestObj.Perform_X2_Handover() + else: + sys.exit('Invalid action') + CiTestObj.FailReportCnt += 1 + if CiTestObj.FailReportCnt == CiTestObj.repeatCounts[0] and CiTestObj.prematureExit: + logging.debug('Testsuite failed ' + str(CiTestObj.FailReportCnt) + ' time(s)') + CiTestObj.CreateHtmlTabFooter(False) + sys.exit('Failed Scenario') + else: + logging.info('Testsuite passed after ' + str(CiTestObj.FailReportCnt) + ' time(s)') + CiTestObj.CreateHtmlTabFooter(True) +else: + GenericHelp(Version) + sys.exit('Invalid mode') +sys.exit(0) diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py new file mode 100644 index 0000000000..2145557343 --- /dev/null +++ b/ci-scripts/ran.py @@ -0,0 +1,765 @@ +#----------------------------------------------------------- +# Import +#----------------------------------------------------------- +import sys # arg +import re # reg +import logging +import os +import time +from multiprocessing import Process, Lock, SimpleQueue + +#----------------------------------------------------------- +# OAI Testing modules +#----------------------------------------------------------- +import sshconnection as mySSH +#from sshconnection import mySSHConnection as mySSH +import helpreadme as HELP +import constants as CONST + + +#----------------------------------------------------------- +# Class Declaration +#----------------------------------------------------------- +class RANManagement(): + def __init__(self): + # self.FailReportCnt = 0 + # self.prematureExit = False + self.ranRepository = '' + self.ranBranch = '' + self.ranAllowMerge = False + self.ranCommitID = '' + self.ranTargetBranch = '' + self.eNBIPAddress = '' + self.eNBUserName = '' + self.eNBPassword = '' + self.eNBSourceCodePath = '' + self.eNB1IPAddress = '' + self.eNB1UserName = '' + self.eNB1Password = '' + self.eNB1SourceCodePath = '' + self.eNB2IPAddress = '' + self.eNB2UserName = '' + self.eNB2Password = '' + self.eNB2SourceCodePath = '' + #self.ADBIPAddress = '' + #self.ADBUserName = '' + #self.ADBPassword = '' + #self.ADBCentralized = True + #self.testCase_id = '' + #self.testXMLfiles = [] + #self.nbTestXMLfiles = 0 + #self.desc = '' + self.Build_eNB_args = '' + self.backgroundBuild = False + self.backgroundBuildTestId = ['', '', ''] + self.Build_eNB_forced_workspace_cleanup = False + self.Initialize_eNB_args = '' + self.air_interface = 'lte' + self.eNB_instance = '' + self.eNB_serverId = '' + self.eNBLogFiles = ['', '', ''] + self.eNBOptions = ['', '', ''] + self.eNBmbmsEnables = [False, False, False] + self.eNBstatuses = [-1, -1, -1] + #self.ping_args = '' + #self.ping_packetloss_threshold = '' + #self.iperf_args = '' + #self.iperf_packetloss_threshold = '' + #self.iperf_profile = '' + #self.iperf_options = '' + #self.nbMaxUEtoAttach = -1 + #self.UEDevices = [] + #self.UEDevicesStatus = [] + #self.UEDevicesRemoteServer = [] + #self.UEDevicesRemoteUser = [] + #self.UEDevicesOffCmd = [] + #self.UEDevicesOnCmd = [] + #self.UEDevicesRebootCmd = [] + #self.CatMDevices = [] + #self.UEIPAddresses = [] + #self.htmlFile = '' + #self.htmlHeaderCreated = False + #self.htmlFooterCreated = False + #self.htmlUEConnected = -1 + #self.htmleNBFailureMsg = '' + #self.htmlUEFailureMsg = '' + #self.picocom_closure = False + #self.idle_sleep_time = 0 + #self.x2_ho_options = 'network' + #self.x2NbENBs = 0 + #self.x2ENBBsIds = [] + #self.x2ENBConnectedUEs = [] + #self.htmlTabRefs = [] + #self.htmlTabNames = [] + #self.htmlTabIcons = [] + #self.repeatCounts = [] + #self.finalStatus = False + #self.OsVersion = '' + #self.KernelVersion = '' + #self.UhdVersion = '' + #self.UsrpBoard = '' + #self.CpuNb = '' + #self.CpuModel = '' + #self.CpuMHz = '' + #self.UEIPAddress = '' + #self.UEUserName = '' + #self.UEPassword = '' + #self.UE_instance = '' + #self.UESourceCodePath = '' + #self.UELogFile = '' + #self.Build_OAI_UE_args = '' + #self.Initialize_OAI_UE_args = '' + #self.clean_repository = True + #self.flexranCtrlInstalled = False + #self.flexranCtrlStarted = False + #self.expectedNbOfConnectedUEs = 0 + #self.startTime = 0 + + + def SetranRepository(self, repository): + self.ranRepository = repository + def GetranRepository(self): + return self.ranRepository + def SetranBranch(self, branch): + self.ranBranch = branch + def GetranBranch(self): + return self.ranBranch + def SetranCommitID(self, commitid): + self.ranCommitID = commitid + def GetranCommitID(self): + return self.ranCommitID + def SeteNB_serverId(self, enbsrvid): + self.eNB_serverId = enbsrvid + def GeteNB_serverId(self): + return self.eNB_serverId + def SeteNBIPAddress(self, enbip): + self.eNBIPAddress = enbip + def GeteNBIPAddress(self): + return self.eNBIPAddress + def SeteNBUserName(self, enbusr): + self.eNBUserName = enbusr + def GeteNBUserName(self): + return self.eNBUserName + def SeteNBPassword(self, enbpw): + self.eNBPassword = enbpw + def GeteNBPassword(self): + return self.eNBPassword + def SeteNBSourceCodePath(self, enbcodepath): + self.eNBSourceCodePath = enbcodepath + def GeteNBSourceCodePath(self): + return self.eNBSourceCodePath + def SetranAllowMerge(self, merge): + self.ranAllowMerge = merge + def GetranAllowMerge(self): + return self.ranAllowMerge + def SetranTargetBranch(self, tbranch): + self.ranTargetBranch = tbranch + def GetranTargetBranch(self): + return self.ranTargetBranch + def SetBuild_eNB_args(self, enbbuildarg): + self.Build_eNB_args = enbbuildarg + def GetBuild_eNB_args(self): + return self.Build_eNB_args + def SetInitialize_eNB_args(self, initenbarg): + self.Initialize_eNB_args = initenbarg + def GetInitialize_eNB_args(self): + return self.Initialize_eNB_args + def SetbackgroundBuild(self, bkbuild): + self.backgroundBuild = bkbuild + def GetbackgroundBuild(self): + return self.backgroundBuild + def SetbackgroundBuildTestId(self, bkbuildid): + self.backgroundBuildTestId = bkbuildid + def GetbackgroundBuildTestId(self): + return self.backgroundBuildTestId + def SetBuild_eNB_forced_workspace_cleanup(self, fcdwspclean): + self.Build_eNB_forced_workspace_cleanup = fcdwspclean + def GetBuild_eNB_forced_workspace_cleanup(self): + return self.Build_eNB_forced_workspace_cleanup + def Setair_interface(self, airif): + self.air_interface = airif + def Getair_interface(self): + return self.air_interface + def SeteNB_instance(self, enbinst): + self.eNB_instance = enbinst + def GeteNB_instance(self): + return self.eNB_instance + + def SeteNBLogFiles(self, enblogs): + self.eNBLogFiles = enblogs + def GeteNBLogFiles(self): + return self.eNBLogFiles + + def SeteNBOptions(self, enbopt): + self.eNBOptions = enbopt + def GeteNBOptions(self): + return self.eNBOptions + + def SeteNBmbmsEnables(self, enbmbms): + self.eNBmbmsEnables = enbmbms + def GeteNBmbmsEnables(self): + return self.eNBmbmsEnables + + def SeteNBstatuses(self, enbstatus): + self.eNBstatuses = enbstatus + def GeteNBstatuses(self): + return self.eNBstatuses + + + + def SeteNB1IPAddress(self, enb1ip): + self.eNB1IPAddress = enb1ip + def GeteNB1IPAddress(self): + return self.eNB1IPAddress + def SeteNB1UserName(self, enb1usr): + self.eNB1UserName = enb1usr + def GeteNB1UserName(self): + return self.eNB1UserName + def SeteNB1Password(self, enb1pw): + self.eNB1Password = enb1pw + def GeteNB1Password(self): + return self.eNB1Password + def SeteNB1SourceCodePath(self, enb1codepath): + self.eNB1SourceCodePath = enb1codepath + def GeteNB1SourceCodePath(self): + return self.eNB1SourceCodePath + + def SeteNB2IPAddress(self, enbip): + self.eNB2IPAddress = enb2ip + def GeteNB2IPAddress(self): + return self.eNB2IPAddress + def SeteNB2UserName(self, enb2usr): + self.eNB2UserName = enb2usr + def GeteNB2UserName(self): + return self.eNB2UserName + def SeteNB2Password(self, enb2pw): + self.eNB2Password = enb2pw + def GeteNB2Password(self): + return self.eNB2Password + def SeteNB2SourceCodePath(self, enb2codepath): + self.eNB2SourceCodePath = enb2codepath + def GeteNB2SourceCodePath(self): + return self.eNB2SourceCodePath + + + + def BuildeNB(self): + if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + if self.eNB_serverId == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = self.eNBSourceCodePath + elif self.eNB_serverId == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + lSourcePath = self.eNB1SourceCodePath + elif self.eNB_serverId == '2': + lIpAddr = self.eNB2IPAddress + lUserName = self.eNB2UserName + lPassWord = self.eNB2Password + lSourcePath = self.eNB2SourceCodePath + if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + mySSH = SSH.SSHConnection() + mySSH.open(lIpAddr, lUserName, lPassWord) + # Check if we build an 5G-NR gNB or an LTE eNB + result = re.search('--gNB', self.Build_eNB_args) + if result is not None: + self.air_interface = 'nr' + else: + self.air_interface = 'lte' + # Worakround for some servers, we need to erase completely the workspace + if self.Build_eNB_forced_workspace_cleanup: + mySSH.command('echo ' + lPassWord + ' | sudo -S rm -Rf ' + lSourcePath, '\$', 15) + # on RedHat/CentOS .git extension is mandatory + result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository) + if result is not None: + full_ran_repo_name = self.ranRepository + else: + full_ran_repo_name = self.ranRepository + '.git' + mySSH.command('mkdir -p ' + lSourcePath, '\$', 5) + mySSH.command('cd ' + lSourcePath, '\$', 5) + mySSH.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + full_ran_repo_name + ' .; else stdbuf -o0 git fetch --prune; fi', '\$', 600) + # Raphael: here add a check if git clone or git fetch went smoothly + mySSH.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) + mySSH.command('git config user.name "OAI Jenkins"', '\$', 5) + # Checking the BUILD INFO file + if not self.backgroundBuild: + mySSH.command('ls *.txt', '\$', 5) + result = re.search('LAST_BUILD_INFO', mySSH.getBefore()) + if result is not None: + mismatch = False + mySSH.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) + result = re.search(self.ranCommitID, mySSH.getBefore()) + if result is None: + mismatch = True + mySSH.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) + if (self.ranAllowMerge): + result = re.search('YES', mySSH.getBefore()) + if result is None: + mismatch = True + mySSH.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) + if self.ranTargetBranch == '': + result = re.search('develop', mySSH.getBefore()) + else: + result = re.search(self.ranTargetBranch, mySSH.getBefore()) + if result is None: + mismatch = True + else: + result = re.search('NO', mySSH.getBefore()) + if result is None: + mismatch = True + if not mismatch: + mySSH.close() + self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) + return + + mySSH.command('echo ' + lPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30) + # if the commit ID is provided use it to point to it + if self.ranCommitID != '': + mySSH.command('git checkout -f ' + self.ranCommitID, '\$', 5) + # if the branch is not develop, then it is a merge request and we need to do + # the potential merge. Note that merge conflicts should already been checked earlier + if (self.ranAllowMerge): + if self.ranTargetBranch == '': + if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'): + mySSH.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) + else: + logging.debug('Merging with the target branch: ' + self.ranTargetBranch) + mySSH.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5) + mySSH.command('source oaienv', '\$', 5) + mySSH.command('cd cmake_targets', '\$', 5) + mySSH.command('mkdir -p log', '\$', 5) + mySSH.command('chmod 777 log', '\$', 5) + # no need to remove in log (git clean did the trick) + if self.backgroundBuild: + mySSH.command('echo "./build_oai ' + self.Build_eNB_args + '" > ./my-lte-softmodem-build.sh', '\$', 5) + mySSH.command('chmod 775 ./my-lte-softmodem-build.sh', '\$', 5) + mySSH.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=build_enb_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/compile_oai_enb.log ./my-lte-softmodem-build.sh', '\$', 5) + mySSH.close() + self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) + self.backgroundBuildTestId[int(self.eNB_instance)] = self.testCase_id + return + mySSH.command('stdbuf -o0 ./build_oai ' + self.Build_eNB_args + ' 2>&1 | stdbuf -o0 tee compile_oai_enb.log', 'Bypassing the Tests|build have failed', 1500) + self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.testCase_id) + + + + def WaitBuildeNBisFinished(self): + if self.eNB_serverId == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = self.eNBSourceCodePath + elif self.eNB_serverId == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + lSourcePath = self.eNB1SourceCodePath + elif self.eNB_serverId == '2': + lIpAddr = self.eNB2IPAddress + lUserName = self.eNB2UserName + lPassWord = self.eNB2Password + lSourcePath = self.eNB2SourceCodePath + if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + mySSH = SSH.SSHConnection() + mySSH.open(lIpAddr, lUserName, lPassWord) + count = 40 + buildOAIprocess = True + while (count > 0) and buildOAIprocess: + mySSH.command('ps aux | grep --color=never build_ | grep -v grep', '\$', 3) + result = re.search('build_oai', mySSH.getBefore()) + if result is None: + buildOAIprocess = False + else: + count -= 1 + time.sleep(30) + self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.backgroundBuildTestId[int(self.eNB_instance)]) + + def checkBuildeNB(self, lIpAddr, lUserName, lPassWord, lSourcePath, testcaseId): + mySSH = SSH.SSHConnection() + mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 3) + mySSH.command('ls ran_build/build', '\$', 3) + mySSH.command('ls ran_build/build', '\$', 3) + if self.air_interface == 'nr': + nodeB_prefix = 'g' + else: + nodeB_prefix = 'e' + buildStatus = True + result = re.search(self.air_interface + '-softmodem', mySSH.getBefore()) + if result is None: + buildStatus = False + else: + # Generating a BUILD INFO file + mySSH.command('echo "SRC_BRANCH: ' + self.ranBranch + '" > ../LAST_BUILD_INFO.txt', '\$', 2) + mySSH.command('echo "SRC_COMMIT: ' + self.ranCommitID + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) + if (self.ranAllowMerge): + mySSH.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2) + if self.ranTargetBranch == '': + mySSH.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2) + else: + mySSH.command('echo "TGT_BRANCH: ' + self.ranTargetBranch + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) + else: + mySSH.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) + mySSH.command('mkdir -p build_log_' + testcaseId, '\$', 5) + mySSH.command('mv log/* ' + 'build_log_' + testcaseId, '\$', 5) + mySSH.command('mv compile_oai_enb.log ' + 'build_log_' + testcaseId, '\$', 5) + if self.eNB_serverId != '0': + mySSH.command('cd cmake_targets', '\$', 5) + mySSH.command('if [ -e tmp_build' + testcaseId + '.zip ]; then rm -f tmp_build' + testcaseId + '.zip; fi', '\$', 5) + mySSH.command('zip -r -qq tmp_build' + testcaseId + '.zip build_log_' + testcaseId, '\$', 5) + mySSH.close() + if (os.path.isfile('./tmp_build' + testcaseId + '.zip')): + os.remove('./tmp_build' + testcaseId + '.zip') + mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/tmp_build' + testcaseId + '.zip', '.') + if (os.path.isfile('./tmp_build' + testcaseId + '.zip')): + mySSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './tmp_build' + testcaseId + '.zip', self.eNBSourceCodePath + '/cmake_targets/.') + os.remove('./tmp_build' + testcaseId + '.zip') + mySSH.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) + mySSH.command('cd ' + self.eNBSourceCodePath + '/cmake_targets', '\$', 5) + mySSH.command('unzip -qq -DD tmp_build' + testcaseId + '.zip', '\$', 5) + mySSH.command('rm -f tmp_build' + testcaseId + '.zip', '\$', 5) + mySSH.close() + else: + mySSH.close() + + if buildStatus: + logging.info('\u001B[1m Building OAI ' + nodeB_prefix + 'NB Pass\u001B[0m') + self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) + else: + logging.error('\u001B[1m Building OAI ' + nodeB_prefix + 'NB Failed\u001B[0m') + self.CreateHtmlTestRow(self.Build_eNB_args, 'KO', ALL_PROCESSES_OK) + self.CreateHtmlTabFooter(False) + sys.exit(1) + + + def InitializeeNB(self): + if self.eNB_serverId == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = self.eNBSourceCodePath + elif self.eNB_serverId == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + lSourcePath = self.eNB1SourceCodePath + elif self.eNB_serverId == '2': + lIpAddr = self.eNB2IPAddress + lUserName = self.eNB2UserName + lPassWord = self.eNB2Password + lSourcePath = self.eNB2SourceCodePath + if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + mySSH = SSH.SSHConnection() + check_eNB = False + check_OAI_UE = False + pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (pStatus < 0): + self.CreateHtmlTestRow(self.Initialize_eNB_args, 'KO', pStatus) + self.CreateHtmlTabFooter(False) + sys.exit(1) + # If tracer options is on, running tshark on EPC side and capture traffic b/ EPC and eNB + result = re.search('T_stdout', str(self.Initialize_eNB_args)) + if result is not None: + mySSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + mySSH.command('ip addr show | awk -f /tmp/active_net_interfaces.awk | egrep -v "lo|tun"', '\$', 5) + result = re.search('interfaceToUse=(?P[a-zA-Z0-9\-\_]+)done', mySSH.getBefore()) + if result is not None: + eth_interface = result.group('eth_interface') + logging.debug('\u001B[1m Launching tshark on interface ' + eth_interface + '\u001B[0m') + EPC.Get_PcapFileName() = 'enb_' + self.testCase_id + '_s1log.pcap' + mySSH.command('echo ' + EPC.GetPassword() + ' | sudo -S rm -f /tmp/' + EPC.Get_PcapFileName() , '\$', 5) + mySSH.command('echo $USER; nohup sudo tshark -f "host ' + lIpAddr +'" -i ' + eth_interface + ' -w /tmp/' + EPC.Get_PcapFileName() + ' > /tmp/tshark.log 2>&1 &', EPC.GetUserName(), 5) + mySSH.close() + mySSH.open(lIpAddr, lUserName, lPassWord) + mySSH.command('cd ' + lSourcePath, '\$', 5) + # Initialize_eNB_args usually start with -O and followed by the location in repository + full_config_file = self.Initialize_eNB_args.replace('-O ','') + extra_options = '' + extIdx = full_config_file.find('.conf') + if (extIdx > 0): + extra_options = full_config_file[extIdx + 5:] + # if tracer options is on, compiling and running T Tracer + result = re.search('T_stdout', str(extra_options)) + if result is not None: + logging.debug('\u001B[1m Compiling and launching T Tracer\u001B[0m') + mySSH.command('cd common/utils/T/tracer', '\$', 5) + mySSH.command('make', '\$', 10) + mySSH.command('echo $USER; nohup ./record -d ../T_messages.txt -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.raw -ON -off VCD -off HEAVY -off LEGACY_GROUP_TRACE -off LEGACY_GROUP_DEBUG > ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.log 2>&1 &', lUserName, 5) + mySSH.command('cd ' + lSourcePath, '\$', 5) + full_config_file = full_config_file[:extIdx + 5] + config_path, config_file = os.path.split(full_config_file) + else: + sys.exit('Insufficient Parameter') + ci_full_config_file = config_path + '/ci-' + config_file + rruCheck = False + result = re.search('^rru|^rcc|^du.band', str(config_file)) + if result is not None: + rruCheck = True + # do not reset board twice in IF4.5 case + result = re.search('^rru|^enb|^du.band', str(config_file)) + if result is not None: + mySSH.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 60) + result = re.search('type: b200', mySSH.getBefore()) + if result is not None: + logging.debug('Found a B2xx device --> resetting it') + mySSH.command('echo ' + lPassWord + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10) + # Reloading FGPA bin firmware + mySSH.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 60) + # Make a copy and adapt to EPC / eNB IP addresses + mySSH.command('cp ' + full_config_file + ' ' + ci_full_config_file, '\$', 5) + mySSH.command('sed -i -e \'s/CI_MME_IP_ADDR/' + EPC.GetIPAddress() + '/\' ' + ci_full_config_file, '\$', 2); + mySSH.command('sed -i -e \'s/CI_ENB_IP_ADDR/' + lIpAddr + '/\' ' + ci_full_config_file, '\$', 2); + mySSH.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2); + mySSH.command('sed -i -e \'s/CI_RRU1_IP_ADDR/' + self.eNB1IPAddress + '/\' ' + ci_full_config_file, '\$', 2); + mySSH.command('sed -i -e \'s/CI_RRU2_IP_ADDR/' + self.eNB2IPAddress + '/\' ' + ci_full_config_file, '\$', 2); + if self.flexranCtrlInstalled and self.flexranCtrlStarted: + mySSH.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "yes";/\' ' + ci_full_config_file, '\$', 2); + else: + mySSH.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "no";/\' ' + ci_full_config_file, '\$', 2); + self.eNBmbmsEnables[int(self.eNB_instance)] = False + mySSH.command('grep enable_enb_m2 ' + ci_full_config_file, '\$', 2); + result = re.search('yes', mySSH.getBefore()) + if result is not None: + self.eNBmbmsEnables[int(self.eNB_instance)] = True + logging.debug('\u001B[1m MBMS is enabled on this eNB\u001B[0m') + result = re.search('noS1', str(self.Initialize_eNB_args)) + eNBinNoS1 = False + if result is not None: + eNBinNoS1 = True + logging.debug('\u001B[1m eNB is in noS1 configuration \u001B[0m') + # Launch eNB with the modified config file + mySSH.command('source oaienv', '\$', 5) + mySSH.command('cd cmake_targets', '\$', 5) + mySSH.command('echo "ulimit -c unlimited && ./ran_build/build/' + self.air_interface + '-softmodem -O ' + lSourcePath + '/' + ci_full_config_file + extra_options + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + mySSH.command('chmod 775 ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + mySSH.command('echo ' + lPassWord + ' | sudo -S rm -Rf enb_' + self.testCase_id + '.log', '\$', 5) + mySSH.command('hostnamectl','\$', 5) + result = re.search('CentOS Linux 7', mySSH.getBefore()) + if result is not None: + mySSH.command('echo $USER; nohup sudo ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh > ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log 2>&1 &', lUserName, 10) + else: + mySSH.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=enb' + str(self.eNB_instance) + '_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + self.eNBLogFiles[int(self.eNB_instance)] = 'enb_' + self.testCase_id + '.log' + if extra_options != '': + self.eNBOptions[int(self.eNB_instance)] = extra_options + time.sleep(6) + doLoop = True + loopCounter = 20 + enbDidSync = False + while (doLoop): + loopCounter = loopCounter - 1 + if (loopCounter == 0): + # In case of T tracer recording, we may need to kill it + result = re.search('T_stdout', str(self.Initialize_eNB_args)) + if result is not None: + mySSH.command('killall --signal SIGKILL record', '\$', 5) + mySSH.close() + doLoop = False + logging.error('\u001B[1;37;41m eNB logging system did not show got sync! \u001B[0m') + self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'KO', ALL_PROCESSES_OK) + # In case of T tracer recording, we need to kill tshark on EPC side + result = re.search('T_stdout', str(self.Initialize_eNB_args)) + if result is not None: + mySSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + logging.debug('\u001B[1m Stopping tshark \u001B[0m') + mySSH.command('echo ' + EPC.GetPassword() + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) + if EPC.Get_PcapFileName() != '': + time.sleep(0.5) + mySSH.command('echo ' + EPC.GetPassword() + ' | sudo -S chmod 666 /tmp/' + EPC.Get_PcapFileName() , '\$', 5) + mySSH.close() + time.sleep(1) + if EPC.Get_PcapFileName() != '': + copyin_res = mySSH.copyin(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), '/tmp/' + EPC.Get_PcapFileName() , '.') + if (copyin_res == 0): + mySSH.copyout(lIpAddr, lUserName, lPassWord, EPC.Get_PcapFileName() , lSourcePath + '/cmake_targets/.') + self.prematureExit = True + return + else: + mySSH.command('stdbuf -o0 cat enb_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync|Starting"', '\$', 4) + if rruCheck: + result = re.search('wait RUs', mySSH.getBefore()) + else: + result = re.search('got sync|Starting F1AP at CU', mySSH.getBefore()) + if result is None: + time.sleep(6) + else: + doLoop = False + enbDidSync = True + time.sleep(10) + + if enbDidSync and eNBinNoS1: + mySSH.command('ifconfig oaitun_enb1', '\$', 4) + mySSH.command('ifconfig oaitun_enb1', '\$', 4) + result = re.search('inet addr:1|inet 1', mySSH.getBefore()) + if result is not None: + logging.debug('\u001B[1m oaitun_enb1 interface is mounted and configured\u001B[0m') + else: + logging.error('\u001B[1m oaitun_enb1 interface is either NOT mounted or NOT configured\u001B[0m') + if self.eNBmbmsEnables[int(self.eNB_instance)]: + mySSH.command('ifconfig oaitun_enm1', '\$', 4) + result = re.search('inet addr', mySSH.getBefore()) + if result is not None: + logging.debug('\u001B[1m oaitun_enm1 interface is mounted and configured\u001B[0m') + else: + logging.error('\u001B[1m oaitun_enm1 interface is either NOT mounted or NOT configured\u001B[0m') + if enbDidSync: + self.eNBstatuses[int(self.eNB_instance)] = int(self.eNB_serverId) + + mySSH.close() + self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'OK', ALL_PROCESSES_OK) + logging.debug('\u001B[1m Initialize eNB Completed\u001B[0m') + + + + def CheckeNBProcess(self, status_queue): + try: + # At least the instance 0 SHALL be on! + if self.eNBstatuses[0] == 0: + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + elif self.eNBstatuses[0] == 1: + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + elif self.eNBstatuses[0] == 2: + lIpAddr = self.eNB2IPAddress + lUserName = self.eNB2UserName + lPassWord = self.eNB2Password + else: + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + mySSH = SSH.SSHConnection() + mySSH.open(lIpAddr, lUserName, lPassWord) + mySSH.command('stdbuf -o0 ps -aux | grep --color=never ' + self.air_interface + '-softmodem | grep -v grep', '\$', 5) + result = re.search(self.air_interface + '-softmodem', mySSH.getBefore()) + if result is None: + logging.debug('\u001B[1;37;41m eNB Process Not Found! \u001B[0m') + status_queue.put(ENB_PROCESS_FAILED) + else: + status_queue.put(ENB_PROCESS_OK) + mySSH.close() + except: + os.kill(os.getppid(),signal.SIGUSR1) + + + + def TerminateeNB(self): + if self.eNB_serverId == '0': + lIpAddr = self.eNBIPAddress + lUserName = self.eNBUserName + lPassWord = self.eNBPassword + lSourcePath = self.eNBSourceCodePath + elif self.eNB_serverId == '1': + lIpAddr = self.eNB1IPAddress + lUserName = self.eNB1UserName + lPassWord = self.eNB1Password + lSourcePath = self.eNB1SourceCodePath + elif self.eNB_serverId == '2': + lIpAddr = self.eNB2IPAddress + lUserName = self.eNB2UserName + lPassWord = self.eNB2Password + lSourcePath = self.eNB2SourceCodePath + if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': + GenericHelp(Version) + sys.exit('Insufficient Parameter') + mySSH = SSH.SSHConnection() + mySSH.open(lIpAddr, lUserName, lPassWord) + mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) + if self.air_interface == 'lte': + nodeB_prefix = 'e' + else: + nodeB_prefix = 'g' + mySSH.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + result = re.search('-softmodem', mySSH.getBefore()) + if result is not None: + mySSH.command('echo ' + lPassWord + ' | sudo -S daemon --name=enb' + str(self.eNB_instance) + '_daemon --stop', '\$', 5) + mySSH.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGINT -r .*-softmodem || true', '\$', 5) + time.sleep(10) + mySSH.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) + result = re.search('-softmodem', mySSH.getBefore()) + if result is not None: + mySSH.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGKILL -r .*-softmodem || true', '\$', 5) + time.sleep(5) + mySSH.command('rm -f my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) + mySSH.close() + # If tracer options is on, stopping tshark on EPC side + result = re.search('T_stdout', str(self.Initialize_eNB_args)) + if result is not None: + mySSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + logging.debug('\u001B[1m Stopping tshark \u001B[0m') + mySSH.command('echo ' + EPC.GetPassword() + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) + time.sleep(1) + if EPC.Get_PcapFileName() != '': + mySSH.command('echo ' + EPC.GetPassword() + ' | sudo -S chmod 666 /tmp/' + EPC.Get_PcapFileName() , '\$', 5) + mySSH.copyin(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), '/tmp/' + EPC.Get_PcapFileName() , '.') + mySSH.copyout(lIpAddr, lUserName, lPassWord, EPC.Get_PcapFileName() , lSourcePath + '/cmake_targets/.') + mySSH.close() + logging.debug('\u001B[1m Replaying RAW record file\u001B[0m') + mySSH.open(lIpAddr, lUserName, lPassWord) + mySSH.command('cd ' + lSourcePath + '/common/utils/T/tracer/', '\$', 5) + enbLogFile = self.eNBLogFiles[int(self.eNB_instance)] + raw_record_file = enbLogFile.replace('.log', '_record.raw') + replay_log_file = enbLogFile.replace('.log', '_replay.log') + extracted_txt_file = enbLogFile.replace('.log', '_extracted_messages.txt') + extracted_log_file = enbLogFile.replace('.log', '_extracted_messages.log') + mySSH.command('./extract_config -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + extracted_txt_file, '\$', 5) + mySSH.command('echo $USER; nohup ./replay -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + replay_log_file + ' 2>&1 &', lUserName, 5) + mySSH.command('./textlog -d ' + lSourcePath + '/cmake_targets/' + extracted_txt_file + ' -no-gui -ON -full > ' + lSourcePath + '/cmake_targets/' + extracted_log_file, '\$', 5) + mySSH.close() + mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + extracted_log_file, '.') + logging.debug('\u001B[1m Analyzing eNB replay logfile \u001B[0m') + logStatus = self.AnalyzeLogFile_eNB(extracted_log_file) + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + self.eNBLogFiles[int(self.eNB_instance)] = '' + else: + analyzeFile = False + if self.eNBLogFiles[int(self.eNB_instance)] != '': + analyzeFile = True + fileToAnalyze = self.eNBLogFiles[int(self.eNB_instance)] + self.eNBLogFiles[int(self.eNB_instance)] = '' + if analyzeFile: + copyin_res = mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + fileToAnalyze, '.') + if (copyin_res == -1): + logging.debug('\u001B[1;37;41m Could not copy ' + nodeB_prefix + 'NB logfile to analyze it! \u001B[0m') + self.htmleNBFailureMsg = 'Could not copy ' + nodeB_prefix + 'NB logfile to analyze it!' + self.CreateHtmlTestRow('N/A', 'KO', ENB_PROCESS_NOLOGFILE_TO_ANALYZE) + self.eNBmbmsEnables[int(self.eNB_instance)] = False + return + if self.eNB_serverId != '0': + mySSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './' + fileToAnalyze, self.eNBSourceCodePath + '/cmake_targets/') + logging.debug('\u001B[1m Analyzing ' + nodeB_prefix + 'NB logfile \u001B[0m ' + fileToAnalyze) + logStatus = self.AnalyzeLogFile_eNB(fileToAnalyze) + if (logStatus < 0): + self.CreateHtmlTestRow('N/A', 'KO', logStatus) + self.preamtureExit = True + self.eNBmbmsEnables[int(self.eNB_instance)] = False + return + else: + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + else: + self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + self.eNBmbmsEnables[int(self.eNB_instance)] = False + self.eNBstatuses[int(self.eNB_instance)] = -1 + + + def LogCollecteNB(self): + mySSH = SSH.SSHConnection() + mySSH.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) + mySSH.command('cd ' + self.eNBSourceCodePath, '\$', 5) + mySSH.command('cd cmake_targets', '\$', 5) + mySSH.command('echo ' + self.eNBPassword + ' | sudo -S rm -f enb.log.zip', '\$', 5) + mySSH.command('echo ' + self.eNBPassword + ' | sudo -S zip enb.log.zip enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 60) + mySSH.command('echo ' + self.eNBPassword + ' | sudo -S rm enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 5) + mySSH.close() diff --git a/ci-scripts/sshconnection.py b/ci-scripts/sshconnection.py index d10edf360b..6103bf4f0f 100644 --- a/ci-scripts/sshconnection.py +++ b/ci-scripts/sshconnection.py @@ -68,7 +68,8 @@ class SSHConnection(): elif self.sshresponse == 1: logging.debug('\u001B[1;37;41m Unexpected EOF \u001B[0m') logging.debug('Expected Line : ' + expectedline) - sys.exit(self.sshresponse) + logging.debug(str(self.ssh.before)) + sys.exit(self.sshresponse) elif self.sshresponse == 2: logging.debug('\u001B[1;37;41m Unexpected TIMEOUT \u001B[0m') logging.debug('Expected Line : ' + expectedline) From 53db39b8a02dfdcf2564a2fce11d4650f494a775 Mon Sep 17 00:00:00 2001 From: laurent Date: Mon, 2 Mar 2020 15:41:21 +0100 Subject: [PATCH 087/240] split 7.3 ready for merge --- SystemX-tutorial-design.odt | Bin 55501 -> 0 bytes cmake_targets/CMakeLists.txt | 8 - common/utils/system.c | 6 +- .../SystemX-tutorial-design.md | 21 +- enb.fs6.example.conf | 290 ------- executables/main-fs6.c | 126 +-- executables/main-ocp.c | 789 +++++++++++++----- executables/nr-gnb.c | 137 ++- executables/nr-ru.c | 40 +- executables/nr-softmodem.c | 130 +-- executables/nr-ue.c | 128 +-- executables/nr-uesoftmodem.c | 56 +- executables/softmodem-common.c | 44 +- executables/softmodem-common.h | 9 + executables/split_headers.h | 5 +- openair1/PHY/LTE_TRANSPORT/dlsch_coding.c | 8 +- openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c | 24 +- openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c | 2 +- openair1/PHY/LTE_TRANSPORT/transport_eNB.h | 6 +- openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c | 54 +- .../PHY/LTE_UE_TRANSPORT/dlsch_decoding.c | 2 +- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 2 +- openair1/SCHED/phy_procedures_lte_eNb.c | 23 +- openair1/SIMULATION/LTE_PHY/dlsim.c | 9 +- openair1/SIMULATION/LTE_PHY/ulsim.c | 9 +- openair2/PHY_INTERFACE/IF_Module.h | 6 +- targets/ARCH/rfsimulator/simulator.c | 6 +- targets/COMMON/create_tasks.c | 15 +- targets/RT/USER/lte-softmodem.c | 31 +- 29 files changed, 1032 insertions(+), 954 deletions(-) delete mode 100644 SystemX-tutorial-design.odt rename SystemX-tutorial-design.md => doc/SystemX-tutorial-design.md (93%) delete mode 100644 enb.fs6.example.conf diff --git a/SystemX-tutorial-design.odt b/SystemX-tutorial-design.odt deleted file mode 100644 index 42e195ac112b370ff7d48cfbb5e083d9cfaecf6e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 55501 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
YnRIhBz$ZI{0_ZI3>?OH0uus+P7A)eI|s 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 U6A%AvGbQ$Q5gQ0mG $d/cpufreq/scaling_min_freq; done")) - LOG_W(HW,"Can't set cpu frequency\n"); - + LOG_E(HW,"Can't set cpu frequency\n"); + + mlockall(MCL_CURRENT | MCL_FUTURE); + } diff --git a/SystemX-tutorial-design.md b/doc/SystemX-tutorial-design.md similarity index 93% rename from SystemX-tutorial-design.md rename to doc/SystemX-tutorial-design.md index c5d1f77704..371cb33a75 100644 --- a/SystemX-tutorial-design.md +++ b/doc/SystemX-tutorial-design.md @@ -258,26 +258,22 @@ lte-softmodem. The functionality and parameters is the same, enhanced with FS6 mode. -The environment variable “fs6” enables the fs6 mode and decided to be cu -or du from the fs6 variable content. - -A example configuration file is: $OPENAIR_DIR/enb.fs6.example.conf -The IP addresses in this file should be updated for each network. +The end line option “--split73” enables the fs6 (also called split 7.3) mode and decided to be cu or du. Example: -`fs6=cu ./ocp-softmodem -O $OPENAIR_DIR/enb.fs6.example.conf --rfsim --log_config.phy_log_level debug +./ocp-softmodem -O $OPENAIR_DIR/enb.fs6.example.conf --rfsim --log_config.phy_log_level debug --split73 cu:127.0.0.1 ` +Run the CU init of the split 6 eNB, that will call du on 127.0.0.1 address -Run the CU init of the split 6 eNB. +./ocp-softmodem -O $OPENAIR_DIR/enb.fs6.example.conf --rfsim --log_config.phy_log_level debug --split73 du:127.0.0.1 -`fs6=du ./ocp-softmodem -O $OPENAIR_DIR/enb.fs6.example.conf --rfsim --log_config.phy_log_level debug +will run the du, calling the cu on 127.0.0.1 ` If the CU and the DU are not on the same machine, the remote address of each side need to be specified as per this example -`fs6=du FS6_REMOTE_IP=192.168.2.211 ./ocp-softmodem -O $OPENAIR_DIR/enb.fs6.example.conf --rfsim --log_config.phy_log_level debug +./ocp-softmodem -O $OPENAIR_DIR/enb.fs6.example.conf --rfsim --log_config.phy_log_level debug --split73 du:192.168.1.55 ` - runs the functional split 6 DU `./lte-uesoftmodem -C 2685000000 -r 50 --rfsim --rfsimulator.serveraddr 192.168.1.1 -d @@ -285,10 +281,7 @@ runs the functional split 6 DU Runs the UE (to have the UE signal scope, compile it with make uescope) -CU and DU IP address and port are configurable in the eNB configuration -file (as X2, GTP, … interfaces). - -CU+DU+UE can run with option --noS1 to avoid to use a EPC. +CU+DU+UE can run with option --noS1 to avoid to use a EPC and/or with --rfsim to simulate RF board ##5G and F1 diff --git a/enb.fs6.example.conf b/enb.fs6.example.conf deleted file mode 100644 index 6102f91756..0000000000 --- a/enb.fs6.example.conf +++ /dev/null @@ -1,290 +0,0 @@ -Active_eNBs = ( "eNB-Eurecom-LTEBox"); -# Asn1_verbosity, choice in: none, info, annoying -Asn1_verbosity = "none"; - -eNBs = -( - { - ////////// Identification parameters: - eNB_ID = 0xe00; - - cell_type = "CELL_MACRO_ENB"; - - eNB_name = "eNB-Eurecom-LTEBox"; - - // Tracking area code, 0x0000 and 0xfffe are reserved values - tracking_area_code = 1; - plmn_list = ( { mcc = 208; mnc = 92; mnc_length = 2; } ); - - tr_s_preference = "local_mac" - - ////////// Physical parameters: - - component_carriers = ( - { - node_function = "3GPP_eNODEB"; - node_timing = "synch_to_ext_device"; - node_synch_ref = 0; - frame_type = "FDD"; - tdd_config = 3; - tdd_config_s = 0; - prefix_type = "NORMAL"; - eutra_band = 7; - downlink_frequency = 2685000000L; - uplink_frequency_offset = -120000000; - Nid_cell = 0; - N_RB_DL = 50; - Nid_cell_mbsfn = 0; - nb_antenna_ports = 1; - nb_antennas_tx = 1; - nb_antennas_rx = 1; - tx_gain = 90; - rx_gain = 125; - pbch_repetition = "FALSE"; - prach_root = 0; - prach_config_index = 0; - prach_high_speed = "DISABLE"; - prach_zero_correlation = 1; - prach_freq_offset = 2; - pucch_delta_shift = 1; - pucch_nRB_CQI = 0; - pucch_nCS_AN = 0; - pucch_n1_AN = 0; - pdsch_referenceSignalPower = -27; - pdsch_p_b = 0; - pusch_n_SB = 1; - pusch_enable64QAM = "DISABLE"; - pusch_hoppingMode = "interSubFrame"; - pusch_hoppingOffset = 0; - pusch_groupHoppingEnabled = "ENABLE"; - pusch_groupAssignment = 0; - pusch_sequenceHoppingEnabled = "DISABLE"; - pusch_nDMRS1 = 1; - phich_duration = "NORMAL"; - phich_resource = "ONESIXTH"; - srs_enable = "DISABLE"; - /* srs_BandwidthConfig =; - srs_SubframeConfig =; - srs_ackNackST =; - srs_MaxUpPts =;*/ - - pusch_p0_Nominal = -96; - pusch_alpha = "AL1"; - pucch_p0_Nominal = -104; - msg3_delta_Preamble = 6; - pucch_deltaF_Format1 = "deltaF2"; - pucch_deltaF_Format1b = "deltaF3"; - pucch_deltaF_Format2 = "deltaF0"; - pucch_deltaF_Format2a = "deltaF0"; - pucch_deltaF_Format2b = "deltaF0"; - - rach_numberOfRA_Preambles = 64; - rach_preamblesGroupAConfig = "DISABLE"; - /* - rach_sizeOfRA_PreamblesGroupA = ; - rach_messageSizeGroupA = ; - rach_messagePowerOffsetGroupB = ; - */ - rach_powerRampingStep = 4; - rach_preambleInitialReceivedTargetPower = -108; - rach_preambleTransMax = 10; - rach_raResponseWindowSize = 10; - rach_macContentionResolutionTimer = 48; - rach_maxHARQ_Msg3Tx = 4; - - pcch_default_PagingCycle = 128; - pcch_nB = "oneT"; - drx_Config_present = "prSetup"; //"prSetup" "prRelease" - drx_onDurationTimer = "psf1"; // "psfX": X=1,2,3,4,5,6,8,10,20,30,40,50,60,80,100 - drx_InactivityTimer = "psf1"; // "psfX": X=1,2,3,4,5,6,8,10,20,30,40,50,60,80,100,200,300,500,750,1280,1920,2560 - drx_RetransmissionTimer = "psf1"; // "psfX": X=1,2,4,6,8,16,24,33 - drx_longDrx_CycleStartOffset_present = "prSf128"; // "psfX": X=10,20,32,40,64,80,128,160,256,320,512,640,1024,1280,2048,2560 - drx_longDrx_CycleStartOffset = 0; // X >= 0 && X < drx_longDrx_CycleStartOffset_present - drx_shortDrx_Cycle = "sf16"; // "sfX": X=2,5,8,10,16,20,32,40,64,80,128,160,256,320,512,640 - drx_shortDrx_ShortCycleTimer = 3; // 1..16 integer. Total duration in short cycle = drx_shortDrx_Cycle*drx_shortDrx_ShortCycleTimer [subframe] - bcch_modificationPeriodCoeff = 2; - ue_TimersAndConstants_t300 = 1000; - ue_TimersAndConstants_t301 = 1000; - ue_TimersAndConstants_t310 = 1000; - ue_TimersAndConstants_t311 = 10000; - ue_TimersAndConstants_n310 = 20; - ue_TimersAndConstants_n311 = 1; - ue_TransmissionMode = 1; - - //Parameters for SIB18 - rxPool_sc_CP_Len = "normal"; - rxPool_sc_Period = "sf40"; - rxPool_data_CP_Len = "normal"; - rxPool_ResourceConfig_prb_Num = 20; - rxPool_ResourceConfig_prb_Start = 5; - rxPool_ResourceConfig_prb_End = 44; - rxPool_ResourceConfig_offsetIndicator_present = "prSmall"; - rxPool_ResourceConfig_offsetIndicator_choice = 0; - rxPool_ResourceConfig_subframeBitmap_present = "prBs40"; - rxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "00000000000000000000"; - rxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; - rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; -/* rxPool_dataHoppingConfig_hoppingParameter = 0; - rxPool_dataHoppingConfig_numSubbands = "ns1"; - rxPool_dataHoppingConfig_rbOffset = 0; - rxPool_commTxResourceUC-ReqAllowed = "TRUE"; -*/ - // Parameters for SIB19 - discRxPool_cp_Len = "normal" - discRxPool_discPeriod = "rf32" - discRxPool_numRetx = 1; - discRxPool_numRepetition = 2; - discRxPool_ResourceConfig_prb_Num = 5; - discRxPool_ResourceConfig_prb_Start = 3; - discRxPool_ResourceConfig_prb_End = 21; - discRxPool_ResourceConfig_offsetIndicator_present = "prSmall"; - discRxPool_ResourceConfig_offsetIndicator_choice = 0; - discRxPool_ResourceConfig_subframeBitmap_present = "prBs40"; - discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "f0ffffffff"; - discRxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5; - discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0; - - } - ); - - - srb1_parameters : - { - # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] - timer_poll_retransmit = 80; - - # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] - timer_reordering = 35; - - # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] - timer_status_prohibit = 0; - - # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] - poll_pdu = 4; - - # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] - poll_byte = 99999; - - # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] - max_retx_threshold = 4; - } - - # ------- SCTP definitions - SCTP : - { - # Number of streams to use in input/output - SCTP_INSTREAMS = 2; - SCTP_OUTSTREAMS = 2; - }; - - - ////////// MME parameters: - mme_ip_address = ( { ipv4 = "127.0.0.20"; - ipv6 = "192:168:30::17"; - active = "yes"; - preference = "ipv4"; - } - ); - - enable_measurement_reports = "no"; - ///X2 - enable_x2 = "no"; - t_reloc_prep = 1000; /* unit: millisecond */ - tx2_reloc_overall = 2000; /* unit: millisecond */ - - NETWORK_INTERFACES : - { - - ENB_INTERFACE_NAME_FOR_S1_MME = "lo"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "127.0.0.10"; - ENB_INTERFACE_NAME_FOR_S1U = "lo"; - ENB_IPV4_ADDRESS_FOR_S1U = "127.0.0.10"; - ENB_PORT_FOR_S1U = 2152; # Spec 2152 - - ENB_IPV4_ADDRESS_FOR_X2C = "127.0.0.1"; - ENB_PORT_FOR_X2C = 36422; # Spec 36422 - }; - } -); - -MACRLCs = ( - { - num_cc = 1; - tr_s_preference = "local_L1"; - tr_n_preference = "local_RRC"; - //scheduler_mode = "fairRR"; - phy_test_mode = 0; - puSch10xSnr = 160; - puCch10xSnr = 160; - } -); - -L1s = ( - { - num_cc = 1; - tr_n_preference = "local_mac"; - } -); - -RUs = ( - { - local_rf = "yes" - nb_tx = 1 - nb_rx = 1 - att_tx = 0 - att_rx = 0; - bands = [7]; - max_pdschReferenceSignalPower = -27; - max_rxgain = 108; - eNB_instances = [0]; - - } -); - -NETWORK_CONTROLLER : -{ - FLEXRAN_ENABLED = "no"; - FLEXRAN_INTERFACE_NAME = "lo"; - FLEXRAN_IPV4_ADDRESS = "127.0.0.1"; - FLEXRAN_PORT = 2210; - FLEXRAN_CACHE = "/mnt/oai_agent_cache"; - FLEXRAN_AWAIT_RECONF = "no"; -}; - -THREAD_STRUCT = ( - { - #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" - parallel_config = "PARALLEL_SINGLE_THREAD"; - #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" - worker_config = "WORKER_DISABLE"; - } -); - -#example config for rfsimulator -rfsimulator : -{ - serveraddr = "enb"; - serverport = "4043"; - options = (); #("saviq"); - modelname = "AWGN"; - IQfile = "/tmp/rfsimulator.iqs"; -}; - - log_config : - { - global_log_level ="info"; - global_log_verbosity ="medium"; - hw_log_level ="info"; - hw_log_verbosity ="medium"; - phy_log_level ="info"; - phy_log_verbosity ="medium"; - mac_log_level ="info"; - mac_log_verbosity ="high"; - rlc_log_level ="info"; - rlc_log_verbosity ="medium"; - pdcp_log_level ="info"; - pdcp_log_verbosity ="medium"; - rrc_log_level ="info"; - rrc_log_verbosity ="medium"; - }; - diff --git a/executables/main-fs6.c b/executables/main-fs6.c index 727f80a72b..c20777a5d6 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -165,16 +165,16 @@ void prach_eNB_tosplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB *eNB, L1_r } ocp_rx_prach(eNB, - proc, - eNB->RU_list[0], - header->max_preamble, - header->max_preamble_energy, - header->max_preamble_delay, - header->avg_preamble_energy, - proc->frame_prach, - 0, - false - ); + proc, + eNB->RU_list[0], + header->max_preamble, + header->max_preamble_energy, + header->max_preamble_delay, + header->avg_preamble_energy, + proc->frame_prach, + 0, + false + ); // run PRACH detection for CE-level 0 only for now when br_flag is set /* fixme: seems not operational and may overwrite regular LTE prach detection * OAI code can call is sequence @@ -513,15 +513,12 @@ void fill_rx_indication_from_split(uint8_t *bufferZone, PHY_VARS_eNB *eNB,int UE nfapi_rx_indication_pdu_t *pdu; int timing_advance_update; uint32_t harq_pid; -#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) - if (eNB->ulsch[UE_id]->ue_type > 0) harq_pid = 0; + if (eNB->ulsch[UE_id]->ue_type > 0) + harq_pid = 0; else -#endif - { harq_pid = subframe2harq_pid (&eNB->frame_parms, frame, subframe); - } pthread_mutex_lock(&eNB->UL_INFO_mutex); eNB->UL_INFO.rx_ind.sfn_sf = frame<<4| subframe; @@ -533,7 +530,7 @@ void fill_rx_indication_from_split(uint8_t *bufferZone, PHY_VARS_eNB *eNB,int UE pdu->rx_indication_rel8.tl.tag = NFAPI_RX_INDICATION_REL8_TAG; pdu->rx_indication_rel8.length = eNB->ulsch[UE_id]->harq_processes[harq_pid]->TBS>>3; pdu->rx_indication_rel8.offset = 1; // DJP - I dont understand - but broken unless 1 ???? 0; // filled in at the end of the UL_INFO formation - pdu->data = eNB->ulsch[UE_id]->harq_processes[harq_pid]->b; + pdu->data = eNB->ulsch[UE_id]->harq_processes[harq_pid]->decodedBytes; // estimate timing advance for MAC timing_advance_update = ul_propa[UE_id].ta; @@ -662,7 +659,7 @@ void pusch_procedures_fromsplit(uint8_t *bufferZone, int bufSize, PHY_VARS_eNB * } // for (i=0; inbDecode > 0) { - notifiedFIFO_elt_t *req=pullTpool(&proc->respDecode, &proc->threadPool); + notifiedFIFO_elt_t *req=pullTpool(proc->respDecode, proc->threadPool); postDecode(proc, req); delNotifiedFIFO_elt(req); } @@ -678,7 +675,7 @@ void recvFs6Ul(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, ul_propagat if ( type == fs6ULsch) { LTE_eNB_ULSCH_t *ulsch =eNB->ulsch[hULUE(bufPtr)->UE_id]; LTE_UL_eNB_HARQ_t *ulsch_harq=ulsch->harq_processes[hULUE(bufPtr)->harq_id]; - memcpy(ulsch_harq->e+hULUE(bufPtr)->r_offset, + memcpy(ulsch_harq->eUL+hULUE(bufPtr)->r_offset, hULUE(bufPtr)+1, hULUE(bufPtr)->segLen); memcpy(eNB->pusch_vars[hULUE(bufPtr)->UE_id]->ulsch_power, @@ -691,7 +688,7 @@ void recvFs6Ul(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, ul_propagat sizeof(ulsch_harq->o_ACK)); memcpy(ulsch_harq->o,hULUE(bufPtr)->o, sizeof(ulsch_harq->o)); ul_propa[hULUE(bufPtr)->UE_id].ta=hULUE(bufPtr)->ta; - LOG_D(PHY,"Received ulsch data for: rnti:%x, cqi_crc_status %d O_ACK: %di, segment: %di, seglen: %d \n", + LOG_D(PHY,"Received ulsch data for: rnti:%x, cqi_crc_status %d O_ACK: %d, segment: %d, seglen: %d \n", ulsch->rnti, ulsch_harq->cqi_crc_status, ulsch_harq->O_ACK,hULUE(bufPtr)->segment, hULUE(bufPtr)->segLen); } else if ( type == fs6ULcch ) { int nb_uci=hULUEuci(bufPtr)->nb_active_ue; @@ -771,10 +768,10 @@ void rcvFs6DL(uint8_t *bufferZone, int nbBlocks, PHY_VARS_eNB *eNB, int frame, i dlsch0->i0=hDLUE(bufPtr)->i0; dlsch0->sib1_br_flag=hDLUE(bufPtr)->sib1_br_flag; #endif - fs6Dlunpack(dlsch_harq->e, + fs6Dlunpack(dlsch_harq->eDL, hDLUE(bufPtr)+1, hDLUE(bufPtr)->dataLen); LOG_D(PHY,"received %d bits, in harq id: %di fsf: %d.%d, sum %d\n", - hDLUE(bufPtr)->dataLen, hDLUE(bufPtr)->harq_pid, frame, subframe, sum(dlsch_harq->e, hDLUE(bufPtr)->dataLen)); + hDLUE(bufPtr)->dataLen, hDLUE(bufPtr)->harq_pid, frame, subframe, sum(dlsch_harq->eDL, hDLUE(bufPtr)->dataLen)); } else if (type == fs6UlConfig) { int nbUE=(((commonUDP_t *)bufPtr)->contentBytes - sizeof(fs6_dl_t)) / sizeof( fs6_dl_ulsched_t ) ; #define cpyVal(a) memcpy(&ulsch_harq->a,&hTxULUE(bufPtr)->a, sizeof(ulsch_harq->a)) @@ -1103,9 +1100,9 @@ void appendFs6DLUE(uint8_t *bufferZone, LTE_DL_FRAME_PARMS *fp, int UE_id, int8_ hDLUE(newUDPheader)->sib1_br_flag=dlsch0->sib1_br_flag; #endif hDLUE(newUDPheader)->dataLen=UEdataLen; - fs6Dlpack(hDLUE(newUDPheader)+1, harqData->e, UEdataLen); + fs6Dlpack(hDLUE(newUDPheader)+1, harqData->eDL, UEdataLen); LOG_D(PHY,"sending %d bits, in harq id: %di fsf: %d.%d, sum %d\n", - UEdataLen, harq_pid, frame, subframe, sum(harqData->e, UEdataLen)); + UEdataLen, harq_pid, frame, subframe, sum(harqData->eDL, UEdataLen)); //for (int i=0; i < UEdataLen; i++) //LOG_D(PHY,"buffer ei[%d]:%hhx\n", i, ( (uint8_t *)(hDLUE(newUDPheader)+1) )[i]); } @@ -1322,7 +1319,11 @@ void phy_procedures_eNB_TX_tosplit(uint8_t *bufferZone, PHY_VARS_eNB *eNB, L1_rx void *DL_du_fs6(void *arg) { RU_t *ru=(RU_t *)arg; static uint64_t lastTS; - L1_rxtx_proc_t L1_proc= {0}; + L1_rxtx_proc_t L1proc= {0}; + // We pick the global thread pool from the legacy code global vars + L1proc.threadPool=RC.eNB[0][0]->proc.L1_proc.threadPool; + L1proc.respEncode=RC.eNB[0][0]->proc.L1_proc.respEncode; + L1proc.respDecode=RC.eNB[0][0]->proc.L1_proc.respDecode; initStaticTime(begingWait); initStaticTime(begingProcessing); initRefTimes(fullLoop); @@ -1338,27 +1339,31 @@ void *DL_du_fs6(void *arg) { updateTimesReset(begingWait, &fullLoop, 1000, false, "DU wait CU"); if (nb_blocks > 0) { - if ( lastTS+ru->eNB_list[i]->frame_parms.samples_per_tti != hUDP(bufferZone)->timestamp) { + if ( lastTS+ru->eNB_list[i]->frame_parms.samples_per_tti < hUDP(bufferZone)->timestamp) { LOG_E(HW,"Missed a subframe: expecting: %lu, received %lu\n", lastTS+ru->eNB_list[i]->frame_parms.samples_per_tti, hUDP(bufferZone)->timestamp); + } else if ( lastTS+ru->eNB_list[i]->frame_parms.samples_per_tti > hUDP(bufferZone)->timestamp) { + LOG_E(HW,"Received a subframe in past time from CU (dropping it): expecting: %lu, received %lu\n", + lastTS+ru->eNB_list[i]->frame_parms.samples_per_tti, + hUDP(bufferZone)->timestamp); } pickStaticTime(begingProcessing); lastTS=hUDP(bufferZone)->timestamp; - setAllfromTS(hUDP(bufferZone)->timestamp - sf_ahead*ru->eNB_list[i]->frame_parms.samples_per_tti, &L1_proc); + setAllfromTS(hUDP(bufferZone)->timestamp - sf_ahead*ru->eNB_list[i]->frame_parms.samples_per_tti, &L1proc); measTransportTime(hDL(bufferZone)->DuClock, hDL(bufferZone)->CuSpentMicroSec, &transportTime, 1000, false, "Transport time, to CU + from CU for one subframe"); - phy_procedures_eNB_TX_fromsplit( bufferZone, nb_blocks, ru->eNB_list[i], &L1_proc, 1); + phy_procedures_eNB_TX_fromsplit( bufferZone, nb_blocks, ru->eNB_list[i], &L1proc, 1); updateTimesReset(begingProcessing, &DuHigh, 1000, false, "DU high layer1 processing for DL"); } else LOG_E(PHY,"DL not received for subframe\n"); } pickStaticTime(begingProcessing); - feptx_prec(ru, L1_proc.frame_tx,L1_proc.subframe_tx ); - feptx_ofdm(ru, L1_proc.frame_tx,L1_proc.subframe_tx ); - ocp_tx_rf(ru, &L1_proc); + feptx_prec(ru, L1proc.frame_tx,L1proc.subframe_tx ); + feptx_ofdm(ru, L1proc.frame_tx,L1proc.subframe_tx ); + ocp_tx_rf(ru, &L1proc); updateTimesReset(begingProcessing, &DuLow, 1000, false, "DU low layer1 processing for DL"); if ( IS_SOFTMODEM_RFSIM ) @@ -1374,7 +1379,6 @@ void UL_du_fs6(RU_t *ru, L1_rxtx_proc_t *proc) { pickStaticTime(begingWait); rx_rf(ru, proc); updateTimesReset(begingWait, &fullLoop, 1000, false, "DU wait USRP"); - setAllfromTS(proc->timestamp_rx, proc); // front end processing: convert from time domain to frequency domain // fills rxdataF buffer fep_full(ru, proc->subframe_rx); @@ -1480,23 +1484,22 @@ void *cu_fs6(void *arg) { init_frame_parms(ru->frame_parms,1); phy_init_RU(ru); wait_sync("ru_thread"); - char *remoteIP; - - if ( getenv("FS6_REMOTE_IP") ) - remoteIP=getenv("FS6_REMOTE_IP"); - else - remoteIP=DU_IP; - - AssertFatal(createUDPsock(NULL, CU_PORT, remoteIP, DU_PORT, &sockFS6), ""); + char remoteIP[1024]; + strncpy(remoteIP,get_softmodem_params()->split73+3, 1023); //three first char should be cu: or du: + char port_def[256]=DU_PORT; + for (int i=0; i <1000; i++) + if (remoteIP[i]==':') { + strncpy(port_def,remoteIP+i+1,255); + remoteIP[i]=0; + break; + } + + AssertFatal(createUDPsock(NULL, CU_PORT, remoteIP, port_def, &sockFS6), ""); L1_rxtx_proc_t L1proc= {0}; - - if ( strlen(get_softmodem_params()->threadPoolConfig) > 0 ) - initTpool(get_softmodem_params()->threadPoolConfig, &L1proc.threadPool, true); - else - initTpool("n", &L1proc.threadPool, true); - - initNotifiedFIFO(&L1proc.respEncode); - initNotifiedFIFO(&L1proc.respDecode); + // We pick the global thread pool from the legacy code global vars + L1proc.threadPool=RC.eNB[0][0]->proc.L1_proc.threadPool; + L1proc.respEncode=RC.eNB[0][0]->proc.L1_proc.respEncode; + L1proc.respDecode=RC.eNB[0][0]->proc.L1_proc.respDecode; uint64_t timeStamp=0; initStaticTime(begingWait); initStaticTime(begingWait2); @@ -1529,14 +1532,16 @@ void *du_fs6(void *arg) { phy_init_RU(ru); init_rf(ru); wait_sync("ru_thread"); - char *remoteIP; - - if ( getenv("FS6_REMOTE_IP") ) - remoteIP=getenv("FS6_REMOTE_IP"); - else - remoteIP=CU_IP; - - AssertFatal(createUDPsock(NULL, DU_PORT, remoteIP, CU_PORT, &sockFS6), ""); + char remoteIP[1024]; + strncpy(remoteIP,get_softmodem_params()->split73+3,1023); //three first char should be cu: or du: + char port_def[256]=CU_PORT; + for (int i=0; i <1000; i++) + if (remoteIP[i]==':') { + strncpy(port_def,remoteIP+i+1,255); + remoteIP[i]=0; + break; + } + AssertFatal(createUDPsock(NULL, DU_PORT, remoteIP, port_def, &sockFS6), ""); if (ru->rfdevice.trx_start_func(&ru->rfdevice) != 0) LOG_E(HW,"Could not start the RF device\n"); @@ -1551,8 +1556,13 @@ void *du_fs6(void *arg) { if ( !IS_SOFTMODEM_RFSIM ) threadCreate(&t, DL_du_fs6, (void *)ru, "MainDuTx", -1, OAI_PRIORITY_RT_MAX); - while(oai_exit) { - L1_rxtx_proc_t L1proc; + L1_rxtx_proc_t L1proc= {0}; + // We pick the global thread pool from the legacy code global vars + L1proc.threadPool=RC.eNB[0][0]->proc.L1_proc.threadPool; + L1proc.respEncode=RC.eNB[0][0]->proc.L1_proc.respEncode; + L1proc.respDecode=RC.eNB[0][0]->proc.L1_proc.respDecode; + + while(!oai_exit) { updateTimesReset(begingWait, &fullLoop, 1000, true,"DU for full SubFrame (must be less 1ms)"); pickStaticTime(begingWait); UL_du_fs6(ru, &L1proc); @@ -1562,7 +1572,7 @@ void *du_fs6(void *arg) { updateTimesReset(begingWait, &waitRxAndProcessingUL, 1000, true,"DU Time in wait Rx + Ul processing"); } - + ru->rfdevice.trx_end_func(&ru->rfdevice); LOG_I(PHY,"RU %d rf device stopped\n",ru->idx); return NULL; diff --git a/executables/main-ocp.c b/executables/main-ocp.c index 97939846fd..50cd1f2714 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -5,8 +5,11 @@ /* * This file replaces + * targets/RT/USER/lte-softmodem.c + * targets/RT/USER/rt_wrapper.c * targets/RT/USER/lte-ru.c * targets/RT/USER/lte-enb.c + * targets/RT/USER/ru_control.c * openair1/SCHED/prach_procedures.c * The merger of OpenAir central code to this branch * should check if these 3 files are modified and analyze if code code has to be copied in here @@ -16,6 +19,7 @@ #include #include +#include static int DEFBANDS[] = {7}; static int DEFENBS[] = {0}; #include @@ -30,8 +34,33 @@ static int DEFENBS[] = {0}; #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -extern uint16_t sf_ahead; +pthread_cond_t nfapi_sync_cond; +pthread_mutex_t nfapi_sync_mutex; +int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex +pthread_cond_t sync_cond; +pthread_mutex_t sync_mutex; +int sync_var=-1; //!< protected by mutex \ref sync_mutex. +int config_sync_var=-1; +volatile int oai_exit = 0; +double cpuf; +uint16_t sf_ahead=4; +int otg_enabled; +uint32_t downlink_frequency[MAX_NUM_CCs][4]; +int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int split73; +char * split73_config; +int split73; static void *ru_thread( void *param ); void kill_RU_proc(RU_t *ru) { @@ -42,6 +71,34 @@ void free_transport(PHY_VARS_eNB *eNB) { } void reset_opp_meas(void) { } +extern void phy_free_RU(RU_t *); + +void exit_function(const char *file, const char *function, const int line, const char *s) { + if (s != NULL) { + printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, s); + } + + close_log_mem(); + oai_exit = 1; + + if (RC.ru == NULL) + exit(-1); // likely init not completed, prevent crash or hang, exit now... + + for (int ru_id=0; ru_idrfdevice.trx_end_func) { + RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice); + RC.ru[ru_id]->rfdevice.trx_end_func = NULL; + } + + if (RC.ru[ru_id] && RC.ru[ru_id]->ifdevice.trx_end_func) { + RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice); + RC.ru[ru_id]->ifdevice.trx_end_func = NULL; + } + } + + sleep(1); //allow lte-softmodem threads to exit first + exit(1); +} // Fixme: there are many mistakes in the datamodel and in redondant variables // TDD is also mode complex @@ -67,92 +124,47 @@ void setAllfromTS(uint64_t TS, L1_rxtx_proc_t *proc) { return; } - -void init_eNB_proc(int inst) { - /*int i=0;*/ - int CC_id; - PHY_VARS_eNB *eNB; - - for (CC_id=0; CC_idUL_INFO_mutex, NULL); - } - - //for multiple CCs: setup master and slaves - /* - for (CC_id=0; CC_idnode_timing == synch_to_ext_device) { //master - proc->num_slaves = MAX_NUM_CCs-1; - proc->slave_proc = (L1_proc_t**)malloc(proc->num_slaves*sizeof(L1_proc_t*)); - - for (i=0; i< eNB->proc.num_slaves; i++) { - if (i < CC_id) eNB->proc.slave_proc[i] = &(PHY_vars_eNB_g[inst][i]->proc); - if (i >= CC_id) eNB->proc.slave_proc[i] = &(PHY_vars_eNB_g[inst][i+1]->proc); - } - } - } - */ -} - void init_RU_proc(RU_t *ru) { pthread_t t; - char *fs6=getenv("fs6"); - if (fs6) { - if ( strncasecmp(fs6,"cu", 2) == 0 ) - threadCreate(&t, cu_fs6, (void *)ru, "MainCu", -1, OAI_PRIORITY_RT_MAX); - else if ( strncasecmp(fs6,"du", 2) == 0 ) { - threadCreate(&t, du_fs6, (void *)ru, "MainDuRx", -1, OAI_PRIORITY_RT_MAX); - } else - AssertFatal(false, "environement variable fs6 is not cu or du"); - } else + switch(split73) { + case SPLIT73_CU: + threadCreate(&t, cu_fs6, (void *)ru, "MainCu", -1, OAI_PRIORITY_RT_MAX); + break; + case SPLIT73_DU: + threadCreate(&t, du_fs6, (void *)ru, "MainDuRx", -1, OAI_PRIORITY_RT_MAX); + break; + default: threadCreate(&t, ru_thread, (void *)ru, "MainRu", -1, OAI_PRIORITY_RT_MAX); + } } +// Create per UE structures void init_transport(PHY_VARS_eNB *eNB) { - int i; - int j; LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; LOG_I(PHY, "Initialise transport\n"); - for (i=0; idlsch[i][j] = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL,0,fp); - - if (!eNB->dlsch[i][j]) { - LOG_E(PHY,"Can't get eNB dlsch structures for UE %d \n", i); - exit(-1); - } else { - eNB->dlsch[i][j]->rnti=0; - LOG_D(PHY,"dlsch[%d][%d] => %p rnti:%d\n",i,j,eNB->dlsch[i][j], eNB->dlsch[i][j]->rnti); - } + for (int j=0; j<2; j++) { + AssertFatal( (eNB->dlsch[i][j] = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL,0,fp)) != NULL, + "Can't get eNB dlsch structures for UE %d \n", i); + eNB->dlsch[i][j]->rnti=0; + LOG_D(PHY,"dlsch[%d][%d] => %p rnti:%d\n",i,j,eNB->dlsch[i][j], eNB->dlsch[i][j]->rnti); } LOG_D(PHY,"Allocating Transport Channel Buffer for ULSCH, UE %d\n",i); - eNB->ulsch[1+i] = new_eNB_ulsch(MAX_TURBO_ITERATIONS,fp->N_RB_UL, 0); - - if (!eNB->ulsch[1+i]) { - LOG_E(PHY,"Can't get eNB ulsch structures\n"); - exit(-1); - } - + AssertFatal((eNB->ulsch[1+i] = new_eNB_ulsch(MAX_TURBO_ITERATIONS,fp->N_RB_UL, 0)) != NULL, + "Can't get eNB ulsch structures\n"); // this is the transmission mode for the signalling channels // this will be overwritten with the real transmission mode by the RRC once the UE is connected eNB->transmission_mode[i] = fp->nb_antenna_ports_eNB==1 ? 1 : 2; } // ULSCH for RA - eNB->ulsch[0] = new_eNB_ulsch(MAX_TURBO_ITERATIONS, fp->N_RB_UL, 0); - - if (!eNB->ulsch[0]) { - LOG_E(PHY,"Can't get eNB ulsch structures\n"); - exit(-1); - } - + AssertFatal( (eNB->ulsch[0] = new_eNB_ulsch(MAX_TURBO_ITERATIONS, fp->N_RB_UL, 0)) !=NULL, + "Can't get eNB ulsch structures\n"); eNB->dlsch_SI = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL, 0, fp); LOG_D(PHY,"eNB %d.%d : SI %p\n",eNB->Mod_id,eNB->CC_id,eNB->dlsch_SI); eNB->dlsch_ra = new_eNB_dlsch(1,8,NSOFT,fp->N_RB_DL, 0, fp); @@ -161,7 +173,7 @@ void init_transport(PHY_VARS_eNB *eNB) { LOG_D(PHY,"eNB %d.%d : MCH %p\n",eNB->Mod_id,eNB->CC_id,eNB->dlsch_MCH); eNB->rx_total_gain_dB=130; - for(i=0; imu_mimo_mode[i].dl_pow_off = 2; eNB->check_for_total_transmissions = 0; @@ -172,23 +184,19 @@ void init_transport(PHY_VARS_eNB *eNB) { } void init_eNB_afterRU(void) { - int inst,CC_id,ru_id,i,aa; - PHY_VARS_eNB *eNB; - - for (inst=0; instframe_parms.nb_antennas_rx = 0; eNB->frame_parms.nb_antennas_tx = 0; eNB->prach_vars.rxsigF[0] = (int16_t **)malloc16(64*sizeof(int16_t *)); for (int ce_level=0; ce_level<4; ce_level++) { - LOG_I(PHY,"Overwriting eNB->prach_vars_br.rxsigF.rxsigF[0]:%p\n", eNB->prach_vars_br.rxsigF[ce_level]); eNB->prach_vars_br.rxsigF[ce_level] = (int16_t **)malloc16(64*sizeof(int16_t *)); } - for (ru_id=0,aa=0; ru_idnum_RU; ru_id++) { + for (int ru_id=0,aa=0; ru_idnum_RU; ru_id++) { eNB->frame_parms.nb_antennas_rx += eNB->RU_list[ru_id]->nb_rx; eNB->frame_parms.nb_antennas_tx += eNB->RU_list[ru_id]->nb_tx; AssertFatal(eNB->RU_list[ru_id]->common.rxdataF!=NULL, @@ -198,7 +206,7 @@ void init_eNB_afterRU(void) { "RU %d : prach_rxsigF is NULL\n", eNB->RU_list[ru_id]->idx); - for (i=0; iRU_list[ru_id]->nb_rx; aa++,i++) { + for (int i=0; iRU_list[ru_id]->nb_rx; aa++,i++) { LOG_I(PHY,"Attaching RU %d antenna %d to eNB antenna %d\n",eNB->RU_list[ru_id]->idx,i,aa); eNB->prach_vars.rxsigF[0][aa] = eNB->RU_list[ru_id]->prach_rxsigF[i]; @@ -209,35 +217,24 @@ void init_eNB_afterRU(void) { } } - /* TODO: review this code, there is something wrong. - * In monolithic mode, we come here with nb_antennas_rx == 0 - * (not tested in other modes). - */ AssertFatal( eNB->frame_parms.nb_antennas_rx > 0 && eNB->frame_parms.nb_antennas_rx < 4, ""); AssertFatal( eNB->frame_parms.nb_antennas_tx > 0 && eNB->frame_parms.nb_antennas_rx < 4, ""); LOG_I(PHY,"inst %d, CC_id %d : nb_antennas_rx %d\n",inst,CC_id,eNB->frame_parms.nb_antennas_rx); init_transport(eNB); //init_precoding_weights(RC.eNB[inst][CC_id]); } - - init_eNB_proc(inst); } } void init_eNB(int single_thread_flag,int wait_for_sync) { - int CC_id; - int inst; - PHY_VARS_eNB *eNB; + AssertFatal(RC.eNB != NULL,"RC.eNB must have been allocated\n"); - if (RC.eNB == NULL) RC.eNB = (PHY_VARS_eNB ** *) malloc(RC.nb_L1_inst*sizeof(PHY_VARS_eNB **)); + for (int inst=0; instabstraction_flag = 0; eNB->single_thread_flag = single_thread_flag; AssertFatal((eNB->if_inst = IF_Module_init(inst))!=NULL,"Cannot register interface"); @@ -245,6 +242,7 @@ void init_eNB(int single_thread_flag,int wait_for_sync) { eNB->if_inst->PHY_config_req = phy_config_request; memset((void *)&eNB->UL_INFO,0,sizeof(eNB->UL_INFO)); memset((void *)&eNB->Sched_INFO,0,sizeof(eNB->Sched_INFO)); + pthread_mutex_init( &eNB->UL_INFO_mutex, NULL); LOG_I(PHY,"Setting indication lists\n"); eNB->UL_INFO.rx_ind.rx_indication_body.rx_pdu_list = eNB->rx_pdu_list; eNB->UL_INFO.crc_ind.crc_indication_body.crc_pdu_list = eNB->crc_pdu_list; @@ -381,7 +379,6 @@ int setup_RU_buffers(RU_t *ru) { return(0); } - void init_precoding_weights(PHY_VARS_eNB *eNB) { int layer,ru_id,aa,re,ue,tb; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; @@ -416,21 +413,21 @@ void init_precoding_weights(PHY_VARS_eNB *eNB) { } void ocp_rx_prach(PHY_VARS_eNB *eNB, - L1_rxtx_proc_t *proc, - RU_t *ru, - uint16_t *max_preamble, - uint16_t *max_preamble_energy, - uint16_t *max_preamble_delay, - uint16_t *avg_preamble_energy, - uint16_t Nf, - uint8_t tdd_mapindex, - uint8_t br_flag) { + L1_rxtx_proc_t *proc, + RU_t *ru, + uint16_t *max_preamble, + uint16_t *max_preamble_energy, + uint16_t *max_preamble_delay, + uint16_t *avg_preamble_energy, + uint16_t Nf, + uint8_t tdd_mapindex, + uint8_t br_flag) { int i; int prach_mask=0; - + if (br_flag == 0) { rx_prach0(eNB,ru,proc->frame_prach, proc->subframe_prach, - max_preamble,max_preamble_energy,max_preamble_delay,avg_preamble_energy,Nf,tdd_mapindex,0,0); + max_preamble,max_preamble_energy,max_preamble_delay,avg_preamble_energy,Nf,tdd_mapindex,0,0); } else { // This is procedure for eMTC, basically handling the repetitions prach_mask = is_prach_subframe(&eNB->frame_parms,proc->frame_prach_br,proc->subframe_prach_br); @@ -445,7 +442,7 @@ void ocp_rx_prach(PHY_VARS_eNB *eNB, eNB->prach_vars_br.repetition_number[i]++; // do basic PRACH reception rx_prach0(eNB,ru,proc->frame_prach, proc->subframe_prach_br, - max_preamble,max_preamble_energy,max_preamble_delay,avg_preamble_energy,Nf,tdd_mapindex,1,i); + max_preamble,max_preamble_energy,max_preamble_delay,avg_preamble_energy,Nf,tdd_mapindex,1,i); // if last repetition, clear counter if (eNB->prach_vars_br.repetition_number[i] == eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_numRepetitionPerPreambleAttempt[i]) { @@ -477,16 +474,16 @@ void prach_procedures_ocp(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int br_flag) // run PRACH detection for CE-level 0 only for now when br_flag is set ocp_rx_prach(eNB, - proc, - eNB->RU_list[0], - &max_preamble[0], - &max_preamble_energy[0], - &max_preamble_delay[0], - &avg_preamble_energy[0], - proc->frame_prach, - 0 - ,br_flag - ); + proc, + eNB->RU_list[0], + &max_preamble[0], + &max_preamble_energy[0], + &max_preamble_delay[0], + &avg_preamble_energy[0], + proc->frame_prach, + 0 + ,br_flag + ); LOG_D(PHY,"RACH detection index 0: max preamble: %u, energy: %u, delay: %u, avg energy: %u\n", max_preamble[0], max_preamble_energy[0], @@ -531,7 +528,7 @@ void prach_procedures_ocp(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int br_flag) /* ind++; } - } */// ce_level + } */// ce_level } else if ((eNB->prach_energy_counter == 100) && (max_preamble_energy[0] > eNB->measurements.prach_I0+eNB->prach_DTX_threshold)) { LOG_I(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure with preamble %d, energy %d.%d dB, delay %d\n", @@ -616,13 +613,6 @@ static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name return(0); } -void eNB_top(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, int dummy1, int dummy2, char *string,RU_t *ru) { - if (!oai_exit) { - if (rxtx(eNB,proc,string) < 0) - LOG_E(PHY,"eNB %d CC_id %d failed during execution\n",eNB->Mod_id,eNB->CC_id); - } -} - void rx_rf(RU_t *ru, L1_rxtx_proc_t *proc) { LTE_DL_FRAME_PARMS *fp = ru->frame_parms; void *rxp[ru->nb_rx]; @@ -728,42 +718,36 @@ void ocp_tx_rf(RU_t *ru, L1_rxtx_proc_t *proc) { static void *ru_thread( void *param ) { setbuf(stdout, NULL); setbuf(stderr, NULL); - RU_t *ru = (RU_t *)param; + RU_t *ru = (RU_t *)param; L1_rxtx_proc_t L1proc= {0}; - L1_rxtx_proc_t *proc=&L1proc; - - if ( strlen(get_softmodem_params()->threadPoolConfig) > 0 ) - initTpool(get_softmodem_params()->threadPoolConfig, &L1proc.threadPool, true); - else - initTpool("n", &L1proc.threadPool, true); - - initNotifiedFIFO(&L1proc.respEncode); - initNotifiedFIFO(&L1proc.respDecode); - + // We pick the global thread pool from the legacy code global vars + L1proc.threadPool=RC.eNB[0][0]->proc.L1_proc.threadPool; + L1proc.respEncode=RC.eNB[0][0]->proc.L1_proc.respEncode; + L1proc.respDecode=RC.eNB[0][0]->proc.L1_proc.respDecode; + if (ru->if_south == LOCAL_RF) { // configure RF parameters only fill_rf_config(ru,ru->rf_config_file); init_frame_parms(ru->frame_parms,1); phy_init_RU(ru); init_rf(ru); } - + AssertFatal(setup_RU_buffers(ru)==0, "Exiting, cannot initialize RU Buffers\n"); LOG_I(PHY, "Signaling main thread that RU %d is ready\n",ru->idx); wait_sync("ru_thread"); - + // Start RF device if any if (ru->rfdevice.trx_start_func(&ru->rfdevice) != 0) LOG_E(HW,"Could not start the RF device\n"); else LOG_I(PHY,"RU %d rf device ready\n",ru->idx); - + // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices while (!oai_exit) { // synchronization on input FH interface, acquire signals/data and block - rx_rf(ru, proc); - + rx_rf(ru, &L1proc); // do RX front-end processing (frequency-shift, dft) if needed - fep_full(ru, proc->subframe_rx); - + fep_full(ru, L1proc.subframe_rx); + // At this point, all information for subframe has been received on FH interface // If this proc is to provide synchronization, do so // Fixme: not used @@ -771,24 +755,23 @@ static void *ru_thread( void *param ) { for (int i=0; inum_eNB; i++) { char string[20]; sprintf(string,"Incoming RU %d",ru->idx); - eNB_top(ru->eNB_list[i],proc, proc->frame_rx,proc->subframe_rx,string,ru); + + if (rxtx(ru->eNB_list[i],&L1proc,string) < 0) + LOG_E(PHY,"eNB %d CC_id %d failed during execution\n", + ru->eNB_list[i]->Mod_id,ru->eNB_list[i]->CC_id); } - + // do TX front-end processing if needed (precoding and/or IDFTs) - feptx_prec(ru, proc->frame_tx, proc->subframe_tx); - + feptx_prec(ru, L1proc.frame_tx, L1proc.subframe_tx); // do OFDM if needed - feptx_ofdm(ru, proc->frame_tx, proc->subframe_tx); - + feptx_ofdm(ru, L1proc.frame_tx, L1proc.subframe_tx); // do outgoing fronthaul (south) if needed - ocp_tx_rf(ru, proc); + ocp_tx_rf(ru, &L1proc); } - + LOG_W(PHY,"Exiting ru_thread \n"); - ru->rfdevice.trx_end_func(&ru->rfdevice); LOG_I(PHY,"RU %d rf device stopped\n",ru->idx); - return NULL; } @@ -801,34 +784,24 @@ int init_rf(RU_t *ru) { return ret; } - -void set_function_spec_param(RU_t *ru) { -} - -//extern void RCconfig_RU(void); - void init_RU(char *rf_config_file, clock_source_t clock_source,clock_source_t time_source,int send_dmrssync) { - int ru_id; RU_t *ru; PHY_VARS_eNB *eNB0= (PHY_VARS_eNB *)NULL; int i; int CC_id; - // create status mask - pthread_mutex_init(&RC.ru_mutex,NULL); - pthread_cond_init(&RC.ru_cond,NULL); // read in configuration file) LOG_I(PHY,"configuring RU from file\n"); - RCconfig_RU(); LOG_I(PHY,"number of L1 instances %d, number of RU %d, number of CPU cores %d\n", RC.nb_L1_inst,RC.nb_RU,get_nprocs()); if (RC.nb_CC != 0) for (i=0; inum_RU=0; + for (CC_id=0; CC_idnum_RU=0; LOG_D(PHY,"Process RUs RC.nb_RU:%d\n",RC.nb_RU); - for (ru_id=0; ru_idrf_config_file = rf_config_file; @@ -862,43 +835,23 @@ void init_RU(char *rf_config_file, clock_source_t clock_source,clock_source_t ti if (ru->num_eNB > 0) { LOG_D(PHY, "%s() RC.ru[%d].num_eNB:%d ru->eNB_list[0]:%p RC.eNB[0][0]:%p rf_config_file:%s\n", __FUNCTION__, ru_id, ru->num_eNB, ru->eNB_list[0], RC.eNB[0][0], ru->rf_config_file); - - if (ru->eNB_list[0] == 0) { - LOG_E(PHY,"%s() DJP - ru->eNB_list ru->num_eNB are not initialized - so do it manually\n", - __FUNCTION__); - ru->eNB_list[0] = RC.eNB[0][0]; - ru->num_eNB=1; - // - // DJP - feptx_prec() / feptx_ofdm() parses the eNB_list (based on num_eNB) and copies the txdata_F to txdata in RU - // - } else { - LOG_E(PHY,"DJP - delete code above this %s:%d\n", __FILE__, __LINE__); - } + AssertFatal(ru->eNB_list[0], "ru->eNB_list is not initialized\n"); + } else { + LOG_E(PHY,"Wrong data model, assigning eNB 0, carrier 0 to RU 0\n"); + ru->eNB_list[0] = RC.eNB[0][0]; + ru->num_eNB=1; } eNB0 = ru->eNB_list[0]; - LOG_D(PHY, "RU FUnction:%d ru->if_south:%d\n", ru->function, ru->if_south); - LOG_D(PHY, "eNB0:%p\n", eNB0); + // datamodel error in regular OAI: a RU uses one single eNB carrier parameters! + ru->frame_parms = &eNB0->frame_parms; - if (eNB0) { - LOG_I(PHY,"Copying frame parms from eNB %d to ru %d\n",eNB0->Mod_id,ru->idx); - ru->frame_parms=&eNB0->frame_parms; - - for (i=0; inum_eNB; i++) { - eNB0 = ru->eNB_list[i]; - eNB0->RU_list[eNB0->num_RU++] = ru; - } + for (i=0; inum_eNB; i++) { + eNB0 = ru->eNB_list[i]; + int ruIndex=eNB0->num_RU++; + eNB0->RU_list[ruIndex] = ru; } - - LOG_I(PHY,"Initializing RRU descriptor %d : (%s,%s,%d)\n", - ru_id,ru_if_types[ru->if_south],NB_timing[ru->if_timing],ru->function); - set_function_spec_param(ru); - LOG_I(PHY,"Starting ru_thread %d\n",ru_id); - init_RU_proc(ru); } // for ru_id - - // sleep(1); - LOG_D(HW,"[lte-softmodem.c] RU threads created\n"); } void stop_RU(int nb_ru) { @@ -912,20 +865,25 @@ void stop_RU(int nb_ru) { /* from here function to use configuration module */ static int DEFBFW[] = {0x00007fff}; void RCconfig_RU(void) { - int j = 0; - int i = 0; paramdef_t RUParams[] = RUPARAMS_DESC; paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0}; config_getlist( &RUParamList,RUParams,sizeof(RUParams)/sizeof(paramdef_t), NULL); - if ( RUParamList.numelt == 0 ) { + if ( RUParamList.numelt == 0 ) { + LOG_W(PHY, "Calling RCconfig_RU while no ru\n"); RC.nb_RU = 0; return; } // setting != NULL + if ( RC.ru != NULL ) { + LOG_W(PHY, "Calling RCconfig_RU twice (nb ru=%d), ignoring the second call data structure is %p\n", + RUParamList.numelt,RC.ru); + return; + } + RC.ru = (RU_t **)malloc(RC.nb_RU*sizeof(RU_t *)); - for (j = 0; j < RC.nb_RU; j++) { + for (int j = 0; j < RC.nb_RU; j++) { RC.ru[j] = (RU_t *)calloc(sizeof(RU_t), 1); RC.ru[j]->idx = j; LOG_I(PHY,"Creating RC.ru[%d]:%p\n", j, RC.ru[j]); @@ -937,7 +895,7 @@ void RCconfig_RU(void) { else RC.ru[j]->num_eNB = 0; - for (i=0; inum_eNB; i++) + for (int i=0; inum_eNB; i++) RC.ru[j]->eNB_list[i] = RC.eNB[vals[RU_ENB_LIST_IDX].iptr[i]][0]; if (config_isparamset(vals, RU_SDR_ADDRS)) { @@ -981,7 +939,7 @@ void RCconfig_RU(void) { RC.ru[j]->sf_extension = *(vals[RU_SF_EXTENSION_IDX].uptr); RC.ru[j]->end_of_burst_delay = *(vals[RU_END_OF_BURST_DELAY_IDX].uptr); - for (i=0; inum_bands; i++) RC.ru[j]->band[i] = vals[RU_BAND_LIST_IDX].iptr[i]; + for (int i=0; inum_bands; i++) RC.ru[j]->band[i] = vals[RU_BAND_LIST_IDX].iptr[i]; } else { LOG_I(PHY,"RU %d: Transport %s\n",j,*(vals[RU_TRANSPORT_PREFERENCE_IDX].strptr)); RC.ru[j]->eth_params.local_if_name = strdup(*(vals[RU_LOCAL_IF_NAME_IDX].strptr)); @@ -1001,3 +959,430 @@ void RCconfig_RU(void) { return; } + + +static void get_options(void) { + CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP); + get_common_options(); + CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP); + + if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) ) { + memset((void *)&RC,0,sizeof(RC)); + /* Read RC configuration file */ + RCConfig(); + NB_eNB_INST = RC.nb_inst; + printf("Configuration: nb_rrc_inst %d, nb_L1_inst %d, nb_ru %d\n",NB_eNB_INST,RC.nb_L1_inst,RC.nb_RU); + + if (!IS_SOFTMODEM_NONBIOT) { + load_NB_IoT(); + printf(" nb_nbiot_rrc_inst %d, nb_nbiot_L1_inst %d, nb_nbiot_macrlc_inst %d\n", + RC.nb_nb_iot_rrc_inst, RC.nb_nb_iot_L1_inst, RC.nb_nb_iot_macrlc_inst); + } else { + printf("All Nb-IoT instances disabled\n"); + RC.nb_nb_iot_rrc_inst=RC.nb_nb_iot_L1_inst=RC.nb_nb_iot_macrlc_inst=0; + } + } +} + +void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) { + int CC_id; + + for (CC_id=0; CC_idframe_type = FDD; + frame_parms[CC_id]->tdd_config = 3; + frame_parms[CC_id]->tdd_config_S = 0; + frame_parms[CC_id]->N_RB_DL = 100; + frame_parms[CC_id]->N_RB_UL = 100; + frame_parms[CC_id]->Ncp = NORMAL; + frame_parms[CC_id]->Ncp_UL = NORMAL; + frame_parms[CC_id]->Nid_cell = 0; + frame_parms[CC_id]->num_MBSFN_config = 0; + frame_parms[CC_id]->nb_antenna_ports_eNB = 1; + frame_parms[CC_id]->nb_antennas_tx = 1; + frame_parms[CC_id]->nb_antennas_rx = 1; + frame_parms[CC_id]->nushift = 0; + frame_parms[CC_id]->phich_config_common.phich_resource = oneSixth; + frame_parms[CC_id]->phich_config_common.phich_duration = normal; + // UL RS Config + frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = 0;//n_DMRS1 set to 0 + frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = 0; + frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = 0; + frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0; + frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22; + frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1; + frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0; + frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.highSpeedFlag=0; + frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_FreqOffset=0; + // downlink_frequency[CC_id][0] = 2680000000; // Use float to avoid issue with frequency over 2^31. + // downlink_frequency[CC_id][1] = downlink_frequency[CC_id][0]; + // downlink_frequency[CC_id][2] = downlink_frequency[CC_id][0]; + // downlink_frequency[CC_id][3] = downlink_frequency[CC_id][0]; + //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]); + frame_parms[CC_id]->dl_CarrierFreq=downlink_frequency[CC_id][0]; + } +} + +void init_pdcp(void) { + if (!NODE_IS_DU(RC.rrc[0]->node_type)) { + pdcp_layer_init(); + uint32_t pdcp_initmask = (IS_SOFTMODEM_NOS1) ? + (PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT; + + if (IS_SOFTMODEM_NOS1) + pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT ; + + pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_W_MBMS_BIT; + + if ( split73!=SPLIT73_DU) + pdcp_module_init(pdcp_initmask); + + if (NODE_IS_CU(RC.rrc[0]->node_type)) { + pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t)proto_agent_send_rlc_data_req); + } else { + pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req); + pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind); + } + } else { + pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) proto_agent_send_pdcp_data_ind); + } +} + +static void wait_nfapi_init(char *thread_name) { + printf( "waiting for NFAPI PNF connection and population of global structure (%s)\n",thread_name); + pthread_mutex_lock( &nfapi_sync_mutex ); + + while (nfapi_sync_var<0) + pthread_cond_wait( &nfapi_sync_cond, &nfapi_sync_mutex ); + + pthread_mutex_unlock(&nfapi_sync_mutex); + printf( "NFAPI: got sync (%s)\n", thread_name); +} + +void terminate_task(module_id_t mod_id, task_id_t from, task_id_t to) { + LOG_I(ENB_APP, "sending TERMINATE_MESSAGE from task %s (%d) to task %s (%d)\n", + itti_get_task_name(from), from, itti_get_task_name(to), to); + MessageDef *msg; + msg = itti_alloc_new_message (from, TERMINATE_MESSAGE); + itti_send_msg_to_task (to, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg); +} + +int stop_L1L2(module_id_t enb_id) { + LOG_W(ENB_APP, "stopping lte-softmodem\n"); + + if (!RC.ru) { + LOG_UI(ENB_APP, "no RU configured\n"); + return -1; + } + + /* these tasks need to pick up new configuration */ + terminate_task(enb_id, TASK_ENB_APP, TASK_RRC_ENB); + oai_exit = 1; + LOG_I(ENB_APP, "calling kill_RU_proc() for instance %d\n", enb_id); + kill_RU_proc(RC.ru[enb_id]); + LOG_I(ENB_APP, "calling kill_eNB_proc() for instance %d\n", enb_id); + kill_eNB_proc(enb_id); + oai_exit = 0; + + for (int cc_id = 0; cc_id < RC.nb_CC[enb_id]; cc_id++) { + free_transport(RC.eNB[enb_id][cc_id]); + phy_free_lte_eNB(RC.eNB[enb_id][cc_id]); + } + + phy_free_RU(RC.ru[enb_id]); + free_lte_top(); + return 0; +} + +/* + * Restart the lte-softmodem after it has been soft-stopped with stop_L1L2() + */ +int restart_L1L2(module_id_t enb_id) { + RU_t *ru = RC.ru[enb_id]; + MessageDef *msg_p = NULL; + LOG_W(ENB_APP, "restarting lte-softmodem\n"); + /* block threads */ + pthread_mutex_lock(&sync_mutex); + sync_var = -1; + pthread_mutex_unlock(&sync_mutex); + RC.ru_mask |= (1 << ru->idx); + /* copy the changed frame parameters to the RU */ + /* TODO this should be done for all RUs associated to this eNB */ + memcpy(&ru->frame_parms, &RC.eNB[enb_id][0]->frame_parms, sizeof(LTE_DL_FRAME_PARMS)); + /* reset the list of connected UEs in the MAC, since in this process with + * loose all UEs (have to reconnect) */ + init_UE_list(&RC.mac[enb_id]->UE_list); + LOG_I(ENB_APP, "attempting to create ITTI tasks\n"); + // No more rrc thread, as many race conditions are hidden behind + rrc_enb_init(); + itti_mark_task_ready(TASK_RRC_ENB); + /* pass a reconfiguration request which will configure everything down to + * RC.eNB[i][j]->frame_parms, too */ + msg_p = itti_alloc_new_message(TASK_ENB_APP, RRC_CONFIGURATION_REQ); + RRC_CONFIGURATION_REQ(msg_p) = RC.rrc[enb_id]->configuration; + itti_send_msg_to_task(TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p); + /* TODO XForms might need to be restarted, but it is currently (09/02/18) + * broken, so we cannot test it */ + init_RU_proc(ru); + ru->rf_map.card = 0; + ru->rf_map.chain = 0; /* CC_id + chain_offset;*/ + init_eNB_afterRU(); + printf("Sending sync to all threads\n"); + pthread_mutex_lock(&sync_mutex); + sync_var=0; + pthread_cond_broadcast(&sync_cond); + pthread_mutex_unlock(&sync_mutex); + return 0; +} + +int main ( int argc, char **argv ) { + int i; + int CC_id = 0; + int node_type = ngran_eNB; + AssertFatal(load_configmodule(argc,argv,0), "[SOFTMODEM] Error, configuration module init failed\n"); + logInit(); + printf("Reading in command-line options\n"); + get_options (); + AssertFatal(!CONFIG_ISFLAGSET(CONFIG_ABORT),"Getting configuration failed\n"); + EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1; +#if T_TRACER + T_Config_Init(); +#endif + configure_linux(); + cpuf=get_cpu_freq_GHz(); + set_taus_seed (0); + + if (opp_enabled ==1) + reset_opp_meas(); + + itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info); + init_opt(); +#ifndef PACKAGE_VERSION +# define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL" +#endif + LOG_I(HW, "Version: %s\n", PACKAGE_VERSION); + + /* Read configuration */ + if (RC.nb_inst > 0) { + // Allocate memory from RC variable + read_config_and_init(); + } else { + printf("RC.nb_inst = 0, Initializing L1\n"); + RCconfig_L1(); + } + + /* We need to read RU configuration before FlexRAN starts so it knows what + * splits to report. Actual RU start comes later. */ + if (RC.nb_RU > 0 && NFAPI_MODE != NFAPI_MODE_VNF) { + RCconfig_RU(); + LOG_I(PHY, + "number of L1 instances %d, number of RU %d, number of CPU cores %d\n", + RC.nb_L1_inst, RC.nb_RU, get_nprocs()); + } + + if ( strlen(get_softmodem_params()->split73) > 0 ) { + char tmp[1024]={0}; + strncpy(tmp,get_softmodem_params()->split73, 1023); + tmp[2]=0; + if ( strncasecmp(tmp,"cu", 2)==0 ) + split73=SPLIT73_CU; + else if ( strncasecmp(tmp,"du", 2)==0 ) + split73=SPLIT73_DU; + else + AssertFatal(false,"split73 syntax: :[:] (string found: %s) \n",get_softmodem_params()->split73); + } + + if (RC.nb_inst > 0) { + /* Start the agent. If it is turned off in the configuration, it won't start */ + for (i = 0; i < RC.nb_inst; i++) { + flexran_agent_start(i); + } + + /* initializes PDCP and sets correct RLC Request/PDCP Indication callbacks + * for monolithic/F1 modes */ + init_pdcp(); + AssertFatal(create_tasks(1)==0,"cannot create ITTI tasks\n"); + + for (int enb_id = 0; enb_id < RC.nb_inst; enb_id++) { + MessageDef *msg_p = itti_alloc_new_message (TASK_ENB_APP, RRC_CONFIGURATION_REQ); + RRC_CONFIGURATION_REQ(msg_p) = RC.rrc[enb_id]->configuration; + itti_send_msg_to_task (TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p); + } + + node_type = RC.rrc[0]->node_type; + } + + if (RC.nb_inst > 0 && NODE_IS_CU(node_type)) { + protocol_ctxt_t ctxt; + ctxt.module_id = 0 ; + ctxt.instance = 0; + ctxt.rnti = 0; + ctxt.enb_flag = 1; + ctxt.frame = 0; + ctxt.subframe = 0; + pdcp_run(&ctxt); + } + + /* start threads if only L1 or not a CU */ + if (RC.nb_inst == 0 || !NODE_IS_CU(node_type) || NFAPI_MODE == NFAPI_MODE_PNF || NFAPI_MODE == NFAPI_MODE_VNF) { + // init UE_PF_PO and mutex lock + pthread_mutex_init(&ue_pf_po_mutex, NULL); + memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*MAX_MOBILES_PER_ENB*MAX_NUM_CCs); + pthread_cond_init(&sync_cond,NULL); + pthread_mutex_init(&sync_mutex, NULL); + + if (NFAPI_MODE!=NFAPI_MONOLITHIC) { + LOG_I(ENB_APP,"NFAPI*** - mutex and cond created - will block shortly for completion of PNF connection\n"); + pthread_cond_init(&sync_cond,NULL); + pthread_mutex_init(&sync_mutex, NULL); + } + + if (NFAPI_MODE==NFAPI_MODE_VNF) {// VNF +#if defined(PRE_SCD_THREAD) + init_ru_vnf(); // ru pointer is necessary for pre_scd. +#endif + wait_nfapi_init("main?"); + } + + LOG_I(ENB_APP,"START MAIN THREADS\n"); + // start the main threads + number_of_cards = 1; + printf("RC.nb_L1_inst:%d\n", RC.nb_L1_inst); + + if (RC.nb_L1_inst > 0) { + printf("Initializing eNB threads single_thread_flag:%d wait_for_sync:%d\n", + get_softmodem_params()->single_thread_flag, + get_softmodem_params()->wait_for_sync); + init_eNB(get_softmodem_params()->single_thread_flag, + get_softmodem_params()->wait_for_sync); + } + + for (int x=0; x < RC.nb_L1_inst; x++) + for (int CC_id=0; CC_idproc.L1_proc; + L1proc->threadPool=(tpool_t *)malloc(sizeof(tpool_t)); + L1proc->respEncode=(notifiedFIFO_t *) malloc(sizeof(notifiedFIFO_t)); + L1proc->respDecode=(notifiedFIFO_t *) malloc(sizeof(notifiedFIFO_t)); + + if ( strlen(get_softmodem_params()->threadPoolConfig) > 0 ) + initTpool(get_softmodem_params()->threadPoolConfig, L1proc->threadPool, true); + else + initTpool("n", L1proc->threadPool, true); + + initNotifiedFIFO(L1proc->respEncode); + initNotifiedFIFO(L1proc->respDecode); + } + } + + printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU); + + // RU thread and some L1 procedure aren't necessary in VNF or L2 FAPI simulator. + // but RU thread deals with pre_scd and this is necessary in VNF and simulator. + // some initialization is necessary and init_ru_vnf do this. + if (RC.nb_RU >0 && NFAPI_MODE!=NFAPI_MODE_VNF) { + printf("Initializing RU threads\n"); + init_RU(get_softmodem_params()->rf_config_file, + get_softmodem_params()->clock_source, + get_softmodem_params()->timing_source, + get_softmodem_params()->send_dmrs_sync); + + for (int ru_id=0; ru_idrf_map.card=0; + RC.ru[ru_id]->rf_map.chain=CC_id+(get_softmodem_params()->chain_offset); + LOG_I(PHY,"Starting ru_thread %d\n",ru_id); + init_RU_proc(RC.ru[ru_id]); + } + + config_sync_var=0; + + if (NFAPI_MODE==NFAPI_MODE_PNF) { // PNF + wait_nfapi_init("main?"); + } + + LOG_I(ENB_APP,"RC.nb_RU:%d\n", RC.nb_RU); + // once all RUs are ready intiailize the rest of the eNBs ((dependence on final RU parameters after configuration) + printf("ALL RUs ready - init eNBs\n"); + + if (NFAPI_MODE!=NFAPI_MODE_PNF && NFAPI_MODE!=NFAPI_MODE_VNF) { + LOG_I(ENB_APP,"Not NFAPI mode - call init_eNB_afterRU()\n"); + init_eNB_afterRU(); + } else { + LOG_I(ENB_APP,"NFAPI mode - DO NOT call init_eNB_afterRU()\n"); + } + + LOG_UI(ENB_APP,"ALL RUs ready - ALL eNBs ready\n"); + // connect the TX/RX buffers + sleep(1); /* wait for thread activation */ + LOG_I(ENB_APP,"Sending sync to all threads\n"); + pthread_mutex_lock(&sync_mutex); + sync_var=0; + pthread_cond_broadcast(&sync_cond); + pthread_mutex_unlock(&sync_mutex); + config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS); + } + + create_tasks_mbms(1); + // wait for end of program + LOG_UI(ENB_APP,"TYPE TO TERMINATE\n"); + // CI -- Flushing the std outputs for the previous marker to show on the eNB / DU / CU log file + fflush(stdout); + fflush(stderr); + + // end of CI modifications + //getchar(); + if(IS_SOFTMODEM_DOFORMS) + load_softscope("enb"); + + itti_wait_tasks_end(); + oai_exit=1; + LOG_I(ENB_APP,"oai_exit=%d\n",oai_exit); + // stop threads + + if (RC.nb_inst == 0 || !NODE_IS_CU(node_type)) { + if(IS_SOFTMODEM_DOFORMS) + end_forms(); + + LOG_I(ENB_APP,"stopping MODEM threads\n"); + stop_eNB(NB_eNB_INST); + stop_RU(RC.nb_RU); + + /* release memory used by the RU/eNB threads (incomplete), after all + * threads have been stopped (they partially use the same memory) */ + for (int inst = 0; inst < NB_eNB_INST; inst++) { + for (int cc_id = 0; cc_id < RC.nb_CC[inst]; cc_id++) { + free_transport(RC.eNB[inst][cc_id]); + phy_free_lte_eNB(RC.eNB[inst][cc_id]); + } + } + + for (int inst = 0; inst < RC.nb_RU; inst++) { + phy_free_RU(RC.ru[inst]); + } + + free_lte_top(); + end_configmodule(); + pthread_cond_destroy(&sync_cond); + pthread_mutex_destroy(&sync_mutex); + pthread_cond_destroy(&nfapi_sync_cond); + pthread_mutex_destroy(&nfapi_sync_mutex); + pthread_mutex_destroy(&ue_pf_po_mutex); + + for(int ru_id=0; ru_idrfdevice.trx_end_func) { + RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice); + RC.ru[ru_id]->rfdevice.trx_end_func = NULL; + } + + if (RC.ru[ru_id]->ifdevice.trx_end_func) { + RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice); + RC.ru[ru_id]->ifdevice.trx_end_func = NULL; + } + } + } + + terminate_opt(); + logClean(); + printf("Bye.\n"); + return 0; +} diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 46689b137a..43407de19b 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -180,14 +180,14 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t // **************************************** // Common RX procedures subframe n T(T_GNB_PHY_DL_TICK, T_INT(gNB->Mod_id), T_INT(frame_tx), T_INT(slot_tx)); -/* - // if this is IF5 or 3GPP_gNB - if (gNB && gNB->RU_list && gNB->RU_list[0] && gNB->RU_list[0]->function < NGFI_RAU_IF4p5) { - wakeup_prach_gNB(gNB,NULL,proc->frame_rx,proc->slot_rx); - } + /* + // if this is IF5 or 3GPP_gNB + if (gNB && gNB->RU_list && gNB->RU_list[0] && gNB->RU_list[0]->function < NGFI_RAU_IF4p5) { + wakeup_prach_gNB(gNB,NULL,proc->frame_rx,proc->slot_rx); + } - // UE-specific RX processing for subframe n - if (nfapi_mode == 0 || nfapi_mode == 1) */ + // UE-specific RX processing for subframe n + if (nfapi_mode == 0 || nfapi_mode == 1) */ pthread_mutex_lock(&gNB->UL_INFO_mutex); gNB->UL_INFO.frame = frame_rx; @@ -207,8 +207,8 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t if (oai_exit) return(-1); - //if (slot_rx == NR_UPLINK_SLOT || gNB->frame_parms.frame_type == FDD) - phy_procedures_gNB_uespec_RX(gNB, frame_rx, slot_rx); + //if (slot_rx == NR_UPLINK_SLOT || gNB->frame_parms.frame_type == FDD) + phy_procedures_gNB_uespec_RX(gNB, frame_rx, slot_rx); if(get_thread_parallel_conf() != PARALLEL_RU_L1_TRX_SPLIT) { phy_procedures_gNB_TX(gNB, frame_tx,slot_tx, 1); @@ -318,7 +318,7 @@ static void *gNB_L1_thread( void *param ) { gNB_L1_rxtx_proc_t *L1_proc = &gNB_proc->L1_proc; //PHY_VARS_gNB *gNB = RC.gNB[0][proc->CC_id]; char thread_name[100]; - + // set default return value // set default return value gNB_thread_rxtx_status = 0; @@ -327,16 +327,15 @@ static void *gNB_L1_thread( void *param ) { while (!oai_exit) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 0 ); - if (wait_on_condition(&L1_proc->mutex,&L1_proc->cond,&L1_proc->instance_cnt,thread_name)<0) break; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 1 ); + if (wait_on_condition(&L1_proc->mutex,&L1_proc->cond,&L1_proc->instance_cnt,thread_name)<0) break; + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 1 ); int frame_rx = L1_proc->frame_rx; int slot_rx = L1_proc->slot_rx; int frame_tx = L1_proc->frame_tx; int slot_tx = L1_proc->slot_tx; uint64_t timestamp_tx = L1_proc->timestamp_tx; - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_TX0_GNB,slot_tx); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_RX0_GNB,slot_rx); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_GNB,frame_tx); @@ -408,17 +407,15 @@ void gNB_top(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, char *string, struct } int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot_tx,uint64_t timestamp_tx) { - RU_t *ru; RU_proc_t *ru_proc; - int waitret = 0, ret = 0, time_ns = 1000*1000; struct timespec now, abstime; - // note this should depend on the numerology used by the TX L1 thread, set here for 500us slot time VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,1); time_ns = time_ns/gNB->frame_parms.slots_per_subframe; AssertFatal((ret = pthread_mutex_lock(&proc->mutex_RUs_tx))==0,"mutex_lock returns %d\n",ret); + while (proc->instance_cnt_RUs < 0) { clock_gettime(CLOCK_REALTIME, &now); abstime.tv_sec = now.tv_sec; @@ -428,35 +425,32 @@ int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot abstime.tv_nsec -= 1000*1000*1000; abstime.tv_sec += 1; } + if((waitret = pthread_cond_timedwait(&proc->cond_RUs,&proc->mutex_RUs_tx,&abstime)) == 0) break; // this unlocks mutex_rxtx while waiting and then locks it again } + proc->instance_cnt_RUs = -1; VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs); AssertFatal((ret = pthread_mutex_unlock(&proc->mutex_RUs_tx))==0,"mutex_unlock returns %d\n",ret); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,0); if (waitret == ETIMEDOUT) { - LOG_W(PHY,"Dropping TX slot (%d.%d) because FH is blocked more than 1 slot times (500us)\n",frame_tx,slot_tx); + LOG_W(PHY,"Dropping TX slot (%d.%d) because FH is blocked more than 1 slot times (500us)\n",frame_tx,slot_tx); + AssertFatal((ret=pthread_mutex_lock(&gNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret); + gNB->proc.RU_mask_tx = 0; + AssertFatal((ret=pthread_mutex_unlock(&gNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret); + AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RUs_tx))==0,"mutex_lock returns %d\n",ret); + proc->instance_cnt_RUs = 0; + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs); + AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RUs_tx))==0,"mutex_unlock returns %d\n",ret); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,1); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,0); + return(-1); + } - AssertFatal((ret=pthread_mutex_lock(&gNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret); - gNB->proc.RU_mask_tx = 0; - AssertFatal((ret=pthread_mutex_unlock(&gNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret); - AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RUs_tx))==0,"mutex_lock returns %d\n",ret); - proc->instance_cnt_RUs = 0; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs); - AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RUs_tx))==0,"mutex_unlock returns %d\n",ret); - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,1); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,0); - - return(-1); - } - - for(int i=0; inum_RU; i++) - { + for(int i=0; inum_RU; i++) { ru = gNB->RU_list[i]; ru_proc = &ru->proc; - if (ru_proc->instance_cnt_gNBs == 0) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST_UE, 1); @@ -464,62 +458,46 @@ int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot AssertFatal((ret=pthread_mutex_lock(&gNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret); gNB->proc.RU_mask_tx = 0; AssertFatal((ret=pthread_mutex_unlock(&gNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST_UE, 0); return(-1); } - AssertFatal((ret = pthread_mutex_lock(&ru_proc->mutex_gNBs))==0,"ERROR pthread_mutex_lock failed on mutex_gNBs L1_thread_tx with ret=%d\n",ret); + AssertFatal((ret = pthread_mutex_lock(&ru_proc->mutex_gNBs))==0,"ERROR pthread_mutex_lock failed on mutex_gNBs L1_thread_tx with ret=%d\n",ret); ru_proc->instance_cnt_gNBs = 0; ru_proc->timestamp_tx = timestamp_tx; ru_proc->tti_tx = slot_tx; ru_proc->frame_tx = frame_tx; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_UE, ru_proc->instance_cnt_gNBs); - - LOG_D(PHY,"Signaling tx_thread_fh for %d.%d\n",frame_tx,slot_tx); + LOG_D(PHY,"Signaling tx_thread_fh for %d.%d\n",frame_tx,slot_tx); // the thread can now be woken up AssertFatal(pthread_cond_signal(&ru_proc->cond_gNBs) == 0, - "[gNB] ERROR pthread_cond_signal for gNB TXnp4 thread\n"); + "[gNB] ERROR pthread_cond_signal for gNB TXnp4 thread\n"); AssertFatal((ret=pthread_mutex_unlock(&ru_proc->mutex_gNBs))==0,"mutex_unlock returned %d\n",ret); - } + return(0); } int wakeup_tx(PHY_VARS_gNB *gNB,int frame_rx,int slot_rx,int frame_tx,int slot_tx,uint64_t timestamp_tx) { - - gNB_L1_rxtx_proc_t *L1_proc_tx = &gNB->proc.L1_proc_tx; - int ret; - - AssertFatal((ret = pthread_mutex_lock(&L1_proc_tx->mutex))==0,"mutex_lock returns %d\n",ret); - - while(L1_proc_tx->instance_cnt == 0){ + while(L1_proc_tx->instance_cnt == 0) { pthread_cond_wait(&L1_proc_tx->cond,&L1_proc_tx->mutex); } L1_proc_tx->instance_cnt = 0; - - L1_proc_tx->slot_rx = slot_rx; L1_proc_tx->frame_rx = frame_rx; L1_proc_tx->slot_tx = slot_tx; L1_proc_tx->frame_tx = frame_tx; L1_proc_tx->timestamp_tx = timestamp_tx; - - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_UE,1); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_UE,0); - // the thread can now be woken up AssertFatal(pthread_cond_signal(&L1_proc_tx->cond) == 0, "ERROR pthread_cond_signal for gNB L1 thread\n"); - AssertFatal((ret=pthread_mutex_unlock(&L1_proc_tx->mutex))==0,"mutex_unlock returns %d\n",ret); - return(0); } @@ -532,22 +510,23 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) { int i; struct timespec abstime; int time_ns = 50000; - AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RU))==0,"mutex_lock returns %d\n",ret); - for (i=0;inum_RU;i++) { + + for (i=0; inum_RU; i++) { if (ru == gNB->RU_list[i]) { if ((proc->RU_mask&(1< 0) - LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n", - gNB->Mod_id,proc->frame_rx,proc->slot_rx,ru->idx,gNB->num_RU,proc->RU_mask); + LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n", + gNB->Mod_id,proc->frame_rx,proc->slot_rx,ru->idx,gNB->num_RU,proc->RU_mask); + proc->RU_mask |= (1<RU_mask != (1<num_RU)-1) { // not all RUs have provided their information so return LOG_E(PHY,"Not all RUs have provided their info\n"); AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU))==0,"mutex_unlock returns %d\n",ret); return(0); - } - else { // all RUs have provided their information so continue on and wakeup gNB processing + } else { // all RUs have provided their information so continue on and wakeup gNB processing proc->RU_mask = 0; AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU))==0,"muex_unlock returns %d\n",ret); } @@ -565,17 +544,16 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) { AssertFatal((ret=pthread_mutex_timedlock(&L1_proc->mutex, &abstime)) == 0,"mutex_lock returns %d\n", ret); if (L1_proc->instance_cnt == 0) { // L1_thread is busy so abort the subframe - AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"muex_unlock return %d\n",ret); - LOG_W(PHY,"L1_thread isn't ready in %d.%d, aborting RX processing\n",ru_proc->frame_rx,ru_proc->tti_rx); - return(-1); + AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"muex_unlock return %d\n",ret); + LOG_W(PHY,"L1_thread isn't ready in %d.%d, aborting RX processing\n",ru_proc->frame_rx,ru_proc->tti_rx); + return(-1); } - + ++L1_proc->instance_cnt; - - // We have just received and processed the common part of a subframe, say n. - // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired + // We have just received and processed the common part of a subframe, say n. + // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired // transmitted timestamp of the next TX slot (first). - // The last (TS_rx mod samples_per_frame) was n*samples_per_tti, + // The last (TS_rx mod samples_per_frame) was n*samples_per_tti, // we want to generate subframe (n+sl_ahead), so TS_tx = TX_rx+sl_ahead*samples_per_tti, // and proc->slot_tx = proc->slot_rx+sl_ahead L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sl_ahead*fp->samples_per_slot); @@ -583,9 +561,7 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) { L1_proc->slot_rx = ru_proc->tti_rx; L1_proc->frame_tx = (L1_proc->slot_rx > (fp->slots_per_frame-1-sl_ahead)) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx; L1_proc->slot_tx = (L1_proc->slot_rx + sl_ahead)%fp->slots_per_frame; - LOG_D(PHY,"wakeupL1: passing parameter IC = %d, RX: %d.%d, TX: %d.%d to L1 sl_ahead = %d\n", L1_proc->instance_cnt, L1_proc->frame_rx, L1_proc->slot_rx, L1_proc->frame_tx, L1_proc->slot_tx, sl_ahead); - pthread_mutex_unlock( &L1_proc->mutex ); // the thread can now be woken up @@ -594,7 +570,7 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) { exit_fun( "ERROR pthread_cond_signal" ); return(-1); } - + return(0); } /* @@ -698,23 +674,20 @@ static void* gNB_thread_prach( void* param ) { extern void init_td_thread(PHY_VARS_gNB *); extern void init_te_thread(PHY_VARS_gNB *); -static void* process_stats_thread(void* param) { - - PHY_VARS_gNB *gNB = (PHY_VARS_gNB*)param; - +static void *process_stats_thread(void *param) { + PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param; reset_meas(&gNB->dlsch_encoding_stats); reset_meas(&gNB->dlsch_scrambling_stats); reset_meas(&gNB->dlsch_modulation_stats); - wait_sync("process_stats_thread"); - while(!oai_exit) - { + while(!oai_exit) { sleep(1); print_meas(&gNB->dlsch_encoding_stats, "pdsch_encoding", NULL, NULL); print_meas(&gNB->dlsch_scrambling_stats, "pdsch_scrambling", NULL, NULL); print_meas(&gNB->dlsch_modulation_stats, "pdsch_modulation", NULL, NULL); } + return(NULL); } @@ -767,6 +740,7 @@ void init_gNB_proc(int inst) { } if(opp_enabled == 1) threadCreate(&proc->L1_stats_thread, process_stats_thread,(void *)gNB, "time_meas", -1, OAI_PRIORITY_RT_LOW); + //pthread_create( &proc->pthread_prach, attr_prach, gNB_thread_prach, gNB ); char name[16]; @@ -904,7 +878,7 @@ void init_eNB_afterRU(void) { for (i=0; iRU_list[ru_id]->nb_rx; aa++,i++) { LOG_I(PHY,"Attaching RU %d antenna %d to gNB antenna %d\n",gNB->RU_list[ru_id]->idx,i,aa); - // gNB->prach_vars.rxsigF[0][aa] = gNB->RU_list[ru_id]->prach_rxsigF[i]; + // gNB->prach_vars.rxsigF[0][aa] = gNB->RU_list[ru_id]->prach_rxsigF[i]; gNB->common_vars.rxdataF[aa] = gNB->RU_list[ru_id]->common.rxdataF[i]; } } @@ -968,7 +942,6 @@ void init_gNB(int single_thread_flag,int wait_for_sync) { gNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list = gNB->harq_pdu_list; gNB->UL_INFO.cqi_ind.cqi_pdu_list = gNB->cqi_pdu_list; gNB->UL_INFO.cqi_ind.cqi_raw_pdu_list = gNB->cqi_raw_pdu_list; - gNB->prach_energy_counter = 0; } } diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 0003cf770d..05ae216d00 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -92,7 +92,7 @@ unsigned short config_frames[4] = {2,9,11,13}; static int DEFBANDS[] = {7}; static int DEFENBS[] = {0}; static int DEFBFW[] = {0x00007fff}; - + //static int DEFNRBANDS[] = {7}; //static int DEFGNBS[] = {0}; @@ -712,7 +712,7 @@ void rx_rf(RU_t *ru,int *frame,int *slot) { } -void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { +void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { RU_proc_t *proc = &ru->proc; NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; //nfapi_nr_config_request_t *cfg = &ru->gNB_list[0]->gNB_config; @@ -758,7 +758,7 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, slot ); - for (i=0; inb_tx; i++){ + for (i=0; inb_tx; i++) { txp[i] = (void *)&ru->common.txdata[i][(slot*fp->samples_per_slot)-sf_extension]; } @@ -870,7 +870,7 @@ static void *ru_thread_prach( void *param ) { 0,0 ); } - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 );*/ + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 );*/ if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break; } @@ -1097,16 +1097,16 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) { } } else if(N_RB == 106) { if (fp->threequarter_fs) { - cfg->sample_rate=46.08e6; - cfg->samples_per_frame = 460800; - cfg->tx_bw = 40e6; - cfg->rx_bw = 40e6; + cfg->sample_rate=46.08e6; + cfg->samples_per_frame = 460800; + cfg->tx_bw = 40e6; + cfg->rx_bw = 40e6; } else { - cfg->sample_rate=61.44e6; - cfg->samples_per_frame = 614400; - cfg->tx_bw = 40e6; - cfg->rx_bw = 40e6; + cfg->sample_rate=61.44e6; + cfg->samples_per_frame = 614400; + cfg->tx_bw = 40e6; + cfg->rx_bw = 40e6; } } else { AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu); @@ -1210,7 +1210,7 @@ static void *ru_stats_thread(void *param) { if (ru->feprx) print_meas(&ru->ofdm_demod_stats,"feprx",NULL,NULL); - if (ru->feptx_ofdm){ + if (ru->feptx_ofdm) { print_meas(&ru->precoding_stats,"feptx_prec",NULL,NULL); print_meas(&ru->txdataF_copy_stats,"txdataF_copy",NULL,NULL); print_meas(&ru->ofdm_mod_stats,"feptx_ofdm",NULL,NULL); @@ -1219,7 +1219,7 @@ static void *ru_stats_thread(void *param) { if (ru->fh_north_asynch_in) print_meas(&ru->rx_fhaul,"rx_fhaul",NULL,NULL); - print_meas(&ru->tx_fhaul,"tx_fhaul",NULL,NULL); + print_meas(&ru->tx_fhaul,"tx_fhaul",NULL,NULL); if (ru->fh_north_out) { print_meas(&ru->compression,"compression",NULL,NULL); print_meas(&ru->transport,"transport",NULL,NULL); @@ -1346,7 +1346,7 @@ static void *ru_thread_tx( void *param ) { if (L1_proc->instance_cnt_RUs == -1) { L1_proc->instance_cnt_RUs = 0; AssertFatal(pthread_cond_signal(&L1_proc->cond_RUs) == 0, - "ERROR pthread_cond_signal for gNB_L1_thread\n"); + "ERROR pthread_cond_signal for gNB_L1_thread\n"); } //else AssertFatal(1==0,"gNB TX thread is not ready\n"); ret = pthread_mutex_unlock(&L1_proc->mutex_RUs_tx); AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret); @@ -1371,7 +1371,7 @@ static void *ru_thread( void *param ) { int print_frame = 8; int i = 0; int aa; - + // set default return value // set default return value ru_thread_status = 0; // set default return value @@ -1499,9 +1499,9 @@ static void *ru_thread( void *param ) { LOG_D(PHY,"RU proc: frame_rx = %d, tti_rx = %d\n", proc->frame_rx, proc->tti_rx); LOG_D(PHY,"Copying rxdataF from RU to gNB\n"); - for (aa=0;aanb_rx;aa++) - memcpy((void*)RC.gNB[0][0]->common_vars.rxdataF[aa], - (void*)ru->common.rxdataF[aa], fp->symbols_per_slot*fp->ofdm_symbol_size*sizeof(int32_t)); + for (aa=0; aanb_rx; aa++) + memcpy((void *)RC.gNB[0][0]->common_vars.rxdataF[aa], + (void *)ru->common.rxdataF[aa], fp->symbols_per_slot*fp->ofdm_symbol_size*sizeof(int32_t)); // At this point, all information for subframe has been received on FH interface @@ -2260,7 +2260,7 @@ void RCconfig_RU(void) } } else { - RC.ru[j]->openair0_cfg.clock_source = unset; + RC.ru[j]->openair0_cfg.clock_source = unset; } if (strcmp(*(RUParamList.paramarray[j][RU_LOCAL_RF_IDX].strptr), "yes") == 0) { diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 6b72562033..60931f7674 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -176,6 +176,10 @@ uint32_t target_ul_mcs = 20; uint32_t timing_advance = 0; uint64_t num_missed_slots=0; // counter for the number of missed slots +int split73=0; +void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset) { + AssertFatal(false, "Must not be called in this context\n"); +} extern void reset_opp_meas(void); extern void print_opp_meas(void); @@ -721,13 +725,9 @@ int restart_L1L2(module_id_t gnb_id) { memcpy(&ru->nr_frame_parms, &RC.gNB[gnb_id][0]->frame_parms, sizeof(NR_DL_FRAME_PARMS)); set_function_spec_param(RC.ru[gnb_id]); LOG_I(GNB_APP, "attempting to create ITTI tasks\n"); - - if (itti_create_task (TASK_RRC_ENB, rrc_enb_task, NULL) < 0) { - LOG_E(RRC, "Create task for RRC eNB failed\n"); - return -1; - } else { - LOG_I(RRC, "Re-created task for RRC gNB successfully\n"); - } + // No more rrc thread, as many race conditions are hidden behind + rrc_enb_init(); + itti_mark_task_ready(TASK_RRC_ENB); if (itti_create_task (TASK_L2L1, l2l1_task, NULL) < 0) { LOG_E(PDCP, "Create task for L2L1 failed\n"); @@ -771,23 +771,23 @@ static void wait_nfapi_init(char *thread_name) { void init_pdcp(void) { //if (!NODE_IS_DU(RC.rrc[0]->node_type)) { - pdcp_layer_init(); - uint32_t pdcp_initmask = (IS_SOFTMODEM_NOS1) ? - (PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT; + pdcp_layer_init(); + uint32_t pdcp_initmask = (IS_SOFTMODEM_NOS1) ? + (PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT; - if (IS_SOFTMODEM_NOS1){ - printf("IS_SOFTMODEM_NOS1 option enabled \n"); - pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT ; - } + if (IS_SOFTMODEM_NOS1) { + printf("IS_SOFTMODEM_NOS1 option enabled \n"); + pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT ; + } - pdcp_module_init(pdcp_initmask); + pdcp_module_init(pdcp_initmask); - /*if (NODE_IS_CU(RC.rrc[0]->node_type)) { - pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t)proto_agent_send_rlc_data_req); - } else {*/ - pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req); - pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind); - //} + /*if (NODE_IS_CU(RC.rrc[0]->node_type)) { + pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t)proto_agent_send_rlc_data_req); + } else {*/ + pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req); + pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind); + //} /*} else { pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) proto_agent_send_pdcp_data_ind); }*/ @@ -841,7 +841,7 @@ int main( int argc, char **argv ) MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX); #endif -init_opt(); + init_opt(); #ifdef PDCP_USE_NETLINK @@ -857,7 +857,7 @@ init_opt(); LOG_I(HW, "Version: %s\n", PACKAGE_VERSION); if(IS_SOFTMODEM_NOS1) - init_pdcp(); + init_pdcp(); #if defined(ENABLE_ITTI) @@ -883,37 +883,37 @@ init_opt(); mlockall(MCL_CURRENT | MCL_FUTURE); pthread_cond_init(&sync_cond,NULL); pthread_mutex_init(&sync_mutex, NULL); -/*#ifdef XFORMS - int UE_id; + /*#ifdef XFORMS + int UE_id; - if (do_forms==1) { - fl_initialize (&argc, argv, NULL, 0, 0); - form_stats_l2 = create_form_stats_form(); - fl_show_form (form_stats_l2->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "l2 stats"); - form_stats = create_form_stats_form(); - fl_show_form (form_stats->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "stats"); + if (do_forms==1) { + fl_initialize (&argc, argv, NULL, 0, 0); + form_stats_l2 = create_form_stats_form(); + fl_show_form (form_stats_l2->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "l2 stats"); + form_stats = create_form_stats_form(); + fl_show_form (form_stats->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "stats"); - for(UE_id=0; UE_idphy_scope_gnb, FL_PLACE_HOTSPOT, FL_FULLBORDER, title); + for(UE_id=0; UE_idphy_scope_gnb, FL_PLACE_HOTSPOT, FL_FULLBORDER, title); - if (otg_enabled) { - fl_set_button(form_gnb[CC_id][UE_id]->button_0,1); - fl_set_object_label(form_gnb[CC_id][UE_id]->button_0,"DL Traffic ON"); - } else { - fl_set_button(form_gnb[CC_id][UE_id]->button_0,0); - fl_set_object_label(form_gnb[CC_id][UE_id]->button_0,"DL Traffic OFF"); - } - } // CC_id - } // UE_id + if (otg_enabled) { + fl_set_button(form_gnb[CC_id][UE_id]->button_0,1); + fl_set_object_label(form_gnb[CC_id][UE_id]->button_0,"DL Traffic ON"); + } else { + fl_set_button(form_gnb[CC_id][UE_id]->button_0,0); + fl_set_object_label(form_gnb[CC_id][UE_id]->button_0,"DL Traffic OFF"); + } + } // CC_id + } // UE_id - threadCreate(&forms_thread, scope_thread, NULL, "scope", -1, OAI_PRIORITY_RT_LOW); - printf("Scope thread created, ret=%d\n",ret); - } + threadCreate(&forms_thread, scope_thread, NULL, "scope", -1, OAI_PRIORITY_RT_LOW); + printf("Scope thread created, ret=%d\n",ret); + } -#endif*/ + #endif*/ usleep(10*1000); if (nfapi_mode) { @@ -1018,27 +1018,27 @@ init_opt(); printf("Terminating application - oai_exit=%d\n",oai_exit); #endif // stop threads -/*#ifdef XFORMS + /*#ifdef XFORMS - printf("waiting for XFORMS thread\n"); + printf("waiting for XFORMS thread\n"); - if (do_forms==1) { - pthread_join(forms_thread,&status); - fl_hide_form(form_stats->stats_form); - fl_free_form(form_stats->stats_form); + if (do_forms==1) { + pthread_join(forms_thread,&status); + fl_hide_form(form_stats->stats_form); + fl_free_form(form_stats->stats_form); - fl_hide_form(form_stats_l2->stats_form); - fl_free_form(form_stats_l2->stats_form); + fl_hide_form(form_stats_l2->stats_form); + fl_free_form(form_stats_l2->stats_form); - for(UE_id=0; UE_idphy_scope_gNB); - fl_free_form(form_enb[CC_id][UE_id]->phy_scope_gNB); - } - } - } + for(UE_id=0; UE_idphy_scope_gNB); + fl_free_form(form_enb[CC_id][UE_id]->phy_scope_gNB); + } + } + } -#endif*/ + #endif*/ printf("stopping MODEM threads\n"); // cleanup stop_gNB(NB_gNB_INST); diff --git a/executables/nr-ue.c b/executables/nr-ue.c index c6e3873f18..f390e40cb5 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -148,7 +148,7 @@ PHY_VARS_NR_UE *init_nr_ue_vars(NR_DL_FRAME_PARMS *frame_parms, ue->Mod_id = UE_id; ue->mac_enabled = 1; - + // initialize all signal buffers // initialize all signal buffers init_nr_ue_signal(ue,1,abstraction_flag); // intialize transport @@ -380,7 +380,7 @@ void processSlotRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) { scheduled_response.CC_id = 0; scheduled_response.frame = proc->frame_rx; scheduled_response.slot = proc->nr_tti_rx; - + //--------------------------Temporary configuration-----------------------------// //--------------------------Temporary configuration-----------------------------// n_rnti = 0x1234; nb_rb = 50; @@ -391,7 +391,7 @@ void processSlotRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) { mcs = 9; harq_pid = 0; rvidx = 0; - //------------------------------------------------------------------------------// + //------------------------------------------------------------------------------// scheduled_response.ul_config->sfn_slot = NR_UPLINK_SLOT; scheduled_response.ul_config->number_pdus = 1; @@ -416,18 +416,18 @@ void processSlotRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) { LOG_D(PHY,"phy_procedures_nrUE_RX: slot:%d, time %lu\n", proc->nr_tti_rx, (rdtsc()-a)/3500); //printf(">>> nr_ue_pdcch_procedures ended\n"); #endif - if(IS_SOFTMODEM_NOS1){ //&& proc->nr_tti_rx==1 - //Hardcoded rnti value - protocol_ctxt_t ctxt; - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, UE->Mod_id, ENB_FLAG_NO, - 0x1234, proc->frame_rx, - proc->nr_tti_rx, 0); - pdcp_run(&ctxt); - pdcp_fifo_flush_sdus(&ctxt); - } + if(IS_SOFTMODEM_NOS1) { //&& proc->nr_tti_rx==1 + //Hardcoded rnti value + protocol_ctxt_t ctxt; + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, UE->Mod_id, ENB_FLAG_NO, + 0x1234, proc->frame_rx, + proc->nr_tti_rx, 0); + pdcp_run(&ctxt); + pdcp_fifo_flush_sdus(&ctxt); + } } - + // no UL for now // no UL for now /* if (UE->mac_enabled==1) { @@ -465,7 +465,7 @@ void UE_processing(void *arg) { PHY_VARS_NR_UE *UE = rxtxD->UE; processSlotRX(UE, proc); uint8_t gNB_id = 0; - + // params for UL time alignment procedure // params for UL time alignment procedure NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &UE->ul_time_alignment[gNB_id]; uint8_t numerology = UE->frame_parms.numerology_index; @@ -475,24 +475,24 @@ void UE_processing(void *arg) { //printf(">>> mac ended\n"); // Prepare the future Tx data -/* -#ifndef NO_RAT_NR + /* + #ifndef NO_RAT_NR - if (slot_select_nr(&UE->frame_parms, proc->frame_tx, proc->nr_tti_tx) & NR_UPLINK_SLOT) -#else - if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) || - (UE->frame_parms.frame_type == FDD) ) -#endif -*/ + if (slot_select_nr(&UE->frame_parms, proc->frame_tx, proc->nr_tti_tx) & NR_UPLINK_SLOT) + #else + if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) || + (UE->frame_parms.frame_type == FDD) ) + #endif + */ /* UL time alignment // If the current tx frame and slot match the TA configuration in ul_time_alignment // then timing advance is processed and set to be applied in the next UL transmission */ if (UE->mac_enabled == 1) { - if (frame_tx == ul_time_alignment->ta_frame && slot_tx == ul_time_alignment->ta_slot){ + if (frame_tx == ul_time_alignment->ta_frame && slot_tx == ul_time_alignment->ta_slot) { LOG_D(PHY,"Applying timing advance -- frame %d -- slot %d\n", frame_tx, slot_tx); - + //if (nfapi_mode!=3){ //if (nfapi_mode!=3){ nr_process_timing_advance(UE->Mod_id, UE->CC_id, ul_time_alignment->ta_command, numerology, bwp_ul_NB_RB); ul_time_alignment->ta_frame = -1; @@ -501,7 +501,7 @@ void UE_processing(void *arg) { } } - if (proc->nr_tti_tx == NR_UPLINK_SLOT || UE->frame_parms.frame_type == FDD){ + if (proc->nr_tti_tx == NR_UPLINK_SLOT || UE->frame_parms.frame_type == FDD) { thread_id = PHY_vars_UE_g[UE->Mod_id][0]->current_thread_id[proc->nr_tti_tx]; @@ -566,7 +566,7 @@ void trashFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) { UE->frame_parms.samples_per_subframe, UE->frame_parms.nb_antennas_rx); if (IS_SOFTMODEM_RFSIM ) { - usleep(1000); // slow down, as would do actual rf to let cpu for the synchro thread + usleep(1000); // slow down, as would do actual rf to let cpu for the synchro thread } } @@ -579,24 +579,24 @@ void trashFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) { void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) { - LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode); - void *dummy_tx[UE->frame_parms.nb_antennas_tx]; + LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode); + void *dummy_tx[UE->frame_parms.nb_antennas_tx]; - for (int i=0; iframe_parms.nb_antennas_tx; i++) - dummy_tx[i]=malloc16_clear(UE->frame_parms.samples_per_subframe*4); + for (int i=0; iframe_parms.nb_antennas_tx; i++) + dummy_tx[i]=malloc16_clear(UE->frame_parms.samples_per_subframe*4); - for ( int size=UE->rx_offset ; size > 0 ; size -= UE->frame_parms.samples_per_subframe ) { - int unitTransfer=size>UE->frame_parms.samples_per_subframe ? UE->frame_parms.samples_per_subframe : size ; - AssertFatal(unitTransfer == - UE->rfdevice.trx_read_func(&UE->rfdevice, - timestamp, - (void **)UE->common_vars.rxdata, - unitTransfer, - UE->frame_parms.nb_antennas_rx),""); - } + for ( int size=UE->rx_offset ; size > 0 ; size -= UE->frame_parms.samples_per_subframe ) { + int unitTransfer=size>UE->frame_parms.samples_per_subframe ? UE->frame_parms.samples_per_subframe : size ; + AssertFatal(unitTransfer == + UE->rfdevice.trx_read_func(&UE->rfdevice, + timestamp, + (void **)UE->common_vars.rxdata, + unitTransfer, + UE->frame_parms.nb_antennas_rx),""); + } - for (int i=0; iframe_parms.nb_antennas_tx; i++) - free(dummy_tx[i]); + for (int i=0; iframe_parms.nb_antennas_tx; i++) + free(dummy_tx[i]); } @@ -727,7 +727,7 @@ void *UE_thread(void *arg) { #ifdef OAI_ADRV9371_ZC706 /*uint32_t total_gain_dB_prev = 0; if (total_gain_dB_prev != UE->rx_total_gain_dB) { - total_gain_dB_prev = UE->rx_total_gain_dB; + total_gain_dB_prev = UE->rx_total_gain_dB; openair0_cfg[0].rx_gain[0] = UE->rx_total_gain_dB; UE->rfdevice.trx_set_gains_func(&UE->rfdevice,&openair0_cfg[0]); }*/ @@ -763,29 +763,29 @@ void *UE_thread(void *arg) { readBlockSize, UE->frame_parms.nb_antennas_rx),""); -if (slot_nr == (20+NR_UPLINK_SLOT-DURATION_RX_TO_TX - 1)%20) - AssertFatal( writeBlockSize == - UE->rfdevice.trx_write_func(&UE->rfdevice, - timestamp+ - (DURATION_RX_TO_TX*UE->frame_parms.samples_per_slot) - - UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0 - - openair0_cfg[0].tx_sample_advance, - txp, - writeBlockSize, - UE->frame_parms.nb_antennas_tx, - 2),""); + if (slot_nr == (20+NR_UPLINK_SLOT-DURATION_RX_TO_TX - 1)%20) + AssertFatal( writeBlockSize == + UE->rfdevice.trx_write_func(&UE->rfdevice, + timestamp+ + (DURATION_RX_TO_TX*UE->frame_parms.samples_per_slot) - + UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0 - + openair0_cfg[0].tx_sample_advance, + txp, + writeBlockSize, + UE->frame_parms.nb_antennas_tx, + 2),""); -if (slot_nr == (20+NR_UPLINK_SLOT-DURATION_RX_TO_TX)%20) - AssertFatal( writeBlockSize == - UE->rfdevice.trx_write_func(&UE->rfdevice, - timestamp+ - (DURATION_RX_TO_TX*UE->frame_parms.samples_per_slot) - - UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0 - - openair0_cfg[0].tx_sample_advance, - txp, - writeBlockSize, - UE->frame_parms.nb_antennas_tx, - 3),""); + if (slot_nr == (20+NR_UPLINK_SLOT-DURATION_RX_TO_TX)%20) + AssertFatal( writeBlockSize == + UE->rfdevice.trx_write_func(&UE->rfdevice, + timestamp+ + (DURATION_RX_TO_TX*UE->frame_parms.samples_per_slot) - + UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0 - + openair0_cfg[0].tx_sample_advance, + txp, + writeBlockSize, + UE->frame_parms.nb_antennas_tx, + 3),""); if( slot_nr==(nb_slot_frame-1)) { // read in first symbol of next frame and adjust for timing drift diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 6bcbec3790..eb57d9a5de 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -214,7 +214,7 @@ int emulate_rf = 0; tpool_t *Tpool; #ifdef UE_DLSCH_PARALLELISATION -tpool_t *Tpool_dl; + tpool_t *Tpool_dl; #endif @@ -308,8 +308,8 @@ static void *scope_thread(void *arg) { while (!oai_exit) { phy_scope_nrUE(form_nrue[0], - PHY_vars_UE_g[0][0], - 0,0,1); + PHY_vars_UE_g[0][0], + 0,0,1); usleep(100*1000); } @@ -382,9 +382,9 @@ static void get_options(void) { int tddflag=0, nonbiotflag, vcdflag=0; char *loopfile=NULL; int dumpframe=0; - //uint32_t noS1; //uint32_t nokrnmod; + //uint32_t nokrnmod; paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC_UE ; config_process_cmdline( cmdline_params,sizeof(cmdline_params)/sizeof(paramdef_t),NULL); @@ -511,12 +511,12 @@ void init_openair0(void) { else { openair0_cfg[card].sample_rate=122.88e6; openair0_cfg[card].samples_per_frame = 1228800; - } + } } else { LOG_E(PHY,"Unsupported numerology!\n"); exit(-1); } - }else if(frame_parms[0]->N_RB_DL == 273) { + } else if(frame_parms[0]->N_RB_DL == 273) { if (numerology==1) { if (frame_parms[0]->threequarter_fs) { AssertFatal(0 == 1,"three quarter sampling not supported for N_RB 273\n"); @@ -524,12 +524,12 @@ void init_openair0(void) { else { openair0_cfg[card].sample_rate=122.88e6; openair0_cfg[card].samples_per_frame = 1228800; - } + } } else { LOG_E(PHY,"Unsupported numerology!\n"); exit(-1); } - }else if(frame_parms[0]->N_RB_DL == 106) { + } else if(frame_parms[0]->N_RB_DL == 106) { if (numerology==0) { if (frame_parms[0]->threequarter_fs) { openair0_cfg[card].sample_rate=23.04e6; @@ -538,15 +538,15 @@ void init_openair0(void) { openair0_cfg[card].sample_rate=30.72e6; openair0_cfg[card].samples_per_frame = 307200; } - } else if (numerology==1) { + } else if (numerology==1) { if (frame_parms[0]->threequarter_fs) { - openair0_cfg[card].sample_rate=46.08e6; - openair0_cfg[card].samples_per_frame = 460800; + openair0_cfg[card].sample_rate=46.08e6; + openair0_cfg[card].samples_per_frame = 460800; } else { - openair0_cfg[card].sample_rate=61.44e6; - openair0_cfg[card].samples_per_frame = 614400; - } + openair0_cfg[card].sample_rate=61.44e6; + openair0_cfg[card].samples_per_frame = 614400; + } } else if (numerology==2) { openair0_cfg[card].sample_rate=122.88e6; openair0_cfg[card].samples_per_frame = 1228800; @@ -621,7 +621,7 @@ void init_pdcp(void) { pdcp_initmask = pdcp_initmask | UE_NAS_USE_TUN_BIT; /*if (rlc_module_init() != 0) { - LOG_I(RLC, "Problem at RLC initiation \n"); + LOG_I(RLC, "Problem at RLC initiation \n"); } pdcp_layer_init(); nr_ip_over_LTE_DRB_preconfiguration();*/ @@ -633,7 +633,7 @@ void init_pdcp(void) { // Stupid function addition because UE itti messages queues definition is common with eNB void *rrc_enb_process_itti_msg(void *notUsed) { - return NULL; + return NULL; } @@ -663,12 +663,12 @@ int main( int argc, char **argv ) { set_taus_seed (0); tpool_t pool; Tpool = &pool; - char params[]="-1,-1"; + char params[]="-1,-1"; initTpool(params, Tpool, false); #ifdef UE_DLSCH_PARALLELISATION tpool_t pool_dl; Tpool_dl = &pool_dl; - char params_dl[]="-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1"; + char params_dl[]="-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1"; initTpool(params_dl, Tpool_dl, false); #endif cpuf=get_cpu_freq_GHz(); @@ -676,21 +676,21 @@ int main( int argc, char **argv ) { init_opt() ; if(IS_SOFTMODEM_NOS1) - init_pdcp(); + init_pdcp(); if (ouput_vcd) { vcd_signal_dumper_init("/tmp/openair_dump_nrUE.vcd"); } -/* -#ifdef PDCP_USE_NETLINK - netlink_init(); -#if defined(PDCP_USE_NETLINK_QUEUES) - pdcp_netlink_init(); -#endif -#endif -*/ - #ifndef PACKAGE_VERSION + /* + #ifdef PDCP_USE_NETLINK + netlink_init(); + #if defined(PDCP_USE_NETLINK_QUEUES) + pdcp_netlink_init(); + #endif + #endif + */ +#ifndef PACKAGE_VERSION # define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL" #endif LOG_I(HW, "Version: %s\n", PACKAGE_VERSION); diff --git a/executables/softmodem-common.c b/executables/softmodem-common.c index 78d0d01ef9..de5009eccc 100644 --- a/executables/softmodem-common.c +++ b/executables/softmodem-common.c @@ -125,27 +125,27 @@ void get_common_options(void) { } void softmodem_printresources(int sig, telnet_printfunc_t pf) { - struct rusage usage; - struct timespec stop; + struct rusage usage; + struct timespec stop; - clock_gettime(CLOCK_BOOTTIME, &stop); + clock_gettime(CLOCK_BOOTTIME, &stop); - uint64_t elapse = (stop.tv_sec - start.tv_sec) ; // in seconds + uint64_t elapse = (stop.tv_sec - start.tv_sec) ; // in seconds - int st = getrusage(RUSAGE_SELF,&usage); - if (!st) { - pf("\nRun time: %lluh %llus\n",(unsigned long long)elapse/3600,(unsigned long long)(elapse - (elapse/3600))); - pf("\tTime executing user inst.: %lds %ldus\n",(long)usage.ru_utime.tv_sec,(long)usage.ru_utime.tv_usec); - pf("\tTime executing system inst.: %lds %ldus\n",(long)usage.ru_stime.tv_sec,(long)usage.ru_stime.tv_usec); - pf("\tMax. Phy. memory usage: %ldkB\n",(long)usage.ru_maxrss); - pf("\tPage fault number (no io): %ld\n",(long)usage.ru_minflt); - pf("\tPage fault number (requiring io): %ld\n",(long)usage.ru_majflt); - pf("\tNumber of file system read: %ld\n",(long)usage.ru_inblock); - pf("\tNumber of filesystem write: %ld\n",(long)usage.ru_oublock); - pf("\tNumber of context switch (process origin, io...): %ld\n",(long)usage.ru_nvcsw); - pf("\tNumber of context switch (os origin, priority...): %ld\n",(long)usage.ru_nivcsw); - } + int st = getrusage(RUSAGE_SELF,&usage); + if (!st) { + pf("\nRun time: %lluh %llus\n",(unsigned long long)elapse/3600,(unsigned long long)(elapse - (elapse/3600))); + pf("\tTime executing user inst.: %lds %ldus\n",(long)usage.ru_utime.tv_sec,(long)usage.ru_utime.tv_usec); + pf("\tTime executing system inst.: %lds %ldus\n",(long)usage.ru_stime.tv_sec,(long)usage.ru_stime.tv_usec); + pf("\tMax. Phy. memory usage: %ldkB\n",(long)usage.ru_maxrss); + pf("\tPage fault number (no io): %ld\n",(long)usage.ru_minflt); + pf("\tPage fault number (requiring io): %ld\n",(long)usage.ru_majflt); + pf("\tNumber of file system read: %ld\n",(long)usage.ru_inblock); + pf("\tNumber of filesystem write: %ld\n",(long)usage.ru_oublock); + pf("\tNumber of context switch (process origin, io...): %ld\n",(long)usage.ru_nvcsw); + pf("\tNumber of context switch (os origin, priority...): %ld\n",(long)usage.ru_nivcsw); + } } void signal_handler(int sig) { @@ -160,9 +160,9 @@ void signal_handler(int sig) { backtrace_symbols_fd(array, size, 2); exit(-1); } else { - if(sig==SIGINT ||sig==SOFTMODEM_RTSIGNAL) - softmodem_printresources(sig,(telnet_printfunc_t)printf); - if (sig != SOFTMODEM_RTSIGNAL) { + if(sig==SIGINT ||sig==SOFTMODEM_RTSIGNAL) + softmodem_printresources(sig,(telnet_printfunc_t)printf); + if (sig != SOFTMODEM_RTSIGNAL) { printf("Linux signal %s...\n",strsignal(sig)); exit_function(__FILE__, __FUNCTION__, __LINE__,"softmodem starting exit procedure\n"); } @@ -172,7 +172,7 @@ void signal_handler(int sig) { void set_softmodem_sighandler(void) { - struct sigaction act,oldact; + struct sigaction act,oldact; clock_gettime(CLOCK_BOOTTIME, &start); memset(&act,0,sizeof(act)); act.sa_handler=signal_handler; @@ -181,5 +181,5 @@ void set_softmodem_sighandler(void) { signal(SIGSEGV, signal_handler); signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); - signal(SIGABRT, signal_handler); + signal(SIGABRT, signal_handler); } diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index 8fedb74949..a356ec50a4 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -37,6 +37,11 @@ extern "C" #endif /* help strings definition for command line options, used in CMDLINE_XXX_DESC macros and printed when -h option is used */ #define CONFIG_HLP_RFCFGF "Configuration file for front-end (e.g. LMS7002M)\n" +#define CONFIG_HLP_SPLIT73 "Split 7.3 (below rate matching) option: ::" +#define CONFIG_HLP_TPOOL "Thread pool configuration: \n\ + default no pool (runs in calling thread),\n\ + list of cores, comma separated (negative value is no core affinity)\n\ + example: -1,3 launches two working threads one floating, the second set on core 3" #define CONFIG_HLP_ULMAXE "set the eNodeB max ULSCH erros\n" #define CONFIG_HLP_CALUER "set UE RX calibration\n" #define CONFIG_HLP_CALUERM "" @@ -87,6 +92,7 @@ extern "C" /* optname helpstr paramflags XXXptr defXXXval type numelt */ /*-----------------------------------------------------------------------------------------------------------------------------------------------------*/ #define RF_CONFIG_FILE softmodem_params.rf_config_file +#define SPLIT73 softmodem_params.split73 #define TP_CONFIG softmodem_params.threadPoolConfig #define PHY_TEST softmodem_params.phy_test #define WAIT_FOR_SYNC softmodem_params.wait_for_sync @@ -103,6 +109,8 @@ extern "C" #define CMDLINE_PARAMS_DESC { \ {"rf-config-file", CONFIG_HLP_RFCFGF, 0, strptr:(char **)&RF_CONFIG_FILE, defstrval:NULL, TYPE_STRING, sizeof(RF_CONFIG_FILE)},\ + {"split73", CONFIG_HLP_SPLIT73, 0, strptr:(char **)&SPLIT73, defstrval:NULL, TYPE_STRING, sizeof(SPLIT73)},\ + {"thread-pool", CONFIG_HLP_TPOOL, 0, strptr:(char **)&TP_CONFIG, defstrval:"n", TYPE_STRING, sizeof(TP_CONFIG)}, \ {"phy-test", CONFIG_HLP_PHYTST, PARAMFLAG_BOOL, iptr:&PHY_TEST, defintval:0, TYPE_INT, 0}, \ {"usim-test", CONFIG_HLP_USIM, PARAMFLAG_BOOL, u8ptr:&USIM_TEST, defintval:0, TYPE_UINT8, 0}, \ {"clock", CONFIG_HLP_CLK, 0, uptr:&CLOCK_SOURCE, defintval:0, TYPE_UINT, 0}, \ @@ -179,6 +187,7 @@ typedef struct { uint64_t optmask; THREAD_STRUCT thread_struct; char rf_config_file[1024]; + char split73[1024]; char threadPoolConfig[1024]; int phy_test; uint8_t usim_test; diff --git a/executables/split_headers.h b/executables/split_headers.h index 3e8fe23b14..54b9930250 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -5,10 +5,11 @@ #include #include -#define CU_IP "127.0.0.1" #define CU_PORT "7878" -#define DU_IP "127.0.0.1" #define DU_PORT "8787" +#define SPLIT73_CU 1 +#define SPLIT73_DU 2 +extern int split73; #define MTU 65536 #define UDP_TIMEOUT 900000L // in micro second (struct timeval, NOT struct timespec) diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c index 75d572c2fc..15eb5206a1 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c @@ -310,7 +310,7 @@ static void TPencode(void * arg) { lte_rate_matching_turbo(hadlsch->RTC[rdata->r], rdata->G, //G hadlsch->w[rdata->r], - hadlsch->e+rdata->r_offset, + hadlsch->eDL+rdata->r_offset, hadlsch->C, // C rdata->dlsch->Nsoft, // Nsoft, rdata->dlsch->Mdlharq, @@ -389,7 +389,7 @@ int dlsch_encoding(PHY_VARS_eNB *eNB, for (int r=0, r_offset=0; rC; r++) { union turboReqUnion id= {.s={dlsch->rnti,frame,subframe,r,0}}; - notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(turboEncode_t), id.p, &proc->respEncode, TPencode); + notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(turboEncode_t), id.p, proc->respEncode, TPencode); turboEncode_t * rdata=(turboEncode_t *) NotifiedFifoData(req); rdata->input=hadlsch->c[r]; rdata->Kr_bytes= ( rCminus ? hadlsch->Kminus : hadlsch->Kplus) >>3; @@ -404,8 +404,8 @@ int dlsch_encoding(PHY_VARS_eNB *eNB, rdata->r_offset=r_offset; rdata->G=G; - if ( proc->threadPool.activated) { - pushTpool(&proc->threadPool,req); + if ( proc->threadPool->activated ) { + pushTpool(proc->threadPool,req); proc->nbEncode++; } else { TPencode(rdata); diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c index 04a49d062a..475c8bd521 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation.c @@ -158,7 +158,7 @@ int allocate_REs_in_RB_no_pilots_QPSK_siso(PHY_VARS_eNB* phy_vars_eNB, { LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->frame_parms; - uint8_t *x0 = dlsch0_harq->e; + uint8_t *x0 = dlsch0_harq->eDL; uint32_t qpsk_table_offset_re = 0; uint32_t qpsk_table_offset_im = 0; @@ -248,7 +248,7 @@ int allocate_REs_in_RB_pilots_QPSK_siso(PHY_VARS_eNB* phy_vars_eNB, LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_eNB->frame_parms; - uint8_t *x0 = dlsch0_harq->e; + uint8_t *x0 = dlsch0_harq->eDL; uint32_t qpsk_table_offset_re = 0; uint32_t qpsk_table_offset_im = 0; @@ -343,7 +343,7 @@ int allocate_REs_in_RB_no_pilots_16QAM_siso(PHY_VARS_eNB* phy_vars_eNB, { LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->frame_parms; - uint8_t *x0 = dlsch0_harq->e; + uint8_t *x0 = dlsch0_harq->eDL; uint32_t qam16_table_offset_re = 0; uint32_t qam16_table_offset_im = 0; @@ -439,7 +439,7 @@ int allocate_REs_in_RB_pilots_16QAM_siso(PHY_VARS_eNB* phy_vars_eNB, LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_eNB->frame_parms; - uint8_t *x0 = dlsch0_harq->e; + uint8_t *x0 = dlsch0_harq->eDL; uint32_t qam16_table_offset_re = 0; uint32_t qam16_table_offset_im = 0; @@ -542,7 +542,7 @@ int allocate_REs_in_RB_no_pilots_64QAM_siso(PHY_VARS_eNB* phy_vars_eNB, LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->frame_parms; - uint8_t *x0 = dlsch0_harq->e; + uint8_t *x0 = dlsch0_harq->eDL; uint32_t qam64_table_offset_re = 0; uint32_t qam64_table_offset_im = 0; @@ -699,7 +699,7 @@ int allocate_REs_in_RB_pilots_64QAM_siso(PHY_VARS_eNB* phy_vars_eNB, LTE_DL_FRAME_PARMS *frame_parms=&phy_vars_eNB->frame_parms; - uint8_t *x0 = dlsch0_harq->e; + uint8_t *x0 = dlsch0_harq->eDL; uint32_t qam64_table_offset_re = 0; uint32_t qam64_table_offset_im = 0; @@ -866,12 +866,12 @@ int allocate_REs_in_RB(PHY_VARS_eNB* phy_vars_eNB, if ((dlsch0_harq != NULL) && (dlsch1_harq != NULL)) { //this is for TM3, TM4 - x0 = dlsch0_harq->e; + x0 = dlsch0_harq->eDL; mimo_mode = dlsch0_harq->mimo_mode; first_layer0 = dlsch0_harq->first_layer; Nlayers0 = dlsch0_harq->Nlayers; mod_order0 = dlsch0_harq->Qm; - x1 = dlsch1_harq->e; + x1 = dlsch1_harq->eDL; // Fill these in later for TM8-10 // Nlayers1 = dlsch1_harq->Nlayers; // first_layer1 = dlsch1_harq->first_layer; @@ -879,7 +879,7 @@ int allocate_REs_in_RB(PHY_VARS_eNB* phy_vars_eNB, } else if ((dlsch0_harq != NULL) && (dlsch1_harq == NULL)){ //This is for SIS0 TM1, TM6, etc - x0 = dlsch0_harq->e; + x0 = dlsch0_harq->eDL; mimo_mode = dlsch0_harq->mimo_mode; first_layer0 = dlsch0_harq->first_layer; Nlayers0 = dlsch0_harq->Nlayers; @@ -887,7 +887,7 @@ int allocate_REs_in_RB(PHY_VARS_eNB* phy_vars_eNB, } else if ((dlsch0_harq == NULL) && (dlsch1_harq != NULL)){ // This is for TM4 retransmission - x0 = dlsch1_harq->e; + x0 = dlsch1_harq->eDL; mimo_mode = dlsch1_harq->mimo_mode; first_layer0 = dlsch1_harq->first_layer; Nlayers0 = dlsch1_harq->Nlayers; @@ -2692,7 +2692,7 @@ int dlsch_modulation_SIC(int32_t **sic_buffer, LTE_DL_eNB_HARQ_t *dlsch0_harq = dlsch0->harq_processes[harq_pid]; uint32_t i,jj,re_allocated=0; uint8_t mod_order0 = dlsch0_harq->Qm; - uint8_t *x0 = dlsch0_harq->e; + uint8_t *x0 = dlsch0_harq->eDL; uint8_t qam64_table_offset_re = 0; uint8_t qam64_table_offset_im = 0; uint8_t qam16_table_offset_re = 0; @@ -2883,7 +2883,7 @@ int mch_modulation(int32_t **txdataF, &jj, re_offset, symbol_offset, - dlsch->harq_processes[0]->e, + dlsch->harq_processes[0]->eDL, l, mod_order, amp, diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c b/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c index 2e8ddde848..d48164e07d 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling.c @@ -52,7 +52,7 @@ void dlsch_scrambling(LTE_DL_FRAME_PARMS *frame_parms, int n; // uint8_t reset; uint32_t x1, x2, s=0; - uint8_t *dlsch_e=dlsch->harq_processes[harq_pid]->e; + uint8_t *dlsch_e=dlsch->harq_processes[harq_pid]->eDL; uint8_t *e=dlsch_e; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_SCRAMBLING, VCD_FUNCTION_IN); // Rule for accumulation of subframes for BL/CE UEs diff --git a/openair1/PHY/LTE_TRANSPORT/transport_eNB.h b/openair1/PHY/LTE_TRANSPORT/transport_eNB.h index 7dd4e46da4..5e446db5fd 100644 --- a/openair1/PHY/LTE_TRANSPORT/transport_eNB.h +++ b/openair1/PHY/LTE_TRANSPORT/transport_eNB.h @@ -100,7 +100,7 @@ typedef struct { /// start symbold of pdsch uint8_t pdsch_start; /// Concatenated "e"-sequences (for definition see 36-212 V8.6 2009-03, p.17-18) - uint8_t e[MAX_NUM_CHANNEL_BITS] __attribute__((aligned(32))); + uint8_t eDL[MAX_NUM_CHANNEL_BITS] __attribute__((aligned(32))); /// Turbo-code outputs (36-212 V8.6 2009-03, p.12 uint8_t *d[MAX_NUM_DLSCH_SEGMENTS];//[(96+3+(3*6144))]; /// Sub-block interleaver outputs (36-212 V8.6 2009-03, p.16-17) @@ -261,11 +261,11 @@ typedef struct { /// coded RI bits int16_t q_RI[MAX_RI_PAYLOAD]; /// Concatenated "e"-sequences (for definition see 36-212 V8.6 2009-03, p.17-18) - int16_t e[MAX_NUM_CHANNEL_BITS] __attribute__((aligned(32))); + int16_t eUL[MAX_NUM_CHANNEL_BITS] __attribute__((aligned(32))); /// Temporary h sequence to flag PUSCH_x/PUSCH_y symbols which are not scrambled uint8_t h[MAX_NUM_CHANNEL_BITS]; /// Pointer to the payload - uint8_t *b; + uint8_t *decodedBytes; /// Pointers to transport block segments //TBD uint8_t *c[MAX_NUM_ULSCH_SEGMENTS]; diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index 581f50494f..36a3cd9a5c 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -54,9 +54,9 @@ void free_eNB_ulsch(LTE_eNB_ULSCH_t *ulsch) { if (ulsch) { for (i=0; i<8; i++) { if (ulsch->harq_processes[i]) { - if (ulsch->harq_processes[i]->b) { - free16(ulsch->harq_processes[i]->b,MAX_ULSCH_PAYLOAD_BYTES); - ulsch->harq_processes[i]->b = NULL; + if (ulsch->harq_processes[i]->decodedBytes) { + free16(ulsch->harq_processes[i]->decodedBytes,MAX_ULSCH_PAYLOAD_BYTES); + ulsch->harq_processes[i]->decodedBytes = NULL; } for (r=0; rharq_processes[i]) { memset(ulsch->harq_processes[i],0,sizeof(LTE_UL_eNB_HARQ_t)); - ulsch->harq_processes[i]->b = (uint8_t *)malloc16(MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); + ulsch->harq_processes[i]->decodedBytes = (uint8_t *)malloc16(MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); - if (ulsch->harq_processes[i]->b) - memset(ulsch->harq_processes[i]->b,0,MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); + if (ulsch->harq_processes[i]->decodedBytes) + memset(ulsch->harq_processes[i]->decodedBytes,0,MAX_ULSCH_PAYLOAD_BYTES/bw_scaling); else exit_flag=3; @@ -229,7 +229,7 @@ void processULSegment(void * arg) { G, ulsch_harq->w[r], (uint8_t *) &dummy_w[0], - ulsch_harq->e+rdata->r_offset, + ulsch_harq->eUL+rdata->r_offset, ulsch_harq->C, NSOFT, 0, //Uplink @@ -327,19 +327,15 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, E = ulsch_harq->Qm * (Gp/ulsch_harq->C); else E = ulsch_harq->Qm * ((GpmodC==0?0:1) + (Gp/ulsch_harq->C)); -#ifdef FS6 - if ( getenv("fs6") != NULL && strncasecmp( getenv("fs6"), "du", 2) == 0 ) { - - sendFs6Ul(eNB, UE_id, harq_pid, r, ulsch_harq->e+r_offset, E*sizeof(int16_t), r_offset); - + + if ( split73 == SPLIT73_DU ) { + sendFs6Ul(eNB, UE_id, harq_pid, r, ulsch_harq->eUL+r_offset, E*sizeof(int16_t), r_offset); r_offset += E; continue; } -#endif - union turboReqUnion id= {.s={ulsch->rnti,proc->frame_rx,proc->subframe_rx,0,0}}; - notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(turboDecode_t), id.p, &proc->respDecode, processULSegment); + notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(turboDecode_t), id.p, proc->respDecode, processULSegment); turboDecode_t * rdata=(turboDecode_t *) NotifiedFifoData(req); rdata->eNB=eNB; @@ -359,7 +355,7 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, rdata->function=td; int Fbytes=(r==0) ? rdata->Fbits>>3 : 0; int sz=Kr_bytes - Fbytes - ((ulsch_harq->C>1)?3:0); - pushTpool(&proc->threadPool,req); + pushTpool(proc->threadPool,req); proc->nbDecode++; LOG_D(PHY,"Added a block to decode, in pipe: %d\n",proc->nbDecode); r_offset+=E; @@ -892,8 +888,8 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, j2+=2; } - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; } break; @@ -905,10 +901,10 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, j2+=4; } - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; } break; @@ -920,12 +916,12 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, j2+=6; } - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; - ulsch_harq->e[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; + ulsch_harq->eUL[iprime++] = y[j2++]; } break; @@ -963,7 +959,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, */ int16_t *yp,*ep; - for (iprime=0,yp=&y[j2],ep=&ulsch_harq->e[0]; + for (iprime=0,yp=&y[j2],ep=&ulsch_harq->eUL[0]; iprimeharq_processes[harq_pid]->RTC[r], G, //G dlsch->harq_processes[harq_pid]->w[r], - dlsch->harq_processes[harq_pid]->e+r_offset, + dlsch->harq_processes[harq_pid]->eDL+r_offset, dlsch->harq_processes[harq_pid]->C, // C dlsch->Nsoft, // Nsoft, dlsch->Mdlharq, diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index 0fabf8c639..e59c651713 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -2032,7 +2032,7 @@ uint16_t nr_dci_format_size (PHY_VARS_NR_UE *ue, ul_res_alloc_type_1 = 1; } - uint8_t n_bits_freq_dom_res_assign_ul=0,n_ul_RGB_tmp; + uint8_t n_bits_freq_dom_res_assign_ul=0,n_ul_RGB_tmp=0; if (ul_res_alloc_type_0 == 1) { // implementation of Table 6.1.2.2.1-1 TC 38.214 subclause 6.1.2.2.1 // config1: PUSCH-Config IE contains rbg-Size ENUMERATED {config1 config2} diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 6e34a71e0c..1ada594725 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -320,10 +320,10 @@ bool dlsch_procedures(PHY_VARS_eNB *eNB, &eNB->dlsch_interleaving_stats); stop_meas(&eNB->dlsch_encoding_stats); - if ( proc->threadPool.activated ) { + if ( proc->threadPool->activated ) { // Wait all other threads finish to process while (proc->nbEncode) { - delNotifiedFIFO_elt(pullTpool(&proc->respEncode, &proc->threadPool)); + delNotifiedFIFO_elt(pullTpool(proc->respEncode, proc->threadPool)); proc->nbEncode--; } } @@ -604,12 +604,11 @@ void srs_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { } void fill_sr_indication(int UEid, PHY_VARS_eNB *eNB,uint16_t rnti,int frame,int subframe,uint32_t stat) { - #ifdef FS6 - if ( getenv("fs6") != NULL && strncasecmp( getenv("fs6"), "du", 2) == 0 ) { + if ( split73 == SPLIT73_DU ) { sendFs6Ulharq(fs6ULindicationSr, UEid, eNB, NULL, frame, subframe, NULL,0,0, rnti, stat); return; } - #endif + pthread_mutex_lock(&eNB->UL_INFO_mutex); nfapi_sr_indication_t *sr_ind = &eNB->UL_INFO.sr_ind; nfapi_sr_indication_body_t *sr_ind_body = &sr_ind->sr_indication_body; @@ -1175,13 +1174,13 @@ void postDecode(L1_rxtx_proc_t *proc, notifiedFIFO_elt_t *req) { if (decodeSucess) { int Fbytes=(rdata->segment_r==0) ? rdata->Fbits>>3 : 0; int sz=(rdata->Kr>>3) - Fbytes - ((ulsch_harq->C>1)?3:0); - memcpy(ulsch_harq->b+rdata->offset, + memcpy(ulsch_harq->decodedBytes+rdata->offset, rdata->decoded_bytes+Fbytes, sz); } else { if ( rdata->nbSegments != ulsch_harq->processedSegments ) { - int nb=abortTpool(&proc->threadPool, req->key); - nb+=abortNotifiedFIFO(&proc->respDecode, req->key); + int nb=abortTpool(proc->threadPool, req->key); + nb+=abortNotifiedFIFO(proc->respDecode, req->key); proc->nbDecode-=nb; LOG_I(PHY,"uplink segment error %d/%d, aborted %d segments\n",rdata->segment_r,rdata->nbSegments, nb); AssertFatal(ulsch_harq->processedSegments+nb == rdata->nbSegments,"processed: %d, aborted: %d, total %d\n", @@ -1329,7 +1328,7 @@ void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { } // for (i=0; inbDecode > 0) { - notifiedFIFO_elt_t *req=pullTpool(&proc->respDecode, &proc->threadPool); + notifiedFIFO_elt_t *req=pullTpool(proc->respDecode, proc->threadPool); postDecode(proc, req); delNotifiedFIFO_elt(req); } @@ -1415,7 +1414,7 @@ void fill_rx_indication(PHY_VARS_eNB *eNB, pdu->rx_indication_rel8.tl.tag = NFAPI_RX_INDICATION_REL8_TAG; pdu->rx_indication_rel8.length = eNB->ulsch[UE_id]->harq_processes[harq_pid]->TBS>>3; pdu->rx_indication_rel8.offset = 1; // DJP - I dont understand - but broken unless 1 ???? 0; // filled in at the end of the UL_INFO formation - pdu->data = eNB->ulsch[UE_id]->harq_processes[harq_pid]->b; + pdu->data = eNB->ulsch[UE_id]->harq_processes[harq_pid]->decodedBytes; // estimate timing advance for MAC sync_pos = lte_est_timing_advance_pusch(eNB,UE_id); timing_advance_update = sync_pos; // - eNB->frame_parms.nb_prefix_samples/4; //to check @@ -1749,12 +1748,10 @@ void fill_ulsch_harq_indication (PHY_VARS_eNB *eNB, LTE_UL_eNB_HARQ_t *ulsch_har } void fill_uci_harq_indication (int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask) { - #ifdef FS6 - if ( getenv("fs6") != NULL && strncasecmp( getenv("fs6"), "du", 2) == 0 ) { + if ( split73 == SPLIT73_DU ) { sendFs6Ulharq(fs6ULindicationHarq, UEid, eNB, uci, frame, subframe, harq_ack, tdd_mapping_mode, tdd_multiplexing_mask, 0, 0); return; } - #endif int UE_id=find_dlsch(uci->rnti,eNB,SEARCH_EXIST); diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index d8ac505d14..6a12831e2d 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -1266,9 +1266,12 @@ int main(int argc, char **argv) { } L1_rxtx_proc_t *proc_eNB = &eNB->proc.L1_proc; - initTpool("n", &proc_eNB->threadPool, true); - initNotifiedFIFO(&proc_eNB->respEncode); - initNotifiedFIFO(&proc_eNB->respDecode); + proc_eNB->threadPool=(tpool_t*)malloc(sizeof(tpool_t)); + proc_eNB->respEncode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + proc_eNB->respDecode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + initTpool("n", proc_eNB->threadPool, true); + initNotifiedFIFO(proc_eNB->respEncode); + initNotifiedFIFO(proc_eNB->respDecode); proc_eNB->frame_tx=0; diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c index 34237771aa..6c04d6edf7 100644 --- a/openair1/SIMULATION/LTE_PHY/ulsim.c +++ b/openair1/SIMULATION/LTE_PHY/ulsim.c @@ -793,9 +793,12 @@ int main(int argc, char **argv) { proc_rxtx_ue->frame_rx = (subframe<4)?(proc_rxtx->frame_tx-1):(proc_rxtx->frame_tx); proc_rxtx_ue->subframe_tx = proc_rxtx->subframe_rx; proc_rxtx_ue->subframe_rx = (proc_rxtx->subframe_tx+6)%10; - initTpool("n", &proc_rxtx->threadPool, true); - initNotifiedFIFO(&proc_rxtx->respEncode); - initNotifiedFIFO(&proc_rxtx->respDecode); + proc_rxtx->threadPool=(tpool_t*)malloc(sizeof(tpool_t)); + proc_rxtx->respEncode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + proc_rxtx->respDecode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + initTpool("n",proc_rxtx->threadPool, true); + initNotifiedFIFO(proc_rxtx->respEncode); + initNotifiedFIFO(proc_rxtx->respDecode); printf("Init UL hopping UE\n"); init_ul_hopping(&UE->frame_parms); diff --git a/openair2/PHY_INTERFACE/IF_Module.h b/openair2/PHY_INTERFACE/IF_Module.h index 5bcbc2420d..42a4459732 100644 --- a/openair2/PHY_INTERFACE/IF_Module.h +++ b/openair2/PHY_INTERFACE/IF_Module.h @@ -176,11 +176,11 @@ typedef struct { pthread_cond_t cond_RUs; /// mutex for RXn-TXnp4 processing thread pthread_mutex_t mutex_RUs; - tpool_t threadPool; + tpool_t *threadPool; int nbEncode; int nbDecode; - notifiedFIFO_t respEncode; - notifiedFIFO_t respDecode; + notifiedFIFO_t *respEncode; + notifiedFIFO_t *respDecode; pthread_mutex_t mutex_emulateRF; int instance_cnt_emulateRF; pthread_t pthread_emulateRF; diff --git a/targets/ARCH/rfsimulator/simulator.c b/targets/ARCH/rfsimulator/simulator.c index 94f8f2e938..01a78213ca 100644 --- a/targets/ARCH/rfsimulator/simulator.c +++ b/targets/ARCH/rfsimulator/simulator.c @@ -346,7 +346,7 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t, openair0_timestamp if ( t->lastWroteTS != 0 && abs((double)t->lastWroteTS-timestamp) > (double)CirSize) LOG_E(HW,"Discontinuous TX gap too large Tx:%lu, %lu\n", t->lastWroteTS, timestamp); - if (t->lastWroteTS >= timestamp+1) + if (t->lastWroteTS > timestamp+nsamps) LOG_E(HW,"Not supported to send Tx out of order (same in USRP) %lu, %lu\n", t->lastWroteTS, timestamp); t->lastWroteTS=timestamp+nsamps; @@ -468,8 +468,8 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi } else if ( b->lastReceivedTS == b->th.timestamp ) { // normal case } else { - abort(); - AssertFatal(false, "received data in past: current is %lu, new reception: %lu!\n", b->lastReceivedTS, b->th.timestamp); + LOG_E(HW, "received data in past: current is %lu, new reception: %lu!\n", b->lastReceivedTS, b->th.timestamp); + b->trashingPacket=true; } pthread_mutex_lock(&Sockmutex); diff --git a/targets/COMMON/create_tasks.c b/targets/COMMON/create_tasks.c index 1f2e8fa8f1..10691d2db8 100644 --- a/targets/COMMON/create_tasks.c +++ b/targets/COMMON/create_tasks.c @@ -41,6 +41,7 @@ # include "f1ap_du_task.h" # include "enb_app.h" # include "openair2/LAYER2/MAC/mac_proto.h" +#include extern RAN_CONTEXT_t RC; @@ -50,25 +51,21 @@ int create_tasks(uint32_t enb_nb) { int rc; if (enb_nb == 0) return 0; - bool fs6Du=false; - if ( getenv("fs6") != NULL && strncasecmp( getenv("fs6"), "du", 2) == 0 ) - fs6Du=true; LOG_I(ENB_APP, "Creating ENB_APP eNB Task\n"); rc = itti_create_task (TASK_ENB_APP, eNB_app_task, NULL); AssertFatal(rc >= 0, "Create task for eNB APP failed\n"); - LOG_I(RRC,"Creating RRC eNB Task\n"); - rc = itti_create_task (TASK_RRC_ENB, rrc_enb_task, NULL); - AssertFatal(rc >= 0, "Create task for RRC eNB failed\n"); + // No more rrc thread, as many race conditions are hidden behind + rrc_enb_init(); + itti_mark_task_ready(TASK_RRC_ENB); - if (EPC_MODE_ENABLED && !fs6Du ) { + if (EPC_MODE_ENABLED && ! ( split73==SPLIT73_DU ) ) { rc = itti_create_task(TASK_SCTP, sctp_eNB_task, NULL); AssertFatal(rc >= 0, "Create task for SCTP failed\n"); } - - if (EPC_MODE_ENABLED && !NODE_IS_DU(type) && !fs6Du ) { + if (EPC_MODE_ENABLED && !NODE_IS_DU(type) && ! ( split73==SPLIT73_DU ) ) { rc = itti_create_task(TASK_S1AP, s1ap_eNB_task, NULL); AssertFatal(rc >= 0, "Create task for S1AP failed\n"); if (!(get_softmodem_params()->emulate_rf)){ diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 8e85ae11c6..67f9c62256 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -93,6 +93,7 @@ unsigned short config_frames[4] = {2,9,11,13}; #include "lte-softmodem.h" #include "NB_IoT_interface.h" +#include pthread_cond_t nfapi_sync_cond; @@ -152,6 +153,13 @@ int otg_enabled; uint64_t num_missed_slots=0; // counter for the number of missed slots +int split73=0; +void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset) { + AssertFatal(false, "Must not be called in this context\n"); +} +void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, uint16_t rnti, int32_t stat) { + AssertFatal(false, "Must not be called in this context\n"); +} extern void reset_opp_meas(void); extern void print_opp_meas(void); @@ -438,12 +446,9 @@ int restart_L1L2(module_id_t enb_id) { init_UE_list(&RC.mac[enb_id]->UE_list); LOG_I(ENB_APP, "attempting to create ITTI tasks\n"); - if (itti_create_task (TASK_RRC_ENB, rrc_enb_task, NULL) < 0) { - LOG_E(RRC, "Create task for RRC eNB failed\n"); - return -1; - } else { - LOG_I(RRC, "Re-created task for RRC eNB successfully\n"); - } + // No more rrc thread, as many race conditions are hidden behind + rrc_enb_init(); + itti_mark_task_ready(TASK_RRC_ENB); /* pass a reconfiguration request which will configure everything down to * RC.eNB[i][j]->frame_parms, too */ @@ -477,8 +482,7 @@ void init_pdcp(void) { pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_W_MBMS_BIT; - if ( getenv("fs6") != NULL && strncasecmp( getenv("fs6"), "du", 2) == 0 ) - pdcp_module_init(pdcp_initmask); + pdcp_module_init(pdcp_initmask); if (NODE_IS_CU(RC.rrc[0]->node_type)) { pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t)proto_agent_send_rlc_data_req); @@ -643,12 +647,15 @@ int main ( int argc, char **argv ) for (int x=0; x < RC.nb_L1_inst; x++) for (int CC_id=0; CC_idproc.L1_proc; + L1proc->threadPool=(tpool_t*)malloc(sizeof(tpool_t)); + L1proc->respEncode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); + L1proc->respDecode=(notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t)); if ( strlen(get_softmodem_params()->threadPoolConfig) > 0 ) - initTpool(get_softmodem_params()->threadPoolConfig, &L1proc->threadPool, true); + initTpool(get_softmodem_params()->threadPoolConfig, L1proc->threadPool, true); else - initTpool("n", &L1proc->threadPool, true); - initNotifiedFIFO(&L1proc->respEncode); - initNotifiedFIFO(&L1proc->respDecode); + initTpool("n", L1proc->threadPool, true); + initNotifiedFIFO(L1proc->respEncode); + initNotifiedFIFO(L1proc->respDecode); } From 7ad4efb37a22f469efdd5216fc3ae1c311e8690d Mon Sep 17 00:00:00 2001 From: laurent Date: Mon, 2 Mar 2020 17:39:44 +0100 Subject: [PATCH 088/240] fix warnings, reduce formating differences with develop branch --- executables/main-fs6.c | 4 + executables/main-ocp.c | 7 +- executables/nr-gnb.c | 57 +++++++++--- executables/split_headers.h | 4 + executables/transport_split.c | 4 + nfapi/oai_integration/nfapi_vnf.c | 2 +- .../PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c | 4 + .../lte_dl_bf_channel_estimation.c | 92 +++++++++---------- openair1/PHY/LTE_TRANSPORT/if5_tools.c | 2 +- openair1/PHY/LTE_TRANSPORT/phich.c | 2 +- .../PHY/LTE_TRANSPORT/ulsch_demodulation.c | 1 - openair1/SCHED/phy_procedures_lte_eNb.c | 3 +- openair1/SCHED/prach_procedures.c | 9 ++ openair1/SCHED/sched_eNB.h | 2 + openair1/SCHED_UE/phy_procedures_lte_ue.c | 2 +- .../LAYER2/MAC/eNB_scheduler_primitives.c | 7 +- openair2/RRC/LTE/rrc_eNB.c | 3 + targets/RT/USER/lte-softmodem.h | 1 + 18 files changed, 127 insertions(+), 79 deletions(-) diff --git a/executables/main-fs6.c b/executables/main-fs6.c index c20777a5d6..0a5988c802 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -1,3 +1,7 @@ +/* + Author: Laurent THOMAS, Open Cells Project company, funded by IRT SystemX + copyleft: OpenAirInterface Software Alliance and it's licence +*/ #include #include #include diff --git a/executables/main-ocp.c b/executables/main-ocp.c index 50cd1f2714..0635df2bef 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -1,9 +1,6 @@ /* - * Author: Laurent Thomas - * Copyright: Open Cells Project company - */ - -/* + Author: Laurent THOMAS, Open Cells Project company, funded by IRT SystemX + copyleft: OpenAirInterface Software Alliance and it's licence * This file replaces * targets/RT/USER/lte-softmodem.c * targets/RT/USER/rt_wrapper.c diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 43407de19b..3a5916c577 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -327,15 +327,16 @@ static void *gNB_L1_thread( void *param ) { while (!oai_exit) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 0 ); - if (wait_on_condition(&L1_proc->mutex,&L1_proc->cond,&L1_proc->instance_cnt,thread_name)<0) break; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0, 1 ); + int frame_rx = L1_proc->frame_rx; int slot_rx = L1_proc->slot_rx; int frame_tx = L1_proc->frame_tx; int slot_tx = L1_proc->slot_tx; uint64_t timestamp_tx = L1_proc->timestamp_tx; + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_TX0_GNB,slot_tx); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_RX0_GNB,slot_rx); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_GNB,frame_tx); @@ -407,15 +408,17 @@ void gNB_top(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, char *string, struct } int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot_tx,uint64_t timestamp_tx) { + RU_t *ru; RU_proc_t *ru_proc; + int waitret = 0, ret = 0, time_ns = 1000*1000; struct timespec now, abstime; // note this should depend on the numerology used by the TX L1 thread, set here for 500us slot time + // note this should depend on the numerology used by the TX L1 thread, set here for 500us slot time VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,1); time_ns = time_ns/gNB->frame_parms.slots_per_subframe; AssertFatal((ret = pthread_mutex_lock(&proc->mutex_RUs_tx))==0,"mutex_lock returns %d\n",ret); - while (proc->instance_cnt_RUs < 0) { clock_gettime(CLOCK_REALTIME, &now); abstime.tv_sec = now.tv_sec; @@ -425,10 +428,8 @@ int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot abstime.tv_nsec -= 1000*1000*1000; abstime.tv_sec += 1; } - if((waitret = pthread_cond_timedwait(&proc->cond_RUs,&proc->mutex_RUs_tx,&abstime)) == 0) break; // this unlocks mutex_rxtx while waiting and then locks it again } - proc->instance_cnt_RUs = -1; VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs); AssertFatal((ret = pthread_mutex_unlock(&proc->mutex_RUs_tx))==0,"mutex_unlock returns %d\n",ret); @@ -436,6 +437,7 @@ int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot if (waitret == ETIMEDOUT) { LOG_W(PHY,"Dropping TX slot (%d.%d) because FH is blocked more than 1 slot times (500us)\n",frame_tx,slot_tx); + AssertFatal((ret=pthread_mutex_lock(&gNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret); gNB->proc.RU_mask_tx = 0; AssertFatal((ret=pthread_mutex_unlock(&gNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret); @@ -443,61 +445,81 @@ int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot proc->instance_cnt_RUs = 0; VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs); AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RUs_tx))==0,"mutex_unlock returns %d\n",ret); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,1); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,0); + return(-1); } - for(int i=0; inum_RU; i++) { + for(int i=0; inum_RU; i++) + { ru = gNB->RU_list[i]; ru_proc = &ru->proc; + if (ru_proc->instance_cnt_gNBs == 0) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST_UE, 1); LOG_E(PHY,"Frame %d, subframe %d: TX FH thread busy, dropping Frame %d, subframe %d\n", ru_proc->frame_tx, ru_proc->tti_tx, proc->frame_rx, proc->slot_rx); AssertFatal((ret=pthread_mutex_lock(&gNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret); gNB->proc.RU_mask_tx = 0; AssertFatal((ret=pthread_mutex_unlock(&gNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST_UE, 0); return(-1); } - AssertFatal((ret = pthread_mutex_lock(&ru_proc->mutex_gNBs))==0,"ERROR pthread_mutex_lock failed on mutex_gNBs L1_thread_tx with ret=%d\n",ret); + ru_proc->instance_cnt_gNBs = 0; ru_proc->timestamp_tx = timestamp_tx; ru_proc->tti_tx = slot_tx; ru_proc->frame_tx = frame_tx; + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_UE, ru_proc->instance_cnt_gNBs); + LOG_D(PHY,"Signaling tx_thread_fh for %d.%d\n",frame_tx,slot_tx); // the thread can now be woken up AssertFatal(pthread_cond_signal(&ru_proc->cond_gNBs) == 0, "[gNB] ERROR pthread_cond_signal for gNB TXnp4 thread\n"); AssertFatal((ret=pthread_mutex_unlock(&ru_proc->mutex_gNBs))==0,"mutex_unlock returned %d\n",ret); - } + } return(0); } int wakeup_tx(PHY_VARS_gNB *gNB,int frame_rx,int slot_rx,int frame_tx,int slot_tx,uint64_t timestamp_tx) { + + gNB_L1_rxtx_proc_t *L1_proc_tx = &gNB->proc.L1_proc_tx; + int ret; + + AssertFatal((ret = pthread_mutex_lock(&L1_proc_tx->mutex))==0,"mutex_lock returns %d\n",ret); + while(L1_proc_tx->instance_cnt == 0) { pthread_cond_wait(&L1_proc_tx->cond,&L1_proc_tx->mutex); } L1_proc_tx->instance_cnt = 0; + + L1_proc_tx->slot_rx = slot_rx; L1_proc_tx->frame_rx = frame_rx; L1_proc_tx->slot_tx = slot_tx; L1_proc_tx->frame_tx = frame_tx; L1_proc_tx->timestamp_tx = timestamp_tx; + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_UE,1); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_UE,0); // the thread can now be woken up + // the thread can now be woken up AssertFatal(pthread_cond_signal(&L1_proc_tx->cond) == 0, "ERROR pthread_cond_signal for gNB L1 thread\n"); + AssertFatal((ret=pthread_mutex_unlock(&L1_proc_tx->mutex))==0,"mutex_unlock returns %d\n",ret); + return(0); } @@ -510,23 +532,22 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) { int i; struct timespec abstime; int time_ns = 50000; + AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RU))==0,"mutex_lock returns %d\n",ret); - for (i=0; inum_RU; i++) { if (ru == gNB->RU_list[i]) { if ((proc->RU_mask&(1< 0) LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n", gNB->Mod_id,proc->frame_rx,proc->slot_rx,ru->idx,gNB->num_RU,proc->RU_mask); - proc->RU_mask |= (1<RU_mask != (1<num_RU)-1) { // not all RUs have provided their information so return LOG_E(PHY,"Not all RUs have provided their info\n"); AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU))==0,"mutex_unlock returns %d\n",ret); return(0); - } else { // all RUs have provided their information so continue on and wakeup gNB processing + } + else { // all RUs have provided their information so continue on and wakeup gNB processing proc->RU_mask = 0; AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU))==0,"muex_unlock returns %d\n",ret); } @@ -556,12 +577,15 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) { // The last (TS_rx mod samples_per_frame) was n*samples_per_tti, // we want to generate subframe (n+sl_ahead), so TS_tx = TX_rx+sl_ahead*samples_per_tti, // and proc->slot_tx = proc->slot_rx+sl_ahead + // and proc->slot_tx = proc->slot_rx+sl_ahead L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sl_ahead*fp->samples_per_slot); L1_proc->frame_rx = ru_proc->frame_rx; L1_proc->slot_rx = ru_proc->tti_rx; L1_proc->frame_tx = (L1_proc->slot_rx > (fp->slots_per_frame-1-sl_ahead)) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx; L1_proc->slot_tx = (L1_proc->slot_rx + sl_ahead)%fp->slots_per_frame; + LOG_D(PHY,"wakeupL1: passing parameter IC = %d, RX: %d.%d, TX: %d.%d to L1 sl_ahead = %d\n", L1_proc->instance_cnt, L1_proc->frame_rx, L1_proc->slot_rx, L1_proc->frame_tx, L1_proc->slot_tx, sl_ahead); + pthread_mutex_unlock( &L1_proc->mutex ); // the thread can now be woken up @@ -675,19 +699,22 @@ extern void init_td_thread(PHY_VARS_gNB *); extern void init_te_thread(PHY_VARS_gNB *); static void *process_stats_thread(void *param) { + PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param; + reset_meas(&gNB->dlsch_encoding_stats); reset_meas(&gNB->dlsch_scrambling_stats); reset_meas(&gNB->dlsch_modulation_stats); + wait_sync("process_stats_thread"); - while(!oai_exit) { + while(!oai_exit) + { sleep(1); print_meas(&gNB->dlsch_encoding_stats, "pdsch_encoding", NULL, NULL); print_meas(&gNB->dlsch_scrambling_stats, "pdsch_scrambling", NULL, NULL); print_meas(&gNB->dlsch_modulation_stats, "pdsch_modulation", NULL, NULL); } - return(NULL); } @@ -740,7 +767,6 @@ void init_gNB_proc(int inst) { } if(opp_enabled == 1) threadCreate(&proc->L1_stats_thread, process_stats_thread,(void *)gNB, "time_meas", -1, OAI_PRIORITY_RT_LOW); - //pthread_create( &proc->pthread_prach, attr_prach, gNB_thread_prach, gNB ); char name[16]; @@ -942,6 +968,7 @@ void init_gNB(int single_thread_flag,int wait_for_sync) { gNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list = gNB->harq_pdu_list; gNB->UL_INFO.cqi_ind.cqi_pdu_list = gNB->cqi_pdu_list; gNB->UL_INFO.cqi_ind.cqi_raw_pdu_list = gNB->cqi_raw_pdu_list; + gNB->prach_energy_counter = 0; } } diff --git a/executables/split_headers.h b/executables/split_headers.h index 54b9930250..62293c7369 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -1,3 +1,7 @@ +/* + Author: Laurent THOMAS, Open Cells Project company, funded by IRT SystemX + copyleft: OpenAirInterface Software Alliance and it's licence +*/ #ifndef __SPLIT_HEADERS_H #define __SPLIT_HEADERS_H diff --git a/executables/transport_split.c b/executables/transport_split.c index 1ed95db7a0..7a1ee3e85e 100644 --- a/executables/transport_split.c +++ b/executables/transport_split.c @@ -1,3 +1,7 @@ +/* + Author: Laurent THOMAS, Open Cells Project company, funded by IRT SystemX + copyleft: OpenAirInterface Software Alliance and it's licence +*/ #include #include /* See NOTES */ #include diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index c1f69574fd..a0574221f5 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -398,7 +398,7 @@ int phy_sync_indication(struct nfapi_vnf_p7_config *config, uint8_t sync) { return(0); } -int phy_subframe_indication(L1_rxtx_proc_t * proc, struct nfapi_vnf_p7_config *config, uint16_t phy_id, uint16_t sfn_sf) { +int phy_subframe_indication(struct nfapi_vnf_p7_config *config, uint16_t phy_id, uint16_t sfn_sf) { static uint8_t first_time = 1; if (first_time) { diff --git a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c index 294169b75d..04fe19ecbc 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c @@ -148,5 +148,9 @@ int lte_est_timing_advance_pusch(PHY_VARS_eNB *eNB, if (max_pos>frame_parms->ofdm_symbol_size/2) max_pos = max_pos-frame_parms->ofdm_symbol_size; + //#ifdef DEBUG_PHY + LOG_D(PHY,"frame %d: max_pos = %d, sync_pos=%d\n",eNB->proc.frame_rx,max_pos,sync_pos); + //#endif //DEBUG_PHY + return max_pos - sync_pos; } diff --git a/openair1/PHY/LTE_ESTIMATION/lte_dl_bf_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_dl_bf_channel_estimation.c index 43c0350efb..2331e253d5 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_dl_bf_channel_estimation.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_dl_bf_channel_estimation.c @@ -43,7 +43,7 @@ int lte_dl_bf_channel_estimation(PHY_VARS_UE *phy_vars_ue, uint8_t pilot0,pilot1,pilot2,pilot3; short ch[2], *pil, *rxF, *dl_bf_ch, *dl_bf_ch_prev; - short *fl, *fm, *fr, *fl_dc, *fm_dc, *fr_dc, *f1, *f2l, *f2r; + short *fl=NULL, *fm=NULL, *fr=NULL, *fl_dc=NULL, *fm_dc=NULL, *fr_dc=NULL, *f1, *f2l=NULL, *f2r=NULL; unsigned int *rballoc; int **rxdataF; @@ -58,10 +58,10 @@ int lte_dl_bf_channel_estimation(PHY_VARS_UE *phy_vars_ue, dlsch0_harq = dlsch_ue[0]->harq_processes[harq_pid]; if (((frame_parms->Ncp == NORMAL) && (symbol>=7)) || - ((frame_parms->Ncp == EXTENDED) && (symbol>=6))) - rballoc = dlsch0_harq->rb_alloc_odd; + ((frame_parms->Ncp == EXTENDED) && (symbol>=6))) + rballoc = dlsch0_harq->rb_alloc_odd; else - rballoc = dlsch0_harq->rb_alloc_even; + rballoc = dlsch0_harq->rb_alloc_even; rxdataF = phy_vars_ue->common_vars.common_vars_rx_data_per_thread[phy_vars_ue->current_thread_id[Ns>>1]].rxdataF; @@ -69,56 +69,56 @@ int lte_dl_bf_channel_estimation(PHY_VARS_UE *phy_vars_ue, beamforming_mode = phy_vars_ue->transmission_mode[eNB_id]>6 ? phy_vars_ue->transmission_mode[eNB_id] : 0; if (phy_vars_ue->high_speed_flag == 0) // use second channel estimate position for temporary storage - ch_offset = frame_parms->ofdm_symbol_size; + ch_offset = frame_parms->ofdm_symbol_size; else - ch_offset = frame_parms->ofdm_symbol_size*symbol; + ch_offset = frame_parms->ofdm_symbol_size*symbol; + - uespec_nushift = frame_parms->Nid_cell%3; subframe = Ns>>1; - - //generate ue specific pilots - lprime = symbol/3-1; - lte_dl_ue_spec_rx(phy_vars_ue,uespec_pilot,Ns,5,lprime,0,dlsch0_harq->nb_rb); - //LOG_M("uespec_pilot_rx.m","uespec_pilot",uespec_pilot,300,1,1); - if (frame_parms->Ncp==0){ - if (symbol==3 || symbol==6 || symbol==9 || symbol==12) - uespec_pilots = 1; - } else{ - if (symbol==4 || symbol==7 || symbol==10) - uespec_pilots = 1; - } - - if ((frame_parms->Ncp==0 && (symbol==6 ||symbol ==12)) || (frame_parms->Ncp==1 && symbol==7)) - uespec_poffset = 2; + //generate ue specific pilots + lprime = symbol/3-1; + lte_dl_ue_spec_rx(phy_vars_ue,uespec_pilot,Ns,5,lprime,0,dlsch0_harq->nb_rb); + //LOG_M("uespec_pilot_rx.m","uespec_pilot",uespec_pilot,300,1,1); - if (phy_vars_ue->frame_parms.Ncp == 0) { // normal prefix - pilot0 = 3; - pilot1 = 6; - pilot2 = 9; - pilot3 = 12; - } else { // extended prefix - pilot0 = 4; - pilot1 = 7; - pilot2 = 10; - } + if (frame_parms->Ncp==0){ + if (symbol==3 || symbol==6 || symbol==9 || symbol==12) + uespec_pilots = 1; + } else{ + if (symbol==4 || symbol==7 || symbol==10) + uespec_pilots = 1; + } - //define the filter - pil_offset = (uespec_nushift+uespec_poffset)%3; - // printf("symbol=%d,pil_offset=%d\n",symbol,pil_offset); - switch (pil_offset) { - case 0: - fl = filt16_l0; - fm = filt16_m0; - fr = filt16_r0; - fl_dc = filt16_l0; - fm_dc = filt16_m0; - fr_dc = filt16_r0; - f1 = filt16_1; - f2l = filt16_2l0; - f2r = filt16_2r0; + if ((frame_parms->Ncp==0 && (symbol==6 ||symbol ==12)) || (frame_parms->Ncp==1 && symbol==7)) + uespec_poffset = 2; + + if (phy_vars_ue->frame_parms.Ncp == 0) { // normal prefix + pilot0 = 3; + pilot1 = 6; + pilot2 = 9; + pilot3 = 12; + } else { // extended prefix + pilot0 = 4; + pilot1 = 7; + pilot2 = 10; + } + + //define the filter + pil_offset = (uespec_nushift+uespec_poffset)%3; + // printf("symbol=%d,pil_offset=%d\n",symbol,pil_offset); + switch (pil_offset) { + case 0: + fl = filt16_l0; + fm = filt16_m0; + fr = filt16_r0; + fl_dc = filt16_l0; + fm_dc = filt16_m0; + fr_dc = filt16_r0; + f1 = filt16_1; + f2l = filt16_2l0; + f2r = filt16_2r0; break; case 1: diff --git a/openair1/PHY/LTE_TRANSPORT/if5_tools.c b/openair1/PHY/LTE_TRANSPORT/if5_tools.c index 0e383fa04f..1e0dd9db1b 100644 --- a/openair1/PHY/LTE_TRANSPORT/if5_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if5_tools.c @@ -1504,7 +1504,7 @@ void recv_IF5(RU_t *ru, openair0_timestamp *proc_timestamp, int subframe, uint16 rxp[0] = (void*)&ru->common.rxdata[0][subframe*ru->frame_parms->samples_per_tti]; rxp128 = (__m128i *) (rxp[0]); - RU_proc_t *proc = NULL; //&ru->eNB_list[0]->proc.L1_proc; + RU_proc_t *proc = &ru->proc; /* // while(packet_idsamples_per_tti/db_fulllength) { data_block = data_block_head; diff --git a/openair1/PHY/LTE_TRANSPORT/phich.c b/openair1/PHY/LTE_TRANSPORT/phich.c index ab2fe2d743..6d8b58818b 100644 --- a/openair1/PHY/LTE_TRANSPORT/phich.c +++ b/openair1/PHY/LTE_TRANSPORT/phich.c @@ -714,7 +714,7 @@ void generate_phich_top(PHY_VARS_eNB *eNB, int32_t **txdataF = eNB->common_vars.txdataF; uint8_t Ngroup_PHICH,ngroup_PHICH,nseq_PHICH; uint8_t NSF_PHICH = 4; - uint8_t pusch_subframe; + uint8_t pusch_subframe=-1; uint8_t i; int subframe = proc->subframe_tx; phich_config_t *phich; diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c index 9351cf0adc..1b0d7feaf5 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c @@ -1199,7 +1199,6 @@ void dump_ulsch(PHY_VARS_eNB *eNB,int frame,int subframe,uint8_t UE_id,int round eNB->ulsch[UE_id]->harq_processes[harq_pid]->Nsymb_pusch); sprintf(fname,"/tmp/ulsch_r%d_d",round); sprintf(vname,"/tmp/ulsch_r%d_dseq",round); - LOG_UM(fname,vname,&eNB->ulsch[UE_id]->harq_processes[harq_pid]->d[0][96], eNB->ulsch[UE_id]->harq_processes[harq_pid]->Kplus*3,1,0); diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 1ada594725..daa9039236 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -175,7 +175,7 @@ void common_signal_procedures (PHY_VARS_eNB *eNB,int frame, int subframe) { LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; int **txdataF = eNB->common_vars.txdataF; uint8_t *pbch_pdu=&eNB->pbch_pdu[0]; - LOG_D(PHY,"common_signal_procedures: frame %d, subframe %d fdd:%s dir:%s\n",frame,subframe,fp->frame_type == FDD?"FDD":"TDD", subframe_select(fp,subframe) == SF_DL?"DL":"UL?"); + //LOG_D(PHY,"common_signal_procedures: frame %d, subframe %d fdd:%s dir:%s\n",frame,subframe,fp->frame_type == FDD?"FDD":"TDD", subframe_select(fp,subframe) == SF_DL?"DL":"UL?"); // generate Cell-Specific Reference Signals for both slots VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,1); @@ -291,7 +291,6 @@ bool dlsch_procedures(PHY_VARS_eNB *eNB, if (dlsch->rnti!=0xffff) LOG_D(PHY,"Generating DLSCH/PDSCH pdu:%p pdsch_start:%d frame:%d subframe:%d nb_rb:%d rb_alloc:%d Qm:%d Nl:%d round:%d\n", - dlsch_harq->pdu,dlsch_harq->pdsch_start,frame,subframe,dlsch_harq->nb_rb,dlsch_harq->rb_alloc[0], dlsch_harq->Qm,dlsch_harq->Nl,dlsch_harq->round); diff --git a/openair1/SCHED/prach_procedures.c b/openair1/SCHED/prach_procedures.c index 4f2d05ef50..f1e7589a66 100644 --- a/openair1/SCHED/prach_procedures.c +++ b/openair1/SCHED/prach_procedures.c @@ -108,6 +108,15 @@ void prach_procedures(PHY_VARS_eNB *eNB, eNB->prach_energy_counter, eNB->measurements.prach_I0+eNB->prach_DTX_threshold, eNB->measurements.prach_I0); + if (max_preamble_energy[0] > 100 && br_flag==0) + LOG_W(PHY,"[RAPROC] Frame %d, subframe %d : BR %d Most likely preamble %d, energy %d dB delay %d (prach_energy counter %d), threshold %d, I0 %d\n", + frame,subframe,br_flag, + max_preamble[0], + max_preamble_energy[0]/10, + max_preamble_delay[0], + eNB->prach_energy_counter, + eNB->measurements.prach_I0+eNB->prach_DTX_threshold, + eNB->measurements.prach_I0); if (br_flag==1) { int prach_mask; diff --git a/openair1/SCHED/sched_eNB.h b/openair1/SCHED/sched_eNB.h index da0106226e..f04bec2e5c 100644 --- a/openair1/SCHED/sched_eNB.h +++ b/openair1/SCHED/sched_eNB.h @@ -127,9 +127,11 @@ void phy_procedures_eNB_S_RX(PHY_VARS_eNB *phy_vars_eNB,L1_rxtx_proc_t *proc); @param phy_vars_eNB Pointer to eNB variables on which to act @param br_flag indicator for eMTC PRACH */ + void prach_procedures(PHY_VARS_eNB *eNB, int br_flag); + /*! \brief Function to compute timing of Msg3 transmission on UL-SCH (first UE transmission in RA procedure). This implements the timing in paragraph a) from Section 6.1.1 in 36.213 (p. 17 in version 8.6). Used by eNB upon transmission of random-access response (RA_RNTI) to program corresponding ULSCH reception procedure. Used by UE upon reception of random-access response (RA_RNTI) to program corresponding ULSCH transmission procedure. This does not support the UL_delay field in RAR (always assumed to be 0). @param frame_parms Pointer to DL frame parameter descriptor @param current_subframe Index of subframe where RA_RNTI was received diff --git a/openair1/SCHED_UE/phy_procedures_lte_ue.c b/openair1/SCHED_UE/phy_procedures_lte_ue.c index c64a8ef177..8ca533c146 100644 --- a/openair1/SCHED_UE/phy_procedures_lte_ue.c +++ b/openair1/SCHED_UE/phy_procedures_lte_ue.c @@ -3467,7 +3467,7 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue, frame_rx%1024, subframe_rx,(ue->dlsch_decoding_stats[ue->current_thread_id[subframe_rx]].p_time)/(cpuf*1000.0)); } - LOG_D(PHY," ------ end turbo decoder for AbsSubframe %d.%d ------ iter %d \n", frame_rx, subframe_rx,ret1); + LOG_D(PHY," ------ end turbo decoder for AbsSubframe %d.%d ------ \n", frame_rx, subframe_rx); // Check CRC for CW 0 if (ret == (1+dlsch0->max_turbo_iterations)) { diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index 4aef7ce771..5189e76975 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -4982,12 +4982,7 @@ cqi_indication(module_id_t mod_idP, UE_id, ul_cqi_information->channel, ul_cqi_information->ul_cqi); -/* - int sum=0; - for (int i=0; i length; i++) - sum+=pdu[i]; - LOG_D(MAC, "pdu for channel: %d, checksum: %d\n", ul_cqi_information->channel, sum); -*/ + if (ul_cqi_information->channel == 0) { // PUCCH // extract pucch csi information before changing RI information extract_pucch_csi(mod_idP, diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index b77ac07729..baf4d82465 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -8604,6 +8604,8 @@ void *rrc_enb_process_itti_msg(void *notUsed) { return NULL; } +// as there are race conditions, no rrc thread +#if 0 //----------------------------------------------------------------------------- void * rrc_enb_task( @@ -8620,6 +8622,7 @@ rrc_enb_task( //} return NULL; } +#endif /*------------------------------------------------------------------------------*/ void diff --git a/targets/RT/USER/lte-softmodem.h b/targets/RT/USER/lte-softmodem.h index b67a54e4a0..7b896b2817 100644 --- a/targets/RT/USER/lte-softmodem.h +++ b/targets/RT/USER/lte-softmodem.h @@ -135,6 +135,7 @@ #define DEFAULT_DLF 2680000000 + uint64_t get_pdcp_optmask(void); extern pthread_cond_t sync_cond; extern pthread_mutex_t sync_mutex; From 44167f0119ac175d4ae3c4409cdd93cad8d573c3 Mon Sep 17 00:00:00 2001 From: laurent Date: Mon, 2 Mar 2020 19:15:44 +0100 Subject: [PATCH 089/240] Fix phy simulators --- openair1/SIMULATION/LTE_PHY/dlsim.c | 16 ++++++++++++---- openair1/SIMULATION/LTE_PHY/ulsim.c | 9 +++++++++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index 6a12831e2d..f65e1f9633 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -59,6 +59,7 @@ #include "unitary_defs.h" #include "dummy_functions.c" #include "executables/thread-common.h" +#include "executables/split_headers.h" void feptx_ofdm(RU_t *ru, int frame, int subframe); void feptx_prec(RU_t *ru, int frame, int subframe); @@ -78,6 +79,13 @@ int n_tx_dropped = 0; /*!< \brief initial max process time for tx */ int n_rx_dropped = 0; /*!< \brief initial max process time for rx */ int emulate_rf = 0; +int split73=0; +void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset) { + AssertFatal(false, "Must not be called in this context\n"); +} +void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, uint16_t rnti, int32_t stat) { + AssertFatal(false, "Must not be called in this context\n"); +} void handler(int sig) { void *array[10]; @@ -1590,11 +1598,11 @@ int main(int argc, char **argv) { subframe<<1); for (i=0; idlsch[0][0]->harq_processes[0]->e[i]==1 && UE->pdsch_vars[UE->current_thread_id[subframe]][0]->llr[0][i] > 0)|| - (eNB->dlsch[0][0]->harq_processes[0]->e[i]==0 && UE->pdsch_vars[UE->current_thread_id[subframe]][0]->llr[0][i] < 0)) { + if ((eNB->dlsch[0][0]->harq_processes[0]->eDL[i]==1 && UE->pdsch_vars[UE->current_thread_id[subframe]][0]->llr[0][i] > 0)|| + (eNB->dlsch[0][0]->harq_processes[0]->eDL[i]==0 && UE->pdsch_vars[UE->current_thread_id[subframe]][0]->llr[0][i] < 0)) { uncoded_ber_bit[bit_errors++] = 1; printf("error in pos %d : %d => %d\n",i, - eNB->dlsch[0][0]->harq_processes[0]->e[i], + eNB->dlsch[0][0]->harq_processes[0]->eDL[i], UE->pdsch_vars[UE->current_thread_id[subframe]][0]->llr[0][i]); } else { /* @@ -1641,7 +1649,7 @@ int main(int argc, char **argv) { //pdsch_vars printf("coded_bits_per_codeword %u\n",coded_bits_per_codeword); dump_dlsch2(UE,eNB_id,subframe,&coded_bits_per_codeword,round, UE->dlsch[UE->current_thread_id[subframe]][0][0]->current_harq_pid); - LOG_M("dlsch_e.m","e",eNB->dlsch[0][0]->harq_processes[0]->e,coded_bits_per_codeword,1,4); + LOG_M("dlsch_e.m","e",eNB->dlsch[0][0]->harq_processes[0]->eDL,coded_bits_per_codeword,1,4); //pdcch_vars LOG_M("pdcchF0_ext.m","pdcchF_ext", UE->pdcch_vars[0][eNB_id]->rxdataF_ext[0],2*3*UE->frame_parms.ofdm_symbol_size,1,1); LOG_M("pdcch00_ch0_ext.m","pdcch00_ch0_ext",UE->pdcch_vars[0][eNB_id]->dl_ch_estimates_ext[0],300*3,1,1); diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c index 6c04d6edf7..064066801d 100644 --- a/openair1/SIMULATION/LTE_PHY/ulsim.c +++ b/openair1/SIMULATION/LTE_PHY/ulsim.c @@ -54,6 +54,7 @@ #include "common/config/config_load_configmodule.h" #include "executables/thread-common.h" #include "targets/RT/USER/lte-softmodem.h" +#include "executables/split_headers.h" double cpuf; #define inMicroS(a) (((double)(a))/(cpu_freq_GHz*1000.0)) @@ -81,6 +82,14 @@ int n_tx_dropped = 0; /*!< \brief initial max process time for tx */ int n_rx_dropped = 0; /*!< \brief initial max process time for rx */ +int split73=0; +void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset) { + AssertFatal(false, "Must not be called in this context\n"); +} +void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB, LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask, uint16_t rnti, int32_t stat) { + AssertFatal(false, "Must not be called in this context\n"); +} + extern void fep_full(RU_t *ru, int subframe); extern void ru_fep_full_2thread(RU_t *ru, int subframe); //extern void eNB_fep_full(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc); From 9afdaf02444106dd8855554a1f9227a3aa84faf9 Mon Sep 17 00:00:00 2001 From: Gabriele Perrone Date: Wed, 4 Mar 2020 15:13:07 +0100 Subject: [PATCH 090/240] pushing for debugging --- ci-scripts/constants.py | 2 +- ci-scripts/epc.py | 15 +- ci-scripts/html.py | 528 ++++++ ci-scripts/main_enb.py | 1582 +++-------------- ci-scripts/ran.py | 376 +++- ci-scripts/sshconnection.py | 5 +- .../enb_usrp210_band13_test_10mhz_tm1.xml | 2 +- .../x2ho_enb_usrp210_band13_simple_test.xml | 189 ++ 8 files changed, 1352 insertions(+), 1347 deletions(-) create mode 100644 ci-scripts/html.py create mode 100644 ci-scripts/xml_files/x2ho_enb_usrp210_band13_simple_test.xml diff --git a/ci-scripts/constants.py b/ci-scripts/constants.py index f07fd81b43..65fca7193b 100644 --- a/ci-scripts/constants.py +++ b/ci-scripts/constants.py @@ -56,6 +56,7 @@ OAI_UE_PROCESS_COULD_NOT_SYNC = -21 OAI_UE_PROCESS_ASSERTION = -22 OAI_UE_PROCESS_FAILED = -23 OAI_UE_PROCESS_NO_TUNNEL_INTERFACE = -24 +OAI_UE_PROCESS_SEG_FAULT = -25 OAI_UE_PROCESS_OK = +6 UE_STATUS_DETACHED = 0 @@ -68,4 +69,3 @@ X2_HO_REQ_STATE__TARGET_RECEIVES_REQ = 1 X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE = 2 X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ = 3 X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK = 10 - diff --git a/ci-scripts/epc.py b/ci-scripts/epc.py index 91d722a72f..4f283f530e 100644 --- a/ci-scripts/epc.py +++ b/ci-scripts/epc.py @@ -6,6 +6,8 @@ import re # reg import logging import os import time +import signal + from multiprocessing import Process, Lock, SimpleQueue #----------------------------------------------------------- @@ -49,23 +51,22 @@ class EPCManagement(): def GetType(self): return self.EPCType def Set_PcapFileName(self, pcapfn): - self.PcapFileName = pcapfn + self.EPC_PcapFileName = pcapfn def Get_PcapFileName(self): - return self.PcapFileName + return self.EPC_PcapFileName def InitializeHSS(self): if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': HELP.GenericHelp(Version) HELP.EPCSrvHelp(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, self.EPCSourceCodePath, self.EPCType) sys.exit('Insufficient EPC Parameters') - #mySSH = SSH() mySSH = SSH.SSHConnection() mySSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): logging.debug('Using the OAI EPC Release 14 Cassandra-based HSS') mySSH.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) logging.debug('\u001B[1m Launching tshark on all interfaces \u001B[0m') - EPC_PcapFileName = 'epc_' + self.testCase_id + '.pcap' + self.EPC_PcapFileName = 'epc_' + self.testCase_id + '.pcap' mySSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f ' + self.EPC_PcapFileName, '\$', 5) mySSH.command('echo $USER; nohup sudo tshark -f "tcp port not 22 and port not 53" -i any -w ' + self.EPCSourceCodePath + '/scripts/' + self.EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', self.EPCUserName, 5) mySSH.command('echo ' + self.EPCPassword + ' | sudo -S mkdir -p logs', '\$', 5) @@ -85,7 +86,8 @@ class EPCManagement(): mySSH.command('mkdir -p ' + self.EPCSourceCodePath + '/scripts', '\$', 5) mySSH.command('cd /opt/hss_sim0609', '\$', 5) mySSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f hss.log daemon.log', '\$', 5) - mySSH.command('echo ' + self.EPCPassword + ' | sudo -S echo "Starting sudo session" && sudo daemon --unsafe --name=simulated_hss --chdir=/opt/hss_sim0609 ./starthss_real ', '\$', 5) + #mySSH.command('echo ' + self.EPCPassword + ' | sudo -S echo "Starting sudo session" && sudo daemon --unsafe --name=simulated_hss --chdir=/opt/hss_sim0609 ./starthss_real ', '\$', 5) + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S echo "Starting sudo session" && sudo su -c "screen -dm -S simulated_hss ./starthss"', '\$', 5) else: logging.error('This option should not occur!') mySSH.close() @@ -248,7 +250,8 @@ class EPCManagement(): mySSH.command('cd scripts', '\$', 5) mySSH.command('echo ' + self.EPCPassword + ' | sudo -S daemon --name=simulated_hss --stop', '\$', 5) time.sleep(1) - mySSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL hss_sim', '\$', 5) + #mySSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL hss_sim', '\$', 5) + mySSH.command('echo ' + self.EPCPassword + ' | sudo killall hss_sim', '\$', 5) else: logging.error('This should not happen!') mySSH.close() diff --git a/ci-scripts/html.py b/ci-scripts/html.py new file mode 100644 index 0000000000..80ad46f51e --- /dev/null +++ b/ci-scripts/html.py @@ -0,0 +1,528 @@ + +#----------------------------------------------------------- +# Import +#----------------------------------------------------------- +import sys # arg +import re # reg +import logging +import os +import time +import subprocess +from multiprocessing import Process, Lock, SimpleQueue + +#----------------------------------------------------------- +# OAI Testing modules +#----------------------------------------------------------- +#import main_enb +#MAIN = main_enb.OaiCiTest() + + +#----------------------------------------------------------- +# Class Declaration +#----------------------------------------------------------- +class HTMLManagement(): + def __init__(self): + # self.FailReportCnt = 0 + # self.prematureExit = False + self.ranRepository = '' + self.ranBranch = '' + self.ranAllowMerge = False + self.ranCommitID = '' + self.ranTargetBranch = '' + #self.eNBIPAddress = '' + #self.eNBUserName = '' + #self.eNBPassword = '' + #self.eNBSourceCodePath = '' + #self.eNB1IPAddress = '' + #self.eNB1UserName = '' + #self.eNB1Password = '' + #self.eNB1SourceCodePath = '' + #self.eNB2IPAddress = '' + #self.eNB2UserName = '' + #self.eNB2Password = '' + #self.eNB2SourceCodePath = '' + #self.ADBIPAddress = '' + #self.ADBUserName = '' + #self.ADBPassword = '' + #self.ADBCentralized = True + #self.testCase_id = '' + self.testXMLfiles = [] + self.nbTestXMLfiles = 0 + #self.desc = '' + #self.Build_eNB_args = '' + #self.backgroundBuild = False + #self.backgroundBuildTestId = ['', '', ''] + #self.Build_eNB_forced_workspace_cleanup = False + #self.Initialize_eNB_args = '' + #self.air_interface = 'lte' + #self.eNB_instance = '' + #self.eNB_serverId = '' + #self.eNBLogFiles = ['', '', ''] + #self.eNBOptions = ['', '', ''] + #self.eNBmbmsEnables = [False, False, False] + #self.eNBstatuses = [-1, -1, -1] + #self.ping_args = '' + #self.ping_packetloss_threshold = '' + #self.iperf_args = '' + #self.iperf_packetloss_threshold = '' + #self.iperf_profile = '' + #self.iperf_options = '' + #self.nbMaxUEtoAttach = -1 + #self.UEDevices = [] + #self.UEDevicesStatus = [] + #self.UEDevicesRemoteServer = [] + #self.UEDevicesRemoteUser = [] + #self.UEDevicesOffCmd = [] + #self.UEDevicesOnCmd = [] + #self.UEDevicesRebootCmd = [] + #self.CatMDevices = [] + #self.UEIPAddresses = [] + self.htmlFile = '' + self.htmlHeaderCreated = False + self.htmlFooterCreated = False + self.htmlUEConnected = -1 + self.htmlNb_Smartphones = 0 + self.htmlNb_CATM_Modules = 0 + self.htmleNBFailureMsg = '' + self.htmlUEFailureMsg = '' + #self.picocom_closure = False + #self.idle_sleep_time = 0 + #self.x2_ho_options = 'network' + #self.x2NbENBs = 0 + #self.x2ENBBsIds = [] + #self.x2ENBConnectedUEs = [] + self.htmlTabRefs = [] + self.htmlTabNames = [] + self.htmlTabIcons = [] + #self.repeatCounts = [] + #self.finalStatus = False + #self.OsVersion = '' + #self.KernelVersion = '' + #self.UhdVersion = '' + #self.UsrpBoard = '' + #self.CpuNb = '' + #self.CpuModel = '' + #self.CpuMHz = '' + #self.UEIPAddress = '' + #self.UEUserName = '' + #self.UEPassword = '' + #self.UE_instance = '' + #self.UESourceCodePath = '' + #self.UELogFile = '' + #self.Build_OAI_UE_args = '' + #self.Initialize_OAI_UE_args = '' + #self.clean_repository = True + #self.flexranCtrlInstalled = False + #self.flexranCtrlStarted = False + #self.expectedNbOfConnectedUEs = 0 + #self.startTime = 0 + + +#----------------------------------------------------------- +# HTML Reporting.... +#----------------------------------------------------------- + + def Setdesc(self, dsc): + self.desc = dsc + + def SetstartTime(self, sttime): + self.startTime = sttime + + def SettestCase_id(self, tcid): + self.testCase_id = tcid + + + def SetranRepository(self, repository): + self.ranRepository = repository + def GetranRepository(self): + return self.ranRepository + + def SetranAllowMerge(self, merge): + self.ranAllowMerge = merge + def GetranAllowMerge(self): + return self.ranAllowMerge + + + def SetranBranch(self, branch): + self.ranBranch = branch + def GetranBranch(self): + return self.ranBranch + + def SetranCommitID(self, commitid): + self.ranCommitID = commitid + def GetranCommitID(self): + return self.ranCommitID + + def SetranTargetBranch(self, tbranch): + self.ranTargetBranch = tbranch + def GetranTargetBranch(self): + return self.ranTargetBranch + +# def SetADBIPAddress(self, adbip): +# self.ADBIPAddress = adbip +# def GetADBIPAddress(self): +# return self.ADBIPAddress + + def SethtmlUEConnected(self, nbUEs): + self.htmlUEConnected = nbUEs + + def SethtmlNb_Smartphones(self, nbUEs): + self.htmlNb_Smartphones = nbUEs + + def SethtmlNb_CATM_Modules(self, nbUEs): + self.htmlNb_CATM_Modules = nbUEs + + def SetnbTestXMLfiles(self, nb): + self.nbTestXMLfiles = nb + + def SettestXMLfiles(self, xmlFile): + self.testXMLfiles.append(xmlFile) + + def SethtmlTabRefs(self, tabRef): + self.htmlTabRefs.append(tabRef) + + def SethtmlTabNames(self, tabName): + self.htmlTabNames.append(tabName) + + def SethtmlTabIcons(self, tabIcon): + self.htmlTabIcons.append(tabIcon) + + def CreateHtmlHeader(self, ADBIPAddress): + if (not self.htmlHeaderCreated): + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + logging.debug('\u001B[1m Creating HTML header \u001B[0m') + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + self.htmlFile = open('test_results.html', 'w') + self.htmlFile.write('\n') + self.htmlFile.write('\n') + self.htmlFile.write('\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Test Results for TEMPLATE_JOB_NAME job build #TEMPLATE_BUILD_ID\n') + self.htmlFile.write('\n') + self.htmlFile.write('
\n') + self.htmlFile.write('
\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write('
\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' Job Summary -- Job: TEMPLATE_JOB_NAME -- Build-ID: TEMPLATE_BUILD_ID\n') + self.htmlFile.write('
\n') + self.htmlFile.write('
\n') + self.htmlFile.write('
TEMPLATE_STAGE_NAME
\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (self.ranAllowMerge): + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (self.ranAllowMerge): + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (self.ranAllowMerge): + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if self.ranAllowMerge != '': + commit_message = subprocess.check_output("git log -n1 --pretty=format:\"%s\" " + self.ranCommitID, shell=True, universal_newlines=True) + commit_message = commit_message.strip() + self.htmlFile.write(' \n') + if (self.ranAllowMerge): + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (self.ranAllowMerge): + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if (self.ranTargetBranch == ''): + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write('
Build Start Time (UTC) TEMPLATE_BUILD_TIME
GIT Repository ' + self.ranRepository + '
Job Trigger Merge-RequestPush to Branch
Source Branch Branch' + self.ranBranch + '
Source Commit ID Commit ID ' + self.ranCommitID + '
Source Commit Message Commit Message ' + commit_message + '
Target Branch develop' + self.ranTargetBranch + '
\n') + + if (ADBIPAddress != 'none'): + #terminate_ue_flag = True + #MAIN.GetAllUEDevices(terminate_ue_flag) + #self.GetAllCatMDevices(terminate_ue_flag) + #self.htmlUEConnected = len(self.UEDevices) + self.htmlFile.write('

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

\n') + self.htmlFile.write('

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

\n') + else: + #self.UEDevices.append('OAI-UE') + #self.htmlUEConnected = len(self.UEDevices) + self.htmlUEConnected = 1 + self.htmlFile.write('

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

\n') + self.htmlFile.write('
\n') + self.htmlFile.write(' \n') + self.htmlFile.write('
\n') + self.htmlFile.close() + + def CreateHtmlTabHeader(self): + if (not self.htmlHeaderCreated): + if (not os.path.isfile('test_results.html')): + self.CreateHtmlHeader('none') + self.htmlFile = open('test_results.html', 'a') + if (self.nbTestXMLfiles == 1): + self.htmlFile.write('
\n') + self.htmlFile.write('

Test Summary for ' + self.testXMLfiles[0] + '

\n') + else: + self.htmlFile.write('
\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + #if (self.htmlUEConnected == -1): + # terminate_ue_flag = True + # if (self.ADBIPAddress != 'none'): + # self.GetAllUEDevices(terminate_ue_flag) + # self.GetAllCatMDevices(terminate_ue_flag) + # else: + # self.UEDevices.append('OAI-UE') + # self.htmlUEConnected = len(self.UEDevices) + + i = 0 + while (i < self.htmlUEConnected): + self.htmlFile.write(' \n') + i += 1 + self.htmlFile.write(' \n') + self.htmlFile.close() + self.htmlHeaderCreated = True + + def CreateHtmlTabFooter(self, passStatus): + if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): + self.htmlFile = open('test_results.html', 'a') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if passStatus: + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write('
Relative Time (ms)Test IdTest DescTest OptionsTest StatusUE' + str(i) + ' Status
Final Tab StatusPASS FAIL
\n') + self.htmlFile.write('
\n') + self.htmlFile.close() + time.sleep(1) + if passStatus: + cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__//' test_results.html" + subprocess.run(cmd, shell=True) + else: + cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__/<\/span>/' test_results.html" + subprocess.run(cmd, shell=True) + self.htmlFooterCreated = False + + def CreateHtmlFooter(self, passStatus): + if (os.path.isfile('test_results.html')): + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + logging.debug('\u001B[1m Creating HTML footer \u001B[0m') + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + + self.htmlFile = open('test_results.html', 'a') + self.htmlFile.write('
\n') + self.htmlFile.write('

\n') + self.htmlFile.write(' \n') + + machines = [ 'eNB', 'UE' ] + for machine in machines: + #This needs to move back to main and be called before CreateHtmlFooter + res = self.RetrieveSystemVersion(machine) + if res == -1: + continue + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + if passStatus: + self.htmlFile.write(' \n') + else: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write('
' + str(machine) + ' Server Characteristics
OS Version' + self.OsVersion + 'Kernel Version' + self.KernelVersion + 'UHD Version' + self.UhdVersion + 'USRP Board' + self.UsrpBoard + '
Nb CPUs' + self.CpuNb + 'CPU Model Name' + self.CpuModel + 'CPU Frequency' + self.CpuMHz + '
Final StatusPASS FAIL
\n') + self.htmlFile.write('

\n') + self.htmlFile.write('
End of Test Report -- Copyright 2018 OpenAirInterface. All Rights Reserved.
\n') + self.htmlFile.write('
\n') + self.htmlFile.write('\n') + self.htmlFile.close() + + #FailReportCnt should be passed as a parameter of CreateHtmlRetrySeparator method + # no need for a setter and be a member of html class + def CreateHtmlRetrySeparator(self, cntnumfails): + if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): + self.htmlFile = open('test_results.html', 'a') + self.htmlFile.write(' \n') + self.htmlFile.write(' Try Run #' + str(cntnumfails) + '\n') + self.htmlFile.write(' \n') + self.htmlFile.close() + + def CreateHtmlTestRow(self, options, status, processesStatus, machine='eNB'): + if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): + self.htmlFile = open('test_results.html', 'a') + currentTime = int(round(time.time() * 1000)) - self.startTime + self.htmlFile.write(' \n') + self.htmlFile.write(' ' + format(currentTime / 1000, '.1f') + '\n') + self.htmlFile.write(' ' + self.testCase_id + '\n') + self.htmlFile.write(' ' + self.desc + '\n') + self.htmlFile.write(' ' + str(options) + '\n') + if (str(status) == 'OK'): + self.htmlFile.write(' ' + str(status) + '\n') + elif (str(status) == 'KO'): + if (processesStatus == 0): + self.htmlFile.write(' ' + str(status) + '\n') + elif (processesStatus == ENB_PROCESS_FAILED): + self.htmlFile.write(' KO - eNB process not found\n') + elif (processesStatus == OAI_UE_PROCESS_FAILED): + self.htmlFile.write(' KO - OAI UE process not found\n') + elif (processesStatus == ENB_PROCESS_SEG_FAULT) or (processesStatus == OAI_UE_PROCESS_SEG_FAULT): + self.htmlFile.write(' KO - ' + machine + ' process ended in Segmentation Fault\n') + elif (processesStatus == ENB_PROCESS_ASSERTION) or (processesStatus == OAI_UE_PROCESS_ASSERTION): + self.htmlFile.write(' KO - ' + machine + ' process ended in Assertion\n') + elif (processesStatus == ENB_PROCESS_REALTIME_ISSUE): + self.htmlFile.write(' KO - ' + machine + ' process faced Real Time issue(s)\n') + elif (processesStatus == ENB_PROCESS_NOLOGFILE_TO_ANALYZE) or (processesStatus == OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE): + self.htmlFile.write(' OK?\n') + elif (processesStatus == ENB_PROCESS_SLAVE_RRU_NOT_SYNCED): + self.htmlFile.write(' KO - ' + machine + ' Slave RRU could not synch\n') + elif (processesStatus == OAI_UE_PROCESS_COULD_NOT_SYNC): + self.htmlFile.write(' KO - UE could not sync\n') + elif (processesStatus == HSS_PROCESS_FAILED): + self.htmlFile.write(' KO - HSS process not found\n') + elif (processesStatus == MME_PROCESS_FAILED): + self.htmlFile.write(' KO - MME process not found\n') + elif (processesStatus == SPGW_PROCESS_FAILED): + self.htmlFile.write(' KO - SPGW process not found\n') + elif (processesStatus == UE_IP_ADDRESS_ISSUE): + self.htmlFile.write(' KO - Could not retrieve UE IP address\n') + else: + self.htmlFile.write(' ' + str(status) + '\n') + else: + self.htmlFile.write(' ' + str(status) + '\n') + if (len(str(self.htmleNBFailureMsg)) > 2): + cellBgColor = 'white' + result = re.search('ended with|faced real time issues', self.htmleNBFailureMsg) + if result is not None: + cellBgColor = 'red' + else: + result = re.search('showed|Reestablishment|Could not copy eNB logfile', self.htmleNBFailureMsg) + if result is not None: + cellBgColor = 'orange' + self.htmlFile.write('
' + self.htmleNBFailureMsg + '
\n') + self.htmleNBFailureMsg = '' + elif (len(str(self.htmlUEFailureMsg)) > 2): + cellBgColor = 'white' + result = re.search('ended with|faced real time issues', self.htmlUEFailureMsg) + if result is not None: + cellBgColor = 'red' + else: + result = re.search('showed|Could not copy UE logfile|oaitun_ue1 interface is either NOT mounted or NOT configured', self.htmlUEFailureMsg) + if result is not None: + cellBgColor = 'orange' + self.htmlFile.write('
' + self.htmlUEFailureMsg + '
\n') + self.htmlUEFailureMsg = '' + else: + i = 0 + while (i < self.htmlUEConnected): + self.htmlFile.write(' -\n') + i += 1 + self.htmlFile.write(' \n') + self.htmlFile.close() + + def CreateHtmlTestRowQueue(self, options, status, ue_status, ue_queue): + if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): + self.htmlFile = open('test_results.html', 'a') + currentTime = int(round(time.time() * 1000)) - self.startTime + addOrangeBK = False + self.htmlFile.write(' \n') + self.htmlFile.write(' ' + format(currentTime / 1000, '.1f') + '\n') + self.htmlFile.write(' ' + self.testCase_id + '\n') + self.htmlFile.write(' ' + self.desc + '\n') + self.htmlFile.write(' ' + str(options) + '\n') + if (str(status) == 'OK'): + self.htmlFile.write(' ' + str(status) + '\n') + elif (str(status) == 'KO'): + self.htmlFile.write(' ' + str(status) + '\n') + else: + addOrangeBK = True + self.htmlFile.write(' ' + str(status) + '\n') + i = 0 + while (i < self.htmlUEConnected): + if (i < ue_status): + if (not ue_queue.empty()): + if (addOrangeBK): + self.htmlFile.write(' ' + str(ue_queue.get()).replace('white', 'orange') + '\n') + else: + self.htmlFile.write(' ' + str(ue_queue.get()) + '\n') + else: + self.htmlFile.write(' -\n') + else: + self.htmlFile.write(' -\n') + i += 1 + self.htmlFile.write(' \n') + self.htmlFile.close() + + diff --git a/ci-scripts/main_enb.py b/ci-scripts/main_enb.py index e8c530a70b..340aaed9b3 100644 --- a/ci-scripts/main_enb.py +++ b/ci-scripts/main_enb.py @@ -28,6 +28,8 @@ # pexpect #--------------------------------------------------------------------- +import constants as CONST + #----------------------------------------------------------- # Version #----------------------------------------------------------- @@ -36,39 +38,39 @@ Version = '0.1' #----------------------------------------------------------- # Constants #----------------------------------------------------------- -ALL_PROCESSES_OK = 0 -ENB_PROCESS_FAILED = -1 -ENB_PROCESS_OK = +1 -ENB_PROCESS_SEG_FAULT = -11 -ENB_PROCESS_ASSERTION = -12 -ENB_PROCESS_REALTIME_ISSUE = -13 -ENB_PROCESS_NOLOGFILE_TO_ANALYZE = -14 -ENB_PROCESS_SLAVE_RRU_NOT_SYNCED = -15 -HSS_PROCESS_FAILED = -2 -HSS_PROCESS_OK = +2 -MME_PROCESS_FAILED = -3 -MME_PROCESS_OK = +3 -SPGW_PROCESS_FAILED = -4 -SPGW_PROCESS_OK = +4 -UE_IP_ADDRESS_ISSUE = -5 -OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE = -20 -OAI_UE_PROCESS_COULD_NOT_SYNC = -21 -OAI_UE_PROCESS_ASSERTION = -22 -OAI_UE_PROCESS_FAILED = -23 -OAI_UE_PROCESS_NO_TUNNEL_INTERFACE = -24 -OAI_UE_PROCESS_SEG_FAULT = -25 -OAI_UE_PROCESS_OK = +6 +ALL_PROCESSES_OK = CONST.ALL_PROCESSES_OK +ENB_PROCESS_FAILED = CONST.ENB_PROCESS_FAILED +ENB_PROCESS_OK = CONST.ENB_PROCESS_OK +ENB_PROCESS_SEG_FAULT = CONST.ENB_PROCESS_SEG_FAULT +ENB_PROCESS_ASSERTION = CONST.ENB_PROCESS_ASSERTION +ENB_PROCESS_REALTIME_ISSUE = CONST.ENB_PROCESS_REALTIME_ISSUE +ENB_PROCESS_NOLOGFILE_TO_ANALYZE = CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE +ENB_PROCESS_SLAVE_RRU_NOT_SYNCED = CONST.ENB_PROCESS_SLAVE_RRU_NOT_SYNCED +HSS_PROCESS_FAILED = CONST.HSS_PROCESS_FAILED +HSS_PROCESS_OK = CONST.HSS_PROCESS_OK +MME_PROCESS_FAILED = CONST.MME_PROCESS_FAILED +MME_PROCESS_OK = CONST.MME_PROCESS_OK +SPGW_PROCESS_FAILED = CONST.SPGW_PROCESS_FAILED +SPGW_PROCESS_OK = CONST.SPGW_PROCESS_OK +UE_IP_ADDRESS_ISSUE = CONST.UE_IP_ADDRESS_ISSUE +OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE = CONST.OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE +OAI_UE_PROCESS_COULD_NOT_SYNC = CONST.OAI_UE_PROCESS_COULD_NOT_SYNC +OAI_UE_PROCESS_ASSERTION = CONST.OAI_UE_PROCESS_ASSERTION +OAI_UE_PROCESS_FAILED = CONST.OAI_UE_PROCESS_FAILED +OAI_UE_PROCESS_NO_TUNNEL_INTERFACE = CONST.OAI_UE_PROCESS_NO_TUNNEL_INTERFACE +OAI_UE_PROCESS_SEG_FAULT = CONST.OAI_UE_PROCESS_SEG_FAULT +OAI_UE_PROCESS_OK = CONST.OAI_UE_PROCESS_OK -UE_STATUS_DETACHED = 0 -UE_STATUS_DETACHING = 1 -UE_STATUS_ATTACHING = 2 -UE_STATUS_ATTACHED = 3 +UE_STATUS_DETACHED = CONST.UE_STATUS_DETACHED +UE_STATUS_DETACHING = CONST.UE_STATUS_DETACHING +UE_STATUS_ATTACHING = CONST.UE_STATUS_ATTACHING +UE_STATUS_ATTACHED = CONST.UE_STATUS_ATTACHED -X2_HO_REQ_STATE__IDLE = 0 -X2_HO_REQ_STATE__TARGET_RECEIVES_REQ = 1 -X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE = 2 -X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ = 3 -X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK = 10 +X2_HO_REQ_STATE__IDLE = CONST.X2_HO_REQ_STATE__IDLE +X2_HO_REQ_STATE__TARGET_RECEIVES_REQ = CONST.X2_HO_REQ_STATE__TARGET_RECEIVES_REQ +X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE = CONST.X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE +X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ = CONST.X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ +X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK = CONST.X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK #----------------------------------------------------------- # Import @@ -167,9 +169,9 @@ class OaiCiTest(): self.x2NbENBs = 0 self.x2ENBBsIds = [] self.x2ENBConnectedUEs = [] - self.htmlTabRefs = [] - self.htmlTabNames = [] - self.htmlTabIcons = [] + #self.htmlTabRefs = [] + #self.htmlTabNames = [] + #self.htmlTabIcons = [] self.repeatCounts = [] self.finalStatus = False self.OsVersion = '' @@ -192,198 +194,8 @@ class OaiCiTest(): self.flexranCtrlStarted = False self.expectedNbOfConnectedUEs = 0 self.startTime = 0 -''' - def BuildeNB(self): - if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - if self.eNB_serverId == '0': - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - lSourcePath = RAN.GeteNBSourceCodePath() - elif self.eNB_serverId == '1': - lIpAddr = self.eNB1IPAddress - lUserName = self.eNB1UserName - lPassWord = self.eNB1Password - lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId == '2': - lIpAddr = self.eNB2IPAddress - lUserName = self.eNB2UserName - lPassWord = self.eNB2Password - lSourcePath = self.eNB2SourceCodePath - if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - SSH.open(lIpAddr, lUserName, lPassWord) - # Check if we build an 5G-NR gNB or an LTE eNB - result = re.search('--gNB', RAN.GetBuild_eNB_args()) - if result is not None: - self.air_interface = 'nr' - else: - self.air_interface = 'lte' - # Worakround for some servers, we need to erase completely the workspace - if self.Build_eNB_forced_workspace_cleanup: - SSH.command('echo ' + lPassWord + ' | sudo -S rm -Rf ' + lSourcePath, '\$', 15) - # on RedHat/CentOS .git extension is mandatory - result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository) - if result is not None: - full_ran_repo_name = self.ranRepository - else: - full_ran_repo_name = self.ranRepository + '.git' - SSH.command('mkdir -p ' + lSourcePath, '\$', 5) - SSH.command('cd ' + lSourcePath, '\$', 5) - SSH.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + full_ran_repo_name + ' .; else stdbuf -o0 git fetch --prune; fi', '\$', 600) - # Raphael: here add a check if git clone or git fetch went smoothly - SSH.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) - SSH.command('git config user.name "OAI Jenkins"', '\$', 5) - # Checking the BUILD INFO file - if not self.backgroundBuild: - SSH.command('ls *.txt', '\$', 5) - result = re.search('LAST_BUILD_INFO', SSH.getBefore()) - if result is not None: - mismatch = False - SSH.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) - result = re.search(self.ranCommitID, SSH.getBefore()) - if result is None: - mismatch = True - SSH.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) - if (RAN.GetranAllowMerge()): - result = re.search('YES', SSH.getBefore()) - if result is None: - mismatch = True - SSH.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) - if RAN.GetranTargetBranch() == '': - result = re.search('develop', SSH.getBefore()) - else: - result = re.search(RAN.GetranTargetBranch(), SSH.getBefore()) - if result is None: - mismatch = True - else: - result = re.search('NO', SSH.getBefore()) - if result is None: - mismatch = True - if not mismatch: - SSH.close() - self.CreateHtmlTestRow(RAN.GetBuild_eNB_args(), 'OK', ALL_PROCESSES_OK) - return - SSH.command('echo ' + lPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30) - # if the commit ID is provided use it to point to it - if self.ranCommitID != '': - SSH.command('git checkout -f ' + self.ranCommitID, '\$', 5) - # if the branch is not develop, then it is a merge request and we need to do - # the potential merge. Note that merge conflicts should already been checked earlier - if (RAN.GetranAllowMerge()): - if RAN.GetranTargetBranch() == '': - if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'): - SSH.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) - else: - logging.debug('Merging with the target branch: ' + RAN.GetranTargetBranch()) - SSH.command('git merge --ff origin/' + RAN.GetranTargetBranch() + ' -m "Temporary merge for CI"', '\$', 5) - SSH.command('source oaienv', '\$', 5) - SSH.command('cd cmake_targets', '\$', 5) - SSH.command('mkdir -p log', '\$', 5) - SSH.command('chmod 777 log', '\$', 5) - # no need to remove in log (git clean did the trick) - if self.backgroundBuild: - SSH.command('echo "./build_oai ' + RAN.GetBuild_eNB_args() + '" > ./my-lte-softmodem-build.sh', '\$', 5) - SSH.command('chmod 775 ./my-lte-softmodem-build.sh', '\$', 5) - SSH.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=build_enb_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/compile_oai_enb.log ./my-lte-softmodem-build.sh', '\$', 5) - SSH.close() - self.CreateHtmlTestRow(RAN.GetBuild_eNB_args(), 'OK', ALL_PROCESSES_OK) - self.backgroundBuildTestId[int(self.eNB_instance)] = self.testCase_id - return - SSH.command('stdbuf -o0 ./build_oai ' + RAN.GetBuild_eNB_args() + ' 2>&1 | stdbuf -o0 tee compile_oai_enb.log', 'Bypassing the Tests|build have failed', 1500) - self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.testCase_id) - def WaitBuildeNBisFinished(self): - if self.eNB_serverId == '0': - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - lSourcePath = RAN.GeteNBSourceCodePath() - elif self.eNB_serverId == '1': - lIpAddr = self.eNB1IPAddress - lUserName = self.eNB1UserName - lPassWord = self.eNB1Password - lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId == '2': - lIpAddr = self.eNB2IPAddress - lUserName = self.eNB2UserName - lPassWord = self.eNB2Password - lSourcePath = self.eNB2SourceCodePath - if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - SSH.open(lIpAddr, lUserName, lPassWord) - count = 40 - buildOAIprocess = True - while (count > 0) and buildOAIprocess: - SSH.command('ps aux | grep --color=never build_ | grep -v grep', '\$', 3) - result = re.search('build_oai', SSH.getBefore()) - if result is None: - buildOAIprocess = False - else: - count -= 1 - time.sleep(30) - self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.backgroundBuildTestId[int(self.eNB_instance)]) - - def checkBuildeNB(self, lIpAddr, lUserName, lPassWord, lSourcePath, testcaseId): - SSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 3) - SSH.command('ls ran_build/build', '\$', 3) - SSH.command('ls ran_build/build', '\$', 3) - if self.air_interface == 'nr': - nodeB_prefix = 'g' - else: - nodeB_prefix = 'e' - buildStatus = True - result = re.search(self.air_interface + '-softmodem', SSH.getBefore()) - if result is None: - buildStatus = False - else: - # Generating a BUILD INFO file - SSH.command('echo "SRC_BRANCH: ' + self.ranBranch + '" > ../LAST_BUILD_INFO.txt', '\$', 2) - SSH.command('echo "SRC_COMMIT: ' + self.ranCommitID + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) - if (RAN.GetranAllowMerge()): - SSH.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2) - if RAN.GetranTargetBranch() == '': - SSH.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2) - else: - SSH.command('echo "TGT_BRANCH: ' + RAN.GetranTargetBranch() + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) - else: - SSH.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) - SSH.command('mkdir -p build_log_' + testcaseId, '\$', 5) - SSH.command('mv log/* ' + 'build_log_' + testcaseId, '\$', 5) - SSH.command('mv compile_oai_enb.log ' + 'build_log_' + testcaseId, '\$', 5) - if self.eNB_serverId != '0': - SSH.command('cd cmake_targets', '\$', 5) - SSH.command('if [ -e tmp_build' + testcaseId + '.zip ]; then rm -f tmp_build' + testcaseId + '.zip; fi', '\$', 5) - SSH.command('zip -r -qq tmp_build' + testcaseId + '.zip build_log_' + testcaseId, '\$', 5) - SSH.close() - if (os.path.isfile('./tmp_build' + testcaseId + '.zip')): - os.remove('./tmp_build' + testcaseId + '.zip') - SSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/tmp_build' + testcaseId + '.zip', '.') - if (os.path.isfile('./tmp_build' + testcaseId + '.zip')): - SSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './tmp_build' + testcaseId + '.zip', RAN.GeteNBSourceCodePath() + '/cmake_targets/.') - os.remove('./tmp_build' + testcaseId + '.zip') - SSH.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) - SSH.command('cd ' + RAN.GeteNBSourceCodePath() + '/cmake_targets', '\$', 5) - SSH.command('unzip -qq -DD tmp_build' + testcaseId + '.zip', '\$', 5) - SSH.command('rm -f tmp_build' + testcaseId + '.zip', '\$', 5) - SSH.close() - else: - SSH.close() - - if buildStatus: - logging.info('\u001B[1m Building OAI ' + nodeB_prefix + 'NB Pass\u001B[0m') - self.CreateHtmlTestRow(RAN.GetBuild_eNB_args(), 'OK', ALL_PROCESSES_OK) - else: - logging.error('\u001B[1m Building OAI ' + nodeB_prefix + 'NB Failed\u001B[0m') - self.CreateHtmlTestRow(RAN.GetBuild_eNB_args(), 'KO', ALL_PROCESSES_OK) - self.CreateHtmlTabFooter(False) - sys.exit(1) -''' def BuildOAIUE(self): if self.UEIPAddress == '' or RAN.GetranRepository() == '' or RAN.GetranBranch() == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': GenericHelp(Version) @@ -391,10 +203,10 @@ class OaiCiTest(): SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) result = re.search('--nrUE', self.Build_OAI_UE_args) if result is not None: - RAN.Setair_interface() = 'nr' + RAN.Setair_interface('nr') ue_prefix = 'NR ' else: - RAN.Setair_interface() = 'lte' + RAN.Setair_interface('lte') ue_prefix = '' result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', RAN.GetranRepository()) if result is not None: @@ -434,7 +246,7 @@ class OaiCiTest(): mismatch = True if not mismatch: SSH.close() - self.CreateHtmlTestRow(RAN.GetBuild_eNB_args(), 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(RAN.GetBuild_eNB_args(), 'OK', ALL_PROCESSES_OK) return SSH.command('echo ' + self.UEPassword + ' | sudo -S git clean -x -d -ff', '\$', 30) @@ -470,7 +282,7 @@ class OaiCiTest(): # Generating a BUILD INFO file SSH.command('echo "SRC_BRANCH: ' + RAN.GetranBranch() + '" > ../LAST_BUILD_INFO.txt', '\$', 2) SSH.command('echo "SRC_COMMIT: ' + RAN.GetranCommitID() + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) - if (RAN.GetranAllowMerge): + if (RAN.GetranAllowMerge()): SSH.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2) if RAN.GetranTargetBranch() == '': SSH.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2) @@ -479,12 +291,12 @@ class OaiCiTest(): else: SSH.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) SSH.close() - self.CreateHtmlTestRow(self.Build_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE') + HTML.CreateHtmlTestRow(self.Build_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE') else: SSH.close() logging.error('\u001B[1m Building OAI UE Failed\u001B[0m') - self.CreateHtmlTestRow(self.Build_OAI_UE_args, 'KO', ALL_PROCESSES_OK, 'OAI UE') - self.CreateHtmlTabFooter(False) + HTML.CreateHtmlTestRow(self.Build_OAI_UE_args, 'KO', ALL_PROCESSES_OK, 'OAI UE') + HTML.CreateHtmlTabFooter(False) sys.exit(1) def CheckFlexranCtrlInstallation(self): @@ -495,6 +307,7 @@ class OaiCiTest(): result = re.search('/opt/flexran_rtc/build/rt_controller', SSH.getBefore()) if result is not None: self.flexranCtrlInstalled = True + RAN.SetflexranCtrlInstalled(True) logging.debug('Flexran Controller is installed') SSH.close() @@ -515,187 +328,10 @@ class OaiCiTest(): if result is not None: logging.debug('\u001B[1m Initialize FlexRan Controller Completed\u001B[0m') self.flexranCtrlStarted = True + RAN.SetflexranCtrlStarted(True) SSH.close() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) -''' - def InitializeeNB(self): - if self.eNB_serverId == '0': - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - lSourcePath = RAN.GeteNBSourceCodePath() - elif self.eNB_serverId == '1': - lIpAddr = self.eNB1IPAddress - lUserName = self.eNB1UserName - lPassWord = self.eNB1Password - lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId == '2': - lIpAddr = self.eNB2IPAddress - lUserName = self.eNB2UserName - lPassWord = self.eNB2Password - lSourcePath = self.eNB2SourceCodePath - if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - check_eNB = False - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - self.CreateHtmlTestRow(RAN.GetInitialize_eNB_args(), 'KO', pStatus) - self.CreateHtmlTabFooter(False) - sys.exit(1) - # If tracer options is on, running tshark on EPC side and capture traffic b/ EPC and eNB - result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args())) - if result is not None: - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('ip addr show | awk -f /tmp/active_net_interfaces.awk | egrep -v "lo|tun"', '\$', 5) - result = re.search('interfaceToUse=(?P[a-zA-Z0-9\-\_]+)done', SSH.getBefore()) - if result is not None: - eth_interface = result.group('eth_interface') - logging.debug('\u001B[1m Launching tshark on interface ' + eth_interface + '\u001B[0m') - EPC.EPC_PcapFileName = 'enb_' + self.testCase_id + '_s1log.pcap' - SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S rm -f /tmp/' + EPC.EPC_PcapFileName , '\$', 5) - SSH.command('echo $USER; nohup sudo tshark -f "host ' + lIpAddr +'" -i ' + eth_interface + ' -w /tmp/' + EPC.EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', EPC.GetUserName(), 5) - SSH.close() - SSH.open(lIpAddr, lUserName, lPassWord) - SSH.command('cd ' + lSourcePath, '\$', 5) - # Initialize_eNB_args usually start with -O and followed by the location in repository - full_config_file = RAN.GetInitialize_eNB_args().replace('-O ','') - extra_options = '' - extIdx = full_config_file.find('.conf') - if (extIdx > 0): - extra_options = full_config_file[extIdx + 5:] - # if tracer options is on, compiling and running T Tracer - result = re.search('T_stdout', str(extra_options)) - if result is not None: - logging.debug('\u001B[1m Compiling and launching T Tracer\u001B[0m') - SSH.command('cd common/utils/T/tracer', '\$', 5) - SSH.command('make', '\$', 10) - SSH.command('echo $USER; nohup ./record -d ../T_messages.txt -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.raw -ON -off VCD -off HEAVY -off LEGACY_GROUP_TRACE -off LEGACY_GROUP_DEBUG > ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.log 2>&1 &', lUserName, 5) - SSH.command('cd ' + lSourcePath, '\$', 5) - full_config_file = full_config_file[:extIdx + 5] - config_path, config_file = os.path.split(full_config_file) - else: - sys.exit('Insufficient Parameter') - ci_full_config_file = config_path + '/ci-' + config_file - rruCheck = False - result = re.search('^rru|^rcc|^du.band', str(config_file)) - if result is not None: - rruCheck = True - # do not reset board twice in IF4.5 case - result = re.search('^rru|^enb|^du.band', str(config_file)) - if result is not None: - SSH.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 60) - result = re.search('type: b200', SSH.getBefore()) - if result is not None: - logging.debug('Found a B2xx device --> resetting it') - SSH.command('echo ' + lPassWord + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10) - # Reloading FGPA bin firmware - SSH.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 60) - # Make a copy and adapt to EPC / eNB IP addresses - SSH.command('cp ' + full_config_file + ' ' + ci_full_config_file, '\$', 5) - SSH.command('sed -i -e \'s/CI_MME_IP_ADDR/' + EPC.GetIPAddress() + '/\' ' + ci_full_config_file, '\$', 2); - SSH.command('sed -i -e \'s/CI_ENB_IP_ADDR/' + lIpAddr + '/\' ' + ci_full_config_file, '\$', 2); - SSH.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2); - SSH.command('sed -i -e \'s/CI_RRU1_IP_ADDR/' + self.eNB1IPAddress + '/\' ' + ci_full_config_file, '\$', 2); - SSH.command('sed -i -e \'s/CI_RRU2_IP_ADDR/' + self.eNB2IPAddress + '/\' ' + ci_full_config_file, '\$', 2); - if self.flexranCtrlInstalled and self.flexranCtrlStarted: - SSH.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "yes";/\' ' + ci_full_config_file, '\$', 2); - else: - SSH.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "no";/\' ' + ci_full_config_file, '\$', 2); - self.eNBmbmsEnables[int(self.eNB_instance)] = False - SSH.command('grep enable_enb_m2 ' + ci_full_config_file, '\$', 2); - result = re.search('yes', SSH.getBefore()) - if result is not None: - self.eNBmbmsEnables[int(self.eNB_instance)] = True - logging.debug('\u001B[1m MBMS is enabled on this eNB\u001B[0m') - result = re.search('noS1', str(RAN.GetInitialize_eNB_args())) - eNBinNoS1 = False - if result is not None: - eNBinNoS1 = True - logging.debug('\u001B[1m eNB is in noS1 configuration \u001B[0m') - # Launch eNB with the modified config file - SSH.command('source oaienv', '\$', 5) - SSH.command('cd cmake_targets', '\$', 5) - SSH.command('echo "ulimit -c unlimited && ./ran_build/build/' + self.air_interface + '-softmodem -O ' + lSourcePath + '/' + ci_full_config_file + extra_options + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - SSH.command('chmod 775 ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - SSH.command('echo ' + lPassWord + ' | sudo -S rm -Rf enb_' + self.testCase_id + '.log', '\$', 5) - SSH.command('hostnamectl','\$', 5) - result = re.search('CentOS Linux 7', SSH.getBefore()) - if result is not None: - SSH.command('echo $USER; nohup sudo ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh > ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log 2>&1 &', lUserName, 10) - else: - SSH.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=enb' + str(self.eNB_instance) + '_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - self.eNBLogFiles[int(self.eNB_instance)] = 'enb_' + self.testCase_id + '.log' - if extra_options != '': - self.eNBOptions[int(self.eNB_instance)] = extra_options - time.sleep(6) - doLoop = True - loopCounter = 20 - enbDidSync = False - while (doLoop): - loopCounter = loopCounter - 1 - if (loopCounter == 0): - # In case of T tracer recording, we may need to kill it - result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args())) - if result is not None: - SSH.command('killall --signal SIGKILL record', '\$', 5) - SSH.close() - doLoop = False - logging.error('\u001B[1;37;41m eNB logging system did not show got sync! \u001B[0m') - self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'KO', ALL_PROCESSES_OK) - # In case of T tracer recording, we need to kill tshark on EPC side - result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args())) - if result is not None: - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - logging.debug('\u001B[1m Stopping tshark \u001B[0m') - SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) - if EPC.EPC_PcapFileName != '': - time.sleep(0.5) - SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S chmod 666 /tmp/' + EPC.EPC_PcapFileName , '\$', 5) - SSH.close() - time.sleep(1) - if EPC.EPC_PcapFileName != '': - copyin_res = SSH.copyin(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), '/tmp/' + EPC.EPC_PcapFileName , '.') - if (copyin_res == 0): - SSH.copyout(lIpAddr, lUserName, lPassWord, EPC.EPC_PcapFileName , lSourcePath + '/cmake_targets/.') - self.prematureExit = True - return - else: - SSH.command('stdbuf -o0 cat enb_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync|Starting"', '\$', 4) - if rruCheck: - result = re.search('wait RUs', SSH.getBefore()) - else: - result = re.search('got sync|Starting F1AP at CU', SSH.getBefore()) - if result is None: - time.sleep(6) - else: - doLoop = False - enbDidSync = True - time.sleep(10) - - if enbDidSync and eNBinNoS1: - SSH.command('ifconfig oaitun_enb1', '\$', 4) - SSH.command('ifconfig oaitun_enb1', '\$', 4) - result = re.search('inet addr:1|inet 1', SSH.getBefore()) - if result is not None: - logging.debug('\u001B[1m oaitun_enb1 interface is mounted and configured\u001B[0m') - else: - logging.error('\u001B[1m oaitun_enb1 interface is either NOT mounted or NOT configured\u001B[0m') - if self.eNBmbmsEnables[int(self.eNB_instance)]: - SSH.command('ifconfig oaitun_enm1', '\$', 4) - result = re.search('inet addr', SSH.getBefore()) - if result is not None: - logging.debug('\u001B[1m oaitun_enm1 interface is mounted and configured\u001B[0m') - else: - logging.error('\u001B[1m oaitun_enm1 interface is either NOT mounted or NOT configured\u001B[0m') - if enbDidSync: - self.eNBstatuses[int(self.eNB_instance)] = int(self.eNB_serverId) - - SSH.close() - self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'OK', ALL_PROCESSES_OK) - logging.debug('\u001B[1m Initialize eNB Completed\u001B[0m') -''' + HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + def InitializeUE_common(self, device_id, idx): try: SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) @@ -757,7 +393,7 @@ class OaiCiTest(): i += 1 for job in multi_jobs: job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) def InitializeOAIUE(self): if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': @@ -770,8 +406,8 @@ class OaiCiTest(): check_OAI_UE = False pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', pStatus) - self.CreateHtmlTabFooter(False) + HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', pStatus) + HTML.CreateHtmlTabFooter(False) sys.exit(1) UE_prefix = '' else: @@ -915,7 +551,7 @@ class OaiCiTest(): SSH.close() if fullSyncStatus and gotSyncStatus and tunnelInterfaceStatus: - self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE') + HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE') logging.debug('\u001B[1m Initialize OAI UE Completed\u001B[0m') if (self.ADBIPAddress != 'none'): self.UEDevices = [] @@ -928,10 +564,10 @@ class OaiCiTest(): self.htmlUEFailureMsg = 'oaitun_ue1/oaitun_uem1 interfaces are either NOT mounted or NOT configured' else: self.htmlUEFailureMsg = 'oaitun_ue1 interface is either NOT mounted or NOT configured' - self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', OAI_UE_PROCESS_NO_TUNNEL_INTERFACE, 'OAI UE') + HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', OAI_UE_PROCESS_NO_TUNNEL_INTERFACE, 'OAI UE') else: self.htmlUEFailureMsg = 'nr-uesoftmodem did NOT synced' - self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', OAI_UE_PROCESS_COULD_NOT_SYNC, 'OAI UE') + HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', OAI_UE_PROCESS_COULD_NOT_SYNC, 'OAI UE') logging.error('\033[91mInitialize OAI UE Failed! \033[0m') self.AutoTerminateUEandeNB() @@ -961,11 +597,11 @@ class OaiCiTest(): # Calling twice AT to clear all buffers SSH.command('AT', 'OK|ERROR', 5) SSH.command('AT', 'OK', 5) - # Doing a power cycle - self.command('AT^RESET', 'SIMSTORE,READY', 15) - self.command('AT', 'OK|ERROR', 5) - self.command('AT', 'OK', 5) - self.command('ATE1', 'OK', 5) + # Doing a power cycle + self.command('AT^RESET', 'SIMSTORE,READY', 15) + self.command('AT', 'OK|ERROR', 5) + self.command('AT', 'OK', 5) + self.command('ATE1', 'OK', 5) # Disabling the Radio SSH.command('AT+CFUN=0', 'OK', 5) logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') @@ -984,7 +620,7 @@ class OaiCiTest(): # Force closure of picocom but device might still be locked SSH.close() self.picocom_closure = False - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) self.checkDevTTYisUnlocked() def TerminateCatM(self): @@ -1005,7 +641,7 @@ class OaiCiTest(): logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') SSH.close() self.picocom_closure = False - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) self.checkDevTTYisUnlocked() def AttachCatM(self): @@ -1074,12 +710,12 @@ class OaiCiTest(): else: html_cell += '' html_queue.put(html_cell) - self.CreateHtmlTestRowQueue('N/A', 'OK', 1, html_queue) + HTML.CreateHtmlTestRowQueue('N/A', 'OK', 1, html_queue) else: logging.error('\u001B[1m CAT-M module Attachment Failed\u001B[0m') html_cell = '
CAT-M module Attachment Failed
' html_queue.put(html_cell) - self.CreateHtmlTestRowQueue('N/A', 'KO', 1, html_queue) + HTML.CreateHtmlTestRowQueue('N/A', 'KO', 1, html_queue) self.AutoTerminateUEandeNB() def PingCatM(self): @@ -1090,7 +726,7 @@ class OaiCiTest(): check_OAI_UE = False pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) self.AutoTerminateUEandeNB() return try: @@ -1101,8 +737,8 @@ class OaiCiTest(): SSH.command('cd scripts', '\$', 5) if re.match('OAI', EPC.GetType(), re.IGNORECASE): logging.debug('Using the OAI EPC HSS: not implemented yet') - self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) - self.CreateHtmlTabFooter(False) + HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + HTML.CreateHtmlTabFooter(False) sys.exit(1) else: SSH.command('egrep --color=never "Allocated ipv4 addr" /opt/ltebox/var/log/xGwLog.0', '\$', 5) @@ -1110,7 +746,7 @@ class OaiCiTest(): if result is not None: moduleIPAddr = result.group('ipaddr') else: - self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) self.AutoTerminateUEandeNB() return ping_time = re.findall("-c (\d+)",str(self.ping_args)) @@ -1172,9 +808,9 @@ class OaiCiTest(): html_cell = '
CAT-M module\nIP Address  : ' + moduleIPAddr + '\n' + qMsg + '
' statusQueue.put(html_cell) if (packetLossOK): - self.CreateHtmlTestRowQueue(self.ping_args, 'OK', 1, statusQueue) + HTML.CreateHtmlTestRowQueue(self.ping_args, 'OK', 1, statusQueue) else: - self.CreateHtmlTestRowQueue(self.ping_args, 'KO', 1, statusQueue) + HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', 1, statusQueue) self.AutoTerminateUEandeNB() except: os.kill(os.getppid(),signal.SIGUSR1) @@ -1198,6 +834,7 @@ class OaiCiTest(): SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry" | grep -m 1 mDataConnectionState', '\$', 15) else: SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\' | grep -m 1 mDataConnectionState', '\$', 60) + print('#GP: in SSH.getBefore() K=0 (it was K=2 in main.py)') result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', SSH.getBefore()) if result is None: logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m') @@ -1256,7 +893,7 @@ class OaiCiTest(): check_OAI_UE = False pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow('N/A', 'KO', pStatus) + HTML.CreateHtmlTestRow('N/A', 'KO', pStatus) self.AutoTerminateUEandeNB() return multi_jobs = [] @@ -1275,7 +912,7 @@ class OaiCiTest(): job.join() if (status_queue.empty()): - self.CreateHtmlTestRow('N/A', 'KO', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'KO', ALL_PROCESSES_OK) self.AutoTerminateUEandeNB() return else: @@ -1298,13 +935,13 @@ class OaiCiTest(): if self.UEDevicesStatus[cnt] == UE_STATUS_ATTACHING: self.UEDevicesStatus[cnt] = UE_STATUS_ATTACHED cnt += 1 - self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args())) if result is not None: logging.debug('Waiting 5 seconds to fill up record file') time.sleep(5) else: - self.CreateHtmlTestRowQueue('N/A', 'KO', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue('N/A', 'KO', len(self.UEDevices), html_queue) self.AutoTerminateUEandeNB() def DetachUE_common(self, device_id, idx): @@ -1330,7 +967,7 @@ class OaiCiTest(): check_OAI_UE = False pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow('N/A', 'KO', pStatus) + HTML.CreateHtmlTestRow('N/A', 'KO', pStatus) self.AutoTerminateUEandeNB() return multi_jobs = [] @@ -1344,7 +981,7 @@ class OaiCiTest(): cnt += 1 for job in multi_jobs: job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args())) if result is not None: logging.debug('Waiting 5 seconds to fill up record file') @@ -1401,8 +1038,8 @@ class OaiCiTest(): check_OAI_UE = False pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow('N/A', 'KO', pStatus) - self.CreateHtmlTabFooter(False) + HTML.CreateHtmlTestRow('N/A', 'KO', pStatus) + HTML.CreateHtmlTabFooter(False) sys.exit(1) multi_jobs = [] for device_id in self.UEDevices: @@ -1412,7 +1049,7 @@ class OaiCiTest(): multi_jobs.append(p) for job in multi_jobs: job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) def DataDisableUE_common(self, device_id, idx): try: @@ -1441,7 +1078,7 @@ class OaiCiTest(): i += 1 for job in multi_jobs: job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) def DataEnableUE_common(self, device_id, idx): try: @@ -1470,7 +1107,7 @@ class OaiCiTest(): i += 1 for job in multi_jobs: job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) def GetAllUEDevices(self, terminate_ue_flag): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': @@ -1506,11 +1143,13 @@ class OaiCiTest(): self.UEDevicesRebootCmd.append(comma_split[5]) phone_list_file.close() - if terminate_ue_flag == False: + if terminate_ue_flag == True: + print('terminate_ue_flag == True') if len(self.UEDevices) == 0: logging.debug('\u001B[1;37;41m UE Not Found! \u001B[0m') sys.exit(1) if len(self.UEDevicesStatus) == 0: + print('len(self.UEDevicesStatus) == 0') cnt = 0 while cnt < len(self.UEDevices): self.UEDevicesStatus.append(UE_STATUS_DETACHED) @@ -1533,7 +1172,7 @@ class OaiCiTest(): SSH.close() if result is not None: logging.debug('Found a module list file on ADB server') - if terminate_ue_flag == False: + if terminate_ue_flag == True: if len(self.CatMDevices) == 0: logging.debug('\u001B[1;37;41m CAT-M UE Not Found! \u001B[0m') sys.exit(1) @@ -1596,8 +1235,8 @@ class OaiCiTest(): check_OAI_UE = False pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow('N/A', 'KO', pStatus) - self.CreateHtmlTabFooter(False) + HTML.CreateHtmlTestRow('N/A', 'KO', pStatus) + HTML.CreateHtmlTabFooter(False) sys.exit(1) multi_jobs = [] lock = Lock() @@ -1633,7 +1272,7 @@ class OaiCiTest(): htmlOptions = 'N/A' if (status_queue.empty()): - self.CreateHtmlTestRow(htmlOptions, 'KO', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(htmlOptions, 'KO', ALL_PROCESSES_OK) self.AutoTerminateUEandeNB() else: check_status = True @@ -1647,9 +1286,9 @@ class OaiCiTest(): html_cell = '
UE (' + device_id + ')\n' + message + '
' html_queue.put(html_cell) if check_status and passStatus: - self.CreateHtmlTestRowQueue(htmlOptions, 'OK', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(htmlOptions, 'OK', len(self.UEDevices), html_queue) else: - self.CreateHtmlTestRowQueue(htmlOptions, 'KO', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(htmlOptions, 'KO', len(self.UEDevices), html_queue) self.AutoTerminateUEandeNB() def GetAllUEIPAddresses(self): @@ -1680,6 +1319,7 @@ class OaiCiTest(): SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) idx = 0 for device_id in self.UEDevices: + print('UE status attched'+UE_STATUS_ATTACHED) if self.UEDevicesStatus[idx] != UE_STATUS_ATTACHED: idx += 1 continue @@ -1809,14 +1449,14 @@ class OaiCiTest(): html_queue = SimpleQueue() html_cell = '
OAI UE ping result\n' + qMsg + '
' html_queue.put(html_cell) - self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) def PingNoS1(self): check_eNB = True check_OAI_UE = True pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) self.AutoTerminateUEandeNB() return ping_from_eNB = re.search('oaitun_enb1', str(self.ping_args)) @@ -1889,13 +1529,13 @@ class OaiCiTest(): html_cell = '
OAI UE ping result\n' + qMsg + '
' html_queue.put(html_cell) if packetLossOK: - self.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) else: - self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) # copying on the EPC server for logCollection if ping_from_eNB is not None: - copyin_res = SSH.copyin(RAN.GeteNBIPAddress, RAN.GeteNBUserName, RAN.GeteNBPassword, RAN.GeteNBSourceCodePath() + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') + copyin_res = SSH.copyin(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath() + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') else: copyin_res = SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') if (copyin_res == 0): @@ -1918,12 +1558,12 @@ class OaiCiTest(): check_OAI_UE = False pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) self.AutoTerminateUEandeNB() return ueIpStatus = self.GetAllUEIPAddresses() if (ueIpStatus < 0): - self.CreateHtmlTestRow(self.ping_args, 'KO', UE_IP_ADDRESS_ISSUE) + HTML.CreateHtmlTestRow(self.ping_args, 'KO', UE_IP_ADDRESS_ISSUE) self.AutoTerminateUEandeNB() return multi_jobs = [] @@ -1941,7 +1581,7 @@ class OaiCiTest(): job.join() if (status_queue.empty()): - self.CreateHtmlTestRow(self.ping_args, 'KO', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.ping_args, 'KO', ALL_PROCESSES_OK) self.AutoTerminateUEandeNB() else: ping_status = True @@ -1956,9 +1596,9 @@ class OaiCiTest(): html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' html_queue.put(html_cell) if (ping_status): - self.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) else: - self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) self.AutoTerminateUEandeNB() def Iperf_ComputeTime(self): @@ -2347,6 +1987,7 @@ class OaiCiTest(): def Iperf_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue): try: + logging.debug('entring Iperf_common') # Single-UE profile -- iperf only on one UE if self.iperf_profile == 'single-ue' and idx != 0: return @@ -2520,9 +2161,9 @@ class OaiCiTest(): SSH.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, EPC.GetSourceCodePath() + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') SSH.command('fromdos -o iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) # fromdos has to be called on the python executor not on ADB server - cmd = 'fromdos -o iperf_server_' + self.testCase_id + '_' + device_id + '.log' - subprocess.run(cmd, shell=True) - self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) + cmd = 'fromdos -o iperf_server_' + self.testCase_id + '_' + device_id + '.log' + subprocess.run(cmd, shell=True) + self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) # in case of OAI UE: if (device_id == 'OAI-UE'): @@ -2543,14 +2184,14 @@ class OaiCiTest(): check_OAI_UE = True pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) + HTML.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) self.AutoTerminateUEandeNB() return server_on_enb = re.search('-R', str(self.iperf_args)) if server_on_enb is not None: - iServerIPAddr = RAN.GeteNBIPAddress - iServerUser = RAN.GeteNBUserName - iServerPasswd = RAN.GeteNBPassword + iServerIPAddr = RAN.GeteNBIPAddress() + iServerUser = RAN.GeteNBUserName() + iServerPasswd = RAN.GeteNBPassword() iClientIPAddr = self.UEIPAddress iClientUser = self.UEUserName iClientPasswd = self.UEPassword @@ -2558,9 +2199,9 @@ class OaiCiTest(): iServerIPAddr = self.UEIPAddress iServerUser = self.UEUserName iServerPasswd = self.UEPassword - iClientIPAddr = RAN.GeteNBIPAddress - iClientUser = RAN.GeteNBUserName - iClientPasswd = RAN.GeteNBPassword + iClientIPAddr = RAN.GeteNBIPAddress() + iClientUser = RAN.GeteNBUserName() + iClientPasswd = RAN.GeteNBPassword() if self.iperf_options != 'sink': # Starting the iperf server SSH.open(iServerIPAddr, iServerUser, iServerPasswd) @@ -2637,11 +2278,11 @@ class OaiCiTest(): html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' html_queue.put(html_cell) if (iperf_noperf and iperf_status): - self.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) elif (iperf_status): - self.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) else: - self.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) self.AutoTerminateUEandeNB() def Iperf(self): @@ -2659,12 +2300,13 @@ class OaiCiTest(): check_OAI_UE = False pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) + HTML.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) self.AutoTerminateUEandeNB() return ueIpStatus = self.GetAllUEIPAddresses() if (ueIpStatus < 0): - self.CreateHtmlTestRow(self.iperf_args, 'KO', UE_IP_ADDRESS_ISSUE) + logging.debug('going here') + HTML.CreateHtmlTestRow(self.iperf_args, 'KO', UE_IP_ADDRESS_ISSUE) self.AutoTerminateUEandeNB() return @@ -2684,9 +2326,10 @@ class OaiCiTest(): ue_num = len(self.UEIPAddresses) lock = Lock() status_queue = SimpleQueue() + logging.debug('ue_num = ' + str(ue_num)) for UE_IPAddress in self.UEIPAddresses: device_id = self.UEDevices[i] - p = Process(target = CiTestObj.Iperf_common, args = (lock,UE_IPAddress,device_id,i,ue_num,status_queue,)) + p = Process(target = self.Iperf_common, args = (lock,UE_IPAddress,device_id,i,ue_num,status_queue,)) p.daemon = True p.start() multi_jobs.append(p) @@ -2695,7 +2338,7 @@ class OaiCiTest(): job.join() if (status_queue.empty()): - self.CreateHtmlTestRow(self.iperf_args, 'KO', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.iperf_args, 'KO', ALL_PROCESSES_OK) self.AutoTerminateUEandeNB() else: iperf_status = True @@ -2713,11 +2356,11 @@ class OaiCiTest(): html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' html_queue.put(html_cell) if (iperf_noperf and iperf_status): - self.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) elif (iperf_status): - self.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) else: - self.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) self.AutoTerminateUEandeNB() def CheckProcessExist(self, check_eNB, check_OAI_UE): @@ -2743,12 +2386,12 @@ class OaiCiTest(): if (check_eNB == False) and (check_OAI_UE == False): return 0 if check_eNB: - p = Process(target = CiTestObj.CheckeNBProcess, args = (status_queue,)) + p = Process(target = RAN.CheckeNBProcess, args = (status_queue,)) p.daemon = True p.start() multi_jobs.append(p) if check_OAI_UE: - p = Process(target = CiTestObj.CheckOAIUEProcess, args = (status_queue,)) + p = Process(target = self.CheckOAIUEProcess, args = (status_queue,)) p.daemon = True p.start() multi_jobs.append(p) @@ -2766,7 +2409,7 @@ class OaiCiTest(): if result == ENB_PROCESS_FAILED: fileCheck = re.search('enb_', str(RAN.GeteNBLogFiles[0])) if fileCheck is not None: - SSH.copyin(RAN.GeteNBIPAddress, RAN.GeteNBUserName, RAN.GeteNBPassword, RAN.GeteNBSourceCodePath() + '/cmake_targets/' + RAN.GeteNBLogFiles[0], '.') + SSH.copyin(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath() + '/cmake_targets/' + RAN.GeteNBLogFiles[0], '.') logStatus = self.AnalyzeLogFile_eNB(RAN.GeteNBLogFiles[0]) if logStatus < 0: result = logStatus @@ -2779,7 +2422,7 @@ class OaiCiTest(): multi_jobs = [] status_queue = SimpleQueue() if initialize_OAI_UE_flag == False: - p = Process(target = CiTestObj.CheckOAIUEProcess, args = (status_queue,)) + p = Process(target = self.CheckOAIUEProcess, args = (status_queue,)) p.daemon = True p.start() multi_jobs.append(p) @@ -2816,293 +2459,10 @@ class OaiCiTest(): SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) -''' - def CheckeNBProcess(self, status_queue): - try: - # At least the instance 0 SHALL be on! - if self.eNBstatuses[0] == 0: - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - elif self.eNBstatuses[0] == 1: - lIpAddr = self.eNB1IPAddress - lUserName = self.eNB1UserName - lPassWord = self.eNB1Password - elif self.eNBstatuses[0] == 2: - lIpAddr = self.eNB2IPAddress - lUserName = self.eNB2UserName - lPassWord = self.eNB2Password - else: - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - SSH.open(lIpAddr, lUserName, lPassWord) - SSH.command('stdbuf -o0 ps -aux | grep --color=never ' + self.air_interface + '-softmodem | grep -v grep', '\$', 5) - result = re.search(self.air_interface + '-softmodem', SSH.getBefore()) - if result is None: - logging.debug('\u001B[1;37;41m eNB Process Not Found! \u001B[0m') - status_queue.put(ENB_PROCESS_FAILED) - else: - status_queue.put(ENB_PROCESS_OK) - SSH.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) -''' - def AnalyzeLogFile_eNB(self, eNBlogFile): - if (not os.path.isfile('./' + eNBlogFile)): - return -1 - enb_log_file = open('./' + eNBlogFile, 'r') - exitSignalReceived = False - foundAssertion = False - msgAssertion = '' - msgLine = 0 - foundSegFault = False - foundRealTimeIssue = False - rrcSetupComplete = 0 - rrcReleaseRequest = 0 - rrcReconfigRequest = 0 - rrcReconfigComplete = 0 - rrcReestablishRequest = 0 - rrcReestablishComplete = 0 - rrcReestablishReject = 0 - rlcDiscardBuffer = 0 - rachCanceledProcedure = 0 - uciStatMsgCount = 0 - pdcpFailure = 0 - ulschFailure = 0 - cdrxActivationMessageCount = 0 - dropNotEnoughRBs = 0 - mbmsRequestMsg = 0 - self.htmleNBFailureMsg = '' - isRRU = False - isSlave = False - slaveReceivesFrameResyncCmd = False - X2HO_state = X2_HO_REQ_STATE__IDLE - X2HO_inNbProcedures = 0 - X2HO_outNbProcedures = 0 - for line in enb_log_file.readlines(): - if X2HO_state == X2_HO_REQ_STATE__IDLE: - result = re.search('target eNB Receives X2 HO Req X2AP_HANDOVER_REQ', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__TARGET_RECEIVES_REQ - result = re.search('source eNB receives the X2 HO ACK X2AP_HANDOVER_REQ_ACK', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK - if X2HO_state == X2_HO_REQ_STATE__TARGET_RECEIVES_REQ: - result = re.search('Received LTE_RRCConnectionReconfigurationComplete from UE', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE - if X2HO_state == X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE: - result = re.search('issue rrc_eNB_send_PATH_SWITCH_REQ', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ - if X2HO_state == X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ: - result = re.search('received path switch ack S1AP_PATH_SWITCH_REQ_ACK', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__IDLE - X2HO_inNbProcedures += 1 - if X2HO_state == X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK: - result = re.search('source eNB receives the X2 UE CONTEXT RELEASE X2AP_UE_CONTEXT_RELEASE', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__IDLE - X2HO_outNbProcedures += 1 - if RAN.SeteNBOptions[int(RAN.GeteNB_instance())] != '': - res1 = re.search('max_rxgain (?P[0-9]+)', RAN.GeteNBOptions[int(RAN.GeteNB_instance())]) - res2 = re.search('max_rxgain (?P[0-9]+)', str(line)) - if res1 is not None and res2 is not None: - requested_option = int(res1.group('requested_option')) - applied_option = int(res2.group('applied_option')) - if requested_option == applied_option: - self.htmleNBFailureMsg += ' Command line option(s) correctly applied ' + RAN.GeteNBOptions[int(RAN.GeteNB_instance())] + '\n\n' - else: - self.htmleNBFailureMsg += ' Command line option(s) NOT applied ' + RAN.GeteNBOptions[int(RAN.GeteNB_instance())] + '\n\n' - result = re.search('Exiting OAI softmodem', str(line)) - if result is not None: - exitSignalReceived = True - result = re.search('[Ss]egmentation [Ff]ault', str(line)) - 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('./ran_build/build/lte-softmodem', str(line)) - if result is not None and not exitSignalReceived: - foundSegFault = True - result = re.search('[Aa]ssertion', str(line)) - if result is not None and not exitSignalReceived: - foundAssertion = True - result = re.search('LLL', str(line)) - if result is not None and not exitSignalReceived: - foundRealTimeIssue = True - if foundAssertion and (msgLine < 3): - msgLine += 1 - msgAssertion += str(line) - result = re.search('Setting function for RU', str(line)) - if result is not None: - isRRU = True - if isRRU: - result = re.search('RU 0 is_slave=yes', str(line)) - if result is not None: - isSlave = True - if isSlave: - result = re.search('Received RRU_frame_resynch command', str(line)) - if result is not None: - slaveReceivesFrameResyncCmd = True - result = re.search('LTE_RRCConnectionSetupComplete from UE', str(line)) - if result is not None: - rrcSetupComplete += 1 - result = re.search('Generate LTE_RRCConnectionRelease|Generate RRCConnectionRelease', str(line)) - if result is not None: - rrcReleaseRequest += 1 - result = re.search('Generate LTE_RRCConnectionReconfiguration', str(line)) - if result is not None: - rrcReconfigRequest += 1 - result = re.search('LTE_RRCConnectionReconfigurationComplete from UE rnti', str(line)) - if result is not None: - rrcReconfigComplete += 1 - result = re.search('LTE_RRCConnectionReestablishmentRequest', str(line)) - if result is not None: - rrcReestablishRequest += 1 - result = re.search('LTE_RRCConnectionReestablishmentComplete', str(line)) - if result is not None: - rrcReestablishComplete += 1 - result = re.search('LTE_RRCConnectionReestablishmentReject', str(line)) - if result is not None: - rrcReestablishReject += 1 - result = re.search('CDRX configuration activated after RRC Connection', str(line)) - if result is not None: - cdrxActivationMessageCount += 1 - result = re.search('uci->stat', str(line)) - if result is not None: - uciStatMsgCount += 1 - result = re.search('PDCP.*Out of Resources.*reason', str(line)) - if result is not None: - pdcpFailure += 1 - result = re.search('ULSCH in error in round', str(line)) - if result is not None: - ulschFailure += 1 - result = re.search('BAD all_segments_received', str(line)) - if result is not None: - rlcDiscardBuffer += 1 - 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 - if RAN.GeteNBmbmsEnables[int(RAN.GeteNB_instance())]: - result = re.search('MBMS USER-PLANE.*Requesting.*bytes from RLC', str(line)) - if result is not None: - mbmsRequestMsg += 1 - enb_log_file.close() - logging.debug(' File analysis completed') - self.htmleNBFailureMsg = '' - if RAN.Getair_interface() == 'lte': - nodeB_prefix = 'e' - else: - nodeB_prefix = 'g' - if uciStatMsgCount > 0: - statMsg = nodeB_prefix + 'NB showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmleNBFailureMsg += statMsg + '\n' - if pdcpFailure > 0: - statMsg = nodeB_prefix + 'NB showed ' + str(pdcpFailure) + ' "PDCP Out of Resources" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmleNBFailureMsg += statMsg + '\n' - if ulschFailure > 0: - statMsg = nodeB_prefix + 'NB 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 = nodeB_prefix + 'NB completed ' + str(rrcSetupComplete) + ' RRC Connection Setup(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - rrcMsg = ' -- ' + str(rrcSetupComplete) + ' were completed' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if rrcReleaseRequest > 0: - rrcMsg = nodeB_prefix + 'NB requested ' + str(rrcReleaseRequest) + ' RRC Connection Release(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if rrcReconfigRequest > 0 or rrcReconfigComplete > 0: - rrcMsg = nodeB_prefix + 'NB requested ' + str(rrcReconfigRequest) + ' RRC Connection Reconfiguration(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - rrcMsg = ' -- ' + str(rrcReconfigComplete) + ' were completed' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if rrcReestablishRequest > 0 or rrcReestablishComplete > 0 or rrcReestablishReject > 0: - rrcMsg = nodeB_prefix + 'NB requested ' + str(rrcReestablishRequest) + ' RRC Connection Reestablishment(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - rrcMsg = ' -- ' + str(rrcReestablishComplete) + ' were completed' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - rrcMsg = ' -- ' + str(rrcReestablishReject) + ' were rejected' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if RAN.GeteNBmbmsEnables[int(RAN.GeteNB_instance())]: - if mbmsRequestMsg > 0: - rrcMsg = 'eNB requested ' + str(mbmsRequestMsg) + ' times the RLC for MBMS USER-PLANE' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if X2HO_inNbProcedures > 0: - rrcMsg = 'eNB completed ' + str(X2HO_inNbProcedures) + ' X2 Handover Connection procedure(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if X2HO_outNbProcedures > 0: - rrcMsg = 'eNB completed ' + str(X2HO_outNbProcedures) + ' X2 Handover Release procedure(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if RAN.SeteNBOptions[int(RAN.GeteNB_instance())] != '': - res1 = re.search('drx_Config_present prSetup', RAN.GeteNBOptions[int(RAN.GeteNB_instance())]) - if res1 is not None: - if cdrxActivationMessageCount > 0: - rrcMsg = 'eNB activated the CDRX Configuration for ' + str(cdrxActivationMessageCount) + ' time(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - else: - rrcMsg = 'eNB did NOT ACTIVATE the CDRX Configuration' - logging.debug('\u001B[1;37;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if rachCanceledProcedure > 0: - rachMsg = nodeB_prefix + 'NB cancelled ' + str(rachCanceledProcedure) + ' RA procedure(s)' - logging.debug('\u001B[1;30;43m ' + rachMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rachMsg + '\n' - if isRRU: - if isSlave: - if slaveReceivesFrameResyncCmd: - rruMsg = 'Slave RRU received the RRU_frame_resynch command from RAU' - logging.debug('\u001B[1;30;43m ' + rruMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rruMsg + '\n' - else: - rruMsg = 'Slave RRU DID NOT receive the RRU_frame_resynch command from RAU' - logging.debug('\u001B[1;37;41m ' + rruMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rruMsg + '\n' - self.prematureExit = True - return ENB_PROCESS_SLAVE_RRU_NOT_SYNCED - if foundSegFault: - logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB ended with a Segmentation Fault! \u001B[0m') - return ENB_PROCESS_SEG_FAULT - if foundAssertion: - logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB ended with an assertion! \u001B[0m') - self.htmleNBFailureMsg += msgAssertion - return ENB_PROCESS_ASSERTION - if foundRealTimeIssue: - logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB faced real time issues! \u001B[0m') - self.htmleNBFailureMsg += nodeB_prefix + 'NB faced real time issues!\n' - #return ENB_PROCESS_REALTIME_ISSUE - if rlcDiscardBuffer > 0: - rlcMsg = nodeB_prefix + 'NB RLC discarded ' + str(rlcDiscardBuffer) + ' buffer(s)' - logging.debug('\u001B[1;37;41m ' + rlcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rlcMsg + '\n' - return ENB_PROCESS_REALTIME_ISSUE - return 0 + +# def AnalyzeLogFile_eNB(self, eNBlogFile): +# ... def AnalyzeLogFile_UE(self, UElogFile): if (not os.path.isfile('./' + UElogFile)): @@ -3354,104 +2714,8 @@ class OaiCiTest(): self.htmlUEFailureMsg += 'UE could not synchronize!\n' return OAI_UE_PROCESS_COULD_NOT_SYNC return 0 -''' - def TerminateeNB(self): - if self.eNB_serverId == '0': - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - lSourcePath = RAN.GeteNBSourceCodePath() - elif self.eNB_serverId == '1': - lIpAddr = self.eNB1IPAddress - lUserName = self.eNB1UserName - lPassWord = self.eNB1Password - lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId == '2': - lIpAddr = self.eNB2IPAddress - lUserName = self.eNB2UserName - lPassWord = self.eNB2Password - lSourcePath = self.eNB2SourceCodePath - if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - SSH.open(lIpAddr, lUserName, lPassWord) - SSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) - if self.air_interface == 'lte': - nodeB_prefix = 'e' - else: - nodeB_prefix = 'g' - SSH.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('-softmodem', SSH.getBefore()) - if result is not None: - SSH.command('echo ' + lPassWord + ' | sudo -S daemon --name=enb' + str(self.eNB_instance) + '_daemon --stop', '\$', 5) - SSH.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGINT -r .*-softmodem || true', '\$', 5) - time.sleep(10) - SSH.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('-softmodem', SSH.getBefore()) - if result is not None: - SSH.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGKILL -r .*-softmodem || true', '\$', 5) - time.sleep(5) - SSH.command('rm -f my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - SSH.close() - # If tracer options is on, stopping tshark on EPC side - result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args())) - if result is not None: - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - logging.debug('\u001B[1m Stopping tshark \u001B[0m') - SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) - time.sleep(1) - if EPC.EPC_PcapFileName != '': - SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S chmod 666 /tmp/' + EPC.EPC_PcapFileName , '\$', 5) - SSH.copyin(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), '/tmp/' + EPC.EPC_PcapFileName , '.') - SSH.copyout(lIpAddr, lUserName, lPassWord, EPC.EPC_PcapFileName , lSourcePath + '/cmake_targets/.') - SSH.close() - logging.debug('\u001B[1m Replaying RAW record file\u001B[0m') - SSH.open(lIpAddr, lUserName, lPassWord) - SSH.command('cd ' + lSourcePath + '/common/utils/T/tracer/', '\$', 5) - enbLogFile = self.eNBLogFiles[int(self.eNB_instance)] - raw_record_file = enbLogFile.replace('.log', '_record.raw') - replay_log_file = enbLogFile.replace('.log', '_replay.log') - extracted_txt_file = enbLogFile.replace('.log', '_extracted_messages.txt') - extracted_log_file = enbLogFile.replace('.log', '_extracted_messages.log') - SSH.command('./extract_config -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + extracted_txt_file, '\$', 5) - SSH.command('echo $USER; nohup ./replay -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + replay_log_file + ' 2>&1 &', lUserName, 5) - SSH.command('./textlog -d ' + lSourcePath + '/cmake_targets/' + extracted_txt_file + ' -no-gui -ON -full > ' + lSourcePath + '/cmake_targets/' + extracted_log_file, '\$', 5) - SSH.close() - SSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + extracted_log_file, '.') - logging.debug('\u001B[1m Analyzing eNB replay logfile \u001B[0m') - logStatus = self.AnalyzeLogFile_eNB(extracted_log_file) - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - self.eNBLogFiles[int(self.eNB_instance)] = '' - else: - analyzeFile = False - if self.eNBLogFiles[int(self.eNB_instance)] != '': - analyzeFile = True - fileToAnalyze = self.eNBLogFiles[int(self.eNB_instance)] - self.eNBLogFiles[int(self.eNB_instance)] = '' - if analyzeFile: - copyin_res = SSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + fileToAnalyze, '.') - if (copyin_res == -1): - logging.debug('\u001B[1;37;41m Could not copy ' + nodeB_prefix + 'NB logfile to analyze it! \u001B[0m') - self.htmleNBFailureMsg = 'Could not copy ' + nodeB_prefix + 'NB logfile to analyze it!' - self.CreateHtmlTestRow('N/A', 'KO', ENB_PROCESS_NOLOGFILE_TO_ANALYZE) - self.eNBmbmsEnables[int(self.eNB_instance)] = False - return - if self.eNB_serverId != '0': - SSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './' + fileToAnalyze, RAN.GeteNBSourceCodePath() + '/cmake_targets/') - logging.debug('\u001B[1m Analyzing ' + nodeB_prefix + 'NB logfile \u001B[0m ' + fileToAnalyze) - logStatus = self.AnalyzeLogFile_eNB(fileToAnalyze) - if (logStatus < 0): - self.CreateHtmlTestRow('N/A', 'KO', logStatus) - self.preamtureExit = True - self.eNBmbmsEnables[int(self.eNB_instance)] = False - return - else: - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - else: - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - self.eNBmbmsEnables[int(self.eNB_instance)] = False - self.eNBstatuses[int(self.eNB_instance)] = -1 -''' + + def TerminateFlexranCtrl(self): if self.flexranCtrlInstalled == False or self.flexranCtrlStarted == False: return @@ -3465,7 +2729,7 @@ class OaiCiTest(): time.sleep(1) SSH.close() self.flexranCtrlStarted = False - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) def TerminateUE_common(self, device_id, idx): try: @@ -3496,19 +2760,19 @@ class OaiCiTest(): os.kill(os.getppid(),signal.SIGUSR1) def TerminateUE(self): - terminate_ue_flag = True + terminate_ue_flag = False self.GetAllUEDevices(terminate_ue_flag) multi_jobs = [] i = 0 for device_id in self.UEDevices: - p = Process(target= CiTestObj.TerminateUE_common, args = (device_id,i,)) + p = Process(target= self.TerminateUE_common, args = (device_id,i,)) p.daemon = True p.start() multi_jobs.append(p) i += 1 for job in multi_jobs: job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) def TerminateOAIUE(self): SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) @@ -3531,7 +2795,7 @@ class OaiCiTest(): if (copyin_res == -1): logging.debug('\u001B[1;37;41m Could not copy UE logfile to analyze it! \u001B[0m') self.htmlUEFailureMsg = 'Could not copy UE logfile to analyze it!' - self.CreateHtmlTestRow('N/A', 'KO', OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE, 'UE') + HTML.CreateHtmlTestRow('N/A', 'KO', OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE, 'UE') self.UELogFile = '' return logging.debug('\u001B[1m Analyzing UE logfile \u001B[0m') @@ -3544,7 +2808,7 @@ class OaiCiTest(): if (logStatus < 0): logging.debug('\u001B[1m' + ueAction + ' Failed \u001B[0m') self.htmlUEFailureMsg = '' + ueAction + ' Failed\n' + self.htmlUEFailureMsg - self.CreateHtmlTestRow('N/A', 'KO', logStatus, 'UE') + HTML.CreateHtmlTestRow('N/A', 'KO', logStatus, 'UE') if RAN.Getair_interface() == 'lte': # In case of sniffing on commercial eNBs we have random results # Not an error then @@ -3558,38 +2822,42 @@ class OaiCiTest(): else: logging.debug('\u001B[1m' + ueAction + ' Completed \u001B[0m') self.htmlUEFailureMsg = '' + ueAction + ' Completed\n' + self.htmlUEFailureMsg - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) self.UELogFile = '' else: - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) def AutoTerminateUEandeNB(self): if (self.ADBIPAddress != 'none'): self.testCase_id = 'AUTO-KILL-UE' + RAN.SettestCase_id(self.testCase_id) self.desc = 'Automatic Termination of UE' self.ShowTestID() self.TerminateUE() if (self.Initialize_OAI_UE_args != ''): self.testCase_id = 'AUTO-KILL-UE' + RAN.SettestCase_id(self.testCase_id) self.desc = 'Automatic Termination of UE' self.ShowTestID() self.TerminateOAIUE() if (RAN.GetInitialize_eNB_args() != ''): self.testCase_id = 'AUTO-KILL-eNB' + RAN.SettestCase_id(self.testCase_id) self.desc = 'Automatic Termination of eNB' self.ShowTestID() - RAN.SeteNB_instance() = '0' - self.TerminateeNB() + RAN.SeteNB_instance('0') + RAN.TerminateeNB() if self.flexranCtrlInstalled and self.flexranCtrlStarted: self.testCase_id = 'AUTO-KILL-flexran-ctl' + RAN.SettestCase_id(self.testCase_id) self.desc = 'Automatic Termination of FlexRan CTL' self.ShowTestID() self.TerminateFlexranCtrl() - self.prematureExit = True + RAN.SetprematureExit(True) def IdleSleep(self): time.sleep(self.idle_sleep_time) - self.CreateHtmlTestRow(str(self.idle_sleep_time) + ' sec', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(str(self.idle_sleep_time) + ' sec', 'OK', ALL_PROCESSES_OK) def X2_Status(self, idx, fileName): cmd = "curl --silent http://" + EPC.GetIPAddress() + ":9999/stats | jq '.' > " + fileName @@ -3691,21 +2959,21 @@ class OaiCiTest(): logging.debug(msg) fullMessage += msg + '' html_queue.put(fullMessage) - self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) else: msg = "X2 Handover FAILED" logging.error(msg) fullMessage += msg + '' html_queue.put(fullMessage) - self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) else: - self.CreateHtmlTestRow('Cannot perform requested X2 Handover', 'KO', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('Cannot perform requested X2 Handover', 'KO', ALL_PROCESSES_OK) def LogCollectBuild(self): if (RAN.GeteNBIPAddress() != '' and RAN.GeteNBUserName() != '' and RAN.GeteNBPassword() != ''): - IPAddress = RAN.GeteNBIPAddress - UserName = RAN.GeteNBUserName - Password = RAN.GeteNBPassword + IPAddress = RAN.GeteNBIPAddress() + UserName = RAN.GeteNBUserName() + Password = RAN.GeteNBPassword() SourceCodePath = RAN.GeteNBSourceCodePath() elif (self.UEIPAddress != '' and self.UEUserName != '' and self.UEPassword != ''): IPAddress = self.UEIPAddress @@ -3720,16 +2988,6 @@ class OaiCiTest(): SSH.command('rm -f build.log.zip', '\$', 5) SSH.command('zip build.log.zip build_log_*/*', '\$', 60) SSH.close() -''' - def LogCollecteNB(self): - SSH.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) - SSH.command('cd ' + RAN.GeteNBSourceCodePath(), '\$', 5) - SSH.command('cd cmake_targets', '\$', 5) - SSH.command('echo ' + self.eNBPassword + ' | sudo -S rm -f enb.log.zip', '\$', 5) - SSH.command('echo ' + self.eNBPassword + ' | sudo -S zip enb.log.zip enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 60) - SSH.command('echo ' + self.eNBPassword + ' | sudo -S rm enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 5) - SSH.close() -''' def LogCollectPing(self): SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) SSH.command('cd ' + EPC.GetSourceCodePath(), '\$', 5) @@ -3769,9 +3027,9 @@ class OaiCiTest(): return 0 if machine == 'eNB': if RAN.GeteNBIPAddress() != '' and RAN.GeteNBUserName() != '' and RAN.GeteNBPassword() != '': - IPAddress = RAN.GeteNBIPAddress - UserName = RAN.GeteNBUserName - Password = RAN.GeteNBPassword + IPAddress = RAN.GeteNBIPAddress() + UserName = RAN.GeteNBUserName() + Password = RAN.GeteNBPassword() else: return -1 if machine == 'UE': @@ -3837,335 +3095,6 @@ class OaiCiTest(): logging.debug('cpu_mhz: ' + self.CpuMHz) SSH.close() -#----------------------------------------------------------- -# HTML Reporting.... -#----------------------------------------------------------- - def CreateHtmlHeader(self): - if (not self.htmlHeaderCreated): - logging.debug('\u001B[1m----------------------------------------\u001B[0m') - logging.debug('\u001B[1m Creating HTML header \u001B[0m') - logging.debug('\u001B[1m----------------------------------------\u001B[0m') - self.htmlFile = open('test_results.html', 'w') - self.htmlFile.write('\n') - self.htmlFile.write('\n') - self.htmlFile.write('\n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' Test Results for TEMPLATE_JOB_NAME job build #TEMPLATE_BUILD_ID\n') - self.htmlFile.write('\n') - self.htmlFile.write('
\n') - self.htmlFile.write('
\n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write('
\n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' Job Summary -- Job: TEMPLATE_JOB_NAME -- Build-ID: TEMPLATE_BUILD_ID\n') - self.htmlFile.write('
\n') - self.htmlFile.write('
\n') - self.htmlFile.write('
TEMPLATE_STAGE_NAME
\n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (RAN.GetranAllowMerge): - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (RAN.GetranAllowMerge): - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (RAN.GetranAllowMerge): - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if RAN.GetranAllowMerge() != '': - commit_message = subprocess.check_output("git log -n1 --pretty=format:\"%s\" " + RAN.GetranCommitID, shell=True, universal_newlines=True) - commit_message = commit_message.strip() - self.htmlFile.write(' \n') - if (RAN.GetranAllowMerge): - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (RAN.GetranAllowMerge): - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (RAN.GetranTargetBranch() == ''): - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write('
Build Start Time (UTC) TEMPLATE_BUILD_TIME
GIT Repository ' + RAN.GetranRepository() + '
Job Trigger Merge-RequestPush to Branch
Source Branch Branch' + RAN.GetranBranch() + '
Source Commit ID Commit ID ' + RAN.GetranCommitID() + '
Source Commit Message Commit Message ' + commit_message + '
Target Branch develop' + RAN.GetranTargetBranch() + '
\n') - - if (self.ADBIPAddress != 'none'): - terminate_ue_flag = True - self.GetAllUEDevices(terminate_ue_flag) - self.GetAllCatMDevices(terminate_ue_flag) - self.htmlUEConnected = len(self.UEDevices) - self.htmlFile.write('

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

\n') - self.htmlFile.write('

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

\n') - else: - self.UEDevices.append('OAI-UE') - self.htmlUEConnected = len(self.UEDevices) - self.htmlFile.write('

' + str(len(self.UEDevices)) + ' OAI UE(s) is(are) connected to CI bench

\n') - self.htmlFile.write('
\n') - self.htmlFile.write(' \n') - self.htmlFile.write('
\n') - self.htmlFile.close() - - def CreateHtmlTabHeader(self): - if (not self.htmlHeaderCreated): - if (not os.path.isfile('test_results.html')): - self.CreateHtmlHeader() - self.htmlFile = open('test_results.html', 'a') - if (self.nbTestXMLfiles == 1): - self.htmlFile.write('
\n') - self.htmlFile.write('

Test Summary for ' + self.testXMLfiles[0] + '

\n') - else: - self.htmlFile.write('
\n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (self.htmlUEConnected == -1): - terminate_ue_flag = True - if (self.ADBIPAddress != 'none'): - self.GetAllUEDevices(terminate_ue_flag) - self.GetAllCatMDevices(terminate_ue_flag) - else: - self.UEDevices.append('OAI-UE') - self.htmlUEConnected = len(self.UEDevices) - - i = 0 - while (i < self.htmlUEConnected): - self.htmlFile.write(' \n') - i += 1 - self.htmlFile.write(' \n') - self.htmlHeaderCreated = True - - def CreateHtmlTabFooter(self, passStatus): - if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if passStatus: - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write('
Relative Time (ms)Test IdTest DescTest OptionsTest StatusUE' + str(i) + ' Status
Final Tab StatusPASS FAIL
\n') - self.htmlFile.write('
\n') - self.htmlFile.close() - time.sleep(1) - if passStatus: - cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__//' test_results.html" - subprocess.run(cmd, shell=True) - else: - cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__/<\/span>/' test_results.html" - subprocess.run(cmd, shell=True) - self.htmlFooterCreated = False - - def CreateHtmlFooter(self, passStatus): - if (os.path.isfile('test_results.html')): - logging.debug('\u001B[1m----------------------------------------\u001B[0m') - logging.debug('\u001B[1m Creating HTML footer \u001B[0m') - logging.debug('\u001B[1m----------------------------------------\u001B[0m') - - self.htmlFile = open('test_results.html', 'a') - self.htmlFile.write('
\n') - self.htmlFile.write('

\n') - self.htmlFile.write(' \n') - - machines = [ 'eNB', 'UE' ] - for machine in machines: - res = self.RetrieveSystemVersion(machine) - if res == -1: - continue - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if passStatus: - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write('
' + str(machine) + ' Server Characteristics
OS Version' + self.OsVersion + 'Kernel Version' + self.KernelVersion + 'UHD Version' + self.UhdVersion + 'USRP Board' + self.UsrpBoard + '
Nb CPUs' + self.CpuNb + 'CPU Model Name' + self.CpuModel + 'CPU Frequency' + self.CpuMHz + '
Final StatusPASS FAIL
\n') - self.htmlFile.write('

\n') - self.htmlFile.write('
End of Test Report -- Copyright 2018 OpenAirInterface. All Rights Reserved.
\n') - self.htmlFile.write('
\n') - self.htmlFile.write('\n') - self.htmlFile.close() - - def CreateHtmlRetrySeparator(self): - if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): - self.htmlFile.write(' \n') - self.htmlFile.write(' Try Run #' + str(self.FailReportCnt) + '\n') - self.htmlFile.write(' \n') - - def CreateHtmlTestRow(self, options, status, processesStatus, machine='eNB'): - if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): - currentTime = int(round(time.time() * 1000)) - self.startTime - self.htmlFile.write(' \n') - self.htmlFile.write(' ' + format(currentTime / 1000, '.1f') + '\n') - self.htmlFile.write(' ' + self.testCase_id + '\n') - self.htmlFile.write(' ' + self.desc + '\n') - self.htmlFile.write(' ' + str(options) + '\n') - if (str(status) == 'OK'): - self.htmlFile.write(' ' + str(status) + '\n') - elif (str(status) == 'KO'): - if (processesStatus == 0): - self.htmlFile.write(' ' + str(status) + '\n') - elif (processesStatus == ENB_PROCESS_FAILED): - self.htmlFile.write(' KO - eNB process not found\n') - elif (processesStatus == OAI_UE_PROCESS_FAILED): - self.htmlFile.write(' KO - OAI UE process not found\n') - elif (processesStatus == ENB_PROCESS_SEG_FAULT) or (processesStatus == OAI_UE_PROCESS_SEG_FAULT): - self.htmlFile.write(' KO - ' + machine + ' process ended in Segmentation Fault\n') - elif (processesStatus == ENB_PROCESS_ASSERTION) or (processesStatus == OAI_UE_PROCESS_ASSERTION): - self.htmlFile.write(' KO - ' + machine + ' process ended in Assertion\n') - elif (processesStatus == ENB_PROCESS_REALTIME_ISSUE): - self.htmlFile.write(' KO - ' + machine + ' process faced Real Time issue(s)\n') - elif (processesStatus == ENB_PROCESS_NOLOGFILE_TO_ANALYZE) or (processesStatus == OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE): - self.htmlFile.write(' OK?\n') - elif (processesStatus == ENB_PROCESS_SLAVE_RRU_NOT_SYNCED): - self.htmlFile.write(' KO - ' + machine + ' Slave RRU could not synch\n') - elif (processesStatus == OAI_UE_PROCESS_COULD_NOT_SYNC): - self.htmlFile.write(' KO - UE could not sync\n') - elif (processesStatus == HSS_PROCESS_FAILED): - self.htmlFile.write(' KO - HSS process not found\n') - elif (processesStatus == MME_PROCESS_FAILED): - self.htmlFile.write(' KO - MME process not found\n') - elif (processesStatus == SPGW_PROCESS_FAILED): - self.htmlFile.write(' KO - SPGW process not found\n') - elif (processesStatus == UE_IP_ADDRESS_ISSUE): - self.htmlFile.write(' KO - Could not retrieve UE IP address\n') - else: - self.htmlFile.write(' ' + str(status) + '\n') - else: - self.htmlFile.write(' ' + str(status) + '\n') - if (len(str(self.htmleNBFailureMsg)) > 2): - cellBgColor = 'white' - result = re.search('ended with|faced real time issues', self.htmleNBFailureMsg) - if result is not None: - cellBgColor = 'red' - else: - result = re.search('showed|Reestablishment|Could not copy eNB logfile', self.htmleNBFailureMsg) - if result is not None: - cellBgColor = 'orange' - self.htmlFile.write('
' + self.htmleNBFailureMsg + '
\n') - self.htmleNBFailureMsg = '' - elif (len(str(self.htmlUEFailureMsg)) > 2): - cellBgColor = 'white' - result = re.search('ended with|faced real time issues', self.htmlUEFailureMsg) - if result is not None: - cellBgColor = 'red' - else: - result = re.search('showed|Could not copy UE logfile|oaitun_ue1 interface is either NOT mounted or NOT configured', self.htmlUEFailureMsg) - if result is not None: - cellBgColor = 'orange' - self.htmlFile.write('
' + self.htmlUEFailureMsg + '
\n') - self.htmlUEFailureMsg = '' - else: - i = 0 - while (i < self.htmlUEConnected): - self.htmlFile.write(' -\n') - i += 1 - self.htmlFile.write(' \n') - - def CreateHtmlTestRowQueue(self, options, status, ue_status, ue_queue): - if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): - currentTime = int(round(time.time() * 1000)) - self.startTime - addOrangeBK = False - self.htmlFile.write(' \n') - self.htmlFile.write(' ' + format(currentTime / 1000, '.1f') + '\n') - self.htmlFile.write(' ' + self.testCase_id + '\n') - self.htmlFile.write(' ' + self.desc + '\n') - self.htmlFile.write(' ' + str(options) + '\n') - if (str(status) == 'OK'): - self.htmlFile.write(' ' + str(status) + '\n') - elif (str(status) == 'KO'): - self.htmlFile.write(' ' + str(status) + '\n') - else: - addOrangeBK = True - self.htmlFile.write(' ' + str(status) + '\n') - i = 0 - while (i < self.htmlUEConnected): - if (i < ue_status): - if (not ue_queue.empty()): - if (addOrangeBK): - self.htmlFile.write(' ' + str(ue_queue.get()).replace('white', 'orange') + '\n') - else: - self.htmlFile.write(' ' + str(ue_queue.get()) + '\n') - else: - self.htmlFile.write(' -\n') - else: - self.htmlFile.write(' -\n') - i += 1 - self.htmlFile.write(' \n') - #----------------------------------------------------------- # ShowTestID() #----------------------------------------------------------- @@ -4183,47 +3112,47 @@ def CheckClassValidity(action,id): def GetParametersFromXML(action): if action == 'Build_eNB': - RAN.SetBuild_eNB_args() = test.findtext('Build_eNB_args') + RAN.SetBuild_eNB_args(test.findtext('Build_eNB_args')) forced_workspace_cleanup = test.findtext('forced_workspace_cleanup') if (forced_workspace_cleanup is None): - RAN.SetBuild_eNB_forced_workspace_cleanup() = False + RAN.SetBuild_eNB_forced_workspace_cleanup(False) else: if re.match('true', forced_workspace_cleanup, re.IGNORECASE): - RAN.SetBuild_eNB_forced_workspace_cleanup() = True + RAN.SetBuild_eNB_forced_workspace_cleanup(True) else: - RAN.SetBuild_eNB_forced_workspace_cleanup() = False - RAN.SeteNB_instance() = test.findtext('eNB_instance') + RAN.SetBuild_eNB_forced_workspace_cleanup(False) + RAN.SeteNB_instance(test.findtext('eNB_instance')) if (RAN.GeteNB_instance() is None): - RAN.SeteNB_instance() = '0' - CiTestObj.eNB_serverId = test.findtext('eNB_serverId') - if (CiTestObj.eNB_serverId is None): - CiTestObj.eNB_serverId = '0' + RAN.SeteNB_instance('0') + RAN.SeteNB_serverId(test.findtext('eNB_serverId')) + if (RAN.GeteNB_serverId() is None): + RAN.SeteNB_serverId('0') xmlBgBuildField = test.findtext('backgroundBuild') if (xmlBgBuildField is None): - RAN.SetbackgroundBuild() = False + RAN.SetbackgroundBuild(False) else: if re.match('true', xmlBgBuildField, re.IGNORECASE): - RAN.SetbackgroundBuild() = True + RAN.SetbackgroundBuild(True) else: - RAN.SetbackgroundBuild() = False + RAN.SetbackgroundBuild(False) if action == 'WaitEndBuild_eNB': - RAN.SetBuild_eNB_args() = test.findtext('Build_eNB_args') - RAN.SeteNB_instance() = test.findtext('eNB_instance') + RAN.SetBuild_eNB_args(test.findtext('Build_eNB_args')) + RAN.SeteNB_instance(test.findtext('eNB_instance')) if (RAN.GeteNB_instance() is None): - RAN.SeteNB_instance() = '0' - CiTestObj.eNB_serverId = test.findtext('eNB_serverId') - if (CiTestObj.eNB_serverId is None): - CiTestObj.eNB_serverId = '0' + RAN.SeteNB_instance('0') + RAN.SeteNB_serverId(test.findtext('eNB_serverId')) + if (RAN.GeteNB_serverId() is None): + RAN.SeteNB_serverId('0') if action == 'Initialize_eNB': - RAN.SetInitialize_eNB_args() = test.findtext('Initialize_eNB_args') - RAN.SeteNB_instance() = test.findtext('eNB_instance') + RAN.SetInitialize_eNB_args(test.findtext('Initialize_eNB_args')) + RAN.SeteNB_instance(test.findtext('eNB_instance')) if (RAN.GeteNB_instance() is None): - RAN.SeteNB_instance = '0' - CiTestObj.eNB_serverId = test.findtext('eNB_serverId') - if (CiTestObj.eNB_serverId is None): - CiTestObj.eNB_serverId = '0' + RAN.SeteNB_instance('0') + RAN.SeteNB_serverId(test.findtext('eNB_serverId')) + if (RAN.GeteNB_serverId() is None): + RAN.SeteNB_serverId('0') CiTestObj.air_interface = test.findtext('air_interface') if (CiTestObj.air_interface is None): CiTestObj.air_interface = 'lte' @@ -4231,12 +3160,12 @@ def GetParametersFromXML(action): CiTestObj.air_interface = CiTestObj.air_interface.lower() if action == 'Terminate_eNB': - RAN.SeteNB_instance() = test.findtext('eNB_instance') + RAN.SeteNB_instance(test.findtext('eNB_instance')) if (RAN.GeteNB_instance() is None): - RAN.SeteNB_instance() = '0' - CiTestObj.eNB_serverId = test.findtext('eNB_serverId') - if (CiTestObj.eNB_serverId is None): - CiTestObj.eNB_serverId = '0' + RAN.SeteNB_instance('0') + RAN.SeteNB_serverId(test.findtext('eNB_serverId')) + if (RAN.GeteNB_serverId() is None): + RAN.SeteNB_serverId('0') CiTestObj.air_interface = test.findtext('air_interface') if (CiTestObj.air_interface is None): CiTestObj.air_interface = 'lte' @@ -4277,7 +3206,7 @@ def GetParametersFromXML(action): CiTestObj.air_interface = SSH.air_interface.lower() if action == 'Terminate_OAI_UE': - RAN.SeteNB_instance = test.findtext('UE_instance') + RAN.SeteNB_instance(test.findtext('UE_instance')) if (CiTestObj.UE_instance is None): CiTestObj.UE_instance = '0' @@ -4340,15 +3269,18 @@ def receive_signal(signum, frame): mode = '' CiTestObj = OaiCiTest() -from sshconnection import * -from epc import * -from helpreadme import * -from enb import * -SSH = SSHConnection() -EPC = EPCManagement() -RAN = RANManagement() -#HELP = HelpReadme() -#HELP.GenericHelp() +import sshconnection +import epc +import helpreadme +import ran +import html +import constants + +SSH = sshconnection.SSHConnection() +EPC = epc.EPCManagement() +RAN = ran.RANManagement() +HTML = html.HTMLManagement() + argvs = sys.argv argc = len(argvs) @@ -4356,6 +3288,7 @@ cwd = os.getcwd() while len(argvs) > 1: myArgv = argvs.pop(1) # 0th is this file's name + if re.match('^\-\-help$', myArgv, re.IGNORECASE): GenericHelp(Version) sys.exit(0) @@ -4367,7 +3300,8 @@ while len(argvs) > 1: matchReg = re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE) else: matchReg = re.match('^\-\-ranRepository=(.+)$', myArgv, re.IGNORECASE) - RAN.SetranRepository() = matchReg.group(1) + RAN.SetranRepository(matchReg.group(1)) + HTML.SetranRepository(matchReg.group(1)) elif re.match('^\-\-eNB_AllowMerge=(.+)$|^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE) @@ -4375,68 +3309,72 @@ while len(argvs) > 1: matchReg = re.match('^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE) doMerge = matchReg.group(1) if ((doMerge == 'true') or (doMerge == 'True')): - RAN.SetranAllowMerge() = True + RAN.SetranAllowMerge(True) + HTML.SetranAllowMerge(True) elif re.match('^\-\-eNBBranch=(.+)$|^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE) else: matchReg = re.match('^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE) - RAN.SetranBranch() = matchReg.group(1) + RAN.SetranBranch(matchReg.group(1)) + HTML.SetranBranch(matchReg.group(1)) elif re.match('^\-\-eNBCommitID=(.*)$|^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE) else: matchReg = re.match('^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE) - RAN.SetranCommitID() = matchReg.group(1) + RAN.SetranCommitID(matchReg.group(1)) + HTML.SetranCommitID(matchReg.group(1)) elif re.match('^\-\-eNBTargetBranch=(.*)$|^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE) else: matchReg = re.match('^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE) - RAN.SetranTargetBranch() = matchReg.group(1) + RAN.SetranTargetBranch(matchReg.group(1)) elif re.match('^\-\-eNBIPAddress=(.+)$|^\-\-eNB[1-2]IPAddress=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNBIPAddress() = matchReg.group(1) + RAN.SeteNBIPAddress(matchReg.group(1)) elif re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB1IPAddress() = matchReg.group(1) + RAN.SeteNB1IPAddress(matchReg.group(1)) elif re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB2IPAddress() = matchReg.group(1) + RAN.SeteNB2IPAddress(matchReg.group(1)) elif re.match('^\-\-eNBUserName=(.+)$|^\-\-eNB[1-2]UserName=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNBUserName() = matchReg.group(1) + RAN.SeteNBUserName(matchReg.group(1)) elif re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB1UserName() = matchReg.group(1) + RAN.SeteNB1UserName(matchReg.group(1)) elif re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB2UserName() = matchReg.group(1) + RAN.SeteNB2UserName(matchReg.group(1)) elif re.match('^\-\-eNBPassword=(.+)$|^\-\-eNB[1-2]Password=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNBPassword() = matchReg.group(1) + RAN.SeteNBPassword(matchReg.group(1)) elif re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB1Password() = matchReg.group(1) + RAN.SeteNB1Password(matchReg.group(1)) elif re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB2Password() = matchReg.group(1) + RAN.SeteNB2Password(matchReg.group(1)) elif re.match('^\-\-eNBSourceCodePath=(.+)$|^\-\-eNB[1-2]SourceCodePath=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNBSourceCodePath() = matchReg.group(1) + RAN.SeteNBSourceCodePath(matchReg.group(1)) elif re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB1SourceCodePath() = matchReg.group(1) + RAN.SeteNB1SourceCodePath(matchReg.group(1)) elif re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB2SourceCodePath() = matchReg.group(1) + RAN.SeteNB2SourceCodePath(matchReg.group(1)) elif re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE) EPC.SetIPAddress(matchReg.group(1)) +#GP250220: do we still need EPCBranch? it's not used anywhere elif re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE) CiTestObj.EPCBranch = matchReg.group(1) @@ -4476,6 +3414,7 @@ while len(argvs) > 1: elif re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE) CiTestObj.testXMLfiles.append(matchReg.group(1)) + HTML.SettestXMLfiles(matchReg.group(1)) CiTestObj.nbTestXMLfiles += 1 elif re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE) @@ -4502,9 +3441,9 @@ if re.match('^TerminateeNB$', mode, re.IGNORECASE): if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '': GenericHelp(Version) sys.exit('Insufficient Parameter') - CiTestObj.eNB_serverId = '0' - RAN.SeteNB_instance = '0' - RAN.GeteNBSourceCodePath() = '/tmp/' + RAN.SeteNB_serverId('0') + RAN.SeteNB_instance('0') + RAN.SeteNBSourceCodePath('/tmp/') CiTestObj.TerminateeNB() elif re.match('^TerminateUE$', mode, re.IGNORECASE): if (CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == ''): @@ -4588,23 +3527,38 @@ elif re.match('^InitiateHtml$', mode, re.IGNORECASE): except: print("Error while parsing file: " + xml_test_file) xmlRoot = xmlTree.getroot() - CiTestObj.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count))) - CiTestObj.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-' + str(count))) - CiTestObj.htmlTabIcons.append(xmlRoot.findtext('htmlTabIcon',default='info-sign')) + HTML.SethtmlTabRefs(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count))) + HTML.SethtmlTabNames(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count))) + HTML.SethtmlTabIcons(xmlRoot.findtext('htmlTabIcon',default='info-sign')) + #CiTestObj.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count))) + #CiTestObj.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-' + str(count))) + #CiTestObj.htmlTabIcons.append(xmlRoot.findtext('htmlTabIcon',default='info-sign')) foundCount += 1 count += 1 if foundCount != CiTestObj.nbTestXMLfiles: CiTestObj.nbTestXMLfiles = foundCount - CiTestObj.CreateHtmlHeader() + HTML.SetnbTestXMLfiles(CiTestObj.nbTestXMLfiles) + + if (CiTestObj.ADBIPAddress != 'none'): + terminate_ue_flag = False + CiTestObj.GetAllUEDevices(terminate_ue_flag) + CiTestObj.GetAllCatMDevices(terminate_ue_flag) + HTML.SethtmlUEConnected(len(CiTestObj.UEDevices) + len(CiTestObj.CatMDevices)) + HTML.SethtmlNb_Smartphones(len(CiTestObj.UEDevices)) + HTML.SethtmlNb_CATM_Modules(len(CiTestObj.CatMDevices)) + HTML.CreateHtmlHeader(CiTestObj.ADBIPAddress) elif re.match('^FinalizeHtml$', mode, re.IGNORECASE): - CiTestObj.CreateHtmlFooter(CiTestObj.finalStatus) + HTML.CreateHtmlFooter(CiTestObj.finalStatus) elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re.IGNORECASE): if re.match('^TesteNB$', mode, re.IGNORECASE): if RAN.GeteNBIPAddress() == '' or RAN.GetranRepository() == '' or RAN.GetranBranch() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '' or EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '' or CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == '': GenericHelp(Version) if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '' or EPC.GetType() == '': EPCSrvHelp(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), EPC.GetSourceCodePath(), EPC.GetType()) - # Gabriele: other if conditions relevant to eNB etc. to be added + if RAN.GetranRepository() == '': + GitSrvHelp(RAN.GetranRepository(),RAN.GetranBranch(),RAN.GetranCommitID(),RAN.GetranAllowMerge(),RAN.GetranTargetBranch()) + if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '': + eNBSrvHelp(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath()) sys.exit('Insufficient Parameter') if (EPC.GetIPAddress() != '') and (EPC.GetIPAddress() != 'none'): @@ -4628,8 +3582,10 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re exclusion_tests=xmlRoot.findtext('TestCaseExclusionList',default='') requested_tests=xmlRoot.findtext('TestCaseRequestedList',default='') if (CiTestObj.nbTestXMLfiles == 1): - CiTestObj.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-0')) - CiTestObj.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-0')) + HTML.SethtmlTabRefs(xmlRoot.findtext('htmlTabRef',default='test-tab-0')) + HTML.SethtmlTabNames(xmlRoot.findtext('htmlTabName',default='Test-0')) + #CiTestObj.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-0')) + #CiTestObj.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-0')) repeatCount = xmlRoot.findtext('repeatCount',default='1') CiTestObj.repeatCounts.append(int(repeatCount)) all_tests=xmlRoot.findall('testCase') @@ -4671,26 +3627,38 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re signal.signal(signal.SIGUSR1, receive_signal) - CiTestObj.CreateHtmlTabHeader() + if (CiTestObj.ADBIPAddress != 'none'): + terminate_ue_flag = False + CiTestObj.GetAllUEDevices(terminate_ue_flag) + CiTestObj.GetAllCatMDevices(terminate_ue_flag) + else: + CiTestObj.UEDevices.append('OAI-UE') + HTML.SethtmlUEConnected(len(CiTestObj.UEDevices) + len(CiTestObj.CatMDevices)) + HTML.CreateHtmlTabHeader() CiTestObj.FailReportCnt = 0 - CiTestObj.prematureExit = True + RAN.SetprematureExit(True) CiTestObj.startTime = int(round(time.time() * 1000)) - while CiTestObj.FailReportCnt < CiTestObj.repeatCounts[0] and CiTestObj.prematureExit: - CiTestObj.prematureExit = False + HTML.SetstartTime(CiTestObj.startTime) + while CiTestObj.FailReportCnt < CiTestObj.repeatCounts[0] and RAN.GetprematureExit(): + RAN.SetprematureExit(False) # At every iteratin of the retry loop, a separator will be added - CiTestObj.CreateHtmlRetrySeparator() + # pass CiTestObj.FailReportCnt as parameter of HTML.CreateHtmlRetrySeparator + HTML.CreateHtmlRetrySeparator(CiTestObj.FailReportCnt) for test_case_id in todo_tests: - if CiTestObj.prematureExit: + if RAN.GetprematureExit(): break for test in all_tests: - if CiTestObj.prematureExit: + if RAN.GetprematureExit(): break id = test.get('id') if test_case_id != id: continue CiTestObj.testCase_id = id + RAN.SettestCase_id(CiTestObj.testCase_id) + HTML.SettestCase_id(CiTestObj.testCase_id) CiTestObj.desc = test.findtext('desc') + HTML.Setdesc(CiTestObj.desc) action = test.findtext('class') if (CheckClassValidity(action, id) == False): continue @@ -4705,6 +3673,10 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re elif action == 'WaitEndBuild_eNB': RAN.WaitBuildeNBisFinished() elif action == 'Initialize_eNB': + check_eNB = False + check_OAI_UE = False + RAN.SetpStatus(CiTestObj.CheckProcessExist(check_eNB, check_OAI_UE)) + RAN.InitializeeNB() elif action == 'Terminate_eNB': RAN.TerminateeNB() @@ -4767,13 +3739,13 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re else: sys.exit('Invalid action') CiTestObj.FailReportCnt += 1 - if CiTestObj.FailReportCnt == CiTestObj.repeatCounts[0] and CiTestObj.prematureExit: + if CiTestObj.FailReportCnt == CiTestObj.repeatCounts[0] and RAN.GetprematureExit(): logging.debug('Testsuite failed ' + str(CiTestObj.FailReportCnt) + ' time(s)') - CiTestObj.CreateHtmlTabFooter(False) + HTML.CreateHtmlTabFooter(False) sys.exit('Failed Scenario') else: logging.info('Testsuite passed after ' + str(CiTestObj.FailReportCnt) + ' time(s)') - CiTestObj.CreateHtmlTabFooter(True) + HTML.CreateHtmlTabFooter(True) else: GenericHelp(Version) sys.exit('Invalid mode') diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py index 2145557343..17461884e9 100644 --- a/ci-scripts/ran.py +++ b/ci-scripts/ran.py @@ -11,11 +11,47 @@ from multiprocessing import Process, Lock, SimpleQueue #----------------------------------------------------------- # OAI Testing modules #----------------------------------------------------------- -import sshconnection as mySSH -#from sshconnection import mySSHConnection as mySSH +import sshconnection as SSH +import epc import helpreadme as HELP import constants as CONST +import html as HTML +EPC = epc.EPCManagement() + +ALL_PROCESSES_OK = CONST.ALL_PROCESSES_OK +ENB_PROCESS_FAILED = CONST.ENB_PROCESS_FAILED +ENB_PROCESS_OK = CONST.ENB_PROCESS_OK +ENB_PROCESS_SEG_FAULT = CONST.ENB_PROCESS_SEG_FAULT +ENB_PROCESS_ASSERTION = CONST.ENB_PROCESS_ASSERTION +ENB_PROCESS_REALTIME_ISSUE = CONST.ENB_PROCESS_REALTIME_ISSUE +ENB_PROCESS_NOLOGFILE_TO_ANALYZE = CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE +ENB_PROCESS_SLAVE_RRU_NOT_SYNCED = CONST.ENB_PROCESS_SLAVE_RRU_NOT_SYNCED +HSS_PROCESS_FAILED = CONST.HSS_PROCESS_FAILED +HSS_PROCESS_OK = CONST.HSS_PROCESS_OK +MME_PROCESS_FAILED = CONST.MME_PROCESS_FAILED +MME_PROCESS_OK = CONST.MME_PROCESS_OK +SPGW_PROCESS_FAILED = CONST.SPGW_PROCESS_FAILED +SPGW_PROCESS_OK = CONST.SPGW_PROCESS_OK +UE_IP_ADDRESS_ISSUE = CONST.UE_IP_ADDRESS_ISSUE +OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE = CONST.OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE +OAI_UE_PROCESS_COULD_NOT_SYNC = CONST.OAI_UE_PROCESS_COULD_NOT_SYNC +OAI_UE_PROCESS_ASSERTION = CONST.OAI_UE_PROCESS_ASSERTION +OAI_UE_PROCESS_FAILED = CONST.OAI_UE_PROCESS_FAILED +OAI_UE_PROCESS_NO_TUNNEL_INTERFACE = CONST.OAI_UE_PROCESS_NO_TUNNEL_INTERFACE +OAI_UE_PROCESS_SEG_FAULT = CONST.OAI_UE_PROCESS_SEG_FAULT +OAI_UE_PROCESS_OK = CONST.OAI_UE_PROCESS_OK + +UE_STATUS_DETACHED = CONST.UE_STATUS_DETACHED +UE_STATUS_DETACHING = CONST.UE_STATUS_DETACHING +UE_STATUS_ATTACHING = CONST.UE_STATUS_ATTACHING +UE_STATUS_ATTACHED = CONST.UE_STATUS_ATTACHED + +X2_HO_REQ_STATE__IDLE = CONST.X2_HO_REQ_STATE__IDLE +X2_HO_REQ_STATE__TARGET_RECEIVES_REQ = CONST.X2_HO_REQ_STATE__TARGET_RECEIVES_REQ +X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE = CONST.X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE +X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ = CONST.X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ +X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK = CONST.X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK #----------------------------------------------------------- # Class Declaration @@ -45,7 +81,7 @@ class RANManagement(): #self.ADBUserName = '' #self.ADBPassword = '' #self.ADBCentralized = True - #self.testCase_id = '' + self.testCase_id = '' #self.testXMLfiles = [] #self.nbTestXMLfiles = 0 #self.desc = '' @@ -110,12 +146,19 @@ class RANManagement(): #self.Build_OAI_UE_args = '' #self.Initialize_OAI_UE_args = '' #self.clean_repository = True - #self.flexranCtrlInstalled = False - #self.flexranCtrlStarted = False + self.flexranCtrlInstalled = False + self.flexranCtrlStarted = False #self.expectedNbOfConnectedUEs = 0 #self.startTime = 0 - + def SettestCase_id(self,tcid): + self.testCase_id = tcid + def SetflexranCtrlInstalled(self,fxrctin): + self.flexranCtrlInstalled = fxrctin + def SetflexranCtrlStarted(self,fxrctst): + self.flexranCtrlStarted = fxrctst + def SetpStatus(self, pSt): + self.pStatus = pSt def SetranRepository(self, repository): self.ranRepository = repository def GetranRepository(self): @@ -241,14 +284,22 @@ class RANManagement(): def GeteNB2SourceCodePath(self): return self.eNB2SourceCodePath + def SetprematureExit(self, premex): + self.prematureExit = premex + def GetprematureExit(self): + return self.prematureExit def BuildeNB(self): + myHTML = HTML.HTMLManagement() if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': GenericHelp(Version) sys.exit('Insufficient Parameter') if self.eNB_serverId == '0': + #checkpoint enB_serverId lIpAddr = self.eNBIPAddress + print(self.eNBIPAddress + 'self.eNBIPAddress') + print(lIpAddr + 'lIpAddr') lUserName = self.eNBUserName lPassWord = self.eNBPassword lSourcePath = self.eNBSourceCodePath @@ -262,11 +313,12 @@ class RANManagement(): lUserName = self.eNB2UserName lPassWord = self.eNB2Password lSourcePath = self.eNB2SourceCodePath + print(lIpAddr + 'just before the error') if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': GenericHelp(Version) sys.exit('Insufficient Parameter') mySSH = SSH.SSHConnection() - mySSH.open(lIpAddr, lUserName, lPassWord) + mySSH.open(lIpAddr, lUserName, lPassWord) # Check if we build an 5G-NR gNB or an LTE eNB result = re.search('--gNB', self.Build_eNB_args) if result is not None: @@ -316,7 +368,7 @@ class RANManagement(): mismatch = True if not mismatch: mySSH.close() - self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) + myHTML.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) return mySSH.command('echo ' + lPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30) @@ -342,7 +394,7 @@ class RANManagement(): mySSH.command('chmod 775 ./my-lte-softmodem-build.sh', '\$', 5) mySSH.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=build_enb_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/compile_oai_enb.log ./my-lte-softmodem-build.sh', '\$', 5) mySSH.close() - self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) + myHTML.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) self.backgroundBuildTestId[int(self.eNB_instance)] = self.testCase_id return mySSH.command('stdbuf -o0 ./build_oai ' + self.Build_eNB_args + ' 2>&1 | stdbuf -o0 tee compile_oai_enb.log', 'Bypassing the Tests|build have failed', 1500) @@ -369,7 +421,7 @@ class RANManagement(): if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': GenericHelp(Version) sys.exit('Insufficient Parameter') - mySSH = SSH.SSHConnection() + mySSH = SSH.SSHConnection() mySSH.open(lIpAddr, lUserName, lPassWord) count = 40 buildOAIprocess = True @@ -384,8 +436,9 @@ class RANManagement(): self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.backgroundBuildTestId[int(self.eNB_instance)]) def checkBuildeNB(self, lIpAddr, lUserName, lPassWord, lSourcePath, testcaseId): + myHTML = HTML.HTMLManagement() mySSH = SSH.SSHConnection() - mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 3) + mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 3) mySSH.command('ls ran_build/build', '\$', 3) mySSH.command('ls ran_build/build', '\$', 3) if self.air_interface == 'nr': @@ -432,15 +485,16 @@ class RANManagement(): if buildStatus: logging.info('\u001B[1m Building OAI ' + nodeB_prefix + 'NB Pass\u001B[0m') - self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) + myHTML.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) else: logging.error('\u001B[1m Building OAI ' + nodeB_prefix + 'NB Failed\u001B[0m') - self.CreateHtmlTestRow(self.Build_eNB_args, 'KO', ALL_PROCESSES_OK) - self.CreateHtmlTabFooter(False) + myHTML.CreateHtmlTestRow(self.Build_eNB_args, 'KO', ALL_PROCESSES_OK) + myHTML.CreateHtmlTabFooter(False) sys.exit(1) def InitializeeNB(self): + myHTML = HTML.HTMLManagement() if self.eNB_serverId == '0': lIpAddr = self.eNBIPAddress lUserName = self.eNBUserName @@ -459,13 +513,13 @@ class RANManagement(): if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': GenericHelp(Version) sys.exit('Insufficient Parameter') - mySSH = SSH.SSHConnection() - check_eNB = False - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - self.CreateHtmlTestRow(self.Initialize_eNB_args, 'KO', pStatus) - self.CreateHtmlTabFooter(False) + mySSH = SSH.SSHConnection() + #check_eNB = False + #check_OAI_UE = False + #pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (self.pStatus < 0): + myHTML.CreateHtmlTestRow(self.Initialize_eNB_args, 'KO', self.pStatus) + myHTML.CreateHtmlTabFooter(False) sys.exit(1) # If tracer options is on, running tshark on EPC side and capture traffic b/ EPC and eNB result = re.search('T_stdout', str(self.Initialize_eNB_args)) @@ -476,7 +530,7 @@ class RANManagement(): if result is not None: eth_interface = result.group('eth_interface') logging.debug('\u001B[1m Launching tshark on interface ' + eth_interface + '\u001B[0m') - EPC.Get_PcapFileName() = 'enb_' + self.testCase_id + '_s1log.pcap' + EPC.Set_PcapFileName('enb_' + self.testCase_id + '_s1log.pcap') mySSH.command('echo ' + EPC.GetPassword() + ' | sudo -S rm -f /tmp/' + EPC.Get_PcapFileName() , '\$', 5) mySSH.command('echo $USER; nohup sudo tshark -f "host ' + lIpAddr +'" -i ' + eth_interface + ' -w /tmp/' + EPC.Get_PcapFileName() + ' > /tmp/tshark.log 2>&1 &', EPC.GetUserName(), 5) mySSH.close() @@ -566,7 +620,7 @@ class RANManagement(): mySSH.close() doLoop = False logging.error('\u001B[1;37;41m eNB logging system did not show got sync! \u001B[0m') - self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'KO', ALL_PROCESSES_OK) + myHTML.CreateHtmlTestRow('-O ' + config_file + extra_options, 'KO', ALL_PROCESSES_OK) # In case of T tracer recording, we need to kill tshark on EPC side result = re.search('T_stdout', str(self.Initialize_eNB_args)) if result is not None: @@ -616,7 +670,7 @@ class RANManagement(): self.eNBstatuses[int(self.eNB_instance)] = int(self.eNB_serverId) mySSH.close() - self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'OK', ALL_PROCESSES_OK) + myHTML.CreateHtmlTestRow('-O ' + config_file + extra_options, 'OK', ALL_PROCESSES_OK) logging.debug('\u001B[1m Initialize eNB Completed\u001B[0m') @@ -640,7 +694,7 @@ class RANManagement(): lIpAddr = self.eNBIPAddress lUserName = self.eNBUserName lPassWord = self.eNBPassword - mySSH = SSH.SSHConnection() + mySSH = SSH.SSHConnection() mySSH.open(lIpAddr, lUserName, lPassWord) mySSH.command('stdbuf -o0 ps -aux | grep --color=never ' + self.air_interface + '-softmodem | grep -v grep', '\$', 5) result = re.search(self.air_interface + '-softmodem', mySSH.getBefore()) @@ -656,6 +710,7 @@ class RANManagement(): def TerminateeNB(self): + myHTML = HTML.HTMLManagement() if self.eNB_serverId == '0': lIpAddr = self.eNBIPAddress lUserName = self.eNBUserName @@ -674,7 +729,7 @@ class RANManagement(): if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': GenericHelp(Version) sys.exit('Insufficient Parameter') - mySSH = SSH.SSHConnection() + mySSH = SSH.SSHConnection() mySSH.open(lIpAddr, lUserName, lPassWord) mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) if self.air_interface == 'lte': @@ -721,7 +776,7 @@ class RANManagement(): mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + extracted_log_file, '.') logging.debug('\u001B[1m Analyzing eNB replay logfile \u001B[0m') logStatus = self.AnalyzeLogFile_eNB(extracted_log_file) - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + myHTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) self.eNBLogFiles[int(self.eNB_instance)] = '' else: analyzeFile = False @@ -734,7 +789,7 @@ class RANManagement(): if (copyin_res == -1): logging.debug('\u001B[1;37;41m Could not copy ' + nodeB_prefix + 'NB logfile to analyze it! \u001B[0m') self.htmleNBFailureMsg = 'Could not copy ' + nodeB_prefix + 'NB logfile to analyze it!' - self.CreateHtmlTestRow('N/A', 'KO', ENB_PROCESS_NOLOGFILE_TO_ANALYZE) + myHTML.CreateHtmlTestRow('N/A', 'KO', ENB_PROCESS_NOLOGFILE_TO_ANALYZE) self.eNBmbmsEnables[int(self.eNB_instance)] = False return if self.eNB_serverId != '0': @@ -742,20 +797,20 @@ class RANManagement(): logging.debug('\u001B[1m Analyzing ' + nodeB_prefix + 'NB logfile \u001B[0m ' + fileToAnalyze) logStatus = self.AnalyzeLogFile_eNB(fileToAnalyze) if (logStatus < 0): - self.CreateHtmlTestRow('N/A', 'KO', logStatus) + myHTML.CreateHtmlTestRow('N/A', 'KO', logStatus) self.preamtureExit = True self.eNBmbmsEnables[int(self.eNB_instance)] = False return else: - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + myHTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) else: - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + myHTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) self.eNBmbmsEnables[int(self.eNB_instance)] = False self.eNBstatuses[int(self.eNB_instance)] = -1 def LogCollecteNB(self): - mySSH = SSH.SSHConnection() + mySSH = SSH.SSHConnection() mySSH.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) mySSH.command('cd ' + self.eNBSourceCodePath, '\$', 5) mySSH.command('cd cmake_targets', '\$', 5) @@ -763,3 +818,260 @@ class RANManagement(): mySSH.command('echo ' + self.eNBPassword + ' | sudo -S zip enb.log.zip enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 60) mySSH.command('echo ' + self.eNBPassword + ' | sudo -S rm enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 5) mySSH.close() + + + def AnalyzeLogFile_eNB(self, eNBlogFile): + if (not os.path.isfile('./' + eNBlogFile)): + return -1 + enb_log_file = open('./' + eNBlogFile, 'r') + exitSignalReceived = False + foundAssertion = False + msgAssertion = '' + msgLine = 0 + foundSegFault = False + foundRealTimeIssue = False + rrcSetupComplete = 0 + rrcReleaseRequest = 0 + rrcReconfigRequest = 0 + rrcReconfigComplete = 0 + rrcReestablishRequest = 0 + rrcReestablishComplete = 0 + rrcReestablishReject = 0 + rlcDiscardBuffer = 0 + rachCanceledProcedure = 0 + uciStatMsgCount = 0 + pdcpFailure = 0 + ulschFailure = 0 + cdrxActivationMessageCount = 0 + dropNotEnoughRBs = 0 + mbmsRequestMsg = 0 + self.htmleNBFailureMsg = '' + isRRU = False + isSlave = False + slaveReceivesFrameResyncCmd = False + X2HO_state = X2_HO_REQ_STATE__IDLE + X2HO_inNbProcedures = 0 + X2HO_outNbProcedures = 0 + for line in enb_log_file.readlines(): + if X2HO_state == X2_HO_REQ_STATE__IDLE: + result = re.search('target eNB Receives X2 HO Req X2AP_HANDOVER_REQ', str(line)) + if result is not None: + X2HO_state = X2_HO_REQ_STATE__TARGET_RECEIVES_REQ + result = re.search('source eNB receives the X2 HO ACK X2AP_HANDOVER_REQ_ACK', str(line)) + if result is not None: + X2HO_state = X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK + if X2HO_state == X2_HO_REQ_STATE__TARGET_RECEIVES_REQ: + result = re.search('Received LTE_RRCConnectionReconfigurationComplete from UE', str(line)) + if result is not None: + X2HO_state = X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE + if X2HO_state == X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE: + result = re.search('issue rrc_eNB_send_PATH_SWITCH_REQ', str(line)) + if result is not None: + X2HO_state = X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ + if X2HO_state == X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ: + result = re.search('received path switch ack S1AP_PATH_SWITCH_REQ_ACK', str(line)) + if result is not None: + X2HO_state = X2_HO_REQ_STATE__IDLE + X2HO_inNbProcedures += 1 + if X2HO_state == X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK: + result = re.search('source eNB receives the X2 UE CONTEXT RELEASE X2AP_UE_CONTEXT_RELEASE', str(line)) + if result is not None: + X2HO_state = X2_HO_REQ_STATE__IDLE + X2HO_outNbProcedures += 1 + + if self.eNBOptions[int(self.eNB_instance)] != '': + res1 = re.search('max_rxgain (?P[0-9]+)', self.eNBOptions[int(self.eNB_instance)]) + res2 = re.search('max_rxgain (?P[0-9]+)', str(line)) + if res1 is not None and res2 is not None: + requested_option = int(res1.group('requested_option')) + applied_option = int(res2.group('applied_option')) + if requested_option == applied_option: + self.htmleNBFailureMsg += ' Command line option(s) correctly applied ' + self.eNBOptions[int(self.eNB_instance)] + '\n\n' + else: + self.htmleNBFailureMsg += ' Command line option(s) NOT applied ' + self.eNBOptions[int(self.eNB_instance)] + '\n\n' + result = re.search('Exiting OAI softmodem', str(line)) + if result is not None: + exitSignalReceived = True + result = re.search('[Ss]egmentation [Ff]ault', str(line)) + 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('./ran_build/build/lte-softmodem', str(line)) + if result is not None and not exitSignalReceived: + foundSegFault = True + result = re.search('[Aa]ssertion', str(line)) + if result is not None and not exitSignalReceived: + foundAssertion = True + result = re.search('LLL', str(line)) + if result is not None and not exitSignalReceived: + foundRealTimeIssue = True + if foundAssertion and (msgLine < 3): + msgLine += 1 + msgAssertion += str(line) + result = re.search('Setting function for RU', str(line)) + if result is not None: + isRRU = True + if isRRU: + result = re.search('RU 0 is_slave=yes', str(line)) + if result is not None: + isSlave = True + if isSlave: + result = re.search('Received RRU_frame_resynch command', str(line)) + if result is not None: + slaveReceivesFrameResyncCmd = True + result = re.search('LTE_RRCConnectionSetupComplete from UE', str(line)) + if result is not None: + rrcSetupComplete += 1 + result = re.search('Generate LTE_RRCConnectionRelease|Generate RRCConnectionRelease', str(line)) + if result is not None: + rrcReleaseRequest += 1 + result = re.search('Generate LTE_RRCConnectionReconfiguration', str(line)) + if result is not None: + rrcReconfigRequest += 1 + result = re.search('LTE_RRCConnectionReconfigurationComplete from UE rnti', str(line)) + if result is not None: + rrcReconfigComplete += 1 + result = re.search('LTE_RRCConnectionReestablishmentRequest', str(line)) + if result is not None: + rrcReestablishRequest += 1 + result = re.search('LTE_RRCConnectionReestablishmentComplete', str(line)) + if result is not None: + rrcReestablishComplete += 1 + result = re.search('LTE_RRCConnectionReestablishmentReject', str(line)) + if result is not None: + rrcReestablishReject += 1 + result = re.search('CDRX configuration activated after RRC Connection', str(line)) + if result is not None: + cdrxActivationMessageCount += 1 + result = re.search('uci->stat', str(line)) + if result is not None: + uciStatMsgCount += 1 + result = re.search('PDCP.*Out of Resources.*reason', str(line)) + if result is not None: + pdcpFailure += 1 + result = re.search('ULSCH in error in round', str(line)) + if result is not None: + ulschFailure += 1 + result = re.search('BAD all_segments_received', str(line)) + if result is not None: + rlcDiscardBuffer += 1 + 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 + if self.eNBmbmsEnables[int(self.eNB_instance)]: + result = re.search('MBMS USER-PLANE.*Requesting.*bytes from RLC', str(line)) + if result is not None: + mbmsRequestMsg += 1 + enb_log_file.close() + logging.debug(' File analysis completed') + self.htmleNBFailureMsg = '' + if self.air_interface() == 'lte': + nodeB_prefix = 'e' + else: + nodeB_prefix = 'g' + if uciStatMsgCount > 0: + statMsg = nodeB_prefix + 'NB showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + self.htmleNBFailureMsg += statMsg + '\n' + if pdcpFailure > 0: + statMsg = nodeB_prefix + 'NB showed ' + str(pdcpFailure) + ' "PDCP Out of Resources" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + self.htmleNBFailureMsg += statMsg + '\n' + if ulschFailure > 0: + statMsg = nodeB_prefix + 'NB 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 = nodeB_prefix + 'NB completed ' + str(rrcSetupComplete) + ' RRC Connection Setup(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + rrcMsg = ' -- ' + str(rrcSetupComplete) + ' were completed' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + if rrcReleaseRequest > 0: + rrcMsg = nodeB_prefix + 'NB requested ' + str(rrcReleaseRequest) + ' RRC Connection Release(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + if rrcReconfigRequest > 0 or rrcReconfigComplete > 0: + rrcMsg = nodeB_prefix + 'NB requested ' + str(rrcReconfigRequest) + ' RRC Connection Reconfiguration(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + rrcMsg = ' -- ' + str(rrcReconfigComplete) + ' were completed' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + if rrcReestablishRequest > 0 or rrcReestablishComplete > 0 or rrcReestablishReject > 0: + rrcMsg = nodeB_prefix + 'NB requested ' + str(rrcReestablishRequest) + ' RRC Connection Reestablishment(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + rrcMsg = ' -- ' + str(rrcReestablishComplete) + ' were completed' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + rrcMsg = ' -- ' + str(rrcReestablishReject) + ' were rejected' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + if self.eNBmbmsEnables[int(self.eNB_instance)]: + if mbmsRequestMsg > 0: + rrcMsg = 'eNB requested ' + str(mbmsRequestMsg) + ' times the RLC for MBMS USER-PLANE' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + if X2HO_inNbProcedures > 0: + rrcMsg = 'eNB completed ' + str(X2HO_inNbProcedures) + ' X2 Handover Connection procedure(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + if X2HO_outNbProcedures > 0: + rrcMsg = 'eNB completed ' + str(X2HO_outNbProcedures) + ' X2 Handover Release procedure(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + if self.eNBOptions[int(self.eNB_instance)] != '': + res1 = re.search('drx_Config_present prSetup', self.eNBOptions[int(self.eNB_instance)]) + if res1 is not None: + if cdrxActivationMessageCount > 0: + rrcMsg = 'eNB activated the CDRX Configuration for ' + str(cdrxActivationMessageCount) + ' time(s)' + logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + else: + rrcMsg = 'eNB did NOT ACTIVATE the CDRX Configuration' + logging.debug('\u001B[1;37;43m ' + rrcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rrcMsg + '\n' + if rachCanceledProcedure > 0: + rachMsg = nodeB_prefix + 'NB cancelled ' + str(rachCanceledProcedure) + ' RA procedure(s)' + logging.debug('\u001B[1;30;43m ' + rachMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rachMsg + '\n' + if isRRU: + if isSlave: + if slaveReceivesFrameResyncCmd: + rruMsg = 'Slave RRU received the RRU_frame_resynch command from RAU' + logging.debug('\u001B[1;30;43m ' + rruMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rruMsg + '\n' + else: + rruMsg = 'Slave RRU DID NOT receive the RRU_frame_resynch command from RAU' + logging.debug('\u001B[1;37;41m ' + rruMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rruMsg + '\n' + self.prematureExit(True) + return ENB_PROCESS_SLAVE_RRU_NOT_SYNCED + if foundSegFault: + logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB ended with a Segmentation Fault! \u001B[0m') + return ENB_PROCESS_SEG_FAULT + if foundAssertion: + logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB ended with an assertion! \u001B[0m') + self.htmleNBFailureMsg += msgAssertion + return ENB_PROCESS_ASSERTION + if foundRealTimeIssue: + logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB faced real time issues! \u001B[0m') + self.htmleNBFailureMsg += nodeB_prefix + 'NB faced real time issues!\n' + #return ENB_PROCESS_REALTIME_ISSUE + if rlcDiscardBuffer > 0: + rlcMsg = nodeB_prefix + 'NB RLC discarded ' + str(rlcDiscardBuffer) + ' buffer(s)' + logging.debug('\u001B[1;37;41m ' + rlcMsg + ' \u001B[0m') + self.htmleNBFailureMsg += rlcMsg + '\n' + return ENB_PROCESS_REALTIME_ISSUE + return 0 diff --git a/ci-scripts/sshconnection.py b/ci-scripts/sshconnection.py index 6103bf4f0f..df1ada4834 100644 --- a/ci-scripts/sshconnection.py +++ b/ci-scripts/sshconnection.py @@ -3,7 +3,8 @@ #----------------------------------------------------------- import pexpect # pexpect import logging - +import time # sleep +import re #----------------------------------------------------------- # Class Declaration #----------------------------------------------------------- @@ -69,7 +70,7 @@ class SSHConnection(): logging.debug('\u001B[1;37;41m Unexpected EOF \u001B[0m') logging.debug('Expected Line : ' + expectedline) logging.debug(str(self.ssh.before)) - sys.exit(self.sshresponse) + sys.exit(self.sshresponse) elif self.sshresponse == 2: logging.debug('\u001B[1;37;41m Unexpected TIMEOUT \u001B[0m') logging.debug('Expected Line : ' + expectedline) diff --git a/ci-scripts/xml_files/enb_usrp210_band13_test_10mhz_tm1.xml b/ci-scripts/xml_files/enb_usrp210_band13_test_10mhz_tm1.xml index 680f09c435..611492b0bc 100644 --- a/ci-scripts/xml_files/enb_usrp210_band13_test_10mhz_tm1.xml +++ b/ci-scripts/xml_files/enb_usrp210_band13_test_10mhz_tm1.xml @@ -24,7 +24,7 @@ test-lte-m-10-tm1 Test-LTE-M-10MHz-TM1 tasks - 2 + 1 030201 040102 diff --git a/ci-scripts/xml_files/x2ho_enb_usrp210_band13_simple_test.xml b/ci-scripts/xml_files/x2ho_enb_usrp210_band13_simple_test.xml new file mode 100644 index 0000000000..8d813a8e2c --- /dev/null +++ b/ci-scripts/xml_files/x2ho_enb_usrp210_band13_simple_test.xml @@ -0,0 +1,189 @@ + + + test-x2-ho-05-tm1 + Test-X2-HO-FDD-05MHz-TM1 + tasks + 1 + + 030201 + 040101 + 030101 040301 040501 040401 040201 030201 + + + + + IdleSleep + Waiting for 60 seconds + 60 + + + + IdleSleep + Waiting for 10 seconds + 10 + + + + Initialize_FlexranCtrl + Starting Flexran Controller + + + + Terminate_FlexranCtrl + Stopping Flexran Controller + + + + Initialize_eNB + Initialize Master eNB (FDD/Band7/5MHz) + -O ci-scripts/conf_files/enb.band13.tm1.25PRB.usrpb210.conf --eNBs.[0].enable_x2 no + 0 + 0 + + + + Initialize_eNB + Initialize Slave eNB (FDD/Band7/5MHz) + -O ci-scripts/conf_files/enb.slave.band13.tm1.25PRB.usrpb210.conf + 1 + 1 + + + + Terminate_eNB + Terminate Master eNB + 0 + 0 + + + + Terminate_eNB + Terminate Slave eNB + 1 + 1 + + + + Initialize_UE + Initialize UE + + + + Terminate_UE + Terminate UE + + + + Attach_UE + Attach UE + + + + Detach_UE + Detach UE + + + + Ping + ping (5MHz - 20 sec) + -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -c 20 + 5 + + + + Ping + ping (5MHz - 20 sec) + -c 20 + 5 + + + + Iperf + iperf (5MHz - DL/8Mbps/UDP)(30 sec) + -u -b 8M -t 30 -i 1 + 50 + single-ue + + + + Iperf + iperf (5MHz - DL/8Mbps/UDP)(30 sec) + -u -b 8M -t 30 -i 1 + 50 + single-ue + + + + Iperf + iperf (5MHz - DL/8Mbps/UDP)(30 sec) + -u -b 8M -t 30 -i 1 + 50 + single-ue + + + + Iperf + iperf (5MHz - UL/5Mbps/UDP)(30 sec) + -u -b 5M -t 30 -i 1 -R + 50 + single-ue + + + + Iperf + iperf (5MHz - UL/5Mbps/UDP)(30 sec) + -u -b 5M -t 30 -i 1 -R + 50 + single-ue + + + + Iperf + iperf (5MHz - UL/5Mbps/UDP)(30 sec) + -u -b 5M -t 30 -i 1 -R + 50 + single-ue + + + + Perform_X2_Handover + Doing a Flexran-Controlled X2 Handover + network + + + + Perform_X2_Handover + Doing a Flexran-Controlled X2 Handover + network + + + From 6aa64bd2864af9af9c67b85295946d3f7dd313a7 Mon Sep 17 00:00:00 2001 From: Gabriele Perrone Date: Tue, 17 Mar 2020 08:24:13 +0100 Subject: [PATCH 091/240] to switch to develop --- ci-scripts/epc.py | 64 +++++++++-- ci-scripts/helpreadme.py | 30 +++++ ci-scripts/html.py | 206 +++++++++++++--------------------- ci-scripts/main_enb.py | 180 +++++++++--------------------- ci-scripts/ran.py | 213 +++++++++++++----------------------- ci-scripts/sshconnection.py | 31 ++++++ 6 files changed, 320 insertions(+), 404 deletions(-) diff --git a/ci-scripts/epc.py b/ci-scripts/epc.py index 4f283f530e..4d88a69e75 100644 --- a/ci-scripts/epc.py +++ b/ci-scripts/epc.py @@ -1,3 +1,33 @@ +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (the "License"); you may not use this file +# * except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.openairinterface.org/?page_id=698 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# Python for CI of OAI-eNB + COTS-UE +# +# Required Python Version +# Python 3.x +# +# Required Python Package +# pexpect +#--------------------------------------------------------------------- + + #----------------------------------------------------------- # Import #----------------------------------------------------------- @@ -14,22 +44,28 @@ from multiprocessing import Process, Lock, SimpleQueue # OAI Testing modules #----------------------------------------------------------- import sshconnection as SSH -#from sshconnection import SSHConnection as SSH import helpreadme as HELP import constants as CONST +import html as HTML #----------------------------------------------------------- # Class Declaration #----------------------------------------------------------- class EPCManagement(): + def __init__(self): - self.EPCIPAddress = '' - self.EPCUserName = '' - self.EPCPassword = '' - self.EPCSourceCodePath = '' - self.EPCType = '' + + self.IPAddress = '' + self.UserName = '' + self.Password = '' + self.SourceCodePath = '' + self.Type = '' self.EPC_PcapFileName = '' +#----------------------------------------------------------- +# Setter and Getters +#----------------------------------------------------------- + def SetIPAddress(self, ipaddress): self.EPCIPAddress = ipaddress def GetIPAddress(self): @@ -55,6 +91,10 @@ class EPCManagement(): def Get_PcapFileName(self): return self.EPC_PcapFileName +#----------------------------------------------------------- +# EPC management functions +#----------------------------------------------------------- + def InitializeHSS(self): if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': HELP.GenericHelp(Version) @@ -91,7 +131,7 @@ class EPCManagement(): else: logging.error('This option should not occur!') mySSH.close() - #self.CreateHtmlTestRow(self.EPCType, 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.EPCType, 'OK', CONST.ALL_PROCESSES_OK) def InitializeMME(self): if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': @@ -124,7 +164,7 @@ class EPCManagement(): else: logging.error('This option should not occur!') mySSH.close() - #self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) def InitializeSPGW(self): if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': @@ -155,7 +195,7 @@ class EPCManagement(): else: logging.error('This option should not occur!') mySSH.close() - #self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) def CheckHSSProcess(self, status_queue): @@ -255,7 +295,7 @@ class EPCManagement(): else: logging.error('This should not happen!') mySSH.close() - #self.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def TerminateMME(self): mySSH = SSH.SSHConnection() @@ -274,7 +314,7 @@ class EPCManagement(): else: logging.error('This should not happen!') mySSH.close() - #self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) def TerminateSPGW(self): mySSH = SSH.SSHConnection() @@ -305,7 +345,7 @@ class EPCManagement(): else: logging.error('This should not happen!') mySSH.close() - #self.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def LogCollectHSS(self): diff --git a/ci-scripts/helpreadme.py b/ci-scripts/helpreadme.py index 294454e270..307ab4ff31 100644 --- a/ci-scripts/helpreadme.py +++ b/ci-scripts/helpreadme.py @@ -1,3 +1,33 @@ +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (the "License"); you may not use this file +# * except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.openairinterface.org/?page_id=698 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# Python for CI of OAI-eNB + COTS-UE +# +# Required Python Version +# Python 3.x +# +# Required Python Package +# pexpect +#--------------------------------------------------------------------- + + #----------------------------------------------------------- # Functions Declaration #----------------------------------------------------------- diff --git a/ci-scripts/html.py b/ci-scripts/html.py index 80ad46f51e..e8930f6e2c 100644 --- a/ci-scripts/html.py +++ b/ci-scripts/html.py @@ -1,3 +1,32 @@ +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (the "License"); you may not use this file +# * except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.openairinterface.org/?page_id=698 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# Python for CI of OAI-eNB + COTS-UE +# +# Required Python Version +# Python 3.x +# +# Required Python Package +# pexpect +#--------------------------------------------------------------------- + #----------------------------------------------------------- # Import @@ -10,117 +39,24 @@ import time import subprocess from multiprocessing import Process, Lock, SimpleQueue -#----------------------------------------------------------- -# OAI Testing modules -#----------------------------------------------------------- -#import main_enb -#MAIN = main_enb.OaiCiTest() - - #----------------------------------------------------------- # Class Declaration #----------------------------------------------------------- class HTMLManagement(): + def __init__(self): - # self.FailReportCnt = 0 - # self.prematureExit = False - self.ranRepository = '' - self.ranBranch = '' - self.ranAllowMerge = False - self.ranCommitID = '' - self.ranTargetBranch = '' - #self.eNBIPAddress = '' - #self.eNBUserName = '' - #self.eNBPassword = '' - #self.eNBSourceCodePath = '' - #self.eNB1IPAddress = '' - #self.eNB1UserName = '' - #self.eNB1Password = '' - #self.eNB1SourceCodePath = '' - #self.eNB2IPAddress = '' - #self.eNB2UserName = '' - #self.eNB2Password = '' - #self.eNB2SourceCodePath = '' - #self.ADBIPAddress = '' - #self.ADBUserName = '' - #self.ADBPassword = '' - #self.ADBCentralized = True - #self.testCase_id = '' - self.testXMLfiles = [] - self.nbTestXMLfiles = 0 - #self.desc = '' - #self.Build_eNB_args = '' - #self.backgroundBuild = False - #self.backgroundBuildTestId = ['', '', ''] - #self.Build_eNB_forced_workspace_cleanup = False - #self.Initialize_eNB_args = '' - #self.air_interface = 'lte' - #self.eNB_instance = '' - #self.eNB_serverId = '' - #self.eNBLogFiles = ['', '', ''] - #self.eNBOptions = ['', '', ''] - #self.eNBmbmsEnables = [False, False, False] - #self.eNBstatuses = [-1, -1, -1] - #self.ping_args = '' - #self.ping_packetloss_threshold = '' - #self.iperf_args = '' - #self.iperf_packetloss_threshold = '' - #self.iperf_profile = '' - #self.iperf_options = '' - #self.nbMaxUEtoAttach = -1 - #self.UEDevices = [] - #self.UEDevicesStatus = [] - #self.UEDevicesRemoteServer = [] - #self.UEDevicesRemoteUser = [] - #self.UEDevicesOffCmd = [] - #self.UEDevicesOnCmd = [] - #self.UEDevicesRebootCmd = [] - #self.CatMDevices = [] - #self.UEIPAddresses = [] - self.htmlFile = '' - self.htmlHeaderCreated = False - self.htmlFooterCreated = False - self.htmlUEConnected = -1 - self.htmlNb_Smartphones = 0 - self.htmlNb_CATM_Modules = 0 - self.htmleNBFailureMsg = '' - self.htmlUEFailureMsg = '' - #self.picocom_closure = False - #self.idle_sleep_time = 0 - #self.x2_ho_options = 'network' - #self.x2NbENBs = 0 - #self.x2ENBBsIds = [] - #self.x2ENBConnectedUEs = [] + self.htmlTabRefs = [] self.htmlTabNames = [] self.htmlTabIcons = [] - #self.repeatCounts = [] - #self.finalStatus = False - #self.OsVersion = '' - #self.KernelVersion = '' - #self.UhdVersion = '' - #self.UsrpBoard = '' - #self.CpuNb = '' - #self.CpuModel = '' - #self.CpuMHz = '' - #self.UEIPAddress = '' - #self.UEUserName = '' - #self.UEPassword = '' - #self.UE_instance = '' - #self.UESourceCodePath = '' - #self.UELogFile = '' - #self.Build_OAI_UE_args = '' - #self.Initialize_OAI_UE_args = '' - #self.clean_repository = True - #self.flexranCtrlInstalled = False - #self.flexranCtrlStarted = False - #self.expectedNbOfConnectedUEs = 0 - #self.startTime = 0 - - + self.testXMLfiles = [] #----------------------------------------------------------- -# HTML Reporting.... +# Setters and Getters #----------------------------------------------------------- + def SetreseNB(self,rsenb): + self.reseNB = rsenb + def SetresUE(self,rsue): + self.resUE = rsue def Setdesc(self, dsc): self.desc = dsc @@ -157,11 +93,6 @@ class HTMLManagement(): self.ranTargetBranch = tbranch def GetranTargetBranch(self): return self.ranTargetBranch - -# def SetADBIPAddress(self, adbip): -# self.ADBIPAddress = adbip -# def GetADBIPAddress(self): -# return self.ADBIPAddress def SethtmlUEConnected(self, nbUEs): self.htmlUEConnected = nbUEs @@ -187,6 +118,12 @@ class HTMLManagement(): def SethtmlTabIcons(self, tabIcon): self.htmlTabIcons.append(tabIcon) + +#----------------------------------------------------------- +# HTML structure creation functions +#----------------------------------------------------------- + + def CreateHtmlHeader(self, ADBIPAddress): if (not self.htmlHeaderCreated): logging.debug('\u001B[1m----------------------------------------\u001B[0m') @@ -270,15 +207,9 @@ class HTMLManagement(): self.htmlFile.write(' \n') if (ADBIPAddress != 'none'): - #terminate_ue_flag = True - #MAIN.GetAllUEDevices(terminate_ue_flag) - #self.GetAllCatMDevices(terminate_ue_flag) - #self.htmlUEConnected = len(self.UEDevices) self.htmlFile.write('

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

\n') self.htmlFile.write('

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

\n') else: - #self.UEDevices.append('OAI-UE') - #self.htmlUEConnected = len(self.UEDevices) self.htmlUEConnected = 1 self.htmlFile.write('

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

\n') self.htmlFile.write('
\n') @@ -316,14 +247,6 @@ class HTMLManagement(): self.htmlFile.write(' Test Desc\n') self.htmlFile.write(' Test Options\n') self.htmlFile.write(' Test Status\n') - #if (self.htmlUEConnected == -1): - # terminate_ue_flag = True - # if (self.ADBIPAddress != 'none'): - # self.GetAllUEDevices(terminate_ue_flag) - # self.GetAllCatMDevices(terminate_ue_flag) - # else: - # self.UEDevices.append('OAI-UE') - # self.htmlUEConnected = len(self.UEDevices) i = 0 while (i < self.htmlUEConnected): @@ -366,14 +289,41 @@ class HTMLManagement(): self.htmlFile.write('

\n') self.htmlFile.write(' \n') - machines = [ 'eNB', 'UE' ] - for machine in machines: - #This needs to move back to main and be called before CreateHtmlFooter - res = self.RetrieveSystemVersion(machine) - if res == -1: - continue + # GP machines = [ 'eNB', 'UE' ] + # GP for machine in machines: + #GP This needs to move back to main and be called before CreateHtmlFooter + + res = self.reseNB + if res != -1: self.htmlFile.write(' \n') - self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') + + + res = self.resUE + if res != -1: + self.htmlFile.write(' \n') + self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') @@ -410,8 +360,6 @@ class HTMLManagement(): self.htmlFile.write('\n') self.htmlFile.close() - #FailReportCnt should be passed as a parameter of CreateHtmlRetrySeparator method - # no need for a setter and be a member of html class def CreateHtmlRetrySeparator(self, cntnumfails): if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): self.htmlFile = open('test_results.html', 'a') diff --git a/ci-scripts/main_enb.py b/ci-scripts/main_enb.py index 340aaed9b3..a42aba76e2 100644 --- a/ci-scripts/main_enb.py +++ b/ci-scripts/main_enb.py @@ -35,43 +35,6 @@ import constants as CONST #----------------------------------------------------------- Version = '0.1' -#----------------------------------------------------------- -# Constants -#----------------------------------------------------------- -ALL_PROCESSES_OK = CONST.ALL_PROCESSES_OK -ENB_PROCESS_FAILED = CONST.ENB_PROCESS_FAILED -ENB_PROCESS_OK = CONST.ENB_PROCESS_OK -ENB_PROCESS_SEG_FAULT = CONST.ENB_PROCESS_SEG_FAULT -ENB_PROCESS_ASSERTION = CONST.ENB_PROCESS_ASSERTION -ENB_PROCESS_REALTIME_ISSUE = CONST.ENB_PROCESS_REALTIME_ISSUE -ENB_PROCESS_NOLOGFILE_TO_ANALYZE = CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE -ENB_PROCESS_SLAVE_RRU_NOT_SYNCED = CONST.ENB_PROCESS_SLAVE_RRU_NOT_SYNCED -HSS_PROCESS_FAILED = CONST.HSS_PROCESS_FAILED -HSS_PROCESS_OK = CONST.HSS_PROCESS_OK -MME_PROCESS_FAILED = CONST.MME_PROCESS_FAILED -MME_PROCESS_OK = CONST.MME_PROCESS_OK -SPGW_PROCESS_FAILED = CONST.SPGW_PROCESS_FAILED -SPGW_PROCESS_OK = CONST.SPGW_PROCESS_OK -UE_IP_ADDRESS_ISSUE = CONST.UE_IP_ADDRESS_ISSUE -OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE = CONST.OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE -OAI_UE_PROCESS_COULD_NOT_SYNC = CONST.OAI_UE_PROCESS_COULD_NOT_SYNC -OAI_UE_PROCESS_ASSERTION = CONST.OAI_UE_PROCESS_ASSERTION -OAI_UE_PROCESS_FAILED = CONST.OAI_UE_PROCESS_FAILED -OAI_UE_PROCESS_NO_TUNNEL_INTERFACE = CONST.OAI_UE_PROCESS_NO_TUNNEL_INTERFACE -OAI_UE_PROCESS_SEG_FAULT = CONST.OAI_UE_PROCESS_SEG_FAULT -OAI_UE_PROCESS_OK = CONST.OAI_UE_PROCESS_OK - -UE_STATUS_DETACHED = CONST.UE_STATUS_DETACHED -UE_STATUS_DETACHING = CONST.UE_STATUS_DETACHING -UE_STATUS_ATTACHING = CONST.UE_STATUS_ATTACHING -UE_STATUS_ATTACHED = CONST.UE_STATUS_ATTACHED - -X2_HO_REQ_STATE__IDLE = CONST.X2_HO_REQ_STATE__IDLE -X2_HO_REQ_STATE__TARGET_RECEIVES_REQ = CONST.X2_HO_REQ_STATE__TARGET_RECEIVES_REQ -X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE = CONST.X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE -X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ = CONST.X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ -X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK = CONST.X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK - #----------------------------------------------------------- # Import #----------------------------------------------------------- @@ -91,36 +54,14 @@ logging.basicConfig( format="[%(asctime)s] %(name)s:%(levelname)s: %(message)s" ) + #----------------------------------------------------------- # Class Declaration #----------------------------------------------------------- class OaiCiTest(): + def __init__(self): self.FailReportCnt = 0 - self.prematureExit = False - #self.ranRepository = '' - #self.ranBranch = '' - #RAN.GetranAllowMerge() = False - #self.ranCommitID = '' - #RAN.GetranTargetBranch() = '' - #self.eNBIPAddress = '' - #self.eNBUserName = '' - #self.eNBPassword = '' - #RAN.GeteNBSourceCodePath() = '' - #self.EPCIPAddress = '' - #self.EPCUserName = '' - #self.EPCPassword = '' - #self.eNB1IPAddress = '' - #self.eNB1UserName = '' - #self.eNB1Password = '' - #self.eNB1SourceCodePath = '' - #self.eNB2IPAddress = '' - #self.eNB2UserName = '' - #self.eNB2Password = '' - #self.eNB2SourceCodePath = '' - #self.EPCSourceCodePath = '' - #self.EPCType = '' - #self.EPC_PcapFileName = '' self.ADBIPAddress = '' self.ADBUserName = '' self.ADBPassword = '' @@ -129,18 +70,6 @@ class OaiCiTest(): self.testXMLfiles = [] self.nbTestXMLfiles = 0 self.desc = '' - #RAN.GetBuild_eNB_args() = '' - #self.backgroundBuild = False - #self.backgroundBuildTestId = ['', '', ''] - #self.Build_eNB_forced_workspace_cleanup = False - #RAN.GetInitialize_eNB_args() = '' - self.air_interface = 'lte' - #self.eNB_instance = '' - #self.eNB_serverId = '' - #self.eNBLogFiles = ['', '', ''] - #self.eNBOptions = ['', '', ''] - #self.eNBmbmsEnables = [False, False, False] - #self.eNBstatuses = [-1, -1, -1] self.ping_args = '' self.ping_packetloss_threshold = '' self.iperf_args = '' @@ -169,9 +98,6 @@ class OaiCiTest(): self.x2NbENBs = 0 self.x2ENBBsIds = [] self.x2ENBConnectedUEs = [] - #self.htmlTabRefs = [] - #self.htmlTabNames = [] - #self.htmlTabIcons = [] self.repeatCounts = [] self.finalStatus = False self.OsVersion = '' @@ -246,7 +172,7 @@ class OaiCiTest(): mismatch = True if not mismatch: SSH.close() - HTML.CreateHtmlTestRow(RAN.GetBuild_eNB_args(), 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(RAN.GetBuild_eNB_args(), 'OK', CONST.ALL_PROCESSES_OK) return SSH.command('echo ' + self.UEPassword + ' | sudo -S git clean -x -d -ff', '\$', 30) @@ -291,11 +217,11 @@ class OaiCiTest(): else: SSH.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) SSH.close() - HTML.CreateHtmlTestRow(self.Build_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE') + HTML.CreateHtmlTestRow(self.Build_OAI_UE_args, 'OK', CONST.ALL_PROCESSES_OK, 'OAI UE') else: SSH.close() logging.error('\u001B[1m Building OAI UE Failed\u001B[0m') - HTML.CreateHtmlTestRow(self.Build_OAI_UE_args, 'KO', ALL_PROCESSES_OK, 'OAI UE') + HTML.CreateHtmlTestRow(self.Build_OAI_UE_args, 'KO', CONST.ALL_PROCESSES_OK, 'OAI UE') HTML.CreateHtmlTabFooter(False) sys.exit(1) @@ -330,7 +256,7 @@ class OaiCiTest(): self.flexranCtrlStarted = True RAN.SetflexranCtrlStarted(True) SSH.close() - HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def InitializeUE_common(self, device_id, idx): try: @@ -393,7 +319,7 @@ class OaiCiTest(): i += 1 for job in multi_jobs: job.join() - HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def InitializeOAIUE(self): if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': @@ -551,23 +477,23 @@ class OaiCiTest(): SSH.close() if fullSyncStatus and gotSyncStatus and tunnelInterfaceStatus: - HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE') + HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'OK', CONST.ALL_PROCESSES_OK, 'OAI UE') logging.debug('\u001B[1m Initialize OAI UE Completed\u001B[0m') if (self.ADBIPAddress != 'none'): self.UEDevices = [] self.UEDevices.append('OAI-UE') self.UEDevicesStatus = [] - self.UEDevicesStatus.append(UE_STATUS_DETACHED) + self.UEDevicesStatus.append(CONST.UE_STATUS_DETACHED) else: if RAN.Getair_interface() == 'lte': if RAN.GeteNBmbmsEnables[0]: self.htmlUEFailureMsg = 'oaitun_ue1/oaitun_uem1 interfaces are either NOT mounted or NOT configured' else: self.htmlUEFailureMsg = 'oaitun_ue1 interface is either NOT mounted or NOT configured' - HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', OAI_UE_PROCESS_NO_TUNNEL_INTERFACE, 'OAI UE') + HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', CONST.OAI_UE_PROCESS_NO_TUNNEL_INTERFACE, 'OAI UE') else: self.htmlUEFailureMsg = 'nr-uesoftmodem did NOT synced' - HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', OAI_UE_PROCESS_COULD_NOT_SYNC, 'OAI UE') + HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', CONST.OAI_UE_PROCESS_COULD_NOT_SYNC, 'OAI UE') logging.error('\033[91mInitialize OAI UE Failed! \033[0m') self.AutoTerminateUEandeNB() @@ -620,7 +546,7 @@ class OaiCiTest(): # Force closure of picocom but device might still be locked SSH.close() self.picocom_closure = False - HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) self.checkDevTTYisUnlocked() def TerminateCatM(self): @@ -641,7 +567,7 @@ class OaiCiTest(): logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') SSH.close() self.picocom_closure = False - HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) self.checkDevTTYisUnlocked() def AttachCatM(self): @@ -902,7 +828,7 @@ class OaiCiTest(): nb_ue_to_connect = 0 for device_id in self.UEDevices: if (self.nbMaxUEtoAttach == -1) or (nb_ue_to_connect < self.nbMaxUEtoAttach): - self.UEDevicesStatus[nb_ue_to_connect] = UE_STATUS_ATTACHING + self.UEDevicesStatus[nb_ue_to_connect] = CONST.UE_STATUS_ATTACHING p = Process(target = self.AttachUE_common, args = (device_id, status_queue, lock,nb_ue_to_connect,)) p.daemon = True p.start() @@ -912,7 +838,7 @@ class OaiCiTest(): job.join() if (status_queue.empty()): - HTML.CreateHtmlTestRow('N/A', 'KO', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ALL_PROCESSES_OK) self.AutoTerminateUEandeNB() return else: @@ -932,8 +858,8 @@ class OaiCiTest(): if (attach_status): cnt = 0 while cnt < len(self.UEDevices): - if self.UEDevicesStatus[cnt] == UE_STATUS_ATTACHING: - self.UEDevicesStatus[cnt] = UE_STATUS_ATTACHED + if self.UEDevicesStatus[cnt] == CONST.UE_STATUS_ATTACHING: + self.UEDevicesStatus[cnt] = CONST.UE_STATUS_ATTACHED cnt += 1 HTML.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args())) @@ -973,7 +899,7 @@ class OaiCiTest(): multi_jobs = [] cnt = 0 for device_id in self.UEDevices: - self.UEDevicesStatus[cnt] = UE_STATUS_DETACHING + self.UEDevicesStatus[cnt] = CONST.UE_STATUS_DETACHING p = Process(target = self.DetachUE_common, args = (device_id,cnt,)) p.daemon = True p.start() @@ -981,14 +907,14 @@ class OaiCiTest(): cnt += 1 for job in multi_jobs: job.join() - HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args())) if result is not None: logging.debug('Waiting 5 seconds to fill up record file') time.sleep(5) cnt = 0 while cnt < len(self.UEDevices): - self.UEDevicesStatus[cnt] = UE_STATUS_DETACHED + self.UEDevicesStatus[cnt] = CONST.UE_STATUS_DETACHED cnt += 1 def RebootUE_common(self, device_id): @@ -1049,7 +975,7 @@ class OaiCiTest(): multi_jobs.append(p) for job in multi_jobs: job.join() - HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def DataDisableUE_common(self, device_id, idx): try: @@ -1078,7 +1004,7 @@ class OaiCiTest(): i += 1 for job in multi_jobs: job.join() - HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def DataEnableUE_common(self, device_id, idx): try: @@ -1107,7 +1033,7 @@ class OaiCiTest(): i += 1 for job in multi_jobs: job.join() - HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def GetAllUEDevices(self, terminate_ue_flag): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': @@ -1152,7 +1078,7 @@ class OaiCiTest(): print('len(self.UEDevicesStatus) == 0') cnt = 0 while cnt < len(self.UEDevices): - self.UEDevicesStatus.append(UE_STATUS_DETACHED) + self.UEDevicesStatus.append(CONST.UE_STATUS_DETACHED) cnt += 1 def GetAllCatMDevices(self, terminate_ue_flag): @@ -1272,7 +1198,7 @@ class OaiCiTest(): htmlOptions = 'N/A' if (status_queue.empty()): - HTML.CreateHtmlTestRow(htmlOptions, 'KO', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(htmlOptions, 'KO', CONST.ALL_PROCESSES_OK) self.AutoTerminateUEandeNB() else: check_status = True @@ -1319,8 +1245,8 @@ class OaiCiTest(): SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) idx = 0 for device_id in self.UEDevices: - print('UE status attched'+UE_STATUS_ATTACHED) - if self.UEDevicesStatus[idx] != UE_STATUS_ATTACHED: + print('UE status attched'+CONST.UE_STATUS_ATTACHED) + if self.UEDevicesStatus[idx] != CONST.UE_STATUS_ATTACHED: idx += 1 continue count = 0 @@ -1563,7 +1489,7 @@ class OaiCiTest(): return ueIpStatus = self.GetAllUEIPAddresses() if (ueIpStatus < 0): - HTML.CreateHtmlTestRow(self.ping_args, 'KO', UE_IP_ADDRESS_ISSUE) + HTML.CreateHtmlTestRow(self.ping_args, 'KO', CONST.UE_IP_ADDRESS_ISSUE) self.AutoTerminateUEandeNB() return multi_jobs = [] @@ -1581,7 +1507,7 @@ class OaiCiTest(): job.join() if (status_queue.empty()): - HTML.CreateHtmlTestRow(self.ping_args, 'KO', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.ping_args, 'KO', CONST.ALL_PROCESSES_OK) self.AutoTerminateUEandeNB() else: ping_status = True @@ -1998,7 +1924,7 @@ class OaiCiTest(): if (device_id != 'OAI-UE'): SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) # if by chance ADB server and EPC are on the same remote host, at least log collection will take care of it - SSH.command('if [ ! -d ' + EPC.GetSourceCodePath() + '/scripts ]; then mkdir -p ' + self.EPCSourceCodePath + '/scripts ; fi', '\$', 5) + SSH.command('if [ ! -d ' + EPC.GetSourceCodePath() + '/scripts ]; then mkdir -p ' + EPC.GetSourceCodePath() + '/scripts ; fi', '\$', 5) SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) # Checking if iperf / iperf3 are installed if self.ADBCentralized: @@ -2306,7 +2232,7 @@ class OaiCiTest(): ueIpStatus = self.GetAllUEIPAddresses() if (ueIpStatus < 0): logging.debug('going here') - HTML.CreateHtmlTestRow(self.iperf_args, 'KO', UE_IP_ADDRESS_ISSUE) + HTML.CreateHtmlTestRow(self.iperf_args, 'KO', CONST.UE_IP_ADDRESS_ISSUE) self.AutoTerminateUEandeNB() return @@ -2338,7 +2264,7 @@ class OaiCiTest(): job.join() if (status_queue.empty()): - HTML.CreateHtmlTestRow(self.iperf_args, 'KO', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.iperf_args, 'KO', CONST.ALL_PROCESSES_OK) self.AutoTerminateUEandeNB() else: iperf_status = True @@ -2406,7 +2332,7 @@ class OaiCiTest(): status = status_queue.get() if (status < 0): result = status - if result == ENB_PROCESS_FAILED: + if result == CONST.ENB_PROCESS_FAILED: fileCheck = re.search('enb_', str(RAN.GeteNBLogFiles[0])) if fileCheck is not None: SSH.copyin(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath() + '/cmake_targets/' + RAN.GeteNBLogFiles[0], '.') @@ -2437,7 +2363,7 @@ class OaiCiTest(): status = status_queue.get() if (status < 0): result = status - if result == OAI_UE_PROCESS_FAILED: + if result == CONST.OAI_UE_PROCESS_FAILED: fileCheck = re.search('ue_', str(self.UELogFile)) if fileCheck is not None: SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.') @@ -2453,9 +2379,9 @@ class OaiCiTest(): result = re.search(RAN.Getair_interface() + '-uesoftmodem', SSH.getBefore()) if result is None: logging.debug('\u001B[1;37;41m OAI UE Process Not Found! \u001B[0m') - status_queue.put(OAI_UE_PROCESS_FAILED) + status_queue.put(CONST.OAI_UE_PROCESS_FAILED) else: - status_queue.put(OAI_UE_PROCESS_OK) + status_queue.put(CONST.OAI_UE_PROCESS_OK) SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) @@ -2688,31 +2614,31 @@ class OaiCiTest(): if foundSegFault: logging.debug('\u001B[1;37;41m UE ended with a Segmentation Fault! \u001B[0m') if not nrUEFlag: - return OAI_UE_PROCESS_SEG_FAULT + return CONST.OAI_UE_PROCESS_SEG_FAULT else: if not frequency_found: - return OAI_UE_PROCESS_SEG_FAULT + return CONST.OAI_UE_PROCESS_SEG_FAULT if foundAssertion: logging.debug('\u001B[1;30;43m UE showed an assertion! \u001B[0m') self.htmlUEFailureMsg += 'UE showed an assertion!\n' if not nrUEFlag: if not mib_found or not frequency_found: - return OAI_UE_PROCESS_ASSERTION + return CONST.OAI_UE_PROCESS_ASSERTION else: if not frequency_found: - return OAI_UE_PROCESS_ASSERTION + return CONST.OAI_UE_PROCESS_ASSERTION if foundRealTimeIssue: logging.debug('\u001B[1;37;41m UE faced real time issues! \u001B[0m') self.htmlUEFailureMsg += 'UE faced real time issues!\n' - #return ENB_PROCESS_REALTIME_ISSUE + #return CONST.ENB_PROCESS_REALTIME_ISSUE if nrUEFlag: if not frequency_found: - return OAI_UE_PROCESS_COULD_NOT_SYNC + return CONST.OAI_UE_PROCESS_COULD_NOT_SYNC else: if no_cell_sync_found and not mib_found: logging.debug('\u001B[1;37;41m UE could not synchronize ! \u001B[0m') self.htmlUEFailureMsg += 'UE could not synchronize!\n' - return OAI_UE_PROCESS_COULD_NOT_SYNC + return CONST.OAI_UE_PROCESS_COULD_NOT_SYNC return 0 @@ -2729,7 +2655,7 @@ class OaiCiTest(): time.sleep(1) SSH.close() self.flexranCtrlStarted = False - HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def TerminateUE_common(self, device_id, idx): try: @@ -2772,7 +2698,7 @@ class OaiCiTest(): i += 1 for job in multi_jobs: job.join() - HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def TerminateOAIUE(self): SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) @@ -2795,7 +2721,7 @@ class OaiCiTest(): if (copyin_res == -1): logging.debug('\u001B[1;37;41m Could not copy UE logfile to analyze it! \u001B[0m') self.htmlUEFailureMsg = 'Could not copy UE logfile to analyze it!' - HTML.CreateHtmlTestRow('N/A', 'KO', OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE, 'UE') + HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE, 'UE') self.UELogFile = '' return logging.debug('\u001B[1m Analyzing UE logfile \u001B[0m') @@ -2812,20 +2738,20 @@ class OaiCiTest(): if RAN.Getair_interface() == 'lte': # In case of sniffing on commercial eNBs we have random results # Not an error then - if (logStatus != OAI_UE_PROCESS_COULD_NOT_SYNC) or (ueAction != 'Sniffing'): + if (logStatus != CONST.OAI_UE_PROCESS_COULD_NOT_SYNC) or (ueAction != 'Sniffing'): self.Initialize_OAI_UE_args = '' self.AutoTerminateUEandeNB() else: - if (logStatus == OAI_UE_PROCESS_COULD_NOT_SYNC): + if (logStatus == CONST.OAI_UE_PROCESS_COULD_NOT_SYNC): self.Initialize_OAI_UE_args = '' self.AutoTerminateUEandeNB() else: logging.debug('\u001B[1m' + ueAction + ' Completed \u001B[0m') self.htmlUEFailureMsg = '' + ueAction + ' Completed\n' + self.htmlUEFailureMsg - HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) self.UELogFile = '' else: - HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def AutoTerminateUEandeNB(self): if (self.ADBIPAddress != 'none'): @@ -2857,7 +2783,7 @@ class OaiCiTest(): def IdleSleep(self): time.sleep(self.idle_sleep_time) - HTML.CreateHtmlTestRow(str(self.idle_sleep_time) + ' sec', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(str(self.idle_sleep_time) + ' sec', 'OK', CONST.ALL_PROCESSES_OK) def X2_Status(self, idx, fileName): cmd = "curl --silent http://" + EPC.GetIPAddress() + ":9999/stats | jq '.' > " + fileName @@ -2967,7 +2893,7 @@ class OaiCiTest(): html_queue.put(fullMessage) HTML.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) else: - HTML.CreateHtmlTestRow('Cannot perform requested X2 Handover', 'KO', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('Cannot perform requested X2 Handover', 'KO', CONST.ALL_PROCESSES_OK) def LogCollectBuild(self): if (RAN.GeteNBIPAddress() != '' and RAN.GeteNBUserName() != '' and RAN.GeteNBPassword() != ''): @@ -3548,6 +3474,8 @@ elif re.match('^InitiateHtml$', mode, re.IGNORECASE): HTML.SethtmlNb_CATM_Modules(len(CiTestObj.CatMDevices)) HTML.CreateHtmlHeader(CiTestObj.ADBIPAddress) elif re.match('^FinalizeHtml$', mode, re.IGNORECASE): + HTML.SetreseNB(RetrieveSystemVersion('eNB')) + HTML.SetresUE(RetrieveSystemVersion('UE')) HTML.CreateHtmlFooter(CiTestObj.finalStatus) elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re.IGNORECASE): if re.match('^TesteNB$', mode, re.IGNORECASE): diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py index 17461884e9..04c2e71c5f 100644 --- a/ci-scripts/ran.py +++ b/ci-scripts/ran.py @@ -1,3 +1,34 @@ + +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (the "License"); you may not use this file +# * except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.openairinterface.org/?page_id=698 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# Python for CI of OAI-eNB + COTS-UE +# +# Required Python Version +# Python 3.x +# +# Required Python Package +# pexpect +#--------------------------------------------------------------------- + + #----------------------------------------------------------- # Import #----------------------------------------------------------- @@ -19,47 +50,15 @@ import html as HTML EPC = epc.EPCManagement() -ALL_PROCESSES_OK = CONST.ALL_PROCESSES_OK -ENB_PROCESS_FAILED = CONST.ENB_PROCESS_FAILED -ENB_PROCESS_OK = CONST.ENB_PROCESS_OK -ENB_PROCESS_SEG_FAULT = CONST.ENB_PROCESS_SEG_FAULT -ENB_PROCESS_ASSERTION = CONST.ENB_PROCESS_ASSERTION -ENB_PROCESS_REALTIME_ISSUE = CONST.ENB_PROCESS_REALTIME_ISSUE -ENB_PROCESS_NOLOGFILE_TO_ANALYZE = CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE -ENB_PROCESS_SLAVE_RRU_NOT_SYNCED = CONST.ENB_PROCESS_SLAVE_RRU_NOT_SYNCED -HSS_PROCESS_FAILED = CONST.HSS_PROCESS_FAILED -HSS_PROCESS_OK = CONST.HSS_PROCESS_OK -MME_PROCESS_FAILED = CONST.MME_PROCESS_FAILED -MME_PROCESS_OK = CONST.MME_PROCESS_OK -SPGW_PROCESS_FAILED = CONST.SPGW_PROCESS_FAILED -SPGW_PROCESS_OK = CONST.SPGW_PROCESS_OK -UE_IP_ADDRESS_ISSUE = CONST.UE_IP_ADDRESS_ISSUE -OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE = CONST.OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE -OAI_UE_PROCESS_COULD_NOT_SYNC = CONST.OAI_UE_PROCESS_COULD_NOT_SYNC -OAI_UE_PROCESS_ASSERTION = CONST.OAI_UE_PROCESS_ASSERTION -OAI_UE_PROCESS_FAILED = CONST.OAI_UE_PROCESS_FAILED -OAI_UE_PROCESS_NO_TUNNEL_INTERFACE = CONST.OAI_UE_PROCESS_NO_TUNNEL_INTERFACE -OAI_UE_PROCESS_SEG_FAULT = CONST.OAI_UE_PROCESS_SEG_FAULT -OAI_UE_PROCESS_OK = CONST.OAI_UE_PROCESS_OK - -UE_STATUS_DETACHED = CONST.UE_STATUS_DETACHED -UE_STATUS_DETACHING = CONST.UE_STATUS_DETACHING -UE_STATUS_ATTACHING = CONST.UE_STATUS_ATTACHING -UE_STATUS_ATTACHED = CONST.UE_STATUS_ATTACHED - -X2_HO_REQ_STATE__IDLE = CONST.X2_HO_REQ_STATE__IDLE -X2_HO_REQ_STATE__TARGET_RECEIVES_REQ = CONST.X2_HO_REQ_STATE__TARGET_RECEIVES_REQ -X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE = CONST.X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE -X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ = CONST.X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ -X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK = CONST.X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK #----------------------------------------------------------- # Class Declaration #----------------------------------------------------------- class RANManagement(): + def __init__(self): - # self.FailReportCnt = 0 - # self.prematureExit = False + + self.prematureExit = False self.ranRepository = '' self.ranBranch = '' self.ranAllowMerge = False @@ -77,14 +76,6 @@ class RANManagement(): self.eNB2UserName = '' self.eNB2Password = '' self.eNB2SourceCodePath = '' - #self.ADBIPAddress = '' - #self.ADBUserName = '' - #self.ADBPassword = '' - #self.ADBCentralized = True - self.testCase_id = '' - #self.testXMLfiles = [] - #self.nbTestXMLfiles = 0 - #self.desc = '' self.Build_eNB_args = '' self.backgroundBuild = False self.backgroundBuildTestId = ['', '', ''] @@ -96,60 +87,11 @@ class RANManagement(): self.eNBLogFiles = ['', '', ''] self.eNBOptions = ['', '', ''] self.eNBmbmsEnables = [False, False, False] - self.eNBstatuses = [-1, -1, -1] - #self.ping_args = '' - #self.ping_packetloss_threshold = '' - #self.iperf_args = '' - #self.iperf_packetloss_threshold = '' - #self.iperf_profile = '' - #self.iperf_options = '' - #self.nbMaxUEtoAttach = -1 - #self.UEDevices = [] - #self.UEDevicesStatus = [] - #self.UEDevicesRemoteServer = [] - #self.UEDevicesRemoteUser = [] - #self.UEDevicesOffCmd = [] - #self.UEDevicesOnCmd = [] - #self.UEDevicesRebootCmd = [] - #self.CatMDevices = [] - #self.UEIPAddresses = [] - #self.htmlFile = '' - #self.htmlHeaderCreated = False - #self.htmlFooterCreated = False - #self.htmlUEConnected = -1 - #self.htmleNBFailureMsg = '' - #self.htmlUEFailureMsg = '' - #self.picocom_closure = False - #self.idle_sleep_time = 0 - #self.x2_ho_options = 'network' - #self.x2NbENBs = 0 - #self.x2ENBBsIds = [] - #self.x2ENBConnectedUEs = [] - #self.htmlTabRefs = [] - #self.htmlTabNames = [] - #self.htmlTabIcons = [] - #self.repeatCounts = [] - #self.finalStatus = False - #self.OsVersion = '' - #self.KernelVersion = '' - #self.UhdVersion = '' - #self.UsrpBoard = '' - #self.CpuNb = '' - #self.CpuModel = '' - #self.CpuMHz = '' - #self.UEIPAddress = '' - #self.UEUserName = '' - #self.UEPassword = '' - #self.UE_instance = '' - #self.UESourceCodePath = '' - #self.UELogFile = '' - #self.Build_OAI_UE_args = '' - #self.Initialize_OAI_UE_args = '' - #self.clean_repository = True - self.flexranCtrlInstalled = False - self.flexranCtrlStarted = False - #self.expectedNbOfConnectedUEs = 0 - #self.startTime = 0 + +#----------------------------------------------------------- +# Setters and Getters +#----------------------------------------------------------- + def SettestCase_id(self,tcid): self.testCase_id = tcid @@ -247,10 +189,8 @@ class RANManagement(): self.eNBstatuses = enbstatus def GeteNBstatuses(self): return self.eNBstatuses - - - - def SeteNB1IPAddress(self, enb1ip): + self.eNB1IPAddress = enb1ip + def SeteNB1IPAddress(self,enb1ip): self.eNB1IPAddress = enb1ip def GeteNB1IPAddress(self): return self.eNB1IPAddress @@ -267,7 +207,7 @@ class RANManagement(): def GeteNB1SourceCodePath(self): return self.eNB1SourceCodePath - def SeteNB2IPAddress(self, enbip): + def SeteNB2IPAddress(self, enb2ip): self.eNB2IPAddress = enb2ip def GeteNB2IPAddress(self): return self.eNB2IPAddress @@ -289,6 +229,11 @@ class RANManagement(): def GetprematureExit(self): return self.prematureExit +#----------------------------------------------------------- +# RAN management functions +#----------------------------------------------------------- + + def BuildeNB(self): myHTML = HTML.HTMLManagement() @@ -296,10 +241,7 @@ class RANManagement(): GenericHelp(Version) sys.exit('Insufficient Parameter') if self.eNB_serverId == '0': - #checkpoint enB_serverId lIpAddr = self.eNBIPAddress - print(self.eNBIPAddress + 'self.eNBIPAddress') - print(lIpAddr + 'lIpAddr') lUserName = self.eNBUserName lPassWord = self.eNBPassword lSourcePath = self.eNBSourceCodePath @@ -313,7 +255,6 @@ class RANManagement(): lUserName = self.eNB2UserName lPassWord = self.eNB2Password lSourcePath = self.eNB2SourceCodePath - print(lIpAddr + 'just before the error') if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': GenericHelp(Version) sys.exit('Insufficient Parameter') @@ -368,7 +309,7 @@ class RANManagement(): mismatch = True if not mismatch: mySSH.close() - myHTML.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) + myHTML.CreateHtmlTestRow(self.Build_eNB_args, 'OK', CONST.ALL_PROCESSES_OK) return mySSH.command('echo ' + lPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30) @@ -394,7 +335,7 @@ class RANManagement(): mySSH.command('chmod 775 ./my-lte-softmodem-build.sh', '\$', 5) mySSH.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=build_enb_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/compile_oai_enb.log ./my-lte-softmodem-build.sh', '\$', 5) mySSH.close() - myHTML.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) + myHTML.CreateHtmlTestRow(self.Build_eNB_args, 'OK', CONST.ALL_PROCESSES_OK) self.backgroundBuildTestId[int(self.eNB_instance)] = self.testCase_id return mySSH.command('stdbuf -o0 ./build_oai ' + self.Build_eNB_args + ' 2>&1 | stdbuf -o0 tee compile_oai_enb.log', 'Bypassing the Tests|build have failed', 1500) @@ -485,10 +426,10 @@ class RANManagement(): if buildStatus: logging.info('\u001B[1m Building OAI ' + nodeB_prefix + 'NB Pass\u001B[0m') - myHTML.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) + myHTML.CreateHtmlTestRow(self.Build_eNB_args, 'OK', CONST.ALL_PROCESSES_OK) else: logging.error('\u001B[1m Building OAI ' + nodeB_prefix + 'NB Failed\u001B[0m') - myHTML.CreateHtmlTestRow(self.Build_eNB_args, 'KO', ALL_PROCESSES_OK) + myHTML.CreateHtmlTestRow(self.Build_eNB_args, 'KO', CONST.ALL_PROCESSES_OK) myHTML.CreateHtmlTabFooter(False) sys.exit(1) @@ -514,9 +455,7 @@ class RANManagement(): GenericHelp(Version) sys.exit('Insufficient Parameter') mySSH = SSH.SSHConnection() - #check_eNB = False - #check_OAI_UE = False - #pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) + if (self.pStatus < 0): myHTML.CreateHtmlTestRow(self.Initialize_eNB_args, 'KO', self.pStatus) myHTML.CreateHtmlTabFooter(False) @@ -620,7 +559,7 @@ class RANManagement(): mySSH.close() doLoop = False logging.error('\u001B[1;37;41m eNB logging system did not show got sync! \u001B[0m') - myHTML.CreateHtmlTestRow('-O ' + config_file + extra_options, 'KO', ALL_PROCESSES_OK) + myHTML.CreateHtmlTestRow('-O ' + config_file + extra_options, 'KO', CONST.ALL_PROCESSES_OK) # In case of T tracer recording, we need to kill tshark on EPC side result = re.search('T_stdout', str(self.Initialize_eNB_args)) if result is not None: @@ -670,7 +609,7 @@ class RANManagement(): self.eNBstatuses[int(self.eNB_instance)] = int(self.eNB_serverId) mySSH.close() - myHTML.CreateHtmlTestRow('-O ' + config_file + extra_options, 'OK', ALL_PROCESSES_OK) + myHTML.CreateHtmlTestRow('-O ' + config_file + extra_options, 'OK', CONST.ALL_PROCESSES_OK) logging.debug('\u001B[1m Initialize eNB Completed\u001B[0m') @@ -700,9 +639,9 @@ class RANManagement(): result = re.search(self.air_interface + '-softmodem', mySSH.getBefore()) if result is None: logging.debug('\u001B[1;37;41m eNB Process Not Found! \u001B[0m') - status_queue.put(ENB_PROCESS_FAILED) + status_queue.put(CONST.ENB_PROCESS_FAILED) else: - status_queue.put(ENB_PROCESS_OK) + status_queue.put(CONST.ENB_PROCESS_OK) mySSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) @@ -776,7 +715,7 @@ class RANManagement(): mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + extracted_log_file, '.') logging.debug('\u001B[1m Analyzing eNB replay logfile \u001B[0m') logStatus = self.AnalyzeLogFile_eNB(extracted_log_file) - myHTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + myHTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) self.eNBLogFiles[int(self.eNB_instance)] = '' else: analyzeFile = False @@ -789,7 +728,7 @@ class RANManagement(): if (copyin_res == -1): logging.debug('\u001B[1;37;41m Could not copy ' + nodeB_prefix + 'NB logfile to analyze it! \u001B[0m') self.htmleNBFailureMsg = 'Could not copy ' + nodeB_prefix + 'NB logfile to analyze it!' - myHTML.CreateHtmlTestRow('N/A', 'KO', ENB_PROCESS_NOLOGFILE_TO_ANALYZE) + myHTML.CreateHtmlTestRow('N/A', 'KO', CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE) self.eNBmbmsEnables[int(self.eNB_instance)] = False return if self.eNB_serverId != '0': @@ -802,9 +741,9 @@ class RANManagement(): self.eNBmbmsEnables[int(self.eNB_instance)] = False return else: - myHTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + myHTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) else: - myHTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + myHTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) self.eNBmbmsEnables[int(self.eNB_instance)] = False self.eNBstatuses[int(self.eNB_instance)] = -1 @@ -849,34 +788,34 @@ class RANManagement(): isRRU = False isSlave = False slaveReceivesFrameResyncCmd = False - X2HO_state = X2_HO_REQ_STATE__IDLE + X2HO_state = CONST.X2_HO_REQ_STATE__IDLE X2HO_inNbProcedures = 0 X2HO_outNbProcedures = 0 for line in enb_log_file.readlines(): - if X2HO_state == X2_HO_REQ_STATE__IDLE: + if X2HO_state == CONST.X2_HO_REQ_STATE__IDLE: result = re.search('target eNB Receives X2 HO Req X2AP_HANDOVER_REQ', str(line)) if result is not None: - X2HO_state = X2_HO_REQ_STATE__TARGET_RECEIVES_REQ + X2HO_state = CONST.X2_HO_REQ_STATE__TARGET_RECEIVES_REQ result = re.search('source eNB receives the X2 HO ACK X2AP_HANDOVER_REQ_ACK', str(line)) if result is not None: - X2HO_state = X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK - if X2HO_state == X2_HO_REQ_STATE__TARGET_RECEIVES_REQ: + X2HO_state = CONST.X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK + if X2HO_state == CONST.X2_HO_REQ_STATE__TARGET_RECEIVES_REQ: result = re.search('Received LTE_RRCConnectionReconfigurationComplete from UE', str(line)) if result is not None: - X2HO_state = X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE - if X2HO_state == X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE: + X2HO_state = CONST.X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE + if X2HO_state == CONST.X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE: result = re.search('issue rrc_eNB_send_PATH_SWITCH_REQ', str(line)) if result is not None: - X2HO_state = X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ - if X2HO_state == X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ: + X2HO_state = CONST.X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ + if X2HO_state == CONST.X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ: result = re.search('received path switch ack S1AP_PATH_SWITCH_REQ_ACK', str(line)) if result is not None: - X2HO_state = X2_HO_REQ_STATE__IDLE + X2HO_state = CONST.X2_HO_REQ_STATE__IDLE X2HO_inNbProcedures += 1 - if X2HO_state == X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK: + if X2HO_state == CONST.X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK: result = re.search('source eNB receives the X2 UE CONTEXT RELEASE X2AP_UE_CONTEXT_RELEASE', str(line)) if result is not None: - X2HO_state = X2_HO_REQ_STATE__IDLE + X2HO_state = CONST.X2_HO_REQ_STATE__IDLE X2HO_outNbProcedures += 1 if self.eNBOptions[int(self.eNB_instance)] != '': @@ -1057,14 +996,14 @@ class RANManagement(): logging.debug('\u001B[1;37;41m ' + rruMsg + ' \u001B[0m') self.htmleNBFailureMsg += rruMsg + '\n' self.prematureExit(True) - return ENB_PROCESS_SLAVE_RRU_NOT_SYNCED + return CONST.ENB_PROCESS_SLAVE_RRU_NOT_SYNCED if foundSegFault: logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB ended with a Segmentation Fault! \u001B[0m') - return ENB_PROCESS_SEG_FAULT + return CONST.ENB_PROCESS_SEG_FAULT if foundAssertion: logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB ended with an assertion! \u001B[0m') self.htmleNBFailureMsg += msgAssertion - return ENB_PROCESS_ASSERTION + return CONST.ENB_PROCESS_ASSERTION if foundRealTimeIssue: logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB faced real time issues! \u001B[0m') self.htmleNBFailureMsg += nodeB_prefix + 'NB faced real time issues!\n' @@ -1073,5 +1012,5 @@ class RANManagement(): rlcMsg = nodeB_prefix + 'NB RLC discarded ' + str(rlcDiscardBuffer) + ' buffer(s)' logging.debug('\u001B[1;37;41m ' + rlcMsg + ' \u001B[0m') self.htmleNBFailureMsg += rlcMsg + '\n' - return ENB_PROCESS_REALTIME_ISSUE + return CONST.ENB_PROCESS_REALTIME_ISSUE return 0 diff --git a/ci-scripts/sshconnection.py b/ci-scripts/sshconnection.py index df1ada4834..ecaf8f4116 100644 --- a/ci-scripts/sshconnection.py +++ b/ci-scripts/sshconnection.py @@ -1,3 +1,34 @@ + +# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +# * contributor license agreements. See the NOTICE file distributed with +# * this work for additional information regarding copyright ownership. +# * The OpenAirInterface Software Alliance licenses this file to You under +# * the OAI Public License, Version 1.1 (the "License"); you may not use this file +# * except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.openairinterface.org/?page_id=698 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# *------------------------------------------------------------------------------- +# * For more information about the OpenAirInterface (OAI) Software Alliance: +# * contact@openairinterface.org +# */ +#--------------------------------------------------------------------- +# Python for CI of OAI-eNB + COTS-UE +# +# Required Python Version +# Python 3.x +# +# Required Python Package +# pexpect +#--------------------------------------------------------------------- + + #----------------------------------------------------------- # Import #----------------------------------------------------------- From e9c6872bb91c8e48d7006f3b14e011e1414aca6e Mon Sep 17 00:00:00 2001 From: OAI Jenkins Date: Fri, 20 Mar 2020 14:09:51 +0100 Subject: [PATCH 092/240] minor modifications during a lease on inria fit14 to keep on debugging main, html, ran.py etc. --- ci-scripts/html.py | 3 +++ ci-scripts/main_enb.py | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/ci-scripts/html.py b/ci-scripts/html.py index e8930f6e2c..3c0544c3cf 100644 --- a/ci-scripts/html.py +++ b/ci-scripts/html.py @@ -50,6 +50,9 @@ class HTMLManagement(): self.htmlTabNames = [] self.htmlTabIcons = [] self.testXMLfiles = [] + self.htmlHeaderCreated = False + self.htmlFooterCreated = False + #----------------------------------------------------------- # Setters and Getters #----------------------------------------------------------- diff --git a/ci-scripts/main_enb.py b/ci-scripts/main_enb.py index a42aba76e2..3b3428eec4 100644 --- a/ci-scripts/main_enb.py +++ b/ci-scripts/main_enb.py @@ -87,8 +87,8 @@ class OaiCiTest(): self.CatMDevices = [] self.UEIPAddresses = [] self.htmlFile = '' - self.htmlHeaderCreated = False - self.htmlFooterCreated = False + # self.htmlHeaderCreated = False + # self.htmlFooterCreated = False self.htmlUEConnected = -1 self.htmleNBFailureMsg = '' self.htmlUEFailureMsg = '' From 897ca561f57bb47df08a36ed7f854953080ab06d Mon Sep 17 00:00:00 2001 From: Florian Kaltenberger Date: Mon, 23 Mar 2020 17:45:48 +0100 Subject: [PATCH 093/240] adding time_source command line parameter and removing duplications of clock_source ignoring command line paramters clock_source and time_source in lte-softmodem and harmonizing it with nr-softmodem time_source and clock_source handled separately in usrp_lib.cpp --- executables/nr-ru.c | 18 +++++++++ executables/nr-uesoftmodem.c | 4 +- executables/nr-uesoftmodem.h | 1 - executables/softmodem-common.h | 4 +- openair2/ENB_APP/enb_paramdef.h | 13 +++--- targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 42 +++++++++++++++----- targets/RT/USER/lte-ru.c | 26 ++++++++++-- targets/RT/USER/lte-softmodem.c | 2 +- targets/RT/USER/lte-softmodem.h | 4 +- targets/RT/USER/lte-uesoftmodem.c | 7 +--- targets/RT/USER/rfsim.c | 4 +- 11 files changed, 90 insertions(+), 35 deletions(-) diff --git a/executables/nr-ru.c b/executables/nr-ru.c index fe10988462..32b5ae3ba9 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -2298,6 +2298,24 @@ void RCconfig_RU(void) RC.ru[j]->openair0_cfg.clock_source = unset; } + if (config_isparamset(RUParamList.paramarray[j], RU_SDR_TME_SRC)) { + if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "internal") == 0) { + RC.ru[j]->openair0_cfg.time_source = internal; + LOG_D(PHY, "RU time source set as internal\n"); + } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "external") == 0) { + RC.ru[j]->openair0_cfg.time_source = external; + LOG_D(PHY, "RU time source set as external\n"); + } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "gpsdo") == 0) { + RC.ru[j]->openair0_cfg.time_source = gpsdo; + LOG_D(PHY, "RU time source set as gpsdo\n"); + } else { + LOG_E(PHY, "Erroneous RU time source in the provided configuration file: '%s'\n", *(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr)); + } + } + else { + RC.ru[j]->openair0_cfg.time_source = unset; + } + if (strcmp(*(RUParamList.paramarray[j][RU_LOCAL_RF_IDX].strptr), "yes") == 0) { if ( !(config_isparamset(RUParamList.paramarray[j],RU_LOCAL_IF_NAME_IDX)) ) { RC.ru[j]->if_south = LOCAL_RF; diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 53e407923f..b0cb899b54 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -127,7 +127,6 @@ volatile int start_eNB = 0; volatile int start_UE = 0; volatile int oai_exit = 0; -static clock_source_t clock_source = unset; int single_thread_flag=1; static double snr_dB=20; @@ -597,7 +596,8 @@ void init_openair0(void) { PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx); openair0_cfg[card].Mod_id = 0; openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; - openair0_cfg[card].clock_source = clock_source; + openair0_cfg[card].clock_source = get_softmodem_params()->clock_source; + openair0_cfg[card].time_source = get_softmodem_params()->timing_source; openair0_cfg[card].tx_num_channels=min(2,PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx); openair0_cfg[card].rx_num_channels=min(2,PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx); diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index 7fad43e897..ba293324e3 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -59,7 +59,6 @@ /* optname helpstr paramflags XXXptr defXXXval type numelt */ /*----------------------------------------------------------------------------------------------------------------------------------------------------*/ #define CMDLINE_PARAMS_DESC_UE { \ - {"clock-source", CONFIG_HLP_EXCCLK, 0, iptr:&clock_source, defintval:0, TYPE_INT, 0}, \ {"single-thread-disable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&single_thread_flag, defintval:1, TYPE_INT, 0}, \ {"nr-dlsch-demod-shift", CONFIG_HLP_DLSHIFT, 0, iptr:(int32_t *)&nr_dlsch_demod_shift, defintval:0, TYPE_INT, 0}, \ {"A" , CONFIG_HLP_TADV, 0, uptr:&timing_advance, defintval:0, TYPE_UINT, 0}, \ diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index cfed951469..2fac7d825e 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -53,6 +53,7 @@ extern "C" #define CONFIG_HLP_EXTS "tells hardware to use an external timing reference\n" #define CONFIG_HLP_DMRSSYNC "tells RU to insert DMRS in subframe 1 slot 0" #define CONFIG_HLP_CLK "tells hardware to use a clock reference (0:internal, 1:external, 2:gpsdo)\n" +#define CONFIG_HLP_TME "tells hardware to use a time reference (0:internal, 1:external, 2:gpsdo)\n" #define CONFIG_HLP_USIM "use XOR autentication algo in case of test usim mode\n" #define CONFIG_HLP_NOSNGLT "Disables single-thread mode in lte-softmodem\n" #define CONFIG_HLP_DLF "Set the downlink frequency for all component carriers\n" @@ -105,7 +106,8 @@ extern "C" {"rf-config-file", CONFIG_HLP_RFCFGF, 0, strptr:(char **)&RF_CONFIG_FILE, defstrval:NULL, TYPE_STRING, sizeof(RF_CONFIG_FILE)},\ {"phy-test", CONFIG_HLP_PHYTST, PARAMFLAG_BOOL, iptr:&PHY_TEST, defintval:0, TYPE_INT, 0}, \ {"usim-test", CONFIG_HLP_USIM, PARAMFLAG_BOOL, u8ptr:&USIM_TEST, defintval:0, TYPE_UINT8, 0}, \ - {"clock", CONFIG_HLP_CLK, 0, uptr:&CLOCK_SOURCE, defintval:0, TYPE_UINT, 0}, \ + {"clock-source", CONFIG_HLP_CLK, 0, uptr:&CLOCK_SOURCE, defintval:0, TYPE_UINT, 0}, \ + {"time-source", CONFIG_HLP_TME, 0, uptr:&TIMING_SOURCE, defintval:0, TYPE_UINT, 0}, \ {"wait-for-sync", NULL, PARAMFLAG_BOOL, iptr:&WAIT_FOR_SYNC, defintval:0, TYPE_INT, 0}, \ {"single-thread-enable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&SINGLE_THREAD_FLAG, defintval:0, TYPE_INT, 0}, \ {"C" , CONFIG_HLP_DLF, 0, u64ptr:&(downlink_frequency[0][0]), defuintval:0, TYPE_UINT64, 0}, \ diff --git a/openair2/ENB_APP/enb_paramdef.h b/openair2/ENB_APP/enb_paramdef.h index f91c7056c5..344214a1f1 100644 --- a/openair2/ENB_APP/enb_paramdef.h +++ b/openair2/ENB_APP/enb_paramdef.h @@ -90,6 +90,7 @@ typedef enum { #define CONFIG_STRING_RU_NBIOTRRC_LIST "NbIoT_RRC_instances" #define CONFIG_STRING_RU_SDR_ADDRS "sdr_addrs" #define CONFIG_STRING_RU_SDR_CLK_SRC "clock_src" +#define CONFIG_STRING_RU_SDR_TME_SRC "time_src" #define CONFIG_STRING_RU_SF_EXTENSION "sf_extension" #define CONFIG_STRING_RU_END_OF_BURST_DELAY "end_of_burst_delay" #define CONFIG_STRING_RU_OTA_SYNC_ENABLE "ota_sync_enabled" @@ -117,11 +118,12 @@ typedef enum { #define RU_NBIOTRRC_LIST_IDX 18 #define RU_SDR_ADDRS 19 #define RU_SDR_CLK_SRC 20 -#define RU_SF_EXTENSION_IDX 21 -#define RU_END_OF_BURST_DELAY_IDX 22 -#define RU_OTA_SYNC_ENABLE_IDX 23 -#define RU_BF_WEIGHTS_LIST_IDX 24 -#define RU_IF_FREQUENCY 25 +#define RU_SDR_TME_SRC 21 +#define RU_SF_EXTENSION_IDX 22 +#define RU_END_OF_BURST_DELAY_IDX 23 +#define RU_OTA_SYNC_ENABLE_IDX 24 +#define RU_BF_WEIGHTS_LIST_IDX 25 +#define RU_IF_FREQUENCY 26 /*-----------------------------------------------------------------------------------------------------------------------------------------*/ /* RU configuration parameters */ @@ -149,6 +151,7 @@ typedef enum { {CONFIG_STRING_RU_NBIOTRRC_LIST, NULL, 0, uptr:NULL, defintarrayval:DEFENBS, TYPE_INTARRAY, 1}, \ {CONFIG_STRING_RU_SDR_ADDRS, NULL, 0, strptr:NULL, defstrval:"type=b200", TYPE_STRING, 0}, \ {CONFIG_STRING_RU_SDR_CLK_SRC, NULL, 0, strptr:NULL, defstrval:"internal", TYPE_STRING, 0}, \ + {CONFIG_STRING_RU_SDR_TME_SRC, NULL, 0, strptr:NULL, defstrval:"internal", TYPE_STRING, 0}, \ {CONFIG_STRING_RU_SF_EXTENSION, NULL, 0, uptr:NULL, defuintval:312, TYPE_UINT, 0}, \ {CONFIG_STRING_RU_END_OF_BURST_DELAY, NULL, 0, uptr:NULL, defuintval:400, TYPE_UINT, 0}, \ {CONFIG_STRING_RU_OTA_SYNC_ENABLE, NULL, 0, strptr:NULL, defstrval:"no", TYPE_STRING, 0}, \ diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index f37c8cf5cf..90b0a2e554 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -835,22 +835,16 @@ extern "C" { if (args.find("clock_source")==std::string::npos) { if (openair0_cfg[0].clock_source == internal) { - //in UHD 3.14 we could use - //s->usrp->set_sync_source("clock_source=internal","time_source=internal"); - s->usrp->set_time_source("internal"); s->usrp->set_clock_source("internal"); - LOG_D(HW,"Setting time and clock source to internal\n"); + LOG_D(HW,"Setting clock source to internal\n"); } else if (openair0_cfg[0].clock_source == external ) { - //s->usrp->set_sync_source("clock_source=external","time_source=external"); - s->usrp->set_time_source("external"); s->usrp->set_clock_source("external"); - LOG_D(HW,"Setting time and clock source to external\n"); + LOG_D(HW,"Setting clock source to external\n"); } else if (openair0_cfg[0].clock_source==gpsdo) { s->usrp->set_clock_source("gpsdo"); - s->usrp->set_time_source("gpsdo"); - LOG_D(HW,"Setting time and clock source to gpsdo\n"); + LOG_D(HW,"Setting clock source to gpsdo\n"); } else { LOG_W(HW,"Clock source set neither in usrp_args nor on command line, using default!\n"); @@ -861,7 +855,31 @@ extern "C" { LOG_W(HW,"Clock source set in both usrp_args and in clock_source, ingnoring the latter!\n"); } } - + + if (args.find("time_source")==std::string::npos) { + if (openair0_cfg[0].time_source == internal) { + s->usrp->set_time_source("internal"); + LOG_D(HW,"Setting time source to internal\n"); + } + else if (openair0_cfg[0].time_source == external ) { + s->usrp->set_time_source("external"); + LOG_D(HW,"Setting time source to external\n"); + } + else if (openair0_cfg[0].time_source==gpsdo) { + s->usrp->set_time_source("gpsdo"); + LOG_D(HW,"Setting time source to gpsdo\n"); + } + else { + LOG_W(HW,"Time source set neither in usrp_args nor on command line, using default!\n"); + } + } + else { + if (openair0_cfg[0].clock_source != unset) { + LOG_W(HW,"Time source set in both usrp_args and in time_source, ingnoring the latter!\n"); + } + } + + if (s->usrp->get_clock_source(0) == "gpsdo") { s->use_gps = 1; @@ -1061,7 +1079,9 @@ extern "C" { //s->usrp->set_time_source("external"); // display USRP settings LOG_I(HW,"Actual master clock: %fMHz...\n",s->usrp->get_master_clock_rate()/1e6); - sleep(1); + LOG_I(HW,"Actual clock source %s...\n",s->usrp->get_clock_source(0).c_str()); + LOG_I(HW,"Actual time source %s...\n",s->usrp->get_time_source(0).c_str()); + sleep(1); // create tx & rx streamer uhd::stream_args_t stream_args_rx("sc16", "sc16"); int samples=openair0_cfg[0].sample_rate; diff --git a/targets/RT/USER/lte-ru.c b/targets/RT/USER/lte-ru.c index e6364cad23..437e640520 100644 --- a/targets/RT/USER/lte-ru.c +++ b/targets/RT/USER/lte-ru.c @@ -1405,7 +1405,6 @@ void fill_rf_config(RU_t *ru, cfg->num_rb_dl=fp->N_RB_DL; cfg->tx_num_channels=ru->nb_tx; cfg->rx_num_channels=ru->nb_rx; - cfg->clock_source=get_softmodem_params()->clock_source; for (int i=0; inb_tx; i++) { cfg->tx_freq[i] = (double)fp->dl_CarrierFreq; @@ -2683,7 +2682,7 @@ void set_function_spec_param(RU_t *ru) { //extern void RCconfig_RU(void); -void init_RU(char *rf_config_file, clock_source_t clock_source, clock_source_t time_source, int send_dmrssync) { +void init_RU(char *rf_config_file, int send_dmrssync) { int ru_id, i, CC_id; RU_t *ru; PHY_VARS_eNB *eNB0 = (PHY_VARS_eNB *)NULL; @@ -2718,8 +2717,6 @@ void init_RU(char *rf_config_file, clock_source_t clock_source, clock_source_t t ru->south_out_cnt = 0; // use eNB_list[0] as a reference for RU frame parameters // NOTE: multiple CC_id are not handled here yet! - ru->openair0_cfg.clock_source = clock_source; - ru->openair0_cfg.time_source = time_source; //ru->generate_dmrs_sync = (ru->is_slave == 0) ? 1 : 0; if ((ru->is_slave == 0) && (ru->ota_sync_enable == 1)) @@ -2956,6 +2953,27 @@ void RCconfig_RU(void) { LOG_E(PHY, "Erroneous RU clock source in the provided configuration file: '%s'\n", *(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr)); } } + else { + RC.ru[j]->openair0_cfg.clock_source = unset; + } + + if (config_isparamset(RUParamList.paramarray[j], RU_SDR_TME_SRC)) { + if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "internal") == 0) { + RC.ru[j]->openair0_cfg.time_source = internal; + LOG_D(PHY, "RU time source set as internal\n"); + } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "external") == 0) { + RC.ru[j]->openair0_cfg.time_source = external; + LOG_D(PHY, "RU time source set as external\n"); + } else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "gpsdo") == 0) { + RC.ru[j]->openair0_cfg.time_source = gpsdo; + LOG_D(PHY, "RU time source set as gpsdo\n"); + } else { + LOG_E(PHY, "Erroneous RU time source in the provided configuration file: '%s'\n", *(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr)); + } + } + else { + RC.ru[j]->openair0_cfg.time_source = unset; + } if (strcmp(*(RUParamList.paramarray[j][RU_LOCAL_RF_IDX].strptr), "yes") == 0) { if ( !(config_isparamset(RUParamList.paramarray[j],RU_LOCAL_IF_NAME_IDX)) ) { diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 0b365ea938..dd77ca2d24 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -654,7 +654,7 @@ int main ( int argc, char **argv ) // some initialization is necessary and init_ru_vnf do this. if (RC.nb_RU >0 && NFAPI_MODE!=NFAPI_MODE_VNF) { printf("Initializing RU threads\n"); - init_RU(get_softmodem_params()->rf_config_file,get_softmodem_params()->clock_source,get_softmodem_params()->timing_source,get_softmodem_params()->send_dmrs_sync); + init_RU(get_softmodem_params()->rf_config_file,get_softmodem_params()->send_dmrs_sync); for (ru_id=0; ru_idrf_map.card=0; diff --git a/targets/RT/USER/lte-softmodem.h b/targets/RT/USER/lte-softmodem.h index 5e1bf36160..c5fdb5f546 100644 --- a/targets/RT/USER/lte-softmodem.h +++ b/targets/RT/USER/lte-softmodem.h @@ -81,7 +81,6 @@ #define CONFIG_HLP_DLSHIFT "dynamic shift for LLR compuation for TM3/4 (default 0)\n" #define CONFIG_HLP_USRP_ARGS "set the arguments to identify USRP (same syntax as in UHD)\n" #define CONFIG_HLP_DMAMAP "sets flag for improved EXMIMO UE performance\n" -#define CONFIG_HLP_CLK "tells hardware to use a clock reference (0:internal, 1:external, 2:gpsdo)\n" #define CONFIG_HLP_TDD "Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n" #define CONFIG_HLP_TADV "Set timing_advance\n" @@ -115,7 +114,6 @@ {"dlsch-demod-shift", CONFIG_HLP_DLSHIFT, 0, iptr:(int32_t *)&dlsch_demod_shift, defintval:0, TYPE_INT, 0}, \ {"usrp-args", CONFIG_HLP_USRP_ARGS, 0, strptr:(char **)&usrp_args, defstrval:"type=b200",TYPE_STRING, 0}, \ {"mmapped-dma", CONFIG_HLP_DMAMAP, PARAMFLAG_BOOL, uptr:&mmapped_dma, defintval:0, TYPE_INT, 0}, \ - {"clock-source", CONFIG_HLP_CLK, 0, iptr:&clock_source, defintval:0, 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} \ } @@ -169,7 +167,7 @@ extern void init_RU_proc(RU_t *ru); extern void stop_RU(int nb_ru); extern void kill_RU_proc(RU_t *ru); extern void set_function_spec_param(RU_t *ru); -extern void init_RU(char *, clock_source_t clock_source, clock_source_t time_source, int send_dmrssync); +extern void init_RU(char *, int send_dmrssync); // In lte-ue.c extern int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg); diff --git a/targets/RT/USER/lte-uesoftmodem.c b/targets/RT/USER/lte-uesoftmodem.c index 25371260bf..b03c16af43 100644 --- a/targets/RT/USER/lte-uesoftmodem.c +++ b/targets/RT/USER/lte-uesoftmodem.c @@ -113,10 +113,6 @@ uint16_t runtime_phy_tx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, volatile int oai_exit = 0; - -clock_source_t clock_source = internal,time_source=internal; - - unsigned int mmapped_dma=0; @@ -467,7 +463,8 @@ void init_openair0(LTE_DL_FRAME_PARMS *frame_parms,int rxgain) { openair0_cfg[card].Mod_id = 0; openair0_cfg[card].num_rb_dl=frame_parms->N_RB_DL; - openair0_cfg[card].clock_source = clock_source; + openair0_cfg[card].clock_source = get_softmodem_params()->clock_source; + openair0_cfg[card].time_source = get_softmodem_params()->timing_source; openair0_cfg[card].tx_num_channels=min(2,frame_parms->nb_antennas_tx); openair0_cfg[card].rx_num_channels=min(2,frame_parms->nb_antennas_rx); diff --git a/targets/RT/USER/rfsim.c b/targets/RT/USER/rfsim.c index bd8305682c..a9a0912433 100644 --- a/targets/RT/USER/rfsim.c +++ b/targets/RT/USER/rfsim.c @@ -64,7 +64,7 @@ sim_t sim; void init_ru_devices(void); -void init_RU(char *,clock_source_t clock_source,clock_source_t time_source,int send_dmrssync); +void init_RU(char *,int send_dmrssync); void *rfsim_top(void *n_frames); @@ -101,7 +101,7 @@ void RCConfig_sim(void) { RC.nb_RU = RUParamList.numelt; AssertFatal(RC.nb_RU>0,"we need at least 1 RU for simulation\n"); printf("returned with %d rus\n",RC.nb_RU); - init_RU(NULL,internal,internal,0); + init_RU(NULL,0); printf("Waiting for RUs to get set up\n"); wait_RUs(); init_ru_devices(); From 6bbf9011ba0fb003ef11182251e531a0516f88bd Mon Sep 17 00:00:00 2001 From: laurent Date: Tue, 24 Mar 2020 19:16:13 +0100 Subject: [PATCH 094/240] compilation ok --- common/utils/ocp_itti/intertask_interface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/utils/ocp_itti/intertask_interface.cpp b/common/utils/ocp_itti/intertask_interface.cpp index 89e19074bf..5e86a69958 100644 --- a/common/utils/ocp_itti/intertask_interface.cpp +++ b/common/utils/ocp_itti/intertask_interface.cpp @@ -7,6 +7,7 @@ #include +extern "C" { #include #include @@ -35,7 +36,6 @@ typedef struct task_list_s { int timer_expired(int fd); task_list_t tasks[TASK_MAX]; -extern "C" { void *pool_buffer_init (void) { return 0; } From 34694363e296104c138eb34ac9b86785231347c7 Mon Sep 17 00:00:00 2001 From: Gabriele Perrone Date: Mon, 30 Mar 2020 17:34:23 +0200 Subject: [PATCH 095/240] clean up the HSS termination procedure using the screen command --- ci-scripts/epc.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ci-scripts/epc.py b/ci-scripts/epc.py index 4d88a69e75..6c48dcd15d 100644 --- a/ci-scripts/epc.py +++ b/ci-scripts/epc.py @@ -126,7 +126,6 @@ class EPCManagement(): mySSH.command('mkdir -p ' + self.EPCSourceCodePath + '/scripts', '\$', 5) mySSH.command('cd /opt/hss_sim0609', '\$', 5) mySSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f hss.log daemon.log', '\$', 5) - #mySSH.command('echo ' + self.EPCPassword + ' | sudo -S echo "Starting sudo session" && sudo daemon --unsafe --name=simulated_hss --chdir=/opt/hss_sim0609 ./starthss_real ', '\$', 5) mySSH.command('echo ' + self.EPCPassword + ' | sudo -S echo "Starting sudo session" && sudo su -c "screen -dm -S simulated_hss ./starthss"', '\$', 5) else: logging.error('This option should not occur!') @@ -288,10 +287,10 @@ class EPCManagement(): elif re.match('ltebox', self.EPCType, re.IGNORECASE): mySSH.command('cd ' + self.EPCSourceCodePath, '\$', 5) mySSH.command('cd scripts', '\$', 5) - mySSH.command('echo ' + self.EPCPassword + ' | sudo -S daemon --name=simulated_hss --stop', '\$', 5) + #mySSH.command('echo ' + self.EPCPassword + ' | sudo -S daemon --name=simulated_hss --stop', '\$', 5) time.sleep(1) #mySSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL hss_sim', '\$', 5) - mySSH.command('echo ' + self.EPCPassword + ' | sudo killall hss_sim', '\$', 5) + mySSH.command('echo ' + self.EPCPassword + ' | sudo screen -X -S simulated_hss quit', '\$', 5) else: logging.error('This should not happen!') mySSH.close() From ddfaa9af5e4dbb7f2b130b91433d02c641bf768a Mon Sep 17 00:00:00 2001 From: Gabriele Perrone Date: Mon, 30 Mar 2020 17:47:08 +0200 Subject: [PATCH 096/240] editorial on html.py --- ci-scripts/html.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ci-scripts/html.py b/ci-scripts/html.py index e8930f6e2c..1a2ae10dc0 100644 --- a/ci-scripts/html.py +++ b/ci-scripts/html.py @@ -46,6 +46,8 @@ class HTMLManagement(): def __init__(self): + self.htmlHeaderCreated = False + self.htmlFooterCreated = False self.htmlTabRefs = [] self.htmlTabNames = [] self.htmlTabIcons = [] From 296494ea4c010e0fb4cd8ca72fe69743a45c92b4 Mon Sep 17 00:00:00 2001 From: frtabu Date: Mon, 30 Mar 2020 00:23:28 +0200 Subject: [PATCH 097/240] create dft shared lib --- cmake_targets/CMakeLists.txt | 6 +- .../PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c | 8 +- openair1/PHY/LTE_ESTIMATION/lte_sync_time.c | 40 +-- .../lte_ul_channel_estimation.c | 16 +- openair1/PHY/LTE_TRANSPORT/prach.c | 46 +-- .../PHY/LTE_TRANSPORT/ulsch_demodulation.c | 204 ++++++------- openair1/PHY/MODULATION/ofdm_mod.c | 24 +- openair1/PHY/MODULATION/slot_fep_nr.c | 50 ++-- openair1/PHY/MODULATION/slot_fep_ul.c | 22 +- openair1/PHY/TOOLS/{lte_dfts.c => oai_dfts.c} | 115 +++++--- openair1/PHY/TOOLS/tools_defs.h | 279 ++++++++++++++---- 11 files changed, 494 insertions(+), 316 deletions(-) rename openair1/PHY/TOOLS/{lte_dfts.c => oai_dfts.c} (99%) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index e62d8fe33c..53714f5560 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -1327,6 +1327,9 @@ add_library(ldpc MODULE ${PHY_LDPC_OPTIM8SEGMULTI_SRC} ) add_library(coding MODULE ${PHY_TURBOSRC} ) +add_library(dfts MODULE ${OPENAIR1_DIR}/PHY/TOOLS/oai_dfts.c ) + + set(PHY_SRC_COMMON ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dci_tools_common.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/lte_mcs.c @@ -1368,7 +1371,7 @@ set(PHY_SRC_COMMON ${OPENAIR1_DIR}/PHY/INIT/lte_parms.c ${OPENAIR1_DIR}/PHY/INIT/lte_param_init.c ${OPENAIR1_DIR}/PHY/TOOLS/cadd_vv.c - ${OPENAIR1_DIR}/PHY/TOOLS/lte_dfts.c +# ${OPENAIR1_DIR}/PHY/TOOLS/lte_dfts.c ${OPENAIR1_DIR}/PHY/TOOLS/log2_approx.c ${OPENAIR1_DIR}/PHY/TOOLS/cmult_sv.c ${OPENAIR1_DIR}/PHY/TOOLS/cmult_vv.c @@ -1576,6 +1579,7 @@ endif () add_library(PHY_COMMON ${PHY_SRC_COMMON}) add_dependencies(PHY_COMMON rrc_flag) +add_dependencies(PHY_COMMON dfts) add_library(PHY ${PHY_SRC}) add_dependencies(PHY rrc_flag) add_library(PHY_UE ${PHY_SRC_UE}) diff --git a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c index 04fe19ecbc..aaa138fcd9 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c @@ -56,22 +56,22 @@ int lte_est_timing_advance(LTE_DL_FRAME_PARMS *frame_parms, // do ifft of channel estimate switch(frame_parms->N_RB_DL) { case 6: - dft128((int16_t*) <e_eNB_srs->srs_ch_estimates[aa][0], + dft(DFT_128,(int16_t*) <e_eNB_srs->srs_ch_estimates[aa][0], (int16_t*) lte_eNB_srs->srs_ch_estimates_time[aa], 1); break; case 25: - dft512((int16_t*) <e_eNB_srs->srs_ch_estimates[aa][0], + dft(DFT_512,(int16_t*) <e_eNB_srs->srs_ch_estimates[aa][0], (int16_t*) lte_eNB_srs->srs_ch_estimates_time[aa], 1); break; case 50: - dft1024((int16_t*) <e_eNB_srs->srs_ch_estimates[aa][0], + dft(DFT_1024,(int16_t*) <e_eNB_srs->srs_ch_estimates[aa][0], (int16_t*) lte_eNB_srs->srs_ch_estimates_time[aa], 1); break; case 100: - dft2048((int16_t*) <e_eNB_srs->srs_ch_estimates[aa][0], + dft(DFT_2048,(int16_t*) <e_eNB_srs->srs_ch_estimates[aa][0], (int16_t*) lte_eNB_srs->srs_ch_estimates_time[aa], 1); break; diff --git a/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c b/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c index 0c98bdc5a5..0d765a18b3 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c @@ -141,28 +141,28 @@ int lte_sync_time_init(LTE_DL_FRAME_PARMS *frame_parms ) // LTE_UE_COMMON *com switch (frame_parms->N_RB_DL) { case 6: - idft128((short*)syncF_tmp, /// complex input + idft(IDFT_128,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 25: - idft512((short*)syncF_tmp, /// complex input + idft(IDFT_512,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 50: - idft1024((short*)syncF_tmp, /// complex input + idft(IDFT_1024,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 75: - idft1536((short*)syncF_tmp, /// complex input + idft(IDFT_1536,(short*)syncF_tmp, /// complex input (short*)sync_tmp, 1); /// complex output break; case 100: - idft2048((short*)syncF_tmp, /// complex input + idft(IDFT_2048,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; @@ -189,28 +189,28 @@ int lte_sync_time_init(LTE_DL_FRAME_PARMS *frame_parms ) // LTE_UE_COMMON *com switch (frame_parms->N_RB_DL) { case 6: - idft128((short*)syncF_tmp, /// complex input + idft(IDFT_128,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 25: - idft512((short*)syncF_tmp, /// complex input + idft(IDFT_512,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 50: - idft1024((short*)syncF_tmp, /// complex input + idft(IDFT_1024,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 75: - idft1536((short*)syncF_tmp, /// complex input + idft(IDFT_1536,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 100: - idft2048((short*)syncF_tmp, /// complex input + idft(IDFT_2048,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; @@ -237,28 +237,28 @@ int lte_sync_time_init(LTE_DL_FRAME_PARMS *frame_parms ) // LTE_UE_COMMON *com switch (frame_parms->N_RB_DL) { case 6: - idft128((short*)syncF_tmp, /// complex input + idft(IDFT_128,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 25: - idft512((short*)syncF_tmp, /// complex input + idft(IDFT_512,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 50: - idft1024((short*)syncF_tmp, /// complex input + idft(IDFT_1024,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 75: - idft1536((short*)syncF_tmp, /// complex input + idft(IDFT_1536,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 100: - idft2048((short*)syncF_tmp, /// complex input + idft(IDFT_2048,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; @@ -492,28 +492,28 @@ int ru_sync_time_init(RU_t *ru) // LTE_UE_COMMON *common_vars switch (ru->frame_parms->N_RB_DL) { case 6: - idft128((int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), + idft(IDFT_128,(int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), ru->dmrssync, /// complex output 1); break; case 25: - idft512((int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), + idft(IDFT_512,(int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), ru->dmrssync, /// complex output 1); break; case 50: - idft1024((int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), + idft(IDFT_1024,(int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), ru->dmrssync, /// complex output 1); break; case 75: - idft1536((int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), + idft(IDFT_1536,(int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), ru->dmrssync, 1); /// complex output break; case 100: - idft2048((int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), + idft(IDFT_2048,(int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), ru->dmrssync, /// complex output 1); break; diff --git a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c index cb001f9dc4..f5543eda52 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c @@ -246,25 +246,25 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB, switch(frame_parms->N_RB_DL) { case 6: - idft128((int16_t *) temp_in_ifft_0, + idft(IDFT_128,(int16_t *) temp_in_ifft_0, (int16_t *) ul_ch_estimates_time[aa], 1); break; case 25: - idft512((int16_t *) temp_in_ifft_0, + idft(IDFT_512,(int16_t *) temp_in_ifft_0, (int16_t *) ul_ch_estimates_time[aa], 1); break; case 50: - idft1024((int16_t *) temp_in_ifft_0, + idft(IDFT_1024,(int16_t *) temp_in_ifft_0, (int16_t *) ul_ch_estimates_time[aa], 1); break; case 100: - idft2048((int16_t *) temp_in_ifft_0, + idft(IDFT_2048,(int16_t *) temp_in_ifft_0, (int16_t *) ul_ch_estimates_time[aa], 1); break; @@ -575,25 +575,25 @@ int32_t lte_ul_channel_estimation_RRU(LTE_DL_FRAME_PARMS *frame_parms, switch(frame_parms->N_RB_DL) { case 6: - idft128((int16_t *) temp_in_ifft_0, + idft(IDFT_128,(int16_t *) temp_in_ifft_0, (int16_t *) ul_ch_estimates_time[aa], 1); break; case 25: - idft512((int16_t *) temp_in_ifft_0, + idft(IDFT_512,(int16_t *) temp_in_ifft_0, (int16_t *) ul_ch_estimates_time[aa], 1); break; case 50: - idft1024((int16_t *) temp_in_ifft_0, + idft(IDFT_1024,(int16_t *) temp_in_ifft_0, (int16_t *) ul_ch_estimates_time[aa], 1); break; case 100: - idft2048((int16_t *) temp_in_ifft_0, + idft(IDFT_2048,(int16_t *) temp_in_ifft_0, (int16_t *) ul_ch_estimates_time[aa], 1); break; diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c index 3471f98af7..983e30c80a 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach.c +++ b/openair1/PHY/LTE_TRANSPORT/prach.c @@ -298,24 +298,24 @@ void rx_prach0(PHY_VARS_eNB *eNB, switch (fp->N_RB_UL) { case 6: if (prach_fmt == 4) { - dft256(prach2,rxsigF[aa],1); + dft(DFT_256,prach2,rxsigF[aa],1); } else { - dft1536(prach2,rxsigF[aa],1); + dft(DFT_1536,prach2,rxsigF[aa],1); if (prach_fmt>1) - dft1536(prach2+3072,rxsigF[aa]+3072,1); + dft(DFT_1536,prach2+3072,rxsigF[aa]+3072,1); } break; case 15: if (prach_fmt == 4) { - dft256(prach2,rxsigF[aa],1); + dft(DFT_256,prach2,rxsigF[aa],1); } else { - dft3072(prach2,rxsigF[aa],1); + dft(DFT_3072,prach2,rxsigF[aa],1); if (prach_fmt>1) - dft3072(prach2+6144,rxsigF[aa]+6144,1); + dft(DFT_3072,prach2+6144,rxsigF[aa]+6144,1); } break; @@ -323,13 +323,13 @@ void rx_prach0(PHY_VARS_eNB *eNB, case 25: default: if (prach_fmt == 4) { - dft1024(prach2,rxsigF[aa],1); + dft(DFT_1024,prach2,rxsigF[aa],1); fft_size = 1024; } else { - dft6144(prach2,rxsigF[aa],1); + dft(DFT_6144,prach2,rxsigF[aa],1); if (prach_fmt>1) - dft6144(prach2+12288,rxsigF[aa]+12288,1); + dft(DFT_6144,prach2+12288,rxsigF[aa]+12288,1); fft_size = 6144; } @@ -338,24 +338,24 @@ void rx_prach0(PHY_VARS_eNB *eNB, case 50: if (prach_fmt == 4) { - dft2048(prach2,rxsigF[aa],1); + dft(DFT_2048,prach2,rxsigF[aa],1); } else { - dft12288(prach2,rxsigF[aa],1); + dft(DFT_12288,prach2,rxsigF[aa],1); if (prach_fmt>1) - dft12288(prach2+24576,rxsigF[aa]+24576,1); + dft(DFT_12288,prach2+24576,rxsigF[aa]+24576,1); } break; case 75: if (prach_fmt == 4) { - dft3072(prach2,rxsigF[aa],1); + dft(DFT_3072,prach2,rxsigF[aa],1); } else { - dft18432(prach2,rxsigF[aa],1); + dft(DFT_18432,prach2,rxsigF[aa],1); if (prach_fmt>1) - dft18432(prach2+36864,rxsigF[aa]+36864,1); + dft(DFT_18432,prach2+36864,rxsigF[aa]+36864,1); } break; @@ -363,21 +363,21 @@ void rx_prach0(PHY_VARS_eNB *eNB, case 100: if (fp->threequarter_fs==0) { if (prach_fmt == 4) { - dft4096(prach2,rxsigF[aa],1); + dft(DFT_4096,prach2,rxsigF[aa],1); } else { - dft24576(prach2,rxsigF[aa],1); + dft(DFT_24576,prach2,rxsigF[aa],1); if (prach_fmt>1) - dft24576(prach2+49152,rxsigF[aa]+49152,1); + dft(DFT_24576,prach2+49152,rxsigF[aa]+49152,1); } } else { if (prach_fmt == 4) { - dft3072(prach2,rxsigF[aa],1); + dft(DFT_3072,prach2,rxsigF[aa],1); } else { - dft18432(prach2,rxsigF[aa],1); + dft(DFT_18432,prach2,rxsigF[aa],1); if (prach_fmt>1) - dft18432(prach2+36864,rxsigF[aa]+36864,1); + dft(DFT_18432,prach2+36864,rxsigF[aa]+36864,1); } } @@ -589,13 +589,13 @@ void rx_prach0(PHY_VARS_eNB *eNB, // Now do IFFT of size 1024 (N_ZC=839) or 256 (N_ZC=139) if (N_ZC == 839) { log2_ifft_size = 10; - idft1024(prachF,prach_ifft_tmp,1); + idft(IDFT_1024,prachF,prach_ifft_tmp,1); // compute energy and accumulate over receive antennas and repetitions for BR for (i=0; i<2048; i++) prach_ifft[i] += (prach_ifft_tmp[i<<1]*prach_ifft_tmp[i<<1] + prach_ifft_tmp[1+(i<<1)]*prach_ifft_tmp[1+(i<<1)])>>9; } else { - idft256(prachF,prach_ifft_tmp,1); + idft(IDFT_256,prachF,prach_ifft_tmp,1); log2_ifft_size = 8; // compute energy and accumulate over receive antennas and repetitions for BR diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c index 1b0d7feaf5..0e7bdd2ae4 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c @@ -154,9 +154,9 @@ void lte_idft(LTE_DL_FRAME_PARMS *frame_parms,uint32_t *z, uint16_t Msc_PUSCH) { switch (Msc_PUSCH) { case 12: - dft12((int16_t *)idft_in0,(int16_t *)idft_out0); - dft12((int16_t *)idft_in1,(int16_t *)idft_out1); - dft12((int16_t *)idft_in2,(int16_t *)idft_out2); + dft(DFT_12,(int16_t *)idft_in0,(int16_t *)idft_out0,0); + dft(DFT_12,(int16_t *)idft_in1,(int16_t *)idft_out1,0); + dft(DFT_12,(int16_t *)idft_in2,(int16_t *)idft_out2,0); #if defined(__x86_64__)||defined(__i386__) norm128 = _mm_set1_epi16(9459); #elif defined(__arm__) @@ -178,201 +178,201 @@ void lte_idft(LTE_DL_FRAME_PARMS *frame_parms,uint32_t *z, uint16_t Msc_PUSCH) { break; case 24: - dft24(idft_in0,idft_out0,1); - dft24(idft_in1,idft_out1,1); - dft24(idft_in2,idft_out2,1); + dft(DFT_24,idft_in0,idft_out0,1); + dft(DFT_24,idft_in1,idft_out1,1); + dft(DFT_24,idft_in2,idft_out2,1); break; case 36: - dft36(idft_in0,idft_out0,1); - dft36(idft_in1,idft_out1,1); - dft36(idft_in2,idft_out2,1); + dft(DFT_36,idft_in0,idft_out0,1); + dft(DFT_36,idft_in1,idft_out1,1); + dft(DFT_36,idft_in2,idft_out2,1); break; case 48: - dft48(idft_in0,idft_out0,1); - dft48(idft_in1,idft_out1,1); - dft48(idft_in2,idft_out2,1); + dft(DFT_48,idft_in0,idft_out0,1); + dft(DFT_48,idft_in1,idft_out1,1); + dft(DFT_48,idft_in2,idft_out2,1); break; case 60: - dft60(idft_in0,idft_out0,1); - dft60(idft_in1,idft_out1,1); - dft60(idft_in2,idft_out2,1); + dft(DFT_60,idft_in0,idft_out0,1); + dft(DFT_60,idft_in1,idft_out1,1); + dft(DFT_60,idft_in2,idft_out2,1); break; case 72: - dft72(idft_in0,idft_out0,1); - dft72(idft_in1,idft_out1,1); - dft72(idft_in2,idft_out2,1); + dft(DFT_72,idft_in0,idft_out0,1); + dft(DFT_72,idft_in1,idft_out1,1); + dft(DFT_72,idft_in2,idft_out2,1); break; case 96: - dft96(idft_in0,idft_out0,1); - dft96(idft_in1,idft_out1,1); - dft96(idft_in2,idft_out2,1); + dft(DFT_96,idft_in0,idft_out0,1); + dft(DFT_96,idft_in1,idft_out1,1); + dft(DFT_96,idft_in2,idft_out2,1); break; case 108: - dft108(idft_in0,idft_out0,1); - dft108(idft_in1,idft_out1,1); - dft108(idft_in2,idft_out2,1); + dft(DFT_108,idft_in0,idft_out0,1); + dft(DFT_108,idft_in1,idft_out1,1); + dft(DFT_108,idft_in2,idft_out2,1); break; case 120: - dft120(idft_in0,idft_out0,1); - dft120(idft_in1,idft_out1,1); - dft120(idft_in2,idft_out2,1); + dft(DFT_120,idft_in0,idft_out0,1); + dft(DFT_120,idft_in1,idft_out1,1); + dft(DFT_120,idft_in2,idft_out2,1); break; case 144: - dft144(idft_in0,idft_out0,1); - dft144(idft_in1,idft_out1,1); - dft144(idft_in2,idft_out2,1); + dft(DFT_144,idft_in0,idft_out0,1); + dft(DFT_144,idft_in1,idft_out1,1); + dft(DFT_144,idft_in2,idft_out2,1); break; case 180: - dft180(idft_in0,idft_out0,1); - dft180(idft_in1,idft_out1,1); - dft180(idft_in2,idft_out2,1); + dft(DFT_180,idft_in0,idft_out0,1); + dft(DFT_180,idft_in1,idft_out1,1); + dft(DFT_180,idft_in2,idft_out2,1); break; case 192: - dft192(idft_in0,idft_out0,1); - dft192(idft_in1,idft_out1,1); - dft192(idft_in2,idft_out2,1); + dft(DFT_192,idft_in0,idft_out0,1); + dft(DFT_192,idft_in1,idft_out1,1); + dft(DFT_192,idft_in2,idft_out2,1); break; case 216: - dft216(idft_in0,idft_out0,1); - dft216(idft_in1,idft_out1,1); - dft216(idft_in2,idft_out2,1); + dft(DFT_216,idft_in0,idft_out0,1); + dft(DFT_216,idft_in1,idft_out1,1); + dft(DFT_216,idft_in2,idft_out2,1); break; case 240: - dft240(idft_in0,idft_out0,1); - dft240(idft_in1,idft_out1,1); - dft240(idft_in2,idft_out2,1); + dft(DFT_240,idft_in0,idft_out0,1); + dft(DFT_240,idft_in1,idft_out1,1); + dft(DFT_240,idft_in2,idft_out2,1); break; case 288: - dft288(idft_in0,idft_out0,1); - dft288(idft_in1,idft_out1,1); - dft288(idft_in2,idft_out2,1); + dft(DFT_288,idft_in0,idft_out0,1); + dft(DFT_288,idft_in1,idft_out1,1); + dft(DFT_288,idft_in2,idft_out2,1); break; case 300: - dft300(idft_in0,idft_out0,1); - dft300(idft_in1,idft_out1,1); - dft300(idft_in2,idft_out2,1); + dft(DFT_300,idft_in0,idft_out0,1); + dft(DFT_300,idft_in1,idft_out1,1); + dft(DFT_300,idft_in2,idft_out2,1); break; case 324: - dft324((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft324((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft324((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_324,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_324,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_324,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 360: - dft360((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft360((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft360((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_360,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_360,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_360,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 384: - dft384((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft384((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft384((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_384,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_384,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_384,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 432: - dft432((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft432((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft432((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_432,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_432,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_432,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 480: - dft480((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft480((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft480((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_480,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_480,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_480,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 540: - dft540((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft540((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft540((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_540,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_540,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_540,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 576: - dft576((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft576((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft576((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_576,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_576,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_576,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 600: - dft600((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft600((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft600((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_600,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_600,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_600,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 648: - dft648((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft648((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft648((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_648,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_648,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_648,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 720: - dft720((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft720((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft720((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_720,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_720,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_720,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 768: - dft768((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft768((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft768((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_768,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_768,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_768,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 864: - dft864((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft864((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft864((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_864,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_864,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_864,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 900: - dft900((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft900((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft900((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_900,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_900,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_900,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 960: - dft960((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft960((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft960((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_960,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_960,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_960,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 972: - dft972((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft972((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft972((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_972,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_972,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_972,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 1080: - dft1080((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft1080((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft1080((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_1080,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_1080,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_1080,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 1152: - dft1152((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft1152((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft1152((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_1152,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_1152,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_1152,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 1200: - dft1200(idft_in0,idft_out0,1); - dft1200(idft_in1,idft_out1,1); - dft1200(idft_in2,idft_out2,1); + dft(DFT_1200,idft_in0,idft_out0,1); + dft(DFT_1200,idft_in1,idft_out1,1); + dft(DFT_1200,idft_in2,idft_out2,1); break; default: diff --git a/openair1/PHY/MODULATION/ofdm_mod.c b/openair1/PHY/MODULATION/ofdm_mod.c index cbeeca1327..855e649cc5 100644 --- a/openair1/PHY/MODULATION/ofdm_mod.c +++ b/openair1/PHY/MODULATION/ofdm_mod.c @@ -95,41 +95,41 @@ void PHY_ofdm_mod(int *input, /// pointer to complex input volatile int *output_ptr=(int*)0; int *temp_ptr=(int*)0; - void (*idft)(int16_t *,int16_t *, int); + idft_size_idx_t idftsize; switch (fftsize) { case 128: - idft = idft128; + idftsize = IDFT_128; break; case 256: - idft = idft256; + idftsize = IDFT_256; break; case 512: - idft = idft512; + idftsize = IDFT_512; break; case 1024: - idft = idft1024; + idftsize = IDFT_1024; break; case 1536: - idft = idft1536; + idftsize = IDFT_1536; break; case 2048: - idft = idft2048; + idftsize = IDFT_2048; break; case 3072: - idft = idft3072; + idftsize = IDFT_3072; break; case 4096: - idft = idft4096; + idftsize = IDFT_4096; break; default: - idft = idft512; + idftsize = IDFT_512; break; } @@ -148,12 +148,12 @@ void PHY_ofdm_mod(int *input, /// pointer to complex input #ifndef __AVX2__ // handle 128-bit alignment for 128-bit SIMD (SSE4,NEON,AltiVEC) - idft((int16_t *)&input[i*fftsize], + idft(idftsize,(int16_t *)&input[i*fftsize], (fftsize==128) ? (int16_t *)temp : (int16_t *)&output[(i*fftsize) + ((1+i)*nb_prefix_samples)], 1); #else // on AVX2 need 256-bit alignment - idft((int16_t *)&input[i*fftsize], + idft(idftsize,(int16_t *)&input[i*fftsize], (int16_t *)temp, 1); diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index 11aaf1f78e..69c52dd697 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -61,44 +61,44 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, unsigned int rx_offset; - void (*dft)(int16_t *,int16_t *, int); + dft_size_idx_t dftsize; int tmp_dft_in[8192] __attribute__ ((aligned (32))); // This is for misalignment issues for 6 and 15 PRBs switch (frame_parms->ofdm_symbol_size) { case 128: - dft = dft128; + dftsize = DFT_128; break; case 256: - dft = dft256; + dftsize = DFT_256; break; case 512: - dft = dft512; + dftsize = DFT_512; break; case 1024: - dft = dft1024; + dftsize = DFT_1024; break; case 1536: - dft = dft1536; + dftsize = DFT_1536; break; case 2048: - dft = dft2048; + dftsize = DFT_2048; break; case 3072: - dft = dft3072; + dftsize = DFT_3072; break; case 4096: - dft = dft4096; + dftsize = DFT_4096; break; case 8192: - dft = dft8192; + dftsize = DFT_8192; break; default: @@ -146,14 +146,14 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, memcpy((void *)tmp_dft_in, (void *) &common_vars->rxdata[aa][rx_offset % frame_length_samples], frame_parms->ofdm_symbol_size*sizeof(int)); - dft((int16_t *)tmp_dft_in, + dft(dftsize,(int16_t *)tmp_dft_in, (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); } else { // use dft input from RX buffer directly #if UE_TIMING_TRACE start_meas(&ue->rx_dft_stats); #endif - dft((int16_t *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], + dft(dftsize,(int16_t *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); #if UE_TIMING_TRACE stop_meas(&ue->rx_dft_stats); @@ -176,11 +176,11 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, memcpy((void *)tmp_dft_in, (void *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], frame_parms->ofdm_symbol_size*sizeof(int)); - dft((int16_t *)tmp_dft_in, + dft(dftsize,(int16_t *)tmp_dft_in, (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); } else { // use dft input from RX buffer directly - dft((int16_t *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], + dft(dftsize,(int16_t *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); } #if UE_TIMING_TRACE @@ -218,43 +218,43 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, unsigned int nb_prefix_samples = (no_prefix ? 0 : frame_parms->nb_prefix_samples); unsigned int nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples0); - void (*dft)(int16_t *,int16_t *, int); + dft_size_idx_t dftsize; switch (frame_parms->ofdm_symbol_size) { case 128: - dft = dft128; + dftsize = DFT_128; break; case 256: - dft = dft256; + dftsize = DFT_256; break; case 512: - dft = dft512; + dftsize = DFT_512; break; case 1024: - dft = dft1024; + dftsize = DFT_1024; break; case 1536: - dft = dft1536; + dftsize = DFT_1536; break; case 2048: - dft = dft2048; + dftsize = DFT_2048; break; case 4096: - dft = dft4096; + dftsize = DFT_4096; break; case 8192: - dft = dft8192; + dftsize = DFT_8192; break; default: - dft = dft512; + dftsize = DFT_512; break; } @@ -266,7 +266,7 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, else rxdata_offset = slot_offset + nb_prefix_samples0 + (symbol * (frame_parms->ofdm_symbol_size + nb_prefix_samples)) - SOFFSET; - dft((int16_t *)&rxdata[rxdata_offset], + dft(dftsize,(int16_t *)&rxdata[rxdata_offset], (int16_t *)&rxdataF[symbol * frame_parms->ofdm_symbol_size], 1); return(0); diff --git a/openair1/PHY/MODULATION/slot_fep_ul.c b/openair1/PHY/MODULATION/slot_fep_ul.c index 3ac8537c69..746f8dbc0e 100644 --- a/openair1/PHY/MODULATION/slot_fep_ul.c +++ b/openair1/PHY/MODULATION/slot_fep_ul.c @@ -44,7 +44,7 @@ int slot_fep_ul(RU_t *ru, unsigned int slot_offset; - void (*dft)(int16_t *,int16_t *, int); + dft_size_idx_t dftsize; int tmp_dft_in[2048] __attribute__ ((aligned (32))); // This is for misalignment issues for 6 and 15 PRBs unsigned int frame_length_samples = fp->samples_per_tti * 10; @@ -52,31 +52,31 @@ int slot_fep_ul(RU_t *ru, switch (fp->ofdm_symbol_size) { case 128: - dft = dft128; + dftsize = DFT_128; break; case 256: - dft = dft256; + dftsize = DFT_256; break; case 512: - dft = dft512; + dftsize = DFT_512; break; case 1024: - dft = dft1024; + dftsize = DFT_1024; break; case 1536: - dft = dft1536; + dftsize = DFT_1536; break; case 2048: - dft = dft2048; + dftsize = DFT_2048; break; default: - dft = dft512; + dftsize = DFT_512; break; } @@ -109,7 +109,7 @@ int slot_fep_ul(RU_t *ru, LOG_D(PHY,"slot_fep: symbol 0 %d dB\n", dB_fixed(signal_energy(&common->rxdata_7_5kHz[aa][rx_offset],fp->ofdm_symbol_size))); #endif - dft( (int16_t *)&common->rxdata_7_5kHz[aa][rx_offset], + dft( dftsize,(int16_t *)&common->rxdata_7_5kHz[aa][rx_offset], (int16_t *)&common->rxdataF[aa][fp->ofdm_symbol_size*symbol], 1 ); @@ -121,13 +121,13 @@ int slot_fep_ul(RU_t *ru, memcpy((void *)&tmp_dft_in, (void *)&common->rxdata_7_5kHz[aa][(rx_offset % frame_length_samples)], fp->ofdm_symbol_size*sizeof(int)); - dft( (short *) tmp_dft_in, + dft( dftsize,(short *) tmp_dft_in, (short*) &common->rxdataF[aa][fp->ofdm_symbol_size*symbol], 1 ); } else{ - dft( (short *)&common->rxdata_7_5kHz[aa][rx_offset], + dft( dftsize,(short *)&common->rxdata_7_5kHz[aa][rx_offset], (short*)&common->rxdataF[aa][fp->ofdm_symbol_size*symbol], 1 ); diff --git a/openair1/PHY/TOOLS/lte_dfts.c b/openair1/PHY/TOOLS/oai_dfts.c similarity index 99% rename from openair1/PHY/TOOLS/lte_dfts.c rename to openair1/PHY/TOOLS/oai_dfts.c index 59369a3bc0..0927b951b7 100644 --- a/openair1/PHY/TOOLS/lte_dfts.c +++ b/openair1/PHY/TOOLS/oai_dfts.c @@ -31,11 +31,10 @@ #ifndef M_PI #define M_PI 3.14159265358979323846 #endif - +#define OAIDFTS #ifndef MR_MAIN #include "PHY/defs_common.h" #include "PHY/impl_defs_top.h" -#include "tools_defs.h" #else #include "time_meas.h" #include "LOG/log.h" @@ -64,6 +63,9 @@ const static int16_t reflip[32] __attribute__((aligned(32))) = {1,-1,1,-1,1,-1, + + + #if defined(__x86_64__) || defined(__i386__) static inline void cmac(__m128i a,__m128i b, __m128i *re32, __m128i *im32) __attribute__((always_inline)); static inline void cmac(__m128i a,__m128i b, __m128i *re32, __m128i *im32) @@ -2588,7 +2590,7 @@ const static int16_t tw64c[96] __attribute__((aligned(32))) = { #endif #ifndef __AVX2__ -void dft64(int16_t *x,int16_t *y,int scale) +void dft64(int16_t *x,int16_t *y,unsigned char scale) { simd_q15_t xtmp[16],ytmp[16],*tw64a_128=(simd_q15_t *)tw64a,*tw64b_128=(simd_q15_t *)tw64b,*x128=(simd_q15_t *)x,*y128=(simd_q15_t *)y; @@ -2702,7 +2704,7 @@ void dft64(int16_t *x,int16_t *y,int scale) } #else // __AVX2__ -void dft64(int16_t *x,int16_t *y,int scale) +void dft64(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[16],ytmp[16],*tw64a_256=(simd256_q15_t *)tw64a,*tw64b_256=(simd256_q15_t *)tw64b,*x256=(simd256_q15_t *)x,*y256=(simd256_q15_t *)y; @@ -2850,7 +2852,7 @@ void dft64(int16_t *x,int16_t *y,int scale) #endif #ifndef __AVX2__ -void idft64(int16_t *x,int16_t *y,int scale) +void idft64(int16_t *x,int16_t *y,unsigned char scale) { simd_q15_t xtmp[16],ytmp[16],*tw64a_128=(simd_q15_t *)tw64,*tw64b_128=(simd_q15_t *)tw64c,*x128=(simd_q15_t *)x,*y128=(simd_q15_t *)y; @@ -2942,7 +2944,7 @@ void idft64(int16_t *x,int16_t *y,int scale) } #else // __AVX2__ -void idft64(int16_t *x,int16_t *y,int scale) +void idft64(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[16],ytmp[16],*tw64a_256=(simd256_q15_t *)tw64,*tw64b_256=(simd256_q15_t *)tw64c,*x256=(simd256_q15_t *)x,*y256=(simd256_q15_t *)y; @@ -3052,7 +3054,7 @@ int16_t tw128b[128] __attribute__((aligned(32))) = {0,32767,-1608,32727,-3212,32 int16_t tw128c[128] __attribute__((aligned(32))) = {0,32767,1608,32727,3212,32609,4808,32412,6393,32137,7962,31785,9512,31356,11039,30851,12540,30272,14010,29621,15447,28897,16846,28105,18205,27244,19520,26318,20788,25329,22005,24278,23170,23169,24279,22004,25330,20787,26319,19519,27245,18204,28106,16845,28898,15446,29622,14009,30273,12539,30852,11038,31357,9511,31786,7961,32138,6392,32413,4807,32610,3211,32728,1607,32767,0,32728,-1608,32610,-3212,32413,-4808,32138,-6393,31786,-7962,31357,-9512,30852,-11039,30273,-12540,29622,-14010,28898,-15447,28106,-16846,27245,-18205,26319,-19520,25330,-20788,24279,-22005,23170,-23170,22005,-24279,20788,-25330,19520,-26319,18205,-27245,16846,-28106,15447,-28898,14010,-29622,12540,-30273,11039,-30852,9512,-31357,7962,-31786,6393,-32138,4808,-32413,3212,-32610,1608,-32728}; #ifndef __AVX2__ -void dft128(int16_t *x,int16_t *y,int scale) +void dft128(int16_t *x,int16_t *y,unsigned char scale) { simdshort_q15_t xtmp[64],*x64 = (simdshort_q15_t *)x; @@ -3159,7 +3161,7 @@ void dft128(int16_t *x,int16_t *y,int scale) } #else // __AVX2__ -void dft128(int16_t *x,int16_t *y,int scale) +void dft128(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[16],*x256 = (simd256_q15_t *)x; @@ -3229,7 +3231,7 @@ void dft128(int16_t *x,int16_t *y,int scale) #endif #ifndef __AVX2__ -void idft128(int16_t *x,int16_t *y,int scale) +void idft128(int16_t *x,int16_t *y,unsigned char scale) { simdshort_q15_t xtmp[64],*x64 = (simdshort_q15_t *)x; @@ -3328,7 +3330,7 @@ void idft128(int16_t *x,int16_t *y,int scale) } #else // __AVX2__ -void idft128(int16_t *x,int16_t *y,int scale) +void idft128(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[16],*x256 = (simd256_q15_t *)x; @@ -3401,7 +3403,7 @@ int16_t tw256b[384] __attribute__((aligned(32))) = {0,32767,-805,32757,-1608,327 0,32767,-2411,32678,-4808,32412,-7180,31970,-9512,31356,-11793,30571,-14010,29621,-16151,28510,-18205,27244,-20160,25831,-22005,24278,-23732,22594,-25330,20787,-26790,18867,-28106,16845,-29269,14732,-30273,12539,-31114,10278,-31786,7961,-32285,5601,-32610,3211,-32758,804,-32728,-1608,-32521,-4012,-32138,-6393,-31581,-8740,-30852,-11039,-29956,-13279,-28898,-15447,-27684,-17531,-26319,-19520,-24812,-21403,-23170,-23170,-21403,-24812,-19520,-26319,-17531,-27684,-15447,-28898,-13279,-29956,-11039,-30852,-8740,-31581,-6393,-32138,-4012,-32521,-1608,-32728,804,-32758,3211,-32610,5601,-32285,7961,-31786,10278,-31114,12539,-30273,14732,-29269,16845,-28106,18867,-26790,20787,-25330,22594,-23732,24278,-22005,25831,-20160,27244,-18205,28510,-16151,29621,-14010,30571,-11793,31356,-9512,31970,-7180,32412,-4808,32678,-2411 }; #ifndef __AVX2__ -void dft256(int16_t *x,int16_t *y,int scale) +void dft256(int16_t *x,int16_t *y,unsigned char scale) { simd_q15_t xtmp[64],ytmp[64],*tw256a_128p=(simd_q15_t *)tw256a,*tw256b_128p=(simd_q15_t *)tw256b,*x128=(simd_q15_t *)x,*y128=(simd_q15_t *)y,*y128p=(simd_q15_t *)y; @@ -3513,7 +3515,7 @@ void dft256(int16_t *x,int16_t *y,int scale) -void idft256(int16_t *x,int16_t *y,int scale) +void idft256(int16_t *x,int16_t *y,unsigned char scale) { simd_q15_t xtmp[64],ytmp[64],*tw256_128p=(simd_q15_t *)tw256,*x128=(simd_q15_t *)x,*y128=(simd_q15_t *)y,*y128p=(simd_q15_t *)y; @@ -3571,7 +3573,7 @@ void idft256(int16_t *x,int16_t *y,int scale) #else //__AVX2__ -void dft256(int16_t *x,int16_t *y,int scale) +void dft256(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[32],ytmp[32],*tw256a_256p=(simd256_q15_t *)tw256a,*tw256b_256p=(simd256_q15_t *)tw256b,*x256=(simd256_q15_t *)x,*y256=(simd256_q15_t *)y,*y256p=(simd256_q15_t *)y; @@ -3663,7 +3665,7 @@ void dft256(int16_t *x,int16_t *y,int scale) } -void idft256(int16_t *x,int16_t *y,int scale) +void idft256(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[32],ytmp[32],*tw256_256p=(simd256_q15_t *)tw256,*x256=(simd256_q15_t *)x,*y256=(simd256_q15_t *)y,*y256p=(simd256_q15_t *)y; @@ -3768,7 +3770,7 @@ int16_t tw512c[512] __attribute__((aligned(32))) = { }; #ifndef __AVX2__ -void dft512(int16_t *x,int16_t *y,int scale) +void dft512(int16_t *x,int16_t *y,unsigned char scale) { simdshort_q15_t xtmp[256],*xtmpp,*x64 = (simdshort_q15_t *)x; @@ -3888,7 +3890,7 @@ void dft512(int16_t *x,int16_t *y,int scale) } -void idft512(int16_t *x,int16_t *y,int scale) +void idft512(int16_t *x,int16_t *y,unsigned char scale) { simdshort_q15_t xtmp[256],*xtmpp,*x64 = (simdshort_q15_t *)x; @@ -3980,7 +3982,7 @@ void idft512(int16_t *x,int16_t *y,int scale) #else //__AVX2__ -void dft512(int16_t *x,int16_t *y,int scale) +void dft512(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[64],*x256 = (simd256_q15_t *)x; @@ -4062,7 +4064,7 @@ void dft512(int16_t *x,int16_t *y,int scale) } -void idft512(int16_t *x,int16_t *y,int scale) +void idft512(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[64],*x256 = (simd256_q15_t *)x; @@ -4149,7 +4151,7 @@ void idft512(int16_t *x,int16_t *y,int scale) int16_t tw1024[1536] __attribute__((aligned(32))); #ifndef __AVX2__ -void dft1024(int16_t *x,int16_t *y,int scale) +void dft1024(int16_t *x,int16_t *y,unsigned char scale) { simd_q15_t xtmp[256],ytmp[256],*tw1024_128p=(simd_q15_t *)tw1024,*x128=(simd_q15_t *)x,*y128=(simd_q15_t *)y,*y128p=(simd_q15_t *)y; @@ -4205,7 +4207,7 @@ void dft1024(int16_t *x,int16_t *y,int scale) } -void idft1024(int16_t *x,int16_t *y,int scale) +void idft1024(int16_t *x,int16_t *y,unsigned char scale) { simd_q15_t xtmp[256],ytmp[256],*tw1024_128p=(simd_q15_t *)tw1024,*x128=(simd_q15_t *)x,*y128=(simd_q15_t *)y,*y128p=(simd_q15_t *)y; @@ -4262,7 +4264,7 @@ void idft1024(int16_t *x,int16_t *y,int scale) } #else //__AVX2__ -void dft1024(int16_t *x,int16_t *y,int scale) +void dft1024(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[128],ytmp[128],*tw1024_256p=(simd256_q15_t *)tw1024,*x256=(simd256_q15_t *)x,*y256=(simd256_q15_t *)y,*y256p=(simd256_q15_t *)y; @@ -4318,7 +4320,7 @@ void dft1024(int16_t *x,int16_t *y,int scale) } -void idft1024(int16_t *x,int16_t *y,int scale) +void idft1024(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[128],ytmp[128],*tw1024_256p=(simd256_q15_t *)tw1024,*x256=(simd256_q15_t *)x,*y256=(simd256_q15_t *)y,*y256p=(simd256_q15_t *)y; @@ -4378,7 +4380,7 @@ void idft1024(int16_t *x,int16_t *y,int scale) int16_t tw2048[2048] __attribute__((aligned(32))); #ifndef __AVX2__ -void dft2048(int16_t *x,int16_t *y,int scale) +void dft2048(int16_t *x,int16_t *y,unsigned char scale) { simdshort_q15_t xtmp[1024],*xtmpp,*x64 = (simdshort_q15_t *)x; @@ -4469,7 +4471,7 @@ void dft2048(int16_t *x,int16_t *y,int scale) } -void idft2048(int16_t *x,int16_t *y,int scale) +void idft2048(int16_t *x,int16_t *y,unsigned char scale) { simdshort_q15_t xtmp[1024],*xtmpp,*x64 = (simdshort_q15_t *)x; @@ -4561,7 +4563,7 @@ void idft2048(int16_t *x,int16_t *y,int scale) #else // __AVX2__ -void dft2048(int16_t *x,int16_t *y,int scale) +void dft2048(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[256],*xtmpp,*x256 = (simd256_q15_t *)x; @@ -4652,7 +4654,7 @@ void dft2048(int16_t *x,int16_t *y,int scale) } -void idft2048(int16_t *x,int16_t *y,int scale) +void idft2048(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[256],*xtmpp,*x256 = (simd256_q15_t *)x; @@ -4749,7 +4751,7 @@ void idft2048(int16_t *x,int16_t *y,int scale) int16_t tw4096[3*2*1024]; #ifndef __AVX2__ -void dft4096(int16_t *x,int16_t *y,int scale) +void dft4096(int16_t *x,int16_t *y,unsigned char scale) { simd_q15_t xtmp[1024],ytmp[1024],*tw4096_128p=(simd_q15_t *)tw4096,*x128=(simd_q15_t *)x,*y128=(simd_q15_t *)y,*y128p=(simd_q15_t *)y; @@ -4807,7 +4809,7 @@ void dft4096(int16_t *x,int16_t *y,int scale) -void idft4096(int16_t *x,int16_t *y,int scale) +void idft4096(int16_t *x,int16_t *y,unsigned char scale) { simd_q15_t xtmp[1024],ytmp[1024],*tw4096_128p=(simd_q15_t *)tw4096,*x128=(simd_q15_t *)x,*y128=(simd_q15_t *)y,*y128p=(simd_q15_t *)y; @@ -4864,7 +4866,7 @@ void idft4096(int16_t *x,int16_t *y,int scale) } #else //__AVX2__ -void dft4096(int16_t *x,int16_t *y,int scale) +void dft4096(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[512],ytmp[512],*tw4096_256p=(simd256_q15_t *)tw4096,*x256=(simd256_q15_t *)x,*y256=(simd256_q15_t *)y,*y256p=(simd256_q15_t *)y; @@ -4920,7 +4922,7 @@ void dft4096(int16_t *x,int16_t *y,int scale) } -void idft4096(int16_t *x,int16_t *y,int scale) +void idft4096(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[512],ytmp[512],*tw4096_256p=(simd256_q15_t *)tw4096,*x256=(simd256_q15_t *)x,*y256=(simd256_q15_t *)y,*y256p=(simd256_q15_t *)y; @@ -4982,7 +4984,7 @@ void idft4096(int16_t *x,int16_t *y,int scale) int16_t tw8192[2*4096] __attribute__((aligned(32))); #ifndef __AVX2__ -void dft8192(int16_t *x,int16_t *y,int scale) +void dft8192(int16_t *x,int16_t *y,unsigned char scale) { simdshort_q15_t xtmp[4096],*xtmpp,*x64 = (simdshort_q15_t *)x; @@ -5072,7 +5074,7 @@ void dft8192(int16_t *x,int16_t *y,int scale) } -void idft8192(int16_t *x,int16_t *y,int scale) +void idft8192(int16_t *x,int16_t *y,unsigned char scale) { simdshort_q15_t xtmp[4096],*xtmpp,*x64 = (simdshort_q15_t *)x; @@ -5163,7 +5165,7 @@ void idft8192(int16_t *x,int16_t *y,int scale) } #else // __AVX2__ -void dft8192(int16_t *x,int16_t *y,int scale) +void dft8192(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[1024],*xtmpp,*x256 = (simd256_q15_t *)x; @@ -5254,7 +5256,7 @@ void dft8192(int16_t *x,int16_t *y,int scale) } -void idft8192(int16_t *x,int16_t *y,int scale) +void idft8192(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[1024],*xtmpp,*x256 = (simd256_q15_t *)x; @@ -5350,7 +5352,7 @@ void idft8192(int16_t *x,int16_t *y,int scale) int16_t twa1536[1024],twb1536[1024]; // 512 x 3 -void idft1536(int16_t *input, int16_t *output, int scale) +void idft1536(int16_t *input, int16_t *output, unsigned char scale) { int i,i2,j; uint32_t tmp[3][512 ]__attribute__((aligned(32))); @@ -5402,7 +5404,7 @@ void idft1536(int16_t *input, int16_t *output, int scale) } -void dft1536(int16_t *input, int16_t *output, int scale) +void dft1536(int16_t *input, int16_t *output, unsigned char scale) { int i,i2,j; uint32_t tmp[3][512] __attribute__((aligned(32))); @@ -5467,7 +5469,7 @@ void dft1536(int16_t *input, int16_t *output, int scale) int16_t twa3072[2048] __attribute__((aligned(32))); int16_t twb3072[2048] __attribute__((aligned(32))); // 1024 x 3 -void dft3072(int16_t *input, int16_t *output,int scale) +void dft3072(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][1024] __attribute__((aligned(32))); @@ -5517,7 +5519,7 @@ void dft3072(int16_t *input, int16_t *output,int scale) _m_empty(); } -void idft3072(int16_t *input, int16_t *output,int scale) +void idft3072(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][1024]__attribute__((aligned(32))); @@ -5571,7 +5573,7 @@ void idft3072(int16_t *input, int16_t *output,int scale) int16_t twa6144[4096] __attribute__((aligned(32))); int16_t twb6144[4096] __attribute__((aligned(32))); -void idft6144(int16_t *input, int16_t *output,int scale) +void idft6144(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][2048] __attribute__((aligned(32))); @@ -5631,7 +5633,7 @@ void idft6144(int16_t *input, int16_t *output,int scale) } -void dft6144(int16_t *input, int16_t *output,int scale) +void dft6144(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][2048] __attribute__((aligned(32))); @@ -5696,7 +5698,7 @@ void dft6144(int16_t *input, int16_t *output,int scale) int16_t twa12288[8192] __attribute__((aligned(32))); int16_t twb12288[8192] __attribute__((aligned(32))); // 4096 x 3 -void dft12288(int16_t *input, int16_t *output,int scale) +void dft12288(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][4096] __attribute__((aligned(32))); @@ -5756,7 +5758,7 @@ void dft12288(int16_t *input, int16_t *output,int scale) } -void idft12288(int16_t *input, int16_t *output,int scale) +void idft12288(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][4096] __attribute__((aligned(32))); @@ -5820,7 +5822,7 @@ void idft12288(int16_t *input, int16_t *output,int scale) int16_t twa18432[12288] __attribute__((aligned(32))); int16_t twb18432[12288] __attribute__((aligned(32))); // 6144 x 3 -void dft18432(int16_t *input, int16_t *output,int scale) { +void dft18432(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][6144] __attribute__((aligned(32))); @@ -5868,7 +5870,7 @@ void dft18432(int16_t *input, int16_t *output,int scale) { _m_empty(); } -void idft18432(int16_t *input, int16_t *output,int scale) { +void idft18432(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][6144] __attribute__((aligned(32))); @@ -5920,7 +5922,7 @@ void idft18432(int16_t *input, int16_t *output,int scale) { int16_t twa24576[16384] __attribute__((aligned(32))); int16_t twb24576[16384] __attribute__((aligned(32))); // 8192 x 3 -void dft24576(int16_t *input, int16_t *output,int scale) +void dft24576(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][8192] __attribute__((aligned(32))); @@ -5983,7 +5985,7 @@ void dft24576(int16_t *input, int16_t *output,int scale) } } -void idft24576(int16_t *input, int16_t *output,int scale) +void idft24576(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][8192] __attribute__((aligned(32))); @@ -6194,7 +6196,7 @@ static inline void dft12f(simd_q15_t *x0, -void dft12(int16_t *x,int16_t *y) +void dft12(int16_t *x,int16_t *y ,unsigned char scale_flag) { simd_q15_t *x128 = (simd_q15_t *)x,*y128 = (simd_q15_t *)y; @@ -8644,7 +8646,8 @@ void init_rad5_rep(int N,int16_t *twa,int16_t *twb,int16_t *twc,int16_t *twd) { twd+=8; } } - +/*----------------------------------------------------------------*/ +/* dft library entry points: */ void init_dfts(void) { @@ -8693,8 +8696,24 @@ void init_dfts(void) init_rad3_rep(1080,twa1080,twb1080); init_rad4_rep(1152,twa1152,twb1152,twc1152); init_rad4_rep(1200,twa1200,twb1200,twc1200); + } + + + +void dft(uint8_t sizeidx, int16_t *sigF,int16_t *sig,unsigned char scale_flag){ + AssertFatal((sizeidx>=0 && sizeidx<(int)DFT_SIZE_IDXTABLESIZE),"Invalid dft size index %i\n",sizeidx); + dft_ftab[sizeidx](sigF,sig,scale_flag); +}; + +void idft(uint8_t sizeidx, int16_t *sigF,int16_t *sig,unsigned char scale_flag){ + AssertFatal((sizeidx>=0 && sizeidx<(int)IDFT_SIZE_IDXTABLESIZE),"Invalid idft size index %i\n",sizeidx); + idft_ftab[sizeidx](sigF,sig,scale_flag); +}; + +/*---------------------------------------------------------------------------------------*/ + #ifdef MR_MAIN #include #include diff --git a/openair1/PHY/TOOLS/tools_defs.h b/openair1/PHY/TOOLS/tools_defs.h index 5ba956fd39..04f7df5217 100644 --- a/openair1/PHY/TOOLS/tools_defs.h +++ b/openair1/PHY/TOOLS/tools_defs.h @@ -181,29 +181,234 @@ This function performs optimized fixed-point radix-2 FFT/IFFT. ); */ -void idft1536(int16_t *sigF,int16_t *sig,int scale); -void idft6144(int16_t *sigF,int16_t *sig,int scale); -void idft12288(int16_t *sigF,int16_t *sig,int scale); -void idft18432(int16_t *sigF,int16_t *sig,int scale); -void idft3072(int16_t *sigF,int16_t *sig,int scale); -void idft24576(int16_t *sigF,int16_t *sig,int scale); -void dft1536(int16_t *sigF,int16_t *sig,int scale); -void dft3072(int16_t *sigF,int16_t *sig,int scale); +#ifdef OAIDFTS +typedef void(*adftfunc_t)(int16_t *sigF,int16_t *sig,unsigned char scale_flag); +typedef void(*aidftfunc_t)(int16_t *sigF,int16_t *sig,unsigned char scale_flag); -void dft6144(int16_t *sigF,int16_t *sig,int scale); +void dft12(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft24(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft36(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft48(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft60(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft72(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft96(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft108(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft120(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft144(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft180(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft192(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft216(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft240(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft288(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft300(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft324(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft360(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft384(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft432(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft480(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft540(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft576(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft600(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft648(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft720(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft768(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft864(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft900(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft960(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft972(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft1080(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft1152(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft1200(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft12288(int16_t *sigF,int16_t *sig,int scale); +void dft64(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft128(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft256(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft512(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft1024(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft2048(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft4096(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft8192(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft18432(int16_t *sigF,int16_t *sig,int scale); +void idft64(int16_t *x,int16_t *y,uint8_t scale_flag); +void idft128(int16_t *x,int16_t *y,uint8_t scale_flag); +void idft256(int16_t *x,int16_t *y,uint8_t scale_flag); +void idft512(int16_t *x,int16_t *y,uint8_t scale_flag); +void idft1024(int16_t *x,int16_t *y,uint8_t scale_flag); +void idft2048(int16_t *x,int16_t *y,uint8_t scale_flag); +void idft4096(int16_t *x,int16_t *y,uint8_t scale_flag); +void idft8192(int16_t *x,int16_t *y,uint8_t scale_flag); + +void idft1536(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void idft6144(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void idft12288(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void idft18432(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void idft3072(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void idft24576(int16_t *sigF,int16_t *sig,uint8_t scale_flag); + +void dft1536(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void dft3072(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void dft6144(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void dft12288(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void dft18432(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void dft24576(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +#else +typedef void(*dftfunc_t)(uint8_t sizeidx,int16_t *sigF,int16_t *sig,unsigned char scale_flag); +typedef void(*idftfunc_t)(uint8_t sizeidx,int16_t *sigF,int16_t *sig,unsigned char scale_flag); +extern dftfunc_t dft; +extern idftfunc_t idft; +#endif + +typedef enum DFT_size_idx { + DFT_12, + DFT_24, + DFT_36, + DFT_48, + DFT_60, + DFT_72, + DFT_96, + DFT_108, + DFT_120, + DFT_128, + DFT_144, + DFT_180, + DFT_192, + DFT_216, + DFT_240, + DFT_256, + DFT_288, + DFT_300, + DFT_324, + DFT_360, + DFT_384, + DFT_432, + DFT_480, + DFT_512, + DFT_540, + DFT_576, + DFT_600, + DFT_648, + DFT_720, + DFT_768, + DFT_864, + DFT_900, + DFT_960, + DFT_972, + DFT_1024, + DFT_1080, + DFT_1152, + DFT_1200, + DFT_1536, + DFT_2048, + DFT_3072, + DFT_4096, + DFT_6144, + DFT_8192, + DFT_12288, + DFT_18432, + DFT_24576, + DFT_SIZE_IDXTABLESIZE, +} dft_size_idx_t; + +#ifdef OAIDFTS +adftfunc_t dft_ftab[]={ + dft12, + dft24, + dft36, + dft48, + dft60, + dft72, + dft96, + dft108, + dft120, + dft128, + dft144, + dft180, + dft192, + dft216, + dft240, + dft256, + dft288, + dft300, + dft324, + dft360, + dft384, + dft432, + dft480, + dft512, + dft540, + dft576, + dft600, + dft648, + dft720, + dft768, + dft864, + dft900, + dft960, + dft972, + dft1024, + dft1080, + dft1152, + dft1200, + dft1536, + dft2048, + dft3072, + dft4096, + dft6144, + dft8192, + dft12288, + dft18432, + dft24576, +}; +#endif + +typedef enum idft_size_idx { + IDFT_128, + IDFT_256, + IDFT_288, + IDFT_300, + IDFT_324, + IDFT_360, + IDFT_384, + IDFT_432, + IDFT_480, + IDFT_512, + IDFT_1024, + IDFT_1536, + IDFT_2048, + IDFT_3072, + IDFT_4096, + IDFT_6144, + IDFT_8192, + IDFT_12288, + IDFT_18432, + IDFT_24576, + IDFT_SIZE_IDXTABLESIZE, +} idft_size_idx_t; +#ifdef OAIDFTS +aidftfunc_t idft_ftab[]={ + idft128, + idft256, + idft512, + idft1024, + idft1536, + idft2048, + idft3072, + idft4096, + idft6144, + idft8192, + idft12288, + idft18432, + idft24576, +}; +#endif -void dft24576(int16_t *sigF,int16_t *sig,int scale); /*!\fn int32_t rotate_cpx_vector(int16_t *x,int16_t *alpha,int16_t *y,uint32_t N,uint16_t output_shift) @@ -374,57 +579,7 @@ int64_t dot_product64(int16_t *x, uint32_t N, //must be a multiple of 8 uint8_t output_shift); -void dft12(int16_t *x,int16_t *y); -void dft24(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft36(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft48(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft60(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft72(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft96(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft108(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft120(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft144(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft180(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft192(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft216(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft240(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft288(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft300(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft324(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft360(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft384(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft432(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft480(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft540(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft576(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft600(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft648(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft720(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft768(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft864(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft900(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft960(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft972(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft1080(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft1152(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft1200(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft64(int16_t *x,int16_t *y,int scale); -void dft128(int16_t *x,int16_t *y,int scale); -void dft256(int16_t *x,int16_t *y,int scale); -void dft512(int16_t *x,int16_t *y,int scale); -void dft1024(int16_t *x,int16_t *y,int scale); -void dft2048(int16_t *x,int16_t *y,int scale); -void dft4096(int16_t *x,int16_t *y,int scale); -void dft8192(int16_t *x,int16_t *y,int scale); -void idft64(int16_t *x,int16_t *y,int scale); -void idft128(int16_t *x,int16_t *y,int scale); -void idft256(int16_t *x,int16_t *y,int scale); -void idft512(int16_t *x,int16_t *y,int scale); -void idft1024(int16_t *x,int16_t *y,int scale); -void idft2048(int16_t *x,int16_t *y,int scale); -void idft4096(int16_t *x,int16_t *y,int scale); -void idft8192(int16_t *x,int16_t *y,int scale); /** @} */ From 4649034b262359b6527ee02dde935b107495f629 Mon Sep 17 00:00:00 2001 From: frtabu Date: Mon, 30 Mar 2020 00:23:28 +0200 Subject: [PATCH 098/240] create dft shared lib --- cmake_targets/CMakeLists.txt | 6 +- .../PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c | 8 +- openair1/PHY/LTE_ESTIMATION/lte_sync_time.c | 40 +-- .../lte_ul_channel_estimation.c | 16 +- openair1/PHY/LTE_TRANSPORT/prach.c | 46 +-- .../PHY/LTE_TRANSPORT/ulsch_demodulation.c | 204 ++++++------- openair1/PHY/MODULATION/ofdm_mod.c | 24 +- openair1/PHY/MODULATION/slot_fep_nr.c | 50 ++-- openair1/PHY/MODULATION/slot_fep_ul.c | 22 +- openair1/PHY/TOOLS/{lte_dfts.c => oai_dfts.c} | 114 ++++--- openair1/PHY/TOOLS/tools_defs.h | 279 ++++++++++++++---- 11 files changed, 492 insertions(+), 317 deletions(-) rename openair1/PHY/TOOLS/{lte_dfts.c => oai_dfts.c} (99%) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 247bc9e073..43e4f109a6 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -1330,6 +1330,9 @@ add_library(ldpc MODULE ${PHY_LDPC_OPTIM8SEGMULTI_SRC} ) add_library(coding MODULE ${PHY_TURBOSRC} ) +add_library(dfts MODULE ${OPENAIR1_DIR}/PHY/TOOLS/oai_dfts.c ) + + set(PHY_SRC_COMMON ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dci_tools_common.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/lte_mcs.c @@ -1370,7 +1373,7 @@ set(PHY_SRC_COMMON ${OPENAIR1_DIR}/PHY/INIT/lte_parms.c ${OPENAIR1_DIR}/PHY/INIT/lte_param_init.c ${OPENAIR1_DIR}/PHY/TOOLS/cadd_vv.c - ${OPENAIR1_DIR}/PHY/TOOLS/lte_dfts.c +# ${OPENAIR1_DIR}/PHY/TOOLS/lte_dfts.c ${OPENAIR1_DIR}/PHY/TOOLS/log2_approx.c ${OPENAIR1_DIR}/PHY/TOOLS/cmult_sv.c ${OPENAIR1_DIR}/PHY/TOOLS/cmult_vv.c @@ -1585,6 +1588,7 @@ endif () add_library(PHY_COMMON ${PHY_SRC_COMMON}) add_dependencies(PHY_COMMON rrc_flag) +add_dependencies(PHY_COMMON dfts) add_library(PHY ${PHY_SRC}) add_dependencies(PHY rrc_flag) add_library(PHY_UE ${PHY_SRC_UE}) diff --git a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c index 04fe19ecbc..aaa138fcd9 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c @@ -56,22 +56,22 @@ int lte_est_timing_advance(LTE_DL_FRAME_PARMS *frame_parms, // do ifft of channel estimate switch(frame_parms->N_RB_DL) { case 6: - dft128((int16_t*) <e_eNB_srs->srs_ch_estimates[aa][0], + dft(DFT_128,(int16_t*) <e_eNB_srs->srs_ch_estimates[aa][0], (int16_t*) lte_eNB_srs->srs_ch_estimates_time[aa], 1); break; case 25: - dft512((int16_t*) <e_eNB_srs->srs_ch_estimates[aa][0], + dft(DFT_512,(int16_t*) <e_eNB_srs->srs_ch_estimates[aa][0], (int16_t*) lte_eNB_srs->srs_ch_estimates_time[aa], 1); break; case 50: - dft1024((int16_t*) <e_eNB_srs->srs_ch_estimates[aa][0], + dft(DFT_1024,(int16_t*) <e_eNB_srs->srs_ch_estimates[aa][0], (int16_t*) lte_eNB_srs->srs_ch_estimates_time[aa], 1); break; case 100: - dft2048((int16_t*) <e_eNB_srs->srs_ch_estimates[aa][0], + dft(DFT_2048,(int16_t*) <e_eNB_srs->srs_ch_estimates[aa][0], (int16_t*) lte_eNB_srs->srs_ch_estimates_time[aa], 1); break; diff --git a/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c b/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c index 0c98bdc5a5..0d765a18b3 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c @@ -141,28 +141,28 @@ int lte_sync_time_init(LTE_DL_FRAME_PARMS *frame_parms ) // LTE_UE_COMMON *com switch (frame_parms->N_RB_DL) { case 6: - idft128((short*)syncF_tmp, /// complex input + idft(IDFT_128,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 25: - idft512((short*)syncF_tmp, /// complex input + idft(IDFT_512,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 50: - idft1024((short*)syncF_tmp, /// complex input + idft(IDFT_1024,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 75: - idft1536((short*)syncF_tmp, /// complex input + idft(IDFT_1536,(short*)syncF_tmp, /// complex input (short*)sync_tmp, 1); /// complex output break; case 100: - idft2048((short*)syncF_tmp, /// complex input + idft(IDFT_2048,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; @@ -189,28 +189,28 @@ int lte_sync_time_init(LTE_DL_FRAME_PARMS *frame_parms ) // LTE_UE_COMMON *com switch (frame_parms->N_RB_DL) { case 6: - idft128((short*)syncF_tmp, /// complex input + idft(IDFT_128,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 25: - idft512((short*)syncF_tmp, /// complex input + idft(IDFT_512,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 50: - idft1024((short*)syncF_tmp, /// complex input + idft(IDFT_1024,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 75: - idft1536((short*)syncF_tmp, /// complex input + idft(IDFT_1536,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 100: - idft2048((short*)syncF_tmp, /// complex input + idft(IDFT_2048,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; @@ -237,28 +237,28 @@ int lte_sync_time_init(LTE_DL_FRAME_PARMS *frame_parms ) // LTE_UE_COMMON *com switch (frame_parms->N_RB_DL) { case 6: - idft128((short*)syncF_tmp, /// complex input + idft(IDFT_128,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 25: - idft512((short*)syncF_tmp, /// complex input + idft(IDFT_512,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 50: - idft1024((short*)syncF_tmp, /// complex input + idft(IDFT_1024,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 75: - idft1536((short*)syncF_tmp, /// complex input + idft(IDFT_1536,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; case 100: - idft2048((short*)syncF_tmp, /// complex input + idft(IDFT_2048,(short*)syncF_tmp, /// complex input (short*)sync_tmp, /// complex output 1); break; @@ -492,28 +492,28 @@ int ru_sync_time_init(RU_t *ru) // LTE_UE_COMMON *common_vars switch (ru->frame_parms->N_RB_DL) { case 6: - idft128((int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), + idft(IDFT_128,(int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), ru->dmrssync, /// complex output 1); break; case 25: - idft512((int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), + idft(IDFT_512,(int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), ru->dmrssync, /// complex output 1); break; case 50: - idft1024((int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), + idft(IDFT_1024,(int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), ru->dmrssync, /// complex output 1); break; case 75: - idft1536((int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), + idft(IDFT_1536,(int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), ru->dmrssync, 1); /// complex output break; case 100: - idft2048((int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), + idft(IDFT_2048,(int16_t*)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]), ru->dmrssync, /// complex output 1); break; diff --git a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c index cb001f9dc4..f5543eda52 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c @@ -246,25 +246,25 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *eNB, switch(frame_parms->N_RB_DL) { case 6: - idft128((int16_t *) temp_in_ifft_0, + idft(IDFT_128,(int16_t *) temp_in_ifft_0, (int16_t *) ul_ch_estimates_time[aa], 1); break; case 25: - idft512((int16_t *) temp_in_ifft_0, + idft(IDFT_512,(int16_t *) temp_in_ifft_0, (int16_t *) ul_ch_estimates_time[aa], 1); break; case 50: - idft1024((int16_t *) temp_in_ifft_0, + idft(IDFT_1024,(int16_t *) temp_in_ifft_0, (int16_t *) ul_ch_estimates_time[aa], 1); break; case 100: - idft2048((int16_t *) temp_in_ifft_0, + idft(IDFT_2048,(int16_t *) temp_in_ifft_0, (int16_t *) ul_ch_estimates_time[aa], 1); break; @@ -575,25 +575,25 @@ int32_t lte_ul_channel_estimation_RRU(LTE_DL_FRAME_PARMS *frame_parms, switch(frame_parms->N_RB_DL) { case 6: - idft128((int16_t *) temp_in_ifft_0, + idft(IDFT_128,(int16_t *) temp_in_ifft_0, (int16_t *) ul_ch_estimates_time[aa], 1); break; case 25: - idft512((int16_t *) temp_in_ifft_0, + idft(IDFT_512,(int16_t *) temp_in_ifft_0, (int16_t *) ul_ch_estimates_time[aa], 1); break; case 50: - idft1024((int16_t *) temp_in_ifft_0, + idft(IDFT_1024,(int16_t *) temp_in_ifft_0, (int16_t *) ul_ch_estimates_time[aa], 1); break; case 100: - idft2048((int16_t *) temp_in_ifft_0, + idft(IDFT_2048,(int16_t *) temp_in_ifft_0, (int16_t *) ul_ch_estimates_time[aa], 1); break; diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c index 3471f98af7..983e30c80a 100644 --- a/openair1/PHY/LTE_TRANSPORT/prach.c +++ b/openair1/PHY/LTE_TRANSPORT/prach.c @@ -298,24 +298,24 @@ void rx_prach0(PHY_VARS_eNB *eNB, switch (fp->N_RB_UL) { case 6: if (prach_fmt == 4) { - dft256(prach2,rxsigF[aa],1); + dft(DFT_256,prach2,rxsigF[aa],1); } else { - dft1536(prach2,rxsigF[aa],1); + dft(DFT_1536,prach2,rxsigF[aa],1); if (prach_fmt>1) - dft1536(prach2+3072,rxsigF[aa]+3072,1); + dft(DFT_1536,prach2+3072,rxsigF[aa]+3072,1); } break; case 15: if (prach_fmt == 4) { - dft256(prach2,rxsigF[aa],1); + dft(DFT_256,prach2,rxsigF[aa],1); } else { - dft3072(prach2,rxsigF[aa],1); + dft(DFT_3072,prach2,rxsigF[aa],1); if (prach_fmt>1) - dft3072(prach2+6144,rxsigF[aa]+6144,1); + dft(DFT_3072,prach2+6144,rxsigF[aa]+6144,1); } break; @@ -323,13 +323,13 @@ void rx_prach0(PHY_VARS_eNB *eNB, case 25: default: if (prach_fmt == 4) { - dft1024(prach2,rxsigF[aa],1); + dft(DFT_1024,prach2,rxsigF[aa],1); fft_size = 1024; } else { - dft6144(prach2,rxsigF[aa],1); + dft(DFT_6144,prach2,rxsigF[aa],1); if (prach_fmt>1) - dft6144(prach2+12288,rxsigF[aa]+12288,1); + dft(DFT_6144,prach2+12288,rxsigF[aa]+12288,1); fft_size = 6144; } @@ -338,24 +338,24 @@ void rx_prach0(PHY_VARS_eNB *eNB, case 50: if (prach_fmt == 4) { - dft2048(prach2,rxsigF[aa],1); + dft(DFT_2048,prach2,rxsigF[aa],1); } else { - dft12288(prach2,rxsigF[aa],1); + dft(DFT_12288,prach2,rxsigF[aa],1); if (prach_fmt>1) - dft12288(prach2+24576,rxsigF[aa]+24576,1); + dft(DFT_12288,prach2+24576,rxsigF[aa]+24576,1); } break; case 75: if (prach_fmt == 4) { - dft3072(prach2,rxsigF[aa],1); + dft(DFT_3072,prach2,rxsigF[aa],1); } else { - dft18432(prach2,rxsigF[aa],1); + dft(DFT_18432,prach2,rxsigF[aa],1); if (prach_fmt>1) - dft18432(prach2+36864,rxsigF[aa]+36864,1); + dft(DFT_18432,prach2+36864,rxsigF[aa]+36864,1); } break; @@ -363,21 +363,21 @@ void rx_prach0(PHY_VARS_eNB *eNB, case 100: if (fp->threequarter_fs==0) { if (prach_fmt == 4) { - dft4096(prach2,rxsigF[aa],1); + dft(DFT_4096,prach2,rxsigF[aa],1); } else { - dft24576(prach2,rxsigF[aa],1); + dft(DFT_24576,prach2,rxsigF[aa],1); if (prach_fmt>1) - dft24576(prach2+49152,rxsigF[aa]+49152,1); + dft(DFT_24576,prach2+49152,rxsigF[aa]+49152,1); } } else { if (prach_fmt == 4) { - dft3072(prach2,rxsigF[aa],1); + dft(DFT_3072,prach2,rxsigF[aa],1); } else { - dft18432(prach2,rxsigF[aa],1); + dft(DFT_18432,prach2,rxsigF[aa],1); if (prach_fmt>1) - dft18432(prach2+36864,rxsigF[aa]+36864,1); + dft(DFT_18432,prach2+36864,rxsigF[aa]+36864,1); } } @@ -589,13 +589,13 @@ void rx_prach0(PHY_VARS_eNB *eNB, // Now do IFFT of size 1024 (N_ZC=839) or 256 (N_ZC=139) if (N_ZC == 839) { log2_ifft_size = 10; - idft1024(prachF,prach_ifft_tmp,1); + idft(IDFT_1024,prachF,prach_ifft_tmp,1); // compute energy and accumulate over receive antennas and repetitions for BR for (i=0; i<2048; i++) prach_ifft[i] += (prach_ifft_tmp[i<<1]*prach_ifft_tmp[i<<1] + prach_ifft_tmp[1+(i<<1)]*prach_ifft_tmp[1+(i<<1)])>>9; } else { - idft256(prachF,prach_ifft_tmp,1); + idft(IDFT_256,prachF,prach_ifft_tmp,1); log2_ifft_size = 8; // compute energy and accumulate over receive antennas and repetitions for BR diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c index 1b0d7feaf5..0e7bdd2ae4 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c @@ -154,9 +154,9 @@ void lte_idft(LTE_DL_FRAME_PARMS *frame_parms,uint32_t *z, uint16_t Msc_PUSCH) { switch (Msc_PUSCH) { case 12: - dft12((int16_t *)idft_in0,(int16_t *)idft_out0); - dft12((int16_t *)idft_in1,(int16_t *)idft_out1); - dft12((int16_t *)idft_in2,(int16_t *)idft_out2); + dft(DFT_12,(int16_t *)idft_in0,(int16_t *)idft_out0,0); + dft(DFT_12,(int16_t *)idft_in1,(int16_t *)idft_out1,0); + dft(DFT_12,(int16_t *)idft_in2,(int16_t *)idft_out2,0); #if defined(__x86_64__)||defined(__i386__) norm128 = _mm_set1_epi16(9459); #elif defined(__arm__) @@ -178,201 +178,201 @@ void lte_idft(LTE_DL_FRAME_PARMS *frame_parms,uint32_t *z, uint16_t Msc_PUSCH) { break; case 24: - dft24(idft_in0,idft_out0,1); - dft24(idft_in1,idft_out1,1); - dft24(idft_in2,idft_out2,1); + dft(DFT_24,idft_in0,idft_out0,1); + dft(DFT_24,idft_in1,idft_out1,1); + dft(DFT_24,idft_in2,idft_out2,1); break; case 36: - dft36(idft_in0,idft_out0,1); - dft36(idft_in1,idft_out1,1); - dft36(idft_in2,idft_out2,1); + dft(DFT_36,idft_in0,idft_out0,1); + dft(DFT_36,idft_in1,idft_out1,1); + dft(DFT_36,idft_in2,idft_out2,1); break; case 48: - dft48(idft_in0,idft_out0,1); - dft48(idft_in1,idft_out1,1); - dft48(idft_in2,idft_out2,1); + dft(DFT_48,idft_in0,idft_out0,1); + dft(DFT_48,idft_in1,idft_out1,1); + dft(DFT_48,idft_in2,idft_out2,1); break; case 60: - dft60(idft_in0,idft_out0,1); - dft60(idft_in1,idft_out1,1); - dft60(idft_in2,idft_out2,1); + dft(DFT_60,idft_in0,idft_out0,1); + dft(DFT_60,idft_in1,idft_out1,1); + dft(DFT_60,idft_in2,idft_out2,1); break; case 72: - dft72(idft_in0,idft_out0,1); - dft72(idft_in1,idft_out1,1); - dft72(idft_in2,idft_out2,1); + dft(DFT_72,idft_in0,idft_out0,1); + dft(DFT_72,idft_in1,idft_out1,1); + dft(DFT_72,idft_in2,idft_out2,1); break; case 96: - dft96(idft_in0,idft_out0,1); - dft96(idft_in1,idft_out1,1); - dft96(idft_in2,idft_out2,1); + dft(DFT_96,idft_in0,idft_out0,1); + dft(DFT_96,idft_in1,idft_out1,1); + dft(DFT_96,idft_in2,idft_out2,1); break; case 108: - dft108(idft_in0,idft_out0,1); - dft108(idft_in1,idft_out1,1); - dft108(idft_in2,idft_out2,1); + dft(DFT_108,idft_in0,idft_out0,1); + dft(DFT_108,idft_in1,idft_out1,1); + dft(DFT_108,idft_in2,idft_out2,1); break; case 120: - dft120(idft_in0,idft_out0,1); - dft120(idft_in1,idft_out1,1); - dft120(idft_in2,idft_out2,1); + dft(DFT_120,idft_in0,idft_out0,1); + dft(DFT_120,idft_in1,idft_out1,1); + dft(DFT_120,idft_in2,idft_out2,1); break; case 144: - dft144(idft_in0,idft_out0,1); - dft144(idft_in1,idft_out1,1); - dft144(idft_in2,idft_out2,1); + dft(DFT_144,idft_in0,idft_out0,1); + dft(DFT_144,idft_in1,idft_out1,1); + dft(DFT_144,idft_in2,idft_out2,1); break; case 180: - dft180(idft_in0,idft_out0,1); - dft180(idft_in1,idft_out1,1); - dft180(idft_in2,idft_out2,1); + dft(DFT_180,idft_in0,idft_out0,1); + dft(DFT_180,idft_in1,idft_out1,1); + dft(DFT_180,idft_in2,idft_out2,1); break; case 192: - dft192(idft_in0,idft_out0,1); - dft192(idft_in1,idft_out1,1); - dft192(idft_in2,idft_out2,1); + dft(DFT_192,idft_in0,idft_out0,1); + dft(DFT_192,idft_in1,idft_out1,1); + dft(DFT_192,idft_in2,idft_out2,1); break; case 216: - dft216(idft_in0,idft_out0,1); - dft216(idft_in1,idft_out1,1); - dft216(idft_in2,idft_out2,1); + dft(DFT_216,idft_in0,idft_out0,1); + dft(DFT_216,idft_in1,idft_out1,1); + dft(DFT_216,idft_in2,idft_out2,1); break; case 240: - dft240(idft_in0,idft_out0,1); - dft240(idft_in1,idft_out1,1); - dft240(idft_in2,idft_out2,1); + dft(DFT_240,idft_in0,idft_out0,1); + dft(DFT_240,idft_in1,idft_out1,1); + dft(DFT_240,idft_in2,idft_out2,1); break; case 288: - dft288(idft_in0,idft_out0,1); - dft288(idft_in1,idft_out1,1); - dft288(idft_in2,idft_out2,1); + dft(DFT_288,idft_in0,idft_out0,1); + dft(DFT_288,idft_in1,idft_out1,1); + dft(DFT_288,idft_in2,idft_out2,1); break; case 300: - dft300(idft_in0,idft_out0,1); - dft300(idft_in1,idft_out1,1); - dft300(idft_in2,idft_out2,1); + dft(DFT_300,idft_in0,idft_out0,1); + dft(DFT_300,idft_in1,idft_out1,1); + dft(DFT_300,idft_in2,idft_out2,1); break; case 324: - dft324((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft324((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft324((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_324,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_324,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_324,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 360: - dft360((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft360((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft360((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_360,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_360,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_360,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 384: - dft384((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft384((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft384((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_384,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_384,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_384,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 432: - dft432((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft432((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft432((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_432,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_432,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_432,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 480: - dft480((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft480((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft480((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_480,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_480,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_480,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 540: - dft540((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft540((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft540((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_540,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_540,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_540,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 576: - dft576((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft576((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft576((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_576,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_576,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_576,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 600: - dft600((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft600((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft600((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_600,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_600,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_600,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 648: - dft648((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft648((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft648((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_648,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_648,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_648,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 720: - dft720((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft720((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft720((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_720,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_720,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_720,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 768: - dft768((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft768((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft768((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_768,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_768,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_768,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 864: - dft864((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft864((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft864((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_864,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_864,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_864,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 900: - dft900((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft900((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft900((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_900,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_900,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_900,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 960: - dft960((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft960((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft960((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_960,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_960,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_960,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 972: - dft972((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft972((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft972((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_972,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_972,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_972,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 1080: - dft1080((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft1080((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft1080((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_1080,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_1080,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_1080,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 1152: - dft1152((int16_t *)idft_in0,(int16_t *)idft_out0,1); - dft1152((int16_t *)idft_in1,(int16_t *)idft_out1,1); - dft1152((int16_t *)idft_in2,(int16_t *)idft_out2,1); + dft(DFT_1152,(int16_t *)idft_in0,(int16_t *)idft_out0,1); + dft(DFT_1152,(int16_t *)idft_in1,(int16_t *)idft_out1,1); + dft(DFT_1152,(int16_t *)idft_in2,(int16_t *)idft_out2,1); break; case 1200: - dft1200(idft_in0,idft_out0,1); - dft1200(idft_in1,idft_out1,1); - dft1200(idft_in2,idft_out2,1); + dft(DFT_1200,idft_in0,idft_out0,1); + dft(DFT_1200,idft_in1,idft_out1,1); + dft(DFT_1200,idft_in2,idft_out2,1); break; default: diff --git a/openair1/PHY/MODULATION/ofdm_mod.c b/openair1/PHY/MODULATION/ofdm_mod.c index cbeeca1327..855e649cc5 100644 --- a/openair1/PHY/MODULATION/ofdm_mod.c +++ b/openair1/PHY/MODULATION/ofdm_mod.c @@ -95,41 +95,41 @@ void PHY_ofdm_mod(int *input, /// pointer to complex input volatile int *output_ptr=(int*)0; int *temp_ptr=(int*)0; - void (*idft)(int16_t *,int16_t *, int); + idft_size_idx_t idftsize; switch (fftsize) { case 128: - idft = idft128; + idftsize = IDFT_128; break; case 256: - idft = idft256; + idftsize = IDFT_256; break; case 512: - idft = idft512; + idftsize = IDFT_512; break; case 1024: - idft = idft1024; + idftsize = IDFT_1024; break; case 1536: - idft = idft1536; + idftsize = IDFT_1536; break; case 2048: - idft = idft2048; + idftsize = IDFT_2048; break; case 3072: - idft = idft3072; + idftsize = IDFT_3072; break; case 4096: - idft = idft4096; + idftsize = IDFT_4096; break; default: - idft = idft512; + idftsize = IDFT_512; break; } @@ -148,12 +148,12 @@ void PHY_ofdm_mod(int *input, /// pointer to complex input #ifndef __AVX2__ // handle 128-bit alignment for 128-bit SIMD (SSE4,NEON,AltiVEC) - idft((int16_t *)&input[i*fftsize], + idft(idftsize,(int16_t *)&input[i*fftsize], (fftsize==128) ? (int16_t *)temp : (int16_t *)&output[(i*fftsize) + ((1+i)*nb_prefix_samples)], 1); #else // on AVX2 need 256-bit alignment - idft((int16_t *)&input[i*fftsize], + idft(idftsize,(int16_t *)&input[i*fftsize], (int16_t *)temp, 1); diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index f2e5d24bad..12a02660f9 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -62,44 +62,44 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, unsigned int rx_offset; - void (*dft)(int16_t *,int16_t *, int); + dft_size_idx_t dftsize; int tmp_dft_in[8192] __attribute__ ((aligned (32))); // This is for misalignment issues for 6 and 15 PRBs switch (frame_parms->ofdm_symbol_size) { case 128: - dft = dft128; + dftsize = DFT_128; break; case 256: - dft = dft256; + dftsize = DFT_256; break; case 512: - dft = dft512; + dftsize = DFT_512; break; case 1024: - dft = dft1024; + dftsize = DFT_1024; break; case 1536: - dft = dft1536; + dftsize = DFT_1536; break; case 2048: - dft = dft2048; + dftsize = DFT_2048; break; case 3072: - dft = dft3072; + dftsize = DFT_3072; break; case 4096: - dft = dft4096; + dftsize = DFT_4096; break; case 8192: - dft = dft8192; + dftsize = DFT_8192; break; default: @@ -155,14 +155,14 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, memcpy((void *)tmp_dft_in, (void *) &common_vars->rxdata[aa][rx_offset % frame_length_samples], frame_parms->ofdm_symbol_size*sizeof(int)); - dft((int16_t *)tmp_dft_in, + dft(dftsize,(int16_t *)tmp_dft_in, (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); } else { // use dft input from RX buffer directly #if UE_TIMING_TRACE start_meas(&ue->rx_dft_stats); #endif - dft((int16_t *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], + dft(dftsize,(int16_t *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); #if UE_TIMING_TRACE stop_meas(&ue->rx_dft_stats); @@ -183,11 +183,11 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, memcpy((void *)tmp_dft_in, (void *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], frame_parms->ofdm_symbol_size*sizeof(int)); - dft((int16_t *)tmp_dft_in, + dft(dftsize,(int16_t *)tmp_dft_in, (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); } else { // use dft input from RX buffer directly - dft((int16_t *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], + dft(dftsize,(int16_t *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); } #if UE_TIMING_TRACE @@ -400,43 +400,43 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, unsigned int nb_prefix_samples = (no_prefix ? 0 : frame_parms->nb_prefix_samples); unsigned int nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples0); - void (*dft)(int16_t *,int16_t *, int); + dft_size_idx_t dftsize; switch (frame_parms->ofdm_symbol_size) { case 128: - dft = dft128; + dftsize = DFT_128; break; case 256: - dft = dft256; + dftsize = DFT_256; break; case 512: - dft = dft512; + dftsize = DFT_512; break; case 1024: - dft = dft1024; + dftsize = DFT_1024; break; case 1536: - dft = dft1536; + dftsize = DFT_1536; break; case 2048: - dft = dft2048; + dftsize = DFT_2048; break; case 4096: - dft = dft4096; + dftsize = DFT_4096; break; case 8192: - dft = dft8192; + dftsize = DFT_8192; break; default: - dft = dft512; + dftsize = DFT_512; break; } @@ -448,7 +448,7 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms, else rxdata_offset = slot_offset + nb_prefix_samples0 + (symbol * (frame_parms->ofdm_symbol_size + nb_prefix_samples)) - SOFFSET; - dft((int16_t *)&rxdata[rxdata_offset], + dft(dftsize,(int16_t *)&rxdata[rxdata_offset], (int16_t *)&rxdataF[symbol * frame_parms->ofdm_symbol_size], 1); return(0); diff --git a/openair1/PHY/MODULATION/slot_fep_ul.c b/openair1/PHY/MODULATION/slot_fep_ul.c index 3ac8537c69..746f8dbc0e 100644 --- a/openair1/PHY/MODULATION/slot_fep_ul.c +++ b/openair1/PHY/MODULATION/slot_fep_ul.c @@ -44,7 +44,7 @@ int slot_fep_ul(RU_t *ru, unsigned int slot_offset; - void (*dft)(int16_t *,int16_t *, int); + dft_size_idx_t dftsize; int tmp_dft_in[2048] __attribute__ ((aligned (32))); // This is for misalignment issues for 6 and 15 PRBs unsigned int frame_length_samples = fp->samples_per_tti * 10; @@ -52,31 +52,31 @@ int slot_fep_ul(RU_t *ru, switch (fp->ofdm_symbol_size) { case 128: - dft = dft128; + dftsize = DFT_128; break; case 256: - dft = dft256; + dftsize = DFT_256; break; case 512: - dft = dft512; + dftsize = DFT_512; break; case 1024: - dft = dft1024; + dftsize = DFT_1024; break; case 1536: - dft = dft1536; + dftsize = DFT_1536; break; case 2048: - dft = dft2048; + dftsize = DFT_2048; break; default: - dft = dft512; + dftsize = DFT_512; break; } @@ -109,7 +109,7 @@ int slot_fep_ul(RU_t *ru, LOG_D(PHY,"slot_fep: symbol 0 %d dB\n", dB_fixed(signal_energy(&common->rxdata_7_5kHz[aa][rx_offset],fp->ofdm_symbol_size))); #endif - dft( (int16_t *)&common->rxdata_7_5kHz[aa][rx_offset], + dft( dftsize,(int16_t *)&common->rxdata_7_5kHz[aa][rx_offset], (int16_t *)&common->rxdataF[aa][fp->ofdm_symbol_size*symbol], 1 ); @@ -121,13 +121,13 @@ int slot_fep_ul(RU_t *ru, memcpy((void *)&tmp_dft_in, (void *)&common->rxdata_7_5kHz[aa][(rx_offset % frame_length_samples)], fp->ofdm_symbol_size*sizeof(int)); - dft( (short *) tmp_dft_in, + dft( dftsize,(short *) tmp_dft_in, (short*) &common->rxdataF[aa][fp->ofdm_symbol_size*symbol], 1 ); } else{ - dft( (short *)&common->rxdata_7_5kHz[aa][rx_offset], + dft( dftsize,(short *)&common->rxdata_7_5kHz[aa][rx_offset], (short*)&common->rxdataF[aa][fp->ofdm_symbol_size*symbol], 1 ); diff --git a/openair1/PHY/TOOLS/lte_dfts.c b/openair1/PHY/TOOLS/oai_dfts.c similarity index 99% rename from openair1/PHY/TOOLS/lte_dfts.c rename to openair1/PHY/TOOLS/oai_dfts.c index 2de8653ab3..0b65e7558d 100644 --- a/openair1/PHY/TOOLS/lte_dfts.c +++ b/openair1/PHY/TOOLS/oai_dfts.c @@ -31,11 +31,10 @@ #ifndef M_PI #define M_PI 3.14159265358979323846 #endif - +#define OAIDFTS #ifndef MR_MAIN #include "PHY/defs_common.h" #include "PHY/impl_defs_top.h" -#include "tools_defs.h" #else #include "time_meas.h" #include "LOG/log.h" @@ -64,6 +63,9 @@ const static int16_t reflip[32] __attribute__((aligned(32))) = {1,-1,1,-1,1,-1, + + + #if defined(__x86_64__) || defined(__i386__) static inline void cmac(__m128i a,__m128i b, __m128i *re32, __m128i *im32) __attribute__((always_inline)); static inline void cmac(__m128i a,__m128i b, __m128i *re32, __m128i *im32) @@ -2588,7 +2590,7 @@ const static int16_t tw64c[96] __attribute__((aligned(32))) = { #endif #ifndef __AVX2__ -void dft64(int16_t *x,int16_t *y,int scale) +void dft64(int16_t *x,int16_t *y,unsigned char scale) { simd_q15_t xtmp[16],ytmp[16],*tw64a_128=(simd_q15_t *)tw64a,*tw64b_128=(simd_q15_t *)tw64b,*x128=(simd_q15_t *)x,*y128=(simd_q15_t *)y; @@ -2702,7 +2704,7 @@ void dft64(int16_t *x,int16_t *y,int scale) } #else // __AVX2__ -void dft64(int16_t *x,int16_t *y,int scale) +void dft64(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[16],ytmp[16],*tw64a_256=(simd256_q15_t *)tw64a,*tw64b_256=(simd256_q15_t *)tw64b,*x256=(simd256_q15_t *)x,*y256=(simd256_q15_t *)y; @@ -2850,7 +2852,7 @@ void dft64(int16_t *x,int16_t *y,int scale) #endif #ifndef __AVX2__ -void idft64(int16_t *x,int16_t *y,int scale) +void idft64(int16_t *x,int16_t *y,unsigned char scale) { simd_q15_t xtmp[16],ytmp[16],*tw64a_128=(simd_q15_t *)tw64,*tw64b_128=(simd_q15_t *)tw64c,*x128=(simd_q15_t *)x,*y128=(simd_q15_t *)y; @@ -2942,7 +2944,7 @@ void idft64(int16_t *x,int16_t *y,int scale) } #else // __AVX2__ -void idft64(int16_t *x,int16_t *y,int scale) +void idft64(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[16],ytmp[16],*tw64a_256=(simd256_q15_t *)tw64,*tw64b_256=(simd256_q15_t *)tw64c,*x256=(simd256_q15_t *)x,*y256=(simd256_q15_t *)y; @@ -3052,7 +3054,7 @@ int16_t tw128b[128] __attribute__((aligned(32))) = {0,32767,-1608,32727,-3212,32 int16_t tw128c[128] __attribute__((aligned(32))) = {0,32767,1608,32727,3212,32609,4808,32412,6393,32137,7962,31785,9512,31356,11039,30851,12540,30272,14010,29621,15447,28897,16846,28105,18205,27244,19520,26318,20788,25329,22005,24278,23170,23169,24279,22004,25330,20787,26319,19519,27245,18204,28106,16845,28898,15446,29622,14009,30273,12539,30852,11038,31357,9511,31786,7961,32138,6392,32413,4807,32610,3211,32728,1607,32767,0,32728,-1608,32610,-3212,32413,-4808,32138,-6393,31786,-7962,31357,-9512,30852,-11039,30273,-12540,29622,-14010,28898,-15447,28106,-16846,27245,-18205,26319,-19520,25330,-20788,24279,-22005,23170,-23170,22005,-24279,20788,-25330,19520,-26319,18205,-27245,16846,-28106,15447,-28898,14010,-29622,12540,-30273,11039,-30852,9512,-31357,7962,-31786,6393,-32138,4808,-32413,3212,-32610,1608,-32728}; #ifndef __AVX2__ -void dft128(int16_t *x,int16_t *y,int scale) +void dft128(int16_t *x,int16_t *y,unsigned char scale) { simdshort_q15_t xtmp[64],*x64 = (simdshort_q15_t *)x; @@ -3159,7 +3161,7 @@ void dft128(int16_t *x,int16_t *y,int scale) } #else // __AVX2__ -void dft128(int16_t *x,int16_t *y,int scale) +void dft128(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[16],*x256 = (simd256_q15_t *)x; @@ -3229,7 +3231,7 @@ void dft128(int16_t *x,int16_t *y,int scale) #endif #ifndef __AVX2__ -void idft128(int16_t *x,int16_t *y,int scale) +void idft128(int16_t *x,int16_t *y,unsigned char scale) { simdshort_q15_t xtmp[64],*x64 = (simdshort_q15_t *)x; @@ -3328,7 +3330,7 @@ void idft128(int16_t *x,int16_t *y,int scale) } #else // __AVX2__ -void idft128(int16_t *x,int16_t *y,int scale) +void idft128(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[16],*x256 = (simd256_q15_t *)x; @@ -3401,7 +3403,7 @@ int16_t tw256b[384] __attribute__((aligned(32))) = {0,32767,-805,32757,-1608,327 0,32767,-2411,32678,-4808,32412,-7180,31970,-9512,31356,-11793,30571,-14010,29621,-16151,28510,-18205,27244,-20160,25831,-22005,24278,-23732,22594,-25330,20787,-26790,18867,-28106,16845,-29269,14732,-30273,12539,-31114,10278,-31786,7961,-32285,5601,-32610,3211,-32758,804,-32728,-1608,-32521,-4012,-32138,-6393,-31581,-8740,-30852,-11039,-29956,-13279,-28898,-15447,-27684,-17531,-26319,-19520,-24812,-21403,-23170,-23170,-21403,-24812,-19520,-26319,-17531,-27684,-15447,-28898,-13279,-29956,-11039,-30852,-8740,-31581,-6393,-32138,-4012,-32521,-1608,-32728,804,-32758,3211,-32610,5601,-32285,7961,-31786,10278,-31114,12539,-30273,14732,-29269,16845,-28106,18867,-26790,20787,-25330,22594,-23732,24278,-22005,25831,-20160,27244,-18205,28510,-16151,29621,-14010,30571,-11793,31356,-9512,31970,-7180,32412,-4808,32678,-2411 }; #ifndef __AVX2__ -void dft256(int16_t *x,int16_t *y,int scale) +void dft256(int16_t *x,int16_t *y,unsigned char scale) { simd_q15_t xtmp[64],ytmp[64],*tw256a_128p=(simd_q15_t *)tw256a,*tw256b_128p=(simd_q15_t *)tw256b,*x128=(simd_q15_t *)x,*y128=(simd_q15_t *)y,*y128p=(simd_q15_t *)y; @@ -3513,7 +3515,7 @@ void dft256(int16_t *x,int16_t *y,int scale) -void idft256(int16_t *x,int16_t *y,int scale) +void idft256(int16_t *x,int16_t *y,unsigned char scale) { simd_q15_t xtmp[64],ytmp[64],*tw256_128p=(simd_q15_t *)tw256,*x128=(simd_q15_t *)x,*y128=(simd_q15_t *)y,*y128p=(simd_q15_t *)y; @@ -3571,7 +3573,7 @@ void idft256(int16_t *x,int16_t *y,int scale) #else //__AVX2__ -void dft256(int16_t *x,int16_t *y,int scale) +void dft256(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[32],ytmp[32],*tw256a_256p=(simd256_q15_t *)tw256a,*tw256b_256p=(simd256_q15_t *)tw256b,*x256=(simd256_q15_t *)x,*y256=(simd256_q15_t *)y,*y256p=(simd256_q15_t *)y; @@ -3663,7 +3665,7 @@ void dft256(int16_t *x,int16_t *y,int scale) } -void idft256(int16_t *x,int16_t *y,int scale) +void idft256(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[32],ytmp[32],*tw256_256p=(simd256_q15_t *)tw256,*x256=(simd256_q15_t *)x,*y256=(simd256_q15_t *)y,*y256p=(simd256_q15_t *)y; @@ -3768,7 +3770,7 @@ int16_t tw512c[512] __attribute__((aligned(32))) = { }; #ifndef __AVX2__ -void dft512(int16_t *x,int16_t *y,int scale) +void dft512(int16_t *x,int16_t *y,unsigned char scale) { simdshort_q15_t xtmp[256],*xtmpp,*x64 = (simdshort_q15_t *)x; @@ -3888,7 +3890,7 @@ void dft512(int16_t *x,int16_t *y,int scale) } -void idft512(int16_t *x,int16_t *y,int scale) +void idft512(int16_t *x,int16_t *y,unsigned char scale) { simdshort_q15_t xtmp[256],*xtmpp,*x64 = (simdshort_q15_t *)x; @@ -3980,7 +3982,7 @@ void idft512(int16_t *x,int16_t *y,int scale) #else //__AVX2__ -void dft512(int16_t *x,int16_t *y,int scale) +void dft512(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[64],*x256 = (simd256_q15_t *)x; @@ -4062,7 +4064,7 @@ void dft512(int16_t *x,int16_t *y,int scale) } -void idft512(int16_t *x,int16_t *y,int scale) +void idft512(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[64],*x256 = (simd256_q15_t *)x; @@ -4149,7 +4151,7 @@ void idft512(int16_t *x,int16_t *y,int scale) int16_t tw1024[1536] __attribute__((aligned(32))); #ifndef __AVX2__ -void dft1024(int16_t *x,int16_t *y,int scale) +void dft1024(int16_t *x,int16_t *y,unsigned char scale) { simd_q15_t xtmp[256],ytmp[256],*tw1024_128p=(simd_q15_t *)tw1024,*x128=(simd_q15_t *)x,*y128=(simd_q15_t *)y,*y128p=(simd_q15_t *)y; @@ -4205,7 +4207,7 @@ void dft1024(int16_t *x,int16_t *y,int scale) } -void idft1024(int16_t *x,int16_t *y,int scale) +void idft1024(int16_t *x,int16_t *y,unsigned char scale) { simd_q15_t xtmp[256],ytmp[256],*tw1024_128p=(simd_q15_t *)tw1024,*x128=(simd_q15_t *)x,*y128=(simd_q15_t *)y,*y128p=(simd_q15_t *)y; @@ -4262,7 +4264,7 @@ void idft1024(int16_t *x,int16_t *y,int scale) } #else //__AVX2__ -void dft1024(int16_t *x,int16_t *y,int scale) +void dft1024(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[128],ytmp[128],*tw1024_256p=(simd256_q15_t *)tw1024,*x256=(simd256_q15_t *)x,*y256=(simd256_q15_t *)y,*y256p=(simd256_q15_t *)y; @@ -4318,7 +4320,7 @@ void dft1024(int16_t *x,int16_t *y,int scale) } -void idft1024(int16_t *x,int16_t *y,int scale) +void idft1024(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[128],ytmp[128],*tw1024_256p=(simd256_q15_t *)tw1024,*x256=(simd256_q15_t *)x,*y256=(simd256_q15_t *)y,*y256p=(simd256_q15_t *)y; @@ -4378,7 +4380,7 @@ void idft1024(int16_t *x,int16_t *y,int scale) int16_t tw2048[2048] __attribute__((aligned(32))); #ifndef __AVX2__ -void dft2048(int16_t *x,int16_t *y,int scale) +void dft2048(int16_t *x,int16_t *y,unsigned char scale) { simdshort_q15_t xtmp[1024],*xtmpp,*x64 = (simdshort_q15_t *)x; @@ -4469,7 +4471,7 @@ void dft2048(int16_t *x,int16_t *y,int scale) } -void idft2048(int16_t *x,int16_t *y,int scale) +void idft2048(int16_t *x,int16_t *y,unsigned char scale) { simdshort_q15_t xtmp[1024],*xtmpp,*x64 = (simdshort_q15_t *)x; @@ -4561,7 +4563,7 @@ void idft2048(int16_t *x,int16_t *y,int scale) #else // __AVX2__ -void dft2048(int16_t *x,int16_t *y,int scale) +void dft2048(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[256],*xtmpp,*x256 = (simd256_q15_t *)x; @@ -4652,7 +4654,7 @@ void dft2048(int16_t *x,int16_t *y,int scale) } -void idft2048(int16_t *x,int16_t *y,int scale) +void idft2048(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[256],*xtmpp,*x256 = (simd256_q15_t *)x; @@ -4749,7 +4751,7 @@ void idft2048(int16_t *x,int16_t *y,int scale) int16_t tw4096[3*2*1024]; #ifndef __AVX2__ -void dft4096(int16_t *x,int16_t *y,int scale) +void dft4096(int16_t *x,int16_t *y,unsigned char scale) { simd_q15_t xtmp[1024],ytmp[1024],*tw4096_128p=(simd_q15_t *)tw4096,*x128=(simd_q15_t *)x,*y128=(simd_q15_t *)y,*y128p=(simd_q15_t *)y; @@ -4807,7 +4809,7 @@ void dft4096(int16_t *x,int16_t *y,int scale) -void idft4096(int16_t *x,int16_t *y,int scale) +void idft4096(int16_t *x,int16_t *y,unsigned char scale) { simd_q15_t xtmp[1024],ytmp[1024],*tw4096_128p=(simd_q15_t *)tw4096,*x128=(simd_q15_t *)x,*y128=(simd_q15_t *)y,*y128p=(simd_q15_t *)y; @@ -4864,7 +4866,7 @@ void idft4096(int16_t *x,int16_t *y,int scale) } #else //__AVX2__ -void dft4096(int16_t *x,int16_t *y,int scale) +void dft4096(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[512],ytmp[512],*tw4096_256p=(simd256_q15_t *)tw4096,*x256=(simd256_q15_t *)x,*y256=(simd256_q15_t *)y,*y256p=(simd256_q15_t *)y; @@ -4920,7 +4922,7 @@ void dft4096(int16_t *x,int16_t *y,int scale) } -void idft4096(int16_t *x,int16_t *y,int scale) +void idft4096(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[512],ytmp[512],*tw4096_256p=(simd256_q15_t *)tw4096,*x256=(simd256_q15_t *)x,*y256=(simd256_q15_t *)y,*y256p=(simd256_q15_t *)y; @@ -4982,7 +4984,7 @@ void idft4096(int16_t *x,int16_t *y,int scale) int16_t tw8192[2*4096] __attribute__((aligned(32))); #ifndef __AVX2__ -void dft8192(int16_t *x,int16_t *y,int scale) +void dft8192(int16_t *x,int16_t *y,unsigned char scale) { simdshort_q15_t xtmp[4096],*xtmpp,*x64 = (simdshort_q15_t *)x; @@ -5072,7 +5074,7 @@ void dft8192(int16_t *x,int16_t *y,int scale) } -void idft8192(int16_t *x,int16_t *y,int scale) +void idft8192(int16_t *x,int16_t *y,unsigned char scale) { simdshort_q15_t xtmp[4096],*xtmpp,*x64 = (simdshort_q15_t *)x; @@ -5163,7 +5165,7 @@ void idft8192(int16_t *x,int16_t *y,int scale) } #else // __AVX2__ -void dft8192(int16_t *x,int16_t *y,int scale) +void dft8192(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[1024],*xtmpp,*x256 = (simd256_q15_t *)x; @@ -5254,7 +5256,7 @@ void dft8192(int16_t *x,int16_t *y,int scale) } -void idft8192(int16_t *x,int16_t *y,int scale) +void idft8192(int16_t *x,int16_t *y,unsigned char scale) { simd256_q15_t xtmp[1024],*xtmpp,*x256 = (simd256_q15_t *)x; @@ -5350,7 +5352,7 @@ void idft8192(int16_t *x,int16_t *y,int scale) int16_t twa1536[1024],twb1536[1024]; // 512 x 3 -void idft1536(int16_t *input, int16_t *output, int scale) +void idft1536(int16_t *input, int16_t *output, unsigned char scale) { int i,i2,j; uint32_t tmp[3][512 ]__attribute__((aligned(32))); @@ -5402,7 +5404,7 @@ void idft1536(int16_t *input, int16_t *output, int scale) } -void dft1536(int16_t *input, int16_t *output, int scale) +void dft1536(int16_t *input, int16_t *output, unsigned char scale) { int i,i2,j; uint32_t tmp[3][512] __attribute__((aligned(32))); @@ -5467,7 +5469,7 @@ void dft1536(int16_t *input, int16_t *output, int scale) int16_t twa3072[2048] __attribute__((aligned(32))); int16_t twb3072[2048] __attribute__((aligned(32))); // 1024 x 3 -void dft3072(int16_t *input, int16_t *output,int scale) +void dft3072(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][1024] __attribute__((aligned(32))); @@ -5517,7 +5519,7 @@ void dft3072(int16_t *input, int16_t *output,int scale) _m_empty(); } -void idft3072(int16_t *input, int16_t *output,int scale) +void idft3072(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][1024]__attribute__((aligned(32))); @@ -5571,7 +5573,7 @@ void idft3072(int16_t *input, int16_t *output,int scale) int16_t twa6144[4096] __attribute__((aligned(32))); int16_t twb6144[4096] __attribute__((aligned(32))); -void idft6144(int16_t *input, int16_t *output,int scale) +void idft6144(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][2048] __attribute__((aligned(32))); @@ -5631,7 +5633,7 @@ void idft6144(int16_t *input, int16_t *output,int scale) } -void dft6144(int16_t *input, int16_t *output,int scale) +void dft6144(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][2048] __attribute__((aligned(32))); @@ -5708,7 +5710,7 @@ void idft9216(int16_t *input, int16_t *output,int scale) { int16_t twa12288[8192] __attribute__((aligned(32))); int16_t twb12288[8192] __attribute__((aligned(32))); // 4096 x 3 -void dft12288(int16_t *input, int16_t *output,int scale) +void dft12288(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][4096] __attribute__((aligned(32))); @@ -5768,7 +5770,7 @@ void dft12288(int16_t *input, int16_t *output,int scale) } -void idft12288(int16_t *input, int16_t *output,int scale) +void idft12288(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][4096] __attribute__((aligned(32))); @@ -5832,7 +5834,7 @@ void idft12288(int16_t *input, int16_t *output,int scale) int16_t twa18432[12288] __attribute__((aligned(32))); int16_t twb18432[12288] __attribute__((aligned(32))); // 6144 x 3 -void dft18432(int16_t *input, int16_t *output,int scale) { +void dft18432(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][6144] __attribute__((aligned(32))); @@ -5880,7 +5882,7 @@ void dft18432(int16_t *input, int16_t *output,int scale) { _m_empty(); } -void idft18432(int16_t *input, int16_t *output,int scale) { +void idft18432(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][6144] __attribute__((aligned(32))); @@ -5932,7 +5934,7 @@ void idft18432(int16_t *input, int16_t *output,int scale) { int16_t twa24576[16384] __attribute__((aligned(32))); int16_t twb24576[16384] __attribute__((aligned(32))); // 8192 x 3 -void dft24576(int16_t *input, int16_t *output,int scale) +void dft24576(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][8192] __attribute__((aligned(32))); @@ -5995,7 +5997,7 @@ void dft24576(int16_t *input, int16_t *output,int scale) } } -void idft24576(int16_t *input, int16_t *output,int scale) +void idft24576(int16_t *input, int16_t *output,unsigned char scale) { int i,i2,j; uint32_t tmp[3][8192] __attribute__((aligned(32))); @@ -6259,7 +6261,7 @@ static inline void dft12f(simd_q15_t *x0, -void dft12(int16_t *x,int16_t *y) +void dft12(int16_t *x,int16_t *y ,unsigned char scale_flag) { simd_q15_t *x128 = (simd_q15_t *)x,*y128 = (simd_q15_t *)y; @@ -8711,7 +8713,8 @@ void init_rad5_rep(int N,int16_t *twa,int16_t *twb,int16_t *twc,int16_t *twd) { twd+=8; } } - +/*----------------------------------------------------------------*/ +/* dft library entry points: */ void init_dfts(void) { @@ -8760,9 +8763,22 @@ void init_dfts(void) init_rad3_rep(1080,twa1080,twb1080); init_rad4_rep(1152,twa1152,twb1152,twc1152); init_rad4_rep(1200,twa1200,twb1200,twc1200); + } -//#undef round + +void dft(uint8_t sizeidx, int16_t *sigF,int16_t *sig,unsigned char scale_flag){ + AssertFatal((sizeidx>=0 && sizeidx<(int)DFT_SIZE_IDXTABLESIZE),"Invalid dft size index %i\n",sizeidx); + dft_ftab[sizeidx](sigF,sig,scale_flag); +}; + +void idft(uint8_t sizeidx, int16_t *sigF,int16_t *sig,unsigned char scale_flag){ + AssertFatal((sizeidx>=0 && sizeidx<(int)IDFT_SIZE_IDXTABLESIZE),"Invalid idft size index %i\n",sizeidx); + idft_ftab[sizeidx](sigF,sig,scale_flag); +}; + +/*---------------------------------------------------------------------------------------*/ + #ifdef MR_MAIN #include diff --git a/openair1/PHY/TOOLS/tools_defs.h b/openair1/PHY/TOOLS/tools_defs.h index d753b501b6..eb94f2dc4b 100644 --- a/openair1/PHY/TOOLS/tools_defs.h +++ b/openair1/PHY/TOOLS/tools_defs.h @@ -179,29 +179,234 @@ This function performs optimized fixed-point radix-2 FFT/IFFT. ); */ -void idft1536(int16_t *sigF,int16_t *sig,int scale); -void idft6144(int16_t *sigF,int16_t *sig,int scale); -void idft12288(int16_t *sigF,int16_t *sig,int scale); -void idft18432(int16_t *sigF,int16_t *sig,int scale); -void idft3072(int16_t *sigF,int16_t *sig,int scale); -void idft24576(int16_t *sigF,int16_t *sig,int scale); -void dft1536(int16_t *sigF,int16_t *sig,int scale); -void dft3072(int16_t *sigF,int16_t *sig,int scale); +#ifdef OAIDFTS +typedef void(*adftfunc_t)(int16_t *sigF,int16_t *sig,unsigned char scale_flag); +typedef void(*aidftfunc_t)(int16_t *sigF,int16_t *sig,unsigned char scale_flag); -void dft6144(int16_t *sigF,int16_t *sig,int scale); +void dft12(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft24(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft36(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft48(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft60(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft72(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft96(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft108(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft120(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft144(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft180(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft192(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft216(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft240(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft288(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft300(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft324(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft360(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft384(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft432(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft480(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft540(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft576(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft600(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft648(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft720(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft768(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft864(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft900(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft960(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft972(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft1080(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft1152(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft1200(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft12288(int16_t *sigF,int16_t *sig,int scale); +void dft64(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft128(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft256(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft512(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft1024(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft2048(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft4096(int16_t *x,int16_t *y,uint8_t scale_flag); +void dft8192(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft18432(int16_t *sigF,int16_t *sig,int scale); +void idft64(int16_t *x,int16_t *y,uint8_t scale_flag); +void idft128(int16_t *x,int16_t *y,uint8_t scale_flag); +void idft256(int16_t *x,int16_t *y,uint8_t scale_flag); +void idft512(int16_t *x,int16_t *y,uint8_t scale_flag); +void idft1024(int16_t *x,int16_t *y,uint8_t scale_flag); +void idft2048(int16_t *x,int16_t *y,uint8_t scale_flag); +void idft4096(int16_t *x,int16_t *y,uint8_t scale_flag); +void idft8192(int16_t *x,int16_t *y,uint8_t scale_flag); + +void idft1536(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void idft6144(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void idft12288(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void idft18432(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void idft3072(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void idft24576(int16_t *sigF,int16_t *sig,uint8_t scale_flag); + +void dft1536(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void dft3072(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void dft6144(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void dft12288(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void dft18432(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +void dft24576(int16_t *sigF,int16_t *sig,uint8_t scale_flag); +#else +typedef void(*dftfunc_t)(uint8_t sizeidx,int16_t *sigF,int16_t *sig,unsigned char scale_flag); +typedef void(*idftfunc_t)(uint8_t sizeidx,int16_t *sigF,int16_t *sig,unsigned char scale_flag); +extern dftfunc_t dft; +extern idftfunc_t idft; +#endif + +typedef enum DFT_size_idx { + DFT_12, + DFT_24, + DFT_36, + DFT_48, + DFT_60, + DFT_72, + DFT_96, + DFT_108, + DFT_120, + DFT_128, + DFT_144, + DFT_180, + DFT_192, + DFT_216, + DFT_240, + DFT_256, + DFT_288, + DFT_300, + DFT_324, + DFT_360, + DFT_384, + DFT_432, + DFT_480, + DFT_512, + DFT_540, + DFT_576, + DFT_600, + DFT_648, + DFT_720, + DFT_768, + DFT_864, + DFT_900, + DFT_960, + DFT_972, + DFT_1024, + DFT_1080, + DFT_1152, + DFT_1200, + DFT_1536, + DFT_2048, + DFT_3072, + DFT_4096, + DFT_6144, + DFT_8192, + DFT_12288, + DFT_18432, + DFT_24576, + DFT_SIZE_IDXTABLESIZE, +} dft_size_idx_t; + +#ifdef OAIDFTS +adftfunc_t dft_ftab[]={ + dft12, + dft24, + dft36, + dft48, + dft60, + dft72, + dft96, + dft108, + dft120, + dft128, + dft144, + dft180, + dft192, + dft216, + dft240, + dft256, + dft288, + dft300, + dft324, + dft360, + dft384, + dft432, + dft480, + dft512, + dft540, + dft576, + dft600, + dft648, + dft720, + dft768, + dft864, + dft900, + dft960, + dft972, + dft1024, + dft1080, + dft1152, + dft1200, + dft1536, + dft2048, + dft3072, + dft4096, + dft6144, + dft8192, + dft12288, + dft18432, + dft24576, +}; +#endif + +typedef enum idft_size_idx { + IDFT_128, + IDFT_256, + IDFT_288, + IDFT_300, + IDFT_324, + IDFT_360, + IDFT_384, + IDFT_432, + IDFT_480, + IDFT_512, + IDFT_1024, + IDFT_1536, + IDFT_2048, + IDFT_3072, + IDFT_4096, + IDFT_6144, + IDFT_8192, + IDFT_12288, + IDFT_18432, + IDFT_24576, + IDFT_SIZE_IDXTABLESIZE, +} idft_size_idx_t; +#ifdef OAIDFTS +aidftfunc_t idft_ftab[]={ + idft128, + idft256, + idft512, + idft1024, + idft1536, + idft2048, + idft3072, + idft4096, + idft6144, + idft8192, + idft12288, + idft18432, + idft24576, +}; +#endif -void dft24576(int16_t *sigF,int16_t *sig,int scale); void dft49152(int16_t *sigF,int16_t *sig,int scale); void idft49152(int16_t *sigF,int16_t *sig,int scale); @@ -387,57 +592,7 @@ int64_t dot_product64(int16_t *x, uint32_t N, //must be a multiple of 8 uint8_t output_shift); -void dft12(int16_t *x,int16_t *y); -void dft24(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft36(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft48(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft60(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft72(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft96(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft108(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft120(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft144(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft180(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft192(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft216(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft240(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft288(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft300(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft324(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft360(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft384(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft432(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft480(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft540(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft576(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft600(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft648(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft720(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft768(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft864(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft900(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft960(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft972(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft1080(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft1152(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft1200(int16_t *x,int16_t *y,uint8_t scale_flag); -void dft64(int16_t *x,int16_t *y,int scale); -void dft128(int16_t *x,int16_t *y,int scale); -void dft256(int16_t *x,int16_t *y,int scale); -void dft512(int16_t *x,int16_t *y,int scale); -void dft1024(int16_t *x,int16_t *y,int scale); -void dft2048(int16_t *x,int16_t *y,int scale); -void dft4096(int16_t *x,int16_t *y,int scale); -void dft8192(int16_t *x,int16_t *y,int scale); -void idft64(int16_t *x,int16_t *y,int scale); -void idft128(int16_t *x,int16_t *y,int scale); -void idft256(int16_t *x,int16_t *y,int scale); -void idft512(int16_t *x,int16_t *y,int scale); -void idft1024(int16_t *x,int16_t *y,int scale); -void idft2048(int16_t *x,int16_t *y,int scale); -void idft4096(int16_t *x,int16_t *y,int scale); -void idft8192(int16_t *x,int16_t *y,int scale); /** @} */ From 5e0d6253b8f951dbb4f5ac00d4059601043d8105 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 6 Feb 2020 18:26:52 +0100 Subject: [PATCH 099/240] Fix: search UE in ULSCH when handling UCI --- openair1/SCHED/fapi_l1.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openair1/SCHED/fapi_l1.c b/openair1/SCHED/fapi_l1.c index 8105877bc3..4ce89775c7 100644 --- a/openair1/SCHED/fapi_l1.c +++ b/openair1/SCHED/fapi_l1.c @@ -596,7 +596,8 @@ void handle_uci_sr_pdu(PHY_VARS_eNB *eNB, uci->frame = frame; uci->subframe = subframe; uci->rnti = ul_config_pdu->uci_sr_pdu.ue_information.ue_information_rel8.rnti; - uci->ue_id = find_dlsch(ul_config_pdu->uci_sr_pdu.ue_information.ue_information_rel8.rnti,eNB,SEARCH_EXIST_OR_FREE); + uci->ue_id = find_ulsch(ul_config_pdu->uci_sr_pdu.ue_information.ue_information_rel8.rnti,eNB,SEARCH_EXIST_OR_FREE); + AssertFatal(uci->ue_id < MAX_MOBILES_PER_ENB, "illegal UE_id %d\n", uci->ue_id); uci->type = SR; uci->pucch_fmt = pucch_format1; uci->num_antenna_ports = 1; @@ -622,7 +623,8 @@ void handle_uci_sr_harq_pdu(PHY_VARS_eNB *eNB,int UE_id,nfapi_ul_config_request_ uci->frame = frame; uci->subframe = subframe; uci->rnti = ul_config_pdu->uci_sr_harq_pdu.ue_information.ue_information_rel8.rnti; - uci->ue_id = find_dlsch(ul_config_pdu->uci_sr_harq_pdu.ue_information.ue_information_rel8.rnti,eNB,SEARCH_EXIST_OR_FREE); + uci->ue_id = find_ulsch(ul_config_pdu->uci_sr_harq_pdu.ue_information.ue_information_rel8.rnti,eNB,SEARCH_EXIST_OR_FREE); + AssertFatal(uci->ue_id < MAX_MOBILES_PER_ENB, "illegal UE_id %d\n", uci->ue_id); uci->type = HARQ_SR; uci->num_antenna_ports = 1; uci->num_pucch_resources = 1; @@ -644,7 +646,8 @@ void handle_uci_harq_pdu(PHY_VARS_eNB *eNB,int UE_id,nfapi_ul_config_request_pdu uci->frame = frame; uci->subframe = subframe; uci->rnti = ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.rnti; - uci->ue_id = find_dlsch(ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.rnti,eNB,SEARCH_EXIST_OR_FREE); + uci->ue_id = find_ulsch(ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.rnti,eNB,SEARCH_EXIST_OR_FREE); + AssertFatal(uci->ue_id < MAX_MOBILES_PER_ENB, "illegal UE_id %d\n", uci->ue_id); uci->type = HARQ; uci->srs_active = srs_active; uci->num_antenna_ports = ul_config_pdu->uci_harq_pdu.harq_information.harq_information_rel11.num_ant_ports; From 1efd2b428b69ba84af1513b594baa8e3064fb739 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 23 Jan 2020 09:58:02 +0100 Subject: [PATCH 100/240] Remove useless MAC/defs.h file --- openair2/LAYER2/MAC/defs.h | 1321 ------------------------------------ 1 file changed, 1321 deletions(-) delete mode 100644 openair2/LAYER2/MAC/defs.h diff --git a/openair2/LAYER2/MAC/defs.h b/openair2/LAYER2/MAC/defs.h deleted file mode 100644 index 05660b727e..0000000000 --- a/openair2/LAYER2/MAC/defs.h +++ /dev/null @@ -1,1321 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! \file LAYER2/MAC/defs.h -* \brief MAC data structures, constant, and function prototype -* \author Navid Nikaein and Raymond Knopp -* \date 2011 -* \version 0.5 -* \email navid.nikaein@eurecom.fr - -*/ -/** @defgroup _oai2 openair2 Reference Implementation - * @ingroup _ref_implementation_ - * @{ - */ - -/*@}*/ - -#ifndef __LAYER2_MAC_DEFS_H__ -#define __LAYER2_MAC_DEFS_H__ - - - -#ifdef USER_MODE - #include - #include - #include -#endif - -//#include "COMMON/openair_defs.h" - - - -#include "PHY/defs.h" -#include "PHY/LTE_TRANSPORT/defs.h" -#include "COMMON/platform_constants.h" -#include "BCCH-BCH-Message.h" -#include "RadioResourceConfigCommon.h" -#include "RadioResourceConfigDedicated.h" -#include "MeasGapConfig.h" -#include "SchedulingInfoList.h" -#include "TDD-Config.h" -#include "RACH-ConfigCommon.h" -#include "MeasObjectToAddModList.h" -#include "MobilityControlInfo.h" -#include "MBSFN-AreaInfoList-r9.h" -#include "MBSFN-SubframeConfigList.h" -#include "PMCH-InfoList-r9.h" -#include "SCellToAddMod-r10.h" -#include "SystemInformationBlockType1-v1310-IEs.h" - - -#include "nfapi_interface.h" -#include "PHY_INTERFACE/IF_Module.h" - -/** @defgroup _mac MAC - * @ingroup _oai2 - * @{ - */ - -#define BCCH_PAYLOAD_SIZE_MAX 128 -#define CCCH_PAYLOAD_SIZE_MAX 128 -#define PCCH_PAYLOAD_SIZE_MAX 128 -#define RAR_PAYLOAD_SIZE_MAX 128 - -#define SCH_PAYLOAD_SIZE_MAX 4096 -/// Logical channel ids from 36-311 (Note BCCH is not specified in 36-311, uses the same as first DRB) - - -// Mask for identifying subframe for MBMS -#define MBSFN_TDD_SF3 0x80// for TDD -#define MBSFN_TDD_SF4 0x40 -#define MBSFN_TDD_SF7 0x20 -#define MBSFN_TDD_SF8 0x10 -#define MBSFN_TDD_SF9 0x08 -#define MBSFN_FDD_SF1 0x80// for FDD -#define MBSFN_FDD_SF2 0x40 -#define MBSFN_FDD_SF3 0x20 -#define MBSFN_FDD_SF6 0x10 -#define MBSFN_FDD_SF7 0x08 -#define MBSFN_FDD_SF8 0x04 - -#define MAX_MBSFN_AREA 8 -#define MAX_PMCH_perMBSFN 15 -/*!\brief MAX MCCH payload size */ -#define MCCH_PAYLOAD_SIZE_MAX 128 - - -#ifdef USER_MODE - #define printk printf -#endif //USER_MODE - -/*!\brief Maximum number of logical channl group IDs */ -#define MAX_NUM_LCGID 4 -/*!\brief logical channl group ID 0 */ -#define LCGID0 0 -/*!\brief logical channl group ID 1 */ -#define LCGID1 1 -/*!\brief logical channl group ID 2 */ -#define LCGID2 2 -/*!\brief logical channl group ID 3 */ -#define LCGID3 3 -/*!\brief Maximum number of logical chanels */ -#define MAX_NUM_LCID 11 -/*!\brief Maximum number od control elemenets */ -#define MAX_NUM_CE 5 -/*!\brief Maximum number of random access process */ -#define NB_RA_PROC_MAX 4 -/*!\brief size of buffer status report table */ -#define BSR_TABLE_SIZE 64 -/*!\brief The power headroom reporting range is from -23 ...+40 dB and beyond, with step 1 */ -#define PHR_MAPPING_OFFSET 23 // if ( x>= -23 ) val = floor (x + 23) -/*!\brief maximum number of resource block groups */ -#define N_RBG_MAX 25 // for 20MHz channel BW -/*!\brief minimum value for channel quality indicator */ -#define MIN_CQI_VALUE 0 -/*!\brief maximum value for channel quality indicator */ -#define MAX_CQI_VALUE 15 -/*!\briefmaximum number of supported bandwidth (1.4, 5, 10, 20 MHz) */ -#define MAX_SUPPORTED_BW 4 -/*!\brief CQI values range from 1 to 15 (4 bits) */ -#define CQI_VALUE_RANGE 16 - -/*!\brief value for indicating BSR Timer is not running */ -#define MAC_UE_BSR_TIMER_NOT_RUNNING (0xFFFF) - -#define LCID_EMPTY 0 -#define LCID_NOT_EMPTY 1 - -/*!\brief minimum RLC PDU size to be transmitted = min RLC Status PDU or RLC UM PDU SN 5 bits */ -#define MIN_RLC_PDU_SIZE (2) - -/*!\brief minimum MAC data needed for transmitting 1 min RLC PDU size + 1 byte MAC subHeader */ -#define MIN_MAC_HDR_RLC_SIZE (1 + MIN_RLC_PDU_SIZE) - -/*!\brief maximum number of slices / groups */ -#define MAX_NUM_SLICES 4 - -/* - * eNB part - */ - - -/* - * UE/ENB common part - */ -/*!\brief MAC header of Random Access Response for Random access preamble identifier (RAPID) */ -typedef struct { - uint8_t RAPID:6; - uint8_t T:1; - uint8_t E:1; -} __attribute__((__packed__))RA_HEADER_RAPID; - -/*!\brief MAC header of Random Access Response for backoff indicator (BI)*/ -typedef struct { - uint8_t BI:4; - uint8_t R:2; - uint8_t T:1; - uint8_t E:1; -} __attribute__((__packed__))RA_HEADER_BI; -/* -typedef struct { - uint64_t padding:16; - uint64_t t_crnti:16; - uint64_t hopping_flag:1; - uint64_t rb_alloc:10; - uint64_t mcs:4; - uint64_t TPC:3; - uint64_t UL_delay:1; - uint64_t cqi_req:1; - uint64_t Timing_Advance_Command:11; // first/2nd octet LSB - uint64_t R:1; // octet MSB - } __attribute__((__packed__))RAR_PDU; - -typedef struct { - uint64_t padding:16; - uint64_t R:1; // octet MSB - uint64_t Timing_Advance_Command:11; // first/2nd octet LSB - uint64_t cqi_req:1; - uint64_t UL_delay:1; - uint64_t TPC:3; - uint64_t mcs:4; - uint64_t rb_alloc:10; - uint64_t hopping_flag:1; - uint64_t t_crnti:16; - } __attribute__((__packed__))RAR_PDU; - -#define sizeof_RAR_PDU 6 -*/ -/*!\brief MAC subheader short with 7bit Length field */ -typedef struct { - uint8_t LCID:5; // octet 1 LSB - uint8_t E:1; - uint8_t R:2; // octet 1 MSB - uint8_t L:7; // octet 2 LSB - uint8_t F:1; // octet 2 MSB -} __attribute__((__packed__))SCH_SUBHEADER_SHORT; -/*!\brief MAC subheader long with 15bit Length field */ -typedef struct { - uint8_t LCID:5; // octet 1 LSB - uint8_t E:1; - uint8_t R:2; // octet 1 MSB - uint8_t L_MSB:7; - uint8_t F:1; // octet 2 MSB - uint8_t L_LSB:8; - uint8_t padding; -} __attribute__((__packed__))SCH_SUBHEADER_LONG; -/*!\brief MAC subheader short without length field */ -typedef struct { - uint8_t LCID:5; - uint8_t E:1; - uint8_t R:2; -} __attribute__((__packed__))SCH_SUBHEADER_FIXED; - -/*!\brief mac control element: short buffer status report for a specific logical channel group ID*/ -typedef struct { - uint8_t Buffer_size:6; // octet 1 LSB - uint8_t LCGID:2; // octet 1 MSB -} __attribute__((__packed__))BSR_SHORT; - -typedef BSR_SHORT BSR_TRUNCATED; -/*!\brief mac control element: long buffer status report for all logical channel group ID*/ -typedef struct { - uint8_t Buffer_size3:6; - uint8_t Buffer_size2:6; - uint8_t Buffer_size1:6; - uint8_t Buffer_size0:6; -} __attribute__((__packed__))BSR_LONG; - -#define BSR_LONG_SIZE (sizeof(BSR_LONG)) -/*!\brief mac control element: timing advance */ -typedef struct { - uint8_t TA:6; - uint8_t R:2; -} __attribute__((__packed__))TIMING_ADVANCE_CMD; -/*!\brief mac control element: power headroom report */ -typedef struct { - uint8_t PH:6; - uint8_t R:2; -} __attribute__((__packed__))POWER_HEADROOM_CMD; - -/*! \brief MIB payload */ -typedef struct { - uint8_t payload[3] ; -} __attribute__((__packed__))MIB_PDU; -/*! \brief CCCH payload */ -typedef struct { - uint8_t payload[CCCH_PAYLOAD_SIZE_MAX] ; -} __attribute__((__packed__))CCCH_PDU; -/*! \brief BCCH payload */ -typedef struct { - uint8_t payload[BCCH_PAYLOAD_SIZE_MAX] ; -} __attribute__((__packed__))BCCH_PDU; -/*! \brief RAR payload */ -typedef struct { - uint8_t payload[RAR_PAYLOAD_SIZE_MAX]; -} __attribute__ ((__packed__)) RAR_PDU; -/*! \brief BCCH payload */ -typedef struct { - uint8_t payload[PCCH_PAYLOAD_SIZE_MAX] ; -} __attribute__((__packed__))PCCH_PDU; - -/*! \brief MCCH payload */ -typedef struct { - uint8_t payload[MCCH_PAYLOAD_SIZE_MAX] ; -} __attribute__((__packed__))MCCH_PDU; -/*!< \brief MAC control element for activation and deactivation of component carriers */ -typedef struct { - uint8_t C7:1;/*!< \brief Component carrier 7 */ - uint8_t C6:1;/*!< \brief Component carrier 6 */ - uint8_t C5:1;/*!< \brief Component carrier 5 */ - uint8_t C4:1;/*!< \brief Component carrier 4 */ - uint8_t C3:1;/*!< \brief Component carrier 3 */ - uint8_t C2:1;/*!< \brief Component carrier 2 */ - uint8_t C1:1;/*!< \brief Component carrier 1 */ - uint8_t R:1;/*!< \brief Reserved */ -} __attribute__((__packed__))CC_ELEMENT; -/*! \brief MAC control element: MCH Scheduling Information */ -typedef struct { - uint8_t stop_sf_MSB:3; // octet 1 LSB - uint8_t lcid:5; // octet 2 MSB - uint8_t stop_sf_LSB:8; -} __attribute__((__packed__))MSI_ELEMENT; -/*! \brief Values of CCCH LCID for DLSCH */ -#define CCCH_LCHANID 0 -/*!\brief Values of BCCH logical channel (fake)*/ -#define BCCH 3 // SI -/*!\brief Values of PCCH logical channel (fake)*/ -#define PCCH 4 // Paging -/*!\brief Values of PCCH logical channel (fake) */ -#define MIBCH 5 // MIB -/*!\brief Values of BCCH SIB1_BR logical channel (fake) */ -#define BCCH_SIB1_BR 6 // SIB1_BR -/*!\brief Values of BCCH SIB_BR logical channel (fake) */ -#define BCCH_SI_BR 7 // SI-BR -/*!\brief Value of CCCH / SRB0 logical channel */ -#define CCCH 0 // srb0 -/*!\brief DCCH / SRB1 logical channel */ -#define DCCH 1 // srb1 -/*!\brief DCCH1 / SRB2 logical channel */ -#define DCCH1 2 // srb2 -/*!\brief DTCH DRB1 logical channel */ -#define DTCH 3 // LCID -/*!\brief MCCH logical channel */ -#define MCCH 11 -/*!\brief MTCH logical channel */ -#define MTCH 1 -// DLSCH LCHAN ID -/*!\brief LCID of UE contention resolution identity for DLSCH*/ -#define UE_CONT_RES 28 -/*!\brief LCID of timing advance for DLSCH */ -#define TIMING_ADV_CMD 29 -/*!\brief LCID of discontinous reception mode for DLSCH */ -#define DRX_CMD 30 -/*!\brief LCID of padding LCID for DLSCH */ -#define SHORT_PADDING 31 - -// MCH LCHAN IDs (table6.2.1-4 TS36.321) -/*!\brief LCID of MCCH for DL */ -#define MCCH_LCHANID 0 -/*!\brief LCID of MCH scheduling info for DL */ -#define MCH_SCHDL_INFO 3 -/*!\brief LCID of Carrier component activation/deactivation */ -#define CC_ACT_DEACT 27 - -// ULSCH LCHAN IDs -/*!\brief LCID of extended power headroom for ULSCH */ -#define EXTENDED_POWER_HEADROOM 25 -/*!\brief LCID of power headroom for ULSCH */ -#define POWER_HEADROOM 26 -/*!\brief LCID of CRNTI for ULSCH */ -#define CRNTI 27 -/*!\brief LCID of truncated BSR for ULSCH */ -#define TRUNCATED_BSR 28 -/*!\brief LCID of short BSR for ULSCH */ -#define SHORT_BSR 29 -/*!\brief LCID of long BSR for ULSCH */ -#define LONG_BSR 30 -/*!\bitmaps for BSR Triggers */ -#define BSR_TRIGGER_NONE (0) /* No BSR Trigger */ -#define BSR_TRIGGER_REGULAR (1) /* For Regular and ReTxBSR Expiry Triggers */ -#define BSR_TRIGGER_PERIODIC (2) /* For BSR Periodic Timer Expiry Trigger */ -#define BSR_TRIGGER_PADDING (4) /* For Padding BSR Trigger */ - - -/*! \brief Downlink SCH PDU Structure */ -typedef struct { - uint8_t payload[8][SCH_PAYLOAD_SIZE_MAX]; - uint16_t Pdu_size[8]; -} __attribute__ ((__packed__)) DLSCH_PDU; - - -/*! \brief MCH PDU Structure */ -typedef struct { - int8_t payload[SCH_PAYLOAD_SIZE_MAX]; - uint16_t Pdu_size; - uint8_t mcs; - uint8_t sync_area; - uint8_t msi_active; - uint8_t mcch_active; - uint8_t mtch_active; -} __attribute__ ((__packed__)) MCH_PDU; - -/*! \brief Uplink SCH PDU Structure */ -typedef struct { - int8_t payload[SCH_PAYLOAD_SIZE_MAX]; /*!< \brief SACH payload */ - uint16_t Pdu_size; -} __attribute__ ((__packed__)) ULSCH_PDU; - -#include "PHY/impl_defs_top.h" - -/*!\brief UE ULSCH scheduling states*/ -typedef enum { - S_UL_NONE =0, - S_UL_WAITING, - S_UL_SCHEDULED, - S_UL_BUFFERED, - S_UL_NUM_STATUS -} UE_ULSCH_STATUS; - -/*!\brief UE DLSCH scheduling states*/ -typedef enum { - S_DL_NONE =0, - S_DL_WAITING, - S_DL_SCHEDULED, - S_DL_BUFFERED, - S_DL_NUM_STATUS -} UE_DLSCH_STATUS; - -/*!\brief scheduling policy for the contention-based access */ -typedef enum { - CBA_ES=0, /// equal share of RB among groups w - CBA_ES_S, /// equal share of RB among groups with small allocation - CBA_PF, /// proportional fair (kind of) - CBA_PF_S, /// proportional fair (kind of) with small RB allocation - CBA_RS /// random allocation -} CBA_POLICY; - - -/*! \brief temporary struct for ULSCH sched */ -typedef struct { - rnti_t rnti; - uint16_t subframe; - uint16_t serving_num; - UE_ULSCH_STATUS status; -} eNB_ULSCH_INFO; -/*! \brief temp struct for DLSCH sched */ -typedef struct { - rnti_t rnti; - uint16_t weight; - uint16_t subframe; - uint16_t serving_num; - UE_DLSCH_STATUS status; -} eNB_DLSCH_INFO; -/*! \brief eNB overall statistics */ -typedef struct { - /// num BCCH PDU per CC - uint32_t total_num_bcch_pdu; - /// BCCH buffer size - uint32_t bcch_buffer; - /// total BCCH buffer size - uint32_t total_bcch_buffer; - /// BCCH MCS - uint32_t bcch_mcs; - - /// num CCCH PDU per CC - uint32_t total_num_ccch_pdu; - /// BCCH buffer size - uint32_t ccch_buffer; - /// total BCCH buffer size - uint32_t total_ccch_buffer; - /// BCCH MCS - uint32_t ccch_mcs; - - /// num active users - uint16_t num_dlactive_UEs; - /// available number of PRBs for a give SF - uint16_t available_prbs; - /// total number of PRB available for the user plane - uint32_t total_available_prbs; - /// aggregation - /// total avilable nccc : num control channel element - uint16_t available_ncces; - // only for a new transmission, should be extended for retransmission - // current dlsch bit rate for all transport channels - uint32_t dlsch_bitrate; - // - uint32_t dlsch_bytes_tx; - // - uint32_t dlsch_pdus_tx; - // - uint32_t total_dlsch_bitrate; - // - uint32_t total_dlsch_bytes_tx; - // - uint32_t total_dlsch_pdus_tx; - - // here for RX - // - uint32_t ulsch_bitrate; - // - uint32_t ulsch_bytes_rx; - // - uint64_t ulsch_pdus_rx; - - uint32_t total_ulsch_bitrate; - // - uint32_t total_ulsch_bytes_rx; - // - uint32_t total_ulsch_pdus_rx; - - - /// MAC agent-related stats - /// total number of scheduling decisions - int sched_decisions; - /// missed deadlines - int missed_deadlines; - -} eNB_STATS; -/*! \brief eNB statistics for the connected UEs*/ -typedef struct { - - /// CRNTI of UE - rnti_t crnti; ///user id (rnti) of connected UEs - // rrc status - uint8_t rrc_status; - /// harq pid - uint8_t harq_pid; - /// harq rounf - uint8_t harq_round; - /// total available number of PRBs for a new transmission - uint16_t rbs_used; - /// total available number of PRBs for a retransmission - uint16_t rbs_used_retx; - /// total nccc used for a new transmission: num control channel element - uint16_t ncce_used; - /// total avilable nccc for a retransmission: num control channel element - uint16_t ncce_used_retx; - - // mcs1 before the rate adaptaion - uint8_t dlsch_mcs1; - /// Target mcs2 after rate-adaptation - uint8_t dlsch_mcs2; - // current TBS with mcs2 - uint32_t TBS; - // total TBS with mcs2 - // uint32_t total_TBS; - // total rb used for a new transmission - uint32_t total_rbs_used; - // total rb used for retransmission - uint32_t total_rbs_used_retx; - - /// TX - /// Num pkt - uint32_t num_pdu_tx[NB_RB_MAX]; - /// num bytes - uint32_t num_bytes_tx[NB_RB_MAX]; - /// num retransmission / harq - uint32_t num_retransmission; - /// instantaneous tx throughput for each TTI - // uint32_t tti_throughput[NB_RB_MAX]; - - /// overall - // - uint32_t dlsch_bitrate; - //total - uint32_t total_dlsch_bitrate; - /// headers+ CE + padding bytes for a MAC PDU - uint64_t overhead_bytes; - /// headers+ CE + padding bytes for a MAC PDU - uint64_t total_overhead_bytes; - /// headers+ CE + padding bytes for a MAC PDU - uint64_t avg_overhead_bytes; - // MAC multiplexed payload - uint64_t total_sdu_bytes; - // total MAC pdu bytes - uint64_t total_pdu_bytes; - - // total num pdu - uint32_t total_num_pdus; - // - // uint32_t avg_pdu_size; - - /// RX - - /// PUCCH1a/b power (dBm) - int32_t Po_PUCCH_dBm; - /// Indicator that Po_PUCCH has been updated by PHY - int32_t Po_PUCCH_update; - /// Uplink measured RSSI - int32_t UL_rssi; - /// preassigned mcs after rate adaptation - uint8_t ulsch_mcs1; - /// adjusted mcs - uint8_t ulsch_mcs2; - - /// estimated average pdu inter-departure time - uint32_t avg_pdu_idt; - /// estimated average pdu size - uint32_t avg_pdu_ps; - /// - uint32_t aggregated_pdu_size; - uint32_t aggregated_pdu_arrival; - - /// uplink transport block size - uint32_t ulsch_TBS; - - /// total rb used for a new uplink transmission - uint32_t num_retransmission_rx; - /// total rb used for a new uplink transmission - uint32_t rbs_used_rx; - /// total rb used for a new uplink retransmission - uint32_t rbs_used_retx_rx; - /// total rb used for a new uplink transmission - uint32_t total_rbs_used_rx; - /// snr - int32_t snr; - /// target snr - int32_t target_snr; - - /// num rx pdu - uint32_t num_pdu_rx[NB_RB_MAX]; - /// num bytes rx - uint32_t num_bytes_rx[NB_RB_MAX]; - /// instantaneous rx throughput for each TTI - // uint32_t tti_goodput[NB_RB_MAX]; - /// errors - uint32_t num_errors_rx; - - uint64_t overhead_bytes_rx; - /// headers+ CE + padding bytes for a MAC PDU - uint64_t total_overhead_bytes_rx; - /// headers+ CE + padding bytes for a MAC PDU - uint64_t avg_overhead_bytes_rx; - // - uint32_t ulsch_bitrate; - //total - uint32_t total_ulsch_bitrate; - /// overall - /// MAC pdu bytes - uint64_t pdu_bytes_rx; - /// total MAC pdu bytes - uint64_t total_pdu_bytes_rx; - /// total num pdu - uint32_t total_num_pdus_rx; - /// num of error pdus - uint32_t total_num_errors_rx; - -} eNB_UE_STATS; -/*! \brief eNB template for UE context information */ -typedef struct { - /// C-RNTI of UE - rnti_t rnti; - /// NDI from last scheduling - uint8_t oldNDI[8]; - /// mcs1 from last scheduling - uint8_t oldmcs1[8]; - /// mcs2 from last scheduling - uint8_t oldmcs2[8]; - /// NDI from last UL scheduling - uint8_t oldNDI_UL[8]; - /// mcs from last UL scheduling - uint8_t mcs_UL[8]; - /// TBS from last UL scheduling - uint8_t TBS_UL[8]; - /// CQI_req from last scheduling - uint8_t oldCQI_UL[8]; - /// TPC from last scheduling - uint8_t oldTPC_UL[8]; - /// Flag to indicate UL has been scheduled at least once - boolean_t ul_active; - /// Flag to indicate UE has been configured (ACK from RRCConnectionSetup received) - boolean_t configured; - - /// MCS from last scheduling - uint8_t mcs[8]; - - /// TPC from last scheduling - uint8_t oldTPC[8]; - - // PHY interface info - - /// Number of Allocated RBs for DL after scheduling (prior to frequency allocation) - uint16_t nb_rb[8]; // num_max_harq - - /// Number of Allocated RBs for UL after scheduling - uint16_t nb_rb_ul[8]; // num_max_harq - - /// Number of Allocated RBs for UL after scheduling - uint16_t first_rb_ul[8]; // num_max_harq - - /// Is CQI requested for UL after scheduling 1st transmission - uint8_t cqi_req[8]; // num_max_harq - - /// Cyclic shift for DMRS after scheduling - uint16_t cshift[8]; // num_max_harq - - /// Number of Allocated RBs by the ulsch preprocessor - uint8_t pre_allocated_nb_rb_ul; - - /// index of Allocated RBs by the ulsch preprocessor - int8_t pre_allocated_rb_table_index_ul; - - /// total allocated RBs - int8_t total_allocated_rbs; - - /// pre-assigned MCS by the ulsch preprocessor - uint8_t pre_assigned_mcs_ul; - - /// assigned MCS by the ulsch scheduler - uint8_t assigned_mcs_ul; - - /// DL DAI - uint8_t DAI; - - /// UL DAI - uint8_t DAI_ul[10]; - - /// UL Scheduling Request Received - uint8_t ul_SR; - - ///Resource Block indication for each sub-band in MU-MIMO - uint8_t rballoc_subband[8][50]; - - // Logical channel info for link with RLC - - /// Last received UE BSR info for each logical channel group id - uint8_t bsr_info[MAX_NUM_LCGID]; - - /// LCGID mapping - long lcgidmap[11]; - - /// phr information - int8_t phr_info; - - /// phr information - int8_t phr_info_configured; - - ///dl buffer info - uint32_t dl_buffer_info[MAX_NUM_LCID]; - /// total downlink buffer info - uint32_t dl_buffer_total; - /// total downlink pdus - uint32_t dl_pdus_total; - /// downlink pdus for each LCID - uint32_t dl_pdus_in_buffer[MAX_NUM_LCID]; - /// creation time of the downlink buffer head for each LCID - uint32_t dl_buffer_head_sdu_creation_time[MAX_NUM_LCID]; - /// maximum creation time of the downlink buffer head across all LCID - uint32_t dl_buffer_head_sdu_creation_time_max; - /// a flag indicating that the downlink head SDU is segmented - uint8_t dl_buffer_head_sdu_is_segmented[MAX_NUM_LCID]; - /// size of remaining size to send for the downlink head SDU - uint32_t dl_buffer_head_sdu_remaining_size_to_send[MAX_NUM_LCID]; - - /// total uplink buffer size - uint32_t ul_total_buffer; - /// uplink buffer creation time for each LCID - uint32_t ul_buffer_creation_time[MAX_NUM_LCGID]; - /// maximum uplink buffer creation time across all the LCIDs - uint32_t ul_buffer_creation_time_max; - /// uplink buffer size per LCID - uint32_t ul_buffer_info[MAX_NUM_LCGID]; - - /// UE tx power - int32_t ue_tx_power; - - /// stores the frame where the last TPC was transmitted - uint32_t pusch_tpc_tx_frame; - uint32_t pusch_tpc_tx_subframe; - uint32_t pucch_tpc_tx_frame; - uint32_t pucch_tpc_tx_subframe; - -#ifdef LOCALIZATION - eNB_UE_estimated_distances distance; -#endif - - - uint8_t rach_resource_type; - - uint16_t mpdcch_repetition_cnt; - struct PhysicalConfigDedicated *physicalConfigDedicated; - frame_t Msg2_frame; - sub_frame_t Msg2_subframe; - -} UE_TEMPLATE; - -/*! \brief scheduling control information set through an API (not used)*/ -typedef struct { - ///UL transmission bandwidth in RBs - uint8_t ul_bandwidth[MAX_NUM_LCID]; - ///DL transmission bandwidth in RBs - uint8_t dl_bandwidth[MAX_NUM_LCID]; - - //To do GBR bearer - uint8_t min_ul_bandwidth[MAX_NUM_LCID]; - - uint8_t min_dl_bandwidth[MAX_NUM_LCID]; - - ///aggregated bit rate of non-gbr bearer per UE - uint64_t ue_AggregatedMaximumBitrateDL; - ///aggregated bit rate of non-gbr bearer per UE - uint64_t ue_AggregatedMaximumBitrateUL; - ///CQI scheduling interval in subframes. - uint16_t cqiSchedInterval; - ///Contention resolution timer used during random access - uint8_t mac_ContentionResolutionTimer; - - uint16_t max_allowed_rbs[MAX_NUM_LCID]; - - uint8_t max_mcs[MAX_NUM_LCID]; - - uint16_t priority[MAX_NUM_LCID]; - - // resource scheduling information - - /// Current DL harq round per harq_pid on each CC - uint8_t round[MAX_NUM_CCs][10]; - /// Current Active TBs per harq_pid on each CC - uint8_t tbcnt[MAX_NUM_CCs][10]; - /// Current UL harq round per harq_pid on each CC - uint8_t round_UL[MAX_NUM_CCs][8]; - uint8_t dl_pow_off[MAX_NUM_CCs]; - uint16_t pre_nb_available_rbs[MAX_NUM_CCs]; - unsigned char rballoc_sub_UE[MAX_NUM_CCs][N_RBG_MAX]; - uint16_t ta_timer; - int16_t ta_update; - uint16_t ul_consecutive_errors; - int32_t context_active_timer; - int32_t cqi_req_timer; - int32_t ul_inactivity_timer; - int32_t ul_failure_timer; - int32_t ul_scheduled; - int32_t ra_pdcch_order_sent; - int32_t ul_out_of_sync; - int32_t phr_received; - uint8_t periodic_ri_received[NFAPI_CC_MAX]; - uint8_t aperiodic_ri_received[NFAPI_CC_MAX]; - uint32_t pucch_tpc_accumulated[NFAPI_CC_MAX]; - uint8_t pucch1_cqi_update[NFAPI_CC_MAX]; - uint8_t pucch1_snr[NFAPI_CC_MAX]; - uint8_t pucch2_cqi_update[NFAPI_CC_MAX]; - uint8_t pucch2_snr[NFAPI_CC_MAX]; - uint8_t pucch3_cqi_update[NFAPI_CC_MAX]; - uint8_t pucch3_snr[NFAPI_CC_MAX]; - uint8_t pusch_snr[NFAPI_CC_MAX]; - uint16_t feedback_cnt[NFAPI_CC_MAX]; - uint16_t timing_advance; - uint16_t timing_advance_r9; - uint8_t periodic_wideband_cqi[NFAPI_CC_MAX]; - uint8_t periodic_wideband_spatial_diffcqi[NFAPI_CC_MAX]; - uint8_t periodic_wideband_pmi[NFAPI_CC_MAX]; - uint8_t periodic_subband_cqi[NFAPI_CC_MAX][16]; - uint8_t periodic_subband_spatial_diffcqi[NFAPI_CC_MAX][16]; - uint8_t aperiodic_subband_cqi0[NFAPI_CC_MAX][25]; - uint8_t aperiodic_subband_pmi[NFAPI_CC_MAX][25]; - uint8_t aperiodic_subband_diffcqi0[NFAPI_CC_MAX][25]; - uint8_t aperiodic_subband_cqi1[NFAPI_CC_MAX][25]; - uint8_t aperiodic_subband_diffcqi1[NFAPI_CC_MAX][25]; - uint8_t aperiodic_wideband_cqi0[NFAPI_CC_MAX]; - uint8_t aperiodic_wideband_pmi[NFAPI_CC_MAX]; - uint8_t aperiodic_wideband_cqi1[NFAPI_CC_MAX]; - uint8_t aperiodic_wideband_pmi1[NFAPI_CC_MAX]; - uint8_t dl_cqi[NFAPI_CC_MAX]; -} UE_sched_ctrl; -/*! \brief eNB template for the Random access information */ -typedef struct { - /// Flag to indicate this process is active - boolean_t RA_active; - /// Size of DCI for RA-Response (bytes) - uint8_t RA_dci_size_bytes1; - /// Size of DCI for RA-Response (bits) - uint8_t RA_dci_size_bits1; - /// Actual DCI to transmit for RA-Response - uint8_t RA_alloc_pdu1[(MAX_DCI_SIZE_BITS>>3)+1]; - /// DCI format for RA-Response (should be 1A) - uint8_t RA_dci_fmt1; - /// Size of DCI for Msg4/ContRes (bytes) - uint8_t RA_dci_size_bytes2; - /// Size of DCI for Msg4/ContRes (bits) - uint8_t RA_dci_size_bits2; - /// Actual DCI to transmit for Msg4/ContRes - uint8_t RA_alloc_pdu2[(MAX_DCI_SIZE_BITS>>3)+1]; - /// DCI format for Msg4/ContRes (should be 1A) - uint8_t RA_dci_fmt2; - /// Flag to indicate the eNB should generate RAR. This is triggered by detection of PRACH - uint8_t generate_rar; - /// Subframe where preamble was received - uint8_t preamble_subframe; - /// Subframe where Msg2 is to be sent - uint8_t Msg2_subframe; - /// Frame where Msg2 is to be sent - frame_t Msg2_frame; - /// Subframe where Msg3 is to be sent - sub_frame_t Msg3_subframe; - /// Frame where Msg3 is to be sent - frame_t Msg3_frame; - /// Subframe where Msg4 is to be sent - sub_frame_t Msg4_subframe; - /// Frame where Msg4 is to be sent - frame_t Msg4_frame; - /// Flag to indicate the eNB should generate Msg4 upon reception of SDU from RRC. This is triggered by first ULSCH reception at eNB for new user. - uint8_t generate_Msg4; - /// Flag to indicate that eNB is waiting for ACK that UE has received Msg3. - uint8_t wait_ack_Msg4; - /// harq_pid used for Msg4 transmission - uint8_t harq_pid; - /// UE RNTI allocated during RAR - rnti_t rnti; - /// RA RNTI allocated from received PRACH - uint16_t RA_rnti; - /// Received preamble_index - uint8_t preamble_index; - /// Received UE Contention Resolution Identifier - uint8_t cont_res_id[6]; - /// Timing offset indicated by PHY - int16_t timing_offset; - /// Timeout for RRC connection - int16_t RRC_timer; - /// Msg3 first RB - uint8_t msg3_first_rb; - /// Msg3 number of RB - uint8_t msg3_nb_rb; - /// Msg3 MCS - uint8_t msg3_mcs; - /// Msg3 TPC command - uint8_t msg3_TPC; - /// Msg3 ULdelay command - uint8_t msg3_ULdelay; - /// Msg3 cqireq command - uint8_t msg3_cqireq; - /// Round of Msg3 HARQ - uint8_t msg3_round; - /// TBS used for Msg4 - int msg4_TBsize; - /// MCS used for Msg4 - int msg4_mcs; - /// size off piggybacked RRC SDU - uint8_t msg4_rrc_sdu_length; - uint32_t msg4_delay; - uint8_t rach_resource_type; - uint8_t msg2_mpdcch_repetition_cnt; - uint8_t msg2_mpdcch_done; - uint8_t msg4_mpdcch_repetition_cnt; - uint8_t msg4_mpdcch_done; - uint8_t msg2_narrowband; - uint32_t msg34_narrowband; -} RA_TEMPLATE; - - -/*! \brief subband bitmap confguration (for ALU icic algo purpose), in test phase */ -typedef struct { - uint8_t sbmap[NUMBER_OF_SUBBANDS_MAX]; //13 = number of SB MAX for 100 PRB - uint8_t periodicity; - uint8_t first_subframe; - uint8_t sb_size; - uint8_t nb_active_sb; -} SBMAP_CONF; -/*! \brief UE list used by eNB to order UEs/CC for scheduling*/ -typedef struct { - /// Dedicated information for UEs - struct PhysicalConfigDedicated *physicalConfigDedicated[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; - /// DLSCH pdu - DLSCH_PDU DLSCH_pdu[MAX_NUM_CCs][2][NUMBER_OF_UE_MAX]; - /// DCI template and MAC connection parameters for UEs - UE_TEMPLATE UE_template[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; - /// DCI template and MAC connection for RA processes - int pCC_id[NUMBER_OF_UE_MAX]; - /// sorted downlink component carrier for the scheduler - int ordered_CCids[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; - /// number of downlink active component carrier - int numactiveCCs[NUMBER_OF_UE_MAX]; - /// sorted uplink component carrier for the scheduler - int ordered_ULCCids[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; - /// number of uplink active component carrier - int numactiveULCCs[NUMBER_OF_UE_MAX]; - /// number of downlink active component carrier - uint8_t dl_CC_bitmap[NUMBER_OF_UE_MAX]; - /// eNB to UE statistics - eNB_UE_STATS eNB_UE_stats[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; - /// scheduling control info - UE_sched_ctrl UE_sched_ctrl[NUMBER_OF_UE_MAX]; - int next[NUMBER_OF_UE_MAX]; - int head; - int next_ul[NUMBER_OF_UE_MAX]; - int head_ul; - int avail; - int num_UEs; - boolean_t active[NUMBER_OF_UE_MAX]; -} UE_list_t; - -/*! \brief eNB common channels */ -typedef struct { - int physCellId; - int p_eNB; - int Ncp; - int eutra_band; - uint32_t dl_CarrierFreq; - BCCH_BCH_Message_t *mib; - RadioResourceConfigCommonSIB_t *radioResourceConfigCommon; - RadioResourceConfigCommonSIB_t *radioResourceConfigCommon_BR; - TDD_Config_t *tdd_Config; - SchedulingInfoList_t *schedulingInfoList; - ARFCN_ValueEUTRA_t ul_CarrierFreq; - long ul_Bandwidth; - /// Outgoing MIB PDU for PHY - MIB_PDU MIB_pdu; - /// Outgoing BCCH pdu for PHY - BCCH_PDU BCCH_pdu; - /// Outgoing BCCH DCI allocation - uint32_t BCCH_alloc_pdu; - /// Outgoing CCCH pdu for PHY - CCCH_PDU CCCH_pdu; - /// Outgoing RAR pdu for PHY - RAR_PDU RAR_pdu; - /// Template for RA computations - RA_TEMPLATE RA_template[NB_RA_PROC_MAX]; - /// VRB map for common channels - uint8_t vrb_map[100]; - /// VRB map for common channels and retransmissions by PHICH - uint8_t vrb_map_UL[100]; - /// MBSFN SubframeConfig - struct MBSFN_SubframeConfig *mbsfn_SubframeConfig[8]; - /// number of subframe allocation pattern available for MBSFN sync area - uint8_t num_sf_allocation_pattern; - /// MBMS Flag - uint8_t MBMS_flag; - /// Outgoing MCCH pdu for PHY - MCCH_PDU MCCH_pdu; - /// MCCH active flag - uint8_t msi_active; - /// MCCH active flag - uint8_t mcch_active; - /// MTCH active flag - uint8_t mtch_active; - /// number of active MBSFN area - uint8_t num_active_mbsfn_area; - /// MBSFN Area Info - struct MBSFN_AreaInfo_r9 *mbsfn_AreaInfo[MAX_MBSFN_AREA]; - /// PMCH Config - struct PMCH_Config_r9 *pmch_Config[MAX_PMCH_perMBSFN]; - /// MBMS session info list - struct MBMS_SessionInfoList_r9 *mbms_SessionList[MAX_PMCH_perMBSFN]; - /// Outgoing MCH pdu for PHY - MCH_PDU MCH_pdu; - /// Rel13 parameters from SIB1 - SystemInformationBlockType1_v1310_IEs_t *sib1_v13ext; - /// Counter for SIB1-BR scheduling - int SIB1_BR_cnt; - /// Outgoing BCCH-BR pdu for PHY - BCCH_PDU BCCH_BR_pdu[20]; -} COMMON_channels_t; -/*! \brief top level eNB MAC structure */ -typedef struct eNB_MAC_INST_s { - /// Ethernet parameters for northbound midhaul interface - eth_params_t eth_params_n; - /// Ethernet parameters for fronthaul interface - eth_params_t eth_params_s; - /// - module_id_t Mod_id; - /// frame counter - frame_t frame; - /// subframe counter - sub_frame_t subframe; - /// Pointer to IF module instance for PHY - IF_Module_t *if_inst; - /// Common cell resources - COMMON_channels_t common_channels[MAX_NUM_CCs]; - /// current PDU index (BCH,MCH,DLSCH) - uint16_t pdu_index[MAX_NUM_CCs]; - - /// NFAPI Config Request Structure - nfapi_config_request_t config[MAX_NUM_CCs]; - /// Preallocated DL pdu list - nfapi_dl_config_request_pdu_t dl_config_pdu_list[MAX_NUM_CCs][MAX_NUM_DL_PDU]; - /// NFAPI DL Config Request Structure - nfapi_dl_config_request_t DL_req[MAX_NUM_CCs]; - /// Preallocated UL pdu list - nfapi_ul_config_request_pdu_t ul_config_pdu_list[MAX_NUM_CCs][MAX_NUM_UL_PDU]; - /// Preallocated UL pdu list for ULSCH (n+k delay) - nfapi_ul_config_request_pdu_t ul_config_pdu_list_tmp[MAX_NUM_CCs][10][MAX_NUM_UL_PDU]; - /// NFAPI UL Config Request Structure, send to L1 4 subframes before processing takes place - nfapi_ul_config_request_t UL_req[MAX_NUM_CCs]; - /// NFAPI "Temporary" UL Config Request Structure, holds future UL_config requests - nfapi_ul_config_request_t UL_req_tmp[MAX_NUM_CCs][10]; - /// Preallocated HI_DCI0 pdu list - nfapi_hi_dci0_request_pdu_t hi_dci0_pdu_list[MAX_NUM_CCs][MAX_NUM_HI_DCI0_PDU]; - /// NFAPI HI/DCI0 Config Request Structure - nfapi_hi_dci0_request_t HI_DCI0_req[MAX_NUM_CCs]; - /// Prealocated TX pdu list - nfapi_tx_request_pdu_t tx_request_pdu[MAX_NUM_CCs][MAX_NUM_TX_REQUEST_PDU]; - /// NFAPI DL PDU structure - nfapi_tx_request_t TX_req[MAX_NUM_CCs]; - /// UL handle - uint32_t ul_handle; - UE_list_t UE_list; - - ///subband bitmap configuration - SBMAP_CONF sbmap_conf; - /// CCE table used to build DCI scheduling information - int CCE_table[MAX_NUM_CCs][800]; - /// active flag for Other lcid - uint8_t lcid_active[NB_RB_MAX]; - /// eNB stats - eNB_STATS eNB_stats[MAX_NUM_CCs]; - // MAC function execution peformance profiler - /// processing time of eNB scheduler - time_stats_t eNB_scheduler; - /// processing time of eNB scheduler for SI - time_stats_t schedule_si; - /// processing time of eNB scheduler for Random access - time_stats_t schedule_ra; - /// processing time of eNB ULSCH scheduler - time_stats_t schedule_ulsch; - /// processing time of eNB DCI generation - time_stats_t fill_DLSCH_dci; - /// processing time of eNB MAC preprocessor - time_stats_t schedule_dlsch_preprocessor; - /// processing time of eNB DLSCH scheduler - time_stats_t schedule_dlsch; // include rlc_data_req + MAC header + preprocessor - /// processing time of eNB MCH scheduler - time_stats_t schedule_mch; - /// processing time of eNB ULSCH reception - time_stats_t rx_ulsch_sdu; // include rlc_data_ind -} eNB_MAC_INST; - -/* - * UE part - */ - -typedef enum { - TYPE0, - TYPE1, - TYPE1A, - TYPE2, - TYPE2A, - TYPEUESPEC -} MPDCCH_TYPES_t; - -/*!\brief UE layer 2 status */ -typedef enum { - CONNECTION_OK=0, - CONNECTION_LOST, - PHY_RESYNCH, - PHY_HO_PRACH -} UE_L2_STATE_t; - -/*!\brief UE scheduling info */ -typedef struct { - /// buffer status for each lcgid - uint8_t BSR[MAX_NUM_LCGID]; // should be more for mesh topology - /// keep the number of bytes in rlc buffer for each lcgid - int32_t BSR_bytes[MAX_NUM_LCGID]; - /// after multiplexing buffer remain for each lcid - int32_t LCID_buffer_remain[MAX_NUM_LCID]; - /// sum of all lcid buffer size - uint16_t All_lcid_buffer_size_lastTTI; - /// buffer status for each lcid - uint8_t LCID_status[MAX_NUM_LCID]; - /// SR pending as defined in 36.321 - uint8_t SR_pending; - /// SR_COUNTER as defined in 36.321 - uint16_t SR_COUNTER; - /// logical channel group ide for each LCID - uint8_t LCGID[MAX_NUM_LCID]; - /// retxBSR-Timer, default value is sf2560 - uint16_t retxBSR_Timer; - /// retxBSR_SF, number of subframe before triggering a regular BSR - uint16_t retxBSR_SF; - /// periodicBSR-Timer, default to infinity - uint16_t periodicBSR_Timer; - /// periodicBSR_SF, number of subframe before triggering a periodic BSR - uint16_t periodicBSR_SF; - /// default value is 0: not configured - uint16_t sr_ProhibitTimer; - /// sr ProhibitTime running - uint8_t sr_ProhibitTimer_Running; - /// default value to n5 - uint16_t maxHARQ_Tx; - /// default value is false - uint16_t ttiBundling; - /// default value is release - struct DRX_Config *drx_config; - /// default value is release - struct MAC_MainConfig__phr_Config *phr_config; - ///timer before triggering a periodic PHR - uint16_t periodicPHR_Timer; - ///timer before triggering a prohibit PHR - uint16_t prohibitPHR_Timer; - ///DL Pathloss change value - uint16_t PathlossChange; - ///number of subframe before triggering a periodic PHR - int16_t periodicPHR_SF; - ///number of subframe before triggering a prohibit PHR - int16_t prohibitPHR_SF; - ///DL Pathloss Change in db - uint16_t PathlossChange_db; - - /// default value is false - uint16_t extendedBSR_Sizes_r10; - /// default value is false - uint16_t extendedPHR_r10; - - //Bj bucket usage per lcid - int16_t Bj[MAX_NUM_LCID]; - // Bucket size per lcid - int16_t bucket_size[MAX_NUM_LCID]; -} UE_SCHEDULING_INFO; -/*!\brief Top level UE MAC structure */ -typedef struct { - uint16_t Node_id; - /// RX frame counter - frame_t rxFrame; - /// RX subframe counter - sub_frame_t rxSubframe; - /// TX frame counter - frame_t txFrame; - /// TX subframe counter - sub_frame_t txSubframe; - /// C-RNTI of UE - uint16_t crnti; - /// C-RNTI of UE before HO - rnti_t crnti_before_ho; ///user id (rnti) of connected UEs - /// uplink active flag - uint8_t ul_active; - /// pointer to RRC PHY configuration - RadioResourceConfigCommonSIB_t *radioResourceConfigCommon; - /// pointer to RACH_ConfigDedicated (NULL when not active, i.e. upon HO completion or T304 expiry) - struct RACH_ConfigDedicated *rach_ConfigDedicated; - /// pointer to RRC PHY configuration - struct PhysicalConfigDedicated *physicalConfigDedicated; - /// pointer to RRC PHY configuration SCEll - struct PhysicalConfigDedicatedSCell_r10 *physicalConfigDedicatedSCell_r10; - /// pointer to TDD Configuration (NULL for FDD) - TDD_Config_t *tdd_Config; - /// Number of adjacent cells to measure - uint8_t n_adj_cells; - /// Array of adjacent physical cell ids - uint32_t adj_cell_id[6]; - /// Pointer to RRC MAC configuration - MAC_MainConfig_t *macConfig; - /// Pointer to RRC Measurement gap configuration - MeasGapConfig_t *measGapConfig; - /// Pointers to LogicalChannelConfig indexed by LogicalChannelIdentity. Note NULL means LCHAN is inactive. - LogicalChannelConfig_t *logicalChannelConfig[MAX_NUM_LCID]; - /// Scheduling Information - UE_SCHEDULING_INFO scheduling_info; - /// Outgoing CCCH pdu for PHY - CCCH_PDU CCCH_pdu; - /// Outgoing RAR pdu for PHY - RAR_PDU RAR_pdu; - /// Incoming DLSCH pdu for PHY - DLSCH_PDU DLSCH_pdu[NUMBER_OF_UE_MAX][2]; - /// number of attempt for rach - uint8_t RA_attempt_number; - /// Random-access procedure flag - uint8_t RA_active; - /// Random-access window counter - int8_t RA_window_cnt; - /// Random-access Msg3 size in bytes - uint8_t RA_Msg3_size; - /// Random-access prachMaskIndex - uint8_t RA_prachMaskIndex; - /// Flag indicating Preamble set (A,B) used for first Msg3 transmission - uint8_t RA_usedGroupA; - /// Random-access Resources - PRACH_RESOURCES_t RA_prach_resources; - /// Random-access PREAMBLE_TRANSMISSION_COUNTER - uint8_t RA_PREAMBLE_TRANSMISSION_COUNTER; - /// Random-access backoff counter - int16_t RA_backoff_cnt; - /// Random-access variable for window calculation (frame of last change in window counter) - uint32_t RA_tx_frame; - /// Random-access variable for window calculation (subframe of last change in window counter) - uint8_t RA_tx_subframe; - /// Random-access Group B maximum path-loss - /// Random-access variable for backoff (frame of last change in backoff counter) - uint32_t RA_backoff_frame; - /// Random-access variable for backoff (subframe of last change in backoff counter) - uint8_t RA_backoff_subframe; - /// Random-access Group B maximum path-loss - uint16_t RA_maxPL; - /// Random-access Contention Resolution Timer active flag - uint8_t RA_contention_resolution_timer_active; - /// Random-access Contention Resolution Timer count value - uint8_t RA_contention_resolution_cnt; - /// power headroom reporitng reconfigured - uint8_t PHR_reconfigured; - /// power headroom state as configured by the higher layers - uint8_t PHR_state; - /// power backoff due to power management (as allowed by P-MPRc) for this cell - uint8_t PHR_reporting_active; - /// power backoff due to power management (as allowed by P-MPRc) for this cell - uint8_t power_backoff_db[NUMBER_OF_eNB_MAX]; - /// BSR report falg management - uint8_t BSR_reporting_active; - /// retxBSR-Timer expires flag - uint8_t retxBSRTimer_expires_flag; - /// periodBSR-Timer expires flag - uint8_t periodBSRTimer_expires_flag; - - /// MBSFN_Subframe Configuration - struct MBSFN_SubframeConfig *mbsfn_SubframeConfig[8]; // FIXME replace 8 by MAX_MBSFN_AREA? - /// number of subframe allocation pattern available for MBSFN sync area - uint8_t num_sf_allocation_pattern; - /// number of active MBSFN area - uint8_t num_active_mbsfn_area; - /// MBSFN Area Info - struct MBSFN_AreaInfo_r9 *mbsfn_AreaInfo[MAX_MBSFN_AREA]; - /// PMCH Config - struct PMCH_Config_r9 *pmch_Config[MAX_PMCH_perMBSFN]; - /// MCCH status - uint8_t mcch_status; - /// MSI status - uint8_t msi_status;// could be an array if there are >1 MCH in one MBSFN area - /// CBA RNTI for each group - uint16_t cba_rnti[NUM_MAX_CBA_GROUP]; - /// last SFN for CBA channel access - uint8_t cba_last_access[NUM_MAX_CBA_GROUP]; - /// total UE scheduler processing time - time_stats_t ue_scheduler; // total - /// UE ULSCH tx processing time inlcuding RLC interface (rlc_data_req) and mac header generation - time_stats_t tx_ulsch_sdu; - /// UE DLSCH rx processing time inlcuding RLC interface (mac_rrc_data_ind or mac_rlc_status_ind+mac_rlc_data_ind) and mac header parser - time_stats_t rx_dlsch_sdu ; - /// UE query for MCH subframe processing time - time_stats_t ue_query_mch; - /// UE MCH rx processing time - time_stats_t rx_mch_sdu; - /// UE BCCH rx processing time including RLC interface (mac_rrc_data_ind) - time_stats_t rx_si; - /// UE PCCH rx processing time including RLC interface (mac_rrc_data_ind) - time_stats_t rx_p; -} UE_MAC_INST; -/*! \brief ID of the neighboring cells used for HO*/ -typedef struct { - uint16_t cell_ids[6]; - uint8_t n_adj_cells; -} neigh_cell_id_t; - -#include "proto.h" -/*@}*/ -#endif /*__LAYER2_MAC_DEFS_H__ */ From ffc4f464f57e43349f77cb4c20aa6433a8bf97f7 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 21 Jan 2020 18:40:14 +0100 Subject: [PATCH 101/240] Remove useless mac_proto.h include When a header is changed, all including files need to be recompiled, too. Thus, including a header needlessly all over the place drives compile times up without any reason. --- executables/nr-gnb.c | 2 -- executables/nr-ru.c | 2 -- executables/nr-softmodem.c | 2 -- executables/nr-uesoftmodem.c | 1 - nfapi/oai_integration/nfapi_pnf.c | 1 - openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_ue.c | 1 - openair1/PHY/LTE_UE_TRANSPORT/initial_sync.c | 1 - openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c | 1 - openair2/F1AP/f1ap_cu_ue_context_management.c | 1 - openair2/LAYER2/MAC/eNB_scheduler.c | 1 - 10 files changed, 13 deletions(-) diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index e03700e4f5..8f4f8e45eb 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -62,9 +62,7 @@ #include "PHY/phy_extern.h" -#include "LAYER2/MAC/mac.h" #include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h" -#include "LAYER2/MAC/mac_proto.h" #include "RRC/LTE/rrc_extern.h" #include "PHY_INTERFACE/phy_interface.h" #include "common/utils/LOG/log_extern.h" diff --git a/executables/nr-ru.c b/executables/nr-ru.c index fe10988462..1dc66e99a9 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -72,9 +72,7 @@ #include "SCHED/sched_eNB.h" #include "SCHED_NR/sched_nr.h" -#include "LAYER2/MAC/mac.h" #include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h" -#include "LAYER2/MAC/mac_proto.h" #include "RRC/LTE/rrc_extern.h" #include "PHY_INTERFACE/phy_interface.h" diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 04c515e556..1146d281b0 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -49,8 +49,6 @@ #include "PHY/phy_vars.h" #include "SCHED/sched_common_vars.h" #include "LAYER2/MAC/mac_vars.h" -#include "LAYER2/MAC/mac.h" -#include "LAYER2/MAC/mac_proto.h" #include "RRC/LTE/rrc_vars.h" #include "PHY_INTERFACE/phy_interface_vars.h" #include "gnb_config.h" diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 53e407923f..a8140f0b11 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -47,7 +47,6 @@ #include "PHY/NR_REFSIG/nr_mod_table.h" #include "LAYER2/MAC/mac_vars.h" -#include "LAYER2/MAC/mac_proto.h" #include "RRC/LTE/rrc_vars.h" #include "PHY_INTERFACE/phy_interface_vars.h" #include "openair1/SIMULATION/TOOLS/sim.h" diff --git a/nfapi/oai_integration/nfapi_pnf.c b/nfapi/oai_integration/nfapi_pnf.c index f07fb1ad23..481c410561 100644 --- a/nfapi/oai_integration/nfapi_pnf.c +++ b/nfapi/oai_integration/nfapi_pnf.c @@ -49,7 +49,6 @@ extern RAN_CONTEXT_t RC; #include "fapi_stub.h" //#include "fapi_l1.h" #include "common/utils/LOG/log.h" -#include "openair2/LAYER2/MAC/mac_proto.h" #include "PHY/INIT/phy_init.h" #include "PHY/LTE_TRANSPORT/transport_proto.h" diff --git a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_ue.c b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_ue.c index 7414c3a69d..23f261149a 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_ue.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_ue.c @@ -23,7 +23,6 @@ #include "PHY/defs_UE.h" #include "PHY/LTE_ESTIMATION/lte_estimation.h" #include "PHY/impl_defs_top.h" -#include "openair2/LAYER2/MAC/mac_proto.h" #include "common/utils/LOG/vcd_signal_dumper.h" diff --git a/openair1/PHY/LTE_UE_TRANSPORT/initial_sync.c b/openair1/PHY/LTE_UE_TRANSPORT/initial_sync.c index afa46de820..ba904629a1 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/initial_sync.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/initial_sync.c @@ -38,7 +38,6 @@ #include "PHY/MODULATION/modulation_UE.h" #include "PHY/LTE_ESTIMATION/lte_estimation.h" #include "PHY/LTE_REFSIG/lte_refsig.h" -#include "openair2/LAYER2/MAC/mac_proto.h" #include "common_lib.h" #include "PHY/INIT/phy_init.h" diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c index cc22e5f7d7..7f5872e885 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c @@ -23,7 +23,6 @@ #include "PHY/defs_nr_UE.h" #include "PHY/NR_UE_ESTIMATION/nr_estimation.h" #include "PHY/impl_defs_top.h" -//#include "openair2/LAYER2/MAC/mac_proto.h" #include "common/utils/LOG/vcd_signal_dumper.h" diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index edc5a2c0a9..a64f2d529b 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -37,7 +37,6 @@ #include "f1ap_cu_ue_context_management.h" #include -#include "openair2/LAYER2/MAC/mac_proto.h" #include "rrc_extern.h" #include "rrc_eNB_UE_context.h" #include "rrc_eNB_S1AP.h" diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c index eef1f9c976..2b3705dc67 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler.c +++ b/openair2/LAYER2/MAC/eNB_scheduler.c @@ -35,7 +35,6 @@ #include "LAYER2/MAC/mac_extern.h" #include "LAYER2/MAC/mac_proto.h" -#include "LAYER2/NR_MAC_gNB/mac_proto.h" #include "common/utils/LOG/log.h" #include "nfapi/oai_integration/vendor_ext.h" #include "common/utils/LOG/vcd_signal_dumper.h" From 81fb7628c502c01c2bea7ce7fe2f7737b579a650 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 16 Jan 2020 17:37:55 +0100 Subject: [PATCH 102/240] get_min_rb_unit(): all channel bandwidths --- openair2/LAYER2/MAC/eNB_scheduler_primitives.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index e76e6b24ba..390d6bf665 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -2776,19 +2776,21 @@ get_min_rb_unit(module_id_t module_id, int N_RB_DL = to_prb(RC.mac[module_id]->common_channels[CC_id].mib->message.dl_Bandwidth); switch (N_RB_DL) { - case 6: // 1.4 MHz + case 6: // 1.4MHz min_rb_unit = 1; break; - case 25: // 5HMz + case 15: // 3MHz + case 25: // 5MHz min_rb_unit = 2; break; - case 50: // 10HMz + case 50: // 10MHz min_rb_unit = 3; break; - case 100: // 20HMz + case 75: // 15MHz + case 100: // 20MHz min_rb_unit = 4; break; From 99301f438f83a931f908a66132d19c72d75ae5af Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 16 Jan 2020 14:20:39 +0100 Subject: [PATCH 103/240] Call schedule_ue_spec() once for each CC --- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 1988 ++++++++++----------- openair2/LAYER2/MAC/mac_proto.h | 7 +- 2 files changed, 992 insertions(+), 1003 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index eba4bdcee9..d7efbeeeea 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -420,17 +420,8 @@ set_ul_DAI(int module_idP, //------------------------------------------------------------------------------ void schedule_dlsch(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP, int *mbsfn_flag) { - int i = 0; - slice_info_t *sli = &RC.mac[module_idP]->slice_info; - memset(sli->rballoc_sub, 0, sizeof(sli->rballoc_sub)); - - for (i = 0; i < sli->n_dl; i++) { - // Run each enabled slice-specific schedulers one by one - sli->dl[i].sched_cb(module_idP, - i, - frameP, - subframeP, - mbsfn_flag/*, dl_info*/); + for (int CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; CC_id++) { + schedule_ue_spec(module_idP, CC_id, frameP, subframeP, mbsfn_flag); } } @@ -454,13 +445,12 @@ void getRepetition(UE_TEMPLATE *pue_template,unsigned int *maxRep, unsigned int */ void schedule_ue_spec(module_id_t module_idP, - int slice_idxP, + int CC_id, frame_t frameP, sub_frame_t subframeP, int *mbsfn_flag) //------------------------------------------------------------------------------ { - int CC_id; int UE_id; int aggregation; mac_rlc_status_resp_t rlc_status; @@ -478,7 +468,6 @@ schedule_ue_spec(module_id_t module_idP, uint8_t ra_ii; eNB_UE_STATS *eNB_UE_stats = NULL; UE_TEMPLATE *ue_template = NULL; - eNB_STATS *eNB_stats = NULL; RRC_release_ctrl_t *release_ctrl = NULL; DLSCH_PDU *dlsch_pdu = NULL; RA_t *ra = NULL; @@ -491,11 +480,11 @@ schedule_ue_spec(module_id_t module_idP, int tpc = 1; UE_sched_ctrl_t *ue_sched_ctrl; int mcs; - int i; - int min_rb_unit[NFAPI_CC_MAX]; - int N_RB_DL[NFAPI_CC_MAX]; - int total_nb_available_rb[NFAPI_CC_MAX]; - int N_RBG[NFAPI_CC_MAX]; + const int min_rb_unit = get_min_rb_unit(module_idP, CC_id); + const int dl_Bandwidth = cc[CC_id].mib->message.dl_Bandwidth; + const int N_RB_DL = to_prb(dl_Bandwidth); + const int N_RBG = to_rbg(dl_Bandwidth); + int total_nb_available_rb = N_RB_DL; nfapi_dl_config_request_body_t *dl_req; nfapi_dl_config_request_pdu_t *dl_config_pdu; int tdd_sfa; @@ -503,22 +492,19 @@ schedule_ue_spec(module_id_t module_idP, int header_length_last; int header_length_total; rrc_eNB_ue_context_t *ue_contextP = NULL; - int nb_mac_CC = RC.nb_mac_CC[module_idP]; - long dl_Bandwidth; if(is_pmch_subframe(frameP,subframeP,&RC.eNB[module_idP][0]->frame_parms)){ //LOG_E(MAC,"Frame[%d] SF:%d This SF should not be allocated\n",frameP,subframeP); return ; } - start_meas(&eNB->schedule_dlsch); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH, VCD_FUNCTION_IN); // for TDD: check that we have to act here, otherwise return - if (cc[0].tdd_Config) { - tdd_sfa = cc[0].tdd_Config->subframeAssignment; + if (cc[CC_id].tdd_Config) { + tdd_sfa = cc[CC_id].tdd_Config->subframeAssignment; switch (subframeP) { case 0: @@ -567,33 +553,25 @@ schedule_ue_spec(module_id_t module_idP, aggregation = 2; - for (CC_id = 0, eNB_stats = &eNB->eNB_stats[0]; CC_id < nb_mac_CC; CC_id++, eNB_stats++) { - dl_Bandwidth = cc[CC_id].mib->message.dl_Bandwidth; - N_RB_DL[CC_id] = to_prb(dl_Bandwidth); - min_rb_unit[CC_id] = get_min_rb_unit(module_idP, CC_id); - // get number of PRBs less those used by common channels - total_nb_available_rb[CC_id] = N_RB_DL[CC_id]; + for (int i = 0; i < N_RB_DL; i++) + if (cc[CC_id].vrb_map[i] != 0) + total_nb_available_rb--; - for (i = 0; i < N_RB_DL[CC_id]; i++) - if (cc[CC_id].vrb_map[i] != 0) - total_nb_available_rb[CC_id]--; - - N_RBG[CC_id] = to_rbg(dl_Bandwidth); - // store the global enb stats: - eNB_stats->num_dlactive_UEs = UE_list->num_UEs; - eNB_stats->available_prbs = total_nb_available_rb[CC_id]; - eNB_stats->total_available_prbs += total_nb_available_rb[CC_id]; - eNB_stats->dlsch_bytes_tx = 0; - eNB_stats->dlsch_pdus_tx = 0; - } + // store the global enb stats: + eNB->eNB_stats[CC_id].num_dlactive_UEs = UE_list->num_UEs; + eNB->eNB_stats[CC_id].available_prbs = total_nb_available_rb; + eNB->eNB_stats[CC_id].total_available_prbs += total_nb_available_rb; + eNB->eNB_stats[CC_id].dlsch_bytes_tx = 0; + eNB->eNB_stats[CC_id].dlsch_pdus_tx = 0; // CALLING Pre_Processor for downlink scheduling // (Returns estimation of RBs required by each UE and the allocation on sub-band) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR, VCD_FUNCTION_IN); start_meas(&eNB->schedule_dlsch_preprocessor); + memset(eNB->slice_info.rballoc_sub, 0, sizeof(eNB->slice_info.rballoc_sub)); dlsch_scheduler_pre_processor(module_idP, - slice_idxP, + 0, //slice_idxP, frameP, subframeP, mbsfn_flag, @@ -610,1034 +588,1042 @@ schedule_ue_spec(module_id_t module_idP, /* the interslice multiplexing re-sorts the UE_list for the slices it tries * to multiplex, so we need to sort it for the current slice again */ sort_UEs(module_idP, - slice_idxP, + 0,//slice_idxP, frameP, subframeP); } - for (CC_id = 0; CC_id < nb_mac_CC; CC_id++) { - LOG_D(MAC, "doing schedule_ue_spec for CC_id %d\n", - CC_id); - dl_req = &eNB->DL_req[CC_id].dl_config_request_body; + LOG_D(MAC, "doing schedule_ue_spec for CC_id %d\n", + CC_id); + dl_req = &eNB->DL_req[CC_id].dl_config_request_body; - if (mbsfn_flag[CC_id] > 0) - continue; + //if (mbsfn_flag[CC_id] > 0) + // return; - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { - LOG_D(MAC, "doing schedule_ue_spec for CC_id %d UE %d\n", - CC_id, - UE_id); - continue_flag = 0; // reset the flag to allow allocation for the remaining UEs - rnti = UE_RNTI(module_idP, UE_id); - ue_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id]; - ue_template = &UE_list->UE_template[CC_id][UE_id]; + for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + LOG_D(MAC, "doing schedule_ue_spec for CC_id %d UE %d\n", + CC_id, + UE_id); + continue_flag = 0; // reset the flag to allow allocation for the remaining UEs + rnti = UE_RNTI(module_idP, UE_id); + ue_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id]; + ue_template = &UE_list->UE_template[CC_id][UE_id]; - if (ue_template->rach_resource_type > 0) { - continue_flag = 1; + if (ue_template->rach_resource_type > 0) { + continue_flag = 1; + } + + if (&(UE_list->eNB_UE_stats[CC_id][UE_id]) == NULL) { + LOG_D(MAC, "[eNB] Cannot find eNB_UE_stats\n"); + continue_flag = 1; + } else { + eNB_UE_stats = &(UE_list->eNB_UE_stats[CC_id][UE_id]); + } + + if (continue_flag != 1) { + switch (get_tmode(module_idP, + CC_id, + UE_id)) { + case 1: + case 2: + case 7: + aggregation = get_aggregation(get_bw_index(module_idP, + CC_id), + ue_sched_ctrl->dl_cqi[CC_id], + format1); + break; + + case 3: + aggregation = get_aggregation(get_bw_index(module_idP, + CC_id), + ue_sched_ctrl->dl_cqi[CC_id], + format2A); + break; + + default: + AssertFatal(1==0,"Unsupported transmission mode %d\n", get_tmode(module_idP, CC_id, UE_id)); + aggregation = 2; + break; } + } - if (&(UE_list->eNB_UE_stats[CC_id][UE_id]) == NULL) { - LOG_D(MAC, "[eNB] Cannot find eNB_UE_stats\n"); - continue_flag = 1; - } else { - eNB_UE_stats = &(UE_list->eNB_UE_stats[CC_id][UE_id]); - } - - if (continue_flag != 1) { - switch (get_tmode(module_idP, - CC_id, - UE_id)) { - case 1: - case 2: - case 7: - aggregation = get_aggregation(get_bw_index(module_idP, - CC_id), - ue_sched_ctrl->dl_cqi[CC_id], - format1); - break; - - case 3: - aggregation = get_aggregation(get_bw_index(module_idP, - CC_id), - ue_sched_ctrl->dl_cqi[CC_id], - format2A); - break; - - default: - AssertFatal(1==0,"Unsupported transmission mode %d\n", get_tmode(module_idP, CC_id, UE_id)); - aggregation = 2; - break; - } - } - - /* if (continue_flag != 1 */ - if (ue_sched_ctrl->pre_nb_available_rbs[CC_id] == 0 || // no RBs allocated - CCE_allocation_infeasible(module_idP, - CC_id, - 1, - subframeP, - aggregation, - rnti)) { - LOG_D(MAC, "[eNB %d] Frame %d : no RB allocated for UE %d on CC_id %d: continue \n", - module_idP, - frameP, - UE_id, - CC_id); - continue_flag = 1; //to next user (there might be rbs availiable for other UEs in TM5 - } - - // If TDD - if (cc[CC_id].tdd_Config != NULL) { //TDD - set_ue_dai(subframeP, - UE_id, - CC_id, - cc[CC_id].tdd_Config->subframeAssignment, - UE_list); - // update UL DAI after DLSCH scheduling - set_ul_DAI(module_idP, - UE_id, - CC_id, - frameP, - subframeP); - } - - if (continue_flag == 1) { - add_ue_dlsch_info(module_idP, - CC_id, - UE_id, - subframeP, - S_DL_NONE, - rnti); - continue; - } - - nb_available_rb = ue_sched_ctrl->pre_nb_available_rbs[CC_id]; - harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, - frameP, - subframeP); - round_DL = ue_sched_ctrl->round[CC_id][harq_pid]; - eNB_UE_stats->crnti = rnti; - eNB_UE_stats->rrc_status = mac_eNB_get_rrc_status(module_idP, rnti); - eNB_UE_stats->harq_pid = harq_pid; - eNB_UE_stats->harq_round = round_DL; - - if (eNB_UE_stats->rrc_status < RRC_RECONFIGURED) { - ue_sched_ctrl->uplane_inactivity_timer = 0; - } - - if (eNB_UE_stats->rrc_status < RRC_CONNECTED) { - LOG_D(MAC, "UE %d is not in RRC_CONNECTED\n", UE_id); - continue; - } - - header_length_total = 0; - sdu_length_total = 0; - num_sdus = 0; - - /* - DevCheck(((eNB_UE_stats->dl_cqi < MIN_CQI_VALUE) || - (eNB_UE_stats->dl_cqi > MAX_CQI_VALUE)), - eNB_UE_stats->dl_cqi, MIN_CQI_VALUE, MAX_CQI_VALUE); - */ - if (NFAPI_MODE != NFAPI_MONOLITHIC) { - eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[ue_sched_ctrl->dl_cqi[CC_id]]; - } else { // this operation is also done in the preprocessor - eNB_UE_stats->dlsch_mcs1 = cmin(eNB_UE_stats->dlsch_mcs1, - eNB->slice_info.dl[slice_idxP].maxmcs); // cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs); - } - - // Store stats - // eNB_UE_stats->dl_cqi= eNB_UE_stats->dl_cqi; - - // Initializing the rb allocation indicator for each UE - for (j = 0; j < N_RBG[CC_id]; j++) { - ue_template->rballoc_subband[harq_pid][j] = 0; - } - - LOG_D(MAC, "[eNB %d] Frame %d: Scheduling UE %d on CC_id %d (rnti %x, harq_pid %d, round %d, rb %d, cqi %d, mcs %d, rrc %d)\n", + /* if (continue_flag != 1 */ + if (ue_sched_ctrl->pre_nb_available_rbs[CC_id] == 0 || // no RBs allocated + CCE_allocation_infeasible(module_idP, + CC_id, + 1, + subframeP, + aggregation, + rnti)) { + LOG_D(MAC, "[eNB %d] Frame %d : no RB allocated for UE %d on CC_id %d: continue \n", module_idP, frameP, UE_id, - CC_id, - rnti, - harq_pid, - round_DL, - nb_available_rb, - ue_sched_ctrl->dl_cqi[CC_id], - eNB_UE_stats->dlsch_mcs1, - eNB_UE_stats->rrc_status); + CC_id); + continue_flag = 1; //to next user (there might be rbs availiable for other UEs in TM5 + } - /* Process retransmission */ - if (round_DL != 8) { - // get freq_allocation - nb_rb = ue_template->nb_rb[harq_pid]; - TBS = get_TBS_DL(ue_template->oldmcs1[harq_pid], - nb_rb); + // If TDD + if (cc[CC_id].tdd_Config != NULL) { //TDD + set_ue_dai(subframeP, + UE_id, + CC_id, + cc[CC_id].tdd_Config->subframeAssignment, + UE_list); + // update UL DAI after DLSCH scheduling + set_ul_DAI(module_idP, + UE_id, + CC_id, + frameP, + subframeP); + } - if (nb_rb <= nb_available_rb) { - /* CDRX */ - ue_sched_ctrl->harq_rtt_timer[CC_id][harq_pid] = 1; // restart HARQ RTT timer + if (continue_flag == 1) { + add_ue_dlsch_info(module_idP, + CC_id, + UE_id, + subframeP, + S_DL_NONE, + rnti); + continue; + } - if (ue_sched_ctrl->cdrx_configured) { - ue_sched_ctrl->drx_retransmission_timer[harq_pid] = 0; // stop drx retransmission + nb_available_rb = ue_sched_ctrl->pre_nb_available_rbs[CC_id]; + harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, + frameP, + subframeP); + round_DL = ue_sched_ctrl->round[CC_id][harq_pid]; + eNB_UE_stats->crnti = rnti; + eNB_UE_stats->rrc_status = mac_eNB_get_rrc_status(module_idP, rnti); + eNB_UE_stats->harq_pid = harq_pid; + eNB_UE_stats->harq_round = round_DL; - /* - * Note: contrary to the spec drx_retransmission_timer[harq_pid] is reset not stop. - */ - if (harq_pid == 0) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_RETRANSMISSION_HARQ0, (unsigned long) ue_sched_ctrl->drx_retransmission_timer[0]); - } + if (eNB_UE_stats->rrc_status < RRC_RECONFIGURED) { + ue_sched_ctrl->uplane_inactivity_timer = 0; + } + + if (eNB_UE_stats->rrc_status < RRC_CONNECTED) { + LOG_D(MAC, "UE %d is not in RRC_CONNECTED\n", UE_id); + continue; + } + + header_length_total = 0; + sdu_length_total = 0; + num_sdus = 0; + + /* + DevCheck(((eNB_UE_stats->dl_cqi < MIN_CQI_VALUE) || + (eNB_UE_stats->dl_cqi > MAX_CQI_VALUE)), + eNB_UE_stats->dl_cqi, MIN_CQI_VALUE, MAX_CQI_VALUE); + */ + if (NFAPI_MODE != NFAPI_MONOLITHIC) { + eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[ue_sched_ctrl->dl_cqi[CC_id]]; + } else { // this operation is also done in the preprocessor + eNB_UE_stats->dlsch_mcs1 = cmin(eNB_UE_stats->dlsch_mcs1, + eNB->slice_info.dl[0/*slice_idxP*/].maxmcs); // cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs); + } + + // Store stats + // eNB_UE_stats->dl_cqi= eNB_UE_stats->dl_cqi; + + // Initializing the rb allocation indicator for each UE + for (j = 0; j < N_RBG; j++) { + ue_template->rballoc_subband[harq_pid][j] = 0; + } + + LOG_D(MAC, "[eNB %d] Frame %d: Scheduling UE %d on CC_id %d (rnti %x, harq_pid %d, round %d, rb %d, cqi %d, mcs %d, rrc %d)\n", + module_idP, + frameP, + UE_id, + CC_id, + rnti, + harq_pid, + round_DL, + nb_available_rb, + ue_sched_ctrl->dl_cqi[CC_id], + eNB_UE_stats->dlsch_mcs1, + eNB_UE_stats->rrc_status); + + /* Process retransmission */ + if (round_DL != 8) { + // get freq_allocation + nb_rb = ue_template->nb_rb[harq_pid]; + TBS = get_TBS_DL(ue_template->oldmcs1[harq_pid], + nb_rb); + + if (nb_rb <= nb_available_rb) { + /* CDRX */ + ue_sched_ctrl->harq_rtt_timer[CC_id][harq_pid] = 1; // restart HARQ RTT timer + + if (ue_sched_ctrl->cdrx_configured) { + ue_sched_ctrl->drx_retransmission_timer[harq_pid] = 0; // stop drx retransmission + + /* + * Note: contrary to the spec drx_retransmission_timer[harq_pid] is reset not stop. + */ + if (harq_pid == 0) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_RETRANSMISSION_HARQ0, (unsigned long) ue_sched_ctrl->drx_retransmission_timer[0]); } + } - if (cc[CC_id].tdd_Config != NULL) { - ue_template->DAI++; - update_ul_dci(module_idP, - CC_id, - rnti, - ue_template->DAI, - subframeP); - LOG_D(MAC, "DAI update: CC_id %d subframeP %d: UE %d, DAI %d\n", - CC_id, - subframeP, - UE_id, - ue_template->DAI); - } - - if (nb_rb == ue_sched_ctrl->pre_nb_available_rbs[CC_id]) { - for (j = 0; j < N_RBG[CC_id]; j++) { // for indicating the rballoc for each sub-band - ue_template->rballoc_subband[harq_pid][j] = ue_sched_ctrl->rballoc_sub_UE[CC_id][j]; - } - } else { - nb_rb_temp = nb_rb; - j = 0; - - while ((nb_rb_temp > 0) && (j < N_RBG[CC_id])) { - if (ue_sched_ctrl->rballoc_sub_UE[CC_id][j] == 1) { - if (ue_template->rballoc_subband[harq_pid][j]) - LOG_W(MAC, "WARN: rballoc_subband not free for retrans?\n"); - - ue_template->rballoc_subband[harq_pid][j] = ue_sched_ctrl->rballoc_sub_UE[CC_id][j]; - nb_rb_temp -= min_rb_unit[CC_id]; - - if ((j == N_RBG[CC_id] - 1) && (N_RB_DL[CC_id] == 25 || N_RB_DL[CC_id] == 50)) - nb_rb_temp++; - } - - j++; - } - } - - nb_available_rb -= nb_rb; - - switch (get_tmode(module_idP, CC_id, UE_id)) { - case 1: - case 2: - case 7: - default: - LOG_D(MAC, "retransmission DL_REQ: rnti:%x\n", - rnti); - dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; - memset((void *) dl_config_pdu, - 0, - sizeof(nfapi_dl_config_request_pdu_t)); - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; - dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu)); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = - get_aggregation(get_bw_index(module_idP, - CC_id), - ue_sched_ctrl->dl_cqi[CC_id], - format1); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // CRNTI: see Table 4-10 from SCF082 - nFAPI specifications - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = harq_pid; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // Don't adjust power when retransmitting - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = ue_template->oldNDI[harq_pid]; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = ue_template->oldmcs1[harq_pid]; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = round_DL & 3; - - // TDD - if (cc[CC_id].tdd_Config != NULL) { - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.downlink_assignment_index = (ue_template->DAI - 1) & 3; - LOG_D(MAC, "[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, dai %d, mcs %d\n", - module_idP, - CC_id, - harq_pid, - round_DL, - ue_template->DAI - 1, - ue_template->oldmcs1[harq_pid]); - } else { - LOG_D(MAC, "[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, mcs %d\n", - module_idP, - CC_id, - harq_pid, - round_DL, - ue_template->oldmcs1[harq_pid]); - } - - if (!CCE_allocation_infeasible(module_idP, - CC_id, - 1, - subframeP, - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, - rnti)) { - dl_req->number_dci++; - dl_req->number_pdu++; - dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG; - eNB->DL_req[CC_id].sfn_sf = frameP<<4 | subframeP; - eNB->DL_req[CC_id].header.message_id = NFAPI_DL_CONFIG_REQUEST; - fill_nfapi_dlsch_config(eNB, - dl_req, - TBS, - -1, // retransmission, no pdu_index - rnti, - 0, // type 0 allocation from 7.1.6 in 36.213 - 0, // virtual_resource_block_assignment_flag, unused here - 0, // resource_block_coding, to be filled in later - getQm(ue_template->oldmcs1[harq_pid]), - round_DL & 3, // redundancy version - 1, // transport blocks - 0, // transport block to codeword swap flag - cc[CC_id].p_eNB == 1 ? 0 : 1, // transmission_scheme - 1, // number of layers - 1, // number of subbands - // uint8_t codebook_index, - 4, // UE category capacity - ue_template->physicalConfigDedicated->pdsch_ConfigDedicated->p_a, - 0, // delta_power_offset for TM5 - 0, // ngap - 0, // nprb - cc[CC_id].p_eNB == 1 ? 1 : 2, // transmission mode - 0, //number of PRBs treated as one subband, not used here - 0); // number of beamforming vectors, not used here - LOG_D(MAC, "Filled NFAPI configuration for DCI/DLSCH %d, retransmission round %d\n", - eNB->pdu_index[CC_id], - round_DL); - program_dlsch_acknak(module_idP, - CC_id, - UE_id, - frameP, - subframeP, - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx); - // No TX request for retransmission (check if null request for FAPI) - } else { - LOG_W(MAC, "Frame %d, Subframe %d: Dropping DLSCH allocation for UE %d\%x, infeasible CCE allocation\n", - frameP, - subframeP, - UE_id, - rnti); - } - } - - add_ue_dlsch_info(module_idP, - CC_id, UE_id, - subframeP, - S_DL_SCHEDULED, - rnti); - //eNB_UE_stats->dlsch_trials[round]++; - eNB_UE_stats->num_retransmission += 1; - eNB_UE_stats->rbs_used_retx = nb_rb; - eNB_UE_stats->total_rbs_used_retx += nb_rb; - eNB_UE_stats->dlsch_mcs2 = eNB_UE_stats->dlsch_mcs1; - } else { - LOG_D(MAC, - "[eNB %d] Frame %d CC_id %d : don't schedule UE %d, its retransmission takes more resources than we have\n", - module_idP, - frameP, + if (cc[CC_id].tdd_Config != NULL) { + ue_template->DAI++; + update_ul_dci(module_idP, + CC_id, + rnti, + ue_template->DAI, + subframeP); + LOG_D(MAC, "DAI update: CC_id %d subframeP %d: UE %d, DAI %d\n", CC_id, - UE_id); + subframeP, + UE_id, + ue_template->DAI); } - } else { - /* This is a potentially new SDU opportunity */ - rlc_status.bytes_in_buffer = 0; - // Now check RLC information to compute number of required RBs - // get maximum TBS size for RLC request - TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, - nb_available_rb); - // add the length for all the control elements (timing adv, drx, etc) : header + payload - - if (ue_sched_ctrl->ta_timer == 0) { - ta_update = ue_sched_ctrl->ta_update; - - /* if we send TA then set timer to not send it for a while */ - if (ta_update != 31) { - ue_sched_ctrl->ta_timer = 20; + if (nb_rb == ue_sched_ctrl->pre_nb_available_rbs[CC_id]) { + for (j = 0; j < N_RBG; j++) { // for indicating the rballoc for each sub-band + ue_template->rballoc_subband[harq_pid][j] = ue_sched_ctrl->rballoc_sub_UE[CC_id][j]; } - - /* reset ta_update */ - ue_sched_ctrl->ta_update = 31; } else { - ta_update = 31; - } + nb_rb_temp = nb_rb; + j = 0; - ta_len = (ta_update != 31) ? 2 : 0; + while ((nb_rb_temp > 0) && (j < N_RBG)) { + if (ue_sched_ctrl->rballoc_sub_UE[CC_id][j] == 1) { + if (ue_template->rballoc_subband[harq_pid][j]) + LOG_W(MAC, "WARN: rballoc_subband not free for retrans?\n"); - // RLC data on DCCH - if (TBS - ta_len - header_length_total - sdu_length_total - 3 > 0) { - rlc_status = mac_rlc_status_ind(module_idP, - rnti, - module_idP, - frameP, - subframeP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - DCCH, - TBS - ta_len - header_length_total - sdu_length_total - 3, 0, 0 - ); - sdu_lengths[0] = 0; + ue_template->rballoc_subband[harq_pid][j] = ue_sched_ctrl->rballoc_sub_UE[CC_id][j]; + nb_rb_temp -= min_rb_unit; - if (rlc_status.bytes_in_buffer > 0) { - LOG_D(MAC, "[eNB %d] SFN/SF %d.%d, DL-DCCH->DLSCH CC_id %d, Requesting %d bytes from RLC (RRC message)\n", - module_idP, - frameP, - subframeP, - CC_id, - TBS - ta_len - header_length_total - sdu_length_total - 3); - sdu_lengths[0] = mac_rlc_data_req(module_idP, - rnti, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - DCCH, - TBS, //not used - (char *)&dlsch_buffer[0], 0, 0 - ); - - if((rrc_release_info.num_UEs > 0) && (rlc_am_mui.rrc_mui_num > 0)) { - while(pthread_mutex_trylock(&rrc_release_freelist)) { - /* spin... */ - } - - uint16_t release_total = 0; - - for (release_num = 0, release_ctrl = &rrc_release_info.RRC_release_ctrl[0]; - release_num < NUMBER_OF_UE_MAX; - release_num++, release_ctrl++) { - if(release_ctrl->flag > 0) { - release_total++; - } else { - continue; - } - - if(release_ctrl->flag == 1) { - if(release_ctrl->rnti == rnti) { - for(uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) { - if(release_ctrl->rrc_eNB_mui == rlc_am_mui.rrc_mui[mui_num]) { - release_ctrl->flag = 3; - LOG_D(MAC,"DLSCH Release send:index %d rnti %x mui %d mui_num %d flag 1->3\n", - release_num, - rnti, - rlc_am_mui.rrc_mui[mui_num], - mui_num); - break; - } - } - } - } - - if(release_ctrl->flag == 2) { - if(release_ctrl->rnti == rnti) { - for (uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) { - if(release_ctrl->rrc_eNB_mui == rlc_am_mui.rrc_mui[mui_num]) { - release_ctrl->flag = 4; - LOG_D(MAC, "DLSCH Release send:index %d rnti %x mui %d mui_num %d flag 2->4\n", - release_num, - rnti, - rlc_am_mui.rrc_mui[mui_num], - mui_num); - break; - } - } - } - } - - if(release_total >= rrc_release_info.num_UEs) - break; - } - - pthread_mutex_unlock(&rrc_release_freelist); + if ((j == N_RBG - 1) && (N_RB_DL == 25 || N_RB_DL == 50)) + nb_rb_temp++; } - for (ra_ii = 0, ra = &eNB->common_channels[CC_id].ra[0]; ra_ii < NB_RA_PROC_MAX; ra_ii++, ra++) { - if ((ra->rnti == rnti) && (ra->state == MSGCRNTI)) { - for (uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) { - if (ra->crnti_rrc_mui == rlc_am_mui.rrc_mui[mui_num]) { - ra->crnti_harq_pid = harq_pid; - ra->state = MSGCRNTI_ACK; - break; - } - } - } - } - - T(T_ENB_MAC_UE_DL_SDU, - T_INT(module_idP), - T_INT(CC_id), - T_INT(rnti), - T_INT(frameP), - T_INT(subframeP), - T_INT(harq_pid), - T_INT(DCCH), - T_INT(sdu_lengths[0])); - LOG_D(MAC, "[eNB %d][DCCH] CC_id %d Got %d bytes from RLC\n", - module_idP, - CC_id, - sdu_lengths[0]); - sdu_length_total = sdu_lengths[0]; - sdu_lcids[0] = DCCH; - eNB_UE_stats->lcid_sdu[0] = DCCH; - eNB_UE_stats->sdu_length_tx[DCCH] = sdu_lengths[0]; - eNB_UE_stats->num_pdu_tx[DCCH] += 1; - eNB_UE_stats->num_bytes_tx[DCCH] += sdu_lengths[0]; - header_length_last = 1 + 1 + (sdu_lengths[0] >= 128); - header_length_total += header_length_last; - num_sdus = 1; -#ifdef DEBUG_eNB_SCHEDULER - LOG_T(MAC, "[eNB %d][DCCH] CC_id %d Got %d bytes :", - module_idP, - CC_id, - sdu_lengths[0]); - - for (j = 0; j < sdu_lengths[0]; ++j) { - LOG_T(MAC, "%x ", - dlsch_buffer[j]); - } - - LOG_T(MAC, "\n"); -#endif + j++; } } - // RLC data on DCCH1 - if (TBS - ta_len - header_length_total - sdu_length_total - 3 > 0) { - rlc_status = mac_rlc_status_ind(module_idP, - rnti, - module_idP, - frameP, - subframeP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - DCCH + 1, - TBS - ta_len - header_length_total - sdu_length_total - 3, 0, 0 - ); - // DCCH SDU - sdu_lengths[num_sdus] = 0; + nb_available_rb -= nb_rb; - if (rlc_status.bytes_in_buffer > 0) { - LOG_D(MAC, "[eNB %d], Frame %d, DCCH1->DLSCH, CC_id %d, Requesting %d bytes from RLC (RRC message)\n", - module_idP, frameP, CC_id, - TBS - ta_len - header_length_total - sdu_length_total - 3); - sdu_lengths[num_sdus] += mac_rlc_data_req(module_idP, - rnti, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, DCCH + 1, - TBS, //not used - (char *) &dlsch_buffer[sdu_length_total], 0, 0 - ); - T(T_ENB_MAC_UE_DL_SDU, - T_INT(module_idP), - T_INT(CC_id), - T_INT(rnti), - T_INT(frameP), - T_INT(subframeP), - T_INT(harq_pid), - T_INT(DCCH + 1), - T_INT(sdu_lengths[num_sdus])); - sdu_lcids[num_sdus] = DCCH1; - sdu_length_total += sdu_lengths[num_sdus]; - eNB_UE_stats->lcid_sdu[num_sdus] = DCCH1; - eNB_UE_stats->sdu_length_tx[DCCH1] = sdu_lengths[num_sdus]; - eNB_UE_stats->num_pdu_tx[DCCH1] += 1; - eNB_UE_stats->num_bytes_tx[DCCH1] += sdu_lengths[num_sdus]; - header_length_last = 1 + 1 + (sdu_lengths[num_sdus] >= 128); - header_length_total += header_length_last; - num_sdus++; -#ifdef DEBUG_eNB_SCHEDULER - LOG_T(MAC, "[eNB %d][DCCH1] CC_id %d Got %d bytes :", - module_idP, - CC_id, - sdu_lengths[num_sdus]); + switch (get_tmode(module_idP, CC_id, UE_id)) { + case 1: + case 2: + case 7: + default: + LOG_D(MAC, "retransmission DL_REQ: rnti:%x\n", + rnti); + dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + memset((void *) dl_config_pdu, + 0, + sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; + dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu)); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = + get_aggregation(get_bw_index(module_idP, + CC_id), + ue_sched_ctrl->dl_cqi[CC_id], + format1); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // CRNTI: see Table 4-10 from SCF082 - nFAPI specifications + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = harq_pid; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // Don't adjust power when retransmitting + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = ue_template->oldNDI[harq_pid]; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = ue_template->oldmcs1[harq_pid]; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = round_DL & 3; - for (j = 0; j < sdu_lengths[num_sdus]; ++j) { - LOG_T(MAC, "%x ", - dlsch_buffer[j]); + // TDD + if (cc[CC_id].tdd_Config != NULL) { + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.downlink_assignment_index = (ue_template->DAI - 1) & 3; + LOG_D(MAC, "[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, dai %d, mcs %d\n", + module_idP, + CC_id, + harq_pid, + round_DL, + ue_template->DAI - 1, + ue_template->oldmcs1[harq_pid]); + } else { + LOG_D(MAC, "[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, mcs %d\n", + module_idP, + CC_id, + harq_pid, + round_DL, + ue_template->oldmcs1[harq_pid]); } - LOG_T(MAC, "\n"); -#endif - } + if (!CCE_allocation_infeasible(module_idP, + CC_id, + 1, + subframeP, + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, + rnti)) { + dl_req->number_dci++; + dl_req->number_pdu++; + dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG; + eNB->DL_req[CC_id].sfn_sf = frameP<<4 | subframeP; + eNB->DL_req[CC_id].header.message_id = NFAPI_DL_CONFIG_REQUEST; + fill_nfapi_dlsch_config(eNB, + dl_req, + TBS, + -1, // retransmission, no pdu_index + rnti, + 0, // type 0 allocation from 7.1.6 in 36.213 + 0, // virtual_resource_block_assignment_flag, unused here + 0, // resource_block_coding, to be filled in later + getQm(ue_template->oldmcs1[harq_pid]), + round_DL & 3, // redundancy version + 1, // transport blocks + 0, // transport block to codeword swap flag + cc[CC_id].p_eNB == 1 ? 0 : 1, // transmission_scheme + 1, // number of layers + 1, // number of subbands + // uint8_t codebook_index, + 4, // UE category capacity + ue_template->physicalConfigDedicated->pdsch_ConfigDedicated->p_a, + 0, // delta_power_offset for TM5 + 0, // ngap + 0, // nprb + cc[CC_id].p_eNB == 1 ? 1 : 2, // transmission mode + 0, //number of PRBs treated as one subband, not used here + 0); // number of beamforming vectors, not used here + LOG_D(MAC, "Filled NFAPI configuration for DCI/DLSCH %d, retransmission round %d\n", + eNB->pdu_index[CC_id], + round_DL); + program_dlsch_acknak(module_idP, + CC_id, + UE_id, + frameP, + subframeP, + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx); + // No TX request for retransmission (check if null request for FAPI) + } else { + LOG_W(MAC, "Frame %d, Subframe %d: Dropping DLSCH allocation for UE %d\%x, infeasible CCE allocation\n", + frameP, + subframeP, + UE_id, + rnti); + } } - // TODO: lcid has to be sorted before the actual allocation (similar struct as ue_list). - for (lcid = NB_RB_MAX - 1; lcid >= DTCH; lcid--) { - // TODO: check if the lcid is active - LOG_D(MAC, "[eNB %d], Frame %d, DTCH%d->DLSCH, Checking RLC status (tbs %d, len %d)\n", + add_ue_dlsch_info(module_idP, + CC_id, UE_id, + subframeP, + S_DL_SCHEDULED, + rnti); + //eNB_UE_stats->dlsch_trials[round]++; + eNB_UE_stats->num_retransmission += 1; + eNB_UE_stats->rbs_used_retx = nb_rb; + eNB_UE_stats->total_rbs_used_retx += nb_rb; + eNB_UE_stats->dlsch_mcs2 = eNB_UE_stats->dlsch_mcs1; + } else { + LOG_D(MAC, + "[eNB %d] Frame %d CC_id %d : don't schedule UE %d, its retransmission takes more resources than we have\n", + module_idP, + frameP, + CC_id, + UE_id); + } + } else { + /* This is a potentially new SDU opportunity */ + rlc_status.bytes_in_buffer = 0; + // Now check RLC information to compute number of required RBs + // get maximum TBS size for RLC request + TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, + nb_available_rb); + + // add the length for all the control elements (timing adv, drx, etc) : header + payload + + if (ue_sched_ctrl->ta_timer == 0) { + ta_update = ue_sched_ctrl->ta_update; + + /* if we send TA then set timer to not send it for a while */ + if (ta_update != 31) { + ue_sched_ctrl->ta_timer = 20; + } + + /* reset ta_update */ + ue_sched_ctrl->ta_update = 31; + } else { + ta_update = 31; + } + + ta_len = (ta_update != 31) ? 2 : 0; + + // RLC data on DCCH + if (TBS - ta_len - header_length_total - sdu_length_total - 3 > 0) { + rlc_status = mac_rlc_status_ind(module_idP, + rnti, + module_idP, + frameP, + subframeP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + DCCH, + TBS - ta_len - header_length_total - sdu_length_total - 3, + 0, + 0 + ); + sdu_lengths[0] = 0; + + if (rlc_status.bytes_in_buffer > 0) { + LOG_D(MAC, "[eNB %d] SFN/SF %d.%d, DL-DCCH->DLSCH CC_id %d, Requesting %d bytes from RLC (RRC message)\n", module_idP, frameP, - lcid, - TBS, + subframeP, + CC_id, TBS - ta_len - header_length_total - sdu_length_total - 3); - - if (TBS - ta_len - header_length_total - sdu_length_total - 3 > 0) { - rlc_status = mac_rlc_status_ind(module_idP, + sdu_lengths[0] = mac_rlc_data_req(module_idP, rnti, module_idP, frameP, - subframeP, ENB_FLAG_YES, MBMS_FLAG_NO, - lcid, - TBS - ta_len - header_length_total - sdu_length_total - 3, 0, 0 + DCCH, + TBS, //not used + (char *)&dlsch_buffer[0], + 0, + 0 ); - if (rlc_status.bytes_in_buffer > 0) { - LOG_D(MAC, "[eNB %d][USER-PLANE DEFAULT DRB] Frame %d : DTCH->DLSCH, Requesting %d bytes from RLC (lcid %d total hdr len %d)\n", - module_idP, - frameP, - TBS - ta_len - header_length_total - sdu_length_total - 3, - lcid, - header_length_total); - sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, - rnti, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - lcid, - TBS, //not used - (char *) &dlsch_buffer[sdu_length_total], 0, 0 - ); - T(T_ENB_MAC_UE_DL_SDU, - T_INT(module_idP), - T_INT(CC_id), - T_INT(rnti), - T_INT(frameP), - T_INT(subframeP), - T_INT(harq_pid), - T_INT(lcid), - T_INT(sdu_lengths[num_sdus])); - LOG_D(MAC, "[eNB %d][USER-PLANE DEFAULT DRB] Got %d bytes for DTCH %d \n", - module_idP, - sdu_lengths[num_sdus], - lcid); - sdu_lcids[num_sdus] = lcid; - sdu_length_total += sdu_lengths[num_sdus]; - eNB_UE_stats->num_pdu_tx[lcid]++; - eNB_UE_stats->lcid_sdu[num_sdus] = lcid; - eNB_UE_stats->sdu_length_tx[lcid] = sdu_lengths[num_sdus]; - eNB_UE_stats->num_bytes_tx[lcid] += sdu_lengths[num_sdus]; - header_length_last = 1 + 1 + (sdu_lengths[num_sdus] >= 128); - header_length_total += header_length_last; - num_sdus++; - ue_sched_ctrl->uplane_inactivity_timer = 0; - // reset RRC inactivity timer after uplane activity - ue_contextP = rrc_eNB_get_ue_context(RC.rrc[module_idP], rnti); + if((rrc_release_info.num_UEs > 0) && (rlc_am_mui.rrc_mui_num > 0)) { + while(pthread_mutex_trylock(&rrc_release_freelist)) { + /* spin... */ + } - if (ue_contextP != NULL) { - ue_contextP->ue_context.ue_rrc_inactivity_timer = 1; + uint16_t release_total = 0; + + for (release_num = 0, release_ctrl = &rrc_release_info.RRC_release_ctrl[0]; + release_num < NUMBER_OF_UE_MAX; + release_num++, release_ctrl++) { + if(release_ctrl->flag > 0) { + release_total++; } else { - LOG_E(MAC, "[eNB %d] CC_id %d Couldn't find the context associated to UE (RNTI %d) and reset RRC inactivity timer\n", - module_idP, - CC_id, - rnti); + continue; } - } // end if (rlc_status.bytes_in_buffer > 0) - } else { // no TBS left - break; // break for (lcid = NB_RB_MAX - 1; lcid >= DTCH; lcid--) - } - } - /* Last header does not have length field */ - if (header_length_total) { - header_length_total -= header_length_last; - header_length_total++; - } - - // there is at least one SDU or TA command - // if (num_sdus > 0 ){ - if (ta_len + sdu_length_total + header_length_total > 0) { - // Now compute number of required RBs for total sdu length - // Assume RAH format 2 - mcs = eNB_UE_stats->dlsch_mcs1; - - if (mcs == 0) { - nb_rb = 4; // don't let the TBS get too small - } else { - nb_rb = min_rb_unit[CC_id]; - } - - TBS = get_TBS_DL(mcs, nb_rb); - - while (TBS < sdu_length_total + header_length_total + ta_len) { - nb_rb += min_rb_unit[CC_id]; // - - if (nb_rb > nb_available_rb) { // if we've gone beyond the maximum number of RBs - // (can happen if N_RB_DL is odd) - TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, - nb_available_rb); - nb_rb = nb_available_rb; - break; - } - - TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, - nb_rb); - } - - if (nb_rb == ue_sched_ctrl->pre_nb_available_rbs[CC_id]) { - for (j = 0; j < N_RBG[CC_id]; ++j) { // for indicating the rballoc for each sub-band - ue_template->rballoc_subband[harq_pid][j] = ue_sched_ctrl->rballoc_sub_UE[CC_id][j]; - } - } else { - nb_rb_temp = nb_rb; - j = 0; - - while ((nb_rb_temp > 0) && (j < N_RBG[CC_id])) { - if (ue_sched_ctrl->rballoc_sub_UE[CC_id][j] == 1) { - ue_template->rballoc_subband[harq_pid][j] = ue_sched_ctrl->rballoc_sub_UE[CC_id][j]; - - if ((j == N_RBG[CC_id] - 1) && ((N_RB_DL[CC_id] == 25) || (N_RB_DL[CC_id] == 50))) { - nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id] + 1; - } else { - nb_rb_temp = nb_rb_temp - min_rb_unit[CC_id]; + if(release_ctrl->flag == 1) { + if(release_ctrl->rnti == rnti) { + for(uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) { + if(release_ctrl->rrc_eNB_mui == rlc_am_mui.rrc_mui[mui_num]) { + release_ctrl->flag = 3; + LOG_D(MAC,"DLSCH Release send:index %d rnti %x mui %d mui_num %d flag 1->3\n", + release_num, + rnti, + rlc_am_mui.rrc_mui[mui_num], + mui_num); + break; + } + } } } - j++; + if(release_ctrl->flag == 2) { + if(release_ctrl->rnti == rnti) { + for (uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) { + if(release_ctrl->rrc_eNB_mui == rlc_am_mui.rrc_mui[mui_num]) { + release_ctrl->flag = 4; + LOG_D(MAC, "DLSCH Release send:index %d rnti %x mui %d mui_num %d flag 2->4\n", + release_num, + rnti, + rlc_am_mui.rrc_mui[mui_num], + mui_num); + break; + } + } + } + } + + if(release_total >= rrc_release_info.num_UEs) + break; + } + + pthread_mutex_unlock(&rrc_release_freelist); + } + + for (ra_ii = 0, ra = &eNB->common_channels[CC_id].ra[0]; ra_ii < NB_RA_PROC_MAX; ra_ii++, ra++) { + if ((ra->rnti == rnti) && (ra->state == MSGCRNTI)) { + for (uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) { + if (ra->crnti_rrc_mui == rlc_am_mui.rrc_mui[mui_num]) { + ra->crnti_harq_pid = harq_pid; + ra->state = MSGCRNTI_ACK; + break; + } + } } } - // decrease mcs until TBS falls below required length - while ((TBS > sdu_length_total + header_length_total + ta_len) && (mcs > 0)) { - mcs--; - TBS = get_TBS_DL(mcs, - nb_rb); - } - - // if we have decreased too much or we don't have enough RBs, increase MCS - while (TBS < sdu_length_total + header_length_total + ta_len && - ((ue_sched_ctrl->dl_pow_off[CC_id] > 0 && mcs < 28) || (ue_sched_ctrl->dl_pow_off[CC_id] == 0 && mcs <= 15))) { - mcs++; - TBS = get_TBS_DL(mcs, - nb_rb); - } - - LOG_D(MAC, "dlsch_mcs before and after the rate matching = (%d, %d)\n", - eNB_UE_stats->dlsch_mcs1, - mcs); -#ifdef DEBUG_eNB_SCHEDULER - LOG_D(MAC, "[eNB %d] CC_id %d Generated DLSCH header (mcs %d, TBS %d, nb_rb %d)\n", - module_idP, - CC_id, - mcs, TBS, - nb_rb); - // msg("[MAC][eNB ] Reminder of DLSCH with random data %d %d %d %d \n", - // TBS, sdu_length_total, offset, TBS-sdu_length_total-offset); -#endif - - if (TBS - header_length_total - sdu_length_total - ta_len <= 2) { - padding = TBS - header_length_total - sdu_length_total - ta_len; - post_padding = 0; - } else { - padding = 0; - post_padding = 1; - } - - offset = generate_dlsch_header((unsigned char *) UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], - num_sdus, //num_sdus - sdu_lengths, // - sdu_lcids, - 255, // no drx - ta_update, // timing advance - NULL, // contention res id - padding, - post_padding); - - //#ifdef DEBUG_eNB_SCHEDULER - if (ta_update != 31) { - LOG_D(MAC, - "[eNB %d][DLSCH] Frame %d Generate header for UE_id %d on CC_id %d: sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d,timing advance value : %d, padding %d,post_padding %d,(mcs %d, TBS %d, nb_rb %d),header_length %d\n", - module_idP, - frameP, - UE_id, - CC_id, - sdu_length_total, - num_sdus, - sdu_lengths[0], - sdu_lcids[0], - offset, - ta_update, - padding, - post_padding, - mcs, - TBS, - nb_rb, - header_length_total); - } - - //#endif -#ifdef DEBUG_eNB_SCHEDULER - LOG_T(MAC, "[eNB %d] First 16 bytes of DLSCH : \n"); - - for (i = 0; i < 16; i++) { - LOG_T(MAC, "%x.", - dlsch_buffer[i]); - } - - LOG_T(MAC, "\n"); -#endif - // cycle through SDUs and place in dlsch_buffer - dlsch_pdu = &UE_list->DLSCH_pdu[CC_id][0][UE_id]; - memcpy(&dlsch_pdu->payload[0][offset], - dlsch_buffer, - sdu_length_total); - // memcpy(RC.mac[0].DLSCH_pdu[0][0].payload[0][offset],dcch_buffer,sdu_lengths[0]); - - // fill remainder of DLSCH with 0 - for (j = 0; j < (TBS - sdu_length_total - offset); j++) { - dlsch_pdu->payload[0][offset + sdu_length_total + j] = 0; - } - - trace_pdu(DIRECTION_DOWNLINK, - (uint8_t *) dlsch_pdu->payload[0], - TBS, - module_idP, - WS_C_RNTI, - UE_RNTI(module_idP, - UE_id), - eNB->frame, - eNB->subframe, - 0, - 0); - T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, + T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP), T_INT(harq_pid), - T_BUFFER(dlsch_pdu->payload[0], - TBS)); - ue_template->nb_rb[harq_pid] = nb_rb; - add_ue_dlsch_info(module_idP, - CC_id, - UE_id, - subframeP, - S_DL_SCHEDULED, - rnti); - // store stats - eNB->eNB_stats[CC_id].dlsch_bytes_tx += sdu_length_total; - eNB->eNB_stats[CC_id].dlsch_pdus_tx += 1; - eNB_UE_stats->rbs_used = nb_rb; - eNB_UE_stats->num_mac_sdu_tx = num_sdus; - eNB_UE_stats->total_rbs_used += nb_rb; - eNB_UE_stats->dlsch_mcs2 = mcs; - eNB_UE_stats->TBS = TBS; - eNB_UE_stats->overhead_bytes = TBS - sdu_length_total; - eNB_UE_stats->total_sdu_bytes += sdu_length_total; - eNB_UE_stats->total_pdu_bytes += TBS; - eNB_UE_stats->total_num_pdus += 1; + T_INT(DCCH), + T_INT(sdu_lengths[0])); + LOG_D(MAC, "[eNB %d][DCCH] CC_id %d Got %d bytes from RLC\n", + module_idP, + CC_id, + sdu_lengths[0]); + sdu_length_total = sdu_lengths[0]; + sdu_lcids[0] = DCCH; + eNB_UE_stats->lcid_sdu[0] = DCCH; + eNB_UE_stats->sdu_length_tx[DCCH] = sdu_lengths[0]; + eNB_UE_stats->num_pdu_tx[DCCH] += 1; + eNB_UE_stats->num_bytes_tx[DCCH] += sdu_lengths[0]; + header_length_last = 1 + 1 + (sdu_lengths[0] >= 128); + header_length_total += header_length_last; + num_sdus = 1; +#ifdef DEBUG_eNB_SCHEDULER + LOG_T(MAC, "[eNB %d][DCCH] CC_id %d Got %d bytes :", + module_idP, + CC_id, + sdu_lengths[0]); - if (cc[CC_id].tdd_Config != NULL) { // TDD - ue_template->DAI++; - update_ul_dci(module_idP, - CC_id, - rnti, - ue_template->DAI, - subframeP); + for (j = 0; j < sdu_lengths[0]; ++j) { + LOG_T(MAC, "%x ", + dlsch_buffer[j]); } - // do PUCCH power control - // this is the snr - // unit is not dBm, it's special from nfapi - // converting to dBm - snr = (5 * ue_sched_ctrl->pucch1_snr[CC_id] - 640) / 10; - target_snr = eNB->puCch10xSnr / 10; - // this assumes accumulated tpc - // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out - int32_t framex10psubframe = ue_template->pucch_tpc_tx_frame * 10 + ue_template->pucch_tpc_tx_subframe; - - if (framex10psubframe + 10 <= (frameP * 10) + subframeP || //normal case - (framex10psubframe > (frameP * 10) + subframeP && 10240 - framex10psubframe + (frameP * 10) + subframeP >= 10)) //frame wrap-around - if (ue_sched_ctrl->pucch1_cqi_update[CC_id] == 1) { - ue_sched_ctrl->pucch1_cqi_update[CC_id] = 0; - ue_template->pucch_tpc_tx_frame = frameP; - ue_template->pucch_tpc_tx_subframe = subframeP; - - if (snr > target_snr + 4) { - tpc = 0; //-1 - } else if (snr < target_snr - 4) { - tpc = 2; //+1 - } else { - tpc = 1; //0 - } - - LOG_D(MAC, "[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, snr/target snr %d/%d (normal case)\n", - module_idP, - frameP, - subframeP, - harq_pid, - tpc, - snr, - target_snr); - } // Po_PUCCH has been updated - else { - tpc = 1; //0 - } // time to do TPC update - else { - tpc = 1; //0 - } - - dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; - memset((void *) dl_config_pdu, - 0, - sizeof(nfapi_dl_config_request_pdu_t)); - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; - dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu)); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = - get_aggregation(get_bw_index(module_idP, - CC_id), - ue_sched_ctrl->dl_cqi[CC_id], - format1); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // CRNTI : see Table 4-10 from SCF082 - nFAPI specifications - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = harq_pid; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = tpc; // dont adjust power when retransmitting - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 1 - ue_template->oldNDI[harq_pid]; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = mcs; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 0; - //deactivate second codeword - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_2 = 0; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_2 = 1; - - if (cc[CC_id].tdd_Config != NULL) { //TDD - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.downlink_assignment_index = (ue_template->DAI - 1) & 3; - LOG_D(MAC, "[eNB %d] Initial transmission CC_id %d : harq_pid %d, dai %d, mcs %d\n", - module_idP, - CC_id, - harq_pid, - (ue_template->DAI - 1), - mcs); - } else { - LOG_D(MAC, "[eNB %d] Initial transmission CC_id %d : harq_pid %d, mcs %d\n", - module_idP, - CC_id, - harq_pid, - mcs); - } - - LOG_D(MAC, "Checking feasibility pdu %d (new sdu)\n", - dl_req->number_pdu); - - if (!CCE_allocation_infeasible(module_idP, - CC_id, - 1, - subframeP, - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, - rnti)) { - ue_sched_ctrl->round[CC_id][harq_pid] = 0; - dl_req->number_dci++; - dl_req->number_pdu++; - dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG; - eNB->DL_req[CC_id].sfn_sf = frameP << 4 | subframeP; - eNB->DL_req[CC_id].header.message_id = NFAPI_DL_CONFIG_REQUEST; - /* CDRX */ - ue_sched_ctrl->harq_rtt_timer[CC_id][harq_pid] = 1; // restart HARQ RTT timer - - if (ue_sched_ctrl->cdrx_configured) { - ue_sched_ctrl->drx_inactivity_timer = 1; // restart drx inactivity timer when new transmission - ue_sched_ctrl->drx_retransmission_timer[harq_pid] = 0; // stop drx retransmission - /* - * Note: contrary to the spec drx_retransmission_timer[harq_pid] is reset not stop. - */ - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_INACTIVITY, (unsigned long) ue_sched_ctrl->drx_inactivity_timer); - - if (harq_pid == 0) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_RETRANSMISSION_HARQ0, (unsigned long) ue_sched_ctrl->drx_retransmission_timer[0]); - } - } - - // Toggle NDI for next time - LOG_D(MAC, "CC_id %d Frame %d, subframeP %d: Toggling Format1 NDI for UE %d (rnti %x/%d) oldNDI %d\n", - CC_id, - frameP, - subframeP, - UE_id, - rnti, - harq_pid, - ue_template->oldNDI[harq_pid]); - ue_template->oldNDI[harq_pid] = 1 - ue_template->oldNDI[harq_pid]; - ue_template->oldmcs1[harq_pid] = mcs; - ue_template->oldmcs2[harq_pid] = 0; - AssertFatal(ue_template->physicalConfigDedicated != NULL, "physicalConfigDedicated is NULL\n"); - AssertFatal(ue_template->physicalConfigDedicated->pdsch_ConfigDedicated != NULL, - "physicalConfigDedicated->pdsch_ConfigDedicated is NULL\n"); - fill_nfapi_dlsch_config(eNB, - dl_req, - TBS, - eNB->pdu_index[CC_id], - rnti, - 0, // type 0 allocation from 7.1.6 in 36.213 - 0, // virtual_resource_block_assignment_flag, unused here - 0, // resource_block_coding, to be filled in later - getQm(mcs), - 0, // redundancy version - 1, // transport blocks - 0, // transport block to codeword swap flag - cc[CC_id].p_eNB == 1 ? 0 : 1, // transmission_scheme - 1, // number of layers - 1, // number of subbands - // uint8_t codebook_index, - 4, // UE category capacity - ue_template->physicalConfigDedicated->pdsch_ConfigDedicated->p_a, - 0, // delta_power_offset for TM5 - 0, // ngap - 0, // nprb - cc[CC_id].p_eNB == 1 ? 1 : 2, // transmission mode - 0, //number of PRBs treated as one subband, not used here - 0); // number of beamforming vectors, not used here - eNB->TX_req[CC_id].sfn_sf = fill_nfapi_tx_req(&eNB->TX_req[CC_id].tx_request_body, - (frameP * 10) + subframeP, - TBS, - eNB->pdu_index[CC_id], - dlsch_pdu->payload[0]); - LOG_D(MAC, "Filled NFAPI configuration for DCI/DLSCH/TXREQ %d, new SDU\n", - eNB->pdu_index[CC_id]); - eNB->pdu_index[CC_id]++; - program_dlsch_acknak(module_idP, - CC_id, - UE_id, - frameP, - subframeP, - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx); - } else { - LOG_W(MAC, "Frame %d, Subframe %d: Dropping DLSCH allocation for UE %d/%x, infeasible CCE allocations\n", - frameP, - subframeP, - UE_id, - rnti); - } - } else { // There is no data from RLC or MAC header, so don't schedule + LOG_T(MAC, "\n"); +#endif } } - if (cc[CC_id].tdd_Config != NULL) { // TDD - set_ul_DAI(module_idP, - UE_id, - CC_id, - frameP, - subframeP); + // RLC data on DCCH1 + if (TBS - ta_len - header_length_total - sdu_length_total - 3 > 0) { + rlc_status = mac_rlc_status_ind(module_idP, + rnti, + module_idP, + frameP, + subframeP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + DCCH + 1, + TBS - ta_len - header_length_total - sdu_length_total - 3, + 0, + 0 + ); + // DCCH SDU + sdu_lengths[num_sdus] = 0; + + if (rlc_status.bytes_in_buffer > 0) { + LOG_D(MAC, "[eNB %d], Frame %d, DCCH1->DLSCH, CC_id %d, Requesting %d bytes from RLC (RRC message)\n", + module_idP, frameP, CC_id, + TBS - ta_len - header_length_total - sdu_length_total - 3); + sdu_lengths[num_sdus] += mac_rlc_data_req(module_idP, + rnti, + module_idP, + frameP, + ENB_FLAG_YES, + MBMS_FLAG_NO, DCCH + 1, + TBS, //not used + (char *) &dlsch_buffer[sdu_length_total], + 0, + 0 + ); + T(T_ENB_MAC_UE_DL_SDU, + T_INT(module_idP), + T_INT(CC_id), + T_INT(rnti), + T_INT(frameP), + T_INT(subframeP), + T_INT(harq_pid), + T_INT(DCCH + 1), + T_INT(sdu_lengths[num_sdus])); + sdu_lcids[num_sdus] = DCCH1; + sdu_length_total += sdu_lengths[num_sdus]; + eNB_UE_stats->lcid_sdu[num_sdus] = DCCH1; + eNB_UE_stats->sdu_length_tx[DCCH1] = sdu_lengths[num_sdus]; + eNB_UE_stats->num_pdu_tx[DCCH1] += 1; + eNB_UE_stats->num_bytes_tx[DCCH1] += sdu_lengths[num_sdus]; + header_length_last = 1 + 1 + (sdu_lengths[num_sdus] >= 128); + header_length_total += header_length_last; + num_sdus++; +#ifdef DEBUG_eNB_SCHEDULER + LOG_T(MAC, "[eNB %d][DCCH1] CC_id %d Got %d bytes :", + module_idP, + CC_id, + sdu_lengths[num_sdus]); + + for (j = 0; j < sdu_lengths[num_sdus]; ++j) { + LOG_T(MAC, "%x ", + dlsch_buffer[j]); + } + + LOG_T(MAC, "\n"); +#endif + } } - } // UE_id loop - } // CC_id loop + + // TODO: lcid has to be sorted before the actual allocation (similar struct as ue_list). + for (lcid = NB_RB_MAX - 1; lcid >= DTCH; lcid--) { + // TODO: check if the lcid is active + LOG_D(MAC, "[eNB %d], Frame %d, DTCH%d->DLSCH, Checking RLC status (tbs %d, len %d)\n", + module_idP, + frameP, + lcid, + TBS, + TBS - ta_len - header_length_total - sdu_length_total - 3); + + if (TBS - ta_len - header_length_total - sdu_length_total - 3 > 0) { + rlc_status = mac_rlc_status_ind(module_idP, + rnti, + module_idP, + frameP, + subframeP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + lcid, + TBS - ta_len - header_length_total - sdu_length_total - 3, 0, 0 + ); + + if (rlc_status.bytes_in_buffer > 0) { + LOG_D(MAC, "[eNB %d][USER-PLANE DEFAULT DRB] Frame %d : DTCH->DLSCH, Requesting %d bytes from RLC (lcid %d total hdr len %d)\n", + module_idP, + frameP, + TBS - ta_len - header_length_total - sdu_length_total - 3, + lcid, + header_length_total); + sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, + rnti, + module_idP, + frameP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + lcid, + TBS, //not used + (char *) &dlsch_buffer[sdu_length_total], + 0, + 0 + ); + T(T_ENB_MAC_UE_DL_SDU, + T_INT(module_idP), + T_INT(CC_id), + T_INT(rnti), + T_INT(frameP), + T_INT(subframeP), + T_INT(harq_pid), + T_INT(lcid), + T_INT(sdu_lengths[num_sdus])); + LOG_D(MAC, "[eNB %d][USER-PLANE DEFAULT DRB] Got %d bytes for DTCH %d \n", + module_idP, + sdu_lengths[num_sdus], + lcid); + sdu_lcids[num_sdus] = lcid; + sdu_length_total += sdu_lengths[num_sdus]; + eNB_UE_stats->num_pdu_tx[lcid]++; + eNB_UE_stats->lcid_sdu[num_sdus] = lcid; + eNB_UE_stats->sdu_length_tx[lcid] = sdu_lengths[num_sdus]; + eNB_UE_stats->num_bytes_tx[lcid] += sdu_lengths[num_sdus]; + header_length_last = 1 + 1 + (sdu_lengths[num_sdus] >= 128); + header_length_total += header_length_last; + num_sdus++; + ue_sched_ctrl->uplane_inactivity_timer = 0; + // reset RRC inactivity timer after uplane activity + ue_contextP = rrc_eNB_get_ue_context(RC.rrc[module_idP], rnti); + + if (ue_contextP != NULL) { + ue_contextP->ue_context.ue_rrc_inactivity_timer = 1; + } else { + LOG_E(MAC, "[eNB %d] CC_id %d Couldn't find the context associated to UE (RNTI %d) and reset RRC inactivity timer\n", + module_idP, + CC_id, + rnti); + } + } // end if (rlc_status.bytes_in_buffer > 0) + } else { // no TBS left + break; // break for (lcid = NB_RB_MAX - 1; lcid >= DTCH; lcid--) + } + } + + /* Last header does not have length field */ + if (header_length_total) { + header_length_total -= header_length_last; + header_length_total++; + } + + // there is at least one SDU or TA command + // if (num_sdus > 0 ){ + if (ta_len + sdu_length_total + header_length_total > 0) { + // Now compute number of required RBs for total sdu length + // Assume RAH format 2 + mcs = eNB_UE_stats->dlsch_mcs1; + + if (mcs == 0) { + nb_rb = 4; // don't let the TBS get too small + } else { + nb_rb = min_rb_unit; + } + + TBS = get_TBS_DL(mcs, nb_rb); + + while (TBS < sdu_length_total + header_length_total + ta_len) { + nb_rb += min_rb_unit; // + + if (nb_rb > nb_available_rb) { // if we've gone beyond the maximum number of RBs + // (can happen if N_RB_DL is odd) + TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, + nb_available_rb); + nb_rb = nb_available_rb; + break; + } + + TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, + nb_rb); + } + + if (nb_rb == ue_sched_ctrl->pre_nb_available_rbs[CC_id]) { + for (j = 0; j < N_RBG; ++j) { // for indicating the rballoc for each sub-band + ue_template->rballoc_subband[harq_pid][j] = ue_sched_ctrl->rballoc_sub_UE[CC_id][j]; + } + } else { + nb_rb_temp = nb_rb; + j = 0; + + while ((nb_rb_temp > 0) && (j < N_RBG)) { + if (ue_sched_ctrl->rballoc_sub_UE[CC_id][j] == 1) { + ue_template->rballoc_subband[harq_pid][j] = ue_sched_ctrl->rballoc_sub_UE[CC_id][j]; + + if ((j == N_RBG - 1) && ((N_RB_DL == 25) || (N_RB_DL == 50))) { + nb_rb_temp = nb_rb_temp - min_rb_unit + 1; + } else { + nb_rb_temp = nb_rb_temp - min_rb_unit; + } + } + + j++; + } + } + + // decrease mcs until TBS falls below required length + while ((TBS > sdu_length_total + header_length_total + ta_len) && (mcs > 0)) { + mcs--; + TBS = get_TBS_DL(mcs, + nb_rb); + } + + // if we have decreased too much or we don't have enough RBs, increase MCS + while (TBS < sdu_length_total + header_length_total + ta_len && + ((ue_sched_ctrl->dl_pow_off[CC_id] > 0 && mcs < 28) || (ue_sched_ctrl->dl_pow_off[CC_id] == 0 && mcs <= 15))) { + mcs++; + TBS = get_TBS_DL(mcs, + nb_rb); + } + + LOG_D(MAC, "dlsch_mcs before and after the rate matching = (%d, %d)\n", + eNB_UE_stats->dlsch_mcs1, + mcs); +#ifdef DEBUG_eNB_SCHEDULER + LOG_D(MAC, "[eNB %d] CC_id %d Generated DLSCH header (mcs %d, TBS %d, nb_rb %d)\n", + module_idP, + CC_id, + mcs, TBS, + nb_rb); + // msg("[MAC][eNB ] Reminder of DLSCH with random data %d %d %d %d \n", + // TBS, sdu_length_total, offset, TBS-sdu_length_total-offset); +#endif + + if (TBS - header_length_total - sdu_length_total - ta_len <= 2) { + padding = TBS - header_length_total - sdu_length_total - ta_len; + post_padding = 0; + } else { + padding = 0; + post_padding = 1; + } + + offset = generate_dlsch_header((unsigned char *) UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], + num_sdus, //num_sdus + sdu_lengths, // + sdu_lcids, + 255, // no drx + ta_update, // timing advance + NULL, // contention res id + padding, + post_padding); + + //#ifdef DEBUG_eNB_SCHEDULER + if (ta_update != 31) { + LOG_D(MAC, + "[eNB %d][DLSCH] Frame %d Generate header for UE_id %d on CC_id %d: sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d,timing advance value : %d, padding %d,post_padding %d,(mcs %d, TBS %d, nb_rb %d),header_length %d\n", + module_idP, + frameP, + UE_id, + CC_id, + sdu_length_total, + num_sdus, + sdu_lengths[0], + sdu_lcids[0], + offset, + ta_update, + padding, + post_padding, + mcs, + TBS, + nb_rb, + header_length_total); + } + + //#endif +#ifdef DEBUG_eNB_SCHEDULER + LOG_T(MAC, "[eNB %d] First 16 bytes of DLSCH : \n"); + + for (int i = 0; i < 16; i++) { + LOG_T(MAC, "%x.", + dlsch_buffer[i]); + } + + LOG_T(MAC, "\n"); +#endif + // cycle through SDUs and place in dlsch_buffer + dlsch_pdu = &UE_list->DLSCH_pdu[CC_id][0][UE_id]; + memcpy(&dlsch_pdu->payload[0][offset], + dlsch_buffer, + sdu_length_total); + // memcpy(RC.mac[0].DLSCH_pdu[0][0].payload[0][offset],dcch_buffer,sdu_lengths[0]); + + // fill remainder of DLSCH with 0 + for (j = 0; j < (TBS - sdu_length_total - offset); j++) { + dlsch_pdu->payload[0][offset + sdu_length_total + j] = 0; + } + + trace_pdu(DIRECTION_DOWNLINK, + (uint8_t *) dlsch_pdu->payload[0], + TBS, + module_idP, + WS_C_RNTI, + UE_RNTI(module_idP, + UE_id), + eNB->frame, + eNB->subframe, + 0, + 0); + T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, + T_INT(module_idP), + T_INT(CC_id), + T_INT(rnti), + T_INT(frameP), + T_INT(subframeP), + T_INT(harq_pid), + T_BUFFER(dlsch_pdu->payload[0], + TBS)); + ue_template->nb_rb[harq_pid] = nb_rb; + add_ue_dlsch_info(module_idP, + CC_id, + UE_id, + subframeP, + S_DL_SCHEDULED, + rnti); + // store stats + eNB->eNB_stats[CC_id].dlsch_bytes_tx += sdu_length_total; + eNB->eNB_stats[CC_id].dlsch_pdus_tx += 1; + eNB_UE_stats->rbs_used = nb_rb; + eNB_UE_stats->num_mac_sdu_tx = num_sdus; + eNB_UE_stats->total_rbs_used += nb_rb; + eNB_UE_stats->dlsch_mcs2 = mcs; + eNB_UE_stats->TBS = TBS; + eNB_UE_stats->overhead_bytes = TBS - sdu_length_total; + eNB_UE_stats->total_sdu_bytes += sdu_length_total; + eNB_UE_stats->total_pdu_bytes += TBS; + eNB_UE_stats->total_num_pdus += 1; + + if (cc[CC_id].tdd_Config != NULL) { // TDD + ue_template->DAI++; + update_ul_dci(module_idP, + CC_id, + rnti, + ue_template->DAI, + subframeP); + } + + // do PUCCH power control + // this is the snr + // unit is not dBm, it's special from nfapi + // converting to dBm + snr = (5 * ue_sched_ctrl->pucch1_snr[CC_id] - 640) / 10; + target_snr = eNB->puCch10xSnr / 10; + // this assumes accumulated tpc + // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out + int32_t framex10psubframe = ue_template->pucch_tpc_tx_frame * 10 + ue_template->pucch_tpc_tx_subframe; + + if (framex10psubframe + 10 <= (frameP * 10) + subframeP || //normal case + (framex10psubframe > (frameP * 10) + subframeP && 10240 - framex10psubframe + (frameP * 10) + subframeP >= 10)) //frame wrap-around + if (ue_sched_ctrl->pucch1_cqi_update[CC_id] == 1) { + ue_sched_ctrl->pucch1_cqi_update[CC_id] = 0; + ue_template->pucch_tpc_tx_frame = frameP; + ue_template->pucch_tpc_tx_subframe = subframeP; + + if (snr > target_snr + 4) { + tpc = 0; //-1 + } else if (snr < target_snr - 4) { + tpc = 2; //+1 + } else { + tpc = 1; //0 + } + + LOG_D(MAC, "[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, snr/target snr %d/%d (normal case)\n", + module_idP, + frameP, + subframeP, + harq_pid, + tpc, + snr, + target_snr); + } // Po_PUCCH has been updated + else { + tpc = 1; //0 + } // time to do TPC update + else { + tpc = 1; //0 + } + + dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + memset((void *) dl_config_pdu, + 0, + sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; + dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu)); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = + get_aggregation(get_bw_index(module_idP, + CC_id), + ue_sched_ctrl->dl_cqi[CC_id], + format1); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // CRNTI : see Table 4-10 from SCF082 - nFAPI specifications + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = harq_pid; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = tpc; // dont adjust power when retransmitting + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 1 - ue_template->oldNDI[harq_pid]; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = mcs; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 0; + //deactivate second codeword + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_2 = 0; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_2 = 1; + + if (cc[CC_id].tdd_Config != NULL) { //TDD + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.downlink_assignment_index = (ue_template->DAI - 1) & 3; + LOG_D(MAC, "[eNB %d] Initial transmission CC_id %d : harq_pid %d, dai %d, mcs %d\n", + module_idP, + CC_id, + harq_pid, + (ue_template->DAI - 1), + mcs); + } else { + LOG_D(MAC, "[eNB %d] Initial transmission CC_id %d : harq_pid %d, mcs %d\n", + module_idP, + CC_id, + harq_pid, + mcs); + } + + LOG_D(MAC, "Checking feasibility pdu %d (new sdu)\n", + dl_req->number_pdu); + + if (!CCE_allocation_infeasible(module_idP, + CC_id, + 1, + subframeP, + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, + rnti)) { + ue_sched_ctrl->round[CC_id][harq_pid] = 0; + dl_req->number_dci++; + dl_req->number_pdu++; + dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG; + eNB->DL_req[CC_id].sfn_sf = frameP << 4 | subframeP; + eNB->DL_req[CC_id].header.message_id = NFAPI_DL_CONFIG_REQUEST; + /* CDRX */ + ue_sched_ctrl->harq_rtt_timer[CC_id][harq_pid] = 1; // restart HARQ RTT timer + + if (ue_sched_ctrl->cdrx_configured) { + ue_sched_ctrl->drx_inactivity_timer = 1; // restart drx inactivity timer when new transmission + ue_sched_ctrl->drx_retransmission_timer[harq_pid] = 0; // stop drx retransmission + /* + * Note: contrary to the spec drx_retransmission_timer[harq_pid] is reset not stop. + */ + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_INACTIVITY, (unsigned long) ue_sched_ctrl->drx_inactivity_timer); + + if (harq_pid == 0) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_RETRANSMISSION_HARQ0, (unsigned long) ue_sched_ctrl->drx_retransmission_timer[0]); + } + } + + // Toggle NDI for next time + LOG_D(MAC, "CC_id %d Frame %d, subframeP %d: Toggling Format1 NDI for UE %d (rnti %x/%d) oldNDI %d\n", + CC_id, + frameP, + subframeP, + UE_id, + rnti, + harq_pid, + ue_template->oldNDI[harq_pid]); + ue_template->oldNDI[harq_pid] = 1 - ue_template->oldNDI[harq_pid]; + ue_template->oldmcs1[harq_pid] = mcs; + ue_template->oldmcs2[harq_pid] = 0; + AssertFatal(ue_template->physicalConfigDedicated != NULL, "physicalConfigDedicated is NULL\n"); + AssertFatal(ue_template->physicalConfigDedicated->pdsch_ConfigDedicated != NULL, + "physicalConfigDedicated->pdsch_ConfigDedicated is NULL\n"); + fill_nfapi_dlsch_config(eNB, + dl_req, + TBS, + eNB->pdu_index[CC_id], + rnti, + 0, // type 0 allocation from 7.1.6 in 36.213 + 0, // virtual_resource_block_assignment_flag, unused here + 0, // resource_block_coding, to be filled in later + getQm(mcs), + 0, // redundancy version + 1, // transport blocks + 0, // transport block to codeword swap flag + cc[CC_id].p_eNB == 1 ? 0 : 1, // transmission_scheme + 1, // number of layers + 1, // number of subbands + // uint8_t codebook_index, + 4, // UE category capacity + ue_template->physicalConfigDedicated->pdsch_ConfigDedicated->p_a, + 0, // delta_power_offset for TM5 + 0, // ngap + 0, // nprb + cc[CC_id].p_eNB == 1 ? 1 : 2, // transmission mode + 0, //number of PRBs treated as one subband, not used here + 0); // number of beamforming vectors, not used here + eNB->TX_req[CC_id].sfn_sf = fill_nfapi_tx_req(&eNB->TX_req[CC_id].tx_request_body, + (frameP * 10) + subframeP, + TBS, + eNB->pdu_index[CC_id], + dlsch_pdu->payload[0]); + LOG_D(MAC, "Filled NFAPI configuration for DCI/DLSCH/TXREQ %d, new SDU\n", + eNB->pdu_index[CC_id]); + eNB->pdu_index[CC_id]++; + program_dlsch_acknak(module_idP, + CC_id, + UE_id, + frameP, + subframeP, + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx); + } else { + LOG_W(MAC, "Frame %d, Subframe %d: Dropping DLSCH allocation for UE %d/%x, infeasible CCE allocations\n", + frameP, + subframeP, + UE_id, + rnti); + } + } else { // There is no data from RLC or MAC header, so don't schedule + } + } + + if (cc[CC_id].tdd_Config != NULL) { // TDD + set_ul_DAI(module_idP, + UE_id, + CC_id, + frameP, + subframeP); + } + } // UE_id loop fill_DLSCH_dci(module_idP, frameP, diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index 476fb68584..23aa03ca8b 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -156,8 +156,11 @@ void fill_DLSCH_dci(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,i void schedule_dlsch(module_id_t module_idP, frame_t frameP, sub_frame_t subframe, int *mbsfn_flag); -void schedule_ue_spec(module_id_t module_idP, int slice_idxP, - frame_t frameP,sub_frame_t subframe, int *mbsfn_flag); +void schedule_ue_spec(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t subframe, + int *mbsfn_flag); void schedule_ue_spec_br(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP); From cd480271af373f265f069962ba380db2b98a3c7a Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 16 Jan 2020 15:35:27 +0100 Subject: [PATCH 104/240] Remove everything related to TM5 in pre_processor --- openair2/LAYER2/MAC/pre_processor.c | 378 ---------------------------- 1 file changed, 378 deletions(-) diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index bd4e4de2a4..b5a0a350ac 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -763,9 +763,6 @@ void dlsch_scheduler_pre_processor_positioning(module_id_t Mod_id, uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]) { int UE_id, CC_id; int i; -#ifdef TM5 - uint8_t transmission_mode; -#endif uint8_t slice_allocation_mask[NFAPI_CC_MAX][N_RBG_MAX]; int N_RBG[NFAPI_CC_MAX]; UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; @@ -787,9 +784,6 @@ void dlsch_scheduler_pre_processor_positioning(module_id_t Mod_id, for (i = 0; i < UE_num_active_CC(UE_list, UE_id); i++) { CC_id = UE_list->ordered_CCids[i][UE_id]; nb_rbs_remaining[CC_id][UE_id] = nb_rbs_accounted[CC_id][UE_id]; -#ifdef TM5 - transmission_mode = get_tmode(Mod_id, CC_id, UE_id); -#endif if (nb_rbs_required[CC_id][UE_id] > 0) LOG_D(MAC, @@ -814,162 +808,6 @@ void dlsch_scheduler_pre_processor_positioning(module_id_t Mod_id, rballoc_sub, slice_allocation_mask, MIMO_mode_indicator); -#ifdef TM5 - - // data chanel TM5: to be revisited - if ((round == 0) && - (transmission_mode == 5) && - (ue_sched_ctl->dl_pow_off[CC_id] != 1)) { - for (j = 0; j < N_RBG[CC_id]; j += 2) { - if ((((j == (N_RBG[CC_id] - 1)) - && (rballoc_sub[CC_id][j] == 0) - && (ue_sched_ctl-> - rballoc_sub_UE[CC_id][j] == 0)) - || ((j < (N_RBG[CC_id] - 1)) - && (rballoc_sub[CC_id][j + 1] == 0) - && - (ue_sched_ctl->rballoc_sub_UE - [CC_id][j + 1] == 0))) - && (nb_rbs_remaining[CC_id][UE_id] - > 0)) { - for (i = UE_list->next[UE_id + 1]; i >= 0; - i = UE_list->next[i]) { - UE_id2 = i; - rnti2 = UE_RNTI(Mod_id, UE_id2); - ue_sched_ctl2 = - &UE_list->UE_sched_ctrl[UE_id2]; - round2 = ue_sched_ctl2->round[CC_id]; - - if (rnti2 == NOT_A_RNTI) - continue; - - if (UE_list-> - UE_sched_ctrl - [UE_id2].ul_out_of_sync == 1) - continue; - - eNB_UE_stats2 = - UE_list-> - eNB_UE_stats[CC_id][UE_id2]; - //mac_xface->get_ue_active_harq_pid(Mod_id,CC_id,rnti2,frameP,subframeP,&harq_pid2,&round2,0); - - if ((mac_eNB_get_rrc_status - (Mod_id, - rnti2) >= RRC_RECONFIGURED) - && (round2 == 0) - && - (get_tmode(Mod_id, CC_id, UE_id2) - == 5) - && (ue_sched_ctl-> - dl_pow_off[CC_id] != 1)) { - if ((((j == (N_RBG[CC_id] - 1)) - && - (ue_sched_ctl->rballoc_sub_UE - [CC_id][j] == 0)) - || ((j < (N_RBG[CC_id] - 1)) - && - (ue_sched_ctl-> - rballoc_sub_UE[CC_id][j + - 1] - == 0))) - && - (nb_rbs_remaining - [CC_id] - [UE_id2] > 0)) { - if ((((eNB_UE_stats2-> - DL_pmi_single ^ - eNB_UE_stats1-> - DL_pmi_single) - << (14 - j)) & 0xc000) == 0x4000) { //MU-MIMO only for 25 RBs configuration - rballoc_sub[CC_id][j] = 1; - ue_sched_ctl-> - rballoc_sub_UE[CC_id] - [j] = 1; - ue_sched_ctl2-> - rballoc_sub_UE[CC_id] - [j] = 1; - MIMO_mode_indicator[CC_id] - [j] = 0; - - if (j < N_RBG[CC_id] - 1) { - rballoc_sub[CC_id][j + - 1] = - 1; - ue_sched_ctl-> - rballoc_sub_UE - [CC_id][j + 1] = 1; - ue_sched_ctl2->rballoc_sub_UE - [CC_id][j + 1] = 1; - MIMO_mode_indicator - [CC_id][j + 1] - = 0; - } - - ue_sched_ctl-> - dl_pow_off[CC_id] - = 0; - ue_sched_ctl2-> - dl_pow_off[CC_id] - = 0; - - if ((j == N_RBG[CC_id] - 1) - && ((N_RB_DL == 25) - || (N_RB_DL == - 50))) { - nb_rbs_remaining - [CC_id][UE_id] = - nb_rbs_remaining - [CC_id][UE_id] - - min_rb_unit[CC_id] - + 1; - ue_sched_ctl->pre_nb_available_rbs - [CC_id] = - ue_sched_ctl->pre_nb_available_rbs - [CC_id] + - min_rb_unit[CC_id] - - 1; - nb_rbs_remaining - [CC_id][UE_id2] = - nb_rbs_remaining - [CC_id][UE_id2] - - min_rb_unit[CC_id] - + 1; - ue_sched_ctl2->pre_nb_available_rbs - [CC_id] = - ue_sched_ctl2->pre_nb_available_rbs - [CC_id] + - min_rb_unit[CC_id] - - 1; - } else { - nb_rbs_remaining - [CC_id][UE_id] = - nb_rbs_remaining - [CC_id][UE_id] - 4; - ue_sched_ctl->pre_nb_available_rbs - [CC_id] = - ue_sched_ctl->pre_nb_available_rbs - [CC_id] + 4; - nb_rbs_remaining - [CC_id][UE_id2] = - nb_rbs_remaining - [CC_id][UE_id2] - - 4; - ue_sched_ctl2->pre_nb_available_rbs - [CC_id] = - ue_sched_ctl2->pre_nb_available_rbs - [CC_id] + 4; - } - - break; - } - } - } - } - } - } - } - -#endif } } } @@ -984,9 +822,6 @@ void dlsch_scheduler_pre_processor_intraslice_sharing(module_id_t Mod_id, uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]) { int UE_id, CC_id; int i; -#ifdef TM5 - uint8_t transmission_mode; -#endif UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; int N_RBG[NFAPI_CC_MAX]; slice_info_t *sli = &RC.mac[Mod_id]->slice_info; @@ -1014,10 +849,6 @@ void dlsch_scheduler_pre_processor_intraslice_sharing(module_id_t Mod_id, if (nb_rbs_remaining[CC_id][UE_id] < 0) abort(); -#ifdef TM5 - transmission_mode = get_tmode(Mod_id, CC_id, UE_id); -#endif - if (nb_rbs_required[CC_id][UE_id] > 0) LOG_D(MAC, "Step 2: nb_rbs_remaining[%d][%d]= %d (accounted %d, required %d, pre_nb_available_rbs %d, N_RBG %d, rb_unit %d)\n", @@ -1041,162 +872,6 @@ void dlsch_scheduler_pre_processor_intraslice_sharing(module_id_t Mod_id, rballoc_sub, slice_allocation_mask, MIMO_mode_indicator); -#ifdef TM5 - - // data chanel TM5: to be revisited - if ((round == 0) && - (transmission_mode == 5) && - (ue_sched_ctl->dl_pow_off[CC_id] != 1)) { - for (j = 0; j < N_RBG[CC_id]; j += 2) { - if ((((j == (N_RBG[CC_id] - 1)) - && (rballoc_sub[CC_id][j] == 0) - && (ue_sched_ctl-> - rballoc_sub_UE[CC_id][j] == 0)) - || ((j < (N_RBG[CC_id] - 1)) - && (rballoc_sub[CC_id][j + 1] == 0) - && - (ue_sched_ctl->rballoc_sub_UE - [CC_id][j + 1] == 0))) - && (nb_rbs_remaining[CC_id][UE_id] - > 0)) { - for (i = UE_list->next[UE_id + 1]; i >= 0; - i = UE_list->next[i]) { - UE_id2 = i; - rnti2 = UE_RNTI(Mod_id, UE_id2); - ue_sched_ctl2 = - &UE_list->UE_sched_ctrl[UE_id2]; - round2 = ue_sched_ctl2->round[CC_id]; - - if (rnti2 == NOT_A_RNTI) - continue; - - if (UE_list-> - UE_sched_ctrl - [UE_id2].ul_out_of_sync == 1) - continue; - - eNB_UE_stats2 = - UE_list-> - eNB_UE_stats[CC_id][UE_id2]; - //mac_xface->get_ue_active_harq_pid(Mod_id,CC_id,rnti2,frameP,subframeP,&harq_pid2,&round2,0); - - if ((mac_eNB_get_rrc_status - (Mod_id, - rnti2) >= RRC_RECONFIGURED) - && (round2 == 0) - && - (get_tmode(Mod_id, CC_id, UE_id2) - == 5) - && (ue_sched_ctl-> - dl_pow_off[CC_id] != 1)) { - if ((((j == (N_RBG[CC_id] - 1)) - && - (ue_sched_ctl->rballoc_sub_UE - [CC_id][j] == 0)) - || ((j < (N_RBG[CC_id] - 1)) - && - (ue_sched_ctl-> - rballoc_sub_UE[CC_id][j + - 1] - == 0))) - && - (nb_rbs_remaining - [CC_id] - [UE_id2] > 0)) { - if ((((eNB_UE_stats2-> - DL_pmi_single ^ - eNB_UE_stats1-> - DL_pmi_single) - << (14 - j)) & 0xc000) == 0x4000) { //MU-MIMO only for 25 RBs configuration - rballoc_sub[CC_id][j] = 1; - ue_sched_ctl-> - rballoc_sub_UE[CC_id] - [j] = 1; - ue_sched_ctl2-> - rballoc_sub_UE[CC_id] - [j] = 1; - MIMO_mode_indicator[CC_id] - [j] = 0; - - if (j < N_RBG[CC_id] - 1) { - rballoc_sub[CC_id][j + - 1] = - 1; - ue_sched_ctl-> - rballoc_sub_UE - [CC_id][j + 1] = 1; - ue_sched_ctl2->rballoc_sub_UE - [CC_id][j + 1] = 1; - MIMO_mode_indicator - [CC_id][j + 1] - = 0; - } - - ue_sched_ctl-> - dl_pow_off[CC_id] - = 0; - ue_sched_ctl2-> - dl_pow_off[CC_id] - = 0; - - if ((j == N_RBG[CC_id] - 1) - && ((N_RB_DL == 25) - || (N_RB_DL == - 50))) { - nb_rbs_remaining - [CC_id][UE_id] = - nb_rbs_remaining - [CC_id][UE_id] - - min_rb_unit[CC_id] - + 1; - ue_sched_ctl->pre_nb_available_rbs - [CC_id] = - ue_sched_ctl->pre_nb_available_rbs - [CC_id] + - min_rb_unit[CC_id] - - 1; - nb_rbs_remaining - [CC_id][UE_id2] = - nb_rbs_remaining - [CC_id][UE_id2] - - min_rb_unit[CC_id] - + 1; - ue_sched_ctl2->pre_nb_available_rbs - [CC_id] = - ue_sched_ctl2->pre_nb_available_rbs - [CC_id] + - min_rb_unit[CC_id] - - 1; - } else { - nb_rbs_remaining - [CC_id][UE_id] = - nb_rbs_remaining - [CC_id][UE_id] - 4; - ue_sched_ctl->pre_nb_available_rbs - [CC_id] = - ue_sched_ctl->pre_nb_available_rbs - [CC_id] + 4; - nb_rbs_remaining - [CC_id][UE_id2] = - nb_rbs_remaining - [CC_id][UE_id2] - - 4; - ue_sched_ctl2->pre_nb_available_rbs - [CC_id] = - ue_sched_ctl2->pre_nb_available_rbs - [CC_id] + 4; - } - - break; - } - } - } - } - } - } - } - -#endif } } } @@ -1222,16 +897,6 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, UE_list_t *UE_list = &eNB->UE_list; UE_sched_ctrl_t *ue_sched_ctl; // int rrc_status = RRC_IDLE; -#ifdef TM5 - int harq_pid1 = 0; - int round1 = 0, round2 = 0; - int UE_id2; - uint16_t i1, i2, i3; - rnti_t rnti1, rnti2; - LTE_eNB_UE_stats *eNB_UE_stats1 = NULL; - LTE_eNB_UE_stats *eNB_UE_stats2 = NULL; - 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])); // FIXME: After the memset above, some of the resets in reset() are redundant @@ -1295,40 +960,6 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, MIMO_mode_indicator); } -#ifdef TM5 - - // This has to be revisited!!!! - for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_id]; CC_id++) { - COMMON_channels_t *cc = &eNB->common_channels[CC_id]; - int N_RBG = to_rbg(cc->mib->message.dl_Bandwidth); - i1 = 0; - i2 = 0; - i3 = 0; - - for (j = 0; j < N_RBG; j++) { - if (MIMO_mode_indicator[CC_id][j] == 2) { - i1++; - } else if (MIMO_mode_indicator[CC_id][j] == 1) { - i2++; - } else if (MIMO_mode_indicator[CC_id][j] == 0) { - i3++; - } - } - - if (i1 < N_RBG) { - if (i2 > 0 && i3 == 0) { - PHY_vars_eNB_g[Mod_id][CC_id]->check_for_SUMIMO_transmissions = PHY_vars_eNB_g[Mod_id][CC_id]->check_for_SUMIMO_transmissions + 1; - } else if (i3 > 0) { - PHY_vars_eNB_g[Mod_id][CC_id]->check_for_MUMIMO_transmissions = PHY_vars_eNB_g[Mod_id][CC_id]->check_for_MUMIMO_transmissions + 1; - } - } else if (i3 == N_RBG && i1 == 0 && i2 == 0) { - PHY_vars_eNB_g[Mod_id][CC_id]->FULL_MUMIMO_transmissions = PHY_vars_eNB_g[Mod_id][CC_id]->FULL_MUMIMO_transmissions + 1; - } - - PHY_vars_eNB_g[Mod_id][CC_id]->check_for_total_transmissions = PHY_vars_eNB_g[Mod_id][CC_id]->check_for_total_transmissions + 1; - } - -#endif for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; @@ -1604,7 +1235,6 @@ dlsch_scheduler_pre_processor_allocate(module_id_t Mod_id, uint8_t slice_allocation_mask[NFAPI_CC_MAX][N_RBG_MAX], uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]) { 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_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); @@ -1629,10 +1259,6 @@ dlsch_scheduler_pre_processor_allocate(module_id_t Mod_id, ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1; MIMO_mode_indicator[CC_id][i] = 1; - if (tm == 5) { - ue_sched_ctl->dl_pow_off[CC_id] = 1; - } - nb_rbs_remaining[CC_id][UE_id] = nb_rbs_remaining[CC_id][UE_id] - min_rb_unit + 1; ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit - 1; } @@ -1643,10 +1269,6 @@ dlsch_scheduler_pre_processor_allocate(module_id_t Mod_id, ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1; MIMO_mode_indicator[CC_id][i] = 1; - if (tm == 5) { - ue_sched_ctl->dl_pow_off[CC_id] = 1; - } - nb_rbs_remaining[CC_id][UE_id] = nb_rbs_remaining[CC_id][UE_id] - min_rb_unit; ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit; } From 8e72b1364ab8c41d6f0afb46fd2350f3726f79cc Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 16 Jan 2020 15:39:20 +0100 Subject: [PATCH 105/240] Remove sf0 DC limitation --- openair2/LAYER2/MAC/pre_processor.c | 49 ----------------------------- 1 file changed, 49 deletions(-) diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index b5a0a350ac..cfa0204a18 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -997,8 +997,6 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, } } -#define SF0_LIMIT 1 - void dlsch_scheduler_pre_processor_reset(module_id_t module_idP, int slice_idx, @@ -1016,9 +1014,6 @@ dlsch_scheduler_pre_processor_reset(module_id_t module_idP, UE_sched_ctrl_t *ue_sched_ctl; int N_RB_DL, RBGsize, RBGsize_last; int N_RBG[NFAPI_CC_MAX]; -#ifdef SF0_LIMIT - int sf0_lower, sf0_upper; -#endif rnti_t rnti; uint8_t *vrb_map; COMMON_channels_t *cc; @@ -1120,39 +1115,6 @@ dlsch_scheduler_pre_processor_reset(module_id_t module_idP, } N_RB_DL = to_prb(RC.mac[module_idP]->common_channels[CC_id].mib->message.dl_Bandwidth); -#ifdef SF0_LIMIT - - switch (N_RBG[CC_id]) { - case 6: - sf0_lower = 0; - sf0_upper = 5; - break; - - case 8: - sf0_lower = 2; - sf0_upper = 5; - break; - - case 13: - sf0_lower = 4; - sf0_upper = 7; - break; - - case 17: - sf0_lower = 7; - sf0_upper = 9; - break; - - case 25: - sf0_lower = 11; - sf0_upper = 13; - break; - - default: - AssertFatal(1 == 0, "unsupported RBs (%d)\n", N_RB_DL); - } - -#endif switch (N_RB_DL) { case 6: @@ -1194,17 +1156,6 @@ dlsch_scheduler_pre_processor_reset(module_id_t module_idP, // Initialize Subbands according to VRB map for (i = 0; i < N_RBG[CC_id]; i++) { int rb_size = i == N_RBG[CC_id] - 1 ? RBGsize_last : RBGsize; -#ifdef SF0_LIMIT - - // for avoiding 6+ PRBs around DC in subframe 0 (avoid excessive errors) - /* TODO: make it proper - allocate those RBs, do not "protect" them, but - * compute number of available REs and limit MCS according to the - * TBS table 36.213 7.1.7.2.1-1 (can be done after pre-processor) - */ - if (subframeP == 0 && i >= sf0_lower && i <= sf0_upper) - rballoc_sub[CC_id][i] = 1; - -#endif // for SI-RNTI,RA-RNTI and P-RNTI allocations for (j = 0; j < rb_size; j++) { From ff766786a835a424706a1c377b28aefaf636dbbe Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 17 Jan 2020 09:54:20 +0100 Subject: [PATCH 106/240] Remove mbsfn_flag from schedule_ue_spec(), simplify pre_processor interface --- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 25 ++++++-------------- openair2/LAYER2/MAC/eNB_scheduler_fairRR.c | 3 +-- openair2/LAYER2/MAC/mac_proto.h | 27 +++++++++------------- openair2/LAYER2/MAC/pre_processor.c | 20 +++++++--------- 4 files changed, 27 insertions(+), 48 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index d7efbeeeea..6857c4aa9a 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -421,7 +421,8 @@ set_ul_DAI(int module_idP, void schedule_dlsch(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP, int *mbsfn_flag) { for (int CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; CC_id++) { - schedule_ue_spec(module_idP, CC_id, frameP, subframeP, mbsfn_flag); + if (mbsfn_flag[CC_id] == 0) + schedule_ue_spec(module_idP, CC_id, frameP, subframeP); } } @@ -447,8 +448,7 @@ void schedule_ue_spec(module_id_t module_idP, int CC_id, frame_t frameP, - sub_frame_t subframeP, - int *mbsfn_flag) + sub_frame_t subframeP) //------------------------------------------------------------------------------ { int UE_id; @@ -569,13 +569,10 @@ schedule_ue_spec(module_id_t module_idP, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR, VCD_FUNCTION_IN); start_meas(&eNB->schedule_dlsch_preprocessor); - memset(eNB->slice_info.rballoc_sub, 0, sizeof(eNB->slice_info.rballoc_sub)); dlsch_scheduler_pre_processor(module_idP, - 0, //slice_idxP, + CC_id, frameP, - subframeP, - mbsfn_flag, - eNB->slice_info.rballoc_sub); + subframeP); stop_meas(&eNB->schedule_dlsch_preprocessor); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR, VCD_FUNCTION_OUT); @@ -597,9 +594,6 @@ schedule_ue_spec(module_id_t module_idP, CC_id); dl_req = &eNB->DL_req[CC_id].dl_config_request_body; - //if (mbsfn_flag[CC_id] > 0) - // return; - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { LOG_D(MAC, "doing schedule_ue_spec for CC_id %d UE %d\n", CC_id, @@ -1627,8 +1621,7 @@ schedule_ue_spec(module_id_t module_idP, fill_DLSCH_dci(module_idP, frameP, - subframeP, - mbsfn_flag); + subframeP); stop_meas(&eNB->schedule_dlsch); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH, VCD_FUNCTION_OUT); @@ -2520,8 +2513,7 @@ schedule_ue_spec_br(module_id_t module_idP, void fill_DLSCH_dci(module_id_t module_idP, frame_t frameP, - sub_frame_t subframeP, - int *mbsfn_flagP) + sub_frame_t subframeP) //------------------------------------------------------------------------------ { // loop over all allocated UEs and compute frequency allocations for PDSCH @@ -2550,9 +2542,6 @@ fill_DLSCH_dci(module_id_t module_idP, LOG_D(MAC, "Doing fill DCI for CC_id %d\n", CC_id); - if (mbsfn_flagP[CC_id] > 0) - continue; - cc = &eNB->common_channels[CC_id]; N_RBG = to_rbg(cc->mib->message.dl_Bandwidth); N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth); diff --git a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c index 260d8a7417..ab5b6a76f6 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c @@ -619,8 +619,7 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id, min_rb_unit, (uint16_t (*)[MAX_MOBILES_PER_ENB])nb_rbs_required, rballoc_sub, - MIMO_mode_indicator, - mbsfn_flag); + MIMO_mode_indicator); } } diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index 23aa03ca8b..f2e33f84b1 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -142,9 +142,8 @@ void schedule_ulsch_rnti_emtc(module_id_t module_idP, @param Mod_id Instance of eNB @param frame Frame index @param subframe Index of subframe -@param mbsfn_flag Indicates that this subframe is for MCH/MCCH */ -void fill_DLSCH_dci(module_id_t module_idP,frame_t frameP,sub_frame_t subframe,int *mbsfn_flag); +void fill_DLSCH_dci(module_id_t module_idP,frame_t frameP,sub_frame_t subframe); /** \brief UE specific DLSCH scheduling. Retrieves next ue to be schduled from round-robin scheduler and gets the appropriate harq_pid for the subframe from PHY. If the process is active and requires a retransmission, it schedules the retransmission with the same PRB count and MCS as the first transmission. Otherwise it consults RLC for DCCH/DTCH SDUs (status with maximum number of available PRBS), builds the MAC header (timing advance sent by default) and copies @param Mod_id Instance ID of eNB @@ -159,8 +158,7 @@ void schedule_dlsch(module_id_t module_idP, frame_t frameP, void schedule_ue_spec(module_id_t module_idP, int CC_id, frame_t frameP, - sub_frame_t subframe, - int *mbsfn_flag); + sub_frame_t subframe); void schedule_ue_spec_br(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP); @@ -234,21 +232,18 @@ void clear_nfapi_information(eNB_MAC_INST *eNB, int CC_idP, void dlsch_scheduler_pre_processor(module_id_t module_idP, - int slice_idxP, + int CC_id, frame_t frameP, - sub_frame_t subframe, - int *mbsfn_flag, - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]); + sub_frame_t subframe); void dlsch_scheduler_pre_processor_reset(module_id_t module_idP, - int slice_idx, - frame_t frameP, - sub_frame_t subframeP, - int min_rb_unit[NFAPI_CC_MAX], - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX], - uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX], - int *mbsfn_flag); + int slice_idx, + frame_t frameP, + sub_frame_t subframeP, + int min_rb_unit[NFAPI_CC_MAX], + uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], + uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX], + uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]); void dlsch_scheduler_pre_processor_partitioning(module_id_t Mod_id, int slice_idx, diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index cfa0204a18..e91ca5f2b2 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -879,15 +879,16 @@ void dlsch_scheduler_pre_processor_intraslice_sharing(module_id_t Mod_id, // This function assigns pre-available RBS to each UE in specified sub-bands before scheduling is done void dlsch_scheduler_pre_processor(module_id_t Mod_id, - int slice_idx, + int CC_id, frame_t frameP, - sub_frame_t subframeP, - int *mbsfn_flag, - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]) { + sub_frame_t subframeP) { int UE_id; - uint8_t CC_id; uint16_t i, j; + int slice_idx = 0; int min_rb_unit[NFAPI_CC_MAX]; + uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]; + memset(rballoc_sub, 0, sizeof(rballoc_sub)); + eNB_MAC_INST *eNB = RC.mac[Mod_id]; slice_info_t *sli = &eNB->slice_info; uint16_t (*nb_rbs_required)[MAX_MOBILES_PER_ENB] = sli->pre_processor_results[slice_idx].nb_rbs_required; @@ -907,8 +908,7 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, min_rb_unit, nb_rbs_required, rballoc_sub, - MIMO_mode_indicator, - mbsfn_flag); // FIXME: Not sure if useful + MIMO_mode_indicator); // STATUS // Store the DLSCH buffer for each logical channel store_dlsch_buffer(Mod_id, @@ -1005,8 +1005,7 @@ dlsch_scheduler_pre_processor_reset(module_id_t module_idP, int min_rb_unit[NFAPI_CC_MAX], uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX], - uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX], - int *mbsfn_flag) { + uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]) { int UE_id; uint8_t CC_id; int i, j; @@ -1025,9 +1024,6 @@ dlsch_scheduler_pre_processor_reset(module_id_t module_idP, N_RBG[CC_id] = to_rbg(cc->mib->message.dl_Bandwidth); min_rb_unit[CC_id] = get_min_rb_unit(module_idP, CC_id); - if (mbsfn_flag[CC_id] > 0) // If this CC is allocated for MBSFN skip it here - continue; - for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; ++UE_id) { UE_list = &RC.mac[module_idP]->UE_list; ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; From 8d3fa4dc227fa1a543d2643de340c0b4dbedd520 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 25 Feb 2020 15:45:24 +0100 Subject: [PATCH 107/240] Simplify dlsch_scheduler_pre_processor_reset() The original reset() function used in fairRR has been moved to eNB_scheduler_fairRR.c --- openair2/LAYER2/MAC/eNB_scheduler_fairRR.c | 184 +++++++++++++++++- openair2/LAYER2/MAC/eNB_scheduler_fairRR.h | 9 + openair2/LAYER2/MAC/mac_proto.h | 9 +- openair2/LAYER2/MAC/pre_processor.c | 207 ++++----------------- 4 files changed, 224 insertions(+), 185 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c index ab5b6a76f6..20e82780e6 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c @@ -558,6 +558,174 @@ void dlsch_scheduler_pre_ue_select_fairRR( return; } +void dlsch_scheduler_pre_processor_reset_fairRR( + module_id_t module_idP, + frame_t frameP, + sub_frame_t subframeP, + int min_rb_unit[NFAPI_CC_MAX], + uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], + uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX], + uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]) { + int UE_id; + uint8_t CC_id; + int i, j; + UE_list_t *UE_list; + UE_sched_ctrl_t *ue_sched_ctl; + int N_RB_DL, RBGsize, RBGsize_last; + int N_RBG[NFAPI_CC_MAX]; + rnti_t rnti; + uint8_t *vrb_map; + COMMON_channels_t *cc; + + // + for (CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; CC_id++) { + // initialize harq_pid and round + cc = &RC.mac[module_idP]->common_channels[CC_id]; + N_RBG[CC_id] = to_rbg(cc->mib->message.dl_Bandwidth); + min_rb_unit[CC_id] = get_min_rb_unit(module_idP, CC_id); + + for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; ++UE_id) { + UE_list = &RC.mac[module_idP]->UE_list; + ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + rnti = UE_RNTI(module_idP, UE_id); + + if (rnti == NOT_A_RNTI) + continue; + + if (UE_list->active[UE_id] != TRUE) + continue; + + LOG_D(MAC, "Running preprocessor for UE %d (%x)\n", UE_id, rnti); + + // initialize harq_pid and round + if (ue_sched_ctl->ta_timer) + ue_sched_ctl->ta_timer--; + + /* + eNB_UE_stats *eNB_UE_stats; + + if (eNB_UE_stats == NULL) + return; + + + mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti, + frameP,subframeP, + &ue_sched_ctl->harq_pid[CC_id], + &ue_sched_ctl->round[CC_id], + openair_harq_DL); + + + if (ue_sched_ctl->ta_timer == 0) { + + // WE SHOULD PROTECT the eNB_UE_stats with a mutex here ... + + ue_sched_ctl->ta_timer = 20; // wait 20 subframes before taking TA measurement from PHY + switch (N_RB_DL) { + case 6: + ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update; + break; + + case 15: + ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/2; + break; + + case 25: + ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/4; + break; + + case 50: + ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/8; + break; + + case 75: + ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/12; + break; + + case 100: + ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/16; + break; + } + // clear the update in case PHY does not have a new measurement after timer expiry + eNB_UE_stats->timing_advance_update = 0; + } + else { + ue_sched_ctl->ta_timer--; + ue_sched_ctl->ta_update =0; // don't trigger a timing advance command + } + + + if (UE_id==0) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_TIMING_ADVANCE,ue_sched_ctl->ta_update); + } + */ + nb_rbs_required[CC_id][UE_id] = 0; + ue_sched_ctl->pre_nb_available_rbs[CC_id] = 0; + ue_sched_ctl->dl_pow_off[CC_id] = 2; + + for (i = 0; i < N_RBG[CC_id]; i++) { + ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 0; + } + } + + N_RB_DL = to_prb(RC.mac[module_idP]->common_channels[CC_id].mib->message.dl_Bandwidth); + + switch (N_RB_DL) { + case 6: + RBGsize = 1; + RBGsize_last = 1; + break; + + case 15: + RBGsize = 2; + RBGsize_last = 1; + break; + + case 25: + RBGsize = 2; + RBGsize_last = 1; + break; + + case 50: + RBGsize = 3; + RBGsize_last = 2; + break; + + case 75: + RBGsize = 4; + RBGsize_last = 3; + break; + + case 100: + RBGsize = 4; + RBGsize_last = 4; + break; + + default: + AssertFatal(1 == 0, "unsupported RBs (%d)\n", N_RB_DL); + } + + vrb_map = RC.mac[module_idP]->common_channels[CC_id].vrb_map; + + // Initialize Subbands according to VRB map + for (i = 0; i < N_RBG[CC_id]; i++) { + int rb_size = i == N_RBG[CC_id] - 1 ? RBGsize_last : RBGsize; + + // for SI-RNTI,RA-RNTI and P-RNTI allocations + for (j = 0; j < rb_size; j++) { + if (vrb_map[j + (i*RBGsize)] != 0) { + rballoc_sub[CC_id][i] = 1; + LOG_D(MAC, "Frame %d, subframe %d : vrb %d allocated\n", frameP, subframeP, j + (i*RBGsize)); + break; + } + } + + //LOG_D(MAC, "Frame %d Subframe %d CC_id %d RBG %i : rb_alloc %d\n", + //frameP, subframeP, CC_id, i, rballoc_sub[CC_id][i]); + MIMO_mode_indicator[CC_id][i] = 2; + } + } +} + // This function assigns pre-available RBS to each UE in specified sub-bands before scheduling is done @@ -612,14 +780,14 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id, UE_id = i; // Initialize scheduling information for all active UEs - dlsch_scheduler_pre_processor_reset(Mod_id, - 0, - frameP, - subframeP, - min_rb_unit, - (uint16_t (*)[MAX_MOBILES_PER_ENB])nb_rbs_required, - rballoc_sub, - MIMO_mode_indicator); + dlsch_scheduler_pre_processor_reset_fairRR( + Mod_id, + frameP, + subframeP, + min_rb_unit, + (uint16_t(*)[MAX_MOBILES_PER_ENB])nb_rbs_required, + rballoc_sub, + MIMO_mode_indicator); } } diff --git a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.h b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.h index 5355a614a6..682bebc1a5 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.h +++ b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.h @@ -85,6 +85,15 @@ void dlsch_scheduler_pre_ue_select_fairRR( uint16_t nb_rbs_required[MAX_NUM_CCs][MAX_MOBILES_PER_ENB], DLSCH_UE_SELECT dlsch_ue_select[MAX_NUM_CCs]); +void dlsch_scheduler_pre_processor_reset_fairRR( + module_id_t module_idP, + frame_t frameP, + sub_frame_t subframeP, + int min_rb_unit[NFAPI_CC_MAX], + uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], + uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX], + uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]); + void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id, frame_t frameP, sub_frame_t subframeP, diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index f2e33f84b1..d9f214f9a2 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -237,13 +237,8 @@ void dlsch_scheduler_pre_processor(module_id_t module_idP, sub_frame_t subframe); void dlsch_scheduler_pre_processor_reset(module_id_t module_idP, - int slice_idx, - frame_t frameP, - sub_frame_t subframeP, - int min_rb_unit[NFAPI_CC_MAX], - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX], - uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]); + int CC_id, + uint8_t rballoc_sub[N_RBG_MAX]); void dlsch_scheduler_pre_processor_partitioning(module_id_t Mod_id, int slice_idx, diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index e91ca5f2b2..83c514e92d 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -886,6 +886,8 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, uint16_t i, j; int slice_idx = 0; int min_rb_unit[NFAPI_CC_MAX]; + min_rb_unit[CC_id] = get_min_rb_unit(Mod_id, CC_id); + // TODO: remove NFAPI_CC_MAX, here for compatibility for the moment uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]; memset(rballoc_sub, 0, sizeof(rballoc_sub)); @@ -894,21 +896,18 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, uint16_t (*nb_rbs_required)[MAX_MOBILES_PER_ENB] = sli->pre_processor_results[slice_idx].nb_rbs_required; uint16_t (*nb_rbs_accounted)[MAX_MOBILES_PER_ENB] = sli->pre_processor_results[slice_idx].nb_rbs_accounted; uint16_t (*nb_rbs_remaining)[MAX_MOBILES_PER_ENB] = sli->pre_processor_results[slice_idx].nb_rbs_remaining; - uint8_t (*MIMO_mode_indicator)[N_RBG_MAX] = sli->pre_processor_results[slice_idx].MIMO_mode_indicator; + // TODO remove this + uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]; + memset(MIMO_mode_indicator, 0, sizeof(MIMO_mode_indicator)); + UE_list_t *UE_list = &eNB->UE_list; UE_sched_ctrl_t *ue_sched_ctl; - // int rrc_status = RRC_IDLE; + // Initialize scheduling information for all active UEs memset(&sli->pre_processor_results[slice_idx], 0, sizeof(sli->pre_processor_results[slice_idx])); - // FIXME: After the memset above, some of the resets in reset() are redundant dlsch_scheduler_pre_processor_reset(Mod_id, - slice_idx, - frameP, - subframeP, - min_rb_unit, - nb_rbs_required, - rballoc_sub, - MIMO_mode_indicator); + CC_id, + rballoc_sub[CC_id]); // STATUS // Store the DLSCH buffer for each logical channel store_dlsch_buffer(Mod_id, @@ -999,173 +998,41 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, void dlsch_scheduler_pre_processor_reset(module_id_t module_idP, - int slice_idx, - frame_t frameP, - sub_frame_t subframeP, - int min_rb_unit[NFAPI_CC_MAX], - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX], - uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]) { - int UE_id; - uint8_t CC_id; - int i, j; - UE_list_t *UE_list; - UE_sched_ctrl_t *ue_sched_ctl; - int N_RB_DL, RBGsize, RBGsize_last; - int N_RBG[NFAPI_CC_MAX]; - rnti_t rnti; - uint8_t *vrb_map; - COMMON_channels_t *cc; + int CC_id, + uint8_t rballoc_sub[N_RBG_MAX]) { + UE_list_t *UE_list = &RC.mac[module_idP]->UE_list; + + for (int UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; ++UE_id) { + UE_sched_ctrl_t *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + const rnti_t rnti = UE_RNTI(module_idP, UE_id); + + if (rnti == NOT_A_RNTI) + continue; + + if (UE_list->active[UE_id] != TRUE) + continue; - // - for (CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; CC_id++) { // initialize harq_pid and round - cc = &RC.mac[module_idP]->common_channels[CC_id]; - N_RBG[CC_id] = to_rbg(cc->mib->message.dl_Bandwidth); - min_rb_unit[CC_id] = get_min_rb_unit(module_idP, CC_id); + if (ue_sched_ctl->ta_timer) + ue_sched_ctl->ta_timer--; - for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; ++UE_id) { - UE_list = &RC.mac[module_idP]->UE_list; - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - rnti = UE_RNTI(module_idP, UE_id); + ue_sched_ctl->pre_nb_available_rbs[CC_id] = 0; + ue_sched_ctl->dl_pow_off[CC_id] = 2; - if (rnti == NOT_A_RNTI) - continue; - - if (UE_list->active[UE_id] != TRUE) - continue; - - if (!ue_dl_slice_membership(module_idP, UE_id, slice_idx)) - continue; - - LOG_D(MAC, "Running preprocessor for UE %d (%x)\n", UE_id, rnti); - - // initialize harq_pid and round - if (ue_sched_ctl->ta_timer) - ue_sched_ctl->ta_timer--; - - /* - eNB_UE_stats *eNB_UE_stats; - - if (eNB_UE_stats == NULL) - return; - - - mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti, - frameP,subframeP, - &ue_sched_ctl->harq_pid[CC_id], - &ue_sched_ctl->round[CC_id], - openair_harq_DL); - - - if (ue_sched_ctl->ta_timer == 0) { - - // WE SHOULD PROTECT the eNB_UE_stats with a mutex here ... - - ue_sched_ctl->ta_timer = 20; // wait 20 subframes before taking TA measurement from PHY - switch (N_RB_DL) { - case 6: - ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update; - break; - - case 15: - ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/2; - break; - - case 25: - ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/4; - break; - - case 50: - ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/8; - break; - - case 75: - ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/12; - break; - - case 100: - ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/16; - break; - } - // clear the update in case PHY does not have a new measurement after timer expiry - eNB_UE_stats->timing_advance_update = 0; - } - else { - ue_sched_ctl->ta_timer--; - ue_sched_ctl->ta_update =0; // don't trigger a timing advance command - } - - - if (UE_id==0) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_TIMING_ADVANCE,ue_sched_ctl->ta_update); - } - */ - nb_rbs_required[CC_id][UE_id] = 0; - ue_sched_ctl->pre_nb_available_rbs[CC_id] = 0; - ue_sched_ctl->dl_pow_off[CC_id] = 2; - - for (i = 0; i < N_RBG[CC_id]; i++) { - ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 0; - } + for (int i = 0; i < sizeof(ue_sched_ctl->rballoc_sub_UE[CC_id])/sizeof(unsigned char); i++) { + ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 0; } + } - N_RB_DL = to_prb(RC.mac[module_idP]->common_channels[CC_id].mib->message.dl_Bandwidth); + const int N_RB_DL = to_prb(RC.mac[module_idP]->common_channels[CC_id].mib->message.dl_Bandwidth); + const int RBGsize = get_min_rb_unit(module_idP, CC_id); + const uint8_t *vrb_map = RC.mac[module_idP]->common_channels[CC_id].vrb_map; - switch (N_RB_DL) { - case 6: - RBGsize = 1; - RBGsize_last = 1; - break; - - case 15: - RBGsize = 2; - RBGsize_last = 1; - break; - - case 25: - RBGsize = 2; - RBGsize_last = 1; - break; - - case 50: - RBGsize = 3; - RBGsize_last = 2; - break; - - case 75: - RBGsize = 4; - RBGsize_last = 3; - break; - - case 100: - RBGsize = 4; - RBGsize_last = 4; - break; - - default: - AssertFatal(1 == 0, "unsupported RBs (%d)\n", N_RB_DL); - } - - vrb_map = RC.mac[module_idP]->common_channels[CC_id].vrb_map; - - // Initialize Subbands according to VRB map - for (i = 0; i < N_RBG[CC_id]; i++) { - int rb_size = i == N_RBG[CC_id] - 1 ? RBGsize_last : RBGsize; - - // for SI-RNTI,RA-RNTI and P-RNTI allocations - for (j = 0; j < rb_size; j++) { - if (vrb_map[j + (i*RBGsize)] != 0) { - rballoc_sub[CC_id][i] = 1; - LOG_D(MAC, "Frame %d, subframe %d : vrb %d allocated\n", frameP, subframeP, j + (i*RBGsize)); - break; - } - } - - //LOG_D(MAC, "Frame %d Subframe %d CC_id %d RBG %i : rb_alloc %d\n", - //frameP, subframeP, CC_id, i, rballoc_sub[CC_id][i]); - MIMO_mode_indicator[CC_id][i] = 2; - } + // Check for SI-RNTI, RA-RNTI or P-RNTI allocations in VRB map and + // initialize subbands accordly + for (int i = 0; i < N_RB_DL; i++) { + if (vrb_map[i] != 0) + rballoc_sub[i/RBGsize] = 1; } } From 4462e2d710be3eddae80126cce80e49ed6b10fa0 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 16 Jan 2020 15:34:27 +0100 Subject: [PATCH 108/240] Remove unused/broken code in preprocessor * Remove MIMO_mode_indicator: it is simply not used ATM * Remove min_rb_unit as parameter: function auto-detects * Remove commented code * Remove slice sharing/multiplexing: it is broken * Remove UE sorting, add UE with add_new_ue() in MAC - UE sorting is useless overhead on every iteration, instead it should be governed by a scheduling algorithm (e.g., RR or PF) - The MAC keeps a UE list and automatically adds a UE - UE_list empty, set head to -1 * Remove slice_positioning: the slicing functionality is broken * Remove unused/untested code --- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 211 --------- openair2/LAYER2/MAC/eNB_scheduler_fairRR.c | 21 +- .../LAYER2/MAC/eNB_scheduler_primitives.c | 165 ++----- openair2/LAYER2/MAC/mac.h | 1 - openair2/LAYER2/MAC/mac_proto.h | 63 +-- openair2/LAYER2/MAC/main.c | 8 +- openair2/LAYER2/MAC/pre_processor.c | 437 ++---------------- 7 files changed, 89 insertions(+), 817 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 6857c4aa9a..9a76bd2e4d 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -577,19 +577,6 @@ schedule_ue_spec(module_id_t module_idP, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR, VCD_FUNCTION_OUT); - if (RC.mac[module_idP]->slice_info.interslice_share_active) { - dlsch_scheduler_interslice_multiplexing(module_idP, - frameP, - subframeP, - eNB->slice_info.rballoc_sub); - /* the interslice multiplexing re-sorts the UE_list for the slices it tries - * to multiplex, so we need to sort it for the current slice again */ - sort_UEs(module_idP, - 0,//slice_idxP, - frameP, - subframeP); - } - LOG_D(MAC, "doing schedule_ue_spec for CC_id %d\n", CC_id); dl_req = &eNB->DL_req[CC_id].dl_config_request_body; @@ -1627,204 +1614,6 @@ schedule_ue_spec(module_id_t module_idP, VCD_FUNCTION_OUT); } -//------------------------------------------------------------------------------ -void -dlsch_scheduler_interslice_multiplexing(module_id_t Mod_id, - int frameP, - sub_frame_t subframeP, - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]) -//------------------------------------------------------------------------------ -{ - // FIXME: I'm prototyping the algorithm, so there may be arrays and variables that carry redundant information here and in pre_processor_results struct. - int UE_id, CC_id, rbg, i; - int N_RB_DL, min_rb_unit, tm; - int owned, used; - eNB_MAC_INST *eNB = RC.mac[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_t *ue_sched_ctl; - COMMON_channels_t *cc; - int N_RBG[NFAPI_CC_MAX]; - int slice_sorted_list[MAX_NUM_SLICES]; - int slice_idx; - int8_t free_rbgs_map[NFAPI_CC_MAX][N_RBG_MAX]; - int has_traffic[NFAPI_CC_MAX][MAX_NUM_SLICES]; - uint8_t allocation_mask[NFAPI_CC_MAX][N_RBG_MAX]; - uint16_t (*nb_rbs_remaining)[MAX_MOBILES_PER_ENB]; - uint16_t (*nb_rbs_required)[MAX_MOBILES_PER_ENB]; - uint8_t (*MIMO_mode_indicator)[N_RBG_MAX]; - - // Initialize the free RBGs map - // free_rbgs_map[CC_id][rbg] = -1 if RBG is allocated, - // otherwise it contains the id of the slice it belongs to. - // (Information about slicing must be retained to deal with isolation). - // FIXME: This method does not consider RBGs that are free and belong to no slices - for (CC_id = 0; CC_id < nb_mac_CC; CC_id++) { - cc = &eNB->common_channels[CC_id]; - N_RBG[CC_id] = to_rbg(cc->mib->message.dl_Bandwidth); - - for (rbg = 0; rbg < N_RBG[CC_id]; rbg++) { - for (i = 0; i < sli->n_dl; ++i) { - owned = sli->pre_processor_results[i].slice_allocation_mask[CC_id][rbg]; - - if (owned) { - used = rballoc_sub[CC_id][rbg]; - free_rbgs_map[CC_id][rbg] = used ? -1 : i; - break; - } - } - } - } - - // Find out which slices need other resources. - // FIXME: I don't think is really needed since we check nb_rbs_remaining later - for (CC_id = 0; CC_id < nb_mac_CC; CC_id++) { - for (i = 0; i < sli->n_dl; i++) { - has_traffic[CC_id][i] = 0; - - for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) { - if (sli->pre_processor_results[i].nb_rbs_remaining[CC_id][UE_id] > 0) { - has_traffic[CC_id][i] = 1; - break; - } - } - } - } - - slice_priority_sort(Mod_id, - slice_sorted_list); - - // MULTIPLEXING - // This part is an adaptation of dlsch_scheduler_pre_processor_allocate() code - for (CC_id = 0; CC_id < nb_mac_CC; ++CC_id) { - N_RB_DL = to_prb(eNB->common_channels[CC_id].mib->message.dl_Bandwidth); - min_rb_unit = get_min_rb_unit(Mod_id, - CC_id); - - for (i = 0; i < sli->n_dl; ++i) { - slice_idx = slice_sorted_list[i]; - - if (has_traffic[CC_id][slice_idx] == 0) continue; - - // Build an ad-hoc allocation mask fo the slice - for (rbg = 0; rbg < N_RBG[CC_id]; ++rbg) { - if (free_rbgs_map[CC_id][rbg] == -1) { - // RBG is already allocated - allocation_mask[CC_id][rbg] = 0; - continue; - } - - if (sli->dl[free_rbgs_map[CC_id][rbg]].isol == 1) { - // RBG belongs to an isolated slice - allocation_mask[CC_id][rbg] = 0; - continue; - } - - // RBG is free - allocation_mask[CC_id][rbg] = 1; - } - - // Sort UE again - // (UE list gets sorted every time pre_processor is called so it is probably dirty at this point) - // FIXME: There is only one UE_list for all slices, so it must be sorted again each time we use it - sort_UEs(Mod_id, - slice_idx, - frameP, - subframeP); - nb_rbs_remaining = sli->pre_processor_results[slice_idx].nb_rbs_remaining; - nb_rbs_required = sli->pre_processor_results[slice_idx].nb_rbs_required; - MIMO_mode_indicator = sli->pre_processor_results[slice_idx].MIMO_mode_indicator; - - // Allocation - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - tm = get_tmode(Mod_id, - CC_id, - UE_id); - - for (rbg = 0; rbg < N_RBG[CC_id]; ++rbg) { - // FIXME: I think that some of these checks are redundant - if (allocation_mask[CC_id][rbg] == 0) continue; - - if (rballoc_sub[CC_id][rbg] != 0) continue; - - if (ue_sched_ctl->rballoc_sub_UE[CC_id][rbg] != 0) continue; - - if (nb_rbs_remaining[CC_id][UE_id] <= 0) continue; - - if (ue_sched_ctl->pre_nb_available_rbs[CC_id] >= nb_rbs_required[CC_id][UE_id]) continue; - - if (ue_sched_ctl->dl_pow_off[CC_id] == 0) continue; - - if ((rbg == N_RBG[CC_id] - 1) && ((N_RB_DL == 25) || (N_RB_DL == 50))) { - // Allocating last, smaller RBG - if (nb_rbs_remaining[CC_id][UE_id] >= min_rb_unit - 1) { - rballoc_sub[CC_id][rbg] = 1; - free_rbgs_map[CC_id][rbg] = -1; - ue_sched_ctl->rballoc_sub_UE[CC_id][rbg] = 1; - MIMO_mode_indicator[CC_id][rbg] = 1; - - if (tm == 5) { - ue_sched_ctl->dl_pow_off[CC_id] = 1; - } - - nb_rbs_remaining[CC_id][UE_id] -= (min_rb_unit - 1); - ue_sched_ctl->pre_nb_available_rbs[CC_id] += (min_rb_unit - 1); - } - } else { - // Allocating a standard-sized RBG - if (nb_rbs_remaining[CC_id][UE_id] >= min_rb_unit) { - rballoc_sub[CC_id][rbg] = 1; - free_rbgs_map[CC_id][rbg] = -1; - ue_sched_ctl->rballoc_sub_UE[CC_id][rbg] = 1; - MIMO_mode_indicator[CC_id][rbg] = 1; - - if (tm == 5) { - ue_sched_ctl->dl_pow_off[CC_id] = 1; - } - - nb_rbs_remaining[CC_id][UE_id] -= min_rb_unit; - ue_sched_ctl->pre_nb_available_rbs[CC_id] += min_rb_unit; - } - } - } - } - } - } - - return; -} - -//------------------------------------------------------------------------------ -void dlsch_scheduler_qos_multiplexing(module_id_t Mod_id, int frameP, sub_frame_t subframeP) -//------------------------------------------------------------------------------ -{ - // int UE_id; - int CC_id, i; - // UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - slice_info_t *sli = &RC.mac[Mod_id]->slice_info; - //UE_sched_ctrl *ue_sched_ctl; - - for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_id]; CC_id++) { - for (i = 0; i < sli->n_dl; i++) { - // Sort UE again - // FIXME: There is only one UE_list for all slices, so it must be sorted again each time we use it - sort_UEs(Mod_id, - (uint8_t)i, - frameP, - subframeP); - /* - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { - //ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - // TODO: Do something here - // ue_sched_ctl->pre_nb_available_rbs[CC_id]; - } - */ - } - } -} - //------------------------------------------------------------------------------ /* * Default DLSCH scheduler for LTE-M diff --git a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c index 20e82780e6..0e8770d3e2 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c @@ -738,9 +738,8 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id, uint16_t temp_total_rbs_count; unsigned char temp_total_ue_count; unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX]; - uint8_t slice_allocation[MAX_NUM_CCs][N_RBG_MAX]; int UE_id, i; - uint16_t j,c; + uint16_t j; uint16_t nb_rbs_required[MAX_NUM_CCs][MAX_MOBILES_PER_ENB]; uint16_t nb_rbs_required_remaining[MAX_NUM_CCs][MAX_MOBILES_PER_ENB]; // uint16_t nb_rbs_required_remaining_1[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; @@ -795,8 +794,7 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id, // Store the DLSCH buffer for each logical channel store_dlsch_buffer(Mod_id,0, frameP, subframeP); // Calculate the number of RBs required by each UE on the basis of logical channel's buffer - assign_rbs_required(Mod_id, 0, frameP, subframeP, nb_rbs_required, - min_rb_unit); + assign_rbs_required(Mod_id, 0, frameP, subframeP, nb_rbs_required); #else memcpy(nb_rbs_required, pre_nb_rbs_required[dlsch_ue_select_tbl_in_use], sizeof(uint16_t)*MAX_NUM_CCs*MAX_MOBILES_PER_ENB); #endif @@ -856,23 +854,14 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id, nb_rbs_required_remaining[CC_id][UE_id] = cmin(average_rbs_per_user[CC_id], dlsch_ue_select[CC_id].list[i].nb_rb); } - /* slicing support has been introduced into the scheduler. Provide dummy - * data so that the preprocessor "simply works" */ - for (c = 0; c < MAX_NUM_CCs; ++c) - for (j = 0; j < N_RBG_MAX; ++j) - slice_allocation[c][j] = 1; - LOG_T(MAC,"calling dlsch_scheduler_pre_processor_allocate .. \n "); dlsch_scheduler_pre_processor_allocate (Mod_id, UE_id, CC_id, N_RBG[CC_id], - min_rb_unit[CC_id], - (uint16_t (*)[MAX_MOBILES_PER_ENB])nb_rbs_required, - (uint16_t (*)[MAX_MOBILES_PER_ENB])nb_rbs_required_remaining, - rballoc_sub, - slice_allocation, - MIMO_mode_indicator); + (uint16_t (*)[NUMBER_OF_UE_MAX])nb_rbs_required, + (uint16_t (*)[NUMBER_OF_UE_MAX])nb_rbs_required_remaining, + rballoc_sub); temp_total_rbs_count -= ue_sched_ctl->pre_nb_available_rbs[CC_id]; temp_total_ue_count--; diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index 390d6bf665..fa93a86309 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -2146,6 +2146,37 @@ dump_ue_list(UE_list_t *listP, return; } +//------------------------------------------------------------------------------ +/* + * Add a UE to the UL or DL UE_list listP + */ +void +add_ue_list(UE_list_t *listP, int UE_id, int ul_flag) { + if (ul_flag == 0) { + if (listP->head == -1) { + listP->head = UE_id; + listP->next[UE_id] = -1; + } else { + int i = listP->head; + while (listP->next[i] >= 0) + i = listP->next[i]; + listP->next[i] = UE_id; + listP->next[UE_id] = -1; + } + } else { + if (listP->head_ul == -1) { + listP->head_ul = UE_id; + listP->next_ul[UE_id] = -1; + } else { + int i = listP->head; + while (listP->next_ul[i] >= 0) + i = listP->next[i]; + listP->next_ul[i] = UE_id; + listP->next_ul[UE_id] = -1; + } + } +} + //------------------------------------------------------------------------------ int add_new_ue(module_id_t mod_idP, @@ -2165,7 +2196,6 @@ add_new_ue(module_id_t mod_idP, rntiP, UE_list->avail, UE_list->num_UEs); - dump_ue_list(UE_list, 0); for (i = 0; i < MAX_MOBILES_PER_ENB; i++) { if (UE_list->active[i] == TRUE) @@ -2182,6 +2212,10 @@ add_new_ue(module_id_t mod_idP, UE_list->ordered_ULCCids[0][UE_id] = cc_idP; UE_list->num_UEs++; UE_list->active[UE_id] = TRUE; + add_ue_list(UE_list, UE_id, 0); + dump_ue_list(UE_list, 0); + add_ue_list(UE_list, UE_id, 1); + dump_ue_list(UE_list, 1); if (IS_SOFTMODEM_IQPLAYER)// not specific to record/playback ? UE_list->UE_template[cc_idP][UE_id].pre_assigned_mcs_ul = 0; UE_list->UE_template[cc_idP][UE_id].rach_resource_type = rach_resource_type; @@ -2211,8 +2245,6 @@ add_new_ue(module_id_t mod_idP, UE_id, cc_idP, rntiP); - dump_ue_list(UE_list, - 0); return (UE_id); } @@ -2248,10 +2280,11 @@ rrc_mac_remove_ue(module_id_t mod_idP, UE_id, pCC_id, rntiP); - dump_ue_list(UE_list, 0); // DL list displayed in LOG_T(MAC) UE_list->active[UE_id] = FALSE; UE_list->num_UEs--; + UE_list->next[UE_id] = -1; + UE_list->next_ul[UE_id] = -1; /* If present, remove UE from DL list */ if (UE_list->head == UE_id) { UE_list->head = UE_list->next[UE_id]; @@ -2391,130 +2424,6 @@ prev(UE_list_t *listP, return -1; } -//------------------------------------------------------------------------------ -void -swap_UEs(UE_list_t *listP, - int nodeiP, - int nodejP, - int ul_flag) -//------------------------------------------------------------------------------ -{ - int prev_i, prev_j, next_i, next_j; - LOG_T(MAC, "Swapping UE %d,%d\n", - nodeiP, - nodejP); - dump_ue_list(listP, - ul_flag); - prev_i = prev(listP, - nodeiP, - ul_flag); - prev_j = prev(listP, - nodejP, - ul_flag); - AssertFatal((prev_i >= 0) && (prev_j >= 0), "swap_UEs: problem"); - - if (ul_flag == 0) { - next_i = listP->next[nodeiP]; - next_j = listP->next[nodejP]; - } else { - next_i = listP->next_ul[nodeiP]; - next_j = listP->next_ul[nodejP]; - } - - LOG_T(MAC, "[%s] next_i %d, next_i, next_j %d, head %d \n", - (ul_flag == 0) ? "DL" : "UL", - next_i, - next_j, - listP->head); - - if (ul_flag == 0) { - if (next_i == nodejP) { // case ... p(i) i j n(j) ... => ... p(j) j i n(i) ... - LOG_T(MAC, "Case ... p(i) i j n(j) ... => ... p(j) j i n(i) ...\n"); - listP->next[nodeiP] = next_j; - listP->next[nodejP] = nodeiP; - - if (nodeiP == listP->head) { // case i j n(j) - listP->head = nodejP; - } else { - listP->next[prev_i] = nodejP; - } - } else if (next_j == nodeiP) { // case ... p(j) j i n(i) ... => ... p(i) i j n(j) ... - LOG_T(MAC, "Case ... p(j) j i n(i) ... => ... p(i) i j n(j) ...\n"); - listP->next[nodejP] = next_i; - listP->next[nodeiP] = nodejP; - - if (nodejP == listP->head) { // case j i n(i) - listP->head = nodeiP; - } else { - listP->next[prev_j] = nodeiP; - } - } else { // case ... p(i) i n(i) ... p(j) j n(j) ... - listP->next[nodejP] = next_i; - listP->next[nodeiP] = next_j; - - if (nodeiP == listP->head) { - LOG_T(MAC, "changing head to %d\n", - nodejP); - listP->head = nodejP; - listP->next[prev_j] = nodeiP; - } else if (nodejP == listP->head) { - LOG_D(MAC, "changing head to %d\n", - nodeiP); - listP->head = nodeiP; - listP->next[prev_i] = nodejP; - } else { - listP->next[prev_i] = nodejP; - listP->next[prev_j] = nodeiP; - } - } - } else { // ul_flag - if (next_i == nodejP) { // case ... p(i) i j n(j) ... => ... p(j) j i n(i) ... - LOG_T(MAC, "[UL] Case ... p(i) i j n(j) ... => ... p(j) j i n(i) ...\n"); - listP->next_ul[nodeiP] = next_j; - listP->next_ul[nodejP] = nodeiP; - - if (nodeiP == listP->head_ul) { // case i j n(j) - listP->head_ul = nodejP; - } else { - listP->next_ul[prev_i] = nodejP; - } - } else if (next_j == nodeiP) { // case ... p(j) j i n(i) ... => ... p(i) i j n(j) ... - LOG_T(MAC, "[UL]Case ... p(j) j i n(i) ... => ... p(i) i j n(j) ...\n"); - listP->next_ul[nodejP] = next_i; - listP->next_ul[nodeiP] = nodejP; - - if (nodejP == listP->head_ul) { // case j i n(i) - listP->head_ul = nodeiP; - } else { - listP->next_ul[prev_j] = nodeiP; - } - } else { // case ... p(i) i n(i) ... p(j) j n(j) ... - listP->next_ul[nodejP] = next_i; - listP->next_ul[nodeiP] = next_j; - - if (nodeiP == listP->head_ul) { - LOG_T(MAC, "[UL]changing head to %d\n", - nodejP); - listP->head_ul = nodejP; - listP->next_ul[prev_j] = nodeiP; - } else if (nodejP == listP->head_ul) { - LOG_T(MAC, "[UL]changing head to %d\n", - nodeiP); - listP->head_ul = nodeiP; - listP->next_ul[prev_i] = nodejP; - } else { - listP->next_ul[prev_i] = nodejP; - listP->next_ul[prev_j] = nodeiP; - } - } - } - - LOG_T(MAC, "After swap\n"); - dump_ue_list(listP, - ul_flag); - return; -} - // This has to be updated to include BSR information //------------------------------------------------------------------------------ uint8_t diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h index ac9819cfe2..5a88ce8ddb 100644 --- a/openair2/LAYER2/MAC/mac.h +++ b/openair2/LAYER2/MAC/mac.h @@ -1190,7 +1190,6 @@ typedef struct { uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]; uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]; uint8_t slice_allocation_mask[NFAPI_CC_MAX][N_RBG_MAX]; - uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]; uint32_t bytes_lcid[MAX_MOBILES_PER_ENB][MAX_NUM_LCID]; uint32_t wb_pmi[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]; diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index d9f214f9a2..81f2e0b707 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -245,52 +245,26 @@ void dlsch_scheduler_pre_processor_partitioning(module_id_t Mod_id, const uint8_t rbs_retx[NFAPI_CC_MAX]); void dlsch_scheduler_pre_processor_accounting(module_id_t Mod_id, - int slice_idx, - frame_t frameP, - sub_frame_t subframeP, - int min_rb_unit[NFAPI_CC_MAX], - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]); + int slice_idx, + frame_t frameP, + sub_frame_t subframeP, + uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], + uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]); void dlsch_scheduler_pre_processor_positioning(module_id_t Mod_id, - int slice_idx, - int min_rb_unit[NFAPI_CC_MAX], - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX], - uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]); - -void dlsch_scheduler_pre_processor_intraslice_sharing(module_id_t Mod_id, - int slice_idx, - int min_rb_unit[NFAPI_CC_MAX], - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX], - uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]); - -void slice_priority_sort(module_id_t Mod_id, int slice_list[MAX_NUM_SLICES]); - -void dlsch_scheduler_interslice_multiplexing(module_id_t Mod_id, - int frameP, - sub_frame_t subframeP, - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]); - -void dlsch_scheduler_qos_multiplexing(module_id_t Mod_id, - int frameP, - sub_frame_t subframeP); + int slice_idx, + uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], + uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], + uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], + uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]); void dlsch_scheduler_pre_processor_allocate(module_id_t Mod_id, - int UE_id, - uint8_t CC_id, - int N_RBG, - int min_rb_unit, - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX], - uint8_t slice_allocation_mask[NFAPI_CC_MAX][N_RBG_MAX], - uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]); + int UE_id, + uint8_t CC_id, + int N_RBG, + uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], + uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], + uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]); /* \brief Function to trigger the eNB scheduling procedure. It is called by PHY at the beginning of each subframe, \f$n$\f and generates all DLSCH allocations for subframe \f$n\f$ and ULSCH allocations for subframe \f$n+k$\f. @@ -715,10 +689,10 @@ int add_new_ue(module_id_t Mod_id, int CC_id, rnti_t rnti, int harq_pid, uint8_t int rrc_mac_remove_ue(module_id_t Mod_id, rnti_t rntiP); void store_dlsch_buffer(module_id_t Mod_id, int slice_idx, frame_t frameP, sub_frame_t subframeP); -void assign_rbs_required(module_id_t Mod_id, int slice_idx, frame_t frameP, sub_frame_t subframe, uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], int min_rb_unit[NFAPI_CC_MAX]); +void assign_rbs_required(module_id_t Mod_id, int slice_idx, frame_t frameP, sub_frame_t subframe, uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]); -void swap_UEs(UE_list_t *listP, int nodeiP, int nodejP, int ul_flag); int prev(UE_list_t *listP, int nodeP, int ul_flag); +void add_ue_list(UE_list_t *listP, int UE_id, int ul_flag); void dump_ue_list(UE_list_t *listP, int ul_flag); int UE_num_active_CC(UE_list_t *listP, int ue_idP); int UE_PCCID(module_id_t mod_idP, int ue_idP); @@ -745,7 +719,6 @@ void adjust_bsr_info(int buffer_occupancy, uint16_t TBS, UE_TEMPLATE *UE_template); int phy_stats_exist(module_id_t Mod_id, int rnti); -void sort_UEs(module_id_t Mod_idP, int slice_idx, int frameP, sub_frame_t subframeP); /*! \fn UE_L2_state_t ue_scheduler(const module_id_t module_idP,const frame_t frameP, const sub_frame_t subframe, const lte_subframe_t direction,const uint8_t eNB_index) \brief UE scheduler where all the ue background tasks are done. This function performs the following: 1) Trigger PDCP every 5ms 2) Call RRC for link status return to PHY3) Perform SR/BSR procedures for scheduling feedback 4) Perform PHR procedures. diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index fe8980101d..60f9e8947c 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -50,12 +50,10 @@ void init_UE_list(UE_list_t *UE_list) UE_list->head = -1; UE_list->head_ul = -1; UE_list->avail = 0; - for (list_el = 0; list_el < MAX_MOBILES_PER_ENB - 1; list_el++) { - UE_list->next[list_el] = list_el + 1; - UE_list->next_ul[list_el] = list_el + 1; + for (list_el = 0; list_el < MAX_MOBILES_PER_ENB; list_el++) { + UE_list->next[list_el] = -1; + UE_list->next_ul[list_el] = -1; } - UE_list->next[list_el] = -1; - UE_list->next_ul[list_el] = -1; memset(UE_list->DLSCH_pdu, 0, sizeof(UE_list->DLSCH_pdu)); memset(UE_list->UE_template, 0, sizeof(UE_list->UE_template)); memset(UE_list->eNB_UE_stats, 0, sizeof(UE_list->eNB_UE_stats)); diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 83c514e92d..13a58ea37e 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -52,9 +52,7 @@ extern RAN_CONTEXT_t RC; #define DEBUG_eNB_SCHEDULER 1 #define DEBUG_HEADER_PARSING 1 -//#define DEBUG_PACKET_TRACE 1 -//#define ICIC 0 void sort_ue_ul(module_id_t module_idP, @@ -63,35 +61,6 @@ sort_ue_ul(module_id_t module_idP, sub_frame_t sched_subframeP, rnti_t *rntiTable); -/* this function checks that get_eNB_UE_stats returns - * a non-NULL pointer for all the active CCs of an UE - */ -/* -int phy_stats_exist(module_id_t Mod_id, int rnti) -{ - int CC_id; - int i; - int UE_id = find_UE_id(Mod_id, rnti); - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - if (UE_id == -1) { - LOG_W(MAC, "[eNB %d] UE %x not found, should be there (in phy_stats_exist)\n", - Mod_id, rnti); - return 0; - } - if (UE_list->numactiveCCs[UE_id] == 0) { - LOG_W(MAC, "[eNB %d] UE %x has no active CC (in phy_stats_exist)\n", - Mod_id, rnti); - return 0; - } - for (i = 0; i < UE_list->numactiveCCs[UE_id]; i++) { - CC_id = UE_list->ordered_CCids[i][UE_id]; - if (mac_xface->get_eNB_UE_stats(Mod_id, CC_id, rnti) == NULL) - return 0; - } - return 1; -} -*/ - // This function stores the downlink buffer for all the logical channels void store_dlsch_buffer(module_id_t Mod_id, @@ -175,8 +144,7 @@ assign_rbs_required(module_id_t Mod_id, int slice_idx, frame_t frameP, sub_frame_t subframe, - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - int min_rb_unit[NFAPI_CC_MAX]) { + uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]) { uint16_t TBS = 0; int UE_id, n, i, j, CC_id, pCCid, tmp; UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; @@ -222,11 +190,12 @@ assign_rbs_required(module_id_t Mod_id, for (i = 0; i < UE_list->numactiveCCs[UE_id]; i++) { CC_id = UE_list->ordered_CCids[i][UE_id]; eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id]; + const int min_rb_unit = get_min_rb_unit(Mod_id, CC_id); if (eNB_UE_stats->dlsch_mcs1 == 0) { nb_rbs_required[CC_id][UE_id] = 4; // don't let the TBS get too small } else { - nb_rbs_required[CC_id][UE_id] = min_rb_unit[CC_id]; + nb_rbs_required[CC_id][UE_id] = min_rb_unit; } TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, nb_rbs_required[CC_id][UE_id]); @@ -242,7 +211,7 @@ assign_rbs_required(module_id_t Mod_id, /* calculating required number of RBs for each UE */ while (TBS < UE_list->UE_template[pCCid][UE_id].dl_buffer_total) { - nb_rbs_required[CC_id][UE_id] += min_rb_unit[CC_id]; + nb_rbs_required[CC_id][UE_id] += min_rb_unit; if (nb_rbs_required[CC_id][UE_id] > UE_list->UE_sched_ctrl[UE_id].max_rbs_allowed_slice[CC_id][slice_idx]) { TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, UE_list->UE_sched_ctrl[UE_id].max_rbs_allowed_slice[CC_id][slice_idx]); @@ -255,7 +224,7 @@ assign_rbs_required(module_id_t Mod_id, LOG_D(MAC, "[eNB %d] Frame %d: UE %d on CC %d: RB unit %d, nb_required RB %d (TBS %d, mcs %d)\n", - Mod_id, frameP, UE_id, CC_id, min_rb_unit[CC_id], + Mod_id, frameP, UE_id, CC_id, min_rb_unit, nb_rbs_required[CC_id][UE_id], TBS, eNB_UE_stats->dlsch_mcs1); sli->pre_processor_results[slice_idx].mcs[CC_id][UE_id] = eNB_UE_stats->dlsch_mcs1; @@ -265,33 +234,6 @@ assign_rbs_required(module_id_t Mod_id, } -// This function scans all CC_ids for a particular UE to find the maximum round index of its HARQ processes -int -maxround(module_id_t Mod_id, uint16_t rnti, int frame, - sub_frame_t subframe) { - uint8_t round, round_max = 0, UE_id; - int CC_id, harq_pid; - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - COMMON_channels_t *cc; - - for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_id]; CC_id++) { - cc = &RC.mac[Mod_id]->common_channels[CC_id]; - UE_id = find_UE_id(Mod_id, rnti); - - if(UE_id == -1) - continue; - - harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frame,subframe); - round = UE_list->UE_sched_ctrl[UE_id].round[CC_id][harq_pid]; - - if (round > round_max) { - round_max = round; - } - } - - return round_max; -} - int maxround_ul(module_id_t Mod_id, uint16_t rnti, int sched_frame, sub_frame_t sched_subframe) { @@ -318,229 +260,6 @@ maxround_ul(module_id_t Mod_id, uint16_t rnti, int sched_frame, return round_max; } -// This function scans all CC_ids for a particular UE to find the maximum DL CQI -// it returns -1 if the UE is not found in PHY layer (get_eNB_UE_stats gives NULL) -int maxcqi(module_id_t Mod_id, int32_t UE_id) { - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - int CC_id, n; - int CQI = 0; - - for (n = 0; n < UE_list->numactiveCCs[UE_id]; n++) { - CC_id = UE_list->ordered_CCids[n][UE_id]; - - if (UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id] > CQI) { - CQI = UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id]; - } - } - - return CQI; -} - -long min_lcgidpriority(module_id_t Mod_id, int32_t UE_id) { - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - int i; - int pCC_id = UE_PCCID(Mod_id, UE_id); - long ret = UE_list->UE_template[pCC_id][UE_id].lcgidpriority[0]; - - for (i = 1; i < 11; ++i) { - if (UE_list->UE_template[pCC_id][UE_id].lcgidpriority[i] < ret) - ret = UE_list->UE_template[pCC_id][UE_id].lcgidpriority[i]; - } - - return ret; -} - -struct sort_ue_dl_params { - int Mod_idP; - int frameP; - int subframeP; - int slice_idx; -}; - -static int ue_dl_compare(const void *_a, const void *_b, void *_params) { - struct sort_ue_dl_params *params = _params; - UE_list_t *UE_list = &RC.mac[params->Mod_idP]->UE_list; - int i; - int slice_idx = params->slice_idx; - int UE_id1 = *(const int *) _a; - int UE_id2 = *(const int *) _b; - int rnti1 = UE_RNTI(params->Mod_idP, UE_id1); - int pCC_id1 = UE_PCCID(params->Mod_idP, UE_id1); - int round1 = maxround(params->Mod_idP, rnti1, params->frameP, params->subframeP); - int rnti2 = UE_RNTI(params->Mod_idP, UE_id2); - int pCC_id2 = UE_PCCID(params->Mod_idP, UE_id2); - int round2 = maxround(params->Mod_idP, rnti2, params->frameP, params->subframeP); - int cqi1 = maxcqi(params->Mod_idP, UE_id1); - int cqi2 = maxcqi(params->Mod_idP, UE_id2); - long lcgid1 = min_lcgidpriority(params->Mod_idP, UE_id1); - long lcgid2 = min_lcgidpriority(params->Mod_idP, UE_id2); - - for (i = 0; i < CR_NUM; ++i) { - switch (UE_list->sorting_criteria[slice_idx][i]) { - case CR_ROUND : - if (round1 > round2) - return -1; - - if (round1 < round2) - return 1; - - break; - - case CR_SRB12 : - if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[1] + - UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[2] > - UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[1] + - UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[2]) - return -1; - - if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[1] + - UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_info[2] < - UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[1] + - UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_info[2]) - return 1; - - break; - - case CR_HOL : - if (UE_list-> UE_template[pCC_id1][UE_id1].dl_buffer_head_sdu_creation_time_max > - UE_list-> UE_template[pCC_id2][UE_id2].dl_buffer_head_sdu_creation_time_max) - return -1; - - if (UE_list-> UE_template[pCC_id1][UE_id1].dl_buffer_head_sdu_creation_time_max < - UE_list-> UE_template[pCC_id2][UE_id2].dl_buffer_head_sdu_creation_time_max) - return 1; - - break; - - case CR_LC : - if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_total > - UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_total) - return -1; - - if (UE_list->UE_template[pCC_id1][UE_id1].dl_buffer_total < - UE_list->UE_template[pCC_id2][UE_id2].dl_buffer_total) - return 1; - - break; - - case CR_CQI : - if (cqi1 > cqi2) - return -1; - - if (cqi1 < cqi2) - return 1; - - break; - - case CR_LCP : - if (lcgid1 < lcgid2) - return -1; - - if (lcgid1 > lcgid2) - return 1; - - default : - break; - } - } - - return 0; -} - -void decode_sorting_policy(module_id_t Mod_idP, int slice_idx) { - int i; - UE_list_t *UE_list = &RC.mac[Mod_idP]->UE_list; - uint32_t policy = RC.mac[Mod_idP]->slice_info.dl[slice_idx].sorting; - uint32_t mask = 0x0000000F; - uint16_t criterion; - - for (i = 0; i < CR_NUM; ++i) { - criterion = (uint16_t) (policy >> 4 * (CR_NUM - 1 - i) & mask); - - if (criterion >= CR_NUM) { - LOG_W(MAC, - "Invalid criterion in slice index %d ID %d policy, revert to default policy \n", - slice_idx, RC.mac[Mod_idP]->slice_info.dl[slice_idx].id); - RC.mac[Mod_idP]->slice_info.dl[slice_idx].sorting = 0x12345; - break; - } - - UE_list->sorting_criteria[slice_idx][i] = criterion; - } -} - -void decode_slice_positioning(module_id_t Mod_idP, - int slice_idx, - uint8_t slice_allocation_mask[NFAPI_CC_MAX][N_RBG_MAX]) { - uint8_t CC_id; - int RBG, start_frequency, end_frequency; - - // Init slice_alloc_mask - for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_idP]; ++CC_id) { - for (RBG = 0; RBG < N_RBG_MAX; ++RBG) { - slice_allocation_mask[CC_id][RBG] = 0; - } - } - - start_frequency = RC.mac[Mod_idP]->slice_info.dl[slice_idx].pos_low; - end_frequency = RC.mac[Mod_idP]->slice_info.dl[slice_idx].pos_high; - - for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_idP]; ++CC_id) { - for (RBG = start_frequency; RBG <= end_frequency; ++RBG) { - slice_allocation_mask[CC_id][RBG] = 1; - } - } -} - -//----------------------------------------------------------------------------- -/* - * This function sorts the UEs in order, depending on their dlsch buffer and CQI - */ -void sort_UEs(module_id_t Mod_idP, - int slice_idx, - int frameP, - sub_frame_t subframeP) -//----------------------------------------------------------------------------- -{ - int list[MAX_MOBILES_PER_ENB]; - 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_t *UE_scheduling_control = NULL; - - for (int i = 0; i < MAX_MOBILES_PER_ENB; i++) { - UE_scheduling_control = &(UE_list->UE_sched_ctrl[i]); - - /* Check CDRX configuration and if UE is in active time for this subframe */ - if (UE_scheduling_control->cdrx_configured == TRUE) { - if (UE_scheduling_control->in_active_time == FALSE) { - continue; - } - } - - if (UE_list->active[i] == TRUE && - UE_RNTI(Mod_idP, i) != NOT_A_RNTI && - UE_list->UE_sched_ctrl[i].ul_out_of_sync != 1 && - ue_dl_slice_membership(Mod_idP, i, slice_idx)) { - list[list_size++] = i; - } - } - - decode_sorting_policy(Mod_idP, slice_idx); - qsort_r(list, list_size, sizeof(int), ue_dl_compare, ¶ms); - - if (list_size) { - for (int i = 0; i < list_size - 1; ++i) { - UE_list->next[list[i]] = list[i + 1]; - } - - UE_list->next[list[list_size - 1]] = -1; - UE_list->head = list[0]; - } else { - UE_list->head = -1; - } -} - void dlsch_scheduler_pre_processor_partitioning(module_id_t Mod_id, int slice_idx, const uint8_t rbs_retx[NFAPI_CC_MAX]) { @@ -575,7 +294,6 @@ void dlsch_scheduler_pre_processor_accounting(module_id_t Mod_id, int slice_idx, frame_t frameP, sub_frame_t subframeP, - int min_rb_unit[NFAPI_CC_MAX], uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]) { int UE_id, CC_id; @@ -694,14 +412,15 @@ void dlsch_scheduler_pre_processor_accounting(module_id_t Mod_id, CC_id = UE_list->ordered_CCids[i][UE_id]; ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; available_rbs[CC_id] = ue_sched_ctl->max_rbs_allowed_slice[CC_id][slice_idx]; + const int min_rb_unit = get_min_rb_unit(Mod_id, CC_id); if (ue_count_newtx[CC_id] == 0) { average_rbs_per_user[CC_id] = 0; - } else if (min_rb_unit[CC_id]*ue_count_newtx[CC_id] <= available_rbs[CC_id]) { + } else if (min_rb_unit*ue_count_newtx[CC_id] <= available_rbs[CC_id]) { average_rbs_per_user[CC_id] = (uint16_t)floor(available_rbs[CC_id]/ue_count_newtx[CC_id]); } else { // consider the total number of use that can be scheduled UE - average_rbs_per_user[CC_id] = (uint16_t)min_rb_unit[CC_id]; + average_rbs_per_user[CC_id] = (uint16_t)min_rb_unit; } } } @@ -755,18 +474,14 @@ void dlsch_scheduler_pre_processor_accounting(module_id_t Mod_id, void dlsch_scheduler_pre_processor_positioning(module_id_t Mod_id, int slice_idx, - int min_rb_unit[NFAPI_CC_MAX], uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX], - uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]) { + uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]) { int UE_id, CC_id; int i; - uint8_t slice_allocation_mask[NFAPI_CC_MAX][N_RBG_MAX]; int N_RBG[NFAPI_CC_MAX]; UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - decode_slice_positioning(Mod_id, slice_idx, slice_allocation_mask); for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_id]; CC_id++) { COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id]; @@ -787,91 +502,23 @@ void dlsch_scheduler_pre_processor_positioning(module_id_t Mod_id, if (nb_rbs_required[CC_id][UE_id] > 0) LOG_D(MAC, - "Step 1: nb_rbs_remaining[%d][%d]= %d (accounted %d, required %d, pre_nb_available_rbs %d, N_RBG %d, rb_unit %d)\n", + "Step 1: nb_rbs_remaining[%d][%d]= %d (accounted %d, required %d, pre_nb_available_rbs %d, N_RBG %d)\n", CC_id, UE_id, nb_rbs_remaining[CC_id][UE_id], nb_rbs_accounted[CC_id][UE_id], nb_rbs_required[CC_id][UE_id], UE_list->UE_sched_ctrl[UE_id].pre_nb_available_rbs[CC_id], - N_RBG[CC_id], - min_rb_unit[CC_id]); + N_RBG[CC_id]); LOG_T(MAC, "calling dlsch_scheduler_pre_processor_allocate .. \n "); dlsch_scheduler_pre_processor_allocate(Mod_id, UE_id, CC_id, N_RBG[CC_id], - min_rb_unit[CC_id], nb_rbs_required, nb_rbs_remaining, - rballoc_sub, - slice_allocation_mask, - MIMO_mode_indicator); - } - } -} - -void dlsch_scheduler_pre_processor_intraslice_sharing(module_id_t Mod_id, - int slice_idx, - int min_rb_unit[NFAPI_CC_MAX], - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX], - uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]) { - int UE_id, CC_id; - int i; - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - int N_RBG[NFAPI_CC_MAX]; - slice_info_t *sli = &RC.mac[Mod_id]->slice_info; - uint8_t (*slice_allocation_mask)[N_RBG_MAX] = sli->pre_processor_results[slice_idx].slice_allocation_mask; - decode_slice_positioning(Mod_id, slice_idx, slice_allocation_mask); - - for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_id]; CC_id++) { - COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id]; - N_RBG[CC_id] = to_rbg(cc->mib->message.dl_Bandwidth); - } - - // Remaining RBs are allocated to high priority UEs - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { - if (UE_RNTI(Mod_id, UE_id) == NOT_A_RNTI) continue; - - if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; - - if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx)) continue; - - for (i = 0; i < UE_num_active_CC(UE_list, UE_id); i++) { - CC_id = UE_list->ordered_CCids[i][UE_id]; - nb_rbs_remaining[CC_id][UE_id] = - nb_rbs_required[CC_id][UE_id] - nb_rbs_accounted[CC_id][UE_id] + nb_rbs_remaining[CC_id][UE_id]; - - if (nb_rbs_remaining[CC_id][UE_id] < 0) - abort(); - - if (nb_rbs_required[CC_id][UE_id] > 0) - LOG_D(MAC, - "Step 2: nb_rbs_remaining[%d][%d]= %d (accounted %d, required %d, pre_nb_available_rbs %d, N_RBG %d, rb_unit %d)\n", - CC_id, - UE_id, - nb_rbs_remaining[CC_id][UE_id], - nb_rbs_accounted[CC_id][UE_id], - nb_rbs_required[CC_id][UE_id], - UE_list->UE_sched_ctrl[UE_id].pre_nb_available_rbs[CC_id], - N_RBG[CC_id], - min_rb_unit[CC_id]); - - LOG_T(MAC, "calling dlsch_scheduler_pre_processor_allocate .. \n "); - dlsch_scheduler_pre_processor_allocate(Mod_id, - UE_id, - CC_id, - N_RBG[CC_id], - min_rb_unit[CC_id], - nb_rbs_required, - nb_rbs_remaining, - rballoc_sub, - slice_allocation_mask, - MIMO_mode_indicator); + rballoc_sub); } } } @@ -885,8 +532,6 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, int UE_id; uint16_t i, j; int slice_idx = 0; - int min_rb_unit[NFAPI_CC_MAX]; - min_rb_unit[CC_id] = get_min_rb_unit(Mod_id, CC_id); // TODO: remove NFAPI_CC_MAX, here for compatibility for the moment uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]; memset(rballoc_sub, 0, sizeof(rballoc_sub)); @@ -896,9 +541,6 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, uint16_t (*nb_rbs_required)[MAX_MOBILES_PER_ENB] = sli->pre_processor_results[slice_idx].nb_rbs_required; uint16_t (*nb_rbs_accounted)[MAX_MOBILES_PER_ENB] = sli->pre_processor_results[slice_idx].nb_rbs_accounted; uint16_t (*nb_rbs_remaining)[MAX_MOBILES_PER_ENB] = sli->pre_processor_results[slice_idx].nb_rbs_remaining; - // TODO remove this - uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]; - memset(MIMO_mode_indicator, 0, sizeof(MIMO_mode_indicator)); UE_list_t *UE_list = &eNB->UE_list; UE_sched_ctrl_t *ue_sched_ctl; @@ -919,45 +561,24 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, slice_idx, frameP, subframeP, - nb_rbs_required, - min_rb_unit); - // Sorts the user on the basis of dlsch logical channel buffer and CQI - sort_UEs(Mod_id, - slice_idx, - frameP, - subframeP); + nb_rbs_required); + // ACCOUNTING // This procedure decides the number of RBs to allocate dlsch_scheduler_pre_processor_accounting(Mod_id, - slice_idx, - frameP, - subframeP, - min_rb_unit, - nb_rbs_required, - nb_rbs_accounted); + slice_idx, + frameP, + subframeP, + nb_rbs_required, + nb_rbs_accounted); // POSITIONING // This procedure does the main allocation of the RBs dlsch_scheduler_pre_processor_positioning(Mod_id, - slice_idx, - min_rb_unit, - nb_rbs_required, - nb_rbs_accounted, - nb_rbs_remaining, - rballoc_sub, - MIMO_mode_indicator); - - // SHARING - // If there are available RBs left in the slice, allocate them to the highest priority UEs - if (eNB->slice_info.intraslice_share_active) { - dlsch_scheduler_pre_processor_intraslice_sharing(Mod_id, - slice_idx, - min_rb_unit, - nb_rbs_required, - nb_rbs_accounted, - nb_rbs_remaining, - rballoc_sub, - MIMO_mode_indicator); - } + slice_idx, + nb_rbs_required, + nb_rbs_accounted, + nb_rbs_remaining, + rballoc_sub); for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { @@ -1042,16 +663,14 @@ dlsch_scheduler_pre_processor_allocate(module_id_t Mod_id, int UE_id, uint8_t CC_id, int N_RBG, - int min_rb_unit, uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX], - uint8_t slice_allocation_mask[NFAPI_CC_MAX][N_RBG_MAX], - uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]) { + uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]) { int i; UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; 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); + const int min_rb_unit = get_min_rb_unit(Mod_id, CC_id); for (i = 0; i < N_RBG; i++) { if (rballoc_sub[CC_id][i] != 0) continue; @@ -1064,14 +683,11 @@ dlsch_scheduler_pre_processor_allocate(module_id_t Mod_id, if (ue_sched_ctl->dl_pow_off[CC_id] == 0) continue; - if (slice_allocation_mask[CC_id][i] == 0) continue; - if ((i == N_RBG - 1) && ((N_RB_DL == 25) || (N_RB_DL == 50))) { // Allocating last, smaller RBG if (nb_rbs_remaining[CC_id][UE_id] >= min_rb_unit - 1) { rballoc_sub[CC_id][i] = 1; ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1; - MIMO_mode_indicator[CC_id][i] = 1; nb_rbs_remaining[CC_id][UE_id] = nb_rbs_remaining[CC_id][UE_id] - min_rb_unit + 1; ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit - 1; @@ -1081,7 +697,6 @@ dlsch_scheduler_pre_processor_allocate(module_id_t Mod_id, if (nb_rbs_remaining[CC_id][UE_id] >= min_rb_unit) { rballoc_sub[CC_id][i] = 1; ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1; - MIMO_mode_indicator[CC_id][i] = 1; nb_rbs_remaining[CC_id][UE_id] = nb_rbs_remaining[CC_id][UE_id] - min_rb_unit; ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit; From fd6618dc1cfaa1228dd36e32d7b6667732f207f3 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 17 Jan 2020 13:34:23 +0100 Subject: [PATCH 109/240] Simplify preprocessor, retain functionality * Simplify store_dlsch_buffer() * Simplify assign_rbs_required() * Simplify dlsch_scheduler_pre_processor_partitioning() * Simplify dlsch_scheduler_pre_processor_accounting() and dlsch_scheduler_pre_processor_accounting_allocate() * Simplify allocation printing The original functions used in the fairRR scheduler have been moved to eNB_scheduler_fairRR --- openair2/LAYER2/MAC/eNB_scheduler_fairRR.c | 175 ++++++- openair2/LAYER2/MAC/eNB_scheduler_fairRR.h | 15 + openair2/LAYER2/MAC/mac.h | 15 - openair2/LAYER2/MAC/mac_proto.h | 30 +- openair2/LAYER2/MAC/pre_processor.c | 578 ++++++--------------- 5 files changed, 341 insertions(+), 472 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c index 0e8770d3e2..e934a54c7c 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c @@ -726,7 +726,163 @@ void dlsch_scheduler_pre_processor_reset_fairRR( } } +// This function returns the estimated number of RBs required by each UE for downlink scheduling +void assign_rbs_required_fairRR( + module_id_t Mod_id, + frame_t frameP, + sub_frame_t subframe, + uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]) { + uint16_t TBS = 0; + int UE_id, n, i, j, CC_id, pCCid, tmp; + UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; + eNB_UE_STATS *eNB_UE_stats, *eNB_UE_stats_i, *eNB_UE_stats_j; + int N_RB_DL; + // clear rb allocations across all CC_id + for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) { + if (UE_list->active[UE_id] != TRUE) + continue; + + pCCid = UE_PCCID(Mod_id, UE_id); + + // update CQI information across component carriers + for (n = 0; n < UE_list->numactiveCCs[UE_id]; n++) { + CC_id = UE_list->ordered_CCids[n][UE_id]; + eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id]; + eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id]]; + } + + // provide the list of CCs sorted according to MCS + for (i = 0; i < UE_list->numactiveCCs[UE_id]; ++i) { + eNB_UE_stats_i = + &UE_list->eNB_UE_stats[UE_list->ordered_CCids[i][UE_id]][UE_id]; + + for (j = i + 1; j < UE_list->numactiveCCs[UE_id]; j++) { + DevAssert(j < NFAPI_CC_MAX); + eNB_UE_stats_j = + &UE_list->eNB_UE_stats[UE_list->ordered_CCids[j][UE_id]][UE_id]; + + if (eNB_UE_stats_j->dlsch_mcs1 > eNB_UE_stats_i->dlsch_mcs1) { + tmp = UE_list->ordered_CCids[i][UE_id]; + UE_list->ordered_CCids[i][UE_id] = UE_list->ordered_CCids[j][UE_id]; + UE_list->ordered_CCids[j][UE_id] = tmp; + } + } + } + + if (UE_list->UE_template[pCCid][UE_id].dl_buffer_total > 0) { + LOG_D(MAC, "[preprocessor] assign RB for UE %d\n", UE_id); + + for (i = 0; i < UE_list->numactiveCCs[UE_id]; i++) { + CC_id = UE_list->ordered_CCids[i][UE_id]; + eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id]; + const int min_rb_unit = get_min_rb_unit(Mod_id, CC_id); + + if (eNB_UE_stats->dlsch_mcs1 == 0) { + nb_rbs_required[CC_id][UE_id] = 4; // don't let the TBS get too small + } else { + nb_rbs_required[CC_id][UE_id] = min_rb_unit; + } + + TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, nb_rbs_required[CC_id][UE_id]); + LOG_D(MAC, + "[preprocessor] start RB assignement for UE %d CC_id %d dl " + "buffer %d (RB unit %d, MCS %d, TBS %d) \n", + UE_id, + CC_id, + UE_list->UE_template[pCCid][UE_id].dl_buffer_total, + nb_rbs_required[CC_id][UE_id], + eNB_UE_stats->dlsch_mcs1, + TBS); + N_RB_DL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); + + /* calculating required number of RBs for each UE */ + while (TBS < UE_list->UE_template[pCCid][UE_id].dl_buffer_total) { + nb_rbs_required[CC_id][UE_id] += min_rb_unit; + + if (nb_rbs_required[CC_id][UE_id] > N_RB_DL) { + TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, N_RB_DL); + nb_rbs_required[CC_id][UE_id] = N_RB_DL; + break; + } + + TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, + nb_rbs_required[CC_id][UE_id]); + } // end of while + + LOG_D(MAC, + "[eNB %d] Frame %d: UE %d on CC %d: RB unit %d, nb_required RB " + "%d (TBS %d, mcs %d)\n", + Mod_id, + frameP, + UE_id, + CC_id, + min_rb_unit, + nb_rbs_required[CC_id][UE_id], + TBS, + eNB_UE_stats->dlsch_mcs1); + } + } + } +} + +void dlsch_scheduler_pre_processor_allocate_fairRR( + module_id_t Mod_id, + int UE_id, + uint8_t CC_id, + int N_RBG, + uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], + uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], + uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]) { + int i; + UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; + 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); + const int min_rb_unit = get_min_rb_unit(Mod_id, CC_id); + + for (i = 0; i < N_RBG; i++) { + if (rballoc_sub[CC_id][i] != 0) + continue; + + if (ue_sched_ctl->rballoc_sub_UE[CC_id][i] != 0) + continue; + + if (nb_rbs_remaining[CC_id][UE_id] <= 0) + continue; + + if (ue_sched_ctl->pre_nb_available_rbs[CC_id] + >= nb_rbs_required[CC_id][UE_id]) + continue; + + if (ue_sched_ctl->dl_pow_off[CC_id] == 0) + continue; + + if ((i == N_RBG - 1) && ((N_RB_DL == 25) || (N_RB_DL == 50))) { + // Allocating last, smaller RBG + if (nb_rbs_remaining[CC_id][UE_id] >= min_rb_unit - 1) { + rballoc_sub[CC_id][i] = 1; + ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1; + + nb_rbs_remaining[CC_id][UE_id] = + nb_rbs_remaining[CC_id][UE_id] - min_rb_unit + 1; + ue_sched_ctl->pre_nb_available_rbs[CC_id] = + ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit - 1; + } + } else { + // Allocating a standard-sized RBG + if (nb_rbs_remaining[CC_id][UE_id] >= min_rb_unit) { + rballoc_sub[CC_id][i] = 1; + ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1; + + nb_rbs_remaining[CC_id][UE_id] = + nb_rbs_remaining[CC_id][UE_id] - min_rb_unit; + ue_sched_ctl->pre_nb_available_rbs[CC_id] = + ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit; + } + } + } +} // This function assigns pre-available RBS to each UE in specified sub-bands before scheduling is done void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id, @@ -792,9 +948,9 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id, #if (!defined(PRE_SCD_THREAD)) // Store the DLSCH buffer for each logical channel - store_dlsch_buffer(Mod_id,0, frameP, subframeP); + store_dlsch_buffer(Mod_id, frameP, subframeP); // Calculate the number of RBs required by each UE on the basis of logical channel's buffer - assign_rbs_required(Mod_id, 0, frameP, subframeP, nb_rbs_required); + assign_rbs_required_fairRR(Mod_id, frameP, subframeP, nb_rbs_required); #else memcpy(nb_rbs_required, pre_nb_rbs_required[dlsch_ue_select_tbl_in_use], sizeof(uint16_t)*MAX_NUM_CCs*MAX_MOBILES_PER_ENB); #endif @@ -855,13 +1011,14 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id, } LOG_T(MAC,"calling dlsch_scheduler_pre_processor_allocate .. \n "); - dlsch_scheduler_pre_processor_allocate (Mod_id, - UE_id, - CC_id, - N_RBG[CC_id], - (uint16_t (*)[NUMBER_OF_UE_MAX])nb_rbs_required, - (uint16_t (*)[NUMBER_OF_UE_MAX])nb_rbs_required_remaining, - rballoc_sub); + dlsch_scheduler_pre_processor_allocate_fairRR( + Mod_id, + UE_id, + CC_id, + N_RBG[CC_id], + (uint16_t(*)[NUMBER_OF_UE_MAX])nb_rbs_required, + (uint16_t(*)[NUMBER_OF_UE_MAX])nb_rbs_required_remaining, + rballoc_sub); temp_total_rbs_count -= ue_sched_ctl->pre_nb_available_rbs[CC_id]; temp_total_ue_count--; diff --git a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.h b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.h index 682bebc1a5..880e60ec19 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.h +++ b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.h @@ -94,6 +94,21 @@ void dlsch_scheduler_pre_processor_reset_fairRR( uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX], uint8_t MIMO_mode_indicator[NFAPI_CC_MAX][N_RBG_MAX]); +void assign_rbs_required_fairRR( + module_id_t Mod_id, + frame_t frameP, + sub_frame_t subframe, + uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]); + +void dlsch_scheduler_pre_processor_allocate_fairRR( + module_id_t Mod_id, + int UE_id, + uint8_t CC_id, + int N_RBG, + uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], + uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], + uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]); + void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id, frame_t frameP, sub_frame_t subframeP, diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h index 5a88ce8ddb..191bc4f5a1 100644 --- a/openair2/LAYER2/MAC/mac.h +++ b/openair2/LAYER2/MAC/mac.h @@ -1184,19 +1184,6 @@ typedef struct { int tail_freelist; ///the tail position of the delete list } UE_free_list_t; -/// Structure for saving the output of each pre_processor instance -typedef struct { - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]; - uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]; - uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]; - uint8_t slice_allocation_mask[NFAPI_CC_MAX][N_RBG_MAX]; - - uint32_t bytes_lcid[MAX_MOBILES_PER_ENB][MAX_NUM_LCID]; - uint32_t wb_pmi[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]; - uint8_t mcs[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]; - -} pre_processor_results_t; - /** * slice specific scheduler for the DL */ @@ -1288,8 +1275,6 @@ typedef struct { int n_ul; slice_sched_conf_ul_t ul[MAX_NUM_SLICES]; - pre_processor_results_t pre_processor_results[MAX_NUM_SLICES]; - /// common rb allocation list between slices uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]; } slice_info_t; diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index 81f2e0b707..be50c7d733 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -240,31 +240,25 @@ void dlsch_scheduler_pre_processor_reset(module_id_t module_idP, int CC_id, uint8_t rballoc_sub[N_RBG_MAX]); -void dlsch_scheduler_pre_processor_partitioning(module_id_t Mod_id, - int slice_idx, - const uint8_t rbs_retx[NFAPI_CC_MAX]); - void dlsch_scheduler_pre_processor_accounting(module_id_t Mod_id, - int slice_idx, + int CC_id, frame_t frameP, sub_frame_t subframeP, - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]); + uint16_t nb_rbs_required[MAX_MOBILES_PER_ENB], + uint16_t nb_rbs_accounted[MAX_MOBILES_PER_ENB]); void dlsch_scheduler_pre_processor_positioning(module_id_t Mod_id, - int slice_idx, - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]); + int CC_id, + uint16_t nb_rbs_required[MAX_MOBILES_PER_ENB], + uint16_t nb_rbs_accounted[MAX_MOBILES_PER_ENB], + uint8_t rballoc_sub[N_RBG_MAX]); void dlsch_scheduler_pre_processor_allocate(module_id_t Mod_id, int UE_id, uint8_t CC_id, - int N_RBG, - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]); + uint16_t nb_rbs_required, + uint16_t *nb_rbs_remaining, + uint8_t rballoc_sub[N_RBG_MAX]); /* \brief Function to trigger the eNB scheduling procedure. It is called by PHY at the beginning of each subframe, \f$n$\f and generates all DLSCH allocations for subframe \f$n\f$ and ULSCH allocations for subframe \f$n+k$\f. @@ -688,8 +682,8 @@ int mac_init(void); int add_new_ue(module_id_t Mod_id, int CC_id, rnti_t rnti, int harq_pid, uint8_t rach_resource_type); int rrc_mac_remove_ue(module_id_t Mod_id, rnti_t rntiP); -void store_dlsch_buffer(module_id_t Mod_id, int slice_idx, frame_t frameP, sub_frame_t subframeP); -void assign_rbs_required(module_id_t Mod_id, int slice_idx, frame_t frameP, sub_frame_t subframe, uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]); +void store_dlsch_buffer(module_id_t Mod_id, frame_t frameP, sub_frame_t subframeP); +void assign_rbs_required(module_id_t Mod_id, int CC_id, uint16_t nb_rbs_required[MAX_MOBILES_PER_ENB]); int prev(UE_list_t *listP, int nodeP, int ul_flag); void add_ue_list(UE_list_t *listP, int UE_id, int ul_flag); diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 13a58ea37e..90cced9c49 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -64,40 +64,34 @@ sort_ue_ul(module_id_t module_idP, // This function stores the downlink buffer for all the logical channels void store_dlsch_buffer(module_id_t Mod_id, - int slice_idx, frame_t frameP, sub_frame_t subframeP) { - int UE_id, lcid; - rnti_t rnti; - mac_rlc_status_resp_t rlc_status; UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - UE_TEMPLATE *UE_template; - for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) { + for (int UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) { if (UE_list->active[UE_id] != TRUE) continue; - if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx)) - continue; - - UE_template = &UE_list->UE_template[UE_PCCID(Mod_id, UE_id)][UE_id]; - // clear logical channel interface variables + /* TODO why UE_template per CC? */ + UE_TEMPLATE *UE_template = &UE_list->UE_template[UE_PCCID(Mod_id, UE_id)][UE_id]; UE_template->dl_buffer_total = 0; UE_template->dl_pdus_total = 0; - for (lcid = 0; lcid < MAX_NUM_LCID; ++lcid) { - UE_template->dl_buffer_info[lcid] = 0; - UE_template->dl_pdus_in_buffer[lcid] = 0; - UE_template->dl_buffer_head_sdu_creation_time[lcid] = 0; - UE_template->dl_buffer_head_sdu_remaining_size_to_send[lcid] = 0; - } + const rnti_t rnti = UE_RNTI(Mod_id, UE_id); - rnti = UE_RNTI(Mod_id, UE_id); - - for (lcid = 0; lcid < MAX_NUM_LCID; ++lcid) { // loop over all the logical channels - rlc_status = mac_rlc_status_ind(Mod_id, rnti, Mod_id, frameP, subframeP, - ENB_FLAG_YES, MBMS_FLAG_NO, lcid, 0,0, 0 - ); + for (int lcid = 0; lcid < MAX_NUM_LCID; ++lcid) { // loop over all the logical channels + const mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(Mod_id, + rnti, + Mod_id, + frameP, + subframeP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + lcid, + 0, + 0, + 0 + ); UE_template->dl_buffer_info[lcid] = rlc_status.bytes_in_buffer; //storing the dlsch buffer for each logical channel UE_template->dl_pdus_in_buffer[lcid] = rlc_status.pdus_in_buffer; UE_template->dl_buffer_head_sdu_creation_time[lcid] = rlc_status.head_sdu_creation_time; @@ -107,21 +101,20 @@ store_dlsch_buffer(module_id_t Mod_id, UE_template->dl_buffer_head_sdu_is_segmented[lcid] = rlc_status.head_sdu_is_segmented; UE_template->dl_buffer_total += UE_template->dl_buffer_info[lcid]; //storing the total dlsch buffer UE_template->dl_pdus_total += UE_template->dl_pdus_in_buffer[lcid]; -#ifdef DEBUG_eNB_SCHEDULER +#ifdef DEBUG_eNB_SCHEDULER /* note for dl_buffer_head_sdu_remaining_size_to_send[lcid] : * 0 if head SDU has not been segmented (yet), else remaining size not already segmented and sent */ if (UE_template->dl_buffer_info[lcid] > 0) LOG_D(MAC, - "[eNB %d][SLICE %d] Frame %d Subframe %d : RLC status for UE %d in LCID%d: total of %d pdus and size %d, head sdu queuing time %d, remaining size %d, is segmeneted %d \n", - Mod_id, RC.mac[Mod_id]->slice_info.dl[slice_idx].id, frameP, + "[eNB %d] Frame %d Subframe %d : RLC status for UE %d in LCID%d: total of %d pdus and size %d, head sdu queuing time %d, remaining size %d, is segmeneted %d \n", + Mod_id, frameP, subframeP, UE_id, lcid, UE_template->dl_pdus_in_buffer[lcid], UE_template->dl_buffer_info[lcid], UE_template->dl_buffer_head_sdu_creation_time[lcid], UE_template->dl_buffer_head_sdu_remaining_size_to_send[lcid], UE_template->dl_buffer_head_sdu_is_segmented[lcid]); - #endif } @@ -134,102 +127,37 @@ store_dlsch_buffer(module_id_t Mod_id, } } -int cqi2mcs(int cqi) { - return cqi_to_mcs[cqi]; +// This function returns the estimated number of RBs required to send the full +// buffer +int get_rbs_required(module_id_t Mod_id, + int CC_id, + int UE_id) { + const UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; + + if (UE_list->UE_template[CC_id][UE_id].dl_buffer_total == 0) + return 0; + + const int dlsch_mcs1 = cqi_to_mcs[UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id]]; + const int min_rb_unit = get_min_rb_unit(Mod_id, CC_id); + int nb_rbs_required = min_rb_unit; + /* calculating required number of RBs for each UE */ + int TBS = get_TBS_DL(dlsch_mcs1, nb_rbs_required); + while (TBS < UE_list->UE_template[CC_id][UE_id].dl_buffer_total) { + nb_rbs_required += min_rb_unit; + TBS = get_TBS_DL(dlsch_mcs1, nb_rbs_required); + } + return nb_rbs_required; } -// This function returns the estimated number of RBs required by each UE for downlink scheduling void assign_rbs_required(module_id_t Mod_id, - int slice_idx, - frame_t frameP, - sub_frame_t subframe, - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]) { - uint16_t TBS = 0; - int UE_id, n, i, j, CC_id, pCCid, tmp; + int CC_id, + uint16_t nb_rbs_required[MAX_MOBILES_PER_ENB]) { UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - slice_info_t *sli = &RC.mac[Mod_id]->slice_info; - eNB_UE_STATS *eNB_UE_stats, *eNB_UE_stats_i, *eNB_UE_stats_j; - int N_RB_DL; - - // clear rb allocations across all CC_id - for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) { - if (UE_list->active[UE_id] != TRUE) continue; - - if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx)) continue; - - pCCid = UE_PCCID(Mod_id, UE_id); - - //update CQI information across component carriers - for (n = 0; n < UE_list->numactiveCCs[UE_id]; n++) { - CC_id = UE_list->ordered_CCids[n][UE_id]; - eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id]; - // eNB_UE_stats->dlsch_mcs1 = cmin(cqi_to_mcs[UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id]], sli->dl[slice_idx].maxmcs); - eNB_UE_stats->dlsch_mcs1 = cmin(cqi2mcs(UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id]), sli->dl[slice_idx].maxmcs); - } - - // provide the list of CCs sorted according to MCS - for (i = 0; i < UE_list->numactiveCCs[UE_id]; ++i) { - eNB_UE_stats_i = &UE_list->eNB_UE_stats[UE_list->ordered_CCids[i][UE_id]][UE_id]; - - for (j = i + 1; j < UE_list->numactiveCCs[UE_id]; j++) { - DevAssert(j < NFAPI_CC_MAX); - eNB_UE_stats_j = &UE_list->eNB_UE_stats[UE_list->ordered_CCids[j][UE_id]][UE_id]; - - if (eNB_UE_stats_j->dlsch_mcs1 > eNB_UE_stats_i->dlsch_mcs1) { - tmp = UE_list->ordered_CCids[i][UE_id]; - UE_list->ordered_CCids[i][UE_id] = UE_list->ordered_CCids[j][UE_id]; - UE_list->ordered_CCids[j][UE_id] = tmp; - } - } - } - - if (UE_list->UE_template[pCCid][UE_id].dl_buffer_total > 0) { - LOG_D(MAC, "[preprocessor] assign RB for UE %d\n", UE_id); - - for (i = 0; i < UE_list->numactiveCCs[UE_id]; i++) { - CC_id = UE_list->ordered_CCids[i][UE_id]; - eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id]; - const int min_rb_unit = get_min_rb_unit(Mod_id, CC_id); - - if (eNB_UE_stats->dlsch_mcs1 == 0) { - nb_rbs_required[CC_id][UE_id] = 4; // don't let the TBS get too small - } else { - nb_rbs_required[CC_id][UE_id] = min_rb_unit; - } - - TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, nb_rbs_required[CC_id][UE_id]); - LOG_D(MAC, - "[preprocessor] start RB assignement for UE %d CC_id %d dl buffer %d (RB unit %d, MCS %d, TBS %d) \n", - UE_id, CC_id, - UE_list->UE_template[pCCid][UE_id].dl_buffer_total, - nb_rbs_required[CC_id][UE_id], - eNB_UE_stats->dlsch_mcs1, TBS); - N_RB_DL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); - UE_list->UE_sched_ctrl[UE_id].max_rbs_allowed_slice[CC_id][slice_idx] = - nb_rbs_allowed_slice(sli->dl[slice_idx].pct, N_RB_DL); - - /* calculating required number of RBs for each UE */ - while (TBS < UE_list->UE_template[pCCid][UE_id].dl_buffer_total) { - nb_rbs_required[CC_id][UE_id] += min_rb_unit; - - if (nb_rbs_required[CC_id][UE_id] > UE_list->UE_sched_ctrl[UE_id].max_rbs_allowed_slice[CC_id][slice_idx]) { - TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, UE_list->UE_sched_ctrl[UE_id].max_rbs_allowed_slice[CC_id][slice_idx]); - nb_rbs_required[CC_id][UE_id] = UE_list->UE_sched_ctrl[UE_id].max_rbs_allowed_slice[CC_id][slice_idx]; - break; - } - - TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, nb_rbs_required[CC_id][UE_id]); - } // end of while - - LOG_D(MAC, - "[eNB %d] Frame %d: UE %d on CC %d: RB unit %d, nb_required RB %d (TBS %d, mcs %d)\n", - Mod_id, frameP, UE_id, CC_id, min_rb_unit, - nb_rbs_required[CC_id][UE_id], TBS, - eNB_UE_stats->dlsch_mcs1); - sli->pre_processor_results[slice_idx].mcs[CC_id][UE_id] = eNB_UE_stats->dlsch_mcs1; - } - } + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + nb_rbs_required[UE_id] = get_rbs_required(Mod_id, CC_id, UE_id); + // TODO: the following should not be here + UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = cqi_to_mcs[UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id]]; } } @@ -260,266 +188,87 @@ maxround_ul(module_id_t Mod_id, uint16_t rnti, int sched_frame, return round_max; } -void dlsch_scheduler_pre_processor_partitioning(module_id_t Mod_id, - int slice_idx, - 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_t *ue_sched_ctl; - uint16_t available_rbs; - - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { - if (UE_RNTI(Mod_id, UE_id) == NOT_A_RNTI) continue; - - if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; - - if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx)) continue; - - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - - for (i = 0; i < UE_num_active_CC(UE_list, UE_id); ++i) { - CC_id = UE_list->ordered_CCids[i][UE_id]; - N_RB_DL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); - available_rbs = nb_rbs_allowed_slice(RC.mac[Mod_id]->slice_info.dl[slice_idx].pct, N_RB_DL); - - if (rbs_retx[CC_id] < available_rbs) - ue_sched_ctl->max_rbs_allowed_slice[CC_id][slice_idx] = available_rbs - rbs_retx[CC_id]; - else - ue_sched_ctl->max_rbs_allowed_slice[CC_id][slice_idx] = 0; - } - } -} - void dlsch_scheduler_pre_processor_accounting(module_id_t Mod_id, - int slice_idx, - frame_t frameP, - sub_frame_t subframeP, - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]) { - int UE_id, CC_id; - int i; - rnti_t rnti; - uint8_t harq_pid, round; - uint16_t available_rbs[NFAPI_CC_MAX]; - uint8_t rbs_retx[NFAPI_CC_MAX]; - uint16_t average_rbs_per_user[NFAPI_CC_MAX]; - int total_ue_count[NFAPI_CC_MAX]; - int ue_count_newtx[NFAPI_CC_MAX]; - 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_t *ue_sched_ctl; - COMMON_channels_t *cc; + int CC_id, + frame_t frameP, + sub_frame_t subframeP, + uint16_t nb_rbs_required[MAX_MOBILES_PER_ENB], + uint16_t nb_rbs_accounted[MAX_MOBILES_PER_ENB]) { + uint16_t available_rbs = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); + uint8_t rbs_retx = 0; + uint16_t average_rbs_per_user = 0; + int ue_count_newtx = 0; + int ue_count_retx = 0; - // Reset - for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_id]; CC_id++) { - total_ue_count[CC_id] = 0; - ue_count_newtx[CC_id] = 0; - ue_count_retx[CC_id] = 0; - rbs_retx[CC_id] = 0; - average_rbs_per_user[CC_id] = 0; - available_rbs[CC_id] = 0; - //for (UE_id = 0; UE_id < NFAPI_CC_MAX; ++UE_id) { - // ue_retx_flag[CC_id][UE_id] = 0; - //} - } + UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; // Find total UE count, and account the RBs required for retransmissions - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { - rnti = UE_RNTI(Mod_id, UE_id); - + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + const rnti_t rnti = UE_RNTI(Mod_id, UE_id); if (rnti == NOT_A_RNTI) continue; - if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; - if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx)) continue; + const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id]; + const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP,subframeP); + const uint8_t round = UE_list->UE_sched_ctrl[UE_id].round[CC_id][harq_pid]; - for (i = 0; i < UE_num_active_CC(UE_list, UE_id); ++i) { - CC_id = UE_list->ordered_CCids[i][UE_id]; - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - cc = &RC.mac[Mod_id]->common_channels[CC_id]; - harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP,subframeP); - round = ue_sched_ctl->round[CC_id][harq_pid]; - - if (nb_rbs_required[CC_id][UE_id] > 0) { - total_ue_count[CC_id]++; - } - - if (round != 8) { - nb_rbs_required[CC_id][UE_id] = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid]; - rbs_retx[CC_id] += nb_rbs_required[CC_id][UE_id]; - ue_count_retx[CC_id]++; - //ue_retx_flag[CC_id][UE_id] = 1; - } else { - ue_count_newtx[CC_id]++; - } + // retransmission + if (round != 8) { + nb_rbs_required[UE_id] = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid]; + rbs_retx += nb_rbs_required[UE_id]; + ue_count_retx++; + } else { + ue_count_newtx++; } } - // PARTITIONING - // Reduces the available RBs according to slicing configuration - dlsch_scheduler_pre_processor_partitioning(Mod_id, slice_idx, rbs_retx); + available_rbs = available_rbs - rbs_retx; + const int min_rb_unit = get_min_rb_unit(Mod_id, CC_id); - for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_id]; ++CC_id) { - if (UE_list->head < 0) continue; // no UEs in list - - // max_rbs_allowed_slice is saved in every UE, so take it from the first one - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_list->head]; - available_rbs[CC_id] = ue_sched_ctl->max_rbs_allowed_slice[CC_id][slice_idx]; + if (ue_count_newtx == 0) { + average_rbs_per_user = 0; + } else if (min_rb_unit*ue_count_newtx <= available_rbs) { + average_rbs_per_user = (uint16_t)floor(available_rbs/ue_count_newtx); + } else { + // consider the total number of use that can be scheduled UE + average_rbs_per_user = (uint16_t)min_rb_unit; } - switch (RC.mac[Mod_id]->slice_info.dl[slice_idx].accounting) { - // If greedy scheduling, try to account all the required RBs - case POL_GREEDY: - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { - rnti = UE_RNTI(Mod_id, UE_id); - - if (rnti == NOT_A_RNTI) continue; - - if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; - - if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx)) continue; - - for (i = 0; i < UE_num_active_CC(UE_list, UE_id); i++) { - CC_id = UE_list->ordered_CCids[i][UE_id]; - - if (available_rbs[CC_id] == 0) continue; - - nb_rbs_accounted[CC_id][UE_id] = cmin(nb_rbs_required[CC_id][UE_id], available_rbs[CC_id]); - available_rbs[CC_id] -= nb_rbs_accounted[CC_id][UE_id]; - } - } - - break; - - // Use the old, fair algorithm - // Loop over all active UEs and account the avg number of RBs to each UE, based on all non-retx UEs. - // case POL_FAIR: - default: - - // FIXME: This is not ideal, why loop on UEs to find average_rbs_per_user[], that is per-CC? - // TODO: Look how to loop on active CCs only without using the UE_num_active_CC() function. - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { - rnti = UE_RNTI(Mod_id, UE_id); - - if (rnti == NOT_A_RNTI) continue; - - if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; - - if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx)) continue; - - for (i = 0; i < UE_num_active_CC(UE_list, UE_id); ++i) { - CC_id = UE_list->ordered_CCids[i][UE_id]; - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - available_rbs[CC_id] = ue_sched_ctl->max_rbs_allowed_slice[CC_id][slice_idx]; - const int min_rb_unit = get_min_rb_unit(Mod_id, CC_id); - - if (ue_count_newtx[CC_id] == 0) { - average_rbs_per_user[CC_id] = 0; - } else if (min_rb_unit*ue_count_newtx[CC_id] <= available_rbs[CC_id]) { - average_rbs_per_user[CC_id] = (uint16_t)floor(available_rbs[CC_id]/ue_count_newtx[CC_id]); - } else { - // consider the total number of use that can be scheduled UE - average_rbs_per_user[CC_id] = (uint16_t)min_rb_unit; - } - } - } - - // note: nb_rbs_required is assigned according to total_buffer_dl - // extend nb_rbs_required to capture per LCID RB required - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { - rnti = UE_RNTI(Mod_id, UE_id); - - if (rnti == NOT_A_RNTI) continue; - - if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; - - if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx)) continue; - - for (i = 0; i < UE_num_active_CC(UE_list, UE_id); i++) { - CC_id = UE_list->ordered_CCids[i][UE_id]; - nb_rbs_accounted[CC_id][UE_id] = cmin(average_rbs_per_user[CC_id], nb_rbs_required[CC_id][UE_id]); - } - } - - break; - } - - // Check retransmissions - // TODO: Do this once at the beginning - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { - rnti = UE_RNTI(Mod_id, UE_id); - + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + const rnti_t rnti = UE_RNTI(Mod_id, UE_id); if (rnti == NOT_A_RNTI) continue; - if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; - if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx)) continue; + const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id]; + const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP,subframeP); + const uint8_t round = UE_list->UE_sched_ctrl[UE_id].round[CC_id][harq_pid]; - for (i = 0; i < UE_num_active_CC(UE_list, UE_id); i++) { - CC_id = UE_list->ordered_CCids[i][UE_id]; - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - cc = &RC.mac[Mod_id]->common_channels[CC_id]; - harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP,subframeP); - round = ue_sched_ctl->round[CC_id][harq_pid]; - - // control channel or retransmission - /* TODO: do we have to check for retransmission? */ - if (mac_eNB_get_rrc_status(Mod_id, rnti) < RRC_RECONFIGURED || round != 8) { - nb_rbs_accounted[CC_id][UE_id] = nb_rbs_required[CC_id][UE_id]; - } - } + /* TODO the first seems unnecessary, remove it */ + if (mac_eNB_get_rrc_status(Mod_id, rnti) < RRC_RECONFIGURED || round != 8) + nb_rbs_accounted[UE_id] = nb_rbs_required[UE_id]; + else + nb_rbs_accounted[UE_id] = cmin(average_rbs_per_user, nb_rbs_required[UE_id]); } } void dlsch_scheduler_pre_processor_positioning(module_id_t Mod_id, - int slice_idx, - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_accounted[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]) { - int UE_id, CC_id; - int i; - int N_RBG[NFAPI_CC_MAX]; + int CC_id, + uint16_t nb_rbs_required[MAX_MOBILES_PER_ENB], + uint16_t nb_rbs_accounted[MAX_MOBILES_PER_ENB], + uint8_t rballoc_sub[N_RBG_MAX]) { UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_id]; CC_id++) { - COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id]; - N_RBG[CC_id] = to_rbg(cc->mib->message.dl_Bandwidth); - } - - // Try to allocate accounted RBs - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { if (UE_RNTI(Mod_id, UE_id) == NOT_A_RNTI) continue; - if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; - if (!ue_dl_slice_membership(Mod_id, UE_id, slice_idx)) continue; + dlsch_scheduler_pre_processor_allocate(Mod_id, + UE_id, + CC_id, + nb_rbs_required[UE_id], + &nb_rbs_accounted[UE_id], + rballoc_sub); - for (i = 0; i < UE_num_active_CC(UE_list, UE_id); i++) { - CC_id = UE_list->ordered_CCids[i][UE_id]; - nb_rbs_remaining[CC_id][UE_id] = nb_rbs_accounted[CC_id][UE_id]; - - if (nb_rbs_required[CC_id][UE_id] > 0) - LOG_D(MAC, - "Step 1: nb_rbs_remaining[%d][%d]= %d (accounted %d, required %d, pre_nb_available_rbs %d, N_RBG %d)\n", - CC_id, - UE_id, - nb_rbs_remaining[CC_id][UE_id], - nb_rbs_accounted[CC_id][UE_id], - nb_rbs_required[CC_id][UE_id], - UE_list->UE_sched_ctrl[UE_id].pre_nb_available_rbs[CC_id], - N_RBG[CC_id]); - - LOG_T(MAC, "calling dlsch_scheduler_pre_processor_allocate .. \n "); - dlsch_scheduler_pre_processor_allocate(Mod_id, - UE_id, - CC_id, - N_RBG[CC_id], - nb_rbs_required, - nb_rbs_remaining, - rballoc_sub); - } } } @@ -529,91 +278,66 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, int CC_id, frame_t frameP, sub_frame_t subframeP) { - int UE_id; - uint16_t i, j; - int slice_idx = 0; - // TODO: remove NFAPI_CC_MAX, here for compatibility for the moment - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]; + uint8_t rballoc_sub[N_RBG_MAX]; memset(rballoc_sub, 0, sizeof(rballoc_sub)); - eNB_MAC_INST *eNB = RC.mac[Mod_id]; - slice_info_t *sli = &eNB->slice_info; - uint16_t (*nb_rbs_required)[MAX_MOBILES_PER_ENB] = sli->pre_processor_results[slice_idx].nb_rbs_required; - uint16_t (*nb_rbs_accounted)[MAX_MOBILES_PER_ENB] = sli->pre_processor_results[slice_idx].nb_rbs_accounted; - uint16_t (*nb_rbs_remaining)[MAX_MOBILES_PER_ENB] = sli->pre_processor_results[slice_idx].nb_rbs_remaining; - - UE_list_t *UE_list = &eNB->UE_list; - UE_sched_ctrl_t *ue_sched_ctl; - // Initialize scheduling information for all active UEs - memset(&sli->pre_processor_results[slice_idx], 0, sizeof(sli->pre_processor_results[slice_idx])); dlsch_scheduler_pre_processor_reset(Mod_id, CC_id, - rballoc_sub[CC_id]); - // STATUS - // Store the DLSCH buffer for each logical channel + rballoc_sub); + store_dlsch_buffer(Mod_id, - slice_idx, frameP, subframeP); + // Calculate the number of RBs required by each UE on the basis of logical channel's buffer + uint16_t nb_rbs_required[MAX_MOBILES_PER_ENB]; + memset(nb_rbs_required, 0, sizeof(nb_rbs_required)); assign_rbs_required(Mod_id, - slice_idx, - frameP, - subframeP, + CC_id, nb_rbs_required); - // ACCOUNTING - // This procedure decides the number of RBs to allocate + + // Decide the number of RBs to allocate + uint16_t nb_rbs_accounted[MAX_MOBILES_PER_ENB]; + memset(nb_rbs_accounted, 0, sizeof(nb_rbs_accounted)); dlsch_scheduler_pre_processor_accounting(Mod_id, - slice_idx, + CC_id, frameP, subframeP, nb_rbs_required, nb_rbs_accounted); + // POSITIONING // This procedure does the main allocation of the RBs dlsch_scheduler_pre_processor_positioning(Mod_id, - slice_idx, + CC_id, nb_rbs_required, nb_rbs_accounted, - nb_rbs_remaining, rballoc_sub); + const UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; + const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id]; + const int N_RBG = to_rbg(cc->mib->message.dl_Bandwidth); + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + const UE_sched_ctrl_t *ue_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id]; - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + if (ue_sched_ctrl->pre_nb_available_rbs[CC_id] == 0) + continue; - for (i = 0; i < UE_num_active_CC(UE_list, UE_id); i++) { - CC_id = UE_list->ordered_CCids[i][UE_id]; - //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].dl_pow_off = dl_pow_off[UE_id]; - COMMON_channels_t *cc = &eNB->common_channels[CC_id]; - int N_RBG = to_rbg(cc->mib->message.dl_Bandwidth); + char s[101]; + for (int i = 0; i < N_RBG; i++) + sprintf(&s[i*2], " %d", ue_sched_ctrl->rballoc_sub_UE[CC_id][i]); - if (ue_sched_ctl->pre_nb_available_rbs[CC_id] > 0) { - LOG_D(MAC, "******************DL Scheduling Information for UE%d ************************\n", - UE_id); - LOG_D(MAC, "dl power offset UE%d = %d \n", - UE_id, - ue_sched_ctl->dl_pow_off[CC_id]); - LOG_D(MAC, "***********RB Alloc for every subband for UE%d ***********\n", - UE_id); - - for (j = 0; j < N_RBG; j++) { - //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].rballoc_sub[UE_id] = rballoc_sub_UE[CC_id][UE_id][UE_id]; - LOG_D(MAC, "RB Alloc for UE%d and Subband%d = %d\n", - UE_id, j, - ue_sched_ctl->rballoc_sub_UE[CC_id][j]); - } - - //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].pre_nb_available_rbs = pre_nb_available_rbs[CC_id][UE_id]; - LOG_D(MAC, "[eNB %d][SLICE %d]Total RBs allocated for UE%d = %d\n", - Mod_id, - eNB->slice_info.dl[slice_idx].id, - UE_id, - ue_sched_ctl->pre_nb_available_rbs[CC_id]); - } - } + LOG_D(MAC, + "%d/%d allocation UE %d RNTI %x:%s, total %d, MCS %d\n", + frameP, + subframeP, + UE_id, + UE_list->UE_template[CC_id][UE_id].rnti, + s, + ue_sched_ctrl->pre_nb_available_rbs[CC_id], + UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1); } } @@ -662,43 +386,37 @@ void dlsch_scheduler_pre_processor_allocate(module_id_t Mod_id, int UE_id, uint8_t CC_id, - int N_RBG, - uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]) { - int i; - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - 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); + uint16_t nb_rbs_required, + uint16_t *nb_rbs_remaining, + uint8_t rballoc_sub[N_RBG_MAX]) { + UE_sched_ctrl_t *ue_sched_ctl = &RC.mac[Mod_id]->UE_list.UE_sched_ctrl[UE_id]; + const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); + const int N_RB_DL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); const int min_rb_unit = get_min_rb_unit(Mod_id, CC_id); - for (i = 0; i < N_RBG; i++) { - if (rballoc_sub[CC_id][i] != 0) continue; - + for (int i = 0; i < N_RBG; i++) { + if (rballoc_sub[i] != 0) continue; if (ue_sched_ctl->rballoc_sub_UE[CC_id][i] != 0) continue; - - if (nb_rbs_remaining[CC_id][UE_id] <= 0) continue; - - if (ue_sched_ctl->pre_nb_available_rbs[CC_id] >= nb_rbs_required[CC_id][UE_id]) continue; - + if (*nb_rbs_remaining <= 0) continue; + if (ue_sched_ctl->pre_nb_available_rbs[CC_id] >= nb_rbs_required) continue; if (ue_sched_ctl->dl_pow_off[CC_id] == 0) continue; if ((i == N_RBG - 1) && ((N_RB_DL == 25) || (N_RB_DL == 50))) { // Allocating last, smaller RBG - if (nb_rbs_remaining[CC_id][UE_id] >= min_rb_unit - 1) { - rballoc_sub[CC_id][i] = 1; + if (*nb_rbs_remaining >= min_rb_unit - 1) { + rballoc_sub[i] = 1; ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1; - nb_rbs_remaining[CC_id][UE_id] = nb_rbs_remaining[CC_id][UE_id] - min_rb_unit + 1; + *nb_rbs_remaining -= min_rb_unit + 1; ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit - 1; } } else { // Allocating a standard-sized RBG - if (nb_rbs_remaining[CC_id][UE_id] >= min_rb_unit) { - rballoc_sub[CC_id][i] = 1; + if (*nb_rbs_remaining >= min_rb_unit) { + rballoc_sub[i] = 1; ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1; - nb_rbs_remaining[CC_id][UE_id] = nb_rbs_remaining[CC_id][UE_id] - min_rb_unit; + *nb_rbs_remaining -= min_rb_unit; ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit; } } From 7c92456338dad32f100f6a5a4e31e3bb00302fe0 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 23 Jan 2020 18:17:02 +0100 Subject: [PATCH 110/240] Remove DL Slicing-related variables --- openair2/ENB_APP/flexran_agent_ran_api.c | 16 +++++++-------- .../LAYER2/MAC/eNB_scheduler_primitives.c | 20 ------------------- openair2/LAYER2/MAC/mac.h | 3 --- openair2/LAYER2/MAC/mac_proto.h | 1 - openair2/LAYER2/MAC/main.c | 1 - 5 files changed, 8 insertions(+), 33 deletions(-) diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index a66081d99f..e917d9d6dc 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -3016,7 +3016,7 @@ uint32_t flexran_get_rrc_enb_ue_s1ap_id(mid_t mod_id, rnti_t rnti) int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return -1; - int slice_idx = RC.mac[mod_id]->UE_list.assoc_dl_slice_idx[ue_id]; + int slice_idx = 0; //RC.mac[mod_id]->UE_list.assoc_dl_slice_idx[ue_id]; if (slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_dl) return RC.mac[mod_id]->slice_info.dl[slice_idx].id; @@ -3031,7 +3031,7 @@ void flexran_set_ue_dl_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx) { if (!flexran_dl_slice_exists(mod_id, slice_idx)) return; - RC.mac[mod_id]->UE_list.assoc_dl_slice_idx[ue_id] = slice_idx; + //RC.mac[mod_id]->UE_list.assoc_dl_slice_idx[ue_id] = slice_idx; } int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id) { @@ -3103,14 +3103,14 @@ int flexran_remove_dl_slice(mid_t mod_id, int slice_idx) { memset(&sli->dl[sli->n_dl], 0, sizeof(sli->dl[sli->n_dl])); /* all UEs that have been in the old slice are put into slice index 0 */ - int *assoc_list = RC.mac[mod_id]->UE_list.assoc_dl_slice_idx; + //int *assoc_list = RC.mac[mod_id]->UE_list.assoc_dl_slice_idx; - for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) { - if (assoc_list[i] == slice_idx) - assoc_list[i] = 0; - } + //for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) { + // if (assoc_list[i] == slice_idx) + // assoc_list[i] = 0; + //} - return sli->n_dl; + return 1; } int flexran_get_num_dl_slices(mid_t mod_id) { diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index fa93a86309..abb053b52e 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -2227,7 +2227,6 @@ add_new_ue(module_id_t mod_idP, sizeof(eNB_UE_STATS)); UE_list->UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 0; /* default slice in case there was something different */ - UE_list->assoc_dl_slice_idx[UE_id] = 0; UE_list->assoc_ul_slice_idx[UE_id] = 0; UE_list->UE_sched_ctrl[UE_id].ta_update = 31; @@ -5123,25 +5122,6 @@ nb_rbs_allowed_slice(float rb_percentage, return (uint16_t) floor(rb_percentage * total_rbs); } -//------------------------------------------------------------------------------ -int -ue_dl_slice_membership(module_id_t mod_id, - int UE_id, - int slice_idx) -//------------------------------------------------------------------------------ -{ - eNB_MAC_INST *eNB = RC.mac[mod_id]; - - if (slice_idx < 0 || slice_idx >= eNB->slice_info.n_dl) { - LOG_W(MAC, "out of range slice index %d (slice ID %d)\n", - slice_idx, - eNB->slice_info.dl[slice_idx].id); - return 0; - } - - return eNB->UE_list.active[UE_id] == TRUE && eNB->UE_list.assoc_dl_slice_idx[UE_id] == slice_idx; -} - //------------------------------------------------------------------------------ int ue_ul_slice_membership(module_id_t mod_id, diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h index 191bc4f5a1..2fdcb862d3 100644 --- a/openair2/LAYER2/MAC/mac.h +++ b/openair2/LAYER2/MAC/mac.h @@ -932,7 +932,6 @@ typedef struct { ///Contention resolution timer used during random access uint8_t mac_ContentionResolutionTimer; - uint16_t max_rbs_allowed_slice[NFAPI_CC_MAX][MAX_NUM_SLICES]; uint16_t max_rbs_allowed_slice_uplink[NFAPI_CC_MAX][MAX_NUM_SLICES]; uint8_t max_mcs[MAX_NUM_LCID]; @@ -1163,8 +1162,6 @@ typedef struct { /// Sorting criteria for the UE list in the MAC preprocessor uint16_t sorting_criteria[MAX_NUM_SLICES][CR_NUM]; uint16_t first_rb_offset[NFAPI_CC_MAX][MAX_NUM_SLICES]; - - int assoc_dl_slice_idx[MAX_MOBILES_PER_ENB]; int assoc_ul_slice_idx[MAX_MOBILES_PER_ENB]; } UE_list_t; diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index be50c7d733..01b463d641 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -1239,7 +1239,6 @@ void pre_scd_nb_rbs_required( module_id_t module_idP, /* Slice related functions */ uint16_t nb_rbs_allowed_slice(float rb_percentage, int total_rbs); -int ue_dl_slice_membership(module_id_t mod_id, int UE_id, int slice_idx); int ue_ul_slice_membership(module_id_t mod_id, int UE_id, int slice_idx); /* DRX Configuration */ diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index 60f9e8947c..12c12fb4bd 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -59,7 +59,6 @@ void init_UE_list(UE_list_t *UE_list) memset(UE_list->eNB_UE_stats, 0, sizeof(UE_list->eNB_UE_stats)); memset(UE_list->UE_sched_ctrl, 0, sizeof(UE_list->UE_sched_ctrl)); memset(UE_list->active, 0, sizeof(UE_list->active)); - memset(UE_list->assoc_dl_slice_idx, 0, sizeof(UE_list->assoc_dl_slice_idx)); memset(UE_list->assoc_ul_slice_idx, 0, sizeof(UE_list->assoc_ul_slice_idx)); } From 8ffe5b4920e19042fb04b2282b8e8fb8a5fef0b7 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 24 Jan 2020 15:16:11 +0100 Subject: [PATCH 111/240] Rename UE_list_t to UE_info_t, UE_list_t separate struct UE_list_t is now used as a separate list. It can be e.g. used in the scheduler to mark groups of users. The original UE_list_t is renamed to UE_info_t to reflect that it is a container for information about UEs. --- openair1/PHY/TOOLS/nr_phy_scope.c | 2 +- openair1/SCHED/phy_procedures_lte_eNb.c | 12 +- .../CONTROL_MODULES/MAC/flexran_agent_mac.c | 8 +- openair2/ENB_APP/flexran_agent_ran_api.c | 82 ++-- openair2/F1AP/f1ap_du_rrc_message_transfer.c | 2 +- openair2/F1AP/f1ap_du_ue_context_management.c | 4 +- openair2/LAYER2/MAC/config.c | 22 +- openair2/LAYER2/MAC/eNB_scheduler.c | 110 ++--- openair2/LAYER2/MAC/eNB_scheduler_RA.c | 40 +- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 114 ++--- openair2/LAYER2/MAC/eNB_scheduler_fairRR.c | 403 ++++++++---------- openair2/LAYER2/MAC/eNB_scheduler_phytest.c | 32 +- .../LAYER2/MAC/eNB_scheduler_primitives.c | 308 ++++++------- openair2/LAYER2/MAC/eNB_scheduler_ulsch.c | 120 +++--- openair2/LAYER2/MAC/mac.h | 20 +- openair2/LAYER2/MAC/mac_proto.h | 13 +- openair2/LAYER2/MAC/main.c | 34 +- openair2/LAYER2/MAC/pre_processor.c | 177 ++++---- openair2/LAYER2/openair2_proc.c | 104 ++--- openair2/RRC/LTE/rrc_eNB.c | 32 +- openair2/RRC/LTE/utils.c | 14 +- targets/RT/USER/lte-enb.c | 8 +- targets/RT/USER/lte-ru.c | 4 +- targets/RT/USER/lte-softmodem.c | 2 +- 24 files changed, 777 insertions(+), 890 deletions(-) diff --git a/openair1/PHY/TOOLS/nr_phy_scope.c b/openair1/PHY/TOOLS/nr_phy_scope.c index 40803c30f4..4682a89029 100644 --- a/openair1/PHY/TOOLS/nr_phy_scope.c +++ b/openair1/PHY/TOOLS/nr_phy_scope.c @@ -182,7 +182,7 @@ void phy_scope_gNB(FD_phy_scope_gnb *form, int Qm = 2; /* - if (!RC.nrmac[0]->UE_list.active[UE_id]) + if (!RC.nrmac[0]->UE_info.active[UE_id]) return; // choose max MCS to compute coded_bits_per_codeword diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 34d5a01590..45448068ae 100644 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -640,6 +640,10 @@ uci_procedures(PHY_VARS_eNB *eNB, uci = &(eNB->uci_vars[i]); if ((uci->active == 1) && (uci->frame == frame) && (uci->subframe == subframe)) { + if (uci->ue_id > MAX_MOBILES_PER_ENB) { + LOG_W(PHY, "UCI for UE %d and/or but is not active in MAC\n", uci->ue_id); + continue; + } LOG_D(PHY,"Frame %d, subframe %d: Running uci procedures (type %d) for %d \n", frame, subframe, @@ -1239,11 +1243,11 @@ void pusch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc) { print_CQI(ulsch_harq->o,ulsch_harq->uci_format,0,fp->N_RB_DL); #endif fill_ulsch_cqi_indication(eNB,frame,subframe,ulsch_harq,ulsch->rnti); - RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_flag &= (~(1 << subframe)); + RC.mac[eNB->Mod_id]->UE_info.UE_sched_ctrl[i].cqi_req_flag &= (~(1 << subframe)); } else { - if(RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_flag & (1 << subframe) ) { - RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_flag &= (~(1 << subframe)); - RC.mac[eNB->Mod_id]->UE_list.UE_sched_ctrl[i].cqi_req_timer=30; + if(RC.mac[eNB->Mod_id]->UE_info.UE_sched_ctrl[i].cqi_req_flag & (1 << subframe) ) { + RC.mac[eNB->Mod_id]->UE_info.UE_sched_ctrl[i].cqi_req_flag &= (~(1 << subframe)); + RC.mac[eNB->Mod_id]->UE_info.UE_sched_ctrl[i].cqi_req_timer=30; LOG_D(PHY,"Frame %d,Subframe %d, We're supposed to get a cqi here. Set cqi_req_timer to 30.\n",frame,subframe); } } 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 c489f10dae..975ac4e96f 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c @@ -939,7 +939,7 @@ int flexran_agent_mac_sf_trigger(mid_t mod_id, const void *params, Protocol__Fle for (i = 0; i < MAX_MOBILES_PER_ENB; i++) { for (j = 0; j < 8; j++) { - if (RC.mac && RC.mac[mod_id] && RC.mac[mod_id]->UE_list.eNB_UE_stats[UE_PCCID(mod_id,i)][i].harq_pid == 1) { + if (RC.mac && RC.mac[mod_id] && RC.mac[mod_id]->UE_info.eNB_UE_stats[UE_PCCID(mod_id,i)][i].harq_pid == 1) { available_harq[i] = j; break; } @@ -977,13 +977,13 @@ int flexran_agent_mac_sf_trigger(mid_t mod_id, const void *params, Protocol__Fle dl_info[i]->harq_process_id = available_harq[UE_id]; if (RC.mac && RC.mac[mod_id]) - RC.mac[mod_id]->UE_list.eNB_UE_stats[UE_PCCID(mod_id, UE_id)][UE_id].harq_pid = 0; + RC.mac[mod_id]->UE_info.eNB_UE_stats[UE_PCCID(mod_id, UE_id)][UE_id].harq_pid = 0; dl_info[i]->has_harq_process_id = 1; /* Fill in the status of the HARQ process (2 TBs)*/ dl_info[i]->n_harq_status = 2; dl_info[i]->harq_status = malloc(sizeof(uint32_t) * dl_info[i]->n_harq_status); for (j = 0; j < dl_info[i]->n_harq_status; j++) { - dl_info[i]->harq_status[j] = RC.mac[mod_id]->UE_list.UE_sched_ctrl[UE_id].round[UE_PCCID(mod_id, UE_id)][j]; + dl_info[i]->harq_status[j] = RC.mac[mod_id]->UE_info.UE_sched_ctrl[UE_id].round[UE_PCCID(mod_id, UE_id)][j]; // TODO: This should be different per TB } // LOG_I(FLEXRAN_AGENT, "Sending subframe trigger for frame %d and subframe %d and harq %d (round %d)\n", flexran_get_current_frame(mod_id), (flexran_get_current_subframe(mod_id) + 1) % 10, dl_info[i]->harq_process_id, dl_info[i]->harq_status[0]); @@ -1357,7 +1357,7 @@ void flexran_agent_init_mac_agent(mid_t mod_id) { for (i = 0; i < MAX_MOBILES_PER_ENB; i++) { for (j = 0; j < 8; j++) { if (RC.mac && RC.mac[mod_id]) - RC.mac[mod_id]->UE_list.eNB_UE_stats[UE_PCCID(mod_id,i)][i].harq_pid = 0; + RC.mac[mod_id]->UE_info.eNB_UE_stats[UE_PCCID(mod_id,i)][i].harq_pid = 0; } } } diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index e917d9d6dc..4fa7db3fd9 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -98,7 +98,7 @@ uint16_t flexran_get_future_sfn_sf(mid_t mod_id, int ahead_of_time) { int flexran_get_mac_num_ues(mid_t mod_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.num_UEs; + return RC.mac[mod_id]->UE_info.num_UEs; } int flexran_get_num_ue_lcs(mid_t mod_id, mid_t ue_id) { @@ -123,7 +123,7 @@ int flexran_get_mac_ue_id_rnti(mid_t mod_id, rnti_t rnti) { /* get the (active) UE with RNTI i */ for (n = 0; n < MAX_MOBILES_PER_ENB; ++n) { - if (RC.mac[mod_id]->UE_list.active[n] == TRUE + if (RC.mac[mod_id]->UE_info.active[n] == TRUE && rnti == UE_RNTI(mod_id, n)) { return n; } @@ -139,7 +139,7 @@ int flexran_get_mac_ue_id(mid_t mod_id, int i) { /* get the (i+1)'th active UE */ for (n = 0; n < MAX_MOBILES_PER_ENB; ++n) { - if (RC.mac[mod_id]->UE_list.active[n] == TRUE) { + if (RC.mac[mod_id]->UE_info.active[n] == TRUE) { if (i == 0) return n; @@ -159,19 +159,19 @@ rnti_t flexran_get_mac_ue_crnti(mid_t mod_id, mid_t ue_id) { int flexran_get_ue_bsr_ul_buffer_info(mid_t mod_id, mid_t ue_id, lcid_t lcid) { if (!mac_is_present(mod_id)) return -1; - return RC.mac[mod_id]->UE_list.UE_template[UE_PCCID(mod_id, ue_id)][ue_id].ul_buffer_info[lcid]; + return RC.mac[mod_id]->UE_info.UE_template[UE_PCCID(mod_id, ue_id)][ue_id].ul_buffer_info[lcid]; } int8_t flexran_get_ue_phr(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.UE_template[UE_PCCID(mod_id, ue_id)][ue_id].phr_info; + return RC.mac[mod_id]->UE_info.UE_template[UE_PCCID(mod_id, ue_id)][ue_id].phr_info; } uint8_t flexran_get_ue_wcqi(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.UE_sched_ctrl[ue_id].dl_cqi[0]; + return RC.mac[mod_id]->UE_info.UE_sched_ctrl[ue_id].dl_cqi[0]; } rlc_buffer_occupancy_t flexran_get_tx_queue_size(mid_t mod_id, mid_t ue_id, logical_chan_id_t channel_id) { @@ -242,7 +242,7 @@ int32_t flexran_get_TA(mid_t mod_id, mid_t ue_id, uint8_t cc_id) { uint32_t flexran_get_total_size_dl_mac_sdus(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].total_sdu_bytes; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].total_sdu_bytes; } uint32_t flexran_get_total_size_ul_mac_sdus(mid_t mod_id, mid_t ue_id, int cc_id) { @@ -251,7 +251,7 @@ uint32_t flexran_get_total_size_ul_mac_sdus(mid_t mod_id, mid_t ue_id, int cc_id uint64_t bytes = 0; for (int i = 0; i < NB_RB_MAX; ++i) { - bytes += RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].num_bytes_rx[i]; + bytes += RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].num_bytes_rx[i]; } return bytes; @@ -260,135 +260,135 @@ uint32_t flexran_get_total_size_ul_mac_sdus(mid_t mod_id, mid_t ue_id, int cc_id uint32_t flexran_get_TBS_dl(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].TBS; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].TBS; } uint32_t flexran_get_TBS_ul(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].ulsch_TBS; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].ulsch_TBS; } uint16_t flexran_get_num_prb_retx_dl_per_ue(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].rbs_used_retx; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].rbs_used_retx; } uint32_t flexran_get_num_prb_retx_ul_per_ue(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].rbs_used_retx_rx; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].rbs_used_retx_rx; } uint16_t flexran_get_num_prb_dl_tx_per_ue(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].rbs_used; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].rbs_used; } uint16_t flexran_get_num_prb_ul_rx_per_ue(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].rbs_used_rx; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].rbs_used_rx; } uint8_t flexran_get_ue_wpmi(mid_t mod_id, mid_t ue_id, uint8_t cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.UE_sched_ctrl[ue_id].periodic_wideband_pmi[cc_id]; + return RC.mac[mod_id]->UE_info.UE_sched_ctrl[ue_id].periodic_wideband_pmi[cc_id]; } uint8_t flexran_get_mcs1_dl(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].dlsch_mcs1; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].dlsch_mcs1; } uint8_t flexran_get_mcs2_dl(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].dlsch_mcs2; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].dlsch_mcs2; } uint8_t flexran_get_mcs1_ul(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].ulsch_mcs1; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].ulsch_mcs1; } uint8_t flexran_get_mcs2_ul(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].ulsch_mcs2; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].ulsch_mcs2; } uint32_t flexran_get_total_prb_dl_tx_per_ue(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].total_rbs_used; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].total_rbs_used; } uint32_t flexran_get_total_prb_ul_rx_per_ue(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].total_rbs_used_rx; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].total_rbs_used_rx; } uint32_t flexran_get_total_num_pdu_dl(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].total_num_pdus; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].total_num_pdus; } uint32_t flexran_get_total_num_pdu_ul(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].total_num_pdus_rx; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].total_num_pdus_rx; } uint64_t flexran_get_total_TBS_dl(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].total_pdu_bytes; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].total_pdu_bytes; } uint64_t flexran_get_total_TBS_ul(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].total_ulsch_TBS; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].total_ulsch_TBS; } int flexran_get_harq_round(mid_t mod_id, uint8_t cc_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].harq_round; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].harq_round; } uint32_t flexran_get_num_mac_sdu_tx(mid_t mod_id, mid_t ue_id, int cc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].num_mac_sdu_tx; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].num_mac_sdu_tx; } unsigned char flexran_get_mac_sdu_lcid_index(mid_t mod_id, mid_t ue_id, int cc_id, int index) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].lcid_sdu[index]; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].lcid_sdu[index]; } uint32_t flexran_get_mac_sdu_size(mid_t mod_id, mid_t ue_id, int cc_id, int lcid) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.eNB_UE_stats[cc_id][ue_id].sdu_length_tx[lcid]; + return RC.mac[mod_id]->UE_info.eNB_UE_stats[cc_id][ue_id].sdu_length_tx[lcid]; } /* TODO needs to be revised */ void flexran_update_TA(mid_t mod_id, mid_t ue_id, uint8_t cc_id) { /* - UE_list_t *UE_list=&eNB_mac_inst[mod_id].UE_list; - UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[ue_id]; + UE_info_t *UE_info=&eNB_mac_inst[mod_id].UE_info; + UE_sched_ctrl *ue_sched_ctl = &UE_info->UE_sched_ctrl[ue_id]; if (ue_sched_ctl->ta_timer == 0) { @@ -432,7 +432,7 @@ int flexran_get_MAC_CE_bitmap_TA(mid_t mod_id, mid_t ue_id, uint8_t cc_id) { int flexran_get_active_CC(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.numactiveCCs[ue_id]; + return RC.mac[mod_id]->UE_info.numactiveCCs[ue_id]; } uint8_t flexran_get_current_RI(mid_t mod_id, mid_t ue_id, uint8_t cc_id) { @@ -890,13 +890,13 @@ uint8_t flexran_get_rrc_status(mid_t mod_id, rnti_t rnti) { uint64_t flexran_get_ue_aggregated_max_bitrate_dl(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.UE_sched_ctrl[ue_id].ue_AggregatedMaximumBitrateDL; + return RC.mac[mod_id]->UE_info.UE_sched_ctrl[ue_id].ue_AggregatedMaximumBitrateDL; } uint64_t flexran_get_ue_aggregated_max_bitrate_ul(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.UE_sched_ctrl[ue_id].ue_AggregatedMaximumBitrateUL; + return RC.mac[mod_id]->UE_info.UE_sched_ctrl[ue_id].ue_AggregatedMaximumBitrateUL; } int flexran_get_half_duplex(mid_t mod_id, rnti_t rnti) { @@ -1235,7 +1235,7 @@ uint64_t flexran_get_ue_imsi(mid_t mod_id, rnti_t rnti) { long flexran_get_lcg(mid_t mod_id, mid_t ue_id, mid_t lc_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_list.UE_template[UE_PCCID(mod_id, ue_id)][ue_id].lcgidmap[lc_id]; + return RC.mac[mod_id]->UE_info.UE_template[UE_PCCID(mod_id, ue_id)][ue_id].lcgidmap[lc_id]; } /* TODO Navid: needs to be revised */ @@ -3016,7 +3016,7 @@ uint32_t flexran_get_rrc_enb_ue_s1ap_id(mid_t mod_id, rnti_t rnti) int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return -1; - int slice_idx = 0; //RC.mac[mod_id]->UE_list.assoc_dl_slice_idx[ue_id]; + int slice_idx = 0; //RC.mac[mod_id]->UE_info.assoc_dl_slice_idx[ue_id]; if (slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_dl) return RC.mac[mod_id]->slice_info.dl[slice_idx].id; @@ -3031,13 +3031,13 @@ void flexran_set_ue_dl_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx) { if (!flexran_dl_slice_exists(mod_id, slice_idx)) return; - //RC.mac[mod_id]->UE_list.assoc_dl_slice_idx[ue_id] = slice_idx; + //RC.mac[mod_id]->UE_info.assoc_dl_slice_idx[ue_id] = slice_idx; } int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return -1; - int slice_idx = RC.mac[mod_id]->UE_list.assoc_ul_slice_idx[ue_id]; + int slice_idx = RC.mac[mod_id]->UE_info.assoc_ul_slice_idx[ue_id]; if (slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_ul) return RC.mac[mod_id]->slice_info.ul[slice_idx].id; @@ -3052,7 +3052,7 @@ void flexran_set_ue_ul_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx) { if (!flexran_ul_slice_exists(mod_id, slice_idx)) return; - RC.mac[mod_id]->UE_list.assoc_ul_slice_idx[ue_id] = slice_idx; + RC.mac[mod_id]->UE_info.assoc_ul_slice_idx[ue_id] = slice_idx; } int flexran_dl_slice_exists(mid_t mod_id, int slice_idx) { @@ -3103,7 +3103,7 @@ int flexran_remove_dl_slice(mid_t mod_id, int slice_idx) { memset(&sli->dl[sli->n_dl], 0, sizeof(sli->dl[sli->n_dl])); /* all UEs that have been in the old slice are put into slice index 0 */ - //int *assoc_list = RC.mac[mod_id]->UE_list.assoc_dl_slice_idx; + //int *assoc_list = RC.mac[mod_id]->UE_info.assoc_dl_slice_idx; //for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) { // if (assoc_list[i] == slice_idx) @@ -3397,7 +3397,7 @@ int flexran_remove_ul_slice(mid_t mod_id, int slice_idx) { memset(&sli->ul[sli->n_ul], 0, sizeof(sli->ul[sli->n_ul])); /* all UEs that have been in the old slice are put into slice index 0 */ - int *assoc_list = RC.mac[mod_id]->UE_list.assoc_ul_slice_idx; + int *assoc_list = RC.mac[mod_id]->UE_info.assoc_ul_slice_idx; for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) { if (assoc_list[i] == slice_idx) diff --git a/openair2/F1AP/f1ap_du_rrc_message_transfer.c b/openair2/F1AP/f1ap_du_rrc_message_transfer.c index 803551818a..fb9450728b 100644 --- a/openair2/F1AP/f1ap_du_rrc_message_transfer.c +++ b/openair2/F1AP/f1ap_du_rrc_message_transfer.c @@ -697,7 +697,7 @@ int DU_send_UL_RRC_MESSAGE_TRANSFER(instance_t instance, break; } - UE_sched_ctrl_t *UE_scheduling_control = &(RC.mac[instance]->UE_list.UE_sched_ctrl[UE_id_mac]); + UE_sched_ctrl_t *UE_scheduling_control = &(RC.mac[instance]->UE_info.UE_sched_ctrl[UE_id_mac]); if (UE_scheduling_control->cdrx_waiting_ack == TRUE) { UE_scheduling_control->cdrx_waiting_ack = FALSE; diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index b9c79e1f18..bae59a509e 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -633,9 +633,9 @@ int DU_handle_UE_CONTEXT_RELEASE_COMMAND(instance_t instance, int UE_out_of_sync = 0; for (int n = 0; n < MAX_MOBILES_PER_ENB; ++n) { - if (RC.mac[instance]->UE_list.active[n] == TRUE + if (RC.mac[instance]->UE_info.active[n] == TRUE && rnti == UE_RNTI(instance, n)) { - UE_out_of_sync = RC.mac[instance]->UE_list.UE_sched_ctrl[n].ul_out_of_sync; + UE_out_of_sync = RC.mac[instance]->UE_info.UE_sched_ctrl[n].ul_out_of_sync; break; } } diff --git a/openair2/LAYER2/MAC/config.c b/openair2/LAYER2/MAC/config.c index 76c8e33b16..4c32ec53be 100644 --- a/openair2/LAYER2/MAC/config.c +++ b/openair2/LAYER2/MAC/config.c @@ -782,7 +782,7 @@ int rrc_mac_config_req_eNB(module_id_t Mod_idP, int i; int UE_id = -1; eNB_MAC_INST *eNB = RC.mac[Mod_idP]; - UE_list_t *UE_list= &eNB->UE_list; + UE_info_t *UE_info= &eNB->UE_info; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_MAC_CONFIG, VCD_FUNCTION_IN); LOG_D(MAC, "RC.mac:%p mib:%p\n", RC.mac, mib); @@ -892,9 +892,9 @@ int rrc_mac_config_req_eNB(module_id_t Mod_idP, } if (logicalChannelConfig) { - UE_list->UE_template[CC_idP][UE_id].lcgidmap[logicalChannelIdentity] = *logicalChannelConfig->ul_SpecificParameters->logicalChannelGroup; - UE_list->UE_template[CC_idP][UE_id].lcgidpriority[logicalChannelIdentity] = logicalChannelConfig->ul_SpecificParameters->priority; - } else UE_list->UE_template[CC_idP][UE_id].lcgidmap[logicalChannelIdentity] = 0; + UE_info->UE_template[CC_idP][UE_id].lcgidmap[logicalChannelIdentity] = *logicalChannelConfig->ul_SpecificParameters->logicalChannelGroup; + UE_info->UE_template[CC_idP][UE_id].lcgidpriority[logicalChannelIdentity] = logicalChannelConfig->ul_SpecificParameters->priority; + } else UE_info->UE_template[CC_idP][UE_id].lcgidmap[logicalChannelIdentity] = 0; } if (physicalConfigDedicated != NULL) { @@ -905,7 +905,7 @@ int rrc_mac_config_req_eNB(module_id_t Mod_idP, return(-1); } - UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated = physicalConfigDedicated; + UE_info->UE_template[CC_idP][UE_id].physicalConfigDedicated = physicalConfigDedicated; LOG_I(MAC,"Added physicalConfigDedicated %p for %d.%d\n",physicalConfigDedicated,CC_idP,UE_id); } @@ -1048,15 +1048,11 @@ void eNB_Config_Local_DRX(instance_t Mod_id, rrc_mac_drx_config_req_t *rrc_mac_drx_config_req) //----------------------------------------------------------------------------- { - UE_list_t *UE_list_mac = NULL; + UE_info_t *UE_info_mac = &RC.mac[Mod_id]->UE_info; UE_sched_ctrl_t *UE_scheduling_control = NULL; - int UE_id = -1; - - rnti_t rnti = rrc_mac_drx_config_req->rnti; LTE_DRX_Config_t *const drx_Configuration = rrc_mac_drx_config_req->drx_Configuration; - - UE_list_mac = &(RC.mac[Mod_id]->UE_list); - UE_id = find_UE_id(Mod_id, rnti); + rnti_t rnti = rrc_mac_drx_config_req->rnti; + int UE_id = find_UE_id(Mod_id, rnti); /* Check UE_id */ if (UE_id == -1) { @@ -1065,7 +1061,7 @@ void eNB_Config_Local_DRX(instance_t Mod_id, } /* Get struct to modify */ - UE_scheduling_control = &(UE_list_mac->UE_sched_ctrl[UE_id]); + UE_scheduling_control = &(UE_info_mac->UE_sched_ctrl[UE_id]); UE_scheduling_control->cdrx_configured = FALSE; // will be set to true when no error /* Check drx_Configuration */ diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c index 2b3705dc67..42eca36dcb 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler.c +++ b/openair2/LAYER2/MAC/eNB_scheduler.c @@ -88,7 +88,7 @@ void schedule_SRS(module_id_t module_idP, const uint16_t deltaTSFCTabType1[15][2] = { {1, 1}, {1, 2}, {2, 2}, {1, 5}, {2, 5}, {4, 5}, {8, 5}, {3, 5}, {12, 5}, {1, 10}, {2, 10}, {4, 10}, {8, 10}, {351, 10}, {383, 10} }; // Table 5.5.3.3-2 3GPP 36.211 FDD const uint16_t deltaTSFCTabType2[14][2] = { {2, 5}, {6, 5}, {10, 5}, {18, 5}, {14, 5}, {22, 5}, {26, 5}, {30, 5}, {70, 10}, {74, 10}, {194, 10}, {326, 10}, {586, 10}, {210, 10} }; // Table 5.5.3.3-2 3GPP 36.211 TDD eNB_MAC_INST *eNB = RC.mac[module_idP]; - UE_list_t *UE_list = &(eNB->UE_list); + UE_info_t *UE_info = &eNB->UE_info; nfapi_ul_config_request_body_t *ul_req = NULL; UE_sched_ctrl_t *UE_scheduling_control = NULL; COMMON_channels_t *cc = eNB->common_channels; @@ -116,7 +116,7 @@ void schedule_SRS(module_id_t module_idP, if ((1 << tmp) & deltaTSFC) { /* This is an SRS subframe, loop over UEs */ for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) { - if (!UE_list->active[UE_id]) { + if (!UE_info->active[UE_id]) { continue; } @@ -125,14 +125,14 @@ void schedule_SRS(module_id_t module_idP, continue; } - if(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated == NULL) { + if(UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated == NULL) { LOG_E(MAC,"physicalConfigDedicated is null for UE %d\n",UE_id); printf("physicalConfigDedicated is null for UE %d\n",UE_id); return; } /* CDRX condition on Active Time and SRS type-0 report (36.321 5.7) */ - UE_scheduling_control = &(UE_list->UE_sched_ctrl[UE_id]); + UE_scheduling_control = &(UE_info->UE_sched_ctrl[UE_id]); /* Test if Active Time not running since 6+ subframes */ if (UE_scheduling_control->cdrx_configured == TRUE && UE_scheduling_control->in_active_time == FALSE) { @@ -144,7 +144,7 @@ void schedule_SRS(module_id_t module_idP, ul_req = &(eNB->UL_req[CC_id].ul_config_request_body); - if ((soundingRS_UL_ConfigDedicated = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated) != NULL) { + if ((soundingRS_UL_ConfigDedicated = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated) != NULL) { if (soundingRS_UL_ConfigDedicated->present == LTE_SoundingRS_UL_ConfigDedicated_PR_setup) { get_srs_pos(&cc[CC_id], soundingRS_UL_ConfigDedicated->choice.setup.srs_ConfigIndex, @@ -160,7 +160,7 @@ void schedule_SRS(module_id_t module_idP, ul_config_pdu->pdu_size = 2 + (uint8_t) (2 + sizeof(nfapi_ul_config_srs_pdu)); ul_config_pdu->srs_pdu.srs_pdu_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG; ul_config_pdu->srs_pdu.srs_pdu_rel8.size = (uint8_t)sizeof(nfapi_ul_config_srs_pdu); - ul_config_pdu->srs_pdu.srs_pdu_rel8.rnti = UE_list->UE_template[CC_id][UE_id].rnti; + ul_config_pdu->srs_pdu.srs_pdu_rel8.rnti = UE_info->UE_template[CC_id][UE_id].rnti; ul_config_pdu->srs_pdu.srs_pdu_rel8.srs_bandwidth = soundingRS_UL_ConfigDedicated->choice.setup.srs_Bandwidth; ul_config_pdu->srs_pdu.srs_pdu_rel8.frequency_domain_position = soundingRS_UL_ConfigDedicated->choice.setup.freqDomainPosition; ul_config_pdu->srs_pdu.srs_pdu_rel8.srs_hopping_bandwidth = soundingRS_UL_ConfigDedicated->choice.setup.srs_HoppingBandwidth;; @@ -172,7 +172,7 @@ void schedule_SRS(module_id_t module_idP, ul_req->number_of_pdus++; } // if (((10*frameP+subframeP) % srsPeriodicity) == srsOffset) } // if (soundingRS_UL_ConfigDedicated->present == SoundingRS_UL_ConfigDedicated_PR_setup) - } // if ((soundingRS_UL_ConfigDedicated = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated)!=NULL) + } // if ((soundingRS_UL_ConfigDedicated = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->soundingRS_UL_ConfigDedicated)!=NULL) } // end for loop on UE_id } // if((1<UE_list; + UE_info_t *UE_info = &eNB->UE_info; COMMON_channels_t *cc = NULL; nfapi_ul_config_request_body_t *ul_req = NULL; UE_sched_ctrl_t *UE_scheduling_control = NULL; @@ -204,7 +204,7 @@ void schedule_CSI(module_id_t module_idP, cc = &eNB->common_channels[CC_id]; for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) { - if (UE_list->active[UE_id] == FALSE) { + if (UE_info->active[UE_id] == FALSE) { continue; } @@ -213,7 +213,7 @@ void schedule_CSI(module_id_t module_idP, continue; } - AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated != NULL, + AssertFatal(UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated != NULL, "physicalConfigDedicated is null for UE %d\n", UE_id); /* @@ -221,7 +221,7 @@ void schedule_CSI(module_id_t module_idP, * Here we consider classic periodic reports on PUCCH without PUSCH simultaneous transmission condition. * TODO: add the handling or test on simultaneous PUCCH/PUSCH transmission */ - UE_scheduling_control = &(UE_list->UE_sched_ctrl[UE_id]); + UE_scheduling_control = &(UE_info->UE_sched_ctrl[UE_id]); if (UE_scheduling_control->cdrx_configured == TRUE) { /* Test if CQI masking activated */ @@ -245,8 +245,8 @@ void schedule_CSI(module_id_t module_idP, ul_req = &(eNB->UL_req[CC_id].ul_config_request_body); - if (UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig != NULL) { - cqi_ReportPeriodic = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic; + if (UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig != NULL) { + cqi_ReportPeriodic = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic; if (cqi_ReportPeriodic != NULL) { /* Rel8 Periodic CSI (CQI/PMI/RI) reporting */ @@ -261,10 +261,10 @@ void schedule_CSI(module_id_t module_idP, ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE; ul_config_pdu->pdu_size = 2 + (uint8_t) (2 + sizeof(nfapi_ul_config_uci_cqi_pdu)); ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG; - ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.rnti = UE_list->UE_template[CC_id][UE_id].rnti; + ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.rnti = UE_info->UE_template[CC_id][UE_id].rnti; ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG; ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.pucch_index = cqi_ReportPeriodic->choice.setup.cqi_PUCCH_ResourceIndex; - ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.dl_cqi_pmi_size = get_rel8_dl_cqi_pmi_size(&UE_list->UE_sched_ctrl[UE_id], CC_id, cc, get_tmode(module_idP, CC_id, UE_id), + ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.dl_cqi_pmi_size = get_rel8_dl_cqi_pmi_size(&UE_info->UE_sched_ctrl[UE_id], CC_id, cc, get_tmode(module_idP, CC_id, UE_id), cqi_ReportPeriodic); ul_req->number_of_pdus++; ul_req->tl.tag = NFAPI_UL_CONFIG_REQUEST_BODY_TAG; @@ -278,7 +278,7 @@ void schedule_CSI(module_id_t module_idP, ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE; ul_config_pdu->pdu_size = 2 + (uint8_t) (2 + sizeof(nfapi_ul_config_uci_cqi_pdu)); ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG; - ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.rnti = UE_list->UE_template[CC_id][UE_id].rnti; + ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.rnti = UE_info->UE_template[CC_id][UE_id].rnti; ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG; ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.pucch_index = cqi_ReportPeriodic->choice.setup.cqi_PUCCH_ResourceIndex; ul_config_pdu->uci_cqi_pdu.cqi_information.cqi_information_rel8.dl_cqi_pmi_size = (cc->p_eNB == 2) ? 1 : 2; @@ -290,7 +290,7 @@ void schedule_CSI(module_id_t module_idP, } // if CSI Periodic is not release state } // if (cqi_ReportPeriodic != NULL) } // if cqi_ReportConfig != NULL - } // for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) { + } // for (UE_id=UE_info->head; UE_id>=0; UE_id=UE_info->next[UE_id]) { } // for (CC_id=0; CC_idUE_list; + UE_info_t *UE_info = &eNB->UE_info; nfapi_ul_config_request_t *ul_req = NULL; nfapi_ul_config_request_body_t *ul_req_body = NULL; LTE_SchedulingRequestConfig_t *SRconfig = NULL; @@ -318,13 +318,13 @@ schedule_SR (module_id_t module_idP, eNB->UL_req[CC_id].sfn_sf = (frameP << 4) + subframeP; for (int UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) { - if (!UE_list->active[UE_id]) { + if (!UE_info->active[UE_id]) { continue; } - if (UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated == NULL) continue; + if (UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated == NULL) continue; - if ((SRconfig = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig) != NULL) { + if ((SRconfig = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig) != NULL) { if (SRconfig->present == LTE_SchedulingRequestConfig_PR_setup) { if (SRconfig->choice.setup.sr_ConfigIndex <= 4) { // 5 ms SR period if ((subframeP % 5) != SRconfig->choice.setup.sr_ConfigIndex) continue; @@ -338,7 +338,7 @@ schedule_SR (module_id_t module_idP, if ((10 * (frameP & 7) + subframeP) != (SRconfig->choice.setup.sr_ConfigIndex - 75)) continue; } } // SRconfig->present == SchedulingRequestConfig_PR_setup) - } // SRconfig = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig)!=NULL) + } // SRconfig = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig)!=NULL) /* If we get here there is some PUCCH1 reception to schedule for SR */ ul_req = &(eNB->UL_req[CC_id]); @@ -353,14 +353,14 @@ schedule_SR (module_id_t module_idP, (ul_req_body->ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE) || (ul_req_body->ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE) || (ul_req_body->ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE)) && - (ul_req_body->ul_config_pdu_list[i].ulsch_pdu.ulsch_pdu_rel8.rnti == UE_list->UE_template[CC_id][UE_id].rnti)) { + (ul_req_body->ul_config_pdu_list[i].ulsch_pdu.ulsch_pdu_rel8.rnti == UE_info->UE_template[CC_id][UE_id].rnti)) { skip_ue = 1; pdu_list_index = i; break; } /* If there is already an HARQ pdu, convert to SR_HARQ */ else if ((ul_req_body->ul_config_pdu_list[i].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE) && - (ul_req_body->ul_config_pdu_list[i].uci_harq_pdu.ue_information.ue_information_rel8.rnti == UE_list->UE_template[CC_id][UE_id].rnti)) { + (ul_req_body->ul_config_pdu_list[i].uci_harq_pdu.ue_information.ue_information_rel8.rnti == UE_info->UE_template[CC_id][UE_id].rnti)) { is_harq = 1; pdu_list_index = i; break; @@ -374,20 +374,20 @@ schedule_SR (module_id_t module_idP, frameP, subframeP, UE_id, - UE_list->UE_template[CC_id][UE_id].rnti, + UE_info->UE_template[CC_id][UE_id].rnti, is_harq); /* Check Rel10 or Rel8 SR */ - if ((UE_list-> UE_template[CC_id][UE_id].physicalConfigDedicated->ext2) && - (UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2->schedulingRequestConfig_v1020) && - (UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2->schedulingRequestConfig_v1020)) { + if ((UE_info-> UE_template[CC_id][UE_id].physicalConfigDedicated->ext2) && + (UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2->schedulingRequestConfig_v1020) && + (UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2->schedulingRequestConfig_v1020)) { sr.sr_information_rel10.tl.tag = NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG; sr.sr_information_rel10.number_of_pucch_resources = 1; - sr.sr_information_rel10.pucch_index_p1 = *UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2->schedulingRequestConfig_v1020->sr_PUCCH_ResourceIndexP1_r10; + sr.sr_information_rel10.pucch_index_p1 = *UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->ext2->schedulingRequestConfig_v1020->sr_PUCCH_ResourceIndexP1_r10; LOG_D(MAC, "REL10 PUCCH INDEX P1:%d \n", sr.sr_information_rel10.pucch_index_p1); } else { sr.sr_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG; - sr.sr_information_rel8.pucch_index = UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig->choice.setup.sr_PUCCH_ResourceIndex; + sr.sr_information_rel8.pucch_index = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig->choice.setup.sr_PUCCH_ResourceIndex; LOG_D(MAC, "REL8 PUCCH INDEX:%d\n", sr.sr_information_rel8.pucch_index); } @@ -400,7 +400,7 @@ schedule_SR (module_id_t module_idP, } else { ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].pdu_type = NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE; ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].uci_sr_pdu.ue_information.ue_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG; - ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].uci_sr_pdu.ue_information.ue_information_rel8.rnti = UE_list->UE_template[CC_id][UE_id].rnti; + ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].uci_sr_pdu.ue_information.ue_information_rel8.rnti = UE_info->UE_template[CC_id][UE_id].rnti; ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].uci_sr_pdu.ue_information.ue_information_rel11.tl.tag = 0; ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].uci_sr_pdu.ue_information.ue_information_rel13.tl.tag = 0; ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus].uci_sr_pdu.sr_information = sr; @@ -415,20 +415,20 @@ schedule_SR (module_id_t module_idP, void check_ul_failure(module_id_t module_idP, int CC_id, int UE_id, frame_t frameP, sub_frame_t subframeP) { - UE_list_t *UE_list = &RC.mac[module_idP]->UE_list; + UE_info_t *UE_info = &RC.mac[module_idP]->UE_info; nfapi_dl_config_request_t *DL_req = &RC.mac[module_idP]->DL_req[0]; uint16_t rnti = UE_RNTI(module_idP, UE_id); COMMON_channels_t *cc = RC.mac[module_idP]->common_channels; // check uplink failure - if ((UE_list->UE_sched_ctrl[UE_id].ul_failure_timer > 0) && - (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 0)) { - if (UE_list->UE_sched_ctrl[UE_id].ul_failure_timer == 1) + if ((UE_info->UE_sched_ctrl[UE_id].ul_failure_timer > 0) && + (UE_info->UE_sched_ctrl[UE_id].ul_out_of_sync == 0)) { + if (UE_info->UE_sched_ctrl[UE_id].ul_failure_timer == 1) LOG_I(MAC, "UE %d rnti %x: UL Failure timer %d \n", UE_id, rnti, - UE_list->UE_sched_ctrl[UE_id].ul_failure_timer); + UE_info->UE_sched_ctrl[UE_id].ul_failure_timer); - if (UE_list->UE_sched_ctrl[UE_id].ra_pdcch_order_sent == 0) { - UE_list->UE_sched_ctrl[UE_id].ra_pdcch_order_sent = 1; + if (UE_info->UE_sched_ctrl[UE_id].ra_pdcch_order_sent == 0) { + UE_info->UE_sched_ctrl[UE_id].ra_pdcch_order_sent = 1; // add a format 1A dci for this UE to request an RA procedure (only one UE per subframe) nfapi_dl_config_request_pdu_t *dl_config_pdu = &DL_req[CC_id].dl_config_request_body.dl_config_pdu_list[DL_req[CC_id].dl_config_request_body.number_pdu]; memset((void *) dl_config_pdu, 0,sizeof(nfapi_dl_config_request_pdu_t)); @@ -437,7 +437,7 @@ check_ul_failure(module_id_t module_idP, int CC_id, int UE_id, dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1A; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = get_aggregation(get_bw_index(module_idP, CC_id), - UE_list->UE_sched_ctrl[UE_id]. + UE_info->UE_sched_ctrl[UE_id]. dl_cqi[CC_id], format1A); dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // CRNTI : see Table 4-10 from SCF082 - nFAPI specifications @@ -453,22 +453,22 @@ check_ul_failure(module_id_t module_idP, int CC_id, int UE_id, LOG_D(MAC, "UE %d rnti %x: sending PDCCH order for RAPROC (failure timer %d), resource_block_coding %d \n", UE_id, rnti, - UE_list->UE_sched_ctrl[UE_id].ul_failure_timer, + UE_info->UE_sched_ctrl[UE_id].ul_failure_timer, dl_config_pdu->dci_dl_pdu. dci_dl_pdu_rel8.resource_block_coding); } else { // ra_pdcch_sent==1 LOG_D(MAC, "UE %d rnti %x: sent PDCCH order for RAPROC waiting (failure timer %d) \n", UE_id, rnti, - UE_list->UE_sched_ctrl[UE_id].ul_failure_timer); + UE_info->UE_sched_ctrl[UE_id].ul_failure_timer); - if ((UE_list->UE_sched_ctrl[UE_id].ul_failure_timer % 80) == 0) UE_list->UE_sched_ctrl[UE_id].ra_pdcch_order_sent = 0; // resend every 8 frames + if ((UE_info->UE_sched_ctrl[UE_id].ul_failure_timer % 80) == 0) UE_info->UE_sched_ctrl[UE_id].ra_pdcch_order_sent = 0; // resend every 8 frames } - UE_list->UE_sched_ctrl[UE_id].ul_failure_timer++; + UE_info->UE_sched_ctrl[UE_id].ul_failure_timer++; // check threshold - if (UE_list->UE_sched_ctrl[UE_id].ul_failure_timer > 4000) { + if (UE_info->UE_sched_ctrl[UE_id].ul_failure_timer > 4000) { // note: probably ul_failure_timer should be less than UE radio link failure time(see T310/N310/N311) if (NODE_IS_DU(RC.rrc[module_idP]->node_type)) { MessageDef *m = itti_alloc_new_message(TASK_MAC_ENB, F1AP_UE_CONTEXT_RELEASE_REQ); @@ -490,17 +490,17 @@ check_ul_failure(module_id_t module_idP, int CC_id, int UE_id, rnti); } - UE_list->UE_sched_ctrl[UE_id].ul_failure_timer = 0; - UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync = 1; + UE_info->UE_sched_ctrl[UE_id].ul_failure_timer = 0; + UE_info->UE_sched_ctrl[UE_id].ul_out_of_sync = 1; } } // ul_failure_timer>0 - UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer++; + UE_info->UE_sched_ctrl[UE_id].uplane_inactivity_timer++; - if((U_PLANE_INACTIVITY_VALUE != 0) && (UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer > (U_PLANE_INACTIVITY_VALUE * 10))) { + if((U_PLANE_INACTIVITY_VALUE != 0) && (UE_info->UE_sched_ctrl[UE_id].uplane_inactivity_timer > (U_PLANE_INACTIVITY_VALUE * 10))) { LOG_D(MAC,"UE %d rnti %x: U-Plane Failure after repeated PDCCH orders: Triggering RRC \n",UE_id,rnti); mac_eNB_rrc_uplane_failure(module_idP,CC_id,frameP,subframeP,rnti); - UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0; + UE_info->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0; }// time > 60s } @@ -564,7 +564,7 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, int CC_id = 0; int UE_id = -1; eNB_MAC_INST *eNB = RC.mac[module_idP]; - UE_list_t *UE_list = &(eNB->UE_list); + UE_info_t *UE_info = &(eNB->UE_info); COMMON_channels_t *cc = eNB->common_channels; UE_sched_ctrl_t *UE_scheduling_control = NULL; start_meas(&(eNB->eNB_scheduler)); @@ -583,16 +583,16 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, /* Refresh UE list based on UEs dropped by PHY in previous subframe */ for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) { - if (UE_list->active[UE_id]) { + if (UE_info->active[UE_id]) { rnti = UE_RNTI(module_idP, UE_id); CC_id = UE_PCCID(module_idP, UE_id); - UE_scheduling_control = &(UE_list->UE_sched_ctrl[UE_id]); + UE_scheduling_control = &(UE_info->UE_sched_ctrl[UE_id]); if (((frameP & 127) == 0) && (subframeP == 0)) { LOG_I(MAC,"UE rnti %x : %s, PHR %d dB DL CQI %d PUSCH SNR %d PUCCH SNR %d\n", rnti, UE_scheduling_control->ul_out_of_sync == 0 ? "in synch" : "out of sync", - UE_list->UE_template[CC_id][UE_id].phr_info, + UE_info->UE_template[CC_id][UE_id].phr_info, UE_scheduling_control->dl_cqi[CC_id], (5 * UE_scheduling_control->pusch_snr[CC_id] - 640) / 10, (5 * UE_scheduling_control->pucch1_snr[CC_id] - 640) / 10); @@ -600,7 +600,7 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, RC.eNB[module_idP][CC_id]->pusch_stats_bsr[UE_id][(frameP * 10) + subframeP] = -63; - if (UE_id == UE_list->head) { + if (UE_id == UE_info->list.head) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_BSR, RC.eNB[module_idP][CC_id]->pusch_stats_bsr[UE_id][(frameP * 10) + subframeP]); } @@ -734,7 +734,7 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, * here for the current subframe. The variable 'UE_scheduling_control->in_active_time' should be updated * ONLY here. The variable can then be used for testing the actual state of the UE for scheduling purpose. */ - UE_template = &(UE_list->UE_template[CC_id][UE_id]); + UE_template = &(UE_info->UE_template[CC_id][UE_id]); /* (a)synchronous HARQ processes handling for Active Time */ for (int harq_process_id = 0; harq_process_id < 8; harq_process_id++) { diff --git a/openair2/LAYER2/MAC/eNB_scheduler_RA.c b/openair2/LAYER2/MAC/eNB_scheduler_RA.c index fb765e6dac..2e8f06586b 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_RA.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_RA.c @@ -587,7 +587,7 @@ generate_Msg4(module_id_t module_idP, { eNB_MAC_INST *mac = RC.mac[module_idP]; COMMON_channels_t *cc = mac->common_channels; - UE_list_t *UE_list = &(mac->UE_list); + UE_info_t *UE_info = &mac->UE_info; int16_t rrc_sdu_length = 0; uint16_t msg4_padding = 0; uint16_t msg4_post_padding = 0; @@ -831,7 +831,7 @@ generate_Msg4(module_id_t module_idP, dl_req_body->number_pdu++; ra->state = WAITMSG4ACK; lcid = 0; - UE_list->UE_sched_ctrl[UE_id].round[CC_idP][ra->harq_pid] = 0; + UE_info->UE_sched_ctrl[UE_id].round[CC_idP][ra->harq_pid] = 0; msg4_header = 1 + 6 + 1; // CR header, CR CE, SDU header AssertFatal((ra->msg4_TBsize - ra->msg4_rrc_sdu_length - msg4_header)>=0, "msg4_TBS %d is too small, change mcs to increase by %d bytes\n",ra->msg4_TBsize,ra->msg4_rrc_sdu_length+msg4_header-ra->msg4_TBsize); @@ -848,7 +848,7 @@ generate_Msg4(module_id_t module_idP, module_idP, CC_idP, frameP, subframeP, ra->msg4_TBsize, ra->msg4_rrc_sdu_length, msg4_header, msg4_padding, msg4_post_padding); DevAssert (UE_id != UE_INDEX_INVALID); // FIXME not sure how to gracefully return // CHECK THIS: &cc[CC_idP].CCCH_pdu.payload[0] - offset = generate_dlsch_header ((unsigned char *) mac->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char) UE_id].payload[0], 1, //num_sdus + offset = generate_dlsch_header ((unsigned char *) mac->UE_info.DLSCH_pdu[CC_idP][0][(unsigned char) UE_id].payload[0], 1, //num_sdus (unsigned short *) &ra->msg4_rrc_sdu_length, // &lcid, // sdu_lcid 255, // no drx @@ -856,7 +856,7 @@ generate_Msg4(module_id_t module_idP, ra->cont_res_id, // contention res id msg4_padding, // no padding msg4_post_padding); - memcpy ((void *) &mac->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char) UE_id].payload[0][(unsigned char) offset], &cc[CC_idP].CCCH_pdu.payload[0], ra->msg4_rrc_sdu_length); + memcpy ((void *) &mac->UE_info.DLSCH_pdu[CC_idP][0][(unsigned char) UE_id].payload[0][(unsigned char) offset], &cc[CC_idP].CCCH_pdu.payload[0], ra->msg4_rrc_sdu_length); // DL request mac->TX_req[CC_idP].sfn_sf = (frameP << 4) + subframeP; TX_req = &mac->TX_req[CC_idP].tx_request_body.tx_pdu_list[mac->TX_req[CC_idP].tx_request_body.number_of_pdus]; @@ -864,7 +864,7 @@ generate_Msg4(module_id_t module_idP, TX_req->pdu_index = mac->pdu_index[CC_idP]++; TX_req->num_segments = 1; TX_req->segments[0].segment_length = ra->msg4_TBsize; - TX_req->segments[0].segment_data = mac->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char) UE_id].payload[0]; + TX_req->segments[0].segment_data = mac->UE_info.DLSCH_pdu[CC_idP][0][(unsigned char) UE_id].payload[0]; mac->TX_req[CC_idP].tx_request_body.number_of_pdus++; // Program ACK/NAK for Msg4 PDSCH int absSF = (frameP * 10) + subframeP; @@ -899,8 +899,8 @@ generate_Msg4(module_id_t module_idP, ul_req_body->number_of_pdus++; T (T_ENB_MAC_UE_DL_PDU_WITH_DATA, T_INT (module_idP), T_INT (CC_idP), T_INT (ra->rnti), T_INT (frameP), T_INT (subframeP), - T_INT (0 /*harq_pid always 0? */ ), T_BUFFER (&mac->UE_list.DLSCH_pdu[CC_idP][0][UE_id].payload[0], ra->msg4_TBsize)); - trace_pdu (DIRECTION_DOWNLINK, (uint8_t *) mac->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char) UE_id].payload[0], + T_INT (0 /*harq_pid always 0? */ ), T_BUFFER (&mac->UE_info.DLSCH_pdu[CC_idP][0][UE_id].payload[0], ra->msg4_TBsize)); + trace_pdu (DIRECTION_DOWNLINK, (uint8_t *) mac->UE_info.DLSCH_pdu[CC_idP][0][(unsigned char) UE_id].payload[0], ra->msg4_rrc_sdu_length, UE_id, 3, UE_RNTI (module_idP, UE_id), mac->frame, mac->subframe, 0, 0); @@ -963,10 +963,10 @@ generate_Msg4(module_id_t module_idP, 1, // tpc, none getRIV(N_RB_DL, first_rb, 4), // resource_block_coding ra->msg4_mcs, // mcs - 1 - UE_list->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid], + 1 - UE_info->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid], 0, // rv 0); // vrb_flag - UE_list->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid] = 1 - UE_list->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid]; + UE_info->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid] = 1 - UE_info->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid]; LOG_D(MAC, "Frame %d, subframe %d: Msg4 DCI pdu_num %d (rnti %x,rnti_type %d,harq_pid %d, resource_block_coding (%p) %d\n", frameP, subframeP, dl_req_body->number_pdu, @@ -1000,7 +1000,7 @@ generate_Msg4(module_id_t module_idP, lcid = 0; // put HARQ process round to 0 ra->harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP,subframeP); - UE_list->UE_sched_ctrl[UE_id].round[CC_idP][ra->harq_pid] = 0; + UE_info->UE_sched_ctrl[UE_id].round[CC_idP][ra->harq_pid] = 0; if ((ra->msg4_TBsize - rrc_sdu_length - msg4_header) <= 2) { msg4_padding = ra->msg4_TBsize - rrc_sdu_length - msg4_header; @@ -1018,7 +1018,7 @@ generate_Msg4(module_id_t module_idP, DevAssert(UE_id != UE_INDEX_INVALID); // FIXME not sure how to gracefully return // CHECK THIS: &cc[CC_idP].CCCH_pdu.payload[0] int num_sdus = rrc_sdu_length > 0 ? 1 : 0; - offset = generate_dlsch_header((unsigned char *) mac->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char) UE_id].payload[0], + offset = generate_dlsch_header((unsigned char *) mac->UE_info.DLSCH_pdu[CC_idP][0][(unsigned char) UE_id].payload[0], num_sdus, //num_sdus (unsigned short *) &rrc_sdu_length, // &lcid, // sdu_lcid @@ -1027,7 +1027,7 @@ generate_Msg4(module_id_t module_idP, ra->cont_res_id, // contention res id msg4_padding, // no padding msg4_post_padding); - memcpy((void *) &mac->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0][(unsigned char)offset], + memcpy((void *) &mac->UE_info.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0][(unsigned char)offset], &cc[CC_idP].CCCH_pdu.payload[0], rrc_sdu_length); // DLSCH Config fill_nfapi_dlsch_config(mac, dl_req_body, ra->msg4_TBsize, mac->pdu_index[CC_idP], ra->rnti, 2, // resource_allocation_type : format 1A/1B/1D @@ -1058,7 +1058,7 @@ generate_Msg4(module_id_t module_idP, (frameP * 10) + subframeP, rrc_sdu_length+offset, mac->pdu_index[CC_idP], - mac->UE_list. + mac->UE_info. DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0]); mac->pdu_index[CC_idP]++; dl_req->sfn_sf = mac->TX_req[CC_idP].sfn_sf; @@ -1074,11 +1074,11 @@ generate_Msg4(module_id_t module_idP, T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_idP), T_INT(ra->rnti), T_INT(frameP), T_INT(subframeP), T_INT(0 /*harq_pid always 0? */ ), - T_BUFFER(&mac->UE_list.DLSCH_pdu[CC_idP][0][UE_id]. + T_BUFFER(&mac->UE_info.DLSCH_pdu[CC_idP][0][UE_id]. payload[0], ra->msg4_TBsize)); trace_pdu(DIRECTION_DOWNLINK, (uint8_t *) mac-> - UE_list.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0], + UE_info.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0], rrc_sdu_length, UE_id, WS_C_RNTI, UE_RNTI(module_idP, UE_id), mac->frame, mac->subframe, 0, 0); @@ -1116,14 +1116,14 @@ check_Msg4_retransmission(module_id_t module_idP, int CC_idP, int first_rb; int N_RB_DL; nfapi_dl_config_request_pdu_t *dl_config_pdu; - UE_list_t *UE_list = &mac->UE_list; + UE_info_t *UE_info = &mac->UE_info; nfapi_dl_config_request_t *dl_req; nfapi_dl_config_request_body_t *dl_req_body; int round; // check HARQ status and retransmit if necessary UE_id = find_UE_id(module_idP, ra->rnti); AssertFatal(UE_id >= 0, "Can't find UE for t-crnti\n"); - round = UE_list->UE_sched_ctrl[UE_id].round[CC_idP][ra->harq_pid]; + round = UE_info->UE_sched_ctrl[UE_id].round[CC_idP][ra->harq_pid]; vrb_map = cc[CC_idP].vrb_map; dl_req = &mac->DL_req[CC_idP]; dl_req_body = &dl_req->dl_config_request_body; @@ -1156,7 +1156,7 @@ check_Msg4_retransmission(module_id_t module_idP, int CC_idP, 1, // tpc, none getRIV(N_RB_DL, first_rb, 4), // resource_block_coding ra->msg4_mcs, // mcs - UE_list->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid], + UE_info->UE_template[CC_idP][UE_id].oldNDI[ra->harq_pid], round & 3, // rv 0); // vrb_flag @@ -1226,8 +1226,8 @@ check_Msg4_retransmission(module_id_t module_idP, int CC_idP, LOG_D(MAC,"[eNB %d][RAPROC] Frame %d, Subframe %d: state:IDLE\n", module_idP, frameP, subframeP); UE_id = find_UE_id(module_idP, ra->rnti); DevAssert(UE_id != -1); - mac->UE_list.UE_template[UE_PCCID(module_idP, UE_id)][UE_id].configured = TRUE; - mac->UE_list.UE_template[UE_PCCID(module_idP, UE_id)][UE_id].pusch_repetition_levels=ra->pusch_repetition_levels; + mac->UE_info.UE_template[UE_PCCID(module_idP, UE_id)][UE_id].configured = TRUE; + mac->UE_info.UE_template[UE_PCCID(module_idP, UE_id)][UE_id].pusch_repetition_levels=ra->pusch_repetition_levels; cancel_ra_proc(module_idP, CC_idP, frameP, ra->rnti); } } diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 9a76bd2e4d..e81754de19 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -94,7 +94,7 @@ schedule_next_dlue(module_id_t module_idP, //------------------------------------------------------------------------------ { int next_ue; - UE_list_t *UE_list = &RC.mac[module_idP]->UE_list; + UE_list_t *UE_list = &RC.mac[module_idP]->UE_info.list; for (next_ue = UE_list->head; next_ue >= 0; next_ue = UE_list->next[next_ue]) { if (eNB_dlsch_info[module_idP][CC_id][next_ue].status == S_DL_WAITING) { @@ -317,12 +317,12 @@ set_ul_DAI(int module_idP, //------------------------------------------------------------------------------ { eNB_MAC_INST *eNB = RC.mac[module_idP]; - UE_list_t *UE_list = &eNB->UE_list; + UE_info_t *UE_info = &eNB->UE_info; unsigned char DAI; COMMON_channels_t *cc = &eNB->common_channels[CC_idP]; if (cc->tdd_Config != NULL) { //TDD - DAI = (UE_list->UE_template[CC_idP][UE_idP].DAI - 1) & 3; + DAI = (UE_info->UE_template[CC_idP][UE_idP].DAI - 1) & 3; LOG_D(MAC, "[eNB %d] CC_id %d Frame %d, subframe %d: DAI %d for UE %d\n", module_idP, CC_idP, @@ -341,20 +341,20 @@ set_ul_DAI(int module_idP, switch (subframeP) { case 0: case 1: - UE_list->UE_template[CC_idP][UE_idP].DAI_ul[7] = DAI; + UE_info->UE_template[CC_idP][UE_idP].DAI_ul[7] = DAI; break; case 4: - UE_list->UE_template[CC_idP][UE_idP].DAI_ul[8] = DAI; + UE_info->UE_template[CC_idP][UE_idP].DAI_ul[8] = DAI; break; case 5: case 6: - UE_list->UE_template[CC_idP][UE_idP].DAI_ul[2] = DAI; + UE_info->UE_template[CC_idP][UE_idP].DAI_ul[2] = DAI; break; case 9: - UE_list->UE_template[CC_idP][UE_idP].DAI_ul[3] = DAI; + UE_info->UE_template[CC_idP][UE_idP].DAI_ul[3] = DAI; break; } @@ -362,30 +362,30 @@ set_ul_DAI(int module_idP, case 2: // if ((subframeP==3)||(subframeP==8)) - // UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI; + // UE_info->UE_template[CC_idP][UE_idP].DAI_ul = DAI; break; case 3: //if ((subframeP==6)||(subframeP==8)||(subframeP==0)) { // LOG_D(MAC,"schedule_ue_spec: setting UL DAI to %d for subframeP %d => %d\n",DAI,subframeP, ((subframeP+8)%10)>>1); - // UE_list->UE_template[CC_idP][UE_idP].DAI_ul[((subframeP+8)%10)>>1] = DAI; + // UE_info->UE_template[CC_idP][UE_idP].DAI_ul[((subframeP+8)%10)>>1] = DAI; //} switch (subframeP) { case 5: case 6: case 1: - UE_list->UE_template[CC_idP][UE_idP].DAI_ul[2] = DAI; + UE_info->UE_template[CC_idP][UE_idP].DAI_ul[2] = DAI; break; case 7: case 8: - UE_list->UE_template[CC_idP][UE_idP].DAI_ul[3] = DAI; + UE_info->UE_template[CC_idP][UE_idP].DAI_ul[3] = DAI; break; case 9: case 0: - UE_list->UE_template[CC_idP][UE_idP].DAI_ul[4] = DAI; + UE_info->UE_template[CC_idP][UE_idP].DAI_ul[4] = DAI; break; default: @@ -396,17 +396,17 @@ set_ul_DAI(int module_idP, case 4: // if ((subframeP==8)||(subframeP==9)) - // UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI; + // UE_info->UE_template[CC_idP][UE_idP].DAI_ul = DAI; break; case 5: // if (subframeP==8) - // UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI; + // UE_info->UE_template[CC_idP][UE_idP].DAI_ul = DAI; break; case 6: // if ((subframeP==1)||(subframeP==4)||(subframeP==6)||(subframeP==9)) - // UE_list->UE_template[CC_idP][UE_idP].DAI_ul = DAI; + // UE_info->UE_template[CC_idP][UE_idP].DAI_ul = DAI; break; default: @@ -474,7 +474,7 @@ schedule_ue_spec(module_id_t module_idP, int sdu_length_total = 0; eNB_MAC_INST *eNB = RC.mac[module_idP]; COMMON_channels_t *cc = eNB->common_channels; - UE_list_t *UE_list = &eNB->UE_list; + UE_info_t *UE_info = &eNB->UE_info; int continue_flag = 0; int32_t snr, target_snr; int tpc = 1; @@ -558,7 +558,7 @@ schedule_ue_spec(module_id_t module_idP, total_nb_available_rb--; // store the global enb stats: - eNB->eNB_stats[CC_id].num_dlactive_UEs = UE_list->num_UEs; + eNB->eNB_stats[CC_id].num_dlactive_UEs = UE_info->num_UEs; eNB->eNB_stats[CC_id].available_prbs = total_nb_available_rb; eNB->eNB_stats[CC_id].total_available_prbs += total_nb_available_rb; eNB->eNB_stats[CC_id].dlsch_bytes_tx = 0; @@ -581,24 +581,24 @@ schedule_ue_spec(module_id_t module_idP, CC_id); dl_req = &eNB->DL_req[CC_id].dl_config_request_body; - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + for (UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { LOG_D(MAC, "doing schedule_ue_spec for CC_id %d UE %d\n", CC_id, UE_id); continue_flag = 0; // reset the flag to allow allocation for the remaining UEs rnti = UE_RNTI(module_idP, UE_id); - ue_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id]; - ue_template = &UE_list->UE_template[CC_id][UE_id]; + ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + ue_template = &UE_info->UE_template[CC_id][UE_id]; if (ue_template->rach_resource_type > 0) { continue_flag = 1; } - if (&(UE_list->eNB_UE_stats[CC_id][UE_id]) == NULL) { + if (&(UE_info->eNB_UE_stats[CC_id][UE_id]) == NULL) { LOG_D(MAC, "[eNB] Cannot find eNB_UE_stats\n"); continue_flag = 1; } else { - eNB_UE_stats = &(UE_list->eNB_UE_stats[CC_id][UE_id]); + eNB_UE_stats = &(UE_info->eNB_UE_stats[CC_id][UE_id]); } if (continue_flag != 1) { @@ -650,7 +650,7 @@ schedule_ue_spec(module_id_t module_idP, UE_id, CC_id, cc[CC_id].tdd_Config->subframeAssignment, - UE_list); + UE_info); // update UL DAI after DLSCH scheduling set_ul_DAI(module_idP, UE_id, @@ -1316,7 +1316,7 @@ schedule_ue_spec(module_id_t module_idP, post_padding = 1; } - offset = generate_dlsch_header((unsigned char *) UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], + offset = generate_dlsch_header((unsigned char *) UE_info->DLSCH_pdu[CC_id][0][UE_id].payload[0], num_sdus, //num_sdus sdu_lengths, // sdu_lcids, @@ -1360,7 +1360,7 @@ schedule_ue_spec(module_id_t module_idP, LOG_T(MAC, "\n"); #endif // cycle through SDUs and place in dlsch_buffer - dlsch_pdu = &UE_list->DLSCH_pdu[CC_id][0][UE_id]; + dlsch_pdu = &UE_info->DLSCH_pdu[CC_id][0][UE_id]; memcpy(&dlsch_pdu->payload[0][offset], dlsch_buffer, sdu_length_total); @@ -1654,7 +1654,7 @@ schedule_ue_spec_br(module_id_t module_idP, unsigned char dlsch_buffer[MAX_DLSCH_PAYLOAD_BYTES]; eNB_MAC_INST *mac = RC.mac[module_idP]; COMMON_channels_t *cc = mac->common_channels; - UE_list_t *UE_list = &mac->UE_list; + UE_info_t *UE_info = &mac->UE_info; UE_TEMPLATE *UE_template = NULL; UE_sched_ctrl_t *ue_sched_ctl = NULL; nfapi_dl_config_request_pdu_t *dl_config_pdu = NULL; @@ -1719,7 +1719,7 @@ schedule_ue_spec_br(module_id_t module_idP, } } - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + for (UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { int harq_pid = 0; rnti = UE_RNTI(module_idP, UE_id); @@ -1727,8 +1727,8 @@ schedule_ue_spec_br(module_id_t module_idP, continue; } - ue_sched_ctl = &(UE_list->UE_sched_ctrl[UE_id]); - UE_template = &(UE_list->UE_template[CC_id][UE_id]); + ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; + UE_template = &UE_info->UE_template[CC_id][UE_id]; if (UE_template->rach_resource_type == 0) { continue; @@ -1836,8 +1836,8 @@ schedule_ue_spec_br(module_id_t module_idP, sdu_lengths[0]); sdu_length_total = sdu_lengths[0]; sdu_lcids[0] = DCCH; - UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[DCCH]+=1; - UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DCCH]+=sdu_lengths[0]; + UE_info->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[DCCH]+=1; + UE_info->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DCCH]+=sdu_lengths[0]; num_sdus = 1; } else { header_len_dcch = 0; @@ -1889,8 +1889,8 @@ schedule_ue_spec_br(module_id_t module_idP, sdu_lcids[num_sdus] = DCCH1; sdu_length_total += sdu_lengths[num_sdus]; header_len_dcch += 2; - UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[DCCH1] += 1; - UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DCCH1] += sdu_lengths[num_sdus]; + UE_info->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[DCCH1] += 1; + UE_info->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DCCH1] += sdu_lengths[num_sdus]; num_sdus++; } } @@ -2042,7 +2042,7 @@ schedule_ue_spec_br(module_id_t module_idP, post_padding = TBS - sdu_length_total - header_len_dcch - header_len_dtch - ta_len; // 1 is for the postpadding header } - offset = generate_dlsch_header((unsigned char *)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], + offset = generate_dlsch_header((unsigned char *)UE_info->DLSCH_pdu[CC_id][0][UE_id].payload[0], num_sdus, //num_sdus sdu_lengths, // sdu_lcids, @@ -2075,15 +2075,15 @@ schedule_ue_spec_br(module_id_t module_idP, } /* Cycle through SDUs and place in dlsch_buffer */ - memcpy(&UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset], dlsch_buffer, sdu_length_total); + memcpy(&UE_info->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset], dlsch_buffer, sdu_length_total); /* Fill remainder of DLSCH with random data */ for (j = 0; j < (TBS - sdu_length_total - offset); j++) { - UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset + sdu_length_total + j] = (char)(taus()&0xff); + UE_info->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset + sdu_length_total + j] = (char)(taus()&0xff); } trace_pdu(DIRECTION_DOWNLINK, - (uint8_t *)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], + (uint8_t *)UE_info->DLSCH_pdu[CC_id][0][UE_id].payload[0], TBS, module_idP, 3, @@ -2099,7 +2099,7 @@ schedule_ue_spec_br(module_id_t module_idP, T_INT(frameP), T_INT(subframeP), T_INT(harq_pid), - T_BUFFER(UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], TBS)); + T_BUFFER(UE_info->DLSCH_pdu[CC_id][0][UE_id].payload[0], TBS)); /* Do PUCCH power control */ /* This is the snr */ /* unit is not dBm, it's special from nfapi, convert to dBm */ @@ -2107,15 +2107,15 @@ schedule_ue_spec_br(module_id_t module_idP, target_snr = mac->puCch10xSnr / 10; /* This assumes accumulated tpc */ /* Make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out */ - int32_t framex10psubframe = UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_frame * 10 + UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe; + int32_t framex10psubframe = UE_info->UE_template[CC_id][UE_id].pucch_tpc_tx_frame * 10 + UE_info->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe; if (((framex10psubframe + 10) <= (frameP * 10 + subframeP)) || // normal case ((framex10psubframe > (frameP * 10 + subframeP)) && (((10240 - framex10psubframe +frameP * 10 + subframeP) >= 10)))) { // frame wrap-around if (ue_sched_ctl->pucch1_cqi_update[CC_id] == 1) { ue_sched_ctl->pucch1_cqi_update[CC_id] = 0; - UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_frame = frameP; - UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe = subframeP; + UE_info->UE_template[CC_id][UE_id].pucch_tpc_tx_frame = frameP; + UE_info->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe = subframeP; if (snr > target_snr + 4) { tpc = 0; //-1 @@ -2249,7 +2249,7 @@ schedule_ue_spec_br(module_id_t module_idP, TX_req->pdu_index = mac->pdu_index[CC_id]++; TX_req->num_segments = 1; TX_req->segments[0].segment_length = TX_req->pdu_length; - TX_req->segments[0].segment_data = mac->UE_list.DLSCH_pdu[CC_id][0][(unsigned char) UE_id].payload[0]; + TX_req->segments[0].segment_data = mac->UE_info.DLSCH_pdu[CC_id][0][(unsigned char) UE_id].payload[0]; mac->TX_req[CC_id].tx_request_body.number_of_pdus++; ackNAK_absSF = absSF + 4; ul_req = &mac->UL_req_tmp[CC_id][ackNAK_absSF % 10].ul_config_request_body; @@ -2283,9 +2283,9 @@ schedule_ue_spec_br(module_id_t module_idP, T_INT (frameP), T_INT (subframeP), T_INT (0 /* harq_pid always 0? */ ), - T_BUFFER (&mac->UE_list.DLSCH_pdu[CC_id][0][UE_id].payload[0], TX_req->pdu_length)); + T_BUFFER (&mac->UE_info.DLSCH_pdu[CC_id][0][UE_id].payload[0], TX_req->pdu_length)); trace_pdu(1, - (uint8_t *) mac->UE_list.DLSCH_pdu[CC_id][0][(unsigned char) UE_id].payload[0], + (uint8_t *) mac->UE_info.DLSCH_pdu[CC_id][0][(unsigned char) UE_id].payload[0], TX_req->pdu_length, UE_id, 3, @@ -2317,7 +2317,7 @@ fill_DLSCH_dci(module_id_t module_idP, int i; int CC_id; eNB_MAC_INST *eNB = RC.mac[module_idP]; - UE_list_t *UE_list = &eNB->UE_list; + UE_info_t *UE_info = &eNB->UE_info; int N_RBG; int N_RB_DL; COMMON_channels_t *cc; @@ -2336,7 +2336,7 @@ fill_DLSCH_dci(module_id_t module_idP, N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth); // UE specific DCIs - for (UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + for (UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { dlsch_info = &eNB_dlsch_info[module_idP][CC_id][UE_id]; LOG_T(MAC, "CC_id %d, UE_id: %d => status %d\n", CC_id, @@ -2349,7 +2349,7 @@ fill_DLSCH_dci(module_id_t module_idP, rnti = UE_RNTI(module_idP, UE_id); harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP, subframeP); - ue_template = &UE_list->UE_template[CC_id][UE_id]; + ue_template = &UE_info->UE_template[CC_id][UE_id]; nb_rb = ue_template->nb_rb[harq_pid]; /// Synchronizing rballoc with rballoc_sub @@ -2425,7 +2425,7 @@ unsigned char *get_dlsch_sdu(module_id_t module_idP, CC_id, rntiP, UE_id); - return ((unsigned char *) &eNB->UE_list.DLSCH_pdu[CC_id][TBindex][UE_id].payload[0]); + return ((unsigned char *) &eNB->UE_info.DLSCH_pdu[CC_id][TBindex][UE_id].payload[0]); } LOG_E(MAC, "[eNB %d] Frame %d: CC_id %d UE with RNTI %x does not exist\n", @@ -2470,61 +2470,61 @@ set_ue_dai(sub_frame_t subframeP, int UE_id, uint8_t CC_id, uint8_t tdd_config, - UE_list_t *UE_list) + UE_info_t *UE_info) //------------------------------------------------------------------------------ { switch (tdd_config) { case 0: if (subframeP == 0 || subframeP == 1 || subframeP == 3 || subframeP == 5 || subframeP == 6 || subframeP == 8) { - UE_list->UE_template[CC_id][UE_id].DAI = 0; + UE_info->UE_template[CC_id][UE_id].DAI = 0; } break; case 1: if (subframeP == 0 || subframeP == 4 || subframeP == 5 || subframeP == 9) { - UE_list->UE_template[CC_id][UE_id].DAI = 0; + UE_info->UE_template[CC_id][UE_id].DAI = 0; } break; case 2: if (subframeP == 4 || subframeP == 5) { - UE_list->UE_template[CC_id][UE_id].DAI = 0; + UE_info->UE_template[CC_id][UE_id].DAI = 0; } break; case 3: if (subframeP == 5 || subframeP == 7 || subframeP == 9) { - UE_list->UE_template[CC_id][UE_id].DAI = 0; + UE_info->UE_template[CC_id][UE_id].DAI = 0; } break; case 4: if (subframeP == 0 || subframeP == 6) { - UE_list->UE_template[CC_id][UE_id].DAI = 0; + UE_info->UE_template[CC_id][UE_id].DAI = 0; } break; case 5: if (subframeP == 9) { - UE_list->UE_template[CC_id][UE_id].DAI = 0; + UE_info->UE_template[CC_id][UE_id].DAI = 0; } break; case 6: if (subframeP == 0 || subframeP == 1 || subframeP == 5 || subframeP == 6 || subframeP == 9) { - UE_list->UE_template[CC_id][UE_id].DAI = 0; + UE_info->UE_template[CC_id][UE_id].DAI = 0; } break; default: - UE_list->UE_template[CC_id][UE_id].DAI = 0; + UE_info->UE_template[CC_id][UE_id].DAI = 0; LOG_I(MAC, "unknown TDD config %d\n", tdd_config); break; diff --git a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c index e934a54c7c..1cc54454fa 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c @@ -120,7 +120,7 @@ void pre_scd_nb_rbs_required( module_id_t module_idP, if(N_RB_DL==100) step_size=4; memset(nb_rbs_required, 0, sizeof(uint16_t)*MAX_NUM_CCs*NUMBER_OF_UE_MAX); - UE_list_t *UE_list = &RC.mac[module_idP]->UE_list; + UE_info_t *UE_info = &RC.mac[module_idP]->UE_info; for (UE_id = 0; UE_id dlsch_mcs1 = cqi_to_mcs[UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id]]; + eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]]; if (UE_template.dl_buffer_total > 0) { nb_rbs_required[CC_id][UE_id] = search_rbs_required(eNB_UE_stats->dlsch_mcs1, UE_template.dl_buffer_total, N_RB_DL, step_size); @@ -175,7 +175,7 @@ void dlsch_scheduler_pre_ue_select_fairRR( DLSCH_UE_SELECT dlsch_ue_select[MAX_NUM_CCs]) { eNB_MAC_INST *eNB = RC.mac[module_idP]; COMMON_channels_t *cc = eNB->common_channels; - UE_list_t *UE_list = &eNB->UE_list; + UE_info_t *UE_info = &eNB->UE_info; UE_sched_ctrl_t *ue_sched_ctl; uint8_t CC_id; int UE_id; @@ -208,7 +208,7 @@ void dlsch_scheduler_pre_ue_select_fairRR( DL_req = &eNB->DL_req[CC_id].dl_config_request_body; for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) { - if (UE_list->active[UE_id] == FALSE) { + if (UE_info->active[UE_id] == FALSE) { continue; } @@ -222,12 +222,12 @@ void dlsch_scheduler_pre_ue_select_fairRR( continue; } - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; harq_pid = frame_subframe2_dl_harq_pid(cc[CC_id].tdd_Config,frameP,subframeP); round = ue_sched_ctl->round[CC_id][harq_pid]; if (round != 8) { // retransmission - if(UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid] == 0) { + if(UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid] == 0) { continue; } @@ -266,7 +266,7 @@ void dlsch_scheduler_pre_ue_select_fairRR( dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = (format_flag == 0)?2:1; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = aggregation; DL_req->number_pdu++; - nb_rbs_required[CC_id][UE_id] = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid]; + nb_rbs_required[CC_id][UE_id] = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid]; // Insert DLSCH(retransmission) UE into selected UE list dlsch_ue_select[CC_id].list[dlsch_ue_select[CC_id].ue_num].UE_id = UE_id; dlsch_ue_select[CC_id].list[dlsch_ue_select[CC_id].ue_num].ue_priority = SCH_DL_RETRANS; @@ -284,7 +284,7 @@ void dlsch_scheduler_pre_ue_select_fairRR( UE_id, CC_id, cc[CC_id].tdd_Config->subframeAssignment, - UE_list); + UE_info); // update UL DAI after DLSCH scheduling set_ul_DAI(module_idP,UE_id,CC_id,frameP,subframeP); } @@ -324,7 +324,7 @@ void dlsch_scheduler_pre_ue_select_fairRR( break; } - if (UE_list->active[UE_id] == FALSE) { + if (UE_info->active[UE_id] == FALSE) { continue; } @@ -337,7 +337,7 @@ void dlsch_scheduler_pre_ue_select_fairRR( continue; } - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; for(i = 0; isubframeAssignment, - UE_list); + UE_info); // update UL DAI after DLSCH scheduling set_ul_DAI(module_idP,UE_id,CC_id,frameP,subframeP); } @@ -448,7 +448,7 @@ void dlsch_scheduler_pre_ue_select_fairRR( break; } - if (UE_list->active[UE_id] == FALSE) { + if (UE_info->active[UE_id] == FALSE) { continue; } @@ -461,7 +461,7 @@ void dlsch_scheduler_pre_ue_select_fairRR( continue; } - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; for(i = 0; isubframeAssignment, - UE_list); + UE_info); // update UL DAI after DLSCH scheduling set_ul_DAI(module_idP,UE_id,CC_id,frameP,subframeP); } @@ -569,7 +569,7 @@ void dlsch_scheduler_pre_processor_reset_fairRR( int UE_id; uint8_t CC_id; int i, j; - UE_list_t *UE_list; + UE_info_t *UE_info; UE_sched_ctrl_t *ue_sched_ctl; int N_RB_DL, RBGsize, RBGsize_last; int N_RBG[NFAPI_CC_MAX]; @@ -585,14 +585,14 @@ void dlsch_scheduler_pre_processor_reset_fairRR( min_rb_unit[CC_id] = get_min_rb_unit(module_idP, CC_id); for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; ++UE_id) { - UE_list = &RC.mac[module_idP]->UE_list; - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + UE_info = &RC.mac[module_idP]->UE_info; + ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; rnti = UE_RNTI(module_idP, UE_id); if (rnti == NOT_A_RNTI) continue; - if (UE_list->active[UE_id] != TRUE) + if (UE_info->active[UE_id] != TRUE) continue; LOG_D(MAC, "Running preprocessor for UE %d (%x)\n", UE_id, rnti); @@ -734,48 +734,48 @@ void assign_rbs_required_fairRR( uint16_t nb_rbs_required[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]) { uint16_t TBS = 0; int UE_id, n, i, j, CC_id, pCCid, tmp; - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; + UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; eNB_UE_STATS *eNB_UE_stats, *eNB_UE_stats_i, *eNB_UE_stats_j; int N_RB_DL; // clear rb allocations across all CC_id for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) { - if (UE_list->active[UE_id] != TRUE) + if (UE_info->active[UE_id] != TRUE) continue; pCCid = UE_PCCID(Mod_id, UE_id); // update CQI information across component carriers - for (n = 0; n < UE_list->numactiveCCs[UE_id]; n++) { - CC_id = UE_list->ordered_CCids[n][UE_id]; - eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id]; - eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id]]; + for (n = 0; n < UE_info->numactiveCCs[UE_id]; n++) { + CC_id = UE_info->ordered_CCids[n][UE_id]; + eNB_UE_stats = &UE_info->eNB_UE_stats[CC_id][UE_id]; + eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]]; } // provide the list of CCs sorted according to MCS - for (i = 0; i < UE_list->numactiveCCs[UE_id]; ++i) { + for (i = 0; i < UE_info->numactiveCCs[UE_id]; ++i) { eNB_UE_stats_i = - &UE_list->eNB_UE_stats[UE_list->ordered_CCids[i][UE_id]][UE_id]; + &UE_info->eNB_UE_stats[UE_info->ordered_CCids[i][UE_id]][UE_id]; - for (j = i + 1; j < UE_list->numactiveCCs[UE_id]; j++) { + for (j = i + 1; j < UE_info->numactiveCCs[UE_id]; j++) { DevAssert(j < NFAPI_CC_MAX); eNB_UE_stats_j = - &UE_list->eNB_UE_stats[UE_list->ordered_CCids[j][UE_id]][UE_id]; + &UE_info->eNB_UE_stats[UE_info->ordered_CCids[j][UE_id]][UE_id]; if (eNB_UE_stats_j->dlsch_mcs1 > eNB_UE_stats_i->dlsch_mcs1) { - tmp = UE_list->ordered_CCids[i][UE_id]; - UE_list->ordered_CCids[i][UE_id] = UE_list->ordered_CCids[j][UE_id]; - UE_list->ordered_CCids[j][UE_id] = tmp; + tmp = UE_info->ordered_CCids[i][UE_id]; + UE_info->ordered_CCids[i][UE_id] = UE_info->ordered_CCids[j][UE_id]; + UE_info->ordered_CCids[j][UE_id] = tmp; } } } - if (UE_list->UE_template[pCCid][UE_id].dl_buffer_total > 0) { + if (UE_info->UE_template[pCCid][UE_id].dl_buffer_total > 0) { LOG_D(MAC, "[preprocessor] assign RB for UE %d\n", UE_id); - for (i = 0; i < UE_list->numactiveCCs[UE_id]; i++) { - CC_id = UE_list->ordered_CCids[i][UE_id]; - eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id]; + for (i = 0; i < UE_info->numactiveCCs[UE_id]; i++) { + CC_id = UE_info->ordered_CCids[i][UE_id]; + eNB_UE_stats = &UE_info->eNB_UE_stats[CC_id][UE_id]; const int min_rb_unit = get_min_rb_unit(Mod_id, CC_id); if (eNB_UE_stats->dlsch_mcs1 == 0) { @@ -790,14 +790,14 @@ void assign_rbs_required_fairRR( "buffer %d (RB unit %d, MCS %d, TBS %d) \n", UE_id, CC_id, - UE_list->UE_template[pCCid][UE_id].dl_buffer_total, + UE_info->UE_template[pCCid][UE_id].dl_buffer_total, nb_rbs_required[CC_id][UE_id], eNB_UE_stats->dlsch_mcs1, TBS); N_RB_DL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); /* calculating required number of RBs for each UE */ - while (TBS < UE_list->UE_template[pCCid][UE_id].dl_buffer_total) { + while (TBS < UE_info->UE_template[pCCid][UE_id].dl_buffer_total) { nb_rbs_required[CC_id][UE_id] += min_rb_unit; if (nb_rbs_required[CC_id][UE_id] > N_RB_DL) { @@ -835,8 +835,8 @@ void dlsch_scheduler_pre_processor_allocate_fairRR( uint16_t nb_rbs_remaining[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB], uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]) { int i; - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - UE_sched_ctrl_t *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; + UE_sched_ctrl_t *ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; int N_RB_DL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); const int min_rb_unit = get_min_rb_unit(Mod_id, CC_id); @@ -904,7 +904,7 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id, int min_rb_unit[MAX_NUM_CCs]; // uint16_t r1=0; uint8_t CC_id; - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; + UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; int N_RB_DL; UE_sched_ctrl_t *ue_sched_ctl; // int rrc_status = RRC_IDLE; @@ -930,7 +930,7 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id, min_rb_unit[CC_id] = get_min_rb_unit(Mod_id, CC_id); for (i = 0; i < NUMBER_OF_UE_MAX; i++) { - if (UE_list->active[i] != TRUE) + if (UE_info->active[i] != TRUE) continue; UE_id = i; @@ -999,7 +999,7 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id, } rnti = dlsch_ue_select[CC_id].list[i].rnti; - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP,subframeP); Round = ue_sched_ctl->round[CC_id][harq_pid]; @@ -1095,7 +1095,7 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id, } UE_id = dlsch_ue_select[CC_id].list[i].UE_id; - ue_sched_ctl = &RC.mac[Mod_id]->UE_list.UE_sched_ctrl[UE_id]; + ue_sched_ctl = &RC.mac[Mod_id]->UE_info.UE_sched_ctrl[UE_id]; //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].dl_pow_off = dl_pow_off[UE_id]; if (ue_sched_ctl->pre_nb_available_rbs[CC_id] > 0) { @@ -1148,7 +1148,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, uint16_t sdu_length_total = 0; eNB_MAC_INST *eNB = RC.mac[module_idP]; COMMON_channels_t *cc = eNB->common_channels; - UE_list_t *UE_list = &eNB->UE_list; + UE_info_t *UE_info = &eNB->UE_info; // int continue_flag = 0; int32_t snr, target_snr; int32_t tpc = 1; @@ -1246,7 +1246,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, N_RBG[CC_id] = to_rbg(cc[CC_id].mib->message.dl_Bandwidth); // store the global enb stats: - eNB->eNB_stats[CC_id].num_dlactive_UEs = UE_list->num_UEs; + eNB->eNB_stats[CC_id].num_dlactive_UEs = UE_info->num_UEs; eNB->eNB_stats[CC_id].available_prbs = total_nb_available_rb[CC_id]; eNB->eNB_stats[CC_id].total_available_prbs += @@ -1286,12 +1286,12 @@ schedule_ue_spec_fairRR(module_id_t module_idP, rnti = UE_RNTI(module_idP,UE_id); if (rnti==NOT_A_RNTI) { - LOG_E(MAC,"Cannot find rnti for UE_id %d (num_UEs %d)\n",UE_id,UE_list->num_UEs); + LOG_E(MAC,"Cannot find rnti for UE_id %d (num_UEs %d)\n",UE_id,UE_info->num_UEs); continue; } - eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id]; - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + eNB_UE_stats = &UE_info->eNB_UE_stats[CC_id][UE_id]; + ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; /* switch(get_tmode(module_idP,CC_id,UE_id)){ @@ -1318,7 +1318,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, UE_id, CC_id, cc[CC_id].tdd_Config->subframeAssignment, - UE_list); + UE_info); // update UL DAI after DLSCH scheduling set_ul_DAI(module_idP,UE_id,CC_id,frameP,subframeP); } @@ -1326,18 +1326,16 @@ schedule_ue_spec_fairRR(module_id_t module_idP, nb_available_rb = ue_sched_ctl->pre_nb_available_rbs[CC_id]; harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP,subframeP); round = ue_sched_ctl->round[CC_id][harq_pid]; - UE_list->eNB_UE_stats[CC_id][UE_id].crnti = rnti; - UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status = - mac_eNB_get_rrc_status(module_idP, rnti); - UE_list->eNB_UE_stats[CC_id][UE_id].harq_pid = harq_pid; - UE_list->eNB_UE_stats[CC_id][UE_id].harq_round = round; + UE_info->eNB_UE_stats[CC_id][UE_id].crnti = rnti; + UE_info->eNB_UE_stats[CC_id][UE_id].rrc_status = mac_eNB_get_rrc_status(module_idP, rnti); + UE_info->eNB_UE_stats[CC_id][UE_id].harq_pid = harq_pid; + UE_info->eNB_UE_stats[CC_id][UE_id].harq_round = round; - if (UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status < RRC_RECONFIGURED) { - UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0; + if (UE_info->eNB_UE_stats[CC_id][UE_id].rrc_status < RRC_RECONFIGURED) { + UE_info->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0; } - if (UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status < - RRC_CONNECTED) + if (UE_info->eNB_UE_stats[CC_id][UE_id].rrc_status < RRC_CONNECTED) continue; sdu_length_total = 0; @@ -1356,13 +1354,11 @@ schedule_ue_spec_fairRR(module_id_t module_idP, //eNB_UE_stats->dlsch_mcs1 = cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs); // store stats - //UE_list->eNB_UE_stats[CC_id][UE_id].dl_cqi= eNB_UE_stats->dl_cqi; + //UE_info->eNB_UE_stats[CC_id][UE_id].dl_cqi= eNB_UE_stats->dl_cqi; // initializing the rb allocation indicator for each UE for (j = 0; j < N_RBG[CC_id]; j++) { - UE_list-> - UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] - = 0; + UE_info->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = 0; } LOG_D(MAC, @@ -1370,33 +1366,31 @@ schedule_ue_spec_fairRR(module_id_t module_idP, module_idP, frameP, UE_id, CC_id, rnti, harq_pid, round, nb_available_rb, ue_sched_ctl->dl_cqi[CC_id], eNB_UE_stats->dlsch_mcs1, - UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status); + UE_info->eNB_UE_stats[CC_id][UE_id].rrc_status); /* process retransmission */ if (round != 8) { // get freq_allocation - nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid]; + nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid]; TBS = - get_TBS_DL(UE_list-> - UE_template[CC_id][UE_id].oldmcs1[harq_pid], + get_TBS_DL(UE_info->UE_template[CC_id][UE_id].oldmcs1[harq_pid], nb_rb); if (nb_rb <= nb_available_rb) { if (cc[CC_id].tdd_Config != NULL) { - UE_list->UE_template[CC_id][UE_id].DAI++; + UE_info->UE_template[CC_id][UE_id].DAI++; update_ul_dci(module_idP, CC_id, rnti, - UE_list->UE_template[CC_id][UE_id]. - DAI,subframeP); + UE_info->UE_template[CC_id][UE_id].DAI,subframeP); LOG_D(MAC, "DAI update: CC_id %d subframeP %d: UE %d, DAI %d\n", CC_id, subframeP, UE_id, - UE_list->UE_template[CC_id][UE_id].DAI); + UE_info->UE_template[CC_id][UE_id].DAI); } if (nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) { for (j = 0; j < N_RBG[CC_id]; j++) { // for indicating the rballoc for each sub-band - UE_list->UE_template[CC_id][UE_id]. + UE_info->UE_template[CC_id][UE_id]. rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j]; } @@ -1407,16 +1401,10 @@ schedule_ue_spec_fairRR(module_id_t module_idP, while ((nb_rb_temp > 0) && (j < N_RBG[CC_id])) { if (ue_sched_ctl->rballoc_sub_UE[CC_id][j] == 1) { - if (UE_list-> - UE_template[CC_id] - [UE_id].rballoc_subband[harq_pid][j]) - printf - ("WARN: rballoc_subband not free for retrans?\n"); + if (UE_info->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j]) + LOG_W(MAC, "WARN: rballoc_subband not free for retrans?\n"); - UE_list-> - UE_template[CC_id] - [UE_id].rballoc_subband[harq_pid][j] = - ue_sched_ctl->rballoc_sub_UE[CC_id][j]; + UE_info->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j]; if ((j == N_RBG[CC_id] - 1) && ((N_RB_DL[CC_id] == 25) || @@ -1440,7 +1428,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, eNB->mu_mimo_mode[UE_id].dl_pow_off = ue_sched_ctl->dl_pow_off[CC_id]; for(j=0; jmu_mimo_mode[UE_id].rballoc_sub[j] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j]; + eNB->mu_mimo_mode[UE_id].rballoc_sub[j] = UE_info->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j]; } */ @@ -1477,36 +1465,23 @@ schedule_ue_spec_fairRR(module_id_t module_idP, harq_process = harq_pid; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // dont adjust power when retransmitting dl_config_pdu->dci_dl_pdu. - dci_dl_pdu_rel8.new_data_indicator_1 = - UE_list->UE_template[CC_id][UE_id]. - oldNDI[harq_pid]; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = - UE_list->UE_template[CC_id][UE_id]. - oldmcs1[harq_pid]; - dl_config_pdu->dci_dl_pdu. - dci_dl_pdu_rel8.redundancy_version_1 = - round & 3; + dci_dl_pdu_rel8.new_data_indicator_1 = UE_info->UE_template[CC_id][UE_id].oldNDI[harq_pid]; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = UE_info->UE_template[CC_id][UE_id].oldmcs1[harq_pid]; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = round & 3; if (cc[CC_id].tdd_Config != NULL) { //TDD dl_config_pdu->dci_dl_pdu. - dci_dl_pdu_rel8.downlink_assignment_index = - (UE_list->UE_template[CC_id][UE_id].DAI - - 1) & 3; + dci_dl_pdu_rel8.downlink_assignment_index = (UE_info->UE_template[CC_id][UE_id].DAI - 1) & 3; LOG_D(MAC, "[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, dai %d, mcs %d\n", module_idP, CC_id, harq_pid, round, - (UE_list->UE_template[CC_id][UE_id].DAI - - 1), - UE_list-> - UE_template[CC_id][UE_id].oldmcs1 - [harq_pid]); + UE_info->UE_template[CC_id][UE_id].DAI - 1, + UE_info-> UE_template[CC_id][UE_id].oldmcs1[harq_pid]); } else { LOG_D(MAC, "[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, mcs %d\n", module_idP, CC_id, harq_pid, round, - UE_list-> - UE_template[CC_id][UE_id].oldmcs1 - [harq_pid]); + UE_info->UE_template[CC_id][UE_id].oldmcs1[harq_pid]); } if (!CCE_allocation_infeasible @@ -1523,7 +1498,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, , rnti, 0, // type 0 allocation from 7.1.6 in 36.213 0, // virtual_resource_block_assignment_flag, unused here 0, // resource_block_coding, to be filled in later - getQm(UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid]), round & 3, // redundancy version + getQm(UE_info->UE_template[CC_id][UE_id].oldmcs1[harq_pid]), round & 3, // redundancy version 1, // transport blocks 0, // transport block to codeword swap flag cc[CC_id].p_eNB == 1 ? 0 : 1, // transmission_scheme @@ -1531,7 +1506,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, 1, // number of subbands // uint8_t codebook_index, 4, // UE category capacity - UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated->p_a, 0, // delta_power_offset for TM5 + UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated->p_a, 0, // delta_power_offset for TM5 0, // ngap 0, // nprb cc[CC_id].p_eNB == 1 ? 1 : 2, // transmission mode @@ -1561,16 +1536,11 @@ schedule_ue_spec_fairRR(module_id_t module_idP, S_DL_SCHEDULED, rnti); //eNB_UE_stats->dlsch_trials[round]++; - UE_list->eNB_UE_stats[CC_id][UE_id]. - num_retransmission += 1; - UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_retx = - nb_rb; - UE_list->eNB_UE_stats[CC_id][UE_id]. - total_rbs_used_retx += nb_rb; - UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = - eNB_UE_stats->dlsch_mcs1; - UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2 = - eNB_UE_stats->dlsch_mcs1; + UE_info->eNB_UE_stats[CC_id][UE_id].num_retransmission += 1; + UE_info->eNB_UE_stats[CC_id][UE_id].rbs_used_retx = nb_rb; + UE_info->eNB_UE_stats[CC_id][UE_id].total_rbs_used_retx += nb_rb; + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = eNB_UE_stats->dlsch_mcs1; + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2 = eNB_UE_stats->dlsch_mcs1; } else { LOG_D(MAC, "[eNB %d] Frame %d CC_id %d : don't schedule UE %d, its retransmission takes more resources than we have\n", @@ -1682,11 +1652,8 @@ schedule_ue_spec_fairRR(module_id_t module_idP, module_idP, CC_id, frameP, subframeP, UE_id, rnti, sdu_lengths[0],rlc_status.bytes_in_buffer,rrc_release_info.num_UEs); sdu_length_total = sdu_lengths[0]; sdu_lcids[0] = DCCH; - UE_list->eNB_UE_stats[CC_id][UE_id]. - num_pdu_tx[DCCH] += 1; - UE_list-> - eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DCCH] - += sdu_lengths[0]; + UE_info->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[DCCH] += 1; + UE_info->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DCCH] += sdu_lengths[0]; num_sdus = 1; #ifdef DEBUG_eNB_SCHEDULER LOG_T(MAC, @@ -1727,11 +1694,8 @@ schedule_ue_spec_fairRR(module_id_t module_idP, sdu_lcids[num_sdus] = DCCH1; sdu_length_total += sdu_lengths[num_sdus]; header_len_dcch += 2; - UE_list->eNB_UE_stats[CC_id][UE_id]. - num_pdu_tx[DCCH1] += 1; - UE_list-> - eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DCCH1] - += sdu_lengths[num_sdus]; + UE_info->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[DCCH1] += 1; + UE_info->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[DCCH1] += sdu_lengths[num_sdus]; num_sdus++; #ifdef DEBUG_eNB_SCHEDULER LOG_T(MAC, @@ -1808,8 +1772,8 @@ schedule_ue_spec_fairRR(module_id_t module_idP, lcid); sdu_lcids[num_sdus] = lcid; sdu_length_total += sdu_lengths[num_sdus]; - UE_list->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[lcid] += 1; - UE_list->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[lcid] += sdu_lengths[num_sdus]; + UE_info->eNB_UE_stats[CC_id][UE_id].num_pdu_tx[lcid] += 1; + UE_info->eNB_UE_stats[CC_id][UE_id].num_bytes_tx[lcid] += sdu_lengths[num_sdus]; if (sdu_lengths[num_sdus] < 128) { header_len_dtch--; @@ -1817,7 +1781,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, } num_sdus++; - UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0; + UE_info->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0; } else { // no data for this LCID header_len_dtch -= 3; } @@ -1870,9 +1834,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, if (nb_rb == ue_sched_ctl->pre_nb_available_rbs[CC_id]) { for (j = 0; j < N_RBG[CC_id]; j++) { // for indicating the rballoc for each sub-band - UE_list->UE_template[CC_id][UE_id]. - rballoc_subband[harq_pid][j] = - ue_sched_ctl->rballoc_sub_UE[CC_id][j]; + UE_info->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j]; } } else { nb_rb_temp = nb_rb; @@ -1881,10 +1843,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, while ((nb_rb_temp > 0) && (j < N_RBG[CC_id])) { if (ue_sched_ctl->rballoc_sub_UE[CC_id][j] == 1) { - UE_list-> - UE_template[CC_id] - [UE_id].rballoc_subband[harq_pid][j] = - ue_sched_ctl->rballoc_sub_UE[CC_id][j]; + UE_info->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j]; if ((j == N_RBG[CC_id] - 1) && ((N_RB_DL[CC_id] == 25) || @@ -1963,7 +1922,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, } #endif - offset = generate_dlsch_header((unsigned char *) UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], num_sdus, //num_sdus + offset = generate_dlsch_header((unsigned char *) UE_info->DLSCH_pdu[CC_id][0][UE_id].payload[0], num_sdus, //num_sdus sdu_lengths, // sdu_lcids, 255, // no drx ta_update, // timing advance @@ -1992,20 +1951,20 @@ schedule_ue_spec_fairRR(module_id_t module_idP, LOG_T(MAC, "\n"); #endif // cycle through SDUs and place in dlsch_buffer - memcpy(&UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset],dlsch_buffer,sdu_length_total); + memcpy(&UE_info->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset],dlsch_buffer,sdu_length_total); // memcpy(RC.mac[0].DLSCH_pdu[0][0].payload[0][offset],dcch_buffer,sdu_lengths[0]); // fill remainder of DLSCH with random data for (j=0; j<(TBS-sdu_length_total-offset); j++) { - UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset+sdu_length_total+j] = (char)(taus()&0xff); + UE_info->DLSCH_pdu[CC_id][0][UE_id].payload[0][offset+sdu_length_total+j] = (char)(taus()&0xff); } - trace_pdu(DIRECTION_DOWNLINK, (uint8_t *)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], + trace_pdu(DIRECTION_DOWNLINK, (uint8_t *)UE_info->DLSCH_pdu[CC_id][0][UE_id].payload[0], TBS, module_idP, WS_RA_RNTI, UE_RNTI(module_idP, UE_id), eNB->frame, eNB->subframe,0,0); T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP), - T_INT(harq_pid), T_BUFFER(UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], TBS)); - UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid] = nb_rb; + T_INT(harq_pid), T_BUFFER(UE_info->DLSCH_pdu[CC_id][0][UE_id].payload[0], TBS)); + UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid] = nb_rb; add_ue_dlsch_info(module_idP, CC_id, UE_id, @@ -2015,37 +1974,37 @@ schedule_ue_spec_fairRR(module_id_t module_idP, // store stats eNB->eNB_stats[CC_id].dlsch_bytes_tx+=sdu_length_total; eNB->eNB_stats[CC_id].dlsch_pdus_tx+=1; - UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used = nb_rb; - UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used += nb_rb; - UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1=eNB_UE_stats->dlsch_mcs1; - UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2=mcs; - UE_list->eNB_UE_stats[CC_id][UE_id].TBS = TBS; - UE_list->eNB_UE_stats[CC_id][UE_id].overhead_bytes= TBS- sdu_length_total; - UE_list->eNB_UE_stats[CC_id][UE_id].total_sdu_bytes+= sdu_length_total; - UE_list->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes+= TBS; - UE_list->eNB_UE_stats[CC_id][UE_id].total_num_pdus+=1; + UE_info->eNB_UE_stats[CC_id][UE_id].rbs_used = nb_rb; + UE_info->eNB_UE_stats[CC_id][UE_id].total_rbs_used += nb_rb; + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1=eNB_UE_stats->dlsch_mcs1; + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2=mcs; + UE_info->eNB_UE_stats[CC_id][UE_id].TBS = TBS; + UE_info->eNB_UE_stats[CC_id][UE_id].overhead_bytes= TBS- sdu_length_total; + UE_info->eNB_UE_stats[CC_id][UE_id].total_sdu_bytes+= sdu_length_total; + UE_info->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes+= TBS; + UE_info->eNB_UE_stats[CC_id][UE_id].total_num_pdus+=1; if (cc[CC_id].tdd_Config != NULL) { // TDD - UE_list->UE_template[CC_id][UE_id].DAI++; - update_ul_dci(module_idP,CC_id,rnti,UE_list->UE_template[CC_id][UE_id].DAI,subframeP); + UE_info->UE_template[CC_id][UE_id].DAI++; + update_ul_dci(module_idP,CC_id,rnti,UE_info->UE_template[CC_id][UE_id].DAI,subframeP); } // do PUCCH power control // this is the snr - eNB_UE_stats = &UE_list->eNB_UE_stats[CC_id][UE_id]; + eNB_UE_stats = &UE_info->eNB_UE_stats[CC_id][UE_id]; /* Unit is not dBm, it's special from nfapi */ snr = (5 * ue_sched_ctl->pucch1_snr[CC_id] - 640) / 10; target_snr = eNB->puCch10xSnr / 10; // this assumes accumulated tpc // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out - int32_t framex10psubframe = UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_frame*10+UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe; + int32_t framex10psubframe = UE_info->UE_template[CC_id][UE_id].pucch_tpc_tx_frame*10+UE_info->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe; if (((framex10psubframe+10)<=(frameP*10+subframeP)) || //normal case ((framex10psubframe>(frameP*10+subframeP)) && (((10240-framex10psubframe+frameP*10+subframeP)>=10)))) //frame wrap-around if (ue_sched_ctl->pucch1_cqi_update[CC_id] == 1) { ue_sched_ctl->pucch1_cqi_update[CC_id] = 0; - UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_frame=frameP; - UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe=subframeP; + UE_info->UE_template[CC_id][UE_id].pucch_tpc_tx_frame=frameP; + UE_info->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe=subframeP; if (snr > target_snr + 4) { tpc = 0; //-1 @@ -2080,7 +2039,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = harq_pid; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = tpc; // dont adjust power when retransmitting - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 1-UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = 1-UE_info->UE_template[CC_id][UE_id].oldNDI[harq_pid]; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = mcs; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = 0; //deactivate second codeword @@ -2088,10 +2047,10 @@ schedule_ue_spec_fairRR(module_id_t module_idP, dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_2 = 1; if (cc[CC_id].tdd_Config != NULL) { //TDD - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.downlink_assignment_index = (UE_list->UE_template[CC_id][UE_id].DAI-1)&3; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.downlink_assignment_index = (UE_info->UE_template[CC_id][UE_id].DAI-1)&3; LOG_D(MAC,"[eNB %d] Initial transmission CC_id %d : harq_pid %d, dai %d, mcs %d\n", module_idP,CC_id,harq_pid, - (UE_list->UE_template[CC_id][UE_id].DAI-1), + (UE_info->UE_template[CC_id][UE_id].DAI-1), mcs); } else { LOG_D(MAC,"[eNB %d] Initial transmission CC_id %d : harq_pid %d, mcs %d\n", @@ -2110,12 +2069,12 @@ schedule_ue_spec_fairRR(module_id_t module_idP, // Toggle NDI for next time LOG_D(MAC,"CC_id %d Frame %d, subframeP %d: Toggling Format1 NDI for UE %d (rnti %x/%d) oldNDI %d\n", CC_id, frameP,subframeP,UE_id, - rnti,harq_pid,UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]); - UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]=1-UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]; - UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid] = mcs; - UE_list->UE_template[CC_id][UE_id].oldmcs2[harq_pid] = 0; - AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated!=NULL,"physicalConfigDedicated is NULL\n"); - AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated!=NULL,"physicalConfigDedicated->pdsch_ConfigDedicated is NULL\n"); + rnti,harq_pid,UE_info->UE_template[CC_id][UE_id].oldNDI[harq_pid]); + UE_info->UE_template[CC_id][UE_id].oldNDI[harq_pid]=1-UE_info->UE_template[CC_id][UE_id].oldNDI[harq_pid]; + UE_info->UE_template[CC_id][UE_id].oldmcs1[harq_pid] = mcs; + UE_info->UE_template[CC_id][UE_id].oldmcs2[harq_pid] = 0; + AssertFatal(UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated!=NULL,"physicalConfigDedicated is NULL\n"); + AssertFatal(UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated!=NULL,"physicalConfigDedicated->pdsch_ConfigDedicated is NULL\n"); fill_nfapi_dlsch_config(eNB,dl_req, TBS, eNB->pdu_index[CC_id], @@ -2132,7 +2091,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, 1, // number of subbands // uint8_t codebook_index, 4, // UE category capacity - UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated->p_a, + UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated->p_a, 0, // delta_power_offset for TM5 0, // ngap 0, // nprb @@ -2144,7 +2103,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, (frameP*10)+subframeP, TBS, eNB->pdu_index[CC_id], - eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0]); + eNB->UE_info.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0]); LOG_D(MAC,"Filled NFAPI configuration for DCI/DLSCH/TXREQ %d, new SDU\n",eNB->pdu_index[CC_id]); eNB->pdu_index[CC_id]++; program_dlsch_acknak(module_idP,CC_id,UE_id,frameP,subframeP,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx); @@ -2189,7 +2148,7 @@ fill_DLSCH_dci_fairRR( int i; int CC_id; eNB_MAC_INST *eNB =RC.mac[module_idP]; - UE_list_t *UE_list = &eNB->UE_list; + UE_info_t *UE_info = &eNB->UE_info; int N_RBG; int N_RB_DL; COMMON_channels_t *cc; @@ -2225,11 +2184,11 @@ fill_DLSCH_dci_fairRR( eNB_dlsch_info[module_idP][CC_id][UE_id].status = S_DL_WAITING; rnti = UE_RNTI(module_idP,UE_id); harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP,subframeP); - nb_rb = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid]; + nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid]; /// Synchronizing rballoc with rballoc_sub for(i=0; iUE_template[CC_id][UE_id].rballoc_subband[harq_pid][i]; + rballoc_sub[i] = UE_info->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][i]; } nfapi_dl_config_request_t *DL_req = &RC.mac[module_idP]->DL_req[0]; @@ -2283,7 +2242,7 @@ void ulsch_scheduler_pre_ue_select_fairRR( 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; + UE_info_t *UE_info= &eNB->UE_info; uint8_t aggregation; int format_flag; nfapi_hi_dci0_request_body_t *HI_DCI0_req; @@ -2302,7 +2261,7 @@ void ulsch_scheduler_pre_ue_select_fairRR( // UE round >0 for ( UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++ ) { - if (UE_list->active[UE_id] == FALSE) + if (UE_info->active[UE_id] == FALSE) continue; rnti = UE_RNTI(module_idP,UE_id); @@ -2312,10 +2271,10 @@ void ulsch_scheduler_pre_ue_select_fairRR( CC_id = UE_PCCID(module_idP,UE_id); - if (UE_list->UE_template[CC_id][UE_id].configured == FALSE) + if (UE_info->UE_template[CC_id][UE_id].configured == FALSE) continue; - if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) + if (UE_info->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; // UL DCI @@ -2339,12 +2298,12 @@ void ulsch_scheduler_pre_ue_select_fairRR( //harq_pid harq_pid = subframe2harqpid(cc,(frameP+(sched_subframePUE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid]; + round = UE_info->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid]; if ( round > 0 ) { hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi]; format_flag = 2; - aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id],format0); + aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id],format0); if (CCE_allocation_infeasible(module_idP,CC_id,format_flag,subframeP,aggregation,rnti) == 1) { cc_id_flag[CC_id] = 1; @@ -2355,8 +2314,8 @@ void ulsch_scheduler_pre_ue_select_fairRR( hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation; HI_DCI0_req->number_of_dci++; ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ue_priority = SCH_UL_RETRANS; - ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].start_rb = eNB->UE_list.UE_template[CC_id][UE_id].first_rb_ul[harq_pid]; - ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].nb_rb = eNB->UE_list.UE_template[CC_id][UE_id].nb_rb_ul[harq_pid]; + ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].start_rb = eNB->UE_info.UE_template[CC_id][UE_id].first_rb_ul[harq_pid]; + ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].nb_rb = eNB->UE_info.UE_template[CC_id][UE_id].nb_rb_ul[harq_pid]; ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].UE_id = UE_id; ulsch_ue_select[CC_id].ue_num++; continue; @@ -2364,7 +2323,7 @@ void ulsch_scheduler_pre_ue_select_fairRR( } // - int bytes_to_schedule = UE_list->UE_template[CC_id][UE_id].estimated_ul_buffer - UE_list->UE_template[CC_id][UE_id].scheduled_ul_bytes; + int bytes_to_schedule = UE_info->UE_template[CC_id][UE_id].estimated_ul_buffer - UE_info->UE_template[CC_id][UE_id].scheduled_ul_bytes; if (bytes_to_schedule < 0) bytes_to_schedule = 0; @@ -2376,14 +2335,14 @@ void ulsch_scheduler_pre_ue_select_fairRR( continue; } - if ( UE_list->UE_template[CC_id][UE_id].ul_SR > 0 ) { + if ( UE_info->UE_template[CC_id][UE_id].ul_SR > 0 ) { first_ue_id[CC_id][ue_first_num[CC_id]]= UE_id; first_ue_total[CC_id] [ue_first_num[CC_id]] = 0; ue_first_num[CC_id]++; continue; } - UE_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + UE_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; rrc_status = mac_eNB_get_rrc_status(module_idP, rnti); if ( ((UE_sched_ctl->ul_inactivity_timer>20)&&(UE_sched_ctl->ul_scheduled==0)) || @@ -2396,7 +2355,7 @@ void ulsch_scheduler_pre_ue_select_fairRR( } /*if ( (ulsch_ue_select[CC_id].ue_num+ul_inactivity_num[CC_id] ) < ulsch_ue_max_num[CC_id] ) { - UE_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + UE_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; uint8_t ul_period = 0; if (cc->tdd_Config) { ul_period = 50; @@ -2426,7 +2385,7 @@ void ulsch_scheduler_pre_ue_select_fairRR( hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi]; format_flag = 2; rnti = UE_RNTI(module_idP,first_ue_id[CC_id][temp]); - aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_list->UE_sched_ctrl[first_ue_id[CC_id][temp]].dl_cqi[CC_id],format0); + aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_info->UE_sched_ctrl[first_ue_id[CC_id][temp]].dl_cqi[CC_id],format0); if (CCE_allocation_infeasible(module_idP,CC_id,format_flag,subframeP,aggregation,rnti) == 1) { cc_id_flag[CC_id] = 1; @@ -2445,7 +2404,7 @@ void ulsch_scheduler_pre_ue_select_fairRR( } for ( UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++ ) { - if (UE_list->active[UE_id] == FALSE) + if (UE_info->active[UE_id] == FALSE) continue; rnti = UE_RNTI(module_idP,UE_id); @@ -2458,10 +2417,10 @@ void ulsch_scheduler_pre_ue_select_fairRR( if (UE_id > last_ulsch_ue_id[CC_id]) continue; - if (UE_list->UE_template[CC_id][UE_id].configured == FALSE) + if (UE_info->UE_template[CC_id][UE_id].configured == FALSE) continue; - if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) + if (UE_info->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; if ( (ulsch_ue_select[CC_id].ue_num >= ulsch_ue_max_num[CC_id]) || (cc_id_flag[CC_id] == 1) ) { @@ -2489,19 +2448,19 @@ void ulsch_scheduler_pre_ue_select_fairRR( HI_DCI0_req = &eNB->HI_DCI0_req[CC_id][subframeP].hi_dci0_request_body; //SR BSR - UE_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - int bytes_to_schedule = UE_list->UE_template[CC_id][UE_id].estimated_ul_buffer - UE_list->UE_template[CC_id][UE_id].scheduled_ul_bytes; + UE_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; + int bytes_to_schedule = UE_info->UE_template[CC_id][UE_id].estimated_ul_buffer - UE_info->UE_template[CC_id][UE_id].scheduled_ul_bytes; if (bytes_to_schedule < 0) bytes_to_schedule = 0; rrc_status = mac_eNB_get_rrc_status(module_idP, rnti); - if ( (bytes_to_schedule > 0) || (UE_list->UE_template[CC_id][UE_id].ul_SR > 0) || + if ( (bytes_to_schedule > 0) || (UE_info->UE_template[CC_id][UE_id].ul_SR > 0) || ((UE_sched_ctl->ul_inactivity_timer>20)&&(UE_sched_ctl->ul_scheduled==0)) || ((UE_sched_ctl->ul_inactivity_timer>10)&&(UE_sched_ctl->ul_scheduled==0)&&(rrc_status < RRC_CONNECTED)) || ((UE_sched_ctl->cqi_req_timer>300)&&((rrc_status >= RRC_CONNECTED))) ) { hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi]; format_flag = 2; - aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id],format0); + aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id],format0); if (CCE_allocation_infeasible(module_idP,CC_id,format_flag,subframeP,aggregation,rnti) == 1) { cc_id_flag[CC_id] = 1; @@ -2515,7 +2474,7 @@ void ulsch_scheduler_pre_ue_select_fairRR( if(bytes_to_schedule > 0) ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ul_total_buffer = bytes_to_schedule; - else if(UE_list->UE_template[CC_id][UE_id].ul_SR > 0) + else if(UE_info->UE_template[CC_id][UE_id].ul_SR > 0) ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].ul_total_buffer = 0; ulsch_ue_select[CC_id].list[ulsch_ue_select[CC_id].ue_num].UE_id = UE_id; @@ -2526,7 +2485,7 @@ void ulsch_scheduler_pre_ue_select_fairRR( //inactivity UE /* if ( (ulsch_ue_select[CC_id].ue_num+ul_inactivity_num[CC_id]) < ulsch_ue_max_num[CC_id] ) { - UE_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + UE_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; uint8_t ul_period = 0; if (cc->tdd_Config) { ul_period = 50; @@ -2555,7 +2514,7 @@ void ulsch_scheduler_pre_ue_select_fairRR( hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi]; format_flag = 2; rnti = UE_RNTI(module_idP,ul_inactivity_id[CC_id][temp]); - aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_list->UE_sched_ctrl[ul_inactivity_id[CC_id][temp]].dl_cqi[CC_id],format0); + aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_info->UE_sched_ctrl[ul_inactivity_id[CC_id][temp]].dl_cqi[CC_id],format0); if (CCE_allocation_infeasible(module_idP,CC_id,format_flag,subframeP,aggregation,rnti) == 1) { cc_id_flag[CC_id] = 1; @@ -2597,7 +2556,7 @@ void ulsch_scheduler_pre_processor_fairRR(module_id_t module_idP, ULSCH_UE_SELECT ulsch_ue_select[MAX_NUM_CCs]) { int CC_id,ulsch_ue_num; eNB_MAC_INST *eNB = RC.mac[module_idP]; - UE_list_t *UE_list= &eNB->UE_list; + UE_info_t *UE_info= &eNB->UE_info; UE_TEMPLATE *UE_template = NULL; LTE_DL_FRAME_PARMS *frame_parms = NULL; uint8_t ue_num_temp; @@ -2696,9 +2655,9 @@ void ulsch_scheduler_pre_processor_fairRR(module_id_t module_idP, } } } else { - UE_template = &UE_list->UE_template[CC_id][UE_id]; + UE_template = &UE_info->UE_template[CC_id][UE_id]; - if ( UE_list->UE_sched_ctrl[UE_id].phr_received == 1 ) { + if ( UE_info->UE_sched_ctrl[UE_id].phr_received == 1 ) { mcs = 20; } else { mcs = 10; @@ -2734,9 +2693,9 @@ void ulsch_scheduler_pre_processor_fairRR(module_id_t module_idP, if ( rb_table[rb_table_index] <= average_rbs ) { // assigne RBS( nb_rb) first_rb[CC_id] = first_rb[CC_id] + rb_table[rb_table_index]; - UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[0] = rb_table[rb_table_index]; - UE_list->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = rb_table_index; - UE_list->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = mcs; + UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[0] = rb_table[rb_table_index]; + UE_info->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = rb_table_index; + UE_info->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = mcs; } if ( rb_table[rb_table_index] > average_rbs ) { @@ -2750,31 +2709,31 @@ void ulsch_scheduler_pre_processor_fairRR(module_id_t module_idP, } first_rb[CC_id] = first_rb[CC_id] + rb_table[rb_table_index]; - UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[0] = rb_table[rb_table_index]; - UE_list->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = rb_table_index; - UE_list->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = mcs; + UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[0] = rb_table[rb_table_index]; + UE_info->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = rb_table_index; + UE_info->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = mcs; } } else { if (mac_eNB_get_rrc_status(module_idP,UE_RNTI(module_idP, UE_id)) < RRC_CONNECTED) { // assigne RBS( 6 RBs) first_rb[CC_id] = first_rb[CC_id] + 6; - UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[0] = 6; - UE_list->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = 5; - UE_list->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = 10; + UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[0] = 6; + UE_info->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = 5; + UE_info->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = 10; } else { // assigne RBS( 3 RBs) first_rb[CC_id] = first_rb[CC_id] + 3; - UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[0] = 3; - UE_list->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = 2; - UE_list->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = 10; + UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[0] = 3; + UE_info->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = 2; + UE_info->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = 10; } } } else if ( ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_INACTIVE ) { // assigne RBS( 3 RBs) first_rb[CC_id] = first_rb[CC_id] + 3; - UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[0] = 3; - UE_list->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = 2; - UE_list->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = 10; + UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[0] = 3; + UE_info->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = 2; + UE_info->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = 10; } } @@ -2954,7 +2913,7 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP, int N_RB_UL; eNB_MAC_INST *eNB = RC.mac[module_idP]; COMMON_channels_t *cc; - UE_list_t *UE_list=&eNB->UE_list; + UE_info_t *UE_info=&eNB->UE_info; UE_TEMPLATE *UE_template; UE_sched_ctrl_t *UE_sched_ctrl; int sched_frame=frameP; @@ -3063,8 +3022,8 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP, continue; } - UE_template = &UE_list->UE_template[CC_id][UE_id]; - UE_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id]; + UE_template = &UE_info->UE_template[CC_id][UE_id]; + UE_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; harq_pid = subframe2harqpid(cc,sched_frame,sched_subframeP); rnti = UE_RNTI(CC_id,UE_id); aggregation=get_aggregation(get_bw_index(module_idP,CC_id),UE_sched_ctrl[UE_id].dl_cqi[CC_id],format0); @@ -3157,9 +3116,9 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP, UE_sched_ctrl->cqi_req_timer); ndi = 1-UE_template->oldNDI_UL[harq_pid]; UE_template->oldNDI_UL[harq_pid]=ndi; - UE_list->eNB_UE_stats[CC_id][UE_id].snr = snr; - UE_list->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr; - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1=UE_template->pre_assigned_mcs_ul; + UE_info->eNB_UE_stats[CC_id][UE_id].snr = snr; + UE_info->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1=UE_template->pre_assigned_mcs_ul; UE_template->mcs_UL[harq_pid] = UE_template->pre_assigned_mcs_ul;//cmin (UE_template->pre_assigned_mcs_ul, openair_daq_vars.target_ue_ul_mcs); // adjust, based on user-defined MCS if (UE_template->pre_allocated_rb_table_index_ul >=0) { @@ -3169,10 +3128,10 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP, rb_table_index=5; // for PHR } - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2=UE_template->mcs_UL[harq_pid]; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2=UE_template->mcs_UL[harq_pid]; UE_template->TBS_UL[harq_pid] = get_TBS_UL(UE_template->mcs_UL[harq_pid],rb_table[rb_table_index]); - UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx+=rb_table[rb_table_index]; - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS=UE_template->TBS_UL[harq_pid]; + UE_info->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx+=rb_table[rb_table_index]; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_TBS=UE_template->TBS_UL[harq_pid]; T(T_ENB_MAC_UE_UL_SCHEDULE, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP), T_INT(harq_pid), T_INT(UE_template->mcs_UL[harq_pid]), T_INT(first_rb[CC_id]), T_INT(rb_table[rb_table_index]), T_INT(UE_template->TBS_UL[harq_pid]), T_INT(ndi)); @@ -3190,7 +3149,7 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP, UE_template->cqi_req[harq_pid] = cqi_req; UE_sched_ctrl->ul_scheduled |= (1<head) + if (UE_id == UE_info->list.head) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_SCHEDULED,UE_sched_ctrl->ul_scheduled); // adjust total UL buffer status by TBS, wait for UL sdus to do final update @@ -3332,8 +3291,8 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP, T(T_ENB_MAC_UE_UL_SCHEDULE_RETRANSMISSION, T_INT(module_idP), T_INT(CC_id), T_INT(rnti), T_INT(frameP), T_INT(subframeP), T_INT(harq_pid), T_INT(UE_template->mcs_UL[harq_pid]), T_INT(ulsch_ue_select[CC_id].list[ulsch_ue_num].start_rb), T_INT(ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb), T_INT(round)); - UE_list->eNB_UE_stats[CC_id][UE_id].snr = snr; - UE_list->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr; + UE_info->eNB_UE_stats[CC_id][UE_id].snr = snr; + UE_info->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr; uint8_t mcs_rv = 0; if(rvidx_tab[round&3]==1) { @@ -3345,7 +3304,7 @@ void schedule_ulsch_rnti_fairRR(module_id_t module_idP, } UE_template->TBS_UL[harq_pid] = get_TBS_UL(UE_template->mcs_UL[harq_pid],ulsch_ue_select[CC_id].list[ulsch_ue_num].nb_rb); - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS=UE_template->TBS_UL[harq_pid]; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_TBS=UE_template->TBS_UL[harq_pid]; if (mac_eNB_get_rrc_status(module_idP,rnti) < RRC_CONNECTED) LOG_D(MAC,"[eNB %d][PUSCH %d/%x] CC_id %d Frame %d subframeP %d Scheduled UE %d (mcs %d, first rb %d, nb_rb %d, TBS %d, harq_pid %d)\n", diff --git a/openair2/LAYER2/MAC/eNB_scheduler_phytest.c b/openair2/LAYER2/MAC/eNB_scheduler_phytest.c index 647db3f624..776f2994cf 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_phytest.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_phytest.c @@ -133,13 +133,13 @@ schedule_ue_spec_phy_test( /* LOG_D(MAC,"CC_id %d Frame %d, subframeP %d: Toggling Format1 NDI for UE %d (rnti %x/%d) oldNDI %d\n", CC_id, frameP,subframeP,UE_id, - rnti,harq_pid,UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]); + rnti,harq_pid,UE_info->UE_template[CC_id][UE_id].oldNDI[harq_pid]); - UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]=1-UE_list->UE_template[CC_id][UE_id].oldNDI[harq_pid]; - UE_list->UE_template[CC_id][UE_id].oldmcs1[harq_pid] = mcs; - UE_list->UE_template[CC_id][UE_id].oldmcs2[harq_pid] = 0; - AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated!=NULL,"physicalConfigDedicated is NULL\n"); - AssertFatal(UE_list->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated!=NULL,"physicalConfigDedicated->pdsch_ConfigDedicated is NULL\n"); + UE_info->UE_template[CC_id][UE_id].oldNDI[harq_pid]=1-UE_info->UE_template[CC_id][UE_id].oldNDI[harq_pid]; + UE_info->UE_template[CC_id][UE_id].oldmcs1[harq_pid] = mcs; + UE_info->UE_template[CC_id][UE_id].oldmcs2[harq_pid] = 0; + AssertFatal(UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated!=NULL,"physicalConfigDedicated is NULL\n"); + AssertFatal(UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated!=NULL,"physicalConfigDedicated->pdsch_ConfigDedicated is NULL\n"); */ fill_nfapi_dlsch_config(eNB, dl_req, @@ -170,7 +170,7 @@ schedule_ue_spec_phy_test( (frameP*10)+subframeP, TBS, eNB->pdu_index[CC_id], - eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0]); + eNB->UE_info.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0]); } else { LOG_W(MAC,"[eNB_scheduler_phytest] DCI allocation infeasible!\n"); } @@ -192,7 +192,7 @@ void schedule_ulsch_phy_test(module_id_t module_idP,frame_t frameP,sub_frame_t s int N_RB_UL; eNB_MAC_INST *mac = RC.mac[module_idP]; COMMON_channels_t *cc = &mac->common_channels[0]; - UE_list_t *UE_list=&mac->UE_list; + UE_info_t *UE_info=&mac->UE_info; UE_TEMPLATE *UE_template; UE_sched_ctrl_t *UE_sched_ctrl; int sched_frame=frameP; @@ -231,8 +231,8 @@ void schedule_ulsch_phy_test(module_id_t module_idP,frame_t frameP,sub_frame_t s first_rb[CC_id] = 1; // loop over all active UEs // if (eNB_UE_stats->mode == PUSCH) { // ue has a ulsch channel - UE_template = &UE_list->UE_template[CC_id][UE_id]; - UE_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id]; + UE_template = &UE_info->UE_template[CC_id][UE_id]; + UE_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; harq_pid = subframe2harqpid(&cc[CC_id],sched_frame,sched_subframe); RC.eNB[module_idP][CC_id]->pusch_stats_BO[UE_id][(frameP*10)+subframeP] = UE_template->TBS_UL[harq_pid]; //power control @@ -242,15 +242,15 @@ void schedule_ulsch_phy_test(module_id_t module_idP,frame_t frameP,sub_frame_t s // new transmission ndi = 1-UE_template->oldNDI_UL[harq_pid]; UE_template->oldNDI_UL[harq_pid]=ndi; - UE_list->eNB_UE_stats[CC_id][UE_id].snr = snr; - UE_list->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr; - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1 = mcs; + UE_info->eNB_UE_stats[CC_id][UE_id].snr = snr; + UE_info->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1 = mcs; UE_template->mcs_UL[harq_pid] = mcs;//cmin (UE_template->pre_assigned_mcs_ul, openair_daq_vars.target_ue_ul_mcs); // adjust, based on user-defined MCS - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2 = mcs; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2 = mcs; // buffer_occupancy = UE_template->ul_total_buffer; UE_template->TBS_UL[harq_pid] = get_TBS_UL(mcs,nb_rb); - UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx += nb_rb; - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS = get_TBS_UL(mcs,nb_rb); + UE_info->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx += nb_rb; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_TBS = get_TBS_UL(mcs,nb_rb); // buffer_occupancy -= TBS; // bad indices : 20 (40 PRB), 21 (45 PRB), 22 (48 PRB) //store for possible retransmission diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index abb053b52e..858be832fc 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -1169,14 +1169,14 @@ program_dlsch_acknak(module_id_t module_idP, { eNB_MAC_INST *eNB = RC.mac[module_idP]; COMMON_channels_t *cc = eNB->common_channels; - UE_list_t *UE_list = &eNB->UE_list; + UE_info_t *UE_info = &eNB->UE_info; rnti_t rnti = UE_RNTI(module_idP, UE_idP); nfapi_ul_config_request_body_t *ul_req; nfapi_ul_config_request_pdu_t *ul_config_pdu; int use_simultaneous_pucch_pusch = 0; nfapi_ul_config_ulsch_harq_information *ulsch_harq_information = NULL; nfapi_ul_config_harq_information *harq_information = NULL; - struct LTE_PhysicalConfigDedicated__ext2 *ext2 = UE_list->UE_template[CC_idP][UE_idP].physicalConfigDedicated->ext2; + struct LTE_PhysicalConfigDedicated__ext2 *ext2 = UE_info->UE_template[CC_idP][UE_idP].physicalConfigDedicated->ext2; if (ext2 && ext2->pucch_ConfigDedicated_v1020 && @@ -1363,12 +1363,12 @@ fill_nfapi_ulsch_harq_information(module_id_t module_ { eNB_MAC_INST *eNB = RC.mac[module_idP]; COMMON_channels_t *cc = &eNB->common_channels[CC_idP]; - UE_list_t *UE_list = &eNB->UE_list; + UE_info_t *UE_info = &eNB->UE_info; int UE_id = find_UE_id(module_idP, rntiP); nfapi_ul_config_ulsch_harq_information_rel10_t *harq_information_rel10 = &harq_information->harq_information_rel10; AssertFatal(UE_id >= 0, "UE_id cannot be found, impossible\n"); - AssertFatal(UE_list != NULL, "UE_list is null\n"); - LTE_PhysicalConfigDedicated_t *physicalConfigDedicated = UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated; + AssertFatal(UE_info != NULL, "UE_info is null\n"); + LTE_PhysicalConfigDedicated_t *physicalConfigDedicated = UE_info->UE_template[CC_idP][UE_id].physicalConfigDedicated; AssertFatal(physicalConfigDedicated != NULL, "physicalConfigDedicated for rnti %x is null\n", rntiP); struct LTE_PUSCH_ConfigDedicated *puschConfigDedicated = physicalConfigDedicated->pusch_ConfigDedicated; @@ -1468,14 +1468,14 @@ fill_nfapi_harq_information(module_id_t module_idP, { eNB_MAC_INST *eNB = RC.mac[module_idP]; COMMON_channels_t *cc = &eNB->common_channels[CC_idP]; - UE_list_t *UE_list = &eNB->UE_list; + UE_info_t *UE_info = &eNB->UE_info; int UE_id = find_UE_id(module_idP, rntiP); AssertFatal(UE_id >= 0, "UE_id cannot be found, impossible\n"); - AssertFatal(UE_list != NULL, "UE_list is null\n"); + AssertFatal(UE_info != NULL, "UE_info is null\n"); harq_information->harq_information_rel11.tl.tag = NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL11_TAG; harq_information->harq_information_rel11.num_ant_ports = 1; - LTE_PhysicalConfigDedicated_t *physicalConfigDedicated = UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated; + LTE_PhysicalConfigDedicated_t *physicalConfigDedicated = UE_info->UE_template[CC_idP][UE_id].physicalConfigDedicated; struct LTE_PUCCH_ConfigDedicated *pucch_ConfigDedicated = NULL; if (physicalConfigDedicated != NULL) pucch_ConfigDedicated = physicalConfigDedicated->pucch_ConfigDedicated; @@ -1489,7 +1489,7 @@ fill_nfapi_harq_information(module_id_t module_idP, case 6: case 7: if (cc->tdd_Config != NULL) { - // AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->pucch_ConfigDedicated != NULL, + // AssertFatal(UE_info->UE_template[CC_idP][UE_id].physicalConfigDedicated->pucch_ConfigDedicated != NULL, // "pucch_ConfigDedicated is null for TDD!\n"); if (physicalConfigDedicated != NULL && pucch_ConfigDedicated != NULL && pucch_ConfigDedicated->tdd_AckNackFeedbackMode != NULL && @@ -1879,8 +1879,7 @@ mpdcch_sf_condition(eNB_MAC_INST *eNB, break; case TYPEUESPEC: - epdcch_setconfig_r11 = - eNB->UE_list.UE_template[CC_id][UE_id].physicalConfigDedicated->ext4->epdcch_Config_r11->config_r11.choice.setup.setConfigToAddModList_r11->list.array[0]; + epdcch_setconfig_r11 = eNB->UE_info.UE_template[CC_id][UE_id].physicalConfigDedicated->ext4->epdcch_Config_r11->config_r11.choice.setup.setConfigToAddModList_r11->list.array[0]; AssertFatal(epdcch_setconfig_r11 != NULL, " epdcch_setconfig_r11 is null for UE specific \n"); AssertFatal(epdcch_setconfig_r11->ext2 != NULL, " ext2 doesn't exist in epdcch config ' \n"); @@ -1988,11 +1987,11 @@ find_UE_id(module_id_t mod_idP, //------------------------------------------------------------------------------ { int UE_id; - UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; + UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info; for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) { - if (UE_list->active[UE_id] == TRUE) { - if (UE_list->UE_template[UE_PCCID(mod_idP, UE_id)][UE_id].rnti == rntiP) { + if (UE_info->active[UE_id] == TRUE) { + if (UE_info->UE_template[UE_PCCID(mod_idP, UE_id)][UE_id].rnti == rntiP) { return UE_id; } } @@ -2027,7 +2026,7 @@ find_RA_id(module_id_t mod_idP, //------------------------------------------------------------------------------ int -UE_num_active_CC(UE_list_t *listP, +UE_num_active_CC(UE_info_t *listP, int ue_idP) //------------------------------------------------------------------------------ { @@ -2040,7 +2039,7 @@ UE_PCCID(module_id_t mod_idP, int ue_idP) //------------------------------------------------------------------------------ { - return (RC.mac[mod_idP]->UE_list.pCC_id[ue_idP]); + return (RC.mac[mod_idP]->UE_info.pCC_id[ue_idP]); } //------------------------------------------------------------------------------ @@ -2051,7 +2050,7 @@ UE_RNTI(module_id_t mod_idP, { if (!RC.mac || !RC.mac[mod_idP]) return 0; - rnti_t rnti = RC.mac[mod_idP]->UE_list.UE_template[UE_PCCID(mod_idP, + rnti_t rnti = RC.mac[mod_idP]->UE_info.UE_template[UE_PCCID(mod_idP, ue_idP)][ue_idP].rnti; if (rnti > 0) { @@ -2069,7 +2068,7 @@ is_UE_active(module_id_t mod_idP, int ue_idP) //------------------------------------------------------------------------------ { - return (RC.mac[mod_idP]->UE_list.active[ue_idP]); + return (RC.mac[mod_idP]->UE_info.active[ue_idP]); } //------------------------------------------------------------------------------ @@ -2122,61 +2121,48 @@ get_aggregation(uint8_t bw_index, //------------------------------------------------------------------------------ /* - * Dump the UL or DL UE_list into LOG_T(MAC) + * Dump the UE_list into LOG_T(MAC) */ void -dump_ue_list(UE_list_t *listP, - int ul_flag) -//------------------------------------------------------------------------------ -{ - if (ul_flag == 0) { - for (int j = listP->head; j >= 0; j = listP->next[j]) { - LOG_T(MAC, "DL list node %d => %d\n", - j, - listP->next[j]); - } - } else { - for (int j = listP->head_ul; j >= 0; j = listP->next_ul[j]) { - LOG_T(MAC, "UL list node %d => %d\n", - j, - listP->next_ul[j]); - } - } - - return; +dump_ue_list(UE_list_t *listP) { + for (int j = listP->head; j >= 0; j = listP->next[j]) + LOG_T(MAC, "DL list node %d => %d\n", j, listP->next[j]); } //------------------------------------------------------------------------------ /* - * Add a UE to the UL or DL UE_list listP + * Add a UE to UE_list listP */ -void -add_ue_list(UE_list_t *listP, int UE_id, int ul_flag) { - if (ul_flag == 0) { - if (listP->head == -1) { - listP->head = UE_id; - listP->next[UE_id] = -1; - } else { - int i = listP->head; - while (listP->next[i] >= 0) - i = listP->next[i]; - listP->next[i] = UE_id; - listP->next[UE_id] = -1; - } +inline void add_ue_list(UE_list_t *listP, int UE_id) { + if (listP->head == -1) { + listP->head = UE_id; + listP->next[UE_id] = -1; } else { - if (listP->head_ul == -1) { - listP->head_ul = UE_id; - listP->next_ul[UE_id] = -1; - } else { - int i = listP->head; - while (listP->next_ul[i] >= 0) - i = listP->next[i]; - listP->next_ul[i] = UE_id; - listP->next_ul[UE_id] = -1; - } + int i = listP->head; + while (listP->next[i] >= 0) + i = listP->next[i]; + listP->next[i] = UE_id; + listP->next[UE_id] = -1; } } +//------------------------------------------------------------------------------ +/* + * Remove a UE from the UE_list listP, return the previous element + */ +inline int remove_ue_list(UE_list_t *listP, int UE_id) { + listP->next[UE_id] = -1; + if (listP->head == UE_id) { + listP->head = listP->next[UE_id]; + return -1; + } + + int previous = prev(listP, UE_id); + if (previous != -1) + listP->next[previous] = listP->next[UE_id]; + return previous; +} + //------------------------------------------------------------------------------ int add_new_ue(module_id_t mod_idP, @@ -2189,52 +2175,49 @@ add_new_ue(module_id_t mod_idP, { int UE_id; int i, j; - UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; - LOG_D(MAC, "[eNB %d, CC_id %d] Adding UE with rnti %x (next avail %d, num_UEs %d)\n", + UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info; + LOG_D(MAC, "[eNB %d, CC_id %d] Adding UE with rnti %x (prev. num_UEs %d)\n", mod_idP, cc_idP, rntiP, - UE_list->avail, - UE_list->num_UEs); + UE_info->num_UEs); for (i = 0; i < MAX_MOBILES_PER_ENB; i++) { - if (UE_list->active[i] == TRUE) + if (UE_info->active[i] == TRUE) continue; UE_id = i; - memset(&UE_list->UE_template[cc_idP][UE_id], 0, sizeof(UE_TEMPLATE)); - UE_list->UE_template[cc_idP][UE_id].rnti = rntiP; - UE_list->UE_template[cc_idP][UE_id].configured = FALSE; - UE_list->numactiveCCs[UE_id] = 1; - UE_list->numactiveULCCs[UE_id] = 1; - UE_list->pCC_id[UE_id] = cc_idP; - UE_list->ordered_CCids[0][UE_id] = cc_idP; - UE_list->ordered_ULCCids[0][UE_id] = cc_idP; - UE_list->num_UEs++; - UE_list->active[UE_id] = TRUE; - add_ue_list(UE_list, UE_id, 0); - dump_ue_list(UE_list, 0); - add_ue_list(UE_list, UE_id, 1); - dump_ue_list(UE_list, 1); + memset(&UE_info->UE_template[cc_idP][UE_id], 0, sizeof(UE_TEMPLATE)); + UE_info->UE_template[cc_idP][UE_id].rnti = rntiP; + UE_info->UE_template[cc_idP][UE_id].configured = FALSE; + UE_info->numactiveCCs[UE_id] = 1; + UE_info->numactiveULCCs[UE_id] = 1; + UE_info->pCC_id[UE_id] = cc_idP; + UE_info->ordered_CCids[0][UE_id] = cc_idP; + UE_info->ordered_ULCCids[0][UE_id] = cc_idP; + UE_info->num_UEs++; + UE_info->active[UE_id] = TRUE; + add_ue_list(&UE_info->list, UE_id); + dump_ue_list(&UE_info->list); if (IS_SOFTMODEM_IQPLAYER)// not specific to record/playback ? - UE_list->UE_template[cc_idP][UE_id].pre_assigned_mcs_ul = 0; - UE_list->UE_template[cc_idP][UE_id].rach_resource_type = rach_resource_type; - memset((void *) &UE_list->UE_sched_ctrl[UE_id], + UE_info->UE_template[cc_idP][UE_id].pre_assigned_mcs_ul = 0; + UE_info->UE_template[cc_idP][UE_id].rach_resource_type = rach_resource_type; + memset((void *) &UE_info->UE_sched_ctrl[UE_id], 0, sizeof(UE_sched_ctrl_t)); - memset((void *) &UE_list->eNB_UE_stats[cc_idP][UE_id], + memset((void *) &UE_info->eNB_UE_stats[cc_idP][UE_id], 0, sizeof(eNB_UE_STATS)); - UE_list->UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 0; + UE_info->UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 0; /* default slice in case there was something different */ - UE_list->assoc_ul_slice_idx[UE_id] = 0; - UE_list->UE_sched_ctrl[UE_id].ta_update = 31; + UE_info->assoc_ul_slice_idx[UE_id] = 0; + UE_info->UE_sched_ctrl[UE_id].ta_update = 31; for (j = 0; j < 8; j++) { - UE_list->UE_template[cc_idP][UE_id].oldNDI[j] = 0; - UE_list->UE_template[cc_idP][UE_id].oldNDI_UL[j] = 0; - UE_list->UE_sched_ctrl[UE_id].round[cc_idP][j] = 8; - UE_list->UE_sched_ctrl[UE_id].round_UL[cc_idP][j] = 0; + UE_info->UE_template[cc_idP][UE_id].oldNDI[j] = 0; + UE_info->UE_template[cc_idP][UE_id].oldNDI_UL[j] = 0; + UE_info->UE_sched_ctrl[UE_id].round[cc_idP][j] = 8; + UE_info->UE_sched_ctrl[UE_id].round_UL[cc_idP][j] = 0; } eNB_ulsch_info[mod_idP][cc_idP][UE_id].status = S_UL_WAITING; @@ -2247,10 +2230,8 @@ add_new_ue(module_id_t mod_idP, return (UE_id); } - // printf("MAC: cannot add new UE for rnti %x\n", rntiP); LOG_E(MAC, "error in add_new_ue(), could not find space in UE_list, Dumping UE list\n"); - dump_ue_list(UE_list, - 0); + dump_ue_list(&UE_info->list); return -1; } @@ -2263,7 +2244,7 @@ rrc_mac_remove_ue(module_id_t mod_idP, rnti_t rntiP) //------------------------------------------------------------------------------ { - UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; + UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info; int UE_id = find_UE_id(mod_idP, rntiP); eNB_UE_STATS *ue_stats = NULL; int pCC_id = -1; @@ -2279,38 +2260,14 @@ rrc_mac_remove_ue(module_id_t mod_idP, UE_id, pCC_id, rntiP); - UE_list->active[UE_id] = FALSE; - UE_list->num_UEs--; + UE_info->active[UE_id] = FALSE; + UE_info->num_UEs--; - UE_list->next[UE_id] = -1; - UE_list->next_ul[UE_id] = -1; - /* If present, remove UE from DL list */ - if (UE_list->head == UE_id) { - UE_list->head = UE_list->next[UE_id]; - } else { - int previous = prev(UE_list, UE_id, 0); - - if (previous != -1) { - UE_list->next[previous] = UE_list->next[UE_id]; - } - } - - /* If present, remove UE from UL list */ - if (UE_list->head_ul == UE_id) { - UE_list->head_ul = UE_list->next_ul[UE_id]; - } else { - int previous = prev(UE_list, UE_id, 1); - - if (previous != -1) { - UE_list->next_ul[previous] = UE_list->next_ul[UE_id]; - } - } + remove_ue_list(&UE_info->list, UE_id); /* Clear all remaining pending transmissions */ - memset(&UE_list->UE_template[pCC_id][UE_id], - 0, - sizeof(UE_TEMPLATE)); - ue_stats = &UE_list->eNB_UE_stats[pCC_id][UE_id]; + memset(&UE_info->UE_template[pCC_id][UE_id], 0, sizeof(UE_TEMPLATE)); + ue_stats = &UE_info->eNB_UE_stats[pCC_id][UE_id]; ue_stats->total_rbs_used = 0; ue_stats->total_rbs_used_retx = 0; @@ -2387,39 +2344,16 @@ rrc_mac_remove_ue(module_id_t mod_idP, /* * Returns the previous UE_id in the scheduling list in UL or DL */ -int -prev(UE_list_t *listP, - int nodeP, - int ul_flag) -//------------------------------------------------------------------------------ -{ - if (ul_flag == 0) { - if (nodeP == listP->head) { - return nodeP; - } +inline int prev(UE_list_t *listP, int nodeP) { + if (nodeP == listP->head) + return -1; /* there is no previous of the head */ - for (int j = listP->head; j >= 0; j = listP->next[j]) { - if (listP->next[j] == nodeP) { - return j; - } - } - } else { - if (nodeP == listP->head_ul) { - return nodeP; - } + for (int j = listP->head; j >= 0; j = listP->next[j]) + if (listP->next[j] == nodeP) + return j; - for (int j = listP->head_ul; j >= 0; j = listP->next_ul[j]) { - if (listP->next_ul[j] == nodeP) { - return j; - } - } - } - - LOG_E(MAC, "error in prev(), could not find previous to %d in UE_list %s, should never happen, Dumping UE list\n", - nodeP, - (ul_flag == 0) ? "DL" : "UL"); - dump_ue_list(listP, - ul_flag); + LOG_E(MAC, "%s(): could not find previous to %d in UE_list\n", __func__, nodeP); + dump_ue_list(listP); return -1; } @@ -2431,8 +2365,8 @@ UE_is_to_be_scheduled(module_id_t module_idP, uint8_t UE_id) //------------------------------------------------------------------------------ { - UE_TEMPLATE *UE_template = &RC.mac[module_idP]->UE_list.UE_template[CC_id][UE_id]; - UE_sched_ctrl_t *UE_sched_ctl = &RC.mac[module_idP]->UE_list.UE_sched_ctrl[UE_id]; + UE_TEMPLATE *UE_template = &RC.mac[module_idP]->UE_info.UE_template[CC_id][UE_id]; + UE_sched_ctrl_t *UE_sched_ctl = &RC.mac[module_idP]->UE_info.UE_sched_ctrl[UE_id]; int rrc_status; // do not schedule UE if UL is not working @@ -2474,7 +2408,7 @@ get_tmode(module_id_t module_idP, { eNB_MAC_INST *eNB = RC.mac[module_idP]; COMMON_channels_t *cc = &eNB->common_channels[CC_idP]; - struct LTE_PhysicalConfigDedicated *physicalConfigDedicated = eNB->UE_list.UE_template[CC_idP][UE_idP].physicalConfigDedicated; + struct LTE_PhysicalConfigDedicated *physicalConfigDedicated = eNB->UE_info.UE_template[CC_idP][UE_idP].physicalConfigDedicated; if (physicalConfigDedicated == NULL) { // RRCConnectionSetup not received by UE yet AssertFatal(cc->p_eNB <= 2, "p_eNB is %d, should be <2\n", @@ -3841,15 +3775,15 @@ 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_t *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + UE_info_t *UE_info = &eNB->UE_info; + UE_sched_ctrl_t *sched_ctl = &UE_info->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; nfapi_harq_indication_tdd_rel13_t *harq_indication_tdd; uint16_t num_ack_nak; - int numCC = UE_list->numactiveCCs[UE_id]; - int pCCid = UE_list->pCC_id[UE_id]; + int numCC = UE_info->numactiveCCs[UE_id]; + int pCCid = UE_info->pCC_id[UE_id]; int spatial_bundling = 0; int tmode[5]; int i, j, m; @@ -3857,7 +3791,7 @@ extract_harq(module_id_t mod_idP, sub_frame_t subframe_tx; int frame_tx; uint8_t harq_pid; - LTE_PhysicalConfigDedicated_t *physicalConfigDedicated = UE_list->UE_template[pCCid][UE_id].physicalConfigDedicated; + LTE_PhysicalConfigDedicated_t *physicalConfigDedicated = UE_info->UE_template[pCCid][UE_id].physicalConfigDedicated; if (physicalConfigDedicated != NULL && physicalConfigDedicated->pucch_ConfigDedicated != NULL && physicalConfigDedicated->ext7 != NULL && physicalConfigDedicated->ext7->pucch_ConfigDedicated_r13 != NULL && @@ -3991,7 +3925,7 @@ extract_harq(module_id_t mod_idP, sched_ctl->round[CC_idP][harq_pid]); // use 1 HARQ proces of BL/CE UE for now - if (UE_list->UE_template[pCCid][UE_id].rach_resource_type > 0) harq_pid = 0; + if (UE_info->UE_template[pCCid][UE_id].rach_resource_type > 0) harq_pid = 0; switch (harq_indication_fdd->mode) { case 0: // Format 1a/b (10.1.2.1) @@ -4477,18 +4411,18 @@ extract_pucch_csi(module_id_t mod_idP, uint8_t length) //------------------------------------------------------------------------------ { - UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; - UE_sched_ctrl_t *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info; + UE_sched_ctrl_t *sched_ctl = &UE_info->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 }; uint8_t Jtab[6] = { 0, 2, 2, 3, 4, 4 }; int feedback_cnt; - AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated != NULL, "physicalConfigDedicated is null for UE %d\n", + AssertFatal(UE_info->UE_template[CC_idP][UE_id].physicalConfigDedicated != NULL, "physicalConfigDedicated is null for UE %d\n", UE_id); - AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig != NULL, "cqi_ReportConfig is null for UE %d\n", + AssertFatal(UE_info->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig != NULL, "cqi_ReportConfig is null for UE %d\n", UE_id); - struct LTE_CQI_ReportPeriodic *cqi_ReportPeriodic = UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic; + struct LTE_CQI_ReportPeriodic *cqi_ReportPeriodic = UE_info->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic; AssertFatal(cqi_ReportPeriodic != NULL, "cqi_ReportPeriodic is null for UE %d\n", UE_id); // determine feedback mode @@ -4588,9 +4522,9 @@ extract_pusch_csi(module_id_t mod_idP, uint8_t length) //------------------------------------------------------------------------------ { - UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; + UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info; COMMON_channels_t *cc = &RC.mac[mod_idP]->common_channels[CC_idP]; - UE_sched_ctrl_t *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + UE_sched_ctrl_t *sched_ctl = &UE_info->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 }; @@ -4599,12 +4533,12 @@ extract_pusch_csi(module_id_t mod_idP, int i; uint64_t p = *(uint64_t *) pdu; int curbyte, curbit; - AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated != NULL, "physicalConfigDedicated is null for UE %d\n", + AssertFatal(UE_info->UE_template[CC_idP][UE_id].physicalConfigDedicated != NULL, "physicalConfigDedicated is null for UE %d\n", UE_id); - AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig != NULL, "cqi_ReportConfig is null for UE %d\n", + AssertFatal(UE_info->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig != NULL, "cqi_ReportConfig is null for UE %d\n", UE_id); LTE_CQI_ReportModeAperiodic_t *cqi_ReportModeAperiodic - = UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic; + = UE_info->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic; AssertFatal(cqi_ReportModeAperiodic != NULL, "cqi_ReportModeAperiodic is null for UE %d\n", UE_id); int N = Ntab[cc->mib->message.dl_Bandwidth]; @@ -4874,14 +4808,14 @@ cqi_indication(module_id_t mod_idP, //------------------------------------------------------------------------------ { int UE_id = find_UE_id(mod_idP, rntiP); - UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; + UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info; if (UE_id == -1) { LOG_W(MAC, "cqi_indication: UE %x not found\n", rntiP); return; } - UE_sched_ctrl_t *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + UE_sched_ctrl_t *sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; if (UE_id >= 0) { LOG_D(MAC,"%s() UE_id:%d channel:%d cqi:%d\n", @@ -4947,11 +4881,11 @@ SR_indication(module_id_t mod_idP, T_INT(subframeP), T_INT(rntiP)); int UE_id = find_UE_id(mod_idP, rntiP); - UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; + UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info; UE_sched_ctrl_t *UE_scheduling_ctrl = NULL; if (UE_id != -1) { - UE_scheduling_ctrl = &(UE_list->UE_sched_ctrl[UE_id]); + UE_scheduling_ctrl = &(UE_info->UE_sched_ctrl[UE_id]); if ((UE_scheduling_ctrl->cdrx_configured == TRUE) && (UE_scheduling_ctrl->dci0_ongoing_timer > 0) && @@ -4975,8 +4909,8 @@ SR_indication(module_id_t mod_idP, cc_idP); } - UE_list->UE_template[cc_idP][UE_id].ul_SR = 1; - UE_list->UE_template[cc_idP][UE_id].ul_active = TRUE; + UE_info->UE_template[cc_idP][UE_id].ul_SR = 1; + UE_info->UE_template[cc_idP][UE_id].ul_active = TRUE; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SR_INDICATION, 1); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SR_INDICATION, 0); } @@ -5003,7 +4937,7 @@ UL_failure_indication(module_id_t mod_idP, //------------------------------------------------------------------------------ { int UE_id = find_UE_id(mod_idP, rntiP); - UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; + UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info; if (UE_id != -1) { LOG_D(MAC, "[eNB %d][UE %d/%x] Frame %d subframeP %d Signaling UL Failure for UE %d on CC_id %d (timer %d)\n", @@ -5014,9 +4948,9 @@ UL_failure_indication(module_id_t mod_idP, subframeP, UE_id, cc_idP, - UE_list->UE_sched_ctrl[UE_id].ul_failure_timer); + UE_info->UE_sched_ctrl[UE_id].ul_failure_timer); - if (UE_list->UE_sched_ctrl[UE_id].ul_failure_timer == 0) UE_list->UE_sched_ctrl[UE_id].ul_failure_timer = 1; + if (UE_info->UE_sched_ctrl[UE_id].ul_failure_timer == 0) UE_info->UE_sched_ctrl[UE_id].ul_failure_timer = 1; } else { // AssertFatal(0, "find_UE_id(%u,rnti %d) not found", enb_mod_idP, rntiP); // AssertError(0, 0, "Frame %d: find_UE_id(%u,rnti %d) not found\n", frameP, enb_mod_idP, rntiP); @@ -5079,8 +5013,8 @@ harq_indication(module_id_t mod_idP, return; } - UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list; - UE_sched_ctrl_t *sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info; + UE_sched_ctrl_t *sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; COMMON_channels_t *cc = &RC.mac[mod_idP]->common_channels[CC_idP]; // extract HARQ Information @@ -5138,5 +5072,5 @@ ue_ul_slice_membership(module_id_t mod_id, return 0; } - return eNB->UE_list.active[UE_id] == TRUE && eNB->UE_list.assoc_ul_slice_idx[UE_id] == slice_idx; + return eNB->UE_info.active[UE_id] == TRUE && eNB->UE_info.assoc_ul_slice_idx[UE_id] == slice_idx; } diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index 7c3b536de2..d7b12aef22 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -123,17 +123,15 @@ rx_sdu(const module_id_t enb_mod_idP, unsigned short rx_lengths[NB_RB_MAX]; uint8_t lcgid = 0; int lcgid_updated[4] = {0, 0, 0, 0}; - eNB_MAC_INST *mac = NULL; - UE_list_t *UE_list = NULL; + eNB_MAC_INST *mac = RC.mac[enb_mod_idP]; + UE_info_t *UE_info = &mac->UE_info; rrc_eNB_ue_context_t *ue_contextP = NULL; UE_sched_ctrl_t *UE_scheduling_control = NULL; UE_TEMPLATE *UE_template_ptr = NULL; /* Init */ current_rnti = rntiP; UE_id = find_UE_id(enb_mod_idP, current_rnti); - mac = RC.mac[enb_mod_idP]; harq_pid = subframe2harqpid(&mac->common_channels[CC_idP], frameP, subframeP); - UE_list = &mac->UE_list; memset(rx_ces, 0, MAX_NUM_CE * sizeof(unsigned char)); memset(rx_lcids, 0, NB_RB_MAX * sizeof(unsigned char)); memset(rx_lengths, 0, NB_RB_MAX * sizeof(unsigned short)); @@ -142,8 +140,8 @@ rx_sdu(const module_id_t enb_mod_idP, trace_pdu(DIRECTION_UPLINK, sduP, sdu_lenP, 0, WS_C_RNTI, current_rnti, frameP, subframeP, 0, 0); if (UE_id != -1) { - UE_scheduling_control = &(UE_list->UE_sched_ctrl[UE_id]); - UE_template_ptr = &(UE_list->UE_template[CC_idP][UE_id]); + UE_scheduling_control = &UE_info->UE_sched_ctrl[UE_id]; + UE_template_ptr = &UE_info->UE_template[CC_idP][UE_id]; LOG_D(MAC, "[eNB %d][PUSCH %d] CC_id %d %d.%d Received ULSCH sdu round %d from PHY (rnti %x, UE_id %d) ul_cqi %d\n", enb_mod_idP, harq_pid, @@ -413,8 +411,8 @@ rx_sdu(const module_id_t enb_mod_idP, UE_id = old_UE_id; current_rnti = old_rnti; /* Clear timer */ - UE_scheduling_control = &(UE_list->UE_sched_ctrl[UE_id]); - UE_template_ptr = &(UE_list->UE_template[CC_idP][UE_id]); + UE_scheduling_control = &UE_info->UE_sched_ctrl[UE_id]; + UE_template_ptr = &UE_info->UE_template[CC_idP][UE_id]; UE_scheduling_control->uplane_inactivity_timer = 0; UE_scheduling_control->ul_inactivity_timer = 0; UE_scheduling_control->ul_failure_timer = 0; @@ -430,7 +428,7 @@ rx_sdu(const module_id_t enb_mod_idP, UE_template_ptr->ul_SR = 1; UE_scheduling_control->crnti_reconfigurationcomplete_flag = 1; - UE_list->UE_template[UE_PCCID(enb_mod_idP, UE_id)][UE_id].configured = 1; + UE_info->UE_template[UE_PCCID(enb_mod_idP, UE_id)][UE_id].configured = 1; cancel_ra_proc(enb_mod_idP, CC_idP, frameP, @@ -480,8 +478,8 @@ rx_sdu(const module_id_t enb_mod_idP, ra->crnti_rrc_mui = rrc_eNB_mui-1; ra->crnti_harq_pid = -1; /* Clear timer */ - UE_scheduling_control = &(UE_list->UE_sched_ctrl[UE_id]); - UE_template_ptr = &(UE_list->UE_template[CC_idP][UE_id]); + UE_scheduling_control = &UE_info->UE_sched_ctrl[UE_id]; + UE_template_ptr = &UE_info->UE_template[CC_idP][UE_id]; UE_scheduling_control->uplane_inactivity_timer = 0; UE_scheduling_control->ul_inactivity_timer = 0; UE_scheduling_control->ul_failure_timer = 0; @@ -532,7 +530,7 @@ rx_sdu(const module_id_t enb_mod_idP, UE_template_ptr->ul_buffer_info[LCGID3]; RC.eNB[enb_mod_idP][CC_idP]->pusch_stats_bsr[UE_id][(frameP * 10) + subframeP] = (payload_ptr[0] & 0x3f); - if (UE_id == UE_list->head) { + if (UE_id == UE_info->list.head) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_BSR, (payload_ptr[0] & 0x3f)); } @@ -689,8 +687,8 @@ rx_sdu(const module_id_t enb_mod_idP, frameP, ra->rnti, UE_id); - UE_scheduling_control = &(UE_list->UE_sched_ctrl[UE_id]); - UE_template_ptr = &(UE_list->UE_template[CC_idP][UE_id]); + UE_scheduling_control = &UE_info->UE_sched_ctrl[UE_id]; + UE_template_ptr = &UE_info->UE_template[CC_idP][UE_id]; } } else { LOG_D(MAC, "[eNB %d][RAPROC] CC_id %d Frame %d CCCH: Received Msg3 from already registered UE %d: length %d, offset %ld\n", @@ -779,11 +777,11 @@ rx_sdu(const module_id_t enb_mod_idP, enb_mod_idP, CC_idP, frameP, rx_lengths[i], UE_id, rx_lcids[i]); mac_rlc_data_ind(enb_mod_idP, current_rnti, enb_mod_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, rx_lcids[i], (char *) payload_ptr, rx_lengths[i], 1, NULL); //(unsigned int*)crc_status); - UE_list->eNB_UE_stats[CC_idP][UE_id].num_pdu_rx[rx_lcids[i]] += 1; - UE_list->eNB_UE_stats[CC_idP][UE_id].num_bytes_rx[rx_lcids[i]] += rx_lengths[i]; + UE_info->eNB_UE_stats[CC_idP][UE_id].num_pdu_rx[rx_lcids[i]] += 1; + UE_info->eNB_UE_stats[CC_idP][UE_id].num_bytes_rx[rx_lcids[i]] += rx_lengths[i]; if (mac_eNB_get_rrc_status(enb_mod_idP, current_rnti) < RRC_RECONFIGURED) { - UE_list->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0; + UE_info->UE_sched_ctrl[UE_id].uplane_inactivity_timer = 0; } } @@ -840,8 +838,8 @@ rx_sdu(const module_id_t enb_mod_idP, if ((rx_lengths[i] < SCH_PAYLOAD_SIZE_MAX) && (rx_lengths[i] > 0)) { // MAX SIZE OF transport block mac_rlc_data_ind(enb_mod_idP, current_rnti, enb_mod_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, rx_lcids[i], (char *) payload_ptr, rx_lengths[i], 1, NULL); - UE_list->eNB_UE_stats[CC_idP][UE_id].num_pdu_rx[rx_lcids[i]] += 1; - UE_list->eNB_UE_stats[CC_idP][UE_id].num_bytes_rx[rx_lcids[i]] += rx_lengths[i]; + UE_info->eNB_UE_stats[CC_idP][UE_id].num_pdu_rx[rx_lcids[i]] += 1; + UE_info->eNB_UE_stats[CC_idP][UE_id].num_bytes_rx[rx_lcids[i]] += rx_lengths[i]; /* Clear uplane_inactivity_timer */ UE_scheduling_control->uplane_inactivity_timer = 0; /* Reset RRC inactivity timer after uplane activity */ @@ -856,7 +854,7 @@ rx_sdu(const module_id_t enb_mod_idP, current_rnti); } } else { /* rx_length[i] Max size */ - UE_list->eNB_UE_stats[CC_idP][UE_id].num_errors_rx += 1; + UE_info->eNB_UE_stats[CC_idP][UE_id].num_errors_rx += 1; LOG_E(MAC, "[eNB %d] CC_id %d Frame %d : Max size of transport block reached LCID %d from UE %d ", enb_mod_idP, CC_idP, @@ -921,12 +919,12 @@ rx_sdu(const module_id_t enb_mod_idP, /* NN--> FK: we could either check the payload, or use a phy helper to detect a false msg3 */ if ((num_sdu == 0) && (num_ce == 0)) { if (UE_id != -1) - UE_list->eNB_UE_stats[CC_idP][UE_id].total_num_errors_rx += 1; + UE_info->eNB_UE_stats[CC_idP][UE_id].total_num_errors_rx += 1; } else { if (UE_id != -1) { - UE_list->eNB_UE_stats[CC_idP][UE_id].pdu_bytes_rx = sdu_lenP; - UE_list->eNB_UE_stats[CC_idP][UE_id].total_pdu_bytes_rx += sdu_lenP; - UE_list->eNB_UE_stats[CC_idP][UE_id].total_num_pdus_rx += 1; + UE_info->eNB_UE_stats[CC_idP][UE_id].pdu_bytes_rx = sdu_lenP; + UE_info->eNB_UE_stats[CC_idP][UE_id].total_pdu_bytes_rx += sdu_lenP; + UE_info->eNB_UE_stats[CC_idP][UE_id].total_num_pdus_rx += 1; } } @@ -1307,20 +1305,16 @@ schedule_ulsch_rnti(module_id_t module_idP, static int32_t tpc_accumulated = 0; int sched_frame = 0; int CC_id = 0; - eNB_MAC_INST *mac = NULL; - COMMON_channels_t *cc = NULL; - UE_list_t *UE_list = NULL; - slice_info_t *sli = NULL; + eNB_MAC_INST *mac = RC.mac[module_idP]; + COMMON_channels_t *cc = mac->common_channels; + UE_info_t *UE_info = &mac->UE_info; + slice_info_t *sli = &mac->slice_info; UE_TEMPLATE *UE_template_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]; /* Init */ - mac = RC.mac[module_idP]; - cc = mac->common_channels; - UE_list = &(mac->UE_list); - sli = &(mac->slice_info); memset(first_rb_slice, 0, NFAPI_CC_MAX * sizeof(int)); memset(n_rb_ul_tab, 0, NFAPI_CC_MAX * sizeof(int)); sched_frame = frameP; @@ -1370,7 +1364,7 @@ schedule_ulsch_rnti(module_id_t module_idP, exit(1); } - UE_list->first_rb_offset[CC_id][slice_idx] = cmin(n_rb_ul_tab[CC_id], sli->ul[slice_idx].first_rb); + UE_info->first_rb_offset[CC_id][slice_idx] = cmin(n_rb_ul_tab[CC_id], sli->ul[slice_idx].first_rb); } /* @@ -1382,19 +1376,19 @@ schedule_ulsch_rnti(module_id_t module_idP, ulsch_scheduler_pre_processor(module_idP, slice_idx, frameP, subframeP, sched_frame, sched_subframeP, first_rb); for (CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; CC_id++) { - first_rb_slice[CC_id] = first_rb[CC_id] + UE_list->first_rb_offset[CC_id][slice_idx]; + first_rb_slice[CC_id] = first_rb[CC_id] + UE_info->first_rb_offset[CC_id][slice_idx]; } // loop over all active UEs until end of function - for (int UE_id = UE_list->head_ul; UE_id >= 0; UE_id = UE_list->next_ul[UE_id]) { + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { if (!ue_ul_slice_membership(module_idP, UE_id, slice_idx)) { continue; } - if (UE_list->UE_template[UE_PCCID(module_idP, UE_id)][UE_id].rach_resource_type > 0) continue; + if (UE_info->UE_template[UE_PCCID(module_idP, UE_id)][UE_id].rach_resource_type > 0) continue; // don't schedule if Msg5 is not received yet - if (UE_list->UE_template[UE_PCCID(module_idP, UE_id)][UE_id].configured == FALSE) { + if (UE_info->UE_template[UE_PCCID(module_idP, UE_id)][UE_id].configured == FALSE) { LOG_D(MAC, "[eNB %d] frame %d, subframe %d, UE %d: not configured, skipping UE scheduling \n", module_idP, frameP, @@ -1415,11 +1409,11 @@ schedule_ulsch_rnti(module_id_t module_idP, } // loop over all active UL CC_ids for this UE until end of function - for (int n = 0; n < UE_list->numactiveULCCs[UE_id]; n++) { + for (int n = 0; n < UE_info->numactiveULCCs[UE_id]; n++) { /* This is the actual CC_id in the list */ - CC_id = UE_list->ordered_ULCCids[n][UE_id]; - UE_template_ptr = &(UE_list->UE_template[CC_id][UE_id]); - UE_sched_ctrl_ptr = &(UE_list->UE_sched_ctrl[UE_id]); + CC_id = UE_info->ordered_ULCCids[n][UE_id]; + UE_template_ptr = &UE_info->UE_template[CC_id][UE_id]; + UE_sched_ctrl_ptr = &UE_info->UE_sched_ctrl[UE_id]; harq_pid = subframe2harqpid(&cc[CC_id], sched_frame, sched_subframeP); round_index = UE_sched_ctrl_ptr->round_UL[CC_id][harq_pid]; AssertFatal(round_index < 8, "round %d > 7 for UE %d/%x\n", @@ -1578,10 +1572,10 @@ schedule_ulsch_rnti(module_id_t module_idP, ndi = 1 - UE_template_ptr->oldNDI_UL[harq_pid]; // NDI: new data indicator UE_template_ptr->oldNDI_UL[harq_pid] = ndi; - UE_list->eNB_UE_stats[CC_id][UE_id].snr = snr; - UE_list->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr; + UE_info->eNB_UE_stats[CC_id][UE_id].snr = snr; + UE_info->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr; UE_template_ptr->mcs_UL[harq_pid] = cmin(UE_template_ptr->pre_assigned_mcs_ul, sli->ul[slice_idx].maxmcs); - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1= UE_template_ptr->mcs_UL[harq_pid]; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1= UE_template_ptr->mcs_UL[harq_pid]; /* CDRX */ if (UE_sched_ctrl_ptr->cdrx_configured) { @@ -1598,7 +1592,7 @@ schedule_ulsch_rnti(module_id_t module_idP, rb_table_index = 5; // for PHR } - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2 = UE_template_ptr->mcs_UL[harq_pid]; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2 = UE_template_ptr->mcs_UL[harq_pid]; while (((rb_table[rb_table_index] > (n_rb_ul_tab[CC_id] - first_rb_slice[CC_id])) || (rb_table[rb_table_index] > 45)) && (rb_table_index > 0)) { @@ -1606,9 +1600,9 @@ schedule_ulsch_rnti(module_id_t module_idP, } UE_template_ptr->TBS_UL[harq_pid] = get_TBS_UL(UE_template_ptr->mcs_UL[harq_pid], rb_table[rb_table_index]); - UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx += rb_table[rb_table_index]; - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS = UE_template_ptr->TBS_UL[harq_pid]; - UE_list->eNB_UE_stats[CC_id][UE_id].total_ulsch_TBS += UE_template_ptr->TBS_UL[harq_pid]; + UE_info->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx += rb_table[rb_table_index]; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_TBS = UE_template_ptr->TBS_UL[harq_pid]; + UE_info->eNB_UE_stats[CC_id][UE_id].total_ulsch_TBS += UE_template_ptr->TBS_UL[harq_pid]; T(T_ENB_MAC_UE_UL_SCHEDULE, T_INT(module_idP), T_INT(CC_id), @@ -1627,7 +1621,7 @@ schedule_ulsch_rnti(module_id_t module_idP, UE_template_ptr->cqi_req[harq_pid] = cqi_req; UE_sched_ctrl_ptr->ul_scheduled |= (1 << harq_pid); - if (UE_id == UE_list->head) { + if (UE_id == UE_info->list.head) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_SCHEDULED, UE_sched_ctrl_ptr->ul_scheduled); } @@ -1926,7 +1920,7 @@ void schedule_ulsch_rnti_emtc(module_id_t module_idP, eNB_MAC_INST *eNB = RC.mac[module_idP]; eNB_RRC_INST *rrc = RC.rrc[module_idP]; COMMON_channels_t *cc = eNB->common_channels; - UE_list_t *UE_list = &(eNB->UE_list); + UE_info_t *UE_info = &eNB->UE_info; UE_TEMPLATE *UE_template = NULL; UE_sched_ctrl_t *UE_sched_ctrl = NULL; uint8_t Total_Num_Rep_ULSCH,pusch_maxNumRepetitionCEmodeA_r13; @@ -1944,8 +1938,8 @@ void schedule_ulsch_rnti_emtc(module_id_t module_idP, nfapi_ul_config_request_pdu_t *ul_config_pdu_Rep; /* Loop over all active UEs */ - for (UE_id = UE_list->head_ul; UE_id >= 0; UE_id = UE_list->next_ul[UE_id]) { - UE_template = &(UE_list->UE_template[UE_PCCID(module_idP, UE_id)][UE_id]); + for (UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + UE_template = &UE_info->UE_template[UE_PCCID(module_idP, UE_id)][UE_id]; /* LTE-M device */ if (UE_template->rach_resource_type == 0) { @@ -1974,12 +1968,12 @@ void schedule_ulsch_rnti_emtc(module_id_t module_idP, } /* Loop over all active UL CC_ids for this UE */ - for (n = 0; n < UE_list->numactiveULCCs[UE_id]; n++) { + for (n = 0; n < UE_info->numactiveULCCs[UE_id]; n++) { /* This is the actual CC_id in the list */ - CC_id = UE_list->ordered_ULCCids[n][UE_id]; + CC_id = UE_info->ordered_ULCCids[n][UE_id]; N_RB_UL = to_prb(cc[CC_id].ul_Bandwidth); - UE_template = &(UE_list->UE_template[CC_id][UE_id]); - UE_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id]; + UE_template = &UE_info->UE_template[CC_id][UE_id]; + UE_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; harq_pid = 0; round_UL = UE_sched_ctrl->round_UL[CC_id][harq_pid]; AssertFatal(round_UL < 8,"round_UL %d > 7 for UE %d/%x\n", @@ -2074,12 +2068,12 @@ void schedule_ulsch_rnti_emtc(module_id_t module_idP, UE_template->oldNDI_UL[harq_pid] = ndi; UE_template->mcs_UL[harq_pid] = 4; UE_template->TBS_UL[harq_pid] = get_TBS_UL(UE_template->mcs_UL[harq_pid], 6); - UE_list->eNB_UE_stats[CC_id][UE_id].snr = snr; - UE_list->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr; - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1 = 4; - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2 = UE_template->mcs_UL[harq_pid]; - UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx += 6; - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS = UE_template->TBS_UL[harq_pid]; + UE_info->eNB_UE_stats[CC_id][UE_id].snr = snr; + UE_info->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1 = 4; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2 = UE_template->mcs_UL[harq_pid]; + UE_info->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx += 6; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_TBS = UE_template->TBS_UL[harq_pid]; T(T_ENB_MAC_UE_UL_SCHEDULE, T_INT(module_idP), T_INT(CC_id), @@ -2096,7 +2090,7 @@ void schedule_ulsch_rnti_emtc(module_id_t module_idP, UE_template->nb_rb_ul[harq_pid] = 6; UE_sched_ctrl->ul_scheduled |= (1 << harq_pid); - if (UE_id == UE_list->head) { + if (UE_id == UE_info->list.head) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_SCHEDULED, UE_sched_ctrl->ul_scheduled); } diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h index 2fdcb862d3..3412aa52c5 100644 --- a/openair2/LAYER2/MAC/mac.h +++ b/openair2/LAYER2/MAC/mac.h @@ -1129,7 +1129,15 @@ typedef struct { uint8_t sb_size; uint8_t nb_active_sb; } SBMAP_CONF; -/*! \brief UE list used by eNB to order UEs/CC for scheduling*/ + +/*! \brief UE_list_t is a "list" of users within UE_info_t. Especial useful in + * the scheduler and to keep "classes" of users. */ +typedef struct { + int head; + int next[MAX_MOBILES_PER_ENB]; +} UE_list_t; + +/*! \brief UE info used by eNB to order UEs/CC for scheduling*/ typedef struct { DLSCH_PDU DLSCH_pdu[NFAPI_CC_MAX][2][MAX_MOBILES_PER_ENB]; @@ -1151,11 +1159,7 @@ typedef struct { eNB_UE_STATS eNB_UE_stats[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]; /// scheduling control info 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]; - int head_ul; - int avail; + UE_list_t list; int num_UEs; boolean_t active[MAX_MOBILES_PER_ENB]; @@ -1163,7 +1167,7 @@ typedef struct { uint16_t sorting_criteria[MAX_NUM_SLICES][CR_NUM]; uint16_t first_rb_offset[NFAPI_CC_MAX][MAX_NUM_SLICES]; int assoc_ul_slice_idx[MAX_MOBILES_PER_ENB]; -} UE_list_t; +} UE_info_t; /*! \brief deleting control information*/ typedef struct { @@ -1395,7 +1399,7 @@ typedef struct eNB_MAC_INST_s { nfapi_ue_release_request_t UE_release_req; /// UL handle uint32_t ul_handle; - UE_list_t UE_list; + UE_info_t UE_info; /// slice-related configuration slice_info_t slice_info; diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index 01b463d641..c5eb16c5b3 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -193,7 +193,7 @@ void add_msg3(module_id_t module_idP, int CC_id, RA_t *ra, frame_t frameP, //main.c -void init_UE_list(UE_list_t *UE_list); +void init_UE_info(UE_info_t *UE_info); void init_slice_info(slice_info_t *sli); @@ -448,7 +448,7 @@ boolean_t CCE_allocation_infeasible(int module_idP, void set_ue_dai(sub_frame_t subframeP, int UE_id, - uint8_t CC_id, uint8_t tdd_config, UE_list_t *UE_list); + uint8_t CC_id, uint8_t tdd_config, UE_info_t *UE_info); uint8_t frame_subframe2_dl_harq_pid(LTE_TDD_Config_t *tdd_Config, int abs_frameP, sub_frame_t subframeP); /** \brief First stage of PCH Scheduling. Gets a PCH SDU from RRC if available and computes the MCS required to transport it as a function of the SDU length. It assumes a length less than or equal to 64 bytes (MCS 6, 3 PRBs). @@ -685,10 +685,11 @@ int rrc_mac_remove_ue(module_id_t Mod_id, rnti_t rntiP); void store_dlsch_buffer(module_id_t Mod_id, frame_t frameP, sub_frame_t subframeP); void assign_rbs_required(module_id_t Mod_id, int CC_id, uint16_t nb_rbs_required[MAX_MOBILES_PER_ENB]); -int prev(UE_list_t *listP, int nodeP, int ul_flag); -void add_ue_list(UE_list_t *listP, int UE_id, int ul_flag); -void dump_ue_list(UE_list_t *listP, int ul_flag); -int UE_num_active_CC(UE_list_t *listP, int ue_idP); +int prev(UE_list_t *listP, int nodeP); +void add_ue_list(UE_list_t *listP, int UE_id); +int remove_ue_list(UE_list_t *listP, int UE_id); +void dump_ue_list(UE_list_t *listP); +int UE_num_active_CC(UE_info_t *listP, int ue_idP); int UE_PCCID(module_id_t mod_idP, int ue_idP); rnti_t UE_RNTI(module_id_t mod_idP, int ue_idP); diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index 12c12fb4bd..ae1e7aee37 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -43,23 +43,19 @@ extern RAN_CONTEXT_t RC; -void init_UE_list(UE_list_t *UE_list) +void init_UE_info(UE_info_t *UE_info) { int list_el; - UE_list->num_UEs = 0; - UE_list->head = -1; - UE_list->head_ul = -1; - UE_list->avail = 0; - for (list_el = 0; list_el < MAX_MOBILES_PER_ENB; list_el++) { - UE_list->next[list_el] = -1; - UE_list->next_ul[list_el] = -1; - } - memset(UE_list->DLSCH_pdu, 0, sizeof(UE_list->DLSCH_pdu)); - memset(UE_list->UE_template, 0, sizeof(UE_list->UE_template)); - memset(UE_list->eNB_UE_stats, 0, sizeof(UE_list->eNB_UE_stats)); - memset(UE_list->UE_sched_ctrl, 0, sizeof(UE_list->UE_sched_ctrl)); - memset(UE_list->active, 0, sizeof(UE_list->active)); - memset(UE_list->assoc_ul_slice_idx, 0, sizeof(UE_list->assoc_ul_slice_idx)); + UE_info->num_UEs = 0; + UE_info->list.head = -1; + for (list_el = 0; list_el < MAX_MOBILES_PER_ENB; list_el++) + UE_info->list.next[list_el] = -1; + memset(UE_info->DLSCH_pdu, 0, sizeof(UE_info->DLSCH_pdu)); + memset(UE_info->UE_template, 0, sizeof(UE_info->UE_template)); + memset(UE_info->eNB_UE_stats, 0, sizeof(UE_info->eNB_UE_stats)); + memset(UE_info->UE_sched_ctrl, 0, sizeof(UE_info->UE_sched_ctrl)); + memset(UE_info->active, 0, sizeof(UE_info->active)); + memset(UE_info->assoc_ul_slice_idx, 0, sizeof(UE_info->assoc_ul_slice_idx)); } void init_slice_info(slice_info_t *sli) @@ -134,7 +130,7 @@ void mac_top_init_eNB(void) mac[i]->if_inst = IF_Module_init(i); - init_UE_list(&mac[i]->UE_list); + init_UE_info(&mac[i]->UE_info); init_slice_info(&mac[i]->slice_info); } @@ -160,12 +156,12 @@ void mac_init_cell_params(int Mod_idP, int CC_idP) memset(&RC.mac[Mod_idP]->eNB_stats, 0, sizeof(eNB_STATS)); UE_template = - (UE_TEMPLATE *) & RC.mac[Mod_idP]->UE_list.UE_template[CC_idP][0]; + (UE_TEMPLATE *) & RC.mac[Mod_idP]->UE_info.UE_template[CC_idP][0]; for (j = 0; j < MAX_MOBILES_PER_ENB; j++) { UE_template[j].rnti = 0; // initiallize the eNB to UE statistics - memset(&RC.mac[Mod_idP]->UE_list.eNB_UE_stats[CC_idP][j], 0, + memset(&RC.mac[Mod_idP]->UE_info.eNB_UE_stats[CC_idP][j], 0, sizeof(eNB_UE_STATS)); } @@ -260,4 +256,4 @@ void *mac_enb_task(void *arg) } // end while return NULL; -} \ No newline at end of file +} diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 90cced9c49..0f1e307222 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -53,7 +53,6 @@ extern RAN_CONTEXT_t RC; #define DEBUG_eNB_SCHEDULER 1 #define DEBUG_HEADER_PARSING 1 - void sort_ue_ul(module_id_t module_idP, int slice_idx, @@ -66,14 +65,14 @@ void store_dlsch_buffer(module_id_t Mod_id, frame_t frameP, sub_frame_t subframeP) { - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; + UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; for (int UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) { - if (UE_list->active[UE_id] != TRUE) + if (UE_info->active[UE_id] != TRUE) continue; /* TODO why UE_template per CC? */ - UE_TEMPLATE *UE_template = &UE_list->UE_template[UE_PCCID(Mod_id, UE_id)][UE_id]; + UE_TEMPLATE *UE_template = &UE_info->UE_template[UE_PCCID(Mod_id, UE_id)][UE_id]; UE_template->dl_buffer_total = 0; UE_template->dl_pdus_total = 0; @@ -132,17 +131,17 @@ store_dlsch_buffer(module_id_t Mod_id, int get_rbs_required(module_id_t Mod_id, int CC_id, int UE_id) { - const UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; + const UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; - if (UE_list->UE_template[CC_id][UE_id].dl_buffer_total == 0) + if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total == 0) return 0; - const int dlsch_mcs1 = cqi_to_mcs[UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id]]; + const int dlsch_mcs1 = cqi_to_mcs[UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]]; const int min_rb_unit = get_min_rb_unit(Mod_id, CC_id); int nb_rbs_required = min_rb_unit; /* calculating required number of RBs for each UE */ int TBS = get_TBS_DL(dlsch_mcs1, nb_rbs_required); - while (TBS < UE_list->UE_template[CC_id][UE_id].dl_buffer_total) { + while (TBS < UE_info->UE_template[CC_id][UE_id].dl_buffer_total) { nb_rbs_required += min_rb_unit; TBS = get_TBS_DL(dlsch_mcs1, nb_rbs_required); } @@ -153,11 +152,11 @@ void assign_rbs_required(module_id_t Mod_id, int CC_id, uint16_t nb_rbs_required[MAX_MOBILES_PER_ENB]) { - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; - for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { nb_rbs_required[UE_id] = get_rbs_required(Mod_id, CC_id, UE_id); // TODO: the following should not be here - UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = cqi_to_mcs[UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id]]; + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = cqi_to_mcs[UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]]; } } @@ -167,7 +166,7 @@ maxround_ul(module_id_t Mod_id, uint16_t rnti, int sched_frame, sub_frame_t sched_subframe) { uint8_t round, round_max = 0, UE_id; int CC_id, harq_pid; - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; + UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; COMMON_channels_t *cc; for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_id]; CC_id++) { @@ -178,7 +177,7 @@ maxround_ul(module_id_t Mod_id, uint16_t rnti, int sched_frame, continue; harq_pid = subframe2harqpid(cc, sched_frame, sched_subframe); - round = UE_list->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid]; + round = UE_info->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid]; if (round > round_max) { round_max = round; @@ -200,21 +199,21 @@ void dlsch_scheduler_pre_processor_accounting(module_id_t Mod_id, int ue_count_newtx = 0; int ue_count_retx = 0; - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; + UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; // Find total UE count, and account the RBs required for retransmissions - for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { const rnti_t rnti = UE_RNTI(Mod_id, UE_id); if (rnti == NOT_A_RNTI) continue; - if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; + if (UE_info->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id]; const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP,subframeP); - const uint8_t round = UE_list->UE_sched_ctrl[UE_id].round[CC_id][harq_pid]; + const uint8_t round = UE_info->UE_sched_ctrl[UE_id].round[CC_id][harq_pid]; // retransmission if (round != 8) { - nb_rbs_required[UE_id] = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid]; + nb_rbs_required[UE_id] = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid]; rbs_retx += nb_rbs_required[UE_id]; ue_count_retx++; } else { @@ -234,14 +233,14 @@ void dlsch_scheduler_pre_processor_accounting(module_id_t Mod_id, average_rbs_per_user = (uint16_t)min_rb_unit; } - for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { const rnti_t rnti = UE_RNTI(Mod_id, UE_id); if (rnti == NOT_A_RNTI) continue; - if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; + if (UE_info->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id]; const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP,subframeP); - const uint8_t round = UE_list->UE_sched_ctrl[UE_id].round[CC_id][harq_pid]; + const uint8_t round = UE_info->UE_sched_ctrl[UE_id].round[CC_id][harq_pid]; /* TODO the first seems unnecessary, remove it */ if (mac_eNB_get_rrc_status(Mod_id, rnti) < RRC_RECONFIGURED || round != 8) @@ -256,11 +255,11 @@ void dlsch_scheduler_pre_processor_positioning(module_id_t Mod_id, uint16_t nb_rbs_required[MAX_MOBILES_PER_ENB], uint16_t nb_rbs_accounted[MAX_MOBILES_PER_ENB], uint8_t rballoc_sub[N_RBG_MAX]) { - UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; + UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; - for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { if (UE_RNTI(Mod_id, UE_id) == NOT_A_RNTI) continue; - if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; + if (UE_info->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; dlsch_scheduler_pre_processor_allocate(Mod_id, UE_id, @@ -316,11 +315,11 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, nb_rbs_accounted, rballoc_sub); - const UE_list_t *UE_list = &RC.mac[Mod_id]->UE_list; + const UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id]; const int N_RBG = to_rbg(cc->mib->message.dl_Bandwidth); - for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { - const UE_sched_ctrl_t *ue_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id]; + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + const UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; if (ue_sched_ctrl->pre_nb_available_rbs[CC_id] == 0) continue; @@ -334,10 +333,10 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, frameP, subframeP, UE_id, - UE_list->UE_template[CC_id][UE_id].rnti, + UE_info->UE_template[CC_id][UE_id].rnti, s, ue_sched_ctrl->pre_nb_available_rbs[CC_id], - UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1); + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1); } } @@ -345,16 +344,16 @@ void dlsch_scheduler_pre_processor_reset(module_id_t module_idP, int CC_id, uint8_t rballoc_sub[N_RBG_MAX]) { - UE_list_t *UE_list = &RC.mac[module_idP]->UE_list; + UE_info_t *UE_info = &RC.mac[module_idP]->UE_info; for (int UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; ++UE_id) { - UE_sched_ctrl_t *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + UE_sched_ctrl_t *ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; const rnti_t rnti = UE_RNTI(module_idP, UE_id); if (rnti == NOT_A_RNTI) continue; - if (UE_list->active[UE_id] != TRUE) + if (UE_info->active[UE_id] != TRUE) continue; // initialize harq_pid and round @@ -389,7 +388,7 @@ dlsch_scheduler_pre_processor_allocate(module_id_t Mod_id, uint16_t nb_rbs_required, uint16_t *nb_rbs_remaining, uint8_t rballoc_sub[N_RBG_MAX]) { - UE_sched_ctrl_t *ue_sched_ctl = &RC.mac[Mod_id]->UE_list.UE_sched_ctrl[UE_id]; + UE_sched_ctrl_t *ue_sched_ctl = &RC.mac[Mod_id]->UE_info.UE_sched_ctrl[UE_id]; const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); const int N_RB_DL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); const int min_rb_unit = get_min_rb_unit(Mod_id, CC_id); @@ -442,7 +441,7 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, int16_t total_remaining_rbs[NFAPI_CC_MAX]; uint16_t total_ue_count[NFAPI_CC_MAX]; eNB_MAC_INST *eNB = RC.mac[module_idP]; - UE_list_t *UE_list = &eNB->UE_list; + UE_info_t *UE_info = &eNB->UE_info; slice_info_t *sli = &eNB->slice_info; UE_TEMPLATE *UE_template = 0; UE_sched_ctrl_t *ue_sched_ctl; @@ -467,11 +466,11 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, } // Step 1.5: Calculate total_ue_count - for (UE_id = UE_list->head_ul; UE_id >= 0; UE_id = UE_list->next_ul[UE_id]) { + for (UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { // This is not the actual CC_id in the list - for (n = 0; n < UE_list->numactiveULCCs[UE_id]; n++) { - CC_id = UE_list->ordered_ULCCids[n][UE_id]; - UE_template = &UE_list->UE_template[CC_id][UE_id]; + for (n = 0; n < UE_info->numactiveULCCs[UE_id]; n++) { + CC_id = UE_info->ordered_ULCCids[n][UE_id]; + UE_template = &UE_info->UE_template[CC_id][UE_id]; if (UE_template->pre_allocated_nb_rb_ul[slice_idx] > 0) { total_ue_count[CC_id]++; @@ -482,16 +481,16 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, // step 2: calculate the average rb per UE LOG_D(MAC, "In ulsch_preprocessor: step2 \n"); - for (UE_id = UE_list->head_ul; UE_id >= 0; UE_id = UE_list->next_ul[UE_id]) { - if (UE_list->UE_template[CC_id][UE_id].rach_resource_type > 0) continue; + for (UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + if (UE_info->UE_template[CC_id][UE_id].rach_resource_type > 0) continue; LOG_D(MAC, "In ulsch_preprocessor: handling UE %d/%x\n", UE_id, rntiTable[UE_id]); - for (n = 0; n < UE_list->numactiveULCCs[UE_id]; n++) { + for (n = 0; n < UE_info->numactiveULCCs[UE_id]; n++) { // This is the actual CC_id in the list - CC_id = UE_list->ordered_ULCCids[n][UE_id]; + CC_id = UE_info->ordered_ULCCids[n][UE_id]; LOG_D(MAC, "In ulsch_preprocessor: handling UE %d/%x CCid %d\n", UE_id, rntiTable[UE_id], @@ -502,10 +501,10 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, max_num_ue_to_be_scheduled+=1; } */ N_RB_UL = to_prb(eNB->common_channels[CC_id].ul_Bandwidth); - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; ue_sched_ctl->max_rbs_allowed_slice_uplink[CC_id][slice_idx] = nb_rbs_allowed_slice(sli->ul[slice_idx].pct, N_RB_UL); - first_rb_offset = UE_list->first_rb_offset[CC_id][slice_idx]; + first_rb_offset = UE_info->first_rb_offset[CC_id][slice_idx]; available_rbs = cmin(ue_sched_ctl->max_rbs_allowed_slice_uplink[CC_id][slice_idx], N_RB_UL - first_rb[CC_id] - first_rb_offset); @@ -539,22 +538,22 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, } // step 3: assigne RBS - for (UE_id = UE_list->head_ul; UE_id >= 0; UE_id = UE_list->next_ul[UE_id]) { + for (UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { // if (continueTable[UE_id]) continue; - for (n = 0; n < UE_list->numactiveULCCs[UE_id]; n++) { + for (n = 0; n < UE_info->numactiveULCCs[UE_id]; n++) { // This is the actual CC_id in the list - CC_id = UE_list->ordered_ULCCids[n][UE_id]; - UE_template = &UE_list->UE_template[CC_id][UE_id]; + CC_id = UE_info->ordered_ULCCids[n][UE_id]; + UE_template = &UE_info->UE_template[CC_id][UE_id]; harq_pid = subframe2harqpid(&RC.mac[module_idP]->common_channels[CC_id], sched_frameP, sched_subframeP); // mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,openair_harq_UL); - if (UE_list->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid] > 0) { - nb_allocated_rbs[CC_id][UE_id] = UE_list->UE_template[CC_id][UE_id].nb_rb_ul[harq_pid]; + if (UE_info->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid] > 0) { + nb_allocated_rbs[CC_id][UE_id] = UE_info->UE_template[CC_id][UE_id].nb_rb_ul[harq_pid]; } else { nb_allocated_rbs[CC_id][UE_id] = - cmin(UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[slice_idx], average_rbs_per_user[CC_id]); + cmin(UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[slice_idx], average_rbs_per_user[CC_id]); } total_allocated_rbs[CC_id] += nb_allocated_rbs[CC_id][UE_id]; @@ -568,16 +567,16 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, } // step 4: assigne the remaining RBs and set the pre_allocated rbs accordingly - for (UE_id = UE_list->head_ul; UE_id >= 0; UE_id = UE_list->next_ul[UE_id]) { + for (UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { // if (continueTable[UE_id]) continue; - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; - for (n = 0; n < UE_list->numactiveULCCs[UE_id]; n++) { + for (n = 0; n < UE_info->numactiveULCCs[UE_id]; n++) { // This is the actual CC_id in the list - CC_id = UE_list->ordered_ULCCids[n][UE_id]; - UE_template = &UE_list->UE_template[CC_id][UE_id]; + CC_id = UE_info->ordered_ULCCids[n][UE_id]; + UE_template = &UE_info->UE_template[CC_id][UE_id]; N_RB_UL = to_prb(eNB->common_channels[CC_id].ul_Bandwidth); - first_rb_offset = UE_list->first_rb_offset[CC_id][slice_idx]; + first_rb_offset = UE_info->first_rb_offset[CC_id][slice_idx]; available_rbs = cmin(ue_sched_ctl->max_rbs_allowed_slice_uplink[CC_id][slice_idx], N_RB_UL - first_rb[CC_id] - first_rb_offset); total_remaining_rbs[CC_id] = available_rbs - total_allocated_rbs[CC_id]; @@ -620,7 +619,7 @@ assign_max_mcs_min_rb(module_id_t module_idP, int mcs; int rb_table_index = 0, tbs, tx_power; eNB_MAC_INST *eNB = RC.mac[module_idP]; - UE_list_t *UE_list = &eNB->UE_list; + UE_info_t *UE_info = &eNB->UE_info; slice_info_t *sli = &eNB->slice_info; UE_TEMPLATE *UE_template; UE_sched_ctrl_t *ue_sched_ctl; @@ -628,8 +627,8 @@ assign_max_mcs_min_rb(module_id_t module_idP, int N_RB_UL; int first_rb_offset, available_rbs; - for (i = UE_list->head_ul; i >= 0; i = UE_list->next_ul[i]) { - if (UE_list->UE_sched_ctrl[i].phr_received == 1) { + for (i = UE_info->list.head; i >= 0; i = UE_info->list.next[i]) { + if (UE_info->UE_sched_ctrl[i].phr_received == 1) { /* if we've received the power headroom information the UE, we can go to * maximum mcs */ mcs = cmin(20, sli->ul[slice_idx].maxmcs); @@ -640,18 +639,18 @@ assign_max_mcs_min_rb(module_id_t module_idP, UE_id = i; - for (n = 0; n < UE_list->numactiveULCCs[UE_id]; n++) { + for (n = 0; n < UE_info->numactiveULCCs[UE_id]; n++) { // This is the actual CC_id in the list - CC_id = UE_list->ordered_ULCCids[n][UE_id]; + CC_id = UE_info->ordered_ULCCids[n][UE_id]; AssertFatal(CC_id < RC.nb_mac_CC[module_idP], "CC_id %u should be < %u, loop n=%u < numactiveULCCs[%u]=%u", CC_id, NFAPI_CC_MAX, n, UE_id, - UE_list->numactiveULCCs[UE_id]); - UE_template = &UE_list->UE_template[CC_id][UE_id]; + UE_info->numactiveULCCs[UE_id]); + UE_template = &UE_info->UE_template[CC_id][UE_id]; UE_template->pre_assigned_mcs_ul = mcs; - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; + ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; Ncp = eNB->common_channels[CC_id].Ncp; N_RB_UL = to_prb(eNB->common_channels[CC_id].ul_Bandwidth); ue_sched_ctl->max_rbs_allowed_slice_uplink[CC_id][slice_idx] = nb_rbs_allowed_slice(sli->ul[slice_idx].pct, N_RB_UL); @@ -675,7 +674,7 @@ assign_max_mcs_min_rb(module_id_t module_idP, tx_power = estimate_ue_tx_power(tbs, rb_table[rb_table_index], 0, Ncp, 0); // fixme: set use_srs } - first_rb_offset = UE_list->first_rb_offset[CC_id][slice_idx]; + first_rb_offset = UE_info->first_rb_offset[CC_id][slice_idx]; available_rbs = cmin(ue_sched_ctl->max_rbs_allowed_slice_uplink[CC_id][slice_idx], N_RB_UL - first_rb[CC_id] - first_rb_offset); @@ -735,7 +734,7 @@ struct sort_ue_ul_params { static int ue_ul_compare(const void *_a, const void *_b, void *_params) { struct sort_ue_ul_params *params = _params; - UE_list_t *UE_list = &RC.mac[params->module_idP]->UE_list; + UE_info_t *UE_info = &RC.mac[params->module_idP]->UE_info; int UE_id1 = *(const int *) _a; int UE_id2 = *(const int *) _b; int rnti1 = UE_RNTI(params->module_idP, UE_id1); @@ -753,19 +752,19 @@ static int ue_ul_compare(const void *_a, const void *_b, void *_params) { if (round1 < round2) return 1; - if (UE_list->UE_template[pCCid1][UE_id1].ul_buffer_info[LCGID0] > - UE_list->UE_template[pCCid2][UE_id2].ul_buffer_info[LCGID0]) + if (UE_info->UE_template[pCCid1][UE_id1].ul_buffer_info[LCGID0] > + UE_info->UE_template[pCCid2][UE_id2].ul_buffer_info[LCGID0]) return -1; - if (UE_list->UE_template[pCCid1][UE_id1].ul_buffer_info[LCGID0] < - UE_list->UE_template[pCCid2][UE_id2].ul_buffer_info[LCGID0]) + if (UE_info->UE_template[pCCid1][UE_id1].ul_buffer_info[LCGID0] < + UE_info->UE_template[pCCid2][UE_id2].ul_buffer_info[LCGID0]) return 1; - int bytes_to_schedule1 = UE_list->UE_template[pCCid1][UE_id1].estimated_ul_buffer - UE_list->UE_template[pCCid1][UE_id1].scheduled_ul_bytes; + int bytes_to_schedule1 = UE_info->UE_template[pCCid1][UE_id1].estimated_ul_buffer - UE_info->UE_template[pCCid1][UE_id1].scheduled_ul_bytes; if (bytes_to_schedule1 < 0) bytes_to_schedule1 = 0; - int bytes_to_schedule2 = UE_list->UE_template[pCCid2][UE_id2].estimated_ul_buffer - UE_list->UE_template[pCCid2][UE_id2].scheduled_ul_bytes; + int bytes_to_schedule2 = UE_info->UE_template[pCCid2][UE_id2].estimated_ul_buffer - UE_info->UE_template[pCCid2][UE_id2].scheduled_ul_bytes; if (bytes_to_schedule2 < 0) bytes_to_schedule2 = 0; @@ -775,20 +774,20 @@ static int ue_ul_compare(const void *_a, const void *_b, void *_params) { if (bytes_to_schedule1 < bytes_to_schedule2) return 1; - if (UE_list->UE_template[pCCid1][UE_id1].pre_assigned_mcs_ul > - UE_list->UE_template[pCCid2][UE_id2].pre_assigned_mcs_ul) + if (UE_info->UE_template[pCCid1][UE_id1].pre_assigned_mcs_ul > + UE_info->UE_template[pCCid2][UE_id2].pre_assigned_mcs_ul) return -1; - if (UE_list->UE_template[pCCid1][UE_id1].pre_assigned_mcs_ul < - UE_list->UE_template[pCCid2][UE_id2].pre_assigned_mcs_ul) + if (UE_info->UE_template[pCCid1][UE_id1].pre_assigned_mcs_ul < + UE_info->UE_template[pCCid2][UE_id2].pre_assigned_mcs_ul) return 1; - if (UE_list->UE_sched_ctrl[UE_id1].cqi_req_timer > - UE_list->UE_sched_ctrl[UE_id2].cqi_req_timer) + if (UE_info->UE_sched_ctrl[UE_id1].cqi_req_timer > + UE_info->UE_sched_ctrl[UE_id2].cqi_req_timer) return -1; - if (UE_list->UE_sched_ctrl[UE_id1].cqi_req_timer < - UE_list->UE_sched_ctrl[UE_id2].cqi_req_timer) + if (UE_info->UE_sched_ctrl[UE_id1].cqi_req_timer < + UE_info->UE_sched_ctrl[UE_id2].cqi_req_timer) return 1; return 0; @@ -808,11 +807,11 @@ void sort_ue_ul(module_id_t module_idP, int list[MAX_MOBILES_PER_ENB]; 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_info_t *UE_info = &RC.mac[module_idP]->UE_info; UE_sched_ctrl_t *UE_scheduling_control = NULL; for (int i = 0; i < MAX_MOBILES_PER_ENB; i++) { - UE_scheduling_control = &(UE_list->UE_sched_ctrl[i]); + UE_scheduling_control = &(UE_info->UE_sched_ctrl[i]); /* Check CDRX configuration and if UE is in active time for this subframe */ if (UE_scheduling_control->cdrx_configured == TRUE) { @@ -824,9 +823,9 @@ void sort_ue_ul(module_id_t module_idP, rntiTable[i] = UE_RNTI(module_idP, i); // Valid element and is not the actual CC_id in the list - if (UE_list->active[i] == TRUE && + if (UE_info->active[i] == TRUE && rntiTable[i] != NOT_A_RNTI && - UE_list->UE_sched_ctrl[i].ul_out_of_sync != 1 && + UE_info->UE_sched_ctrl[i].ul_out_of_sync != 1 && ue_ul_slice_membership(module_idP, i, slice_idx)) { list[list_size++] = i; // Add to list } @@ -836,12 +835,12 @@ void sort_ue_ul(module_id_t module_idP, if (list_size) { // At mimimum one list element for (int i = 0; i < list_size - 1; i++) { - UE_list->next_ul[list[i]] = list[i + 1]; + UE_info->list.next[list[i]] = list[i + 1]; } - UE_list->next_ul[list[list_size - 1]] = -1; - UE_list->head_ul = list[0]; + UE_info->list.next[list[list_size - 1]] = -1; + UE_info->list.head = list[0]; } else { // No element - UE_list->head_ul = -1; + UE_info->list.head = -1; } } diff --git a/openair2/LAYER2/openair2_proc.c b/openair2/LAYER2/openair2_proc.c index 32c4d9788c..bbdc55e036 100644 --- a/openair2/LAYER2/openair2_proc.c +++ b/openair2/LAYER2/openair2_proc.c @@ -91,12 +91,12 @@ int dump_eNB_l2_stats(char *buffer, int length) { number_of_cards=NB_eNB_INST; #endif eNB_MAC_INST *eNB; - UE_list_t *UE_list; + UE_info_t *UE_info; for (eNB_id=0; eNB_idUE_list; + UE_info = &eNB->UE_info; for (CC_id=0 ; CC_id < MAX_NUM_CCs; CC_id++) { eNB->eNB_stats[CC_id].dlsch_bitrate= 0; @@ -141,76 +141,76 @@ int dump_eNB_l2_stats(char *buffer, int length) { len += sprintf(&buffer[len],"\n"); - for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) { - for (i=0; inumactiveCCs[UE_id]; i++) { - CC_id=UE_list->ordered_CCids[i][UE_id]; - UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_bitrate=((UE_list->eNB_UE_stats[CC_id][UE_id].TBS*8)/((eNB->frame + 1)*10)); - UE_list->eNB_UE_stats[CC_id][UE_id].total_dlsch_bitrate= ((UE_list->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes*8)/((eNB->frame + 1)*10)); - UE_list->eNB_UE_stats[CC_id][UE_id].total_overhead_bytes+= UE_list->eNB_UE_stats[CC_id][UE_id].overhead_bytes; - UE_list->eNB_UE_stats[CC_id][UE_id].avg_overhead_bytes=((UE_list->eNB_UE_stats[CC_id][UE_id].total_overhead_bytes*8)/((eNB->frame + 1)*10)); - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_bitrate=((UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS*8)/((eNB->frame + 1)*10)); - UE_list->eNB_UE_stats[CC_id][UE_id].total_ulsch_bitrate= ((UE_list->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes_rx*8)/((eNB->frame + 1)*10)); + for (UE_id=UE_info->list.head; UE_id>=0; UE_id=UE_info->list.next[UE_id]) { + for (i=0; inumactiveCCs[UE_id]; i++) { + CC_id=UE_info->ordered_CCids[i][UE_id]; + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_bitrate=((UE_info->eNB_UE_stats[CC_id][UE_id].TBS*8)/((eNB->frame + 1)*10)); + UE_info->eNB_UE_stats[CC_id][UE_id].total_dlsch_bitrate= ((UE_info->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes*8)/((eNB->frame + 1)*10)); + UE_info->eNB_UE_stats[CC_id][UE_id].total_overhead_bytes+= UE_info->eNB_UE_stats[CC_id][UE_id].overhead_bytes; + UE_info->eNB_UE_stats[CC_id][UE_id].avg_overhead_bytes=((UE_info->eNB_UE_stats[CC_id][UE_id].total_overhead_bytes*8)/((eNB->frame + 1)*10)); + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_bitrate=((UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_TBS*8)/((eNB->frame + 1)*10)); + UE_info->eNB_UE_stats[CC_id][UE_id].total_ulsch_bitrate= ((UE_info->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes_rx*8)/((eNB->frame + 1)*10)); len += sprintf(&buffer[len],"[MAC] UE %d (DLSCH),status %s, RNTI %x : CQI %d, MCS1 %d, MCS2 %d, RB (tx %d, retx %d, total %d), ncce (tx %d, retx %d) \n", UE_id, - map_int_to_str(rrc_status_names, UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status), - UE_list->eNB_UE_stats[CC_id][UE_id].crnti, - UE_list->UE_sched_ctrl[UE_id].dl_cqi[CC_id], - UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1, - UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2, - UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used, - UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_retx, - UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used, - UE_list->eNB_UE_stats[CC_id][UE_id].ncce_used, - UE_list->eNB_UE_stats[CC_id][UE_id].ncce_used_retx + map_int_to_str(rrc_status_names, UE_info->eNB_UE_stats[CC_id][UE_id].rrc_status), + UE_info->eNB_UE_stats[CC_id][UE_id].crnti, + UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id], + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1, + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2, + UE_info->eNB_UE_stats[CC_id][UE_id].rbs_used, + UE_info->eNB_UE_stats[CC_id][UE_id].rbs_used_retx, + UE_info->eNB_UE_stats[CC_id][UE_id].total_rbs_used, + UE_info->eNB_UE_stats[CC_id][UE_id].ncce_used, + UE_info->eNB_UE_stats[CC_id][UE_id].ncce_used_retx ); len += sprintf(&buffer[len], "[MAC] DLSCH bitrate (TTI %d, avg %d), Transmitted bytes " "(TTI %d, total %"PRIu64"), Total Transmitted PDU %d, Overhead " "(TTI %"PRIu64", total %"PRIu64", avg %"PRIu64")\n", - UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_bitrate, - UE_list->eNB_UE_stats[CC_id][UE_id].total_dlsch_bitrate, - UE_list->eNB_UE_stats[CC_id][UE_id].TBS, - UE_list->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes, - UE_list->eNB_UE_stats[CC_id][UE_id].total_num_pdus, - UE_list->eNB_UE_stats[CC_id][UE_id].overhead_bytes, - UE_list->eNB_UE_stats[CC_id][UE_id].total_overhead_bytes, - UE_list->eNB_UE_stats[CC_id][UE_id].avg_overhead_bytes + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_bitrate, + UE_info->eNB_UE_stats[CC_id][UE_id].total_dlsch_bitrate, + UE_info->eNB_UE_stats[CC_id][UE_id].TBS, + UE_info->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes, + UE_info->eNB_UE_stats[CC_id][UE_id].total_num_pdus, + UE_info->eNB_UE_stats[CC_id][UE_id].overhead_bytes, + UE_info->eNB_UE_stats[CC_id][UE_id].total_overhead_bytes, + UE_info->eNB_UE_stats[CC_id][UE_id].avg_overhead_bytes ); len += sprintf(&buffer[len],"[MAC] UE %d (ULSCH), Status %s, Failute timer %d, RNTI %x : snr (%d, target %d), MCS (pre %d, post %d), RB (rx %d, retx %d, total %d), Current TBS %d \n", UE_id, - map_int_to_str(rrc_status_names, UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status), - UE_list->UE_sched_ctrl[UE_id].ul_failure_timer, - UE_list->eNB_UE_stats[CC_id][UE_id].crnti, - UE_list->eNB_UE_stats[CC_id][UE_id].snr, - UE_list->eNB_UE_stats[CC_id][UE_id].target_snr, - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1, - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2, - UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_rx, - UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_retx_rx, - UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx, - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_TBS + map_int_to_str(rrc_status_names, UE_info->eNB_UE_stats[CC_id][UE_id].rrc_status), + UE_info->UE_sched_ctrl[UE_id].ul_failure_timer, + UE_info->eNB_UE_stats[CC_id][UE_id].crnti, + UE_info->eNB_UE_stats[CC_id][UE_id].snr, + UE_info->eNB_UE_stats[CC_id][UE_id].target_snr, + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1, + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2, + UE_info->eNB_UE_stats[CC_id][UE_id].rbs_used_rx, + UE_info->eNB_UE_stats[CC_id][UE_id].rbs_used_retx_rx, + UE_info->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx, + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_TBS ); len += sprintf(&buffer[len], "[MAC] ULSCH bitrate (TTI %d, avg %d), received bytes (total %"PRIu64")," "Total received PDU %d, Total errors %d\n", - UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_bitrate, - UE_list->eNB_UE_stats[CC_id][UE_id].total_ulsch_bitrate, - UE_list->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes_rx, - UE_list->eNB_UE_stats[CC_id][UE_id].total_num_pdus_rx, - UE_list->eNB_UE_stats[CC_id][UE_id].num_errors_rx); - len+= sprintf(&buffer[len],"[MAC] Received PHR PH = %d (db)\n", UE_list->UE_template[CC_id][UE_id].phr_info); + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_bitrate, + UE_info->eNB_UE_stats[CC_id][UE_id].total_ulsch_bitrate, + UE_info->eNB_UE_stats[CC_id][UE_id].total_pdu_bytes_rx, + UE_info->eNB_UE_stats[CC_id][UE_id].total_num_pdus_rx, + UE_info->eNB_UE_stats[CC_id][UE_id].num_errors_rx); + len+= sprintf(&buffer[len],"[MAC] Received PHR PH = %d (db)\n", UE_info->UE_template[CC_id][UE_id].phr_info); len+= sprintf(&buffer[len],"[MAC] Estimated size LCGID[0][1][2][3] = %u %u %u %u\n", - UE_list->UE_template[CC_id][UE_id].ul_buffer_info[LCGID0], - UE_list->UE_template[CC_id][UE_id].ul_buffer_info[LCGID1], - UE_list->UE_template[CC_id][UE_id].ul_buffer_info[LCGID2], - UE_list->UE_template[CC_id][UE_id].ul_buffer_info[LCGID3] + UE_info->UE_template[CC_id][UE_id].ul_buffer_info[LCGID0], + UE_info->UE_template[CC_id][UE_id].ul_buffer_info[LCGID1], + UE_info->UE_template[CC_id][UE_id].ul_buffer_info[LCGID2], + UE_info->UE_template[CC_id][UE_id].ul_buffer_info[LCGID3] ); } PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, eNB_id, ENB_FLAG_YES, - UE_list->eNB_UE_stats[0][UE_id].crnti,//UE_PCCID(eNB_id,UE_id)][UE_id].crnti, + UE_info->eNB_UE_stats[0][UE_id].crnti,//UE_PCCID(eNB_id,UE_id)][UE_id].crnti, eNB->frame, eNB->subframe, eNB_id); @@ -509,7 +509,7 @@ int openair2_stats_read(char *buffer, char **my_buffer, off_t off, int length) { for(i=1; i<=NB_CNX_CH; i++) { if (CH_mac_inst[Mod_id].Dcch_lchan[i].Active==1) { len+=sprintf(&buffer[len],"\nMR index %u: DL SINR (feedback) %d dB, CQI: %s\n\n", - i,//CH_rrc_inst[Mod_id].Info.UE_list[i].L2_id[0], + i,//CH_rrc_inst[Mod_id].Info.UE_info[i].L2_id[0], CH_mac_inst[Mod_id].Def_meas[i].Wideband_sinr, print_cqi(CH_mac_inst[Mod_id].Def_meas[i].cqi)); len+=sprintf(&buffer[len], diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index 1d25bf180a..dc9183a87d 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -656,7 +656,7 @@ rrc_eNB_get_next_transaction_identifier( // AssertFatal(enb_mod_idP < NB_eNB_INST, "eNB index invalid (%d/%d)!", enb_mod_idP, NB_eNB_INST); // // for (i = 0; i < MAX_MOBILES_PER_ENB; i++) { -// if (RC.rrc[enb_mod_idP]->Info.UE_list[i] == UE_identity) { +// if (RC.rrc[enb_mod_idP]->Info.UE_info[i] == UE_identity) { // // UE_identity already registered // reg = TRUE; // break; @@ -1476,9 +1476,9 @@ rrc_eNB_generate_RRCConnectionReestablishment( if (UE_id != -1) { /* Activate reject timer, if RRCComplete not received after 10 frames, reject UE */ - RC.mac[module_id]->UE_list.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 1; + RC.mac[module_id]->UE_info.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 1; /* Reject UE after 10 frames, LTE_RRCConnectionReestablishmentReject is triggered */ - RC.mac[module_id]->UE_list.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer_thres = 100; + RC.mac[module_id]->UE_info.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer_thres = 100; } else { LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Generating LTE_RRCConnectionReestablishment without UE_id(MAC) rnti %x\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), @@ -2086,8 +2086,8 @@ rrc_eNB_generate_RRCConnectionReestablishmentReject( int UE_id = find_UE_id(ctxt_pP->module_id, ctxt_pP->rnti); if(UE_id != -1) { - RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 1; - RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer_thres = 20; + RC.mac[ctxt_pP->module_id]->UE_info.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 1; + RC.mac[ctxt_pP->module_id]->UE_info.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer_thres = 20; } else { LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Generating LTE_RRCConnectionReestablishmentReject without UE_id(MAC) rnti %x\n", @@ -6168,7 +6168,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( return; } - UE_sched_ctrl_t *UE_scheduling_control = &(RC.mac[module_id]->UE_list.UE_sched_ctrl[UE_id_mac]); + UE_sched_ctrl_t *UE_scheduling_control = &(RC.mac[module_id]->UE_info.UE_sched_ctrl[UE_id_mac]); if (UE_scheduling_control->cdrx_waiting_ack == TRUE) { UE_scheduling_control->cdrx_waiting_ack = FALSE; @@ -6831,12 +6831,12 @@ rrc_eNB_decode_ccch( break; } - if((RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer > 0) && - (RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer_thres > 20)) { + if((RC.mac[ctxt_pP->module_id]->UE_info.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer > 0) && + (RC.mac[ctxt_pP->module_id]->UE_info.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer_thres > 20)) { LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" RCConnectionReestablishmentComplete(Previous) don't receive, delete the c-rnti UE\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); - RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 1000; + RC.mac[ctxt_pP->module_id]->UE_info.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 1000; rrc_eNB_previous_SRB2(ue_context_p); ue_context_p->ue_context.ue_reestablishment_timer = 0; } @@ -6862,12 +6862,12 @@ rrc_eNB_decode_ccch( break; } - if((RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer > 0) && - (RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer_thres > 20)) { + if((RC.mac[ctxt_pP->module_id]->UE_info.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer > 0) && + (RC.mac[ctxt_pP->module_id]->UE_info.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer_thres > 20)) { LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" RCConnectionReestablishmentComplete(Previous) don't receive, delete the Previous UE\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); - RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 1000; + RC.mac[ctxt_pP->module_id]->UE_info.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 1000; rrc_eNB_previous_SRB2(ue_context_p); ue_context_p->ue_context.ue_reestablishment_timer = 0; } @@ -7439,12 +7439,12 @@ rrc_eNB_decode_dcch( AssertFatal(!NODE_IS_CU(RC.rrc[ctxt_pP->module_id]->node_type), "CU cannot decode DCCH: no access to RC.mac[]\n"); - if(RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].crnti_reconfigurationcomplete_flag == 1) { + if(RC.mac[ctxt_pP->module_id]->UE_info.UE_sched_ctrl[UE_id].crnti_reconfigurationcomplete_flag == 1) { LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_RECONFIGURED (dedicated DRB, xid %ld) C-RNTI Complete\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ul_dcch_msg->message.choice.c1.choice.rrcConnectionReconfigurationComplete.rrc_TransactionIdentifier); dedicated_DRB = 2; - RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].crnti_reconfigurationcomplete_flag = 0; + RC.mac[ctxt_pP->module_id]->UE_info.UE_sched_ctrl[UE_id].crnti_reconfigurationcomplete_flag = 0; } } else if (ue_context_p->ue_context.Status == RRC_HO_EXECUTION) { int16_t UE_id = find_UE_id(ctxt_pP->module_id, ctxt_pP->rnti); @@ -7459,7 +7459,7 @@ rrc_eNB_decode_dcch( 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; + RC.mac[ctxt_pP->module_id]->UE_info.UE_sched_ctrl[UE_id].crnti_reconfigurationcomplete_flag = 0; ue_context_p->ue_context.Status = RRC_RECONFIGURED; if(ue_context_p->ue_context.handover_info) { @@ -7637,7 +7637,7 @@ rrc_eNB_decode_dcch( break; } - RC.mac[ctxt_pP->module_id]->UE_list.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 0; + RC.mac[ctxt_pP->module_id]->UE_info.UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 0; ue_context_p->ue_context.reestablishment_xid = -1; if (ul_dcch_msg->message.choice.c1.choice.rrcConnectionReestablishmentComplete.criticalExtensions.present == diff --git a/openair2/RRC/LTE/utils.c b/openair2/RRC/LTE/utils.c index 08637e0e67..c84a2be476 100644 --- a/openair2/RRC/LTE/utils.c +++ b/openair2/RRC/LTE/utils.c @@ -60,11 +60,11 @@ uint8_t rrc_find_free_ue_index(uint8_t Mod_id) { uint16_t i; for(i=1; i<=NB_CNX_CH; i++) - if ( (CH_rrc_inst[Mod_id].Info.UE_list[i][0] == 0) && - (CH_rrc_inst[Mod_id].Info.UE_list[i][1] == 0) && - (CH_rrc_inst[Mod_id].Info.UE_list[i][2] == 0) && - (CH_rrc_inst[Mod_id].Info.UE_list[i][3] == 0) && - (CH_rrc_inst[Mod_id].Info.UE_list[i][4] == 0)) { + if ( (CH_rrc_inst[Mod_id].Info.UE_info[i][0] == 0) && + (CH_rrc_inst[Mod_id].Info.UE_info[i][1] == 0) && + (CH_rrc_inst[Mod_id].Info.UE_info[i][2] == 0) && + (CH_rrc_inst[Mod_id].Info.UE_info[i][3] == 0) && + (CH_rrc_inst[Mod_id].Info.UE_info[i][4] == 0)) { return i; } @@ -78,7 +78,7 @@ unsigned short rrc_find_ue_index(unsigned char Mod_id, L2_ID Mac_id) { unsigned char i; /* for(i=0;i<=NB_CNX_CH;i++) - if( bcmp(Mac_id.L2_id,CH_rrc_inst[Mod_id].Info.UE_list[i].L2_id,sizeof(L2_ID))==0) + if( bcmp(Mac_id.L2_id,CH_rrc_inst[Mod_id].Info.UE_info[i].L2_id,sizeof(L2_ID))==0) return i; return i; */ @@ -167,7 +167,7 @@ unsigned char rrc_is_mobile_already_associated(uint8_t Mod_id, L2_ID Mac_id) { /* unsigned char i; for(i=0;ieNB_list[0]->Mod_id]->UE_list.eNB_UE_stats, sizeof(eNB_UE_STATS)*MAX_NUM_CCs*NUMBER_OF_UE_MAX); - // memcpy(&pre_scd_activeUE, &RC.mac[ru->eNB_list[0]->Mod_id]->UE_list.active, sizeof(boolean_t)*NUMBER_OF_UE_MAX); - memcpy(&pre_scd_eNB_UE_stats,&RC.mac[0]->UE_list.eNB_UE_stats, sizeof(eNB_UE_STATS)*MAX_NUM_CCs*NUMBER_OF_UE_MAX); - memcpy(&pre_scd_activeUE, &RC.mac[0]->UE_list.active, sizeof(boolean_t)*NUMBER_OF_UE_MAX); + // memcpy(&pre_scd_eNB_UE_stats,&RC.mac[ru->eNB_list[0]->Mod_id]->UE_info.eNB_UE_stats, sizeof(eNB_UE_STATS)*MAX_NUM_CCs*NUMBER_OF_UE_MAX); + // memcpy(&pre_scd_activeUE, &RC.mac[ru->eNB_list[0]->Mod_id]->UE_info.active, sizeof(boolean_t)*NUMBER_OF_UE_MAX); + memcpy(&pre_scd_eNB_UE_stats,&RC.mac[0]->UE_info.eNB_UE_stats, sizeof(eNB_UE_STATS)*MAX_NUM_CCs*NUMBER_OF_UE_MAX); + memcpy(&pre_scd_activeUE, &RC.mac[0]->UE_info.active, sizeof(boolean_t)*NUMBER_OF_UE_MAX); AssertFatal((ret= pthread_mutex_lock(&ru->proc.mutex_pre_scd))==0,"[eNB] error locking proc mutex for eNB pre scd, return %d\n",ret); ru->proc.instance_pre_scd++; diff --git a/targets/RT/USER/lte-ru.c b/targets/RT/USER/lte-ru.c index e6364cad23..f2038d4ed3 100644 --- a/targets/RT/USER/lte-ru.c +++ b/targets/RT/USER/lte-ru.c @@ -1866,8 +1866,8 @@ static void *ru_thread( void *param ) { #if defined(PRE_SCD_THREAD) new_dlsch_ue_select_tbl_in_use = dlsch_ue_select_tbl_in_use; dlsch_ue_select_tbl_in_use = !dlsch_ue_select_tbl_in_use; - memcpy(&pre_scd_eNB_UE_stats,&RC.mac[ru->eNB_list[0]->Mod_id]->UE_list.eNB_UE_stats, sizeof(eNB_UE_STATS)*MAX_NUM_CCs*NUMBER_OF_UE_MAX); - memcpy(&pre_scd_activeUE, &RC.mac[ru->eNB_list[0]->Mod_id]->UE_list.active, sizeof(boolean_t)*NUMBER_OF_UE_MAX); + memcpy(&pre_scd_eNB_UE_stats,&RC.mac[ru->eNB_list[0]->Mod_id]->UE_info.eNB_UE_stats, sizeof(eNB_UE_STATS)*MAX_NUM_CCs*NUMBER_OF_UE_MAX); + memcpy(&pre_scd_activeUE, &RC.mac[ru->eNB_list[0]->Mod_id]->UE_info.active, sizeof(boolean_t)*NUMBER_OF_UE_MAX); AssertFatal((ret=pthread_mutex_lock(&ru->proc.mutex_pre_scd))==0,"[eNB] error locking proc mutex for eNB pre scd\n"); ru->proc.instance_pre_scd++; diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 0b365ea938..59534fe71f 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -435,7 +435,7 @@ int restart_L1L2(module_id_t enb_id) { set_function_spec_param(RC.ru[enb_id]); /* reset the list of connected UEs in the MAC, since in this process with * loose all UEs (have to reconnect) */ - init_UE_list(&RC.mac[enb_id]->UE_list); + init_UE_info(&RC.mac[enb_id]->UE_info); LOG_I(ENB_APP, "attempting to create ITTI tasks\n"); if (itti_create_task (TASK_RRC_ENB, rrc_enb_task, NULL) < 0) { From 5420e740323240a7dca18015e1a733e1a03a8254 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 1 Apr 2020 11:12:50 +0200 Subject: [PATCH 112/240] Efficient RB estimation through binary search --- openair1/PHY/LTE_TRANSPORT/lte_mcs.c | 29 +++++++++++++++++++ .../LTE_TRANSPORT/transport_common_proto.h | 2 ++ 2 files changed, 31 insertions(+) diff --git a/openair1/PHY/LTE_TRANSPORT/lte_mcs.c b/openair1/PHY/LTE_TRANSPORT/lte_mcs.c index c13876f29a..6144b978bf 100644 --- a/openair1/PHY/LTE_TRANSPORT/lte_mcs.c +++ b/openair1/PHY/LTE_TRANSPORT/lte_mcs.c @@ -94,6 +94,35 @@ unsigned char I_TBS2I_MCS(unsigned char I_TBS) { return I_MCS; } +uint16_t find_nb_rb_DL(uint8_t mcs, uint32_t bytes, uint16_t nb_rb_max, uint16_t rb_gran) { + if (bytes == 0 || mcs > 28 || nb_rb_max == 0) + return 0; + const uint32_t bits = bytes << 3; + const unsigned char I_TBS = get_I_TBS(mcs); + + uint32_t TBS = TBStable[I_TBS][nb_rb_max - 1]; + if (bits >= TBS) // is nb_rb_max too small? + return nb_rb_max; + + TBS = TBStable[I_TBS][rb_gran - 1]; + if (bits <= TBS) // is rb_gran RB enough? + return rb_gran; + + nb_rb_max += nb_rb_max % rb_gran; // round up to full RBG + uint16_t hi = nb_rb_max/rb_gran - 1; + uint16_t lo = 0; + uint16_t p = (hi + lo) / 2; + for (; lo + 1 != hi; p = (hi + lo) / 2) { + const uint16_t rbi = (p + 1) * rb_gran - 1; // convert "RBG" -> RB + TBS = TBStable[I_TBS][rbi]; + if (bits <= TBS) // need less RBs + hi = p; + else // need more RBs + lo = p; + } + return (hi + 1) * rb_gran; +} + uint32_t get_TBS_DL(uint8_t mcs, uint16_t nb_rb) { uint32_t TBS; diff --git a/openair1/PHY/LTE_TRANSPORT/transport_common_proto.h b/openair1/PHY/LTE_TRANSPORT/transport_common_proto.h index 1d7aa598af..e4f5d9a17f 100644 --- a/openair1/PHY/LTE_TRANSPORT/transport_common_proto.h +++ b/openair1/PHY/LTE_TRANSPORT/transport_common_proto.h @@ -60,6 +60,8 @@ unsigned char get_I_TBS_UL(unsigned char I_MCS); @return Transport block size */ uint32_t get_TBS_DL(uint8_t mcs, uint16_t nb_rb); +uint16_t find_nb_rb_DL(uint8_t mcs, uint32_t bytes, uint16_t nb_rb_max, uint16_t rb_gran); + /** \brief Compute Q (modulation order) based on uplink I_MCS. Implements table 7.1.7.1-1 from 36.213. @param I_MCS @param nb_rb From 236b17ce81c32785b3caaf1bfc36970260f502c2 Mon Sep 17 00:00:00 2001 From: Gabriele Perrone Date: Wed, 1 Apr 2020 18:27:34 +0200 Subject: [PATCH 113/240] cleanup of main*.py names and push of minor changes on main.py and html.py --- ci-scripts/html.py | 7 +- ci-scripts/main-cnt-mod.py | 4927 ----------------------------- ci-scripts/main-index-to-class.py | 4921 ---------------------------- ci-scripts/main.py | 1769 ++--------- ci-scripts/main_enb.py | 3680 --------------------- 5 files changed, 344 insertions(+), 14960 deletions(-) delete mode 100644 ci-scripts/main-cnt-mod.py delete mode 100644 ci-scripts/main-index-to-class.py delete mode 100644 ci-scripts/main_enb.py diff --git a/ci-scripts/html.py b/ci-scripts/html.py index 3a520d30e3..ccd89eb577 100644 --- a/ci-scripts/html.py +++ b/ci-scripts/html.py @@ -48,12 +48,12 @@ class HTMLManagement(): self.htmlHeaderCreated = False self.htmlFooterCreated = False + self.ranAllowMerge = False + self.nbTestXMLfiles = 0 self.htmlTabRefs = [] self.htmlTabNames = [] self.htmlTabIcons = [] self.testXMLfiles = [] - self.htmlHeaderCreated = False - self.htmlFooterCreated = False #----------------------------------------------------------- # Setters and Getters @@ -110,6 +110,9 @@ class HTMLManagement(): def SetnbTestXMLfiles(self, nb): self.nbTestXMLfiles = nb + def GetnbTestXMLfiles(self): + return self.nbTestXMLfiles + def SettestXMLfiles(self, xmlFile): self.testXMLfiles.append(xmlFile) diff --git a/ci-scripts/main-cnt-mod.py b/ci-scripts/main-cnt-mod.py deleted file mode 100644 index 439dc0cfe4..0000000000 --- a/ci-scripts/main-cnt-mod.py +++ /dev/null @@ -1,4927 +0,0 @@ -# /* -# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more -# * contributor license agreements. See the NOTICE file distributed with -# * this work for additional information regarding copyright ownership. -# * The OpenAirInterface Software Alliance licenses this file to You under -# * the OAI Public License, Version 1.1 (the "License"); you may not use this file -# * except in compliance with the License. -# * You may obtain a copy of the License at -# * -# * http://www.openairinterface.org/?page_id=698 -# * -# * Unless required by applicable law or agreed to in writing, software -# * distributed under the License is distributed on an "AS IS" BASIS, -# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# * See the License for the specific language governing permissions and -# * limitations under the License. -# *------------------------------------------------------------------------------- -# * For more information about the OpenAirInterface (OAI) Software Alliance: -# * contact@openairinterface.org -# */ -#--------------------------------------------------------------------- -# Python for CI of OAI-eNB + COTS-UE -# -# Required Python Version -# Python 3.x -# -# Required Python Package -# pexpect -#--------------------------------------------------------------------- - -#----------------------------------------------------------- -# Version -#----------------------------------------------------------- -Version = '0.1' - -#----------------------------------------------------------- -# Constants -#----------------------------------------------------------- -ALL_PROCESSES_OK = 0 -ENB_PROCESS_FAILED = -1 -ENB_PROCESS_OK = +1 -ENB_PROCESS_SEG_FAULT = -11 -ENB_PROCESS_ASSERTION = -12 -ENB_PROCESS_REALTIME_ISSUE = -13 -ENB_PROCESS_NOLOGFILE_TO_ANALYZE = -14 -ENB_PROCESS_SLAVE_RRU_NOT_SYNCED = -15 -HSS_PROCESS_FAILED = -2 -HSS_PROCESS_OK = +2 -MME_PROCESS_FAILED = -3 -MME_PROCESS_OK = +3 -SPGW_PROCESS_FAILED = -4 -SPGW_PROCESS_OK = +4 -UE_IP_ADDRESS_ISSUE = -5 -OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE = -20 -OAI_UE_PROCESS_COULD_NOT_SYNC = -21 -OAI_UE_PROCESS_ASSERTION = -22 -OAI_UE_PROCESS_FAILED = -23 -OAI_UE_PROCESS_NO_TUNNEL_INTERFACE = -24 -OAI_UE_PROCESS_OK = +6 - -UE_STATUS_DETACHED = 0 -UE_STATUS_DETACHING = 1 -UE_STATUS_ATTACHING = 2 -UE_STATUS_ATTACHED = 3 - -X2_HO_REQ_STATE__IDLE = 0 -X2_HO_REQ_STATE__TARGET_RECEIVES_REQ = 1 -X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE = 2 -X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ = 3 -X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK = 10 - -#----------------------------------------------------------- -# Import -#----------------------------------------------------------- -import sys # arg -import re # reg -import pexpect # pexpect -import time # sleep -import os -import subprocess -import xml.etree.ElementTree as ET -import logging -import datetime -import signal -from multiprocessing import Process, Lock, SimpleQueue -logging.basicConfig( - level=logging.DEBUG, - format="[%(asctime)s] %(name)s:%(levelname)s: %(message)s" -) - -#----------------------------------------------------------- -# Class Declaration -#----------------------------------------------------------- -class SSHConnection(): - def __init__(self): - self.prematureExit = False - self.ranRepository = '' - self.ranBranch = '' - self.ranAllowMerge = False - self.ranCommitID = '' - self.ranTargetBranch = '' - self.eNBIPAddress = '' - self.eNBUserName = '' - self.eNBPassword = '' - self.eNBSourceCodePath = '' - self.EPCIPAddress = '' - self.EPCUserName = '' - self.EPCPassword = '' - self.eNB1IPAddress = '' - self.eNB1UserName = '' - self.eNB1Password = '' - self.eNB1SourceCodePath = '' - self.eNB2IPAddress = '' - self.eNB2UserName = '' - self.eNB2Password = '' - self.eNB2SourceCodePath = '' - self.EPCSourceCodePath = '' - self.EPCType = '' - self.EPC_PcapFileName = '' - self.ADBIPAddress = '' - self.ADBUserName = '' - self.ADBPassword = '' - self.ADBCentralized = True - self.testCase_id = '' - self.testXMLfiles = [] - self.nbTestXMLfiles = 0 - self.desc = '' - self.Build_eNB_args = '' - self.backgroundBuild = False - self.backgroundBuildTestId = ['', '', ''] - self.Initialize_eNB_args = '' - self.eNB_instance = '' - self.eNB_serverId = '' - self.eNBLogFiles = ['', '', ''] - self.eNBOptions = ['', '', ''] - self.ping_args = '' - self.ping_packetloss_threshold = '' - self.iperf_args = '' - self.iperf_packetloss_threshold = '' - self.iperf_profile = '' - self.nbMaxUEtoAttach = -1 - self.UEDevices = [] - self.UEDevicesStatus = [] - self.UEDevicesRemoteServer = [] - self.UEDevicesRemoteUser = [] - self.UEDevicesOffCmd = [] - self.UEDevicesOnCmd = [] - self.UEDevicesRebootCmd = [] - self.CatMDevices = [] - self.UEIPAddresses = [] - self.htmlFile = '' - self.htmlHeaderCreated = False - self.htmlFooterCreated = False - self.htmlUEConnected = -1 - self.htmleNBFailureMsg = '' - self.htmlUEFailureMsg = '' - self.picocom_closure = False - self.idle_sleep_time = 0 - self.x2_ho_options = 'network' - self.x2NbENBs = 0 - self.x2ENBBsIds = [] - self.x2ENBConnectedUEs = [] - self.htmlTabRefs = [] - self.htmlTabNames = [] - self.htmlTabIcons = [] - # repeatCounts was a list --> becomes an integer - self.repeatCounts = 1 - self.finalStatus = False - self.OsVersion = '' - self.KernelVersion = '' - self.UhdVersion = '' - self.UsrpBoard = '' - self.CpuNb = '' - self.CpuModel = '' - self.CpuMHz = '' - self.UEIPAddress = '' - self.UEUserName = '' - self.UEPassword = '' - self.UE_instance = '' - self.UESourceCodePath = '' - self.UELogFile = '' - self.Build_OAI_UE_args = '' - self.Initialize_OAI_UE_args = '' - self.flexranCtrlInstalled = False - self.flexranCtrlStarted = False - self.expectedNbOfConnectedUEs = 0 - self.startTime = 0 - - def open(self, ipaddress, username, password): - count = 0 - connect_status = False - while count < 4: - self.ssh = pexpect.spawn('ssh', [username + '@' + ipaddress], timeout = 5) - self.sshresponse = self.ssh.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', 'Last login', pexpect.EOF, pexpect.TIMEOUT]) - if self.sshresponse == 0: - self.ssh.sendline('yes') - self.ssh.expect('password:') - self.ssh.sendline(password) - self.sshresponse = self.ssh.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if self.sshresponse == 0: - count = 10 - connect_status = True - else: - logging.debug('self.sshresponse = ' + str(self.sshresponse)) - elif self.sshresponse == 1: - self.ssh.sendline(password) - self.sshresponse = self.ssh.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if self.sshresponse == 0: - count = 10 - connect_status = True - else: - logging.debug('self.sshresponse = ' + str(self.sshresponse)) - elif self.sshresponse == 2: - # Checking if we are really on the remote client defined by its IP address - self.command('stdbuf -o0 ifconfig | egrep --color=never "inet addr:|inet "', '\$', 5) - result = re.search(str(ipaddress), str(self.ssh.before)) - if result is None: - self.close() - else: - count = 10 - connect_status = True - else: - # debug output - logging.debug(str(self.ssh.before)) - logging.debug('self.sshresponse = ' + str(self.sshresponse)) - # adding a tempo when failure - if not connect_status: - time.sleep(1) - count += 1 - if connect_status: - pass - else: - sys.exit('SSH Connection Failed') - - def command(self, commandline, expectedline, timeout): - logging.debug(commandline) - self.ssh.timeout = timeout - self.ssh.sendline(commandline) - self.sshresponse = self.ssh.expect([expectedline, pexpect.EOF, pexpect.TIMEOUT]) - if self.sshresponse == 0: - return 0 - elif self.sshresponse == 1: - logging.debug('\u001B[1;37;41m Unexpected EOF \u001B[0m') - logging.debug('Expected Line : ' + expectedline) - sys.exit(self.sshresponse) - elif self.sshresponse == 2: - logging.debug('\u001B[1;37;41m Unexpected TIMEOUT \u001B[0m') - logging.debug('Expected Line : ' + expectedline) - result = re.search('ping |iperf |picocom', str(commandline)) - if result is None: - logging.debug(str(self.ssh.before)) - sys.exit(self.sshresponse) - else: - return -1 - else: - logging.debug('\u001B[1;37;41m Unexpected Others \u001B[0m') - logging.debug('Expected Line : ' + expectedline) - sys.exit(self.sshresponse) - - def close(self): - self.ssh.timeout = 5 - self.ssh.sendline('exit') - self.sshresponse = self.ssh.expect([pexpect.EOF, pexpect.TIMEOUT]) - if self.sshresponse == 0: - pass - elif self.sshresponse == 1: - if not self.picocom_closure: - logging.debug('\u001B[1;37;41m Unexpected TIMEOUT during closing\u001B[0m') - else: - logging.debug('\u001B[1;37;41m Unexpected Others during closing\u001B[0m') - - def copyin(self, ipaddress, username, password, source, destination): - count = 0 - copy_status = False - logging.debug('scp '+ username + '@' + ipaddress + ':' + source + ' ' + destination) - while count < 10: - scp_spawn = pexpect.spawn('scp '+ username + '@' + ipaddress + ':' + source + ' ' + destination, timeout = 100) - scp_response = scp_spawn.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0: - scp_spawn.sendline('yes') - scp_spawn.expect('password:') - scp_spawn.sendline(password) - scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0: - count = 10 - copy_status = True - else: - logging.debug('1 - scp_response = ' + str(scp_response)) - elif scp_response == 1: - scp_spawn.sendline(password) - scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0 or scp_response == 3: - count = 10 - copy_status = True - else: - logging.debug('2 - scp_response = ' + str(scp_response)) - elif scp_response == 2: - count = 10 - copy_status = True - else: - logging.debug('3 - scp_response = ' + str(scp_response)) - # adding a tempo when failure - if not copy_status: - time.sleep(1) - count += 1 - if copy_status: - return 0 - else: - return -1 - - def copyout(self, ipaddress, username, password, source, destination): - count = 0 - copy_status = False - logging.debug('scp ' + source + ' ' + username + '@' + ipaddress + ':' + destination) - while count < 4: - scp_spawn = pexpect.spawn('scp ' + source + ' ' + username + '@' + ipaddress + ':' + destination, timeout = 100) - scp_response = scp_spawn.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0: - scp_spawn.sendline('yes') - scp_spawn.expect('password:') - scp_spawn.sendline(password) - scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0: - count = 10 - copy_status = True - else: - logging.debug('1 - scp_response = ' + str(scp_response)) - elif scp_response == 1: - scp_spawn.sendline(password) - scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0 or scp_response == 3: - count = 10 - copy_status = True - else: - logging.debug('2 - scp_response = ' + str(scp_response)) - elif scp_response == 2: - count = 10 - copy_status = True - else: - logging.debug('3 - scp_response = ' + str(scp_response)) - # adding a tempo when failure - if not copy_status: - time.sleep(1) - count += 1 - if copy_status: - pass - else: - sys.exit('SCP failed') - - def BuildeNB(self): - if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': - Usage() - sys.exit('Insufficient Parameter') - if self.eNB_serverId == '0': - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - lSourcePath = self.eNBSourceCodePath - elif self.eNB_serverId == '1': - lIpAddr = self.eNB1IPAddress - lUserName = self.eNB1UserName - lPassWord = self.eNB1Password - lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId == '2': - lIpAddr = self.eNB2IPAddress - lUserName = self.eNB2UserName - lPassWord = self.eNB2Password - lSourcePath = self.eNB2SourceCodePath - if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(lIpAddr, lUserName, lPassWord) - self.command('mkdir -p ' + lSourcePath, '\$', 5) - self.command('cd ' + lSourcePath, '\$', 5) - self.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + self.ranRepository + ' .; else stdbuf -o0 git fetch; fi', '\$', 600) - # Raphael: here add a check if git clone or git fetch went smoothly - self.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) - self.command('git config user.name "OAI Jenkins"', '\$', 5) - # Checking the BUILD INFO file - if not self.backgroundBuild: - self.command('ls *.txt', '\$', 5) - result = re.search('LAST_BUILD_INFO', str(self.ssh.before)) - if result is not None: - mismatch = False - self.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) - result = re.search(self.ranCommitID, str(self.ssh.before)) - if result is None: - mismatch = True - self.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) - if (self.ranAllowMerge): - result = re.search('YES', str(self.ssh.before)) - if result is None: - mismatch = True - self.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) - if self.ranTargetBranch == '': - result = re.search('develop', str(self.ssh.before)) - else: - result = re.search(self.ranTargetBranch, str(self.ssh.before)) - if result is None: - mismatch = True - else: - result = re.search('NO', str(self.ssh.before)) - if result is None: - mismatch = True - if not mismatch: - self.close() - self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) - return - - self.command('echo ' + lPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30) - # if the commit ID is provided use it to point to it - if self.ranCommitID != '': - self.command('git checkout -f ' + self.ranCommitID, '\$', 5) - # if the branch is not develop, then it is a merge request and we need to do - # the potential merge. Note that merge conflicts should already been checked earlier - if (self.ranAllowMerge): - if self.ranTargetBranch == '': - if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'): - self.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) - else: - logging.debug('Merging with the target branch: ' + self.ranTargetBranch) - self.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5) - self.command('source oaienv', '\$', 5) - self.command('cd cmake_targets', '\$', 5) - self.command('mkdir -p log', '\$', 5) - self.command('chmod 777 log', '\$', 5) - # no need to remove in log (git clean did the trick) - if self.backgroundBuild: - self.command('echo "./build_oai ' + self.Build_eNB_args + '" > ./my-lte-softmodem-build.sh', '\$', 5) - self.command('chmod 775 ./my-lte-softmodem-build.sh', '\$', 5) - self.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=build_enb_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/compile_oai_enb.log ./my-lte-softmodem-build.sh', '\$', 5) - self.close() - self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) - self.backgroundBuildTestId[int(self.eNB_instance)] = self.testCase_id - return - self.command('stdbuf -o0 ./build_oai ' + self.Build_eNB_args + ' 2>&1 | stdbuf -o0 tee compile_oai_enb.log', 'Bypassing the Tests|build have failed', 1500) - self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.testCase_id) - - def WaitBuildeNBisFinished(self): - if self.eNB_serverId == '0': - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - lSourcePath = self.eNBSourceCodePath - elif self.eNB_serverId == '1': - lIpAddr = self.eNB1IPAddress - lUserName = self.eNB1UserName - lPassWord = self.eNB1Password - lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId == '2': - lIpAddr = self.eNB2IPAddress - lUserName = self.eNB2UserName - lPassWord = self.eNB2Password - lSourcePath = self.eNB2SourceCodePath - if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(lIpAddr, lUserName, lPassWord) - count = 40 - buildOAIprocess = True - while (count > 0) and buildOAIprocess: - self.command('ps aux | grep --color=never build_ | grep -v grep', '\$', 3) - result = re.search('build_oai', str(self.ssh.before)) - if result is None: - buildOAIprocess = False - else: - count -= 1 - time.sleep(30) - self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.backgroundBuildTestId[int(self.eNB_instance)]) - - def checkBuildeNB(self, lIpAddr, lUserName, lPassWord, lSourcePath, testcaseId): - self.command('cd ' + lSourcePath + '/cmake_targets', '\$', 3) - self.command('ls lte_build_oai/build', '\$', 3) - self.command('ls lte_build_oai/build', '\$', 3) - buildStatus = True - result = re.search('lte-softmodem', str(self.ssh.before)) - if result is None: - buildStatus = False - else: - # Generating a BUILD INFO file - self.command('echo "SRC_BRANCH: ' + self.ranBranch + '" > ../LAST_BUILD_INFO.txt', '\$', 2) - self.command('echo "SRC_COMMIT: ' + self.ranCommitID + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) - if (self.ranAllowMerge): - self.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2) - if self.ranTargetBranch == '': - self.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2) - else: - self.command('echo "TGT_BRANCH: ' + self.ranTargetBranch + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) - else: - self.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) - self.command('mkdir -p build_log_' + testcaseId, '\$', 5) - self.command('mv log/* ' + 'build_log_' + testcaseId, '\$', 5) - self.command('mv compile_oai_enb.log ' + 'build_log_' + testcaseId, '\$', 5) - if self.eNB_serverId != '0': - self.command('cd cmake_targets', '\$', 5) - self.command('if [ -e tmp_build' + testcaseId + '.zip ]; then rm -f tmp_build' + testcaseId + '.zip; fi', '\$', 5) - self.command('zip -r -qq tmp_build' + testcaseId + '.zip build_log_' + testcaseId, '\$', 5) - self.close() - if (os.path.isfile('./tmp_build' + testcaseId + '.zip')): - os.remove('./tmp_build' + testcaseId + '.zip') - self.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/tmp_build' + testcaseId + '.zip', '.') - if (os.path.isfile('./tmp_build' + testcaseId + '.zip')): - self.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './tmp_build' + testcaseId + '.zip', self.eNBSourceCodePath + '/cmake_targets/.') - os.remove('./tmp_build' + testcaseId + '.zip') - self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) - self.command('cd ' + self.eNBSourceCodePath + '/cmake_targets', '\$', 5) - self.command('unzip -qq -DD tmp_build' + testcaseId + '.zip', '\$', 5) - self.command('rm -f tmp_build' + testcaseId + '.zip', '\$', 5) - self.close() - else: - self.close() - - if buildStatus: - self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) - else: - logging.error('\u001B[1m Building OAI eNB Failed\u001B[0m') - self.CreateHtmlTestRow(self.Build_eNB_args, 'KO', ALL_PROCESSES_OK) - self.CreateHtmlTabFooter(False) - sys.exit(1) - - def BuildOAIUE(self): - if self.UEIPAddress == '' or self.ranRepository == '' or self.ranBranch == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('mkdir -p ' + self.UESourceCodePath, '\$', 5) - self.command('cd ' + self.UESourceCodePath, '\$', 5) - self.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + self.ranRepository + ' .; else stdbuf -o0 git fetch; fi', '\$', 600) - # here add a check if git clone or git fetch went smoothly - self.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) - self.command('git config user.name "OAI Jenkins"', '\$', 5) - self.command('ls *.txt', '\$', 5) - result = re.search('LAST_BUILD_INFO', str(self.ssh.before)) - if result is not None: - mismatch = False - self.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) - result = re.search(self.ranCommitID, str(self.ssh.before)) - if result is None: - mismatch = True - self.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) - if (self.ranAllowMerge): - result = re.search('YES', str(self.ssh.before)) - if result is None: - mismatch = True - self.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) - if self.ranTargetBranch == '': - result = re.search('develop', str(self.ssh.before)) - else: - result = re.search(self.ranTargetBranch, str(self.ssh.before)) - if result is None: - mismatch = True - else: - result = re.search('NO', str(self.ssh.before)) - if result is None: - mismatch = True - if not mismatch: - self.close() - self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) - return - - self.command('echo ' + self.UEPassword + ' | sudo -S git clean -x -d -ff', '\$', 30) - # if the commit ID is provided use it to point to it - if self.ranCommitID != '': - self.command('git checkout -f ' + self.ranCommitID, '\$', 5) - # if the branch is not develop, then it is a merge request and we need to do - # the potential merge. Note that merge conflicts should already been checked earlier - if (self.ranAllowMerge): - if self.ranTargetBranch == '': - if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'): - self.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) - else: - logging.debug('Merging with the target branch: ' + self.ranTargetBranch) - self.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5) - self.command('source oaienv', '\$', 5) - self.command('cd cmake_targets', '\$', 5) - self.command('mkdir -p log', '\$', 5) - self.command('chmod 777 log', '\$', 5) - # no need to remove in log (git clean did the trick) - self.command('stdbuf -o0 ./build_oai ' + self.Build_OAI_UE_args + ' 2>&1 | stdbuf -o0 tee compile_oai_ue.log', 'Bypassing the Tests|build have failed', 600) - self.command('ls lte_build_oai/build', '\$', 3) - self.command('ls lte_build_oai/build', '\$', 3) - buildStatus = True - result = re.search('lte-uesoftmodem', str(self.ssh.before)) - if result is None: - buildStatus = False - self.command('mkdir -p build_log_' + self.testCase_id, '\$', 5) - self.command('mv log/* ' + 'build_log_' + self.testCase_id, '\$', 5) - self.command('mv compile_oai_ue.log ' + 'build_log_' + self.testCase_id, '\$', 5) - if buildStatus: - # Generating a BUILD INFO file - self.command('echo "SRC_BRANCH: ' + self.ranBranch + '" > ../LAST_BUILD_INFO.txt', '\$', 2) - self.command('echo "SRC_COMMIT: ' + self.ranCommitID + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) - if (self.ranAllowMerge): - self.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2) - if self.ranTargetBranch == '': - self.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2) - else: - self.command('echo "TGT_BRANCH: ' + self.ranTargetBranch + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) - else: - self.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) - self.close() - self.CreateHtmlTestRow(self.Build_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE') - else: - self.close() - logging.error('\u001B[1m Building OAI UE Failed\u001B[0m') - self.CreateHtmlTestRow(self.Build_OAI_UE_args, 'KO', ALL_PROCESSES_OK, 'OAI UE') - self.CreateHtmlTabFooter(False) - sys.exit(1) - - def InitializeHSS(self): - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - logging.debug('Using the OAI EPC Release 14 Cassandra-based HSS') - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - logging.debug('\u001B[1m Launching tshark on all interfaces \u001B[0m') - EPC_PcapFileName = 'epc_' + self.testCase_id + '.pcap' - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f ' + EPC_PcapFileName, '\$', 5) - self.command('echo $USER; nohup sudo tshark -f "tcp port not 22 and port not 53" -i any -w ' + self.EPCSourceCodePath + '/scripts/' + EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', self.EPCUserName, 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S mkdir -p logs', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f hss_' + self.testCase_id + '.log logs/hss*.*', '\$', 5) - self.command('echo "oai_hss -j /usr/local/etc/oai/hss_rel14.json" > ./my-hss.sh', '\$', 5) - self.command('chmod 755 ./my-hss.sh', '\$', 5) - self.command('sudo daemon --unsafe --name=hss_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/hss_' + self.testCase_id + '.log ./my-hss.sh', '\$', 5) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - logging.debug('Using the OAI EPC HSS') - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('source oaienv', '\$', 5) - self.command('cd scripts', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S ./run_hss 2>&1 | stdbuf -o0 awk \'{ print strftime("[%Y/%m/%d %H:%M:%S] ",systime()) $0 }\' | stdbuf -o0 tee -a hss_' + self.testCase_id + '.log &', 'Core state: 2 -> 3', 35) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - logging.debug('Using the ltebox simulated HSS') - self.command('if [ -d ' + self.EPCSourceCodePath + '/scripts ]; then echo ' + self.eNBPassword + ' | sudo -S rm -Rf ' + self.EPCSourceCodePath + '/scripts ; fi', '\$', 5) - self.command('mkdir -p ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('cd /opt/hss_sim0609', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f hss.log daemon.log', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S echo "Starting sudo session" && sudo daemon --unsafe --name=simulated_hss --chdir=/opt/hss_sim0609 ./starthss_real ', '\$', 5) - else: - logging.error('This option should not occur!') - self.close() - self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) - - def InitializeMME(self): - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - logging.debug('Using the OAI EPC Release 14 MME') - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f mme_' + self.testCase_id + '.log', '\$', 5) - self.command('echo "./run_mme --config-file /usr/local/etc/oai/mme.conf --set-virt-if" > ./my-mme.sh', '\$', 5) - self.command('chmod 755 ./my-mme.sh', '\$', 5) - self.command('sudo daemon --unsafe --name=mme_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/mme_' + self.testCase_id + '.log ./my-mme.sh', '\$', 5) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('source oaienv', '\$', 5) - self.command('cd scripts', '\$', 5) - self.command('stdbuf -o0 hostname', '\$', 5) - result = re.search('hostname\\\\r\\\\n(?P[a-zA-Z0-9\-\_]+)\\\\r\\\\n', str(self.ssh.before)) - if result is None: - logging.debug('\u001B[1;37;41m Hostname Not Found! \u001B[0m') - sys.exit(1) - host_name = result.group('host_name') - self.command('echo ' + self.EPCPassword + ' | sudo -S ./run_mme 2>&1 | stdbuf -o0 tee -a mme_' + self.testCase_id + '.log &', 'MME app initialization complete', 100) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cd /opt/ltebox/tools', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S ./start_mme', '\$', 5) - else: - logging.error('This option should not occur!') - self.close() - self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) - - def InitializeSPGW(self): - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - logging.debug('Using the OAI EPC Release 14 SPGW-CUPS') - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f spgwc_' + self.testCase_id + '.log spgwu_' + self.testCase_id + '.log', '\$', 5) - self.command('echo "spgwc -c /usr/local/etc/oai/spgw_c.conf" > ./my-spgwc.sh', '\$', 5) - self.command('chmod 755 ./my-spgwc.sh', '\$', 5) - self.command('sudo daemon --unsafe --name=spgwc_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/spgwc_' + self.testCase_id + '.log ./my-spgwc.sh', '\$', 5) - time.sleep(5) - self.command('echo "spgwu -c /usr/local/etc/oai/spgw_u.conf" > ./my-spgwu.sh', '\$', 5) - self.command('chmod 755 ./my-spgwu.sh', '\$', 5) - self.command('sudo daemon --unsafe --name=spgwu_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/spgwu_' + self.testCase_id + '.log ./my-spgwu.sh', '\$', 5) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('source oaienv', '\$', 5) - self.command('cd scripts', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S ./run_spgw 2>&1 | stdbuf -o0 tee -a spgw_' + self.testCase_id + '.log &', 'Initializing SPGW-APP task interface: DONE', 30) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cd /opt/ltebox/tools', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S ./start_xGw', '\$', 5) - else: - logging.error('This option should not occur!') - self.close() - self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) - - def CheckFlexranCtrlInstallation(self): - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '': - return - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('ls -ls /opt/flexran_rtc/*/rt_controller', '\$', 5) - result = re.search('/opt/flexran_rtc/build/rt_controller', str(self.ssh.before)) - if result is not None: - self.flexranCtrlInstalled = True - logging.debug('Flexran Controller is installed') - self.close() - - def InitializeFlexranCtrl(self): - if self.flexranCtrlInstalled == False: - return - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd /opt/flexran_rtc', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f log/*.log', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S echo "build/rt_controller -c log_config/basic_log" > ./my-flexran-ctl.sh', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S chmod 755 ./my-flexran-ctl.sh', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S daemon --unsafe --name=flexran_rtc_daemon --chdir=/opt/flexran_rtc -o /opt/flexran_rtc/log/flexranctl_' + self.testCase_id + '.log ././my-flexran-ctl.sh', '\$', 5) - self.command('ps -aux | grep --color=never rt_controller', '\$', 5) - result = re.search('rt_controller -c ', str(self.ssh.before)) - if result is not None: - logging.debug('\u001B[1m Initialize FlexRan Controller Completed\u001B[0m') - self.flexranCtrlStarted = True - self.close() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def InitializeeNB(self): - if self.eNB_serverId == '0': - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - lSourcePath = self.eNBSourceCodePath - elif self.eNB_serverId == '1': - lIpAddr = self.eNB1IPAddress - lUserName = self.eNB1UserName - lPassWord = self.eNB1Password - lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId == '2': - lIpAddr = self.eNB2IPAddress - lUserName = self.eNB2UserName - lPassWord = self.eNB2Password - lSourcePath = self.eNB2SourceCodePath - if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - Usage() - sys.exit('Insufficient Parameter') - check_eNB = False - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - self.CreateHtmlTestRow(self.Initialize_eNB_args, 'KO', pStatus) - self.CreateHtmlTabFooter(False) - sys.exit(1) - # If tracer options is on, running tshark on EPC side and capture traffic b/ EPC and eNB - result = re.search('T_stdout', str(self.Initialize_eNB_args)) - if result is not None: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('ip addr show | awk -f /tmp/active_net_interfaces.awk | egrep -v "lo|tun"', '\$', 5) - result = re.search('interfaceToUse=(?P[a-zA-Z0-9\-\_]+)done', str(self.ssh.before)) - if result is not None: - eth_interface = result.group('eth_interface') - logging.debug('\u001B[1m Launching tshark on interface ' + eth_interface + '\u001B[0m') - self.EPC_PcapFileName = 'enb_' + self.testCase_id + '_s1log.pcap' - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f /tmp/' + self.EPC_PcapFileName, '\$', 5) - self.command('echo $USER; nohup sudo tshark -f "host ' + lIpAddr +'" -i ' + eth_interface + ' -w /tmp/' + self.EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', self.EPCUserName, 5) - self.close() - self.open(lIpAddr, lUserName, lPassWord) - self.command('cd ' + lSourcePath, '\$', 5) - # Initialize_eNB_args usually start with -O and followed by the location in repository - full_config_file = self.Initialize_eNB_args.replace('-O ','') - extra_options = '' - extIdx = full_config_file.find('.conf') - if (extIdx > 0): - extra_options = full_config_file[extIdx + 5:] - # if tracer options is on, compiling and running T Tracer - result = re.search('T_stdout', str(extra_options)) - if result is not None: - logging.debug('\u001B[1m Compiling and launching T Tracer\u001B[0m') - self.command('cd common/utils/T/tracer', '\$', 5) - self.command('make', '\$', 10) - self.command('echo $USER; nohup ./record -d ../T_messages.txt -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.raw -ON -off VCD -off HEAVY -off LEGACY_GROUP_TRACE -off LEGACY_GROUP_DEBUG > ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.log 2>&1 &', lUserName, 5) - self.command('cd ' + lSourcePath, '\$', 5) - full_config_file = full_config_file[:extIdx + 5] - config_path, config_file = os.path.split(full_config_file) - else: - sys.exit('Insufficient Parameter') - ci_full_config_file = config_path + '/ci-' + config_file - rruCheck = False - result = re.search('^rru|^rcc|^du.band', str(config_file)) - if result is not None: - rruCheck = True - # do not reset board twice in IF4.5 case - result = re.search('^rru|^enb|^du.band', str(config_file)) - if result is not None: - self.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 10) - result = re.search('type: b200', str(self.ssh.before)) - if result is not None: - logging.debug('Found a B2xx device --> resetting it') - self.command('echo ' + lPassWord + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10) - # Reloading FGPA bin firmware - self.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 15) - # Make a copy and adapt to EPC / eNB IP addresses - self.command('cp ' + full_config_file + ' ' + ci_full_config_file, '\$', 5) - self.command('sed -i -e \'s/CI_MME_IP_ADDR/' + self.EPCIPAddress + '/\' ' + ci_full_config_file, '\$', 2); - self.command('sed -i -e \'s/CI_ENB_IP_ADDR/' + lIpAddr + '/\' ' + ci_full_config_file, '\$', 2); - self.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2); - self.command('sed -i -e \'s/CI_RRU1_IP_ADDR/' + self.eNB1IPAddress + '/\' ' + ci_full_config_file, '\$', 2); - self.command('sed -i -e \'s/CI_RRU2_IP_ADDR/' + self.eNB2IPAddress + '/\' ' + ci_full_config_file, '\$', 2); - if self.flexranCtrlInstalled and self.flexranCtrlStarted: - self.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "yes";/\' ' + ci_full_config_file, '\$', 2); - else: - self.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "no";/\' ' + ci_full_config_file, '\$', 2); - # Launch eNB with the modified config file - self.command('source oaienv', '\$', 5) - self.command('cd cmake_targets', '\$', 5) - self.command('echo "ulimit -c unlimited && ./lte_build_oai/build/lte-softmodem -O ' + lSourcePath + '/' + ci_full_config_file + extra_options + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - self.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - self.command('chmod 775 ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - self.command('echo ' + lPassWord + ' | sudo -S rm -Rf enb_' + self.testCase_id + '.log', '\$', 5) - self.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=enb' + str(self.eNB_instance) + '_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - self.eNBLogFiles[int(self.eNB_instance)] = 'enb_' + self.testCase_id + '.log' - if extra_options != '': - self.eNBOptions[int(self.eNB_instance)] = extra_options - time.sleep(6) - doLoop = True - loopCounter = 10 - while (doLoop): - loopCounter = loopCounter - 1 - if (loopCounter == 0): - # In case of T tracer recording, we may need to kill it - result = re.search('T_stdout', str(self.Initialize_eNB_args)) - if result is not None: - self.command('killall --signal SIGKILL record', '\$', 5) - self.close() - doLoop = False - logging.error('\u001B[1;37;41m eNB logging system did not show got sync! \u001B[0m') - self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'KO', ALL_PROCESSES_OK) - # In case of T tracer recording, we need to kill tshark on EPC side - result = re.search('T_stdout', str(self.Initialize_eNB_args)) - if result is not None: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - logging.debug('\u001B[1m Stopping tshark \u001B[0m') - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) - if self.EPC_PcapFileName != '': - time.sleep(0.5) - self.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 /tmp/' + self.EPC_PcapFileName, '\$', 5) - self.close() - time.sleep(1) - if self.EPC_PcapFileName != '': - copyin_res = self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + self.EPC_PcapFileName, '.') - if (copyin_res == 0): - self.copyout(lIpAddr, lUserName, lPassWord, self.EPC_PcapFileName, lSourcePath + '/cmake_targets/.') - self.prematureExit = True - return - else: - self.command('stdbuf -o0 cat enb_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync|Starting"', '\$', 4) - if rruCheck: - result = re.search('wait RUs', str(self.ssh.before)) - else: - result = re.search('got sync|Starting F1AP at CU', str(self.ssh.before)) - if result is None: - time.sleep(6) - else: - doLoop = False - self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'OK', ALL_PROCESSES_OK) - logging.debug('\u001B[1m Initialize eNB Completed\u001B[0m') - time.sleep(10) - - self.close() - - def InitializeUE_common(self, device_id, idx): - try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - if not self.ADBCentralized: - # Reboot UE - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesRebootCmd[idx], '\$', 60) - # Wait - #time.sleep(60) - # Put in LTE-Mode only - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode 11"\'', '\$', 60) - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode1 11"\'', '\$', 60) - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode2 11"\'', '\$', 60) - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode3 11"\'', '\$', 60) - # enable data service - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) - # we need to do radio on/off cycle to make sure of above changes - # airplane mode off // radio on - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) - #time.sleep(10) - # airplane mode on // radio off - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) - - # normal procedure without reboot - # enable data service - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) - # airplane mode on // radio off - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) - self.close() - return - # enable data service - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data enable"', '\$', 60) - - # The following commands are deprecated since we no longer work on Android 7+ - # self.command('stdbuf -o0 adb -s ' + device_id + ' shell settings put global airplane_mode_on 1', '\$', 10) - # self.command('stdbuf -o0 adb -s ' + device_id + ' shell am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true', '\$', 60) - # a dedicated script has to be installed inside the UE - # airplane mode on means call /data/local/tmp/off - if device_id == '84B7N16418004022': - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) - else: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) - #airplane mode off means call /data/local/tmp/on - logging.debug('\u001B[1mUE (' + device_id + ') Initialize Completed\u001B[0m') - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def InitializeUE(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - multi_jobs = [] - i = 0 - for device_id in self.UEDevices: - p = Process(target = self.InitializeUE_common, args = (device_id,i,)) - p.daemon = True - p.start() - multi_jobs.append(p) - i += 1 - for job in multi_jobs: - job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def InitializeOAIUE(self): - if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) - if result is None: - check_eNB = True - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', pStatus) - self.CreateHtmlTabFooter(False) - sys.exit(1) - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - # b2xx_fx3_utils reset procedure - self.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 10) - result = re.search('type: b200', str(self.ssh.before)) - if result is not None: - logging.debug('Found a B2xx device --> resetting it') - self.command('echo ' + self.UEPassword + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10) - # Reloading FGPA bin firmware - self.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 15) - else: - logging.debug('Did not find any B2xx device') - self.command('cd ' + self.UESourceCodePath, '\$', 5) - self.command('source oaienv', '\$', 5) - self.command('cd cmake_targets/lte_build_oai/build', '\$', 5) - result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) - # We may have to regenerate the .u* files - if result is None: - self.command('ls /tmp/*.sed', '\$', 5) - result = re.search('adapt_usim_parameters', str(self.ssh.before)) - if result is not None: - self.command('sed -f /tmp/adapt_usim_parameters.sed ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5) - else: - self.command('sed -e "s#93#92#" -e "s#8baf473f2f8fd09487cccbd7097c6862#fec86ba6eb707ed08905757b1bb44b8f#" -e "s#e734f8734007d6c5ce7a0508809e7e9c#C42449363BBAD02B66D16BC975D77CC1#" ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5) - self.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf .u*', '\$', 5) - self.command('echo ' + self.UEPassword + ' | sudo -S ../../../targets/bin/conf2uedata -c ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf -o .', '\$', 5) - # Launch UE with the modified config file - self.command('echo "ulimit -c unlimited && ./lte-uesoftmodem ' + self.Initialize_OAI_UE_args + '" > ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) - self.command('chmod 775 ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) - self.UELogFile = 'ue_' + self.testCase_id + '.log' - - # We are now looping several times to hope we really sync w/ an eNB - doOutterLoop = True - outterLoopCounter = 5 - gotSyncStatus = True - fullSyncStatus = True - while (doOutterLoop): - self.command('cd ' + self.UESourceCodePath + '/cmake_targets/lte_build_oai/build', '\$', 5) - self.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log', '\$', 5) - self.command('echo ' + self.UEPassword + ' | sudo -S -E daemon --inherit --unsafe --name=ue' + str(self.UE_instance) + '_daemon --chdir=' + self.UESourceCodePath + '/cmake_targets/lte_build_oai/build -o ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) - time.sleep(6) - self.command('cd ../..', '\$', 5) - doLoop = True - loopCounter = 10 - gotSyncStatus = True - # the 'got sync' message is for the UE threads synchronization - while (doLoop): - loopCounter = loopCounter - 1 - if (loopCounter == 0): - # Here should never occur - logging.error('"got sync" message never showed!') - gotSyncStatus = False - doLoop = False - continue - self.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4) - result = re.search('got sync', str(self.ssh.before)) - if result is None: - time.sleep(6) - else: - doLoop = False - logging.debug('Found "got sync" message!') - if gotSyncStatus == False: - # we certainly need to stop the lte-uesoftmodem process if it is still running! - self.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4) - result = re.search('lte-uesoftmodem', str(self.ssh.before)) - if result is not None: - self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT lte-uesoftmodem', '\$', 4) - time.sleep(3) - # We are now checking if sync w/ eNB DOES NOT OCCUR - # Usually during the cell synchronization stage, the UE returns with No cell synchronization message - doLoop = True - loopCounter = 10 - while (doLoop): - loopCounter = loopCounter - 1 - if (loopCounter == 0): - # Here we do have a great chance that the UE did cell-sync w/ eNB - doLoop = False - doOutterLoop = False - fullSyncStatus = True - continue - self.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4) - result = re.search('No cell synchronization found', str(self.ssh.before)) - if result is None: - time.sleep(6) - else: - doLoop = False - fullSyncStatus = False - logging.debug('Found: "No cell synchronization" message! --> try again') - time.sleep(6) - self.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4) - result = re.search('lte-uesoftmodem', str(self.ssh.before)) - if result is not None: - self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT lte-uesoftmodem', '\$', 4) - outterLoopCounter = outterLoopCounter - 1 - if (outterLoopCounter == 0): - doOutterLoop = False - - if fullSyncStatus and gotSyncStatus: - result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) - if result is None: - self.command('ifconfig oaitun_ue1', '\$', 4) - # ifconfig output is different between ubuntu 16 and ubuntu 18 - result = re.search('inet addr:1|inet 1', str(self.ssh.before)) - if result is not None: - logging.debug('\u001B[1m oaitun_ue1 interface is mounted and configured\u001B[0m') - tunnelInterfaceStatus = True - else: - logging.debug(str(self.ssh.before)) - logging.error('\u001B[1m oaitun_ue1 interface is either NOT mounted or NOT configured\u001B[0m') - tunnelInterfaceStatus = False - else: - tunnelInterfaceStatus = True - - self.close() - if fullSyncStatus and gotSyncStatus and tunnelInterfaceStatus: - self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE') - logging.debug('\u001B[1m Initialize OAI UE Completed\u001B[0m') - if (self.ADBIPAddress != 'none'): - self.UEDevices = [] - self.UEDevices.append('OAI-UE') - self.UEDevicesStatus = [] - self.UEDevicesStatus.append(UE_STATUS_DETACHED) - else: - self.htmlUEFailureMsg = 'oaitun_ue1 interface is either NOT mounted or NOT configured' - self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', OAI_UE_PROCESS_NO_TUNNEL_INTERFACE, 'OAI UE') - logging.error('\033[91mInitialize OAI UE Failed! \033[0m') - self.AutoTerminateUEandeNB() - - def checkDevTTYisUnlocked(self): - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - count = 0 - while count < 5: - self.command('echo ' + self.ADBPassword + ' | sudo -S lsof | grep ttyUSB0', '\$', 10) - result = re.search('picocom', str(self.ssh.before)) - if result is None: - count = 10 - else: - time.sleep(5) - count = count + 1 - self.close() - - def InitializeCatM(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - self.picocom_closure = True - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` - self.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) - self.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) - time.sleep(1) - # Calling twice AT to clear all buffers - self.command('AT', 'OK|ERROR', 5) - self.command('AT', 'OK', 5) - # Disabling the Radio - self.command('AT+CFUN=0', 'OK', 5) - logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') - # Checking if auto-attach is enabled - self.command('AT^AUTOATT?', 'OK', 5) - result = re.search('AUTOATT: (?P[0-9\-]+)', str(self.ssh.before)) - if result is not None: - if result.group('state') is not None: - autoAttachState = int(result.group('state')) - if autoAttachState is not None: - if autoAttachState == 0: - self.command('AT^AUTOATT=1', 'OK', 5) - logging.debug('\u001B[1m Auto-Attach enabled\u001B[0m') - else: - logging.debug('\u001B[1;37;41m Could not check Auto-Attach! \u001B[0m') - # Force closure of picocom but device might still be locked - self.close() - self.picocom_closure = False - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - self.checkDevTTYisUnlocked() - - def TerminateCatM(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - self.picocom_closure = True - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` - self.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) - self.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) - time.sleep(1) - # Calling twice AT to clear all buffers - self.command('AT', 'OK|ERROR', 5) - self.command('AT', 'OK', 5) - # Disabling the Radio - self.command('AT+CFUN=0', 'OK', 5) - logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') - self.close() - self.picocom_closure = False - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - self.checkDevTTYisUnlocked() - - def AttachCatM(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - self.picocom_closure = True - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` - self.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) - self.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) - time.sleep(1) - # Calling twice AT to clear all buffers - self.command('AT', 'OK|ERROR', 5) - self.command('AT', 'OK', 5) - # Enabling the Radio - self.command('AT+CFUN=1', 'SIMSTORE,READY', 5) - logging.debug('\u001B[1m Cellular Functionality enabled\u001B[0m') - time.sleep(4) - # We should check if we register - count = 0 - attach_cnt = 0 - attach_status = False - while count < 5: - self.command('AT+CEREG?', 'OK', 5) - result = re.search('CEREG: 2,(?P[0-9\-]+),', str(self.ssh.before)) - if result is not None: - mDataConnectionState = int(result.group('state')) - if mDataConnectionState is not None: - if mDataConnectionState == 1: - count = 10 - attach_status = True - result = re.search('CEREG: 2,1,"(?P[0-9A-Z]+)","(?P[0-9A-Z]+)"', str(self.ssh.before)) - if result is not None: - networky = result.group('networky') - networkz = result.group('networkz') - logging.debug('\u001B[1m CAT-M module attached to eNB (' + str(networky) + '/' + str(networkz) + ')\u001B[0m') - else: - logging.debug('\u001B[1m CAT-M module attached to eNB\u001B[0m') - else: - logging.debug('+CEREG: 2,' + str(mDataConnectionState)) - attach_cnt = attach_cnt + 1 - else: - logging.debug(str(self.ssh.before)) - attach_cnt = attach_cnt + 1 - count = count + 1 - time.sleep(1) - if attach_status: - self.command('AT+CESQ', 'OK', 5) - result = re.search('CESQ: 99,99,255,255,(?P[0-9]+),(?P[0-9]+)', str(self.ssh.before)) - if result is not None: - nRSRQ = int(result.group('rsrq')) - nRSRP = int(result.group('rsrp')) - if (nRSRQ is not None) and (nRSRP is not None): - logging.debug(' RSRQ = ' + str(-20+(nRSRQ/2)) + ' dB') - logging.debug(' RSRP = ' + str(-140+nRSRP) + ' dBm') - self.close() - self.picocom_closure = False - html_queue = SimpleQueue() - self.checkDevTTYisUnlocked() - if attach_status: - html_cell = '
CAT-M module Attachment Completed in ' + str(attach_cnt+4) + ' seconds'
-			if (nRSRQ is not None) and (nRSRP is not None):
-				html_cell += '\n   RSRQ = ' + str(-20+(nRSRQ/2)) + ' dB'
-				html_cell += '\n   RSRP = ' + str(-140+nRSRP) + ' dBm
' - else: - html_cell += '' - html_queue.put(html_cell) - self.CreateHtmlTestRowQueue('N/A', 'OK', 1, html_queue) - else: - logging.error('\u001B[1m CAT-M module Attachment Failed\u001B[0m') - html_cell = '
CAT-M module Attachment Failed
' - html_queue.put(html_cell) - self.CreateHtmlTestRowQueue('N/A', 'KO', 1, html_queue) - self.AutoTerminateUEandeNB() - - def PingCatM(self): - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - check_eNB = True - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - try: - statusQueue = SimpleQueue() - lock = Lock() - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('cd scripts', '\$', 5) - if re.match('OAI', self.EPCType, re.IGNORECASE): - logging.debug('Using the OAI EPC HSS: not implemented yet') - self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) - self.CreateHtmlTabFooter(False) - sys.exit(1) - else: - self.command('egrep --color=never "Allocated ipv4 addr" /opt/ltebox/var/log/xGwLog.0', '\$', 5) - result = re.search('Allocated ipv4 addr: (?P[0-9\.]+) from Pool', str(self.ssh.before)) - if result is not None: - moduleIPAddr = result.group('ipaddr') - else: - self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - ping_time = re.findall("-c (\d+)",str(self.ping_args)) - device_id = 'catm' - ping_status = self.command('stdbuf -o0 ping ' + self.ping_args + ' ' + str(moduleIPAddr) + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) - # TIMEOUT CASE - if ping_status < 0: - message = 'Ping with UE (' + str(moduleIPAddr) + ') crashed due to TIMEOUT!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() - self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) - return - result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', str(self.ssh.before)) - if result is None: - message = 'Packet Loss Not Found!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() - self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) - return - packetloss = result.group('packetloss') - if float(packetloss) == 100: - message = 'Packet Loss is 100%' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() - self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) - return - result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', str(self.ssh.before)) - if result is None: - message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() - self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) - return - rtt_min = result.group('rtt_min') - rtt_avg = result.group('rtt_avg') - rtt_max = result.group('rtt_max') - pal_msg = 'Packet Loss : ' + packetloss + '%' - min_msg = 'RTT(Min) : ' + rtt_min + ' ms' - avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms' - max_msg = 'RTT(Max) : ' + rtt_max + ' ms' - lock.acquire() - logging.debug('\u001B[1;37;44m ping result (' + moduleIPAddr + ') \u001B[0m') - logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') - qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg - packetLossOK = True - if packetloss is not None: - if float(packetloss) > float(self.ping_packetloss_threshold): - qMsg += '\nPacket Loss too high' - logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') - packetLossOK = False - elif float(packetloss) > 0: - qMsg += '\nPacket Loss is not 0%' - logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m') - lock.release() - self.close() - html_cell = '
CAT-M module\nIP Address  : ' + moduleIPAddr + '\n' + qMsg + '
' - statusQueue.put(html_cell) - if (packetLossOK): - self.CreateHtmlTestRowQueue(self.ping_args, 'OK', 1, statusQueue) - else: - self.CreateHtmlTestRowQueue(self.ping_args, 'KO', 1, statusQueue) - self.AutoTerminateUEandeNB() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def AttachUE_common(self, device_id, statusQueue, lock, idx): - try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - if self.ADBCentralized: - if device_id == '84B7N16418004022': - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/on"', '\$', 60) - else: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60) - else: - # airplane mode off // radio on - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) - time.sleep(2) - max_count = 45 - count = max_count - while count > 0: - if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry" | grep -m 1 mDataConnectionState', '\$', 15) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\' | grep -m 1 mDataConnectionState', '\$', 60) - result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', str(self.ssh.before)) - if result is None: - logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m') - lock.acquire() - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put('mDataConnectionState Not Found!') - lock.release() - break - mDataConnectionState = int(result.group('state')) - if mDataConnectionState == 2: - logging.debug('\u001B[1mUE (' + device_id + ') Attach Completed\u001B[0m') - lock.acquire() - statusQueue.put(max_count - count) - statusQueue.put(device_id) - statusQueue.put('Attach Completed') - lock.release() - break - count = count - 1 - if count == 15 or count == 30: - logging.debug('\u001B[1;30;43m Retry UE (' + device_id + ') Flight Mode Off \u001B[0m') - if self.ADBCentralized: - if device_id == '84B7N16418004022': - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) - else: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) - time.sleep(0.5) - if self.ADBCentralized: - if device_id == '84B7N16418004022': - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/on"', '\$', 60) - else: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) - time.sleep(0.5) - logging.debug('\u001B[1mWait UE (' + device_id + ') a second until mDataConnectionState=2 (' + str(max_count-count) + ' times)\u001B[0m') - time.sleep(1) - if count == 0: - logging.debug('\u001B[1;37;41m UE (' + device_id + ') Attach Failed \u001B[0m') - lock.acquire() - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put('Attach Failed') - lock.release() - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def AttachUE(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - check_eNB = True - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - self.CreateHtmlTestRow('N/A', 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - multi_jobs = [] - status_queue = SimpleQueue() - lock = Lock() - nb_ue_to_connect = 0 - for device_id in self.UEDevices: - if (self.nbMaxUEtoAttach == -1) or (nb_ue_to_connect < self.nbMaxUEtoAttach): - self.UEDevicesStatus[nb_ue_to_connect] = UE_STATUS_ATTACHING - p = Process(target = self.AttachUE_common, args = (device_id, status_queue, lock,nb_ue_to_connect,)) - p.daemon = True - p.start() - multi_jobs.append(p) - nb_ue_to_connect = nb_ue_to_connect + 1 - for job in multi_jobs: - job.join() - - if (status_queue.empty()): - self.CreateHtmlTestRow('N/A', 'KO', ALL_PROCESSES_OK) - self.AutoTerminateUEandeNB() - return - else: - attach_status = True - html_queue = SimpleQueue() - while (not status_queue.empty()): - count = status_queue.get() - if (count < 0): - attach_status = False - device_id = status_queue.get() - message = status_queue.get() - if (count < 0): - html_cell = '
UE (' + device_id + ')\n' + message + '
' - else: - html_cell = '
UE (' + device_id + ')\n' + message + ' in ' + str(count + 2) + ' seconds
' - html_queue.put(html_cell) - if (attach_status): - cnt = 0 - while cnt < len(self.UEDevices): - if self.UEDevicesStatus[cnt] == UE_STATUS_ATTACHING: - self.UEDevicesStatus[cnt] = UE_STATUS_ATTACHED - cnt += 1 - self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) - result = re.search('T_stdout', str(self.Initialize_eNB_args)) - if result is not None: - logging.debug('Waiting 5 seconds to fill up record file') - time.sleep(5) - else: - self.CreateHtmlTestRowQueue('N/A', 'KO', len(self.UEDevices), html_queue) - self.AutoTerminateUEandeNB() - - def DetachUE_common(self, device_id, idx): - try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - if self.ADBCentralized: - if device_id == '84B7N16418004022': - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) - else: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) - logging.debug('\u001B[1mUE (' + device_id + ') Detach Completed\u001B[0m') - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def DetachUE(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - check_eNB = True - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - self.CreateHtmlTestRow('N/A', 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - multi_jobs = [] - cnt = 0 - for device_id in self.UEDevices: - self.UEDevicesStatus[cnt] = UE_STATUS_DETACHING - p = Process(target = self.DetachUE_common, args = (device_id,cnt,)) - p.daemon = True - p.start() - multi_jobs.append(p) - cnt += 1 - for job in multi_jobs: - job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - result = re.search('T_stdout', str(self.Initialize_eNB_args)) - if result is not None: - logging.debug('Waiting 5 seconds to fill up record file') - time.sleep(5) - cnt = 0 - while cnt < len(self.UEDevices): - self.UEDevicesStatus[cnt] = UE_STATUS_DETACHED - cnt += 1 - - def RebootUE_common(self, device_id): - try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - previousmDataConnectionStates = [] - # Save mDataConnectionState - self.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) - self.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) - result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', str(self.ssh.before)) - if result is None: - logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m') - sys.exit(1) - previousmDataConnectionStates.append(int(result.group('state'))) - # Reboot UE - self.command('stdbuf -o0 adb -s ' + device_id + ' shell reboot', '\$', 10) - time.sleep(60) - previousmDataConnectionState = previousmDataConnectionStates.pop(0) - count = 180 - while count > 0: - count = count - 1 - self.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) - result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', str(self.ssh.before)) - if result is None: - mDataConnectionState = None - else: - mDataConnectionState = int(result.group('state')) - logging.debug('mDataConnectionState = ' + result.group('state')) - if mDataConnectionState is None or (previousmDataConnectionState == 2 and mDataConnectionState != 2): - logging.debug('\u001B[1mWait UE (' + device_id + ') a second until reboot completion (' + str(180-count) + ' times)\u001B[0m') - time.sleep(1) - else: - logging.debug('\u001B[1mUE (' + device_id + ') Reboot Completed\u001B[0m') - break - if count == 0: - logging.debug('\u001B[1;37;41m UE (' + device_id + ') Reboot Failed \u001B[0m') - sys.exit(1) - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def RebootUE(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - check_eNB = True - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - self.CreateHtmlTestRow('N/A', 'KO', pStatus) - self.CreateHtmlTabFooter(False) - sys.exit(1) - multi_jobs = [] - for device_id in self.UEDevices: - p = Process(target = self.RebootUE_common, args = (device_id,)) - p.daemon = True - p.start() - multi_jobs.append(p) - for job in multi_jobs: - job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def DataDisableUE_common(self, device_id, idx): - try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - # disable data service - if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data disable"', '\$', 60) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data disable"\'', '\$', 60) - logging.debug('\u001B[1mUE (' + device_id + ') Disabled Data Service\u001B[0m') - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def DataDisableUE(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - multi_jobs = [] - i = 0 - for device_id in self.UEDevices: - p = Process(target = self.DataDisableUE_common, args = (device_id,i,)) - p.daemon = True - p.start() - multi_jobs.append(p) - i += 1 - for job in multi_jobs: - job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def DataEnableUE_common(self, device_id, idx): - try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - # enable data service - if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data enable"', '\$', 60) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) - logging.debug('\u001B[1mUE (' + device_id + ') Enabled Data Service\u001B[0m') - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def DataEnableUE(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - multi_jobs = [] - i = 0 - for device_id in self.UEDevices: - p = Process(target = self.DataEnableUE_common, args = (device_id,i,)) - p.daemon = True - p.start() - multi_jobs.append(p) - i += 1 - for job in multi_jobs: - job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def GetAllUEDevices(self, terminate_ue_flag): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - if self.ADBCentralized: - self.command('adb devices', '\$', 15) - self.UEDevices = re.findall("\\\\r\\\\n([A-Za-z0-9]+)\\\\tdevice",str(self.ssh.before)) - self.close() - else: - if (os.path.isfile('./phones_list.txt')): - os.remove('./phones_list.txt') - self.command('ls /etc/*/phones*.txt', '\$', 5) - result = re.search('/etc/ci/phones_list.txt', str(self.ssh.before)) - self.close() - if (result is not None) and (len(self.UEDevices) == 0): - self.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, '/etc/ci/phones_list.txt', '.') - if (os.path.isfile('./phones_list.txt')): - phone_list_file = open('./phones_list.txt', 'r') - for line in phone_list_file.readlines(): - line = line.strip() - result = re.search('^#', line) - if result is not None: - continue - comma_split = line.split(",") - self.UEDevices.append(comma_split[0]) - self.UEDevicesRemoteServer.append(comma_split[1]) - self.UEDevicesRemoteUser.append(comma_split[2]) - self.UEDevicesOffCmd.append(comma_split[3]) - self.UEDevicesOnCmd.append(comma_split[4]) - self.UEDevicesRebootCmd.append(comma_split[5]) - phone_list_file.close() - - if terminate_ue_flag == False: - if len(self.UEDevices) == 0: - logging.debug('\u001B[1;37;41m UE Not Found! \u001B[0m') - sys.exit(1) - if len(self.UEDevicesStatus) == 0: - cnt = 0 - while cnt < len(self.UEDevices): - self.UEDevicesStatus.append(UE_STATUS_DETACHED) - cnt += 1 - - def GetAllCatMDevices(self, terminate_ue_flag): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - if self.ADBCentralized: - self.command('lsusb | egrep "Future Technology Devices International, Ltd FT2232C" | sed -e "s#:.*##" -e "s# #_#g"', '\$', 15) - self.CatMDevices = re.findall("\\\\r\\\\n([A-Za-z0-9_]+)",str(self.ssh.before)) - else: - if (os.path.isfile('./modules_list.txt')): - os.remove('./modules_list.txt') - self.command('ls /etc/*/modules*.txt', '\$', 5) - result = re.search('/etc/ci/modules_list.txt', str(self.ssh.before)) - self.close() - if result is not None: - logging.debug('Found a module list file on ADB server') - if terminate_ue_flag == False: - if len(self.CatMDevices) == 0: - logging.debug('\u001B[1;37;41m CAT-M UE Not Found! \u001B[0m') - sys.exit(1) - self.close() - - def CheckUEStatus_common(self, lock, device_id, statusQueue, idx): - try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry"', '\$', 15) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\'', '\$', 60) - result = re.search('mServiceState=(?P[0-9]+)', str(self.ssh.before)) - serviceState = 'Service State: UNKNOWN' - if result is not None: - lServiceState = int(result.group('serviceState')) - if lServiceState == 3: - serviceState = 'Service State: RADIO_POWERED_OFF' - if lServiceState == 1: - serviceState = 'Service State: OUT_OF_SERVICE' - if lServiceState == 0: - serviceState = 'Service State: IN_SERVICE' - if lServiceState == 2: - serviceState = 'Service State: EMERGENCY_ONLY' - result = re.search('mDataConnectionState=(?P[0-9]+)', str(self.ssh.before)) - dataConnectionState = 'Data State: UNKNOWN' - if result is not None: - lDataConnectionState = int(result.group('dataConnectionState')) - if lDataConnectionState == 0: - dataConnectionState = 'Data State: DISCONNECTED' - if lDataConnectionState == 1: - dataConnectionState = 'Data State: CONNECTING' - if lDataConnectionState == 2: - dataConnectionState = 'Data State: CONNECTED' - if lDataConnectionState == 3: - dataConnectionState = 'Data State: SUSPENDED' - result = re.search('mDataConnectionReason=(?P[0-9a-zA-Z_]+)', str(self.ssh.before)) - dataConnectionReason = 'Data Reason: UNKNOWN' - if result is not None: - dataConnectionReason = 'Data Reason: ' + result.group('dataConnectionReason') - lock.acquire() - logging.debug('\u001B[1;37;44m Status Check (' + str(device_id) + ') \u001B[0m') - logging.debug('\u001B[1;34m ' + serviceState + '\u001B[0m') - logging.debug('\u001B[1;34m ' + dataConnectionState + '\u001B[0m') - logging.debug('\u001B[1;34m ' + dataConnectionReason + '\u001B[0m') - statusQueue.put(0) - statusQueue.put(device_id) - qMsg = serviceState + '\n' + dataConnectionState + '\n' + dataConnectionReason - statusQueue.put(qMsg) - lock.release() - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def CheckStatusUE(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - check_eNB = True - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - self.CreateHtmlTestRow('N/A', 'KO', pStatus) - self.CreateHtmlTabFooter(False) - sys.exit(1) - multi_jobs = [] - lock = Lock() - status_queue = SimpleQueue() - i = 0 - for device_id in self.UEDevices: - p = Process(target = self.CheckUEStatus_common, args = (lock,device_id,status_queue,i,)) - p.daemon = True - p.start() - multi_jobs.append(p) - i += 1 - for job in multi_jobs: - job.join() - if self.flexranCtrlInstalled and self.flexranCtrlStarted: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd /opt/flexran_rtc', '\$', 5) - self.command('curl http://localhost:9999/stats | jq \'.\' > log/check_status_' + self.testCase_id + '.log 2>&1', '\$', 5) - self.command('cat log/check_status_' + self.testCase_id + '.log | jq \'.eNB_config[0].UE\' | grep -c rnti | sed -e "s#^#Nb Connected UE = #"', '\$', 5) - result = re.search('Nb Connected UE = (?P[0-9]+)', str(self.ssh.before)) - passStatus = True - if result is not None: - nb_ues = int(result.group('nb_ues')) - htmlOptions = 'Nb Connected UE(s) to eNB = ' + str(nb_ues) - logging.debug('\u001B[1;37;44m ' + htmlOptions + ' \u001B[0m') - if self.expectedNbOfConnectedUEs > -1: - if nb_ues != self.expectedNbOfConnectedUEs: - passStatus = False - else: - htmlOptions = 'N/A' - self.close() - else: - passStatus = True - htmlOptions = 'N/A' - - if (status_queue.empty()): - self.CreateHtmlTestRow(htmlOptions, 'KO', ALL_PROCESSES_OK) - self.AutoTerminateUEandeNB() - else: - check_status = True - html_queue = SimpleQueue() - while (not status_queue.empty()): - count = status_queue.get() - if (count < 0): - check_status = False - device_id = status_queue.get() - message = status_queue.get() - html_cell = '
UE (' + device_id + ')\n' + message + '
' - html_queue.put(html_cell) - if check_status and passStatus: - self.CreateHtmlTestRowQueue(htmlOptions, 'OK', len(self.UEDevices), html_queue) - else: - self.CreateHtmlTestRowQueue(htmlOptions, 'KO', len(self.UEDevices), html_queue) - self.AutoTerminateUEandeNB() - - def GetAllUEIPAddresses(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - ue_ip_status = 0 - self.UEIPAddresses = [] - if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): - if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('ifconfig oaitun_ue1', '\$', 4) - result = re.search('inet addr:(?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)|inet (?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)', str(self.ssh.before)) - if result is not None: - if result.group('ueipaddress') is not None: - UE_IPAddress = result.group('ueipaddress') - else: - UE_IPAddress = result.group('ueipaddress2') - logging.debug('\u001B[1mUE (' + self.UEDevices[0] + ') IP Address is ' + UE_IPAddress + '\u001B[0m') - self.UEIPAddresses.append(UE_IPAddress) - else: - logging.debug('\u001B[1;37;41m UE IP Address Not Found! \u001B[0m') - ue_ip_status -= 1 - self.close() - return ue_ip_status - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - idx = 0 - for device_id in self.UEDevices: - if self.UEDevicesStatus[idx] != UE_STATUS_ATTACHED: - idx += 1 - continue - count = 0 - while count < 4: - if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "ip addr show | grep rmnet"', '\$', 15) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ip addr show | grep rmnet"\'', '\$', 60) - result = re.search('inet (?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\/[0-9]+[0-9a-zA-Z\.\s]+', str(self.ssh.before)) - if result is None: - logging.debug('\u001B[1;37;41m UE IP Address Not Found! \u001B[0m') - time.sleep(1) - count += 1 - else: - count = 10 - if count < 9: - ue_ip_status -= 1 - continue - UE_IPAddress = result.group('ueipaddress') - logging.debug('\u001B[1mUE (' + device_id + ') IP Address is ' + UE_IPAddress + '\u001B[0m') - for ueipaddress in self.UEIPAddresses: - if ueipaddress == UE_IPAddress: - logging.debug('\u001B[1mUE (' + device_id + ') IP Address ' + UE_IPAddress + ': has already been allocated to another device !' + '\u001B[0m') - ue_ip_status -= 1 - continue - self.UEIPAddresses.append(UE_IPAddress) - idx += 1 - self.close() - return ue_ip_status - - def ping_iperf_wrong_exit(self, lock, UE_IPAddress, device_id, statusQueue, message): - lock.acquire() - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - statusQueue.put(message) - lock.release() - - def Ping_common(self, lock, UE_IPAddress, device_id, statusQueue): - try: - # Launch ping on the EPC side (true for ltebox and old open-air-cn) - # But for OAI-Rel14-CUPS, we launch from python executor - launchFromEpc = True - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - launchFromEpc = False - ping_time = re.findall("-c (\d+)",str(self.ping_args)) - - if launchFromEpc: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('cd scripts', '\$', 5) - ping_status = self.command('stdbuf -o0 ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) - else: - cmd = 'ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 > ping_' + self.testCase_id + '_' + device_id + '.log' - message = cmd + '\n' - logging.debug(cmd) - ret = subprocess.run(cmd, shell=True) - ping_status = ret.returncode - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'ping_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cat ' + self.EPCSourceCodePath + '/scripts/ping_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - # TIMEOUT CASE - if ping_status < 0: - message = 'Ping with UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) - return - result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', str(self.ssh.before)) - if result is None: - message = 'Packet Loss Not Found!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) - return - packetloss = result.group('packetloss') - if float(packetloss) == 100: - message = 'Packet Loss is 100%' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) - return - result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', str(self.ssh.before)) - if result is None: - message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) - return - rtt_min = result.group('rtt_min') - rtt_avg = result.group('rtt_avg') - rtt_max = result.group('rtt_max') - pal_msg = 'Packet Loss : ' + packetloss + '%' - min_msg = 'RTT(Min) : ' + rtt_min + ' ms' - avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms' - max_msg = 'RTT(Max) : ' + rtt_max + ' ms' - lock.acquire() - logging.debug('\u001B[1;37;44m ping result (' + UE_IPAddress + ') \u001B[0m') - logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') - qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg - packetLossOK = True - if packetloss is not None: - if float(packetloss) > float(self.ping_packetloss_threshold): - qMsg += '\nPacket Loss too high' - logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') - packetLossOK = False - elif float(packetloss) > 0: - qMsg += '\nPacket Loss is not 0%' - logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m') - if (packetLossOK): - statusQueue.put(0) - else: - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - statusQueue.put(qMsg) - lock.release() - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def PingNoS1_wrong_exit(self, qMsg): - html_queue = SimpleQueue() - html_cell = '
OAI UE ping result\n' + qMsg + '
' - html_queue.put(html_cell) - self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) - - def PingNoS1(self): - check_eNB = True - check_OAI_UE = True - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - ping_from_eNB = re.search('oaitun_enb1', str(self.ping_args)) - if ping_from_eNB is not None: - if self.eNBIPAddress == '' or self.eNBUserName == '' or self.eNBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - else: - if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': - Usage() - sys.exit('Insufficient Parameter') - try: - if ping_from_eNB is not None: - self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) - self.command('cd ' + self.eNBSourceCodePath + '/cmake_targets/', '\$', 5) - else: - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('cd ' + self.UESourceCodePath + '/cmake_targets/', '\$', 5) - self.command('cd cmake_targets', '\$', 5) - ping_time = re.findall("-c (\d+)",str(self.ping_args)) - ping_status = self.command('stdbuf -o0 ping ' + self.ping_args + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '.log', '\$', int(ping_time[0])*1.5) - # TIMEOUT CASE - if ping_status < 0: - message = 'Ping with OAI UE crashed due to TIMEOUT!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.PingNoS1_wrong_exit(message) - return - result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', str(self.ssh.before)) - if result is None: - message = 'Packet Loss Not Found!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.PingNoS1_wrong_exit(message) - return - packetloss = result.group('packetloss') - if float(packetloss) == 100: - message = 'Packet Loss is 100%' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.PingNoS1_wrong_exit(message) - return - result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', str(self.ssh.before)) - if result is None: - message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.PingNoS1_wrong_exit(message) - return - rtt_min = result.group('rtt_min') - rtt_avg = result.group('rtt_avg') - rtt_max = result.group('rtt_max') - pal_msg = 'Packet Loss : ' + packetloss + '%' - min_msg = 'RTT(Min) : ' + rtt_min + ' ms' - avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms' - max_msg = 'RTT(Max) : ' + rtt_max + ' ms' - logging.debug('\u001B[1;37;44m OAI UE ping result \u001B[0m') - logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') - qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg - packetLossOK = True - if packetloss is not None: - if float(packetloss) > float(self.ping_packetloss_threshold): - qMsg += '\nPacket Loss too high' - logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') - packetLossOK = False - elif float(packetloss) > 0: - qMsg += '\nPacket Loss is not 0%' - logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m') - self.close() - html_queue = SimpleQueue() - ip_addr = 'TBD' - html_cell = '
OAI UE ping result\n' + qMsg + '
' - html_queue.put(html_cell) - if packetLossOK: - self.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) - else: - self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) - - # copying on the EPC server for logCollection - if ping_from_eNB is not None: - copyin_res = self.copyin(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.eNBSourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') - else: - copyin_res = self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') - if (copyin_res == 0): - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'ping_' + self.testCase_id + '.log', self.EPCSourceCodePath + '/scripts') - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def Ping(self): - result = re.search('noS1', str(self.Initialize_eNB_args)) - if result is not None: - self.PingNoS1() - return - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - check_eNB = True - if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): - check_OAI_UE = True - else: - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - ueIpStatus = self.GetAllUEIPAddresses() - if (ueIpStatus < 0): - self.CreateHtmlTestRow(self.ping_args, 'KO', UE_IP_ADDRESS_ISSUE) - self.AutoTerminateUEandeNB() - return - multi_jobs = [] - i = 0 - lock = Lock() - status_queue = SimpleQueue() - for UE_IPAddress in self.UEIPAddresses: - device_id = self.UEDevices[i] - p = Process(target = self.Ping_common, args = (lock,UE_IPAddress,device_id,status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - i = i + 1 - for job in multi_jobs: - job.join() - - if (status_queue.empty()): - self.CreateHtmlTestRow(self.ping_args, 'KO', ALL_PROCESSES_OK) - self.AutoTerminateUEandeNB() - else: - ping_status = True - html_queue = SimpleQueue() - while (not status_queue.empty()): - count = status_queue.get() - if (count < 0): - ping_status = False - device_id = status_queue.get() - ip_addr = status_queue.get() - message = status_queue.get() - html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' - html_queue.put(html_cell) - if (ping_status): - self.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) - else: - self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) - self.AutoTerminateUEandeNB() - - def Iperf_ComputeTime(self): - result = re.search('-t (?P\d+)', str(self.iperf_args)) - if result is None: - logging.debug('\u001B[1;37;41m Iperf time Not Found! \u001B[0m') - sys.exit(1) - return result.group('iperf_time') - - def Iperf_ComputeModifiedBW(self, idx, ue_num): - result = re.search('-b (?P[0-9\.]+)[KMG]', str(self.iperf_args)) - if result is None: - logging.debug('\u001B[1;37;41m Iperf bandwidth Not Found! \u001B[0m') - sys.exit(1) - iperf_bandwidth = result.group('iperf_bandwidth') - if self.iperf_profile == 'balanced': - iperf_bandwidth_new = float(iperf_bandwidth)/ue_num - if self.iperf_profile == 'single-ue': - iperf_bandwidth_new = float(iperf_bandwidth) - if self.iperf_profile == 'unbalanced': - # residual is 2% of max bw - residualBW = float(iperf_bandwidth) / 50 - if idx == 0: - iperf_bandwidth_new = float(iperf_bandwidth) - ((ue_num - 1) * residualBW) - else: - iperf_bandwidth_new = residualBW - iperf_bandwidth_str = '-b ' + iperf_bandwidth - iperf_bandwidth_str_new = '-b ' + ('%.2f' % iperf_bandwidth_new) - result = re.sub(iperf_bandwidth_str, iperf_bandwidth_str_new, str(self.iperf_args)) - if result is None: - logging.debug('\u001B[1;37;41m Calculate Iperf bandwidth Failed! \u001B[0m') - sys.exit(1) - return result - - def Iperf_analyzeV2TCPOutput(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): - self.command('awk -f /tmp/tcp_iperf_stats.awk /tmp/CI-eNB/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - result = re.search('Avg Bitrate : (?P[0-9\.]+ Mbits\/sec) Max Bitrate : (?P[0-9\.]+ Mbits\/sec) Min Bitrate : (?P[0-9\.]+ Mbits\/sec)', str(self.ssh.before)) - if result is not None: - avgbitrate = result.group('average') - maxbitrate = result.group('maximum') - minbitrate = result.group('minimum') - lock.acquire() - logging.debug('\u001B[1;37;44m TCP iperf result (' + UE_IPAddress + ') \u001B[0m') - msg = 'TCP Stats :\n' - if avgbitrate is not None: - logging.debug('\u001B[1;34m Avg Bitrate : ' + avgbitrate + '\u001B[0m') - msg += 'Avg Bitrate : ' + avgbitrate + '\n' - if maxbitrate is not None: - logging.debug('\u001B[1;34m Max Bitrate : ' + maxbitrate + '\u001B[0m') - msg += 'Max Bitrate : ' + maxbitrate + '\n' - if minbitrate is not None: - logging.debug('\u001B[1;34m Min Bitrate : ' + minbitrate + '\u001B[0m') - msg += 'Min Bitrate : ' + minbitrate + '\n' - statusQueue.put(0) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - statusQueue.put(msg) - lock.release() - return 0 - - def Iperf_analyzeV2Output(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): - result = re.search('-u', str(iperf_real_options)) - if result is None: - return self.Iperf_analyzeV2TCPOutput(lock, UE_IPAddress, device_id, statusQueue, iperf_real_options) - - result = re.search('Server Report:', str(self.ssh.before)) - if result is None: - result = re.search('read failed: Connection refused', str(self.ssh.before)) - if result is not None: - logging.debug('\u001B[1;37;41m Could not connect to iperf server! \u001B[0m') - else: - logging.debug('\u001B[1;37;41m Server Report and Connection refused Not Found! \u001B[0m') - return -1 - # Computing the requested bandwidth in float - result = re.search('-b (?P[0-9\.]+)[KMG]', str(iperf_real_options)) - if result is not None: - req_bandwidth = result.group('iperf_bandwidth') - req_bw = float(req_bandwidth) - result = re.search('-b [0-9\.]+K', str(iperf_real_options)) - if result is not None: - req_bandwidth = '%.1f Kbits/sec' % req_bw - req_bw = req_bw * 1000 - result = re.search('-b [0-9\.]+M', str(iperf_real_options)) - if result is not None: - req_bandwidth = '%.1f Mbits/sec' % req_bw - req_bw = req_bw * 1000000 - result = re.search('-b [0-9\.]+G', str(iperf_real_options)) - if result is not None: - req_bandwidth = '%.1f Gbits/sec' % req_bw - req_bw = req_bw * 1000000000 - - result = re.search('Server Report:\\\\r\\\\n(?:|\[ *\d+\].*) (?P[0-9\.]+ [KMG]bits\/sec) +(?P[0-9\.]+ ms) +(\d+\/..\d+) +(\((?P[0-9\.]+)%\))', str(self.ssh.before)) - if result is not None: - bitrate = result.group('bitrate') - packetloss = result.group('packetloss') - jitter = result.group('jitter') - lock.acquire() - logging.debug('\u001B[1;37;44m iperf result (' + UE_IPAddress + ') \u001B[0m') - iperfStatus = True - msg = 'Req Bitrate : ' + req_bandwidth + '\n' - logging.debug('\u001B[1;34m Req Bitrate : ' + req_bandwidth + '\u001B[0m') - if bitrate is not None: - msg += 'Bitrate : ' + bitrate + '\n' - logging.debug('\u001B[1;34m Bitrate : ' + bitrate + '\u001B[0m') - result = re.search('(?P[0-9\.]+) [KMG]bits/sec', str(bitrate)) - if result is not None: - actual_bw = float(str(result.group('real_bw'))) - result = re.search('[0-9\.]+ K', bitrate) - if result is not None: - actual_bw = actual_bw * 1000 - result = re.search('[0-9\.]+ M', bitrate) - if result is not None: - actual_bw = actual_bw * 1000000 - result = re.search('[0-9\.]+ G', bitrate) - if result is not None: - actual_bw = actual_bw * 1000000000 - br_loss = 100 * actual_bw / req_bw - bitperf = '%.2f ' % br_loss - msg += 'Bitrate Perf: ' + bitperf + '%\n' - logging.debug('\u001B[1;34m Bitrate Perf: ' + bitperf + '%\u001B[0m') - if packetloss is not None: - msg += 'Packet Loss : ' + packetloss + '%\n' - logging.debug('\u001B[1;34m Packet Loss : ' + packetloss + '%\u001B[0m') - if float(packetloss) > float(self.iperf_packetloss_threshold): - msg += 'Packet Loss too high!\n' - logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') - iperfStatus = False - if jitter is not None: - msg += 'Jitter : ' + jitter + '\n' - logging.debug('\u001B[1;34m Jitter : ' + jitter + '\u001B[0m') - if (iperfStatus): - statusQueue.put(0) - else: - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - statusQueue.put(msg) - lock.release() - return 0 - else: - return -2 - - def Iperf_analyzeV2Server(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): - if (not os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not analyze from server log') - return - # Computing the requested bandwidth in float - result = re.search('-b (?P[0-9\.]+)[KMG]', str(iperf_real_options)) - if result is None: - logging.debug('Iperf bandwidth Not Found!') - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not compute Iperf bandwidth!') - return - else: - req_bandwidth = result.group('iperf_bandwidth') - req_bw = float(req_bandwidth) - result = re.search('-b [0-9\.]+K', str(iperf_real_options)) - if result is not None: - req_bandwidth = '%.1f Kbits/sec' % req_bw - req_bw = req_bw * 1000 - result = re.search('-b [0-9\.]+M', str(iperf_real_options)) - if result is not None: - req_bandwidth = '%.1f Mbits/sec' % req_bw - req_bw = req_bw * 1000000 - result = re.search('-b [0-9\.]+G', str(iperf_real_options)) - if result is not None: - req_bandwidth = '%.1f Gbits/sec' % req_bw - req_bw = req_bw * 1000000000 - - server_file = open('iperf_server_' + self.testCase_id + '_' + device_id + '.log', 'r') - br_sum = 0.0 - ji_sum = 0.0 - pl_sum = 0 - ps_sum = 0 - row_idx = 0 - for line in server_file.readlines(): - result = re.search('(?P[0-9\.]+ [KMG]bits\/sec) +(?P[0-9\.]+ ms) +(?P[0-9]+)/ +(?P[0-9]+)', str(line)) - if result is not None: - bitrate = result.group('bitrate') - jitter = result.group('jitter') - packetlost = result.group('lostPack') - packetsent = result.group('sentPack') - br = bitrate.split(' ') - ji = jitter.split(' ') - row_idx = row_idx + 1 - curr_br = float(br[0]) - pl_sum = pl_sum + int(packetlost) - ps_sum = ps_sum + int(packetsent) - if (br[1] == 'Kbits/sec'): - curr_br = curr_br * 1000 - if (br[1] == 'Mbits/sec'): - curr_br = curr_br * 1000 * 1000 - br_sum = curr_br + br_sum - ji_sum = float(ji[0]) + ji_sum - if (row_idx > 0): - br_sum = br_sum / row_idx - ji_sum = ji_sum / row_idx - br_loss = 100 * br_sum / req_bw - if (br_sum > 1000): - br_sum = br_sum / 1000 - if (br_sum > 1000): - br_sum = br_sum / 1000 - bitrate = '%.2f Mbits/sec' % br_sum - else: - bitrate = '%.2f Kbits/sec' % br_sum - else: - bitrate = '%.2f bits/sec' % br_sum - bitperf = '%.2f ' % br_loss - bitperf += '%' - jitter = '%.2f ms' % (ji_sum) - if (ps_sum > 0): - pl = float(100 * pl_sum / ps_sum) - packetloss = '%2.1f ' % (pl) - packetloss += '%' - else: - packetloss = 'unknown' - lock.acquire() - if (br_loss < 90): - statusQueue.put(1) - else: - statusQueue.put(0) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - req_msg = 'Req Bitrate : ' + req_bandwidth - bir_msg = 'Bitrate : ' + bitrate - brl_msg = 'Bitrate Perf: ' + bitperf - jit_msg = 'Jitter : ' + jitter - pal_msg = 'Packet Loss : ' + packetloss - statusQueue.put(req_msg + '\n' + bir_msg + '\n' + brl_msg + '\n' + jit_msg + '\n' + pal_msg + '\n') - logging.debug('\u001B[1;37;45m iperf result (' + UE_IPAddress + ') \u001B[0m') - logging.debug('\u001B[1;35m ' + req_msg + '\u001B[0m') - logging.debug('\u001B[1;35m ' + bir_msg + '\u001B[0m') - logging.debug('\u001B[1;35m ' + brl_msg + '\u001B[0m') - logging.debug('\u001B[1;35m ' + jit_msg + '\u001B[0m') - logging.debug('\u001B[1;35m ' + pal_msg + '\u001B[0m') - lock.release() - else: - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not analyze from server log') - - server_file.close() - - - def Iperf_analyzeV3Output(self, lock, UE_IPAddress, device_id, statusQueue): - result = re.search('(?P[0-9\.]+ [KMG]bits\/sec) +(?:|[0-9\.]+ ms +\d+\/\d+ \((?P[0-9\.]+)%\)) +(?:|receiver)\\\\r\\\\n(?:|\[ *\d+\] Sent \d+ datagrams)\\\\r\\\\niperf Done\.', str(self.ssh.before)) - if result is None: - result = re.search('(?Piperf: error - [a-zA-Z0-9 :]+)', str(self.ssh.before)) - lock.acquire() - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - if result is not None: - logging.debug('\u001B[1;37;41m ' + result.group('error') + ' \u001B[0m') - statusQueue.put(result.group('error')) - else: - logging.debug('\u001B[1;37;41m Bitrate and/or Packet Loss Not Found! \u001B[0m') - statusQueue.put('Bitrate and/or Packet Loss Not Found!') - lock.release() - - bitrate = result.group('bitrate') - packetloss = result.group('packetloss') - lock.acquire() - logging.debug('\u001B[1;37;44m iperf result (' + UE_IPAddress + ') \u001B[0m') - logging.debug('\u001B[1;34m Bitrate : ' + bitrate + '\u001B[0m') - msg = 'Bitrate : ' + bitrate + '\n' - iperfStatus = True - if packetloss is not None: - logging.debug('\u001B[1;34m Packet Loss : ' + packetloss + '%\u001B[0m') - msg += 'Packet Loss : ' + packetloss + '%\n' - if float(packetloss) > float(self.iperf_packetloss_threshold): - logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') - msg += 'Packet Loss too high!\n' - iperfStatus = False - if (iperfStatus): - statusQueue.put(0) - else: - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - statusQueue.put(msg) - lock.release() - - def Iperf_UL_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue): - udpIperf = True - result = re.search('-u', str(self.iperf_args)) - if result is None: - udpIperf = False - ipnumbers = UE_IPAddress.split('.') - if (len(ipnumbers) == 4): - ipnumbers[3] = '1' - EPC_Iperf_UE_IPAddress = ipnumbers[0] + '.' + ipnumbers[1] + '.' + ipnumbers[2] + '.' + ipnumbers[3] - - # Launch iperf server on EPC side (true for ltebox and old open-air-cn0 - # But for OAI-Rel14-CUPS, we launch from python executor and we are using its IP address as iperf client address - launchFromEpc = True - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - launchFromEpc = False - cmd = 'hostname -I' - ret = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, encoding='utf-8') - if ret.stdout is not None: - EPC_Iperf_UE_IPAddress = ret.stdout.strip() - port = 5001 + idx - if launchFromEpc: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - if udpIperf: - self.command('echo $USER; nohup iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.EPCUserName, 5) - else: - self.command('echo $USER; nohup iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.EPCUserName, 5) - self.close() - else: - if self.ueIperfVersion == self.dummyIperfVersion: - prefix = '' - else: - prefix = '' - if self.ueIperfVersion == '2.0.5': - prefix = '/opt/iperf-2.0.5/bin/' - if udpIperf: - cmd = 'nohup ' + prefix + 'iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log 2>&1 &' - else: - cmd = 'nohup ' + prefix + 'iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log 2>&1 &' - logging.debug(cmd) - subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, encoding='utf-8') - time.sleep(0.5) - - # Launch iperf client on UE - if (device_id == 'OAI-UE'): - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) - else: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - iperf_time = self.Iperf_ComputeTime() - time.sleep(0.5) - - if udpIperf: - modified_options = self.Iperf_ComputeModifiedBW(idx, ue_num) - else: - modified_options = str(self.iperf_args) - modified_options = modified_options.replace('-R','') - time.sleep(0.5) - - self.command('rm -f iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - if (device_id == 'OAI-UE'): - iperf_status = self.command('iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + ' -B ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) - else: - if self.ADBCentralized: - iperf_status = self.command('stdbuf -o0 adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '" 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) - else: - iperf_status = self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '"\' 2>&1 > iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) - self.command('fromdos -o iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - self.command('cat iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - # TIMEOUT Case - if iperf_status < 0: - self.close() - message = 'iperf on UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT !' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) - return - clientStatus = self.Iperf_analyzeV2Output(lock, UE_IPAddress, device_id, statusQueue, modified_options) - self.close() - - # Kill iperf server on EPC side - if launchFromEpc: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('killall --signal SIGKILL iperf', self.EPCUserName, 5) - self.close() - else: - cmd = 'killall --signal SIGKILL iperf' - logging.debug(cmd) - subprocess.run(cmd, shell=True) - time.sleep(1) - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') - # in case of failure, retrieve server log - if (clientStatus == -1) or (clientStatus == -2): - if launchFromEpc: - time.sleep(1) - if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): - os.remove('iperf_server_' + self.testCase_id + '_' + device_id + '.log') - self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, self.EPCSourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') - self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) - # in case of OAI-UE - if (device_id == 'OAI-UE'): - self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_' + self.testCase_id + '_' + device_id + '.log', '.') - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') - - def Iperf_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue): - try: - # Single-UE profile -- iperf only on one UE - if self.iperf_profile == 'single-ue' and idx != 0: - return - useIperf3 = False - udpIperf = True - - self.ueIperfVersion = '2.0.5' - if (device_id != 'OAI-UE'): - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - # if by chance ADB server and EPC are on the same remote host, at least log collection will take care of it - self.command('if [ ! -d ' + self.EPCSourceCodePath + '/scripts ]; then mkdir -p ' + self.EPCSourceCodePath + '/scripts ; fi', '\$', 5) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - # Checking if iperf / iperf3 are installed - if self.ADBCentralized: - self.command('adb -s ' + device_id + ' shell "ls /data/local/tmp"', '\$', 5) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ls /data/local/tmp"\'', '\$', 60) - result = re.search('iperf3', str(self.ssh.before)) - if result is None: - result = re.search('iperf', str(self.ssh.before)) - if result is None: - message = 'Neither iperf nor iperf3 installed on UE!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) - return - else: - if self.ADBCentralized: - self.command('adb -s ' + device_id + ' shell "/data/local/tmp/iperf --version"', '\$', 5) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf --version"\'', '\$', 60) - result = re.search('iperf version 2.0.5', str(self.ssh.before)) - if result is not None: - self.ueIperfVersion = '2.0.5' - result = re.search('iperf version 2.0.10', str(self.ssh.before)) - if result is not None: - self.ueIperfVersion = '2.0.10' - else: - useIperf3 = True - self.close() - else: - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('iperf --version', '\$', 5) - result = re.search('iperf version 2.0.5', str(self.ssh.before)) - if result is not None: - self.ueIperfVersion = '2.0.5' - result = re.search('iperf version 2.0.10', str(self.ssh.before)) - if result is not None: - self.ueIperfVersion = '2.0.10' - self.close() - # in case of iperf, UL has its own function - if (not useIperf3): - result = re.search('-R', str(self.iperf_args)) - if result is not None: - self.Iperf_UL_common(lock, UE_IPAddress, device_id, idx, ue_num, statusQueue) - return - - # Launch the IPERF server on the UE side for DL - if (device_id == 'OAI-UE'): - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) - self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - result = re.search('-u', str(self.iperf_args)) - if result is None: - self.command('echo $USER; nohup iperf -B ' + UE_IPAddress + ' -s -i 1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.UEUserName, 5) - udpIperf = False - else: - self.command('echo $USER; nohup iperf -B ' + UE_IPAddress + ' -u -s -i 1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.UEUserName, 5) - else: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - if self.ADBCentralized: - if (useIperf3): - self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/iperf3 -s &', '\$', 5) - else: - self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - result = re.search('-u', str(self.iperf_args)) - if result is None: - self.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) - udpIperf = False - else: - self.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) - else: - self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - self.command('echo $USER; nohup ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" \' 2>&1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 60) - - time.sleep(0.5) - self.close() - - # Launch the IPERF client on the EPC side for DL (true for ltebox and old open-air-cn - # But for OAI-Rel14-CUPS, we launch from python executor - launchFromEpc = True - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - launchFromEpc = False - if launchFromEpc: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - iperf_time = self.Iperf_ComputeTime() - time.sleep(0.5) - - if udpIperf: - modified_options = self.Iperf_ComputeModifiedBW(idx, ue_num) - else: - modified_options = str(self.iperf_args) - time.sleep(0.5) - - if launchFromEpc: - self.command('rm -f iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - else: - if (os.path.isfile('iperf_' + self.testCase_id + '_' + device_id + '.log')): - os.remove('iperf_' + self.testCase_id + '_' + device_id + '.log') - if (useIperf3): - self.command('stdbuf -o0 iperf3 -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) - - clientStatus = 0 - self.Iperf_analyzeV3Output(lock, UE_IPAddress, device_id, statusQueue) - else: - if launchFromEpc: - iperf_status = self.command('stdbuf -o0 iperf -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) - else: - if self.ueIperfVersion == self.dummyIperfVersion: - prefix = '' - else: - prefix = '' - if self.ueIperfVersion == '2.0.5': - prefix = '/opt/iperf-2.0.5/bin/' - cmd = prefix + 'iperf -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 > iperf_' + self.testCase_id + '_' + device_id + '.log' - message = cmd + '\n' - logging.debug(cmd) - ret = subprocess.run(cmd, shell=True) - iperf_status = ret.returncode - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cat ' + self.EPCSourceCodePath + '/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - if iperf_status < 0: - if launchFromEpc: - self.close() - message = 'iperf on UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT !' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) - return - clientStatus = self.Iperf_analyzeV2Output(lock, UE_IPAddress, device_id, statusQueue, modified_options) - self.close() - - # Kill the IPERF server that runs in background - if (device_id == 'OAI-UE'): - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('killall iperf', '\$', 5) - else: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell ps | grep --color=never iperf | grep -v grep', '\$', 5) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ps" | grep --color=never iperf | grep -v grep\'', '\$', 60) - result = re.search('shell +(?P\d+)', str(self.ssh.before)) - if result is not None: - pid_iperf = result.group('pid') - if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell kill -KILL ' + pid_iperf, '\$', 5) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"\'', '\$', 60) - self.close() - # if the client report is absent, try to analyze the server log file - if (clientStatus == -1): - time.sleep(1) - if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): - os.remove('iperf_server_' + self.testCase_id + '_' + device_id + '.log') - if (device_id == 'OAI-UE'): - self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') - else: - self.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, self.EPCSourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') - self.command('fromdos -o iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) - - # in case of OAI UE: - if (device_id == 'OAI-UE'): - if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): - if not launchFromEpc: - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') - else: - self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def IperfNoS1(self): - if self.eNBIPAddress == '' or self.eNBUserName == '' or self.eNBPassword == '' or self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': - Usage() - sys.exit('Insufficient Parameter') - check_eNB = True - check_OAI_UE = True - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - self.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - server_on_enb = re.search('-R', str(self.iperf_args)) - if server_on_enb is not None: - iServerIPAddr = self.eNBIPAddress - iServerUser = self.eNBUserName - iServerPasswd = self.eNBPassword - iClientIPAddr = self.UEIPAddress - iClientUser = self.UEUserName - iClientPasswd = self.UEPassword - else: - iServerIPAddr = self.UEIPAddress - iServerUser = self.UEUserName - iServerPasswd = self.UEPassword - iClientIPAddr = self.eNBIPAddress - iClientUser = self.eNBUserName - iClientPasswd = self.eNBPassword - # Starting the iperf server - self.open(iServerIPAddr, iServerUser, iServerPasswd) - # args SHALL be "-c client -u any" - # -c 10.0.1.2 -u -b 1M -t 30 -i 1 -fm -B 10.0.1.1 - # -B 10.0.1.1 -u -s -i 1 -fm - server_options = re.sub('-u.*$', '-u -s -i 1 -fm', str(self.iperf_args)) - server_options = server_options.replace('-c','-B') - self.command('rm -f /tmp/tmp_iperf_server_' + self.testCase_id + '.log', '\$', 5) - self.command('echo $USER; nohup iperf ' + server_options + ' > /tmp/tmp_iperf_server_' + self.testCase_id + '.log 2>&1 &', iServerUser, 5) - time.sleep(0.5) - self.close() - - # Starting the iperf client - modified_options = self.Iperf_ComputeModifiedBW(0, 1) - modified_options = modified_options.replace('-R','') - iperf_time = self.Iperf_ComputeTime() - self.open(iClientIPAddr, iClientUser, iClientPasswd) - self.command('rm -f /tmp/tmp_iperf_' + self.testCase_id + '.log', '\$', 5) - iperf_status = self.command('stdbuf -o0 iperf ' + modified_options + ' 2>&1 | stdbuf -o0 tee /tmp/tmp_iperf_' + self.testCase_id + '.log', '\$', int(iperf_time)*5.0) - status_queue = SimpleQueue() - lock = Lock() - if iperf_status < 0: - message = 'iperf on OAI UE crashed due to TIMEOUT !' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - clientStatus = -2 - else: - clientStatus = self.Iperf_analyzeV2Output(lock, '10.0.1.2', 'OAI-UE', status_queue, modified_options) - self.close() - - # Stopping the iperf server - self.open(iServerIPAddr, iServerUser, iServerPasswd) - self.command('killall --signal SIGKILL iperf', '\$', 5) - time.sleep(0.5) - self.close() - if (clientStatus == -1): - if (os.path.isfile('iperf_server_' + self.testCase_id + '.log')): - os.remove('iperf_server_' + self.testCase_id + '.log') - self.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log') - self.Iperf_analyzeV2Server(lock, '10.0.1.2', 'OAI-UE', status_queue, modified_options) - - # copying on the EPC server for logCollection - copyin_res = self.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log') - if (copyin_res == 0): - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_OAI-UE.log', self.EPCSourceCodePath + '/scripts') - copyin_res = self.copyin(iClientIPAddr, iClientUser, iClientPasswd, '/tmp/tmp_iperf_' + self.testCase_id + '.log', 'iperf_' + self.testCase_id + '_OAI-UE.log') - if (copyin_res == 0): - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_' + self.testCase_id + '_OAI-UE.log', self.EPCSourceCodePath + '/scripts') - iperf_noperf = False - if status_queue.empty(): - iperf_status = False - else: - iperf_status = True - html_queue = SimpleQueue() - while (not status_queue.empty()): - count = status_queue.get() - if (count < 0): - iperf_status = False - if (count > 0): - iperf_noperf = True - device_id = status_queue.get() - ip_addr = status_queue.get() - message = status_queue.get() - html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' - html_queue.put(html_cell) - if (iperf_noperf and iperf_status): - self.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) - elif (iperf_status): - self.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) - else: - self.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) - self.AutoTerminateUEandeNB() - - def Iperf(self): - result = re.search('noS1', str(self.Initialize_eNB_args)) - if result is not None: - self.IperfNoS1() - return - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - check_eNB = True - if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): - check_OAI_UE = True - else: - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - self.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - ueIpStatus = self.GetAllUEIPAddresses() - if (ueIpStatus < 0): - self.CreateHtmlTestRow(self.iperf_args, 'KO', UE_IP_ADDRESS_ISSUE) - self.AutoTerminateUEandeNB() - return - - self.dummyIperfVersion = '2.0.10' - #cmd = 'iperf --version' - #logging.debug(cmd + '\n') - #iperfStdout = subprocess.check_output(cmd, shell=True, universal_newlines=True) - #result = re.search('iperf version 2.0.5', str(iperfStdout.strip())) - #if result is not None: - # dummyIperfVersion = '2.0.5' - #result = re.search('iperf version 2.0.10', str(iperfStdout.strip())) - #if result is not None: - # dummyIperfVersion = '2.0.10' - - multi_jobs = [] - i = 0 - ue_num = len(self.UEIPAddresses) - lock = Lock() - status_queue = SimpleQueue() - for UE_IPAddress in self.UEIPAddresses: - device_id = self.UEDevices[i] - p = Process(target = SSH.Iperf_common, args = (lock,UE_IPAddress,device_id,i,ue_num,status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - i = i + 1 - for job in multi_jobs: - job.join() - - if (status_queue.empty()): - self.CreateHtmlTestRow(self.iperf_args, 'KO', ALL_PROCESSES_OK) - self.AutoTerminateUEandeNB() - else: - iperf_status = True - iperf_noperf = False - html_queue = SimpleQueue() - while (not status_queue.empty()): - count = status_queue.get() - if (count < 0): - iperf_status = False - if (count > 0): - iperf_noperf = True - device_id = status_queue.get() - ip_addr = status_queue.get() - message = status_queue.get() - html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' - html_queue.put(html_cell) - if (iperf_noperf and iperf_status): - self.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) - elif (iperf_status): - self.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) - else: - self.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) - self.AutoTerminateUEandeNB() - - def CheckProcessExist(self, check_eNB, check_OAI_UE): - multi_jobs = [] - status_queue = SimpleQueue() - # in noS1 config, no need to check status from EPC - result = re.search('noS1', str(self.Initialize_eNB_args)) - if result is None: - p = Process(target = SSH.CheckHSSProcess, args = (status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - p = Process(target = SSH.CheckMMEProcess, args = (status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - p = Process(target = SSH.CheckSPGWProcess, args = (status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - else: - if (check_eNB == False) and (check_OAI_UE == False): - return 0 - if check_eNB: - p = Process(target = SSH.CheckeNBProcess, args = (status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - if check_OAI_UE: - p = Process(target = SSH.CheckOAIUEProcess, args = (status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - for job in multi_jobs: - job.join() - - if (status_queue.empty()): - return -15 - else: - result = 0 - while (not status_queue.empty()): - status = status_queue.get() - if (status < 0): - result = status - if result == ENB_PROCESS_FAILED: - fileCheck = re.search('enb_', str(self.eNBLogFiles[0])) - if fileCheck is not None: - self.copyin(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.eNBSourceCodePath + '/cmake_targets/' + self.eNBLogFiles[0], '.') - logStatus = self.AnalyzeLogFile_eNB(self.eNBLogFiles[0]) - if logStatus < 0: - result = logStatus - self.eNBLogFiles[0] = '' - if self.flexranCtrlInstalled and self.flexranCtrlStarted: - self.TerminateFlexranCtrl() - return result - - def CheckOAIUEProcessExist(self, initialize_OAI_UE_flag): - multi_jobs = [] - status_queue = SimpleQueue() - if initialize_OAI_UE_flag == False: - p = Process(target = SSH.CheckOAIUEProcess, args = (status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - for job in multi_jobs: - job.join() - - if (status_queue.empty()): - return -15 - else: - result = 0 - while (not status_queue.empty()): - status = status_queue.get() - if (status < 0): - result = status - if result == OAI_UE_PROCESS_FAILED: - fileCheck = re.search('ue_', str(self.UELogFile)) - if fileCheck is not None: - self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.') - logStatus = self.AnalyzeLogFile_UE(self.UELogFile) - if logStatus < 0: - result = logStatus - return result - - def CheckOAIUEProcess(self, status_queue): - try: - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('lte-uesoftmodem', str(self.ssh.before)) - if result is None: - logging.debug('\u001B[1;37;41m OAI UE Process Not Found! \u001B[0m') - status_queue.put(OAI_UE_PROCESS_FAILED) - else: - status_queue.put(OAI_UE_PROCESS_OK) - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def CheckeNBProcess(self, status_queue): - try: - self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) - self.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('lte-softmodem', str(self.ssh.before)) - if result is None: - logging.debug('\u001B[1;37;41m eNB Process Not Found! \u001B[0m') - status_queue.put(ENB_PROCESS_FAILED) - else: - status_queue.put(ENB_PROCESS_OK) - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def CheckHSSProcess(self, status_queue): - try: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('stdbuf -o0 ps -aux | grep --color=never hss | grep -v grep', '\$', 5) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - result = re.search('oai_hss -j', str(self.ssh.before)) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - result = re.search('hss_sim s6as diam_hss', str(self.ssh.before)) - else: - logging.error('This should not happen!') - if result is None: - logging.debug('\u001B[1;37;41m HSS Process Not Found! \u001B[0m') - status_queue.put(HSS_PROCESS_FAILED) - else: - status_queue.put(HSS_PROCESS_OK) - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def CheckMMEProcess(self, status_queue): - try: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('stdbuf -o0 ps -aux | grep --color=never mme | grep -v grep', '\$', 5) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - result = re.search('mme -c', str(self.ssh.before)) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - result = re.search('mme', str(self.ssh.before)) - else: - logging.error('This should not happen!') - if result is None: - logging.debug('\u001B[1;37;41m MME Process Not Found! \u001B[0m') - status_queue.put(MME_PROCESS_FAILED) - else: - status_queue.put(MME_PROCESS_OK) - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def CheckSPGWProcess(self, status_queue): - try: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('stdbuf -o0 ps -aux | grep --color=never spgw | grep -v grep', '\$', 5) - result = re.search('spgwu -c ', str(self.ssh.before)) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - self.command('stdbuf -o0 ps -aux | grep --color=never spgw | grep -v grep', '\$', 5) - result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('stdbuf -o0 ps -aux | grep --color=never xGw | grep -v grep', '\$', 5) - result = re.search('xGw', str(self.ssh.before)) - else: - logging.error('This should not happen!') - if result is None: - logging.debug('\u001B[1;37;41m SPGW Process Not Found! \u001B[0m') - status_queue.put(SPGW_PROCESS_FAILED) - else: - status_queue.put(SPGW_PROCESS_OK) - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def AnalyzeLogFile_eNB(self, eNBlogFile): - if (not os.path.isfile('./' + eNBlogFile)): - return -1 - enb_log_file = open('./' + eNBlogFile, 'r') - exitSignalReceived = False - foundAssertion = False - msgAssertion = '' - msgLine = 0 - foundSegFault = False - foundRealTimeIssue = False - rrcSetupComplete = 0 - rrcReleaseRequest = 0 - rrcReconfigRequest = 0 - rrcReconfigComplete = 0 - rrcReestablishRequest = 0 - rrcReestablishComplete = 0 - rrcReestablishReject = 0 - rlcDiscardBuffer = 0 - rachCanceledProcedure = 0 - uciStatMsgCount = 0 - pdcpFailure = 0 - ulschFailure = 0 - cdrxActivationMessageCount = 0 - dropNotEnoughRBs = 0 - self.htmleNBFailureMsg = '' - isRRU = False - isSlave = False - slaveReceivesFrameResyncCmd = False - X2HO_state = X2_HO_REQ_STATE__IDLE - X2HO_inNbProcedures = 0 - X2HO_outNbProcedures = 0 - for line in enb_log_file.readlines(): - if X2HO_state == X2_HO_REQ_STATE__IDLE: - result = re.search('target eNB Receives X2 HO Req X2AP_HANDOVER_REQ', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__TARGET_RECEIVES_REQ - result = re.search('source eNB receives the X2 HO ACK X2AP_HANDOVER_REQ_ACK', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK - if X2HO_state == X2_HO_REQ_STATE__TARGET_RECEIVES_REQ: - result = re.search('Received LTE_RRCConnectionReconfigurationComplete from UE', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE - if X2HO_state == X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE: - result = re.search('issue rrc_eNB_send_PATH_SWITCH_REQ', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ - if X2HO_state == X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ: - result = re.search('received path switch ack S1AP_PATH_SWITCH_REQ_ACK', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__IDLE - X2HO_inNbProcedures += 1 - if X2HO_state == X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK: - result = re.search('source eNB receives the X2 UE CONTEXT RELEASE X2AP_UE_CONTEXT_RELEASE', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__IDLE - X2HO_outNbProcedures += 1 - - if self.eNBOptions[int(self.eNB_instance)] != '': - res1 = re.search('max_rxgain (?P[0-9]+)', self.eNBOptions[int(self.eNB_instance)]) - res2 = re.search('max_rxgain (?P[0-9]+)', str(line)) - if res1 is not None and res2 is not None: - requested_option = int(res1.group('requested_option')) - applied_option = int(res2.group('applied_option')) - if requested_option == applied_option: - self.htmleNBFailureMsg += ' Command line option(s) correctly applied ' + self.eNBOptions[int(self.eNB_instance)] + '\n\n' - else: - self.htmleNBFailureMsg += ' Command line option(s) NOT applied ' + self.eNBOptions[int(self.eNB_instance)] + '\n\n' - result = re.search('Exiting OAI softmodem', str(line)) - if result is not None: - exitSignalReceived = True - result = re.search('[Ss]egmentation [Ff]ault', str(line)) - 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)) - if result is not None and not exitSignalReceived: - foundAssertion = True - result = re.search('LLL', str(line)) - if result is not None and not exitSignalReceived: - foundRealTimeIssue = True - if foundAssertion and (msgLine < 3): - msgLine += 1 - msgAssertion += str(line) - result = re.search('Setting function for RU', str(line)) - if result is not None: - isRRU = True - if isRRU: - result = re.search('RU 0 is_slave=yes', str(line)) - if result is not None: - isSlave = True - if isSlave: - result = re.search('Received RRU_frame_resynch command', str(line)) - if result is not None: - slaveReceivesFrameResyncCmd = True - result = re.search('LTE_RRCConnectionSetupComplete from UE', str(line)) - if result is not None: - rrcSetupComplete += 1 - result = re.search('Generate LTE_RRCConnectionRelease|Generate RRCConnectionRelease', str(line)) - if result is not None: - rrcReleaseRequest += 1 - result = re.search('Generate LTE_RRCConnectionReconfiguration', str(line)) - if result is not None: - rrcReconfigRequest += 1 - result = re.search('LTE_RRCConnectionReconfigurationComplete from UE rnti', str(line)) - if result is not None: - rrcReconfigComplete += 1 - result = re.search('LTE_RRCConnectionReestablishmentRequest', str(line)) - if result is not None: - rrcReestablishRequest += 1 - result = re.search('LTE_RRCConnectionReestablishmentComplete', str(line)) - if result is not None: - rrcReestablishComplete += 1 - result = re.search('LTE_RRCConnectionReestablishmentReject', str(line)) - if result is not None: - rrcReestablishReject += 1 - result = re.search('CDRX configuration activated after RRC Connection', str(line)) - if result is not None: - cdrxActivationMessageCount += 1 - result = re.search('uci->stat', str(line)) - if result is not None: - uciStatMsgCount += 1 - result = re.search('PDCP.*Out of Resources.*reason', str(line)) - if result is not None: - pdcpFailure += 1 - result = re.search('ULSCH in error in round', str(line)) - if result is not None: - ulschFailure += 1 - result = re.search('BAD all_segments_received', str(line)) - if result is not None: - rlcDiscardBuffer += 1 - 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: - statMsg = 'eNB showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmleNBFailureMsg += statMsg + '\n' - if pdcpFailure > 0: - statMsg = 'eNB showed ' + str(pdcpFailure) + ' "PDCP Out of Resources" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmleNBFailureMsg += statMsg + '\n' - if ulschFailure > 0: - 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') - self.htmleNBFailureMsg += rrcMsg + '\n' - if rrcReleaseRequest > 0: - rrcMsg = 'eNB requested ' + str(rrcReleaseRequest) + ' RRC Connection Release(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if rrcReconfigRequest > 0 or rrcReconfigComplete > 0: - rrcMsg = 'eNB requested ' + str(rrcReconfigRequest) + ' RRC Connection Reconfiguration(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - rrcMsg = ' -- ' + str(rrcReconfigComplete) + ' were completed' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if rrcReestablishRequest > 0 or rrcReestablishComplete > 0 or rrcReestablishReject > 0: - rrcMsg = 'eNB requested ' + str(rrcReestablishRequest) + ' RRC Connection Reestablishment(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - rrcMsg = ' -- ' + str(rrcReestablishComplete) + ' were completed' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - rrcMsg = ' -- ' + str(rrcReestablishReject) + ' were rejected' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if X2HO_inNbProcedures > 0: - rrcMsg = 'eNB completed ' + str(X2HO_inNbProcedures) + ' X2 Handover Connection procedure(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if X2HO_outNbProcedures > 0: - rrcMsg = 'eNB completed ' + str(X2HO_outNbProcedures) + ' X2 Handover Release procedure(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if self.eNBOptions[int(self.eNB_instance)] != '': - res1 = re.search('drx_Config_present prSetup', self.eNBOptions[int(self.eNB_instance)]) - if res1 is not None: - if cdrxActivationMessageCount > 0: - rrcMsg = 'eNB activated the CDRX Configuration for ' + str(cdrxActivationMessageCount) + ' time(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - else: - rrcMsg = 'eNB did NOT ACTIVATE the CDRX Configuration' - logging.debug('\u001B[1;37;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if rachCanceledProcedure > 0: - rachMsg = 'eNB cancelled ' + str(rachCanceledProcedure) + ' RA procedure(s)' - logging.debug('\u001B[1;30;43m ' + rachMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rachMsg + '\n' - if isRRU: - if isSlave: - if slaveReceivesFrameResyncCmd: - rruMsg = 'Slave RRU received the RRU_frame_resynch command from RAU' - logging.debug('\u001B[1;30;43m ' + rruMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rruMsg + '\n' - else: - rruMsg = 'Slave RRU DID NOT receive the RRU_frame_resynch command from RAU' - logging.debug('\u001B[1;37;41m ' + rruMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rruMsg + '\n' - self.prematureExit = True - return ENB_PROCESS_SLAVE_RRU_NOT_SYNCED - if foundSegFault: - logging.debug('\u001B[1;37;41m eNB ended with a Segmentation Fault! \u001B[0m') - return ENB_PROCESS_SEG_FAULT - if foundAssertion: - logging.debug('\u001B[1;37;41m eNB ended with an assertion! \u001B[0m') - self.htmleNBFailureMsg += msgAssertion - return ENB_PROCESS_ASSERTION - if foundRealTimeIssue: - logging.debug('\u001B[1;37;41m eNB faced real time issues! \u001B[0m') - self.htmleNBFailureMsg += 'eNB faced real time issues!\n' - #return ENB_PROCESS_REALTIME_ISSUE - if rlcDiscardBuffer > 0: - rlcMsg = 'eNB RLC discarded ' + str(rlcDiscardBuffer) + ' buffer(s)' - logging.debug('\u001B[1;37;41m ' + rlcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rlcMsg + '\n' - return ENB_PROCESS_REALTIME_ISSUE - return 0 - - def AnalyzeLogFile_UE(self, UElogFile): - if (not os.path.isfile('./' + UElogFile)): - return -1 - ue_log_file = open('./' + UElogFile, 'r') - exitSignalReceived = False - foundAssertion = False - msgAssertion = '' - msgLine = 0 - foundSegFault = False - foundRealTimeIssue = False - uciStatMsgCount = 0 - pdcpDataReqFailedCount = 0 - badDciCount = 0 - rrcConnectionRecfgComplete = 0 - no_cell_sync_found = False - mib_found = False - frequency_found = False - plmn_found = False - self.htmlUEFailureMsg = '' - for line in ue_log_file.readlines(): - result = re.search('Exiting OAI softmodem', str(line)) - if result is not None: - exitSignalReceived = True - result = re.search('System error|[Ss]egmentation [Ff]ault|======= Backtrace: =========|======= Memory map: ========', str(line)) - 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)) - if result is not None and not exitSignalReceived: - foundAssertion = True - result = re.search('LLL', str(line)) - if result is not None and not exitSignalReceived: - foundRealTimeIssue = True - if foundAssertion and (msgLine < 3): - msgLine += 1 - msgAssertion += str(line) - result = re.search('uci->stat', str(line)) - if result is not None and not exitSignalReceived: - uciStatMsgCount += 1 - result = re.search('PDCP data request failed', str(line)) - if result is not None and not exitSignalReceived: - pdcpDataReqFailedCount += 1 - result = re.search('bad DCI 1A', str(line)) - if result is not None and not exitSignalReceived: - badDciCount += 1 - result = re.search('Generating RRCConnectionReconfigurationComplete', str(line)) - if result is not None: - rrcConnectionRecfgComplete += 1 - # No cell synchronization found, abandoning - result = re.search('No cell synchronization found, abandoning', str(line)) - if result is not None: - no_cell_sync_found = True - result = re.search("MIB Information => ([a-zA-Z]{1,10}), ([a-zA-Z]{1,10}), NidCell (?P\d{1,3}), N_RB_DL (?P\d{1,3}), PHICH DURATION (?P\d), PHICH RESOURCE (?P.{1,4}), TX_ANT (?P\d)", str(line)) - if result is not None and (not mib_found): - try: - mibMsg = "MIB Information: " + result.group(1) + ', ' + result.group(2) - self.htmlUEFailureMsg += mibMsg + '\n' - logging.debug('\033[94m' + mibMsg + '\033[0m') - mibMsg = " nidcell = " + result.group('nidcell') - self.htmlUEFailureMsg += mibMsg - logging.debug('\033[94m' + mibMsg + '\033[0m') - mibMsg = " n_rb_dl = " + result.group('n_rb_dl') - self.htmlUEFailureMsg += mibMsg + '\n' - logging.debug('\033[94m' + mibMsg + '\033[0m') - mibMsg = " phich_duration = " + result.group('phich_duration') - self.htmlUEFailureMsg += mibMsg - logging.debug('\033[94m' + mibMsg + '\033[0m') - mibMsg = " phich_resource = " + result.group('phich_resource') - self.htmlUEFailureMsg += mibMsg + '\n' - logging.debug('\033[94m' + mibMsg + '\033[0m') - mibMsg = " tx_ant = " + result.group('tx_ant') - self.htmlUEFailureMsg += mibMsg + '\n' - logging.debug('\033[94m' + mibMsg + '\033[0m') - mib_found = True - except Exception as e: - logging.error('\033[91m' + "MIB marker was not found" + '\033[0m') - result = re.search("Measured Carrier Frequency (?P\d{1,15}) Hz", str(line)) - if result is not None and (not frequency_found): - try: - mibMsg = "Measured Carrier Frequency = " + result.group('measured_carrier_frequency') + ' Hz' - self.htmlUEFailureMsg += mibMsg + '\n' - logging.debug('\033[94m' + mibMsg + '\033[0m') - frequency_found = True - except Exception as e: - logging.error('\033[91m' + "Measured Carrier Frequency not found" + '\033[0m') - result = re.search("PLMN MCC (?P\d{1,3}), MNC (?P\d{1,3}), TAC", str(line)) - if result is not None and (not plmn_found): - try: - mibMsg = 'PLMN MCC = ' + result.group('mcc') + ' MNC = ' + result.group('mnc') - self.htmlUEFailureMsg += mibMsg + '\n' - logging.debug('\033[94m' + mibMsg + '\033[0m') - plmn_found = True - except Exception as e: - logging.error('\033[91m' + "PLMN not found" + '\033[0m') - result = re.search("Found (?P[\w,\s]{1,15}) \(name from internal table\)", str(line)) - if result is not None: - try: - mibMsg = "The operator is: " + result.group('operator') - self.htmlUEFailureMsg += mibMsg + '\n' - logging.debug('\033[94m' + mibMsg + '\033[0m') - except Exception as e: - logging.error('\033[91m' + "Operator name not found" + '\033[0m') - result = re.search("SIB5 InterFreqCarrierFreq element (.{1,4})/(.{1,4})", str(line)) - if result is not None: - try: - mibMsg = "SIB5 InterFreqCarrierFreq element " + result.group(1) + '/' + result.group(2) - self.htmlUEFailureMsg += mibMsg + ' -> ' - logging.debug('\033[94m' + mibMsg + '\033[0m') - except Exception as e: - logging.error('\033[91m' + "SIB5 InterFreqCarrierFreq element not found" + '\033[0m') - result = re.search("DL Carrier Frequency/ARFCN : (?P\d{1,15}/\d{1,4})", str(line)) - if result is not None: - try: - freq = result.group('carrier_frequency') - new_freq = re.sub('/[0-9]+','',freq) - float_freq = float(new_freq) / 1000000 - self.htmlUEFailureMsg += 'DL Freq: ' + ('%.1f' % float_freq) + ' MHz' - logging.debug('\033[94m' + " DL Carrier Frequency is: " + freq + '\033[0m') - except Exception as e: - logging.error('\033[91m' + " DL Carrier Frequency not found" + '\033[0m') - result = re.search("AllowedMeasBandwidth : (?P\d{1,7})", str(line)) - if result is not None: - try: - prb = result.group('allowed_bandwidth') - self.htmlUEFailureMsg += ' -- PRB: ' + prb + '\n' - logging.debug('\033[94m' + " AllowedMeasBandwidth: " + prb + '\033[0m') - except Exception as e: - logging.error('\033[91m' + " AllowedMeasBandwidth not found" + '\033[0m') - ue_log_file.close() - if rrcConnectionRecfgComplete > 0: - statMsg = 'UE connected to eNB (' + str(rrcConnectionRecfgComplete) + ' RRCConnectionReconfigurationComplete message(s) generated)' - logging.debug('\033[94m' + statMsg + '\033[0m') - self.htmlUEFailureMsg += statMsg + '\n' - if uciStatMsgCount > 0: - statMsg = 'UE showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' - if pdcpDataReqFailedCount > 0: - statMsg = 'UE showed ' + str(pdcpDataReqFailedCount) + ' "PDCP data request failed" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' - if badDciCount > 0: - statMsg = 'UE showed ' + str(badDciCount) + ' "bad DCI 1A" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' - if foundSegFault: - logging.debug('\u001B[1;37;41m UE ended with a Segmentation Fault! \u001B[0m') - return ENB_PROCESS_SEG_FAULT - if foundAssertion: - logging.debug('\u001B[1;30;43m UE showed an assertion! \u001B[0m') - self.htmlUEFailureMsg += 'UE showed an assertion!\n' - if not mib_found or not frequency_found: - return OAI_UE_PROCESS_ASSERTION - if foundRealTimeIssue: - logging.debug('\u001B[1;37;41m UE faced real time issues! \u001B[0m') - self.htmlUEFailureMsg += 'UE faced real time issues!\n' - #return ENB_PROCESS_REALTIME_ISSUE - if no_cell_sync_found and not mib_found: - logging.debug('\u001B[1;37;41m UE could not synchronize ! \u001B[0m') - self.htmlUEFailureMsg += 'UE could not synchronize!\n' - return OAI_UE_PROCESS_COULD_NOT_SYNC - return 0 - - def TerminateeNB(self): - if self.eNB_serverId == '0': - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - lSourcePath = self.eNBSourceCodePath - elif self.eNB_serverId == '1': - lIpAddr = self.eNB1IPAddress - lUserName = self.eNB1UserName - lPassWord = self.eNB1Password - lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId == '2': - lIpAddr = self.eNB2IPAddress - lUserName = self.eNB2UserName - lPassWord = self.eNB2Password - lSourcePath = self.eNB2SourceCodePath - if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(lIpAddr, lUserName, lPassWord) - self.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) - self.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('lte-softmodem', str(self.ssh.before)) - if result is not None: - self.command('echo ' + lPassWord + ' | sudo -S daemon --name=enb' + str(self.eNB_instance) + '_daemon --stop', '\$', 5) - self.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGINT lte-softmodem || true', '\$', 5) - time.sleep(10) - self.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('lte-softmodem', str(self.ssh.before)) - if result is not None: - self.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGKILL lte-softmodem || true', '\$', 5) - time.sleep(5) - self.command('rm -f my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - self.close() - # If tracer options is on, stopping tshark on EPC side - result = re.search('T_stdout', str(self.Initialize_eNB_args)) - if result is not None: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - logging.debug('\u001B[1m Stopping tshark \u001B[0m') - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) - time.sleep(1) - if self.EPC_PcapFileName != '': - self.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 /tmp/' + self.EPC_PcapFileName, '\$', 5) - self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + self.EPC_PcapFileName, '.') - self.copyout(lIpAddr, lUserName, lPassWord, self.EPC_PcapFileName, lSourcePath + '/cmake_targets/.') - self.close() - logging.debug('\u001B[1m Replaying RAW record file\u001B[0m') - self.open(lIpAddr, lUserName, lPassWord) - self.command('cd ' + lSourcePath + '/common/utils/T/tracer/', '\$', 5) - enbLogFile = self.eNBLogFiles[int(self.eNB_instance)] - raw_record_file = enbLogFile.replace('.log', '_record.raw') - replay_log_file = enbLogFile.replace('.log', '_replay.log') - extracted_txt_file = enbLogFile.replace('.log', '_extracted_messages.txt') - extracted_log_file = enbLogFile.replace('.log', '_extracted_messages.log') - self.command('./extract_config -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + extracted_txt_file, '\$', 5) - self.command('echo $USER; nohup ./replay -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + replay_log_file + ' 2>&1 &', lUserName, 5) - self.command('./textlog -d ' + lSourcePath + '/cmake_targets/' + extracted_txt_file + ' -no-gui -ON -full > ' + lSourcePath + '/cmake_targets/' + extracted_log_file, '\$', 5) - self.close() - self.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + extracted_log_file, '.') - logging.debug('\u001B[1m Analyzing eNB replay logfile \u001B[0m') - logStatus = self.AnalyzeLogFile_eNB(extracted_log_file) - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - self.eNBLogFiles[int(self.eNB_instance)] = '' - else: - analyzeFile = False - if self.eNBLogFiles[int(self.eNB_instance)] != '': - analyzeFile = True - fileToAnalyze = self.eNBLogFiles[int(self.eNB_instance)] - self.eNBLogFiles[int(self.eNB_instance)] = '' - if analyzeFile: - copyin_res = self.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + fileToAnalyze, '.') - if (copyin_res == -1): - logging.debug('\u001B[1;37;41m Could not copy eNB logfile to analyze it! \u001B[0m') - self.htmleNBFailureMsg = 'Could not copy eNB logfile to analyze it!' - self.CreateHtmlTestRow('N/A', 'KO', ENB_PROCESS_NOLOGFILE_TO_ANALYZE) - return - if self.eNB_serverId != '0': - self.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './' + fileToAnalyze, self.eNBSourceCodePath + '/cmake_targets/') - logging.debug('\u001B[1m Analyzing eNB logfile \u001B[0m ' + fileToAnalyze) - logStatus = self.AnalyzeLogFile_eNB(fileToAnalyze) - if (logStatus < 0): - self.CreateHtmlTestRow('N/A', 'KO', logStatus) - self.preamtureExit = True - return - else: - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - else: - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def TerminateHSS(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT oai_hss || true', '\$', 5) - time.sleep(2) - self.command('stdbuf -o0 ps -aux | grep hss | grep -v grep', '\$', 5) - result = re.search('oai_hss -j', str(self.ssh.before)) - if result is not None: - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL oai_hss || true', '\$', 5) - self.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-hss.sh', '\$', 5) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_hss oai_hss || true', '\$', 5) - time.sleep(2) - self.command('stdbuf -o0 ps -aux | grep hss | grep -v grep', '\$', 5) - result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) - if result is not None: - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_hss oai_hss || true', '\$', 5) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('cd scripts', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S daemon --name=simulated_hss --stop', '\$', 5) - time.sleep(1) - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL hss_sim', '\$', 5) - else: - logging.error('This should not happen!') - self.close() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def TerminateMME(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_mme mme || true', '\$', 5) - time.sleep(2) - self.command('stdbuf -o0 ps -aux | grep mme | grep -v grep', '\$', 5) - result = re.search('mme -c', str(self.ssh.before)) - if result is not None: - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_mme mme || true', '\$', 5) - self.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-mme.sh', '\$', 5) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cd /opt/ltebox/tools', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S ./stop_mme', '\$', 5) - else: - logging.error('This should not happen!') - self.close() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def TerminateSPGW(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT spgwc spgwu || true', '\$', 5) - time.sleep(2) - self.command('stdbuf -o0 ps -aux | grep spgw | grep -v grep', '\$', 5) - result = re.search('spgwc -c |spgwu -c ', str(self.ssh.before)) - if result is not None: - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL spgwc spgwu || true', '\$', 5) - self.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-spgw*.sh', '\$', 5) - self.command('stdbuf -o0 ps -aux | grep tshark | grep -v grep', '\$', 5) - result = re.search('-w ', str(self.ssh.before)) - if result is not None: - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT tshark || true', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 ' + self.EPCSourceCodePath + '/scripts/*.pcap', '\$', 5) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_spgw spgw || true', '\$', 5) - time.sleep(2) - self.command('stdbuf -o0 ps -aux | grep spgw | grep -v grep', '\$', 5) - result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) - if result is not None: - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_spgw spgw || true', '\$', 5) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cd /opt/ltebox/tools', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S ./stop_xGw', '\$', 5) - else: - logging.error('This should not happen!') - self.close() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def TerminateFlexranCtrl(self): - if self.flexranCtrlInstalled == False or self.flexranCtrlStarted == False: - return - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('echo ' + self.EPCPassword + ' | sudo -S daemon --name=flexran_rtc_daemon --stop', '\$', 5) - time.sleep(1) - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL rt_controller', '\$', 5) - time.sleep(1) - self.close() - self.flexranCtrlStarted = False - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def TerminateUE_common(self, device_id, idx): - try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - # back in airplane mode on (ie radio off) - if self.ADBCentralized: - if device_id == '84B7N16418004022': - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) - else: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) - logging.debug('\u001B[1mUE (' + device_id + ') Detach Completed\u001B[0m') - - if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "ps | grep --color=never iperf | grep -v grep"', '\$', 5) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ps | grep --color=never iperf | grep -v grep"\'', '\$', 60) - result = re.search('shell +(?P\d+)', str(self.ssh.before)) - if result is not None: - pid_iperf = result.group('pid') - if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"', '\$', 5) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"\'', '\$', 60) - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def TerminateUE(self): - terminate_ue_flag = True - self.GetAllUEDevices(terminate_ue_flag) - multi_jobs = [] - i = 0 - for device_id in self.UEDevices: - p = Process(target= SSH.TerminateUE_common, args = (device_id,i,)) - p.daemon = True - p.start() - multi_jobs.append(p) - i += 1 - for job in multi_jobs: - job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def TerminateOAIUE(self): - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) - self.command('ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('lte-uesoftmodem', str(self.ssh.before)) - if result is not None: - self.command('echo ' + self.UEPassword + ' | sudo -S daemon --name=ue' + str(self.UE_instance) + '_daemon --stop', '\$', 5) - self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGINT lte-uesoftmodem || true', '\$', 5) - time.sleep(10) - self.command('ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('lte-uesoftmodem', str(self.ssh.before)) - if result is not None: - self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGKILL lte-uesoftmodem || true', '\$', 5) - time.sleep(5) - self.command('rm -f my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) - self.close() - result = re.search('ue_', str(self.UELogFile)) - if result is not None: - copyin_res = self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.') - if (copyin_res == -1): - logging.debug('\u001B[1;37;41m Could not copy UE logfile to analyze it! \u001B[0m') - self.htmlUEFailureMsg = 'Could not copy UE logfile to analyze it!' - self.CreateHtmlTestRow('N/A', 'KO', OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE, 'UE') - self.UELogFile = '' - return - logging.debug('\u001B[1m Analyzing UE logfile \u001B[0m') - logStatus = self.AnalyzeLogFile_UE(self.UELogFile) - result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) - if result is not None: - ueAction = 'Sniffing' - else: - ueAction = 'Connection' - if (logStatus < 0): - logging.debug('\u001B[1m' + ueAction + ' Failed \u001B[0m') - self.htmlUEFailureMsg = '' + ueAction + ' Failed\n' + self.htmlUEFailureMsg - self.CreateHtmlTestRow('N/A', 'KO', logStatus, 'UE') - # In case of sniffing on commercial eNBs we have random results - # Not an error then - if (logStatus != OAI_UE_PROCESS_COULD_NOT_SYNC) or (ueAction != 'Sniffing'): - self.Initialize_OAI_UE_args = '' - self.AutoTerminateUEandeNB() - else: - logging.debug('\u001B[1m' + ueAction + ' Completed \u001B[0m') - self.htmlUEFailureMsg = '' + ueAction + ' Completed\n' + self.htmlUEFailureMsg - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - self.UELogFile = '' - else: - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def AutoTerminateUEandeNB(self): - if (self.ADBIPAddress != 'none'): - self.testCase_id = 'AUTO-KILL-UE' - self.desc = 'Automatic Termination of UE' - self.ShowTestID() - self.TerminateUE() - if (self.Initialize_OAI_UE_args != ''): - self.testCase_id = 'AUTO-KILL-UE' - self.desc = 'Automatic Termination of UE' - self.ShowTestID() - self.TerminateOAIUE() - if (self.Initialize_eNB_args != ''): - self.testCase_id = 'AUTO-KILL-eNB' - self.desc = 'Automatic Termination of eNB' - self.ShowTestID() - self.eNB_instance = '0' - self.TerminateeNB() - if self.flexranCtrlInstalled and self.flexranCtrlStarted: - self.testCase_id = 'AUTO-KILL-flexran-ctl' - self.desc = 'Automatic Termination of FlexRan CTL' - self.ShowTestID() - self.TerminateFlexranCtrl() - self.prematureExit = True - - def IdleSleep(self): - time.sleep(self.idle_sleep_time) - self.CreateHtmlTestRow(str(self.idle_sleep_time) + ' sec', 'OK', ALL_PROCESSES_OK) - - def X2_Status(self, idx, fileName): - cmd = "curl --silent http://" + self.EPCIPAddress + ":9999/stats | jq '.' > " + fileName - message = cmd + '\n' - logging.debug(cmd) - subprocess.run(cmd, shell=True) - if idx == 0: - cmd = "jq '.mac_stats | length' " + fileName - strNbEnbs = subprocess.check_output(cmd, shell=True, universal_newlines=True) - self.x2NbENBs = int(strNbEnbs.strip()) - cnt = 0 - while cnt < self.x2NbENBs: - cmd = "jq '.mac_stats[" + str(cnt) + "].bs_id' " + fileName - bs_id = subprocess.check_output(cmd, shell=True, universal_newlines=True) - self.x2ENBBsIds[idx].append(bs_id.strip()) - cmd = "jq '.mac_stats[" + str(cnt) + "].ue_mac_stats | length' " + fileName - stNbUEs = subprocess.check_output(cmd, shell=True, universal_newlines=True) - nbUEs = int(stNbUEs.strip()) - ueIdx = 0 - self.x2ENBConnectedUEs[idx].append([]) - while ueIdx < nbUEs: - cmd = "jq '.mac_stats[" + str(cnt) + "].ue_mac_stats[" + str(ueIdx) + "].rnti' " + fileName - rnti = subprocess.check_output(cmd, shell=True, universal_newlines=True) - self.x2ENBConnectedUEs[idx][cnt].append(rnti.strip()) - ueIdx += 1 - cnt += 1 - - msg = "FlexRan Controller is connected to " + str(self.x2NbENBs) + " eNB(s)" - logging.debug(msg) - message += msg + '\n' - cnt = 0 - while cnt < self.x2NbENBs: - msg = " -- eNB: " + str(self.x2ENBBsIds[idx][cnt]) + " is connected to " + str(len(self.x2ENBConnectedUEs[idx][cnt])) + " UE(s)" - logging.debug(msg) - message += msg + '\n' - ueIdx = 0 - while ueIdx < len(self.x2ENBConnectedUEs[idx][cnt]): - msg = " -- UE rnti: " + str(self.x2ENBConnectedUEs[idx][cnt][ueIdx]) - logging.debug(msg) - message += msg + '\n' - ueIdx += 1 - cnt += 1 - return message - - def Perform_X2_Handover(self): - html_queue = SimpleQueue() - fullMessage = '
'
-		msg = 'Doing X2 Handover w/ option ' + self.x2_ho_options
-		logging.debug(msg)
-		fullMessage += msg + '\n'
-		if self.x2_ho_options == 'network':
-			if self.flexranCtrlInstalled and self.flexranCtrlStarted:
-				self.x2ENBBsIds = []
-				self.x2ENBConnectedUEs = []
-				self.x2ENBBsIds.append([])
-				self.x2ENBBsIds.append([])
-				self.x2ENBConnectedUEs.append([])
-				self.x2ENBConnectedUEs.append([])
-				fullMessage += self.X2_Status(0, self.testCase_id + '_pre_ho.json') 
-
-				msg = "Activating the X2 Net control on each eNB"
-				logging.debug(msg)
-				fullMessage += msg + '\n'
-				eNB_cnt = self.x2NbENBs
-				cnt = 0
-				while cnt < eNB_cnt:
-					cmd = "curl -XPOST http://" + self.EPCIPAddress + ":9999/rrc/x2_ho_net_control/enb/" + str(self.x2ENBBsIds[0][cnt]) + "/1"
-					logging.debug(cmd)
-					fullMessage += cmd + '\n'
-					subprocess.run(cmd, shell=True)
-					cnt += 1
-				# Waiting for the activation to be active
-				time.sleep(10)
-				msg = "Switching UE(s) from eNB to eNB"
-				logging.debug(msg)
-				fullMessage += msg + '\n'
-				cnt = 0
-				while cnt < eNB_cnt:
-					ueIdx = 0
-					while ueIdx < len(self.x2ENBConnectedUEs[0][cnt]):
-						cmd = "curl -XPOST http://" + self.EPCIPAddress + ":9999/rrc/ho/senb/" + str(self.x2ENBBsIds[0][cnt]) + "/ue/" + str(self.x2ENBConnectedUEs[0][cnt][ueIdx]) + "/tenb/" + str(self.x2ENBBsIds[0][eNB_cnt - cnt - 1])
-						logging.debug(cmd)
-						fullMessage += cmd + '\n'
-						subprocess.run(cmd, shell=True)
-						ueIdx += 1
-					cnt += 1
-				time.sleep(10)
-				# check
-				logging.debug("Checking the Status after X2 Handover")
-				fullMessage += self.X2_Status(1, self.testCase_id + '_post_ho.json') 
-				cnt = 0
-				x2Status = True
-				while cnt < eNB_cnt:
-					if len(self.x2ENBConnectedUEs[0][cnt]) == len(self.x2ENBConnectedUEs[1][cnt]):
-						x2Status = False
-					cnt += 1
-				if x2Status:
-					msg = "X2 Handover was successful"
-					logging.debug(msg)
-					fullMessage += msg + '
' - html_queue.put(fullMessage) - self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) - else: - msg = "X2 Handover FAILED" - logging.error(msg) - fullMessage += msg + '' - html_queue.put(fullMessage) - self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) - else: - self.CreateHtmlTestRow('Cannot perform requested X2 Handover', 'KO', ALL_PROCESSES_OK) - - def LogCollectBuild(self): - if (self.eNBIPAddress != '' and self.eNBUserName != '' and self.eNBPassword != ''): - IPAddress = self.eNBIPAddress - UserName = self.eNBUserName - Password = self.eNBPassword - SourceCodePath = self.eNBSourceCodePath - elif (self.UEIPAddress != '' and self.UEUserName != '' and self.UEPassword != ''): - IPAddress = self.UEIPAddress - UserName = self.UEUserName - Password = self.UEPassword - SourceCodePath = self.UESourceCodePath - else: - sys.exit('Insufficient Parameter') - self.open(IPAddress, UserName, Password) - self.command('cd ' + SourceCodePath, '\$', 5) - self.command('cd cmake_targets', '\$', 5) - self.command('rm -f build.log.zip', '\$', 5) - self.command('zip build.log.zip build_log_*/*', '\$', 60) - self.close() - - def LogCollecteNB(self): - self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) - self.command('cd ' + self.eNBSourceCodePath, '\$', 5) - self.command('cd cmake_targets', '\$', 5) - self.command('echo ' + self.eNBPassword + ' | sudo -S rm -f enb.log.zip', '\$', 5) - self.command('echo ' + self.eNBPassword + ' | sudo -S zip enb.log.zip enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 60) - self.command('echo ' + self.eNBPassword + ' | sudo -S rm enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 5) - self.close() - - def LogCollectPing(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('cd scripts', '\$', 5) - self.command('rm -f ping.log.zip', '\$', 5) - self.command('zip ping.log.zip ping*.log', '\$', 60) - self.command('rm ping*.log', '\$', 5) - self.close() - - def LogCollectIperf(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('cd scripts', '\$', 5) - self.command('rm -f iperf.log.zip', '\$', 5) - self.command('zip iperf.log.zip iperf*.log', '\$', 60) - self.command('rm iperf*.log', '\$', 5) - self.close() - - def LogCollectHSS(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('rm -f hss.log.zip', '\$', 5) - if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('zip hss.log.zip hss*.log', '\$', 60) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm hss*.log', '\$', 5) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('zip hss.log.zip logs/hss*.* *.pcap', '\$', 60) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f logs/hss*.* *.pcap', '\$', 5) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cp /opt/hss_sim0609/hss.log .', '\$', 60) - self.command('zip hss.log.zip hss.log', '\$', 60) - else: - logging.error('This option should not occur!') - self.close() - - def LogCollectMME(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('rm -f mme.log.zip', '\$', 5) - if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('zip mme.log.zip mme*.log', '\$', 60) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm mme*.log', '\$', 5) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cp /opt/ltebox/var/log/*Log.0 .', '\$', 5) - self.command('zip mme.log.zip mmeLog.0 s1apcLog.0 s1apsLog.0 s11cLog.0 libLog.0 s1apCodecLog.0', '\$', 60) - else: - logging.error('This option should not occur!') - self.close() - - def LogCollectSPGW(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('rm -f spgw.log.zip', '\$', 5) - if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('zip spgw.log.zip spgw*.log', '\$', 60) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm spgw*.log', '\$', 5) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cp /opt/ltebox/var/log/xGwLog.0 .', '\$', 5) - self.command('zip spgw.log.zip xGwLog.0', '\$', 60) - else: - logging.error('This option should not occur!') - self.close() - - def LogCollectOAIUE(self): - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('cd ' + self.UESourceCodePath, '\$', 5) - self.command('cd cmake_targets', '\$', 5) - self.command('echo ' + self.UEPassword + ' | sudo -S rm -f ue.log.zip', '\$', 5) - self.command('echo ' + self.UEPassword + ' | sudo -S zip ue.log.zip ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 60) - self.command('echo ' + self.UEPassword + ' | sudo -S rm ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 5) - self.close() - - def RetrieveSystemVersion(self, machine): - if self.eNBIPAddress == 'none' or self.UEIPAddress == 'none': - self.OsVersion = 'Ubuntu 16.04.5 LTS' - self.KernelVersion = '4.15.0-45-generic' - self.UhdVersion = '3.13.0.1-0' - self.UsrpBoard = 'B210' - self.CpuNb = '4' - self.CpuModel = 'Intel(R) Core(TM) i5-6200U' - self.CpuMHz = '2399.996 MHz' - return 0 - if machine == 'eNB': - if self.eNBIPAddress != '' and self.eNBUserName != '' and self.eNBPassword != '': - IPAddress = self.eNBIPAddress - UserName = self.eNBUserName - Password = self.eNBPassword - else: - return -1 - if machine == 'UE': - if self.UEIPAddress != '' and self.UEUserName != '' and self.UEPassword != '': - IPAddress = self.UEIPAddress - UserName = self.UEUserName - Password = self.UEPassword - else: - return -1 - - self.open(IPAddress, UserName, Password) - self.command('lsb_release -a', '\$', 5) - result = re.search('Description:\\\\t(?P[a-zA-Z0-9\-\_\.\ ]+)', str(self.ssh.before)) - if result is not None: - self.OsVersion = result.group('os_type') - logging.debug('OS is: ' + self.OsVersion) - self.command('uname -r', '\$', 5) - result = re.search('uname -r\\\\r\\\\n(?P[a-zA-Z0-9\-\_\.]+)', str(self.ssh.before)) - if result is not None: - self.KernelVersion = result.group('kernel_version') - logging.debug('Kernel Version is: ' + self.KernelVersion) - self.command('dpkg --list | egrep --color=never libuhd003', '\$', 5) - result = re.search('libuhd003:amd64 *(?P[0-9\.]+)', str(self.ssh.before)) - if result is not None: - self.UhdVersion = result.group('uhd_version') - logging.debug('UHD Version is: ' + self.UhdVersion) - self.command('echo ' + Password + ' | sudo -S uhd_find_devices', '\$', 15) - result = re.search('product: (?P[0-9A-Za-z]+)\\\\r\\\\n', str(self.ssh.before)) - if result is not None: - self.UsrpBoard = result.group('usrp_board') - logging.debug('USRP Board is: ' + self.UsrpBoard) - self.command('lscpu', '\$', 5) - result = re.search('CPU\(s\): *(?P[0-9]+).*Model name: *(?P[a-zA-Z0-9\-\_\.\ \(\)]+).*CPU MHz: *(?P[0-9\.]+)', str(self.ssh.before)) - if result is not None: - self.CpuNb = result.group('nb_cpus') - logging.debug('nb_cpus: ' + self.CpuNb) - self.CpuModel = result.group('model') - logging.debug('model: ' + self.CpuModel) - self.CpuMHz = result.group('cpu_mhz') + ' MHz' - logging.debug('cpu_mhz: ' + self.CpuMHz) - self.close() - -#----------------------------------------------------------- -# HTML Reporting.... -#----------------------------------------------------------- - def CreateHtmlHeader(self): - if (not self.htmlHeaderCreated): - logging.debug('\u001B[1m----------------------------------------\u001B[0m') - logging.debug('\u001B[1m Creating HTML header \u001B[0m') - logging.debug('\u001B[1m----------------------------------------\u001B[0m') - self.htmlFile = open('test_results.html', 'w') - self.htmlFile.write('\n') - self.htmlFile.write('\n') - self.htmlFile.write('\n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' Test Results for TEMPLATE_JOB_NAME job build #TEMPLATE_BUILD_ID\n') - self.htmlFile.write('\n') - self.htmlFile.write('
\n') - self.htmlFile.write('
\n') - self.htmlFile.write('
' + str(machine) + ' Server Characteristics' + str('eNB') + ' Server Characteristics
OS Version' + self.OsVersion + 'Kernel Version' + self.KernelVersion + 'UHD Version' + self.UhdVersion + 'USRP Board' + self.UsrpBoard + '
Nb CPUs' + self.CpuNb + 'CPU Model Name' + self.CpuModel + 'CPU Frequency' + self.CpuMHz + '
' + str('UE') + ' Server Characteristics
OS Version
\n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write('
\n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' Job Summary -- Job: TEMPLATE_JOB_NAME -- Build-ID: TEMPLATE_BUILD_ID\n') - self.htmlFile.write('
\n') - self.htmlFile.write('
\n') - self.htmlFile.write('
TEMPLATE_STAGE_NAME
\n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (self.ranAllowMerge): - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (self.ranAllowMerge): - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (self.ranAllowMerge): - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if self.ranAllowMerge != '': - commit_message = subprocess.check_output("git log -n1 --pretty=format:\"%s\" " + self.ranCommitID, shell=True, universal_newlines=True) - commit_message = commit_message.strip() - self.htmlFile.write(' \n') - if (self.ranAllowMerge): - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (self.ranAllowMerge): - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (self.ranTargetBranch == ''): - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write('
Build Start Time (UTC) TEMPLATE_BUILD_TIME
GIT Repository ' + self.ranRepository + '
Job Trigger Merge-RequestPush to Branch
Source Branch Branch' + self.ranBranch + '
Source Commit ID Commit ID ' + self.ranCommitID + '
Source Commit Message Commit Message ' + commit_message + '
Target Branch develop' + self.ranTargetBranch + '
\n') - - if (self.ADBIPAddress != 'none'): - terminate_ue_flag = True - self.GetAllUEDevices(terminate_ue_flag) - self.GetAllCatMDevices(terminate_ue_flag) - self.htmlUEConnected = len(self.UEDevices) - self.htmlFile.write('

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

\n') - self.htmlFile.write('

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

\n') - else: - self.UEDevices.append('OAI-UE') - self.htmlUEConnected = len(self.UEDevices) - self.htmlFile.write('

' + str(len(self.UEDevices)) + ' OAI UE(s) is(are) connected to CI bench

\n') - self.htmlFile.write('
\n') - self.htmlFile.write(' \n') - self.htmlFile.write('
\n') - self.htmlFile.close() - - def CreateHtmlTabHeader(self): - if (not self.htmlHeaderCreated): - if (not os.path.isfile('test_results.html')): - self.CreateHtmlHeader() - self.htmlFile = open('test_results.html', 'a') - if (self.nbTestXMLfiles == 1): - self.htmlFile.write('
\n') - self.htmlFile.write('

Test Summary for ' + self.testXMLfiles[0] + '

\n') - else: - self.htmlFile.write('
\n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (self.htmlUEConnected == -1): - terminate_ue_flag = True - if (self.ADBIPAddress != 'none'): - self.GetAllUEDevices(terminate_ue_flag) - self.GetAllCatMDevices(terminate_ue_flag) - else: - self.UEDevices.append('OAI-UE') - self.htmlUEConnected = len(self.UEDevices) - - i = 0 - while (i < self.htmlUEConnected): - self.htmlFile.write(' \n') - i += 1 - self.htmlFile.write(' \n') - self.htmlHeaderCreated = True - - def CreateHtmlTabFooter(self, passStatus): - if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if passStatus: - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write('
Relative Time (ms)Test IdTest DescTest OptionsTest StatusUE' + str(i) + ' Status
Final Tab StatusPASS FAIL
\n') - self.htmlFile.write('
\n') - self.htmlFile.close() - time.sleep(1) - if passStatus: - cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__//' test_results.html" - subprocess.run(cmd, shell=True) - else: - cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__/<\/span>/' test_results.html" - subprocess.run(cmd, shell=True) - self.htmlFooterCreated = False - - def CreateHtmlFooter(self, passStatus): - if (os.path.isfile('test_results.html')): - logging.debug('\u001B[1m----------------------------------------\u001B[0m') - logging.debug('\u001B[1m Creating HTML footer \u001B[0m') - logging.debug('\u001B[1m----------------------------------------\u001B[0m') - - self.htmlFile = open('test_results.html', 'a') - self.htmlFile.write('
\n') - self.htmlFile.write('

\n') - self.htmlFile.write(' \n') - - machines = [ 'eNB', 'UE' ] - for machine in machines: - res = self.RetrieveSystemVersion(machine) - if res == -1: - continue - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if passStatus: - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write('
' + str(machine) + ' Server Characteristics
OS Version' + self.OsVersion + 'Kernel Version' + self.KernelVersion + 'UHD Version' + self.UhdVersion + 'USRP Board' + self.UsrpBoard + '
Nb CPUs' + self.CpuNb + 'CPU Model Name' + self.CpuModel + 'CPU Frequency' + self.CpuMHz + '
Final StatusPASS FAIL
\n') - self.htmlFile.write('

\n') - self.htmlFile.write('
End of Test Report -- Copyright 2018 OpenAirInterface. All Rights Reserved.
\n') - self.htmlFile.write('
\n') - self.htmlFile.write('\n') - self.htmlFile.close() - - def CreateHtmlTestRow(self, options, status, processesStatus, machine='eNB'): - if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): - currentTime = int(round(time.time() * 1000)) - self.startTime - self.htmlFile.write(' \n') - self.htmlFile.write(' ' + format(currentTime / 1000, '.1f') + '\n') - self.htmlFile.write(' ' + self.testCase_id + '\n') - self.htmlFile.write(' ' + self.desc + '\n') - self.htmlFile.write(' ' + str(options) + '\n') - if (str(status) == 'OK'): - self.htmlFile.write(' ' + str(status) + '\n') - elif (str(status) == 'KO'): - if (processesStatus == 0): - self.htmlFile.write(' ' + str(status) + '\n') - elif (processesStatus == ENB_PROCESS_FAILED): - self.htmlFile.write(' KO - eNB process not found\n') - elif (processesStatus == OAI_UE_PROCESS_FAILED): - self.htmlFile.write(' KO - OAI UE process not found\n') - elif (processesStatus == ENB_PROCESS_SEG_FAULT): - self.htmlFile.write(' KO - ' + machine + ' process ended in Segmentation Fault\n') - elif (processesStatus == ENB_PROCESS_ASSERTION) or (processesStatus == OAI_UE_PROCESS_ASSERTION): - self.htmlFile.write(' KO - ' + machine + ' process ended in Assertion\n') - elif (processesStatus == ENB_PROCESS_REALTIME_ISSUE): - self.htmlFile.write(' KO - ' + machine + ' process faced Real Time issue(s)\n') - elif (processesStatus == ENB_PROCESS_NOLOGFILE_TO_ANALYZE) or (processesStatus == OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE): - self.htmlFile.write(' OK?\n') - elif (processesStatus == ENB_PROCESS_SLAVE_RRU_NOT_SYNCED): - self.htmlFile.write(' KO - ' + machine + ' Slave RRU could not synch\n') - elif (processesStatus == OAI_UE_PROCESS_COULD_NOT_SYNC): - self.htmlFile.write(' KO - UE could not sync\n') - elif (processesStatus == HSS_PROCESS_FAILED): - self.htmlFile.write(' KO - HSS process not found\n') - elif (processesStatus == MME_PROCESS_FAILED): - self.htmlFile.write(' KO - MME process not found\n') - elif (processesStatus == SPGW_PROCESS_FAILED): - self.htmlFile.write(' KO - SPGW process not found\n') - elif (processesStatus == UE_IP_ADDRESS_ISSUE): - self.htmlFile.write(' KO - Could not retrieve UE IP address\n') - else: - self.htmlFile.write(' ' + str(status) + '\n') - else: - self.htmlFile.write(' ' + str(status) + '\n') - if (len(str(self.htmleNBFailureMsg)) > 2): - cellBgColor = 'white' - result = re.search('ended with|faced real time issues', self.htmleNBFailureMsg) - if result is not None: - cellBgColor = 'red' - else: - result = re.search('showed|Reestablishment|Could not copy eNB logfile', self.htmleNBFailureMsg) - if result is not None: - cellBgColor = 'orange' - self.htmlFile.write('
' + self.htmleNBFailureMsg + '
\n') - self.htmleNBFailureMsg = '' - elif (len(str(self.htmlUEFailureMsg)) > 2): - cellBgColor = 'white' - result = re.search('ended with|faced real time issues', self.htmlUEFailureMsg) - if result is not None: - cellBgColor = 'red' - else: - result = re.search('showed|Could not copy UE logfile|oaitun_ue1 interface is either NOT mounted or NOT configured', self.htmlUEFailureMsg) - if result is not None: - cellBgColor = 'orange' - self.htmlFile.write('
' + self.htmlUEFailureMsg + '
\n') - self.htmlUEFailureMsg = '' - else: - i = 0 - while (i < self.htmlUEConnected): - self.htmlFile.write(' -\n') - i += 1 - self.htmlFile.write(' \n') - - def CreateHtmlTestRowQueue(self, options, status, ue_status, ue_queue): - if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): - currentTime = int(round(time.time() * 1000)) - self.startTime - addOrangeBK = False - self.htmlFile.write(' \n') - self.htmlFile.write(' ' + format(currentTime / 1000, '.1f') + '\n') - self.htmlFile.write(' ' + self.testCase_id + '\n') - self.htmlFile.write(' ' + self.desc + '\n') - self.htmlFile.write(' ' + str(options) + '\n') - if (str(status) == 'OK'): - self.htmlFile.write(' ' + str(status) + '\n') - elif (str(status) == 'KO'): - self.htmlFile.write(' ' + str(status) + '\n') - else: - addOrangeBK = True - self.htmlFile.write(' ' + str(status) + '\n') - i = 0 - while (i < self.htmlUEConnected): - if (i < ue_status): - if (not ue_queue.empty()): - if (addOrangeBK): - self.htmlFile.write(' ' + str(ue_queue.get()).replace('white', 'orange') + '\n') - else: - self.htmlFile.write(' ' + str(ue_queue.get()) + '\n') - else: - self.htmlFile.write(' -\n') - else: - self.htmlFile.write(' -\n') - i += 1 - self.htmlFile.write(' \n') - -#----------------------------------------------------------- -# ShowTestID() -#----------------------------------------------------------- - def ShowTestID(self): - logging.debug('\u001B[1m----------------------------------------\u001B[0m') - logging.debug('\u001B[1mTest ID:' + self.testCase_id + '\u001B[0m') - logging.debug('\u001B[1m' + self.desc + '\u001B[0m') - logging.debug('\u001B[1m----------------------------------------\u001B[0m') - -#----------------------------------------------------------- -# Usage() -#----------------------------------------------------------- -def Usage(): - print('----------------------------------------------------------------------------------------------------------------------') - print('main.py Ver:' + Version) - print('----------------------------------------------------------------------------------------------------------------------') - print('Usage: python main.py [options]') - print(' --help Show this help.') - print(' --mode=[Mode]') - print(' TesteNB') - print(' InitiateHtml, FinalizeHtml') - print(' TerminateeNB, TerminateUE, TerminateHSS, TerminateMME, TerminateSPGW') - print(' LogCollectBuild, LogCollecteNB, LogCollectHSS, LogCollectMME, LogCollectSPGW, LogCollectPing, LogCollectIperf') - print('---------------------------------------------------------------------------------------------------- Git Options --') - print(' --ranRepository=[OAI RAN Repository URL]') - print(' --ranBranch=[OAI RAN Repository Branch]') - print(' --ranCommitID=[OAI RAN Repository Commit SHA-1]') - print(' --ranAllowMerge=[Allow Merge Request (with target branch) (true or false)]') - print(' --ranTargetBranch=[Target Branch in case of a Merge Request]') - print('--------------------------------------------------------------------------------------------- eNB Server Options --') - print(' --eNBIPAddress=[eNB\'s IP Address]') - print(' --eNBUserName=[eNB\'s Login User Name]') - print(' --eNBPassword=[eNB\'s Login Password]') - print(' --eNBSourceCodePath=[eNB\'s Source Code Path]') - print('------------------------------------------------------------------------------------------ OAI UE Server Options --') - print(' --UEIPAddress=[UE\'s IP Address]') - print(' --UEUserName=[UE\'s Login User Name]') - print(' --UEPassword=[UE\'s Login Password]') - print(' --UESourceCodePath=[UE\'s Source Code Path]') - print('--------------------------------------------------------------------------------------------- EPC Server Options --') - print(' --EPCIPAddress=[EPC\'s IP Address]') - print(' --EPCUserName=[EPC\'s Login User Name]') - print(' --EPCPassword=[EPC\'s Login Password]') - print(' --EPCSourceCodePath=[EPC\'s Source Code Path]') - print(' --EPCType=[EPC\'s Type: OAI or ltebox or OAI-Rel14-CUPS]') - print('--------------------------------------------------------------------------------------------- ABD Server Options --') - print(' --ADBIPAddress=[ADB\'s IP Address]') - print(' --ADBUserName=[ADB\'s Login User Name]') - print(' --ADBPassword=[ADB\'s Login Password]') - print('----------------------------------------------------------------------------------------------------------------------') - print(' --XMLTestFile=[XML Test File to be run]') - print('----------------------------------------------------------------------------------------------------------------------') - -def CheckClassValidity(action,id): - if action != 'Build_eNB' and action != 'WaitEndBuild_eNB' and action != 'Initialize_eNB' and action != 'Terminate_eNB' and action != 'Initialize_UE' and action != 'Terminate_UE' and action != 'Attach_UE' and action != 'Detach_UE' and action != 'Build_OAI_UE' and action != 'Initialize_OAI_UE' and action != 'Terminate_OAI_UE' and action != 'DataDisable_UE' and action != 'DataEnable_UE' and action != 'CheckStatusUE' and action != 'Ping' and action != 'Iperf' and action != 'Reboot_UE' and action != 'Initialize_FlexranCtrl' and action != 'Terminate_FlexranCtrl' and action != 'Initialize_HSS' and action != 'Terminate_HSS' and action != 'Initialize_MME' and action != 'Terminate_MME' and action != 'Initialize_SPGW' and action != 'Terminate_SPGW' and action != 'Initialize_CatM_module' and action != 'Terminate_CatM_module' and action != 'Attach_CatM_module' and action != 'Detach_CatM_module' and action != 'Ping_CatM_module' and action != 'IdleSleep' and action != 'Perform_X2_Handover': - logging.debug('ERROR: test-case ' + id + ' has wrong class ' + action) - return False - return True - -def GetParametersFromXML(action): - if action == 'Build_eNB': - SSH.Build_eNB_args = test.findtext('Build_eNB_args') - SSH.eNB_instance = test.findtext('eNB_instance') - if (SSH.eNB_instance is None): - SSH.eNB_instance = '0' - SSH.eNB_serverId = test.findtext('eNB_serverId') - if (SSH.eNB_serverId is None): - SSH.eNB_serverId = '0' - xmlBgBuildField = test.findtext('backgroundBuild') - if (xmlBgBuildField is None): - SSH.backgroundBuild = False - else: - if re.match('true', xmlBgBuildField, re.IGNORECASE): - SSH.backgroundBuild = True - else: - SSH.backgroundBuild = False - - if action == 'WaitEndBuild_eNB': - SSH.Build_eNB_args = test.findtext('Build_eNB_args') - SSH.eNB_instance = test.findtext('eNB_instance') - if (SSH.eNB_instance is None): - SSH.eNB_instance = '0' - SSH.eNB_serverId = test.findtext('eNB_serverId') - if (SSH.eNB_serverId is None): - SSH.eNB_serverId = '0' - - if action == 'Initialize_eNB': - SSH.Initialize_eNB_args = test.findtext('Initialize_eNB_args') - SSH.eNB_instance = test.findtext('eNB_instance') - if (SSH.eNB_instance is None): - SSH.eNB_instance = '0' - SSH.eNB_serverId = test.findtext('eNB_serverId') - if (SSH.eNB_serverId is None): - SSH.eNB_serverId = '0' - - if action == 'Terminate_eNB': - SSH.eNB_instance = test.findtext('eNB_instance') - if (SSH.eNB_instance is None): - SSH.eNB_instance = '0' - SSH.eNB_serverId = test.findtext('eNB_serverId') - if (SSH.eNB_serverId is None): - SSH.eNB_serverId = '0' - - if action == 'Attach_UE': - nbMaxUEtoAttach = test.findtext('nbMaxUEtoAttach') - if (nbMaxUEtoAttach is None): - SSH.nbMaxUEtoAttach = -1 - else: - SSH.nbMaxUEtoAttach = int(nbMaxUEtoAttach) - - if action == 'CheckStatusUE': - expectedNBUE = test.findtext('expectedNbOfConnectedUEs') - if (expectedNBUE is None): - SSH.expectedNbOfConnectedUEs = -1 - else: - SSH.expectedNbOfConnectedUEs = int(expectedNBUE) - - if action == 'Build_OAI_UE': - SSH.Build_OAI_UE_args = test.findtext('Build_OAI_UE_args') - - if action == 'Initialize_OAI_UE': - SSH.Initialize_OAI_UE_args = test.findtext('Initialize_OAI_UE_args') - SSH.UE_instance = test.findtext('UE_instance') - if (SSH.UE_instance is None): - SSH.UE_instance = '0' - - if action == 'Terminate_OAI_UE': - SSH.eNB_instance = test.findtext('UE_instance') - if (SSH.UE_instance is None): - SSH.UE_instance = '0' - - if action == 'Ping' or action == 'Ping_CatM_module': - SSH.ping_args = test.findtext('ping_args') - SSH.ping_packetloss_threshold = test.findtext('ping_packetloss_threshold') - - if action == 'Iperf': - SSH.iperf_args = test.findtext('iperf_args') - SSH.iperf_packetloss_threshold = test.findtext('iperf_packetloss_threshold') - SSH.iperf_profile = test.findtext('iperf_profile') - if (SSH.iperf_profile is None): - SSH.iperf_profile = 'balanced' - else: - if SSH.iperf_profile != 'balanced' and SSH.iperf_profile != 'unbalanced' and SSH.iperf_profile != 'single-ue': - logging.debug('ERROR: test-case has wrong profile ' + SSH.iperf_profile) - SSH.iperf_profile = 'balanced' - - if action == 'IdleSleep': - string_field = test.findtext('idle_sleep_time_in_sec') - if (string_field is None): - SSH.idle_sleep_time = 5 - else: - SSH.idle_sleep_time = int(string_field) - - if action == 'Perform_X2_Handover': - string_field = test.findtext('x2_ho_options') - if (string_field is None): - SSH.x2_ho_options = 'network' - else: - if string_field != 'network': - logging.error('ERROR: test-case has wrong option ' + string_field) - SSH.x2_ho_options = 'network' - else: - SSH.x2_ho_options = string_field - - -#check if given test is in list -#it is in list if one of the strings in 'list' is at the beginning of 'test' -def test_in_list(test, list): - for check in list: - check=check.replace('+','') - if (test.startswith(check)): - return True - return False - -def receive_signal(signum, frame): - sys.exit(1) - -#----------------------------------------------------------- -# Parameter Check -#----------------------------------------------------------- -mode = '' -SSH = SSHConnection() - -argvs = sys.argv -argc = len(argvs) -cwd = os.getcwd() - -while len(argvs) > 1: - myArgv = argvs.pop(1) # 0th is this file's name - if re.match('^\-\-help$', myArgv, re.IGNORECASE): - Usage() - sys.exit(0) - elif re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE) - mode = matchReg.group(1) - elif re.match('^\-\-eNBRepository=(.+)$|^\-\-ranRepository(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE) - else: - matchReg = re.match('^\-\-ranRepository=(.+)$', myArgv, re.IGNORECASE) - SSH.ranRepository = matchReg.group(1) - elif re.match('^\-\-eNB_AllowMerge=(.+)$|^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE) - else: - matchReg = re.match('^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE) - doMerge = matchReg.group(1) - if ((doMerge == 'true') or (doMerge == 'True')): - SSH.ranAllowMerge = True - elif re.match('^\-\-eNBBranch=(.+)$|^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE) - else: - matchReg = re.match('^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE) - SSH.ranBranch = matchReg.group(1) - elif re.match('^\-\-eNBCommitID=(.*)$|^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE) - else: - matchReg = re.match('^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE) - SSH.ranCommitID = matchReg.group(1) - elif re.match('^\-\-eNBTargetBranch=(.*)$|^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE) - else: - matchReg = re.match('^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE) - SSH.ranTargetBranch = matchReg.group(1) - elif re.match('^\-\-eNBIPAddress=(.+)$|^\-\-eNB[1-2]IPAddress=(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE) - SSH.eNBIPAddress = matchReg.group(1) - elif re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB1IPAddress = matchReg.group(1) - elif re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB2IPAddress = matchReg.group(1) - elif re.match('^\-\-eNBUserName=(.+)$|^\-\-eNB[1-2]UserName=(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE) - SSH.eNBUserName = matchReg.group(1) - elif re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB1UserName = matchReg.group(1) - elif re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB2UserName = matchReg.group(1) - elif re.match('^\-\-eNBPassword=(.+)$|^\-\-eNB[1-2]Password=(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE) - SSH.eNBPassword = matchReg.group(1) - elif re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB1Password = matchReg.group(1) - elif re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB2Password = matchReg.group(1) - elif re.match('^\-\-eNBSourceCodePath=(.+)$|^\-\-eNB[1-2]SourceCodePath=(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE) - SSH.eNBSourceCodePath = matchReg.group(1) - elif re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB1SourceCodePath = matchReg.group(1) - elif re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB2SourceCodePath = matchReg.group(1) - elif re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE) - SSH.EPCIPAddress = matchReg.group(1) - elif re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE) - SSH.EPCBranch = matchReg.group(1) - elif re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE) - SSH.EPCUserName = matchReg.group(1) - elif re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE) - SSH.EPCPassword = matchReg.group(1) - elif re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE) - SSH.EPCSourceCodePath = matchReg.group(1) - elif re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE) - if re.match('OAI', matchReg.group(1), re.IGNORECASE) or re.match('ltebox', matchReg.group(1), re.IGNORECASE) or re.match('OAI-Rel14-CUPS', matchReg.group(1), re.IGNORECASE): - SSH.EPCType = matchReg.group(1) - else: - sys.exit('Invalid EPC Type: ' + matchReg.group(1) + ' -- (should be OAI or ltebox or OAI-Rel14-CUPS)') - elif re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE) - SSH.ADBIPAddress = matchReg.group(1) - elif re.match('^\-\-ADBUserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-ADBUserName=(.+)$', myArgv, re.IGNORECASE) - SSH.ADBUserName = matchReg.group(1) - elif re.match('^\-\-ADBType=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-ADBType=(.+)$', myArgv, re.IGNORECASE) - if re.match('centralized', matchReg.group(1), re.IGNORECASE) or re.match('distributed', matchReg.group(1), re.IGNORECASE): - if re.match('distributed', matchReg.group(1), re.IGNORECASE): - SSH.ADBCentralized = False - else: - SSH.ADBCentralized = True - else: - sys.exit('Invalid ADB Type: ' + matchReg.group(1) + ' -- (should be centralized or distributed)') - elif re.match('^\-\-ADBPassword=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-ADBPassword=(.+)$', myArgv, re.IGNORECASE) - SSH.ADBPassword = matchReg.group(1) - elif re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE) - SSH.testXMLfiles.append(matchReg.group(1)) - SSH.nbTestXMLfiles += 1 - elif re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE) - SSH.UEIPAddress = matchReg.group(1) - elif re.match('^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE) - SSH.UEUserName = matchReg.group(1) - elif re.match('^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE) - SSH.UEPassword = matchReg.group(1) - elif re.match('^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE) - SSH.UESourceCodePath = matchReg.group(1) -# reading repeatCounts from command line - elif re.match('^\-\-repeatCounts=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-repeatCounts=(.+)$', myArgv, re.IGNORECASE) - SSH.repeatCounts = int(matchReg.group(1)) - elif re.match('^\-\-finalStatus=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-finalStatus=(.+)$', myArgv, re.IGNORECASE) - finalStatus = matchReg.group(1) - if ((finalStatus == 'true') or (finalStatus == 'True')): - SSH.finalStatus = True - else: - Usage() - sys.exit('Invalid Parameter: ' + myArgv) - -if re.match('^TerminateeNB$', mode, re.IGNORECASE): - if SSH.eNBIPAddress == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - SSH.eNB_serverId = '0' - SSH.eNB_instance = '0' - SSH.eNBSourceCodePath = '/tmp/' - SSH.TerminateeNB() -elif re.match('^TerminateUE$', mode, re.IGNORECASE): - if (SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == ''): - Usage() - sys.exit('Insufficient Parameter') - signal.signal(signal.SIGUSR1, receive_signal) - SSH.TerminateUE() -elif re.match('^TerminateOAIUE$', mode, re.IGNORECASE): - if SSH.UEIPAddress == '' or SSH.UEUserName == '' or SSH.UEPassword == '': - Usage() - sys.exit('Insufficient Parameter') - signal.signal(signal.SIGUSR1, receive_signal) - SSH.TerminateOAIUE() -elif re.match('^TerminateHSS$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - SSH.TerminateHSS() -elif re.match('^TerminateMME$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - SSH.TerminateMME() -elif re.match('^TerminateSPGW$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - SSH.TerminateSPGW() -elif re.match('^LogCollectBuild$', mode, re.IGNORECASE): - if (SSH.eNBIPAddress == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '' or SSH.eNBSourceCodePath == '') and (SSH.UEIPAddress == '' or SSH.UEUserName == '' or SSH.UEPassword == '' or SSH.UESourceCodePath == ''): - Usage() - sys.exit('Insufficient Parameter') - SSH.LogCollectBuild() -elif re.match('^LogCollecteNB$', mode, re.IGNORECASE): - if SSH.eNBIPAddress == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '' or SSH.eNBSourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - SSH.LogCollecteNB() -elif re.match('^LogCollectHSS$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - SSH.LogCollectHSS() -elif re.match('^LogCollectMME$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - SSH.LogCollectMME() -elif re.match('^LogCollectSPGW$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - SSH.LogCollectSPGW() -elif re.match('^LogCollectPing$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCSourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - SSH.LogCollectPing() -elif re.match('^LogCollectIperf$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCSourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - SSH.LogCollectIperf() -elif re.match('^LogCollectOAIUE$', mode, re.IGNORECASE): - if SSH.UEIPAddress == '' or SSH.UEUserName == '' or SSH.UEPassword == '' or SSH.UESourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - SSH.LogCollectOAIUE() -elif re.match('^InitiateHtml$', mode, re.IGNORECASE): - if (SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == ''): - Usage() - sys.exit('Insufficient Parameter') - count = 0 - foundCount = 0 - while (count < SSH.nbTestXMLfiles): - xml_test_file = cwd + "/" + SSH.testXMLfiles[count] - xml_test_file = sys.path[0] + "/" + SSH.testXMLfiles[count] - if (os.path.isfile(xml_test_file)): - xmlTree = ET.parse(xml_test_file) - xmlRoot = xmlTree.getroot() - SSH.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count))) - SSH.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-' + str(count))) - SSH.htmlTabIcons.append(xmlRoot.findtext('htmlTabIcon',default='info-sign')) - foundCount += 1 - count += 1 - if foundCount != SSH.nbTestXMLfiles: - SSH.nbTestXMLfiles = foundCount - SSH.CreateHtmlHeader() -elif re.match('^FinalizeHtml$', mode, re.IGNORECASE): - SSH.CreateHtmlFooter(SSH.finalStatus) -elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re.IGNORECASE): - if re.match('^TesteNB$', mode, re.IGNORECASE): - if SSH.eNBIPAddress == '' or SSH.ranRepository == '' or SSH.ranBranch == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '' or SSH.eNBSourceCodePath == '' or SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '' or SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - - if (SSH.EPCIPAddress != '') and (SSH.EPCIPAddress != 'none'): - SSH.copyout(SSH.EPCIPAddress, SSH.EPCUserName, SSH.EPCPassword, cwd + "/tcp_iperf_stats.awk", "/tmp") - SSH.copyout(SSH.EPCIPAddress, SSH.EPCUserName, SSH.EPCPassword, cwd + "/active_net_interfaces.awk", "/tmp") - else: - if SSH.UEIPAddress == '' or SSH.ranRepository == '' or SSH.ranBranch == '' or SSH.UEUserName == '' or SSH.UEPassword == '' or SSH.UESourceCodePath == '': - Usage() - sys.exit('UE: Insufficient Parameter') - - #read test_case_list.xml file - # if no parameters for XML file, use default value - if (SSH.nbTestXMLfiles != 1): - xml_test_file = cwd + "/test_case_list.xml" - else: - xml_test_file = cwd + "/" + SSH.testXMLfiles[0] - - xmlTree = ET.parse(xml_test_file) - xmlRoot = xmlTree.getroot() - - exclusion_tests=xmlRoot.findtext('TestCaseExclusionList',default='') - requested_tests=xmlRoot.findtext('TestCaseRequestedList',default='') - if (SSH.nbTestXMLfiles == 1): - SSH.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-0')) - SSH.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-0')) -# repeatCounts not read from the xml file -# repeatCount = xmlRoot.findtext('repeatCount',default='1') -# SSH.repeatCounts.append(int(repeatCount)) - all_tests=xmlRoot.findall('testCase') - - exclusion_tests=exclusion_tests.split() - requested_tests=requested_tests.split() - - #check that exclusion tests are well formatted - #(6 digits or less than 6 digits followed by +) - for test in exclusion_tests: - if (not re.match('^[0-9]{6}$', test) and - not re.match('^[0-9]{1,5}\+$', test)): - logging.debug('ERROR: exclusion test is invalidly formatted: ' + test) - sys.exit(1) - else: - logging.debug(test) - - #check that requested tests are well formatted - #(6 digits or less than 6 digits followed by +) - #be verbose - for test in requested_tests: - if (re.match('^[0-9]{6}$', test) or - re.match('^[0-9]{1,5}\+$', test)): - logging.debug('INFO: test group/case requested: ' + test) - else: - logging.debug('ERROR: requested test is invalidly formatted: ' + test) - sys.exit(1) - if (SSH.EPCIPAddress != '') and (SSH.EPCIPAddress != 'none'): - SSH.CheckFlexranCtrlInstallation() - - #get the list of tests to be done - todo_tests=[] - for test in requested_tests: - if (test_in_list(test, exclusion_tests)): - logging.debug('INFO: test will be skipped: ' + test) - else: - #logging.debug('INFO: test will be run: ' + test) - todo_tests.append(test) - - signal.signal(signal.SIGUSR1, receive_signal) - - SSH.CreateHtmlTabHeader() - - cnt = 0 - SSH.prematureExit = True - SSH.startTime = int(round(time.time() * 1000)) -# repeatCounts becomes an integer (was SSH.repeatCounts[0] --> becomes SSH.repeatCounts) - while cnt < SSH.repeatCounts and SSH.prematureExit: - SSH.prematureExit = False - for test_case_id in todo_tests: - if SSH.prematureExit: - break - for test in all_tests: - if SSH.prematureExit: - break - id = test.get('id') - if test_case_id != id: - continue - SSH.testCase_id = id - SSH.desc = test.findtext('desc') - action = test.findtext('class') - if (CheckClassValidity(action, id) == False): - continue - SSH.ShowTestID() - GetParametersFromXML(action) - if action == 'Initialize_UE' or action == 'Attach_UE' or action == 'Detach_UE' or action == 'Ping' or action == 'Iperf' or action == 'Reboot_UE' or action == 'DataDisable_UE' or action == 'DataEnable_UE' or action == 'CheckStatusUE': - if (SSH.ADBIPAddress != 'none'): - terminate_ue_flag = False - SSH.GetAllUEDevices(terminate_ue_flag) - if action == 'Build_eNB': - SSH.BuildeNB() - elif action == 'WaitEndBuild_eNB': - SSH.WaitBuildeNBisFinished() - elif action == 'Initialize_eNB': - SSH.InitializeeNB() - elif action == 'Terminate_eNB': - SSH.TerminateeNB() - elif action == 'Initialize_UE': - SSH.InitializeUE() - elif action == 'Terminate_UE': - SSH.TerminateUE() - elif action == 'Attach_UE': - SSH.AttachUE() - elif action == 'Detach_UE': - SSH.DetachUE() - elif action == 'DataDisable_UE': - SSH.DataDisableUE() - elif action == 'DataEnable_UE': - SSH.DataEnableUE() - elif action == 'CheckStatusUE': - SSH.CheckStatusUE() - elif action == 'Build_OAI_UE': - SSH.BuildOAIUE() - elif action == 'Initialize_OAI_UE': - SSH.InitializeOAIUE() - elif action == 'Terminate_OAI_UE': - SSH.TerminateOAIUE() - elif action == 'Initialize_CatM_module': - SSH.InitializeCatM() - elif action == 'Terminate_CatM_module': - SSH.TerminateCatM() - elif action == 'Attach_CatM_module': - SSH.AttachCatM() - elif action == 'Detach_CatM_module': - SSH.TerminateCatM() - elif action == 'Ping_CatM_module': - SSH.PingCatM() - elif action == 'Ping': - SSH.Ping() - elif action == 'Iperf': - SSH.Iperf() - elif action == 'Reboot_UE': - SSH.RebootUE() - elif action == 'Initialize_HSS': - SSH.InitializeHSS() - elif action == 'Terminate_HSS': - SSH.TerminateHSS() - elif action == 'Initialize_MME': - SSH.InitializeMME() - elif action == 'Terminate_MME': - SSH.TerminateMME() - elif action == 'Initialize_SPGW': - SSH.InitializeSPGW() - elif action == 'Terminate_SPGW': - SSH.TerminateSPGW() - elif action == 'Initialize_FlexranCtrl': - SSH.InitializeFlexranCtrl() - elif action == 'Terminate_FlexranCtrl': - SSH.TerminateFlexranCtrl() - elif action == 'IdleSleep': - SSH.IdleSleep() - elif action == 'Perform_X2_Handover': - SSH.Perform_X2_Handover() - else: - sys.exit('Invalid action') - cnt += 1 -# repeatCounts becomes an integer (was SSH.repeatCounts[0] --> becomes SSH.repeatCounts) - if cnt == SSH.repeatCounts and SSH.prematureExit: - logging.debug('Testsuite failed ' + str(cnt) + ' time(s)') - SSH.CreateHtmlTabFooter(False) - sys.exit('Failed Scenario') - else: - logging.info('Testsuite passed after ' + str(cnt) + ' time(s)') - SSH.CreateHtmlTabFooter(True) -else: - Usage() - sys.exit('Invalid mode') -sys.exit(0) diff --git a/ci-scripts/main-index-to-class.py b/ci-scripts/main-index-to-class.py deleted file mode 100644 index 68b9558740..0000000000 --- a/ci-scripts/main-index-to-class.py +++ /dev/null @@ -1,4921 +0,0 @@ -# /* -# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more -# * contributor license agreements. See the NOTICE file distributed with -# * this work for additional information regarding copyright ownership. -# * The OpenAirInterface Software Alliance licenses this file to You under -# * the OAI Public License, Version 1.1 (the "License"); you may not use this file -# * except in compliance with the License. -# * You may obtain a copy of the License at -# * -# * http://www.openairinterface.org/?page_id=698 -# * -# * Unless required by applicable law or agreed to in writing, software -# * distributed under the License is distributed on an "AS IS" BASIS, -# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# * See the License for the specific language governing permissions and -# * limitations under the License. -# *------------------------------------------------------------------------------- -# * For more information about the OpenAirInterface (OAI) Software Alliance: -# * contact@openairinterface.org -# */ -#--------------------------------------------------------------------- -# Python for CI of OAI-eNB + COTS-UE -# -# Required Python Version -# Python 3.x -# -# Required Python Package -# pexpect -#--------------------------------------------------------------------- - -#----------------------------------------------------------- -# Version -#----------------------------------------------------------- -Version = '0.1' - -#----------------------------------------------------------- -# Constants -#----------------------------------------------------------- -ALL_PROCESSES_OK = 0 -ENB_PROCESS_FAILED = -1 -ENB_PROCESS_OK = +1 -ENB_PROCESS_SEG_FAULT = -11 -ENB_PROCESS_ASSERTION = -12 -ENB_PROCESS_REALTIME_ISSUE = -13 -ENB_PROCESS_NOLOGFILE_TO_ANALYZE = -14 -ENB_PROCESS_SLAVE_RRU_NOT_SYNCED = -15 -HSS_PROCESS_FAILED = -2 -HSS_PROCESS_OK = +2 -MME_PROCESS_FAILED = -3 -MME_PROCESS_OK = +3 -SPGW_PROCESS_FAILED = -4 -SPGW_PROCESS_OK = +4 -UE_IP_ADDRESS_ISSUE = -5 -OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE = -20 -OAI_UE_PROCESS_COULD_NOT_SYNC = -21 -OAI_UE_PROCESS_ASSERTION = -22 -OAI_UE_PROCESS_FAILED = -23 -OAI_UE_PROCESS_NO_TUNNEL_INTERFACE = -24 -OAI_UE_PROCESS_OK = +6 - -UE_STATUS_DETACHED = 0 -UE_STATUS_DETACHING = 1 -UE_STATUS_ATTACHING = 2 -UE_STATUS_ATTACHED = 3 - -X2_HO_REQ_STATE__IDLE = 0 -X2_HO_REQ_STATE__TARGET_RECEIVES_REQ = 1 -X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE = 2 -X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ = 3 -X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK = 10 - -#----------------------------------------------------------- -# Import -#----------------------------------------------------------- -import sys # arg -import re # reg -import pexpect # pexpect -import time # sleep -import os -import subprocess -import xml.etree.ElementTree as ET -import logging -import datetime -import signal -from multiprocessing import Process, Lock, SimpleQueue -logging.basicConfig( - level=logging.DEBUG, - format="[%(asctime)s] %(name)s:%(levelname)s: %(message)s" -) - -#----------------------------------------------------------- -# Class Declaration -#----------------------------------------------------------- -class SSHConnection(): - def __init__(self): - self.FailReportCnt = 0 # FailReportCnt was an index inside the SSH instantiation (called "cnt"), now it becomes an object - self.prematureExit = False - self.ranRepository = '' - self.ranBranch = '' - self.ranAllowMerge = False - self.ranCommitID = '' - self.ranTargetBranch = '' - self.eNBIPAddress = '' - self.eNBUserName = '' - self.eNBPassword = '' - self.eNBSourceCodePath = '' - self.EPCIPAddress = '' - self.EPCUserName = '' - self.EPCPassword = '' - self.eNB1IPAddress = '' - self.eNB1UserName = '' - self.eNB1Password = '' - self.eNB1SourceCodePath = '' - self.eNB2IPAddress = '' - self.eNB2UserName = '' - self.eNB2Password = '' - self.eNB2SourceCodePath = '' - self.EPCSourceCodePath = '' - self.EPCType = '' - self.EPC_PcapFileName = '' - self.ADBIPAddress = '' - self.ADBUserName = '' - self.ADBPassword = '' - self.ADBCentralized = True - self.testCase_id = '' - self.testXMLfiles = [] - self.nbTestXMLfiles = 0 - self.desc = '' - self.Build_eNB_args = '' - self.backgroundBuild = False - self.backgroundBuildTestId = ['', '', ''] - self.Initialize_eNB_args = '' - self.eNB_instance = '' - self.eNB_serverId = '' - self.eNBLogFiles = ['', '', ''] - self.eNBOptions = ['', '', ''] - self.ping_args = '' - self.ping_packetloss_threshold = '' - self.iperf_args = '' - self.iperf_packetloss_threshold = '' - self.iperf_profile = '' - self.nbMaxUEtoAttach = -1 - self.UEDevices = [] - self.UEDevicesStatus = [] - self.UEDevicesRemoteServer = [] - self.UEDevicesRemoteUser = [] - self.UEDevicesOffCmd = [] - self.UEDevicesOnCmd = [] - self.UEDevicesRebootCmd = [] - self.CatMDevices = [] - self.UEIPAddresses = [] - self.htmlFile = '' - self.htmlHeaderCreated = False - self.htmlFooterCreated = False - self.htmlUEConnected = -1 - self.htmleNBFailureMsg = '' - self.htmlUEFailureMsg = '' - self.picocom_closure = False - self.idle_sleep_time = 0 - self.x2_ho_options = 'network' - self.x2NbENBs = 0 - self.x2ENBBsIds = [] - self.x2ENBConnectedUEs = [] - self.htmlTabRefs = [] - self.htmlTabNames = [] - self.htmlTabIcons = [] - self.repeatCounts = [] - self.finalStatus = False - self.OsVersion = '' - self.KernelVersion = '' - self.UhdVersion = '' - self.UsrpBoard = '' - self.CpuNb = '' - self.CpuModel = '' - self.CpuMHz = '' - self.UEIPAddress = '' - self.UEUserName = '' - self.UEPassword = '' - self.UE_instance = '' - self.UESourceCodePath = '' - self.UELogFile = '' - self.Build_OAI_UE_args = '' - self.Initialize_OAI_UE_args = '' - self.flexranCtrlInstalled = False - self.flexranCtrlStarted = False - self.expectedNbOfConnectedUEs = 0 - self.startTime = 0 - - def open(self, ipaddress, username, password): - count = 0 - connect_status = False - while count < 4: - self.ssh = pexpect.spawn('ssh', [username + '@' + ipaddress], timeout = 5) - self.sshresponse = self.ssh.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', 'Last login', pexpect.EOF, pexpect.TIMEOUT]) - if self.sshresponse == 0: - self.ssh.sendline('yes') - self.ssh.expect('password:') - self.ssh.sendline(password) - self.sshresponse = self.ssh.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if self.sshresponse == 0: - count = 10 - connect_status = True - else: - logging.debug('self.sshresponse = ' + str(self.sshresponse)) - elif self.sshresponse == 1: - self.ssh.sendline(password) - self.sshresponse = self.ssh.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if self.sshresponse == 0: - count = 10 - connect_status = True - else: - logging.debug('self.sshresponse = ' + str(self.sshresponse)) - elif self.sshresponse == 2: - # Checking if we are really on the remote client defined by its IP address - self.command('stdbuf -o0 ifconfig | egrep --color=never "inet addr:|inet "', '\$', 5) - result = re.search(str(ipaddress), str(self.ssh.before)) - if result is None: - self.close() - else: - count = 10 - connect_status = True - else: - # debug output - logging.debug(str(self.ssh.before)) - logging.debug('self.sshresponse = ' + str(self.sshresponse)) - # adding a tempo when failure - if not connect_status: - time.sleep(1) - count += 1 - if connect_status: - pass - else: - sys.exit('SSH Connection Failed') - - def command(self, commandline, expectedline, timeout): - logging.debug(commandline) - self.ssh.timeout = timeout - self.ssh.sendline(commandline) - self.sshresponse = self.ssh.expect([expectedline, pexpect.EOF, pexpect.TIMEOUT]) - if self.sshresponse == 0: - return 0 - elif self.sshresponse == 1: - logging.debug('\u001B[1;37;41m Unexpected EOF \u001B[0m') - logging.debug('Expected Line : ' + expectedline) - sys.exit(self.sshresponse) - elif self.sshresponse == 2: - logging.debug('\u001B[1;37;41m Unexpected TIMEOUT \u001B[0m') - logging.debug('Expected Line : ' + expectedline) - result = re.search('ping |iperf |picocom', str(commandline)) - if result is None: - logging.debug(str(self.ssh.before)) - sys.exit(self.sshresponse) - else: - return -1 - else: - logging.debug('\u001B[1;37;41m Unexpected Others \u001B[0m') - logging.debug('Expected Line : ' + expectedline) - sys.exit(self.sshresponse) - - def close(self): - self.ssh.timeout = 5 - self.ssh.sendline('exit') - self.sshresponse = self.ssh.expect([pexpect.EOF, pexpect.TIMEOUT]) - if self.sshresponse == 0: - pass - elif self.sshresponse == 1: - if not self.picocom_closure: - logging.debug('\u001B[1;37;41m Unexpected TIMEOUT during closing\u001B[0m') - else: - logging.debug('\u001B[1;37;41m Unexpected Others during closing\u001B[0m') - - def copyin(self, ipaddress, username, password, source, destination): - count = 0 - copy_status = False - logging.debug('scp '+ username + '@' + ipaddress + ':' + source + ' ' + destination) - while count < 10: - scp_spawn = pexpect.spawn('scp '+ username + '@' + ipaddress + ':' + source + ' ' + destination, timeout = 100) - scp_response = scp_spawn.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0: - scp_spawn.sendline('yes') - scp_spawn.expect('password:') - scp_spawn.sendline(password) - scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0: - count = 10 - copy_status = True - else: - logging.debug('1 - scp_response = ' + str(scp_response)) - elif scp_response == 1: - scp_spawn.sendline(password) - scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0 or scp_response == 3: - count = 10 - copy_status = True - else: - logging.debug('2 - scp_response = ' + str(scp_response)) - elif scp_response == 2: - count = 10 - copy_status = True - else: - logging.debug('3 - scp_response = ' + str(scp_response)) - # adding a tempo when failure - if not copy_status: - time.sleep(1) - count += 1 - if copy_status: - return 0 - else: - return -1 - - def copyout(self, ipaddress, username, password, source, destination): - count = 0 - copy_status = False - logging.debug('scp ' + source + ' ' + username + '@' + ipaddress + ':' + destination) - while count < 4: - scp_spawn = pexpect.spawn('scp ' + source + ' ' + username + '@' + ipaddress + ':' + destination, timeout = 100) - scp_response = scp_spawn.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0: - scp_spawn.sendline('yes') - scp_spawn.expect('password:') - scp_spawn.sendline(password) - scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0: - count = 10 - copy_status = True - else: - logging.debug('1 - scp_response = ' + str(scp_response)) - elif scp_response == 1: - scp_spawn.sendline(password) - scp_response = scp_spawn.expect(['\$', 'Permission denied', 'password:', pexpect.EOF, pexpect.TIMEOUT]) - if scp_response == 0 or scp_response == 3: - count = 10 - copy_status = True - else: - logging.debug('2 - scp_response = ' + str(scp_response)) - elif scp_response == 2: - count = 10 - copy_status = True - else: - logging.debug('3 - scp_response = ' + str(scp_response)) - # adding a tempo when failure - if not copy_status: - time.sleep(1) - count += 1 - if copy_status: - pass - else: - sys.exit('SCP failed') - - def BuildeNB(self): - if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': - Usage() - sys.exit('Insufficient Parameter') - if self.eNB_serverId == '0': - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - lSourcePath = self.eNBSourceCodePath - elif self.eNB_serverId == '1': - lIpAddr = self.eNB1IPAddress - lUserName = self.eNB1UserName - lPassWord = self.eNB1Password - lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId == '2': - lIpAddr = self.eNB2IPAddress - lUserName = self.eNB2UserName - lPassWord = self.eNB2Password - lSourcePath = self.eNB2SourceCodePath - if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(lIpAddr, lUserName, lPassWord) - self.command('mkdir -p ' + lSourcePath, '\$', 5) - self.command('cd ' + lSourcePath, '\$', 5) - self.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + self.ranRepository + ' .; else stdbuf -o0 git fetch; fi', '\$', 600) - # Raphael: here add a check if git clone or git fetch went smoothly - self.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) - self.command('git config user.name "OAI Jenkins"', '\$', 5) - # Checking the BUILD INFO file - if not self.backgroundBuild: - self.command('ls *.txt', '\$', 5) - result = re.search('LAST_BUILD_INFO', str(self.ssh.before)) - if result is not None: - mismatch = False - self.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) - result = re.search(self.ranCommitID, str(self.ssh.before)) - if result is None: - mismatch = True - self.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) - if (self.ranAllowMerge): - result = re.search('YES', str(self.ssh.before)) - if result is None: - mismatch = True - self.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) - if self.ranTargetBranch == '': - result = re.search('develop', str(self.ssh.before)) - else: - result = re.search(self.ranTargetBranch, str(self.ssh.before)) - if result is None: - mismatch = True - else: - result = re.search('NO', str(self.ssh.before)) - if result is None: - mismatch = True - if not mismatch: - self.close() - self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) - return - - self.command('echo ' + lPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30) - # if the commit ID is provided use it to point to it - if self.ranCommitID != '': - self.command('git checkout -f ' + self.ranCommitID, '\$', 5) - # if the branch is not develop, then it is a merge request and we need to do - # the potential merge. Note that merge conflicts should already been checked earlier - if (self.ranAllowMerge): - if self.ranTargetBranch == '': - if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'): - self.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) - else: - logging.debug('Merging with the target branch: ' + self.ranTargetBranch) - self.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5) - self.command('source oaienv', '\$', 5) - self.command('cd cmake_targets', '\$', 5) - self.command('mkdir -p log', '\$', 5) - self.command('chmod 777 log', '\$', 5) - # no need to remove in log (git clean did the trick) - if self.backgroundBuild: - self.command('echo "./build_oai ' + self.Build_eNB_args + '" > ./my-lte-softmodem-build.sh', '\$', 5) - self.command('chmod 775 ./my-lte-softmodem-build.sh', '\$', 5) - self.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=build_enb_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/compile_oai_enb.log ./my-lte-softmodem-build.sh', '\$', 5) - self.close() - self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) - self.backgroundBuildTestId[int(self.eNB_instance)] = self.testCase_id - return - self.command('stdbuf -o0 ./build_oai ' + self.Build_eNB_args + ' 2>&1 | stdbuf -o0 tee compile_oai_enb.log', 'Bypassing the Tests|build have failed', 1500) - self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.testCase_id) - - def WaitBuildeNBisFinished(self): - if self.eNB_serverId == '0': - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - lSourcePath = self.eNBSourceCodePath - elif self.eNB_serverId == '1': - lIpAddr = self.eNB1IPAddress - lUserName = self.eNB1UserName - lPassWord = self.eNB1Password - lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId == '2': - lIpAddr = self.eNB2IPAddress - lUserName = self.eNB2UserName - lPassWord = self.eNB2Password - lSourcePath = self.eNB2SourceCodePath - if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(lIpAddr, lUserName, lPassWord) - count = 40 - buildOAIprocess = True - while (count > 0) and buildOAIprocess: - self.command('ps aux | grep --color=never build_ | grep -v grep', '\$', 3) - result = re.search('build_oai', str(self.ssh.before)) - if result is None: - buildOAIprocess = False - else: - count -= 1 - time.sleep(30) - self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.backgroundBuildTestId[int(self.eNB_instance)]) - - def checkBuildeNB(self, lIpAddr, lUserName, lPassWord, lSourcePath, testcaseId): - self.command('cd ' + lSourcePath + '/cmake_targets', '\$', 3) - self.command('ls lte_build_oai/build', '\$', 3) - self.command('ls lte_build_oai/build', '\$', 3) - buildStatus = True - result = re.search('lte-softmodem', str(self.ssh.before)) - if result is None: - buildStatus = False - else: - # Generating a BUILD INFO file - self.command('echo "SRC_BRANCH: ' + self.ranBranch + '" > ../LAST_BUILD_INFO.txt', '\$', 2) - self.command('echo "SRC_COMMIT: ' + self.ranCommitID + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) - if (self.ranAllowMerge): - self.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2) - if self.ranTargetBranch == '': - self.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2) - else: - self.command('echo "TGT_BRANCH: ' + self.ranTargetBranch + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) - else: - self.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) - self.command('mkdir -p build_log_' + testcaseId, '\$', 5) - self.command('mv log/* ' + 'build_log_' + testcaseId, '\$', 5) - self.command('mv compile_oai_enb.log ' + 'build_log_' + testcaseId, '\$', 5) - if self.eNB_serverId != '0': - self.command('cd cmake_targets', '\$', 5) - self.command('if [ -e tmp_build' + testcaseId + '.zip ]; then rm -f tmp_build' + testcaseId + '.zip; fi', '\$', 5) - self.command('zip -r -qq tmp_build' + testcaseId + '.zip build_log_' + testcaseId, '\$', 5) - self.close() - if (os.path.isfile('./tmp_build' + testcaseId + '.zip')): - os.remove('./tmp_build' + testcaseId + '.zip') - self.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/tmp_build' + testcaseId + '.zip', '.') - if (os.path.isfile('./tmp_build' + testcaseId + '.zip')): - self.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './tmp_build' + testcaseId + '.zip', self.eNBSourceCodePath + '/cmake_targets/.') - os.remove('./tmp_build' + testcaseId + '.zip') - self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) - self.command('cd ' + self.eNBSourceCodePath + '/cmake_targets', '\$', 5) - self.command('unzip -qq -DD tmp_build' + testcaseId + '.zip', '\$', 5) - self.command('rm -f tmp_build' + testcaseId + '.zip', '\$', 5) - self.close() - else: - self.close() - - if buildStatus: - self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) - else: - logging.error('\u001B[1m Building OAI eNB Failed\u001B[0m') - self.CreateHtmlTestRow(self.Build_eNB_args, 'KO', ALL_PROCESSES_OK) - self.CreateHtmlTabFooter(False) - sys.exit(1) - - def BuildOAIUE(self): - if self.UEIPAddress == '' or self.ranRepository == '' or self.ranBranch == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('mkdir -p ' + self.UESourceCodePath, '\$', 5) - self.command('cd ' + self.UESourceCodePath, '\$', 5) - self.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + self.ranRepository + ' .; else stdbuf -o0 git fetch; fi', '\$', 600) - # here add a check if git clone or git fetch went smoothly - self.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) - self.command('git config user.name "OAI Jenkins"', '\$', 5) - self.command('ls *.txt', '\$', 5) - result = re.search('LAST_BUILD_INFO', str(self.ssh.before)) - if result is not None: - mismatch = False - self.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) - result = re.search(self.ranCommitID, str(self.ssh.before)) - if result is None: - mismatch = True - self.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) - if (self.ranAllowMerge): - result = re.search('YES', str(self.ssh.before)) - if result is None: - mismatch = True - self.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) - if self.ranTargetBranch == '': - result = re.search('develop', str(self.ssh.before)) - else: - result = re.search(self.ranTargetBranch, str(self.ssh.before)) - if result is None: - mismatch = True - else: - result = re.search('NO', str(self.ssh.before)) - if result is None: - mismatch = True - if not mismatch: - self.close() - self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) - return - - self.command('echo ' + self.UEPassword + ' | sudo -S git clean -x -d -ff', '\$', 30) - # if the commit ID is provided use it to point to it - if self.ranCommitID != '': - self.command('git checkout -f ' + self.ranCommitID, '\$', 5) - # if the branch is not develop, then it is a merge request and we need to do - # the potential merge. Note that merge conflicts should already been checked earlier - if (self.ranAllowMerge): - if self.ranTargetBranch == '': - if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'): - self.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) - else: - logging.debug('Merging with the target branch: ' + self.ranTargetBranch) - self.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5) - self.command('source oaienv', '\$', 5) - self.command('cd cmake_targets', '\$', 5) - self.command('mkdir -p log', '\$', 5) - self.command('chmod 777 log', '\$', 5) - # no need to remove in log (git clean did the trick) - self.command('stdbuf -o0 ./build_oai ' + self.Build_OAI_UE_args + ' 2>&1 | stdbuf -o0 tee compile_oai_ue.log', 'Bypassing the Tests|build have failed', 600) - self.command('ls lte_build_oai/build', '\$', 3) - self.command('ls lte_build_oai/build', '\$', 3) - buildStatus = True - result = re.search('lte-uesoftmodem', str(self.ssh.before)) - if result is None: - buildStatus = False - self.command('mkdir -p build_log_' + self.testCase_id, '\$', 5) - self.command('mv log/* ' + 'build_log_' + self.testCase_id, '\$', 5) - self.command('mv compile_oai_ue.log ' + 'build_log_' + self.testCase_id, '\$', 5) - if buildStatus: - # Generating a BUILD INFO file - self.command('echo "SRC_BRANCH: ' + self.ranBranch + '" > ../LAST_BUILD_INFO.txt', '\$', 2) - self.command('echo "SRC_COMMIT: ' + self.ranCommitID + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) - if (self.ranAllowMerge): - self.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2) - if self.ranTargetBranch == '': - self.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2) - else: - self.command('echo "TGT_BRANCH: ' + self.ranTargetBranch + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) - else: - self.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) - self.close() - self.CreateHtmlTestRow(self.Build_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE') - else: - self.close() - logging.error('\u001B[1m Building OAI UE Failed\u001B[0m') - self.CreateHtmlTestRow(self.Build_OAI_UE_args, 'KO', ALL_PROCESSES_OK, 'OAI UE') - self.CreateHtmlTabFooter(False) - sys.exit(1) - - def InitializeHSS(self): - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - logging.debug('Using the OAI EPC Release 14 Cassandra-based HSS') - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - logging.debug('\u001B[1m Launching tshark on all interfaces \u001B[0m') - EPC_PcapFileName = 'epc_' + self.testCase_id + '.pcap' - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f ' + EPC_PcapFileName, '\$', 5) - self.command('echo $USER; nohup sudo tshark -f "tcp port not 22 and port not 53" -i any -w ' + self.EPCSourceCodePath + '/scripts/' + EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', self.EPCUserName, 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S mkdir -p logs', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f hss_' + self.testCase_id + '.log logs/hss*.*', '\$', 5) - self.command('echo "oai_hss -j /usr/local/etc/oai/hss_rel14.json" > ./my-hss.sh', '\$', 5) - self.command('chmod 755 ./my-hss.sh', '\$', 5) - self.command('sudo daemon --unsafe --name=hss_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/hss_' + self.testCase_id + '.log ./my-hss.sh', '\$', 5) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - logging.debug('Using the OAI EPC HSS') - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('source oaienv', '\$', 5) - self.command('cd scripts', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S ./run_hss 2>&1 | stdbuf -o0 awk \'{ print strftime("[%Y/%m/%d %H:%M:%S] ",systime()) $0 }\' | stdbuf -o0 tee -a hss_' + self.testCase_id + '.log &', 'Core state: 2 -> 3', 35) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - logging.debug('Using the ltebox simulated HSS') - self.command('if [ -d ' + self.EPCSourceCodePath + '/scripts ]; then echo ' + self.eNBPassword + ' | sudo -S rm -Rf ' + self.EPCSourceCodePath + '/scripts ; fi', '\$', 5) - self.command('mkdir -p ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('cd /opt/hss_sim0609', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f hss.log daemon.log', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S echo "Starting sudo session" && sudo daemon --unsafe --name=simulated_hss --chdir=/opt/hss_sim0609 ./starthss_real ', '\$', 5) - else: - logging.error('This option should not occur!') - self.close() - self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) - - def InitializeMME(self): - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - logging.debug('Using the OAI EPC Release 14 MME') - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f mme_' + self.testCase_id + '.log', '\$', 5) - self.command('echo "./run_mme --config-file /usr/local/etc/oai/mme.conf --set-virt-if" > ./my-mme.sh', '\$', 5) - self.command('chmod 755 ./my-mme.sh', '\$', 5) - self.command('sudo daemon --unsafe --name=mme_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/mme_' + self.testCase_id + '.log ./my-mme.sh', '\$', 5) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('source oaienv', '\$', 5) - self.command('cd scripts', '\$', 5) - self.command('stdbuf -o0 hostname', '\$', 5) - result = re.search('hostname\\\\r\\\\n(?P[a-zA-Z0-9\-\_]+)\\\\r\\\\n', str(self.ssh.before)) - if result is None: - logging.debug('\u001B[1;37;41m Hostname Not Found! \u001B[0m') - sys.exit(1) - host_name = result.group('host_name') - self.command('echo ' + self.EPCPassword + ' | sudo -S ./run_mme 2>&1 | stdbuf -o0 tee -a mme_' + self.testCase_id + '.log &', 'MME app initialization complete', 100) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cd /opt/ltebox/tools', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S ./start_mme', '\$', 5) - else: - logging.error('This option should not occur!') - self.close() - self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) - - def InitializeSPGW(self): - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - logging.debug('Using the OAI EPC Release 14 SPGW-CUPS') - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f spgwc_' + self.testCase_id + '.log spgwu_' + self.testCase_id + '.log', '\$', 5) - self.command('echo "spgwc -c /usr/local/etc/oai/spgw_c.conf" > ./my-spgwc.sh', '\$', 5) - self.command('chmod 755 ./my-spgwc.sh', '\$', 5) - self.command('sudo daemon --unsafe --name=spgwc_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/spgwc_' + self.testCase_id + '.log ./my-spgwc.sh', '\$', 5) - time.sleep(5) - self.command('echo "spgwu -c /usr/local/etc/oai/spgw_u.conf" > ./my-spgwu.sh', '\$', 5) - self.command('chmod 755 ./my-spgwu.sh', '\$', 5) - self.command('sudo daemon --unsafe --name=spgwu_daemon --chdir=' + self.EPCSourceCodePath + '/scripts -o ' + self.EPCSourceCodePath + '/scripts/spgwu_' + self.testCase_id + '.log ./my-spgwu.sh', '\$', 5) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('source oaienv', '\$', 5) - self.command('cd scripts', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S ./run_spgw 2>&1 | stdbuf -o0 tee -a spgw_' + self.testCase_id + '.log &', 'Initializing SPGW-APP task interface: DONE', 30) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cd /opt/ltebox/tools', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S ./start_xGw', '\$', 5) - else: - logging.error('This option should not occur!') - self.close() - self.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) - - def CheckFlexranCtrlInstallation(self): - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '': - return - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('ls -ls /opt/flexran_rtc/*/rt_controller', '\$', 5) - result = re.search('/opt/flexran_rtc/build/rt_controller', str(self.ssh.before)) - if result is not None: - self.flexranCtrlInstalled = True - logging.debug('Flexran Controller is installed') - self.close() - - def InitializeFlexranCtrl(self): - if self.flexranCtrlInstalled == False: - return - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd /opt/flexran_rtc', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f log/*.log', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S echo "build/rt_controller -c log_config/basic_log" > ./my-flexran-ctl.sh', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S chmod 755 ./my-flexran-ctl.sh', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S daemon --unsafe --name=flexran_rtc_daemon --chdir=/opt/flexran_rtc -o /opt/flexran_rtc/log/flexranctl_' + self.testCase_id + '.log ././my-flexran-ctl.sh', '\$', 5) - self.command('ps -aux | grep --color=never rt_controller', '\$', 5) - result = re.search('rt_controller -c ', str(self.ssh.before)) - if result is not None: - logging.debug('\u001B[1m Initialize FlexRan Controller Completed\u001B[0m') - self.flexranCtrlStarted = True - self.close() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def InitializeeNB(self): - if self.eNB_serverId == '0': - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - lSourcePath = self.eNBSourceCodePath - elif self.eNB_serverId == '1': - lIpAddr = self.eNB1IPAddress - lUserName = self.eNB1UserName - lPassWord = self.eNB1Password - lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId == '2': - lIpAddr = self.eNB2IPAddress - lUserName = self.eNB2UserName - lPassWord = self.eNB2Password - lSourcePath = self.eNB2SourceCodePath - if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - Usage() - sys.exit('Insufficient Parameter') - check_eNB = False - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - self.CreateHtmlTestRow(self.Initialize_eNB_args, 'KO', pStatus) - self.CreateHtmlTabFooter(False) - sys.exit(1) - # If tracer options is on, running tshark on EPC side and capture traffic b/ EPC and eNB - result = re.search('T_stdout', str(self.Initialize_eNB_args)) - if result is not None: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('ip addr show | awk -f /tmp/active_net_interfaces.awk | egrep -v "lo|tun"', '\$', 5) - result = re.search('interfaceToUse=(?P[a-zA-Z0-9\-\_]+)done', str(self.ssh.before)) - if result is not None: - eth_interface = result.group('eth_interface') - logging.debug('\u001B[1m Launching tshark on interface ' + eth_interface + '\u001B[0m') - self.EPC_PcapFileName = 'enb_' + self.testCase_id + '_s1log.pcap' - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f /tmp/' + self.EPC_PcapFileName, '\$', 5) - self.command('echo $USER; nohup sudo tshark -f "host ' + lIpAddr +'" -i ' + eth_interface + ' -w /tmp/' + self.EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', self.EPCUserName, 5) - self.close() - self.open(lIpAddr, lUserName, lPassWord) - self.command('cd ' + lSourcePath, '\$', 5) - # Initialize_eNB_args usually start with -O and followed by the location in repository - full_config_file = self.Initialize_eNB_args.replace('-O ','') - extra_options = '' - extIdx = full_config_file.find('.conf') - if (extIdx > 0): - extra_options = full_config_file[extIdx + 5:] - # if tracer options is on, compiling and running T Tracer - result = re.search('T_stdout', str(extra_options)) - if result is not None: - logging.debug('\u001B[1m Compiling and launching T Tracer\u001B[0m') - self.command('cd common/utils/T/tracer', '\$', 5) - self.command('make', '\$', 10) - self.command('echo $USER; nohup ./record -d ../T_messages.txt -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.raw -ON -off VCD -off HEAVY -off LEGACY_GROUP_TRACE -off LEGACY_GROUP_DEBUG > ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.log 2>&1 &', lUserName, 5) - self.command('cd ' + lSourcePath, '\$', 5) - full_config_file = full_config_file[:extIdx + 5] - config_path, config_file = os.path.split(full_config_file) - else: - sys.exit('Insufficient Parameter') - ci_full_config_file = config_path + '/ci-' + config_file - rruCheck = False - result = re.search('^rru|^rcc|^du.band', str(config_file)) - if result is not None: - rruCheck = True - # do not reset board twice in IF4.5 case - result = re.search('^rru|^enb|^du.band', str(config_file)) - if result is not None: - self.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 10) - result = re.search('type: b200', str(self.ssh.before)) - if result is not None: - logging.debug('Found a B2xx device --> resetting it') - self.command('echo ' + lPassWord + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10) - # Reloading FGPA bin firmware - self.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 15) - # Make a copy and adapt to EPC / eNB IP addresses - self.command('cp ' + full_config_file + ' ' + ci_full_config_file, '\$', 5) - self.command('sed -i -e \'s/CI_MME_IP_ADDR/' + self.EPCIPAddress + '/\' ' + ci_full_config_file, '\$', 2); - self.command('sed -i -e \'s/CI_ENB_IP_ADDR/' + lIpAddr + '/\' ' + ci_full_config_file, '\$', 2); - self.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2); - self.command('sed -i -e \'s/CI_RRU1_IP_ADDR/' + self.eNB1IPAddress + '/\' ' + ci_full_config_file, '\$', 2); - self.command('sed -i -e \'s/CI_RRU2_IP_ADDR/' + self.eNB2IPAddress + '/\' ' + ci_full_config_file, '\$', 2); - if self.flexranCtrlInstalled and self.flexranCtrlStarted: - self.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "yes";/\' ' + ci_full_config_file, '\$', 2); - else: - self.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "no";/\' ' + ci_full_config_file, '\$', 2); - # Launch eNB with the modified config file - self.command('source oaienv', '\$', 5) - self.command('cd cmake_targets', '\$', 5) - self.command('echo "ulimit -c unlimited && ./lte_build_oai/build/lte-softmodem -O ' + lSourcePath + '/' + ci_full_config_file + extra_options + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - self.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - self.command('chmod 775 ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - self.command('echo ' + lPassWord + ' | sudo -S rm -Rf enb_' + self.testCase_id + '.log', '\$', 5) - self.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=enb' + str(self.eNB_instance) + '_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - self.eNBLogFiles[int(self.eNB_instance)] = 'enb_' + self.testCase_id + '.log' - if extra_options != '': - self.eNBOptions[int(self.eNB_instance)] = extra_options - time.sleep(6) - doLoop = True - loopCounter = 10 - while (doLoop): - loopCounter = loopCounter - 1 - if (loopCounter == 0): - # In case of T tracer recording, we may need to kill it - result = re.search('T_stdout', str(self.Initialize_eNB_args)) - if result is not None: - self.command('killall --signal SIGKILL record', '\$', 5) - self.close() - doLoop = False - logging.error('\u001B[1;37;41m eNB logging system did not show got sync! \u001B[0m') - self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'KO', ALL_PROCESSES_OK) - # In case of T tracer recording, we need to kill tshark on EPC side - result = re.search('T_stdout', str(self.Initialize_eNB_args)) - if result is not None: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - logging.debug('\u001B[1m Stopping tshark \u001B[0m') - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) - if self.EPC_PcapFileName != '': - time.sleep(0.5) - self.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 /tmp/' + self.EPC_PcapFileName, '\$', 5) - self.close() - time.sleep(1) - if self.EPC_PcapFileName != '': - copyin_res = self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + self.EPC_PcapFileName, '.') - if (copyin_res == 0): - self.copyout(lIpAddr, lUserName, lPassWord, self.EPC_PcapFileName, lSourcePath + '/cmake_targets/.') - self.prematureExit = True - return - else: - self.command('stdbuf -o0 cat enb_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync|Starting"', '\$', 4) - if rruCheck: - result = re.search('wait RUs', str(self.ssh.before)) - else: - result = re.search('got sync|Starting F1AP at CU', str(self.ssh.before)) - if result is None: - time.sleep(6) - else: - doLoop = False - self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'OK', ALL_PROCESSES_OK) - logging.debug('\u001B[1m Initialize eNB Completed\u001B[0m') - time.sleep(10) - - self.close() - - def InitializeUE_common(self, device_id, idx): - try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - if not self.ADBCentralized: - # Reboot UE - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesRebootCmd[idx], '\$', 60) - # Wait - #time.sleep(60) - # Put in LTE-Mode only - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode 11"\'', '\$', 60) - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode1 11"\'', '\$', 60) - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode2 11"\'', '\$', 60) - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode3 11"\'', '\$', 60) - # enable data service - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) - # we need to do radio on/off cycle to make sure of above changes - # airplane mode off // radio on - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) - #time.sleep(10) - # airplane mode on // radio off - #self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) - - # normal procedure without reboot - # enable data service - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) - # airplane mode on // radio off - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) - self.close() - return - # enable data service - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data enable"', '\$', 60) - - # The following commands are deprecated since we no longer work on Android 7+ - # self.command('stdbuf -o0 adb -s ' + device_id + ' shell settings put global airplane_mode_on 1', '\$', 10) - # self.command('stdbuf -o0 adb -s ' + device_id + ' shell am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true', '\$', 60) - # a dedicated script has to be installed inside the UE - # airplane mode on means call /data/local/tmp/off - if device_id == '84B7N16418004022': - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) - else: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) - #airplane mode off means call /data/local/tmp/on - logging.debug('\u001B[1mUE (' + device_id + ') Initialize Completed\u001B[0m') - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def InitializeUE(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - multi_jobs = [] - i = 0 - for device_id in self.UEDevices: - p = Process(target = self.InitializeUE_common, args = (device_id,i,)) - p.daemon = True - p.start() - multi_jobs.append(p) - i += 1 - for job in multi_jobs: - job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def InitializeOAIUE(self): - if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) - if result is None: - check_eNB = True - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', pStatus) - self.CreateHtmlTabFooter(False) - sys.exit(1) - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - # b2xx_fx3_utils reset procedure - self.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 10) - result = re.search('type: b200', str(self.ssh.before)) - if result is not None: - logging.debug('Found a B2xx device --> resetting it') - self.command('echo ' + self.UEPassword + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10) - # Reloading FGPA bin firmware - self.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 15) - else: - logging.debug('Did not find any B2xx device') - self.command('cd ' + self.UESourceCodePath, '\$', 5) - self.command('source oaienv', '\$', 5) - self.command('cd cmake_targets/lte_build_oai/build', '\$', 5) - result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) - # We may have to regenerate the .u* files - if result is None: - self.command('ls /tmp/*.sed', '\$', 5) - result = re.search('adapt_usim_parameters', str(self.ssh.before)) - if result is not None: - self.command('sed -f /tmp/adapt_usim_parameters.sed ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5) - else: - self.command('sed -e "s#93#92#" -e "s#8baf473f2f8fd09487cccbd7097c6862#fec86ba6eb707ed08905757b1bb44b8f#" -e "s#e734f8734007d6c5ce7a0508809e7e9c#C42449363BBAD02B66D16BC975D77CC1#" ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5) - self.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf .u*', '\$', 5) - self.command('echo ' + self.UEPassword + ' | sudo -S ../../../targets/bin/conf2uedata -c ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf -o .', '\$', 5) - # Launch UE with the modified config file - self.command('echo "ulimit -c unlimited && ./lte-uesoftmodem ' + self.Initialize_OAI_UE_args + '" > ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) - self.command('chmod 775 ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) - self.UELogFile = 'ue_' + self.testCase_id + '.log' - - # We are now looping several times to hope we really sync w/ an eNB - doOutterLoop = True - outterLoopCounter = 5 - gotSyncStatus = True - fullSyncStatus = True - while (doOutterLoop): - self.command('cd ' + self.UESourceCodePath + '/cmake_targets/lte_build_oai/build', '\$', 5) - self.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log', '\$', 5) - self.command('echo ' + self.UEPassword + ' | sudo -S -E daemon --inherit --unsafe --name=ue' + str(self.UE_instance) + '_daemon --chdir=' + self.UESourceCodePath + '/cmake_targets/lte_build_oai/build -o ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) - time.sleep(6) - self.command('cd ../..', '\$', 5) - doLoop = True - loopCounter = 10 - gotSyncStatus = True - # the 'got sync' message is for the UE threads synchronization - while (doLoop): - loopCounter = loopCounter - 1 - if (loopCounter == 0): - # Here should never occur - logging.error('"got sync" message never showed!') - gotSyncStatus = False - doLoop = False - continue - self.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4) - result = re.search('got sync', str(self.ssh.before)) - if result is None: - time.sleep(6) - else: - doLoop = False - logging.debug('Found "got sync" message!') - if gotSyncStatus == False: - # we certainly need to stop the lte-uesoftmodem process if it is still running! - self.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4) - result = re.search('lte-uesoftmodem', str(self.ssh.before)) - if result is not None: - self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT lte-uesoftmodem', '\$', 4) - time.sleep(3) - # We are now checking if sync w/ eNB DOES NOT OCCUR - # Usually during the cell synchronization stage, the UE returns with No cell synchronization message - doLoop = True - loopCounter = 10 - while (doLoop): - loopCounter = loopCounter - 1 - if (loopCounter == 0): - # Here we do have a great chance that the UE did cell-sync w/ eNB - doLoop = False - doOutterLoop = False - fullSyncStatus = True - continue - self.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4) - result = re.search('No cell synchronization found', str(self.ssh.before)) - if result is None: - time.sleep(6) - else: - doLoop = False - fullSyncStatus = False - logging.debug('Found: "No cell synchronization" message! --> try again') - time.sleep(6) - self.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4) - result = re.search('lte-uesoftmodem', str(self.ssh.before)) - if result is not None: - self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT lte-uesoftmodem', '\$', 4) - outterLoopCounter = outterLoopCounter - 1 - if (outterLoopCounter == 0): - doOutterLoop = False - - if fullSyncStatus and gotSyncStatus: - result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) - if result is None: - self.command('ifconfig oaitun_ue1', '\$', 4) - # ifconfig output is different between ubuntu 16 and ubuntu 18 - result = re.search('inet addr:1|inet 1', str(self.ssh.before)) - if result is not None: - logging.debug('\u001B[1m oaitun_ue1 interface is mounted and configured\u001B[0m') - tunnelInterfaceStatus = True - else: - logging.debug(str(self.ssh.before)) - logging.error('\u001B[1m oaitun_ue1 interface is either NOT mounted or NOT configured\u001B[0m') - tunnelInterfaceStatus = False - else: - tunnelInterfaceStatus = True - - self.close() - if fullSyncStatus and gotSyncStatus and tunnelInterfaceStatus: - self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE') - logging.debug('\u001B[1m Initialize OAI UE Completed\u001B[0m') - if (self.ADBIPAddress != 'none'): - self.UEDevices = [] - self.UEDevices.append('OAI-UE') - self.UEDevicesStatus = [] - self.UEDevicesStatus.append(UE_STATUS_DETACHED) - else: - self.htmlUEFailureMsg = 'oaitun_ue1 interface is either NOT mounted or NOT configured' - self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', OAI_UE_PROCESS_NO_TUNNEL_INTERFACE, 'OAI UE') - logging.error('\033[91mInitialize OAI UE Failed! \033[0m') - self.AutoTerminateUEandeNB() - - def checkDevTTYisUnlocked(self): - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - count = 0 - while count < 5: - self.command('echo ' + self.ADBPassword + ' | sudo -S lsof | grep ttyUSB0', '\$', 10) - result = re.search('picocom', str(self.ssh.before)) - if result is None: - count = 10 - else: - time.sleep(5) - count = count + 1 - self.close() - - def InitializeCatM(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - self.picocom_closure = True - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` - self.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) - self.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) - time.sleep(1) - # Calling twice AT to clear all buffers - self.command('AT', 'OK|ERROR', 5) - self.command('AT', 'OK', 5) - # Disabling the Radio - self.command('AT+CFUN=0', 'OK', 5) - logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') - # Checking if auto-attach is enabled - self.command('AT^AUTOATT?', 'OK', 5) - result = re.search('AUTOATT: (?P[0-9\-]+)', str(self.ssh.before)) - if result is not None: - if result.group('state') is not None: - autoAttachState = int(result.group('state')) - if autoAttachState is not None: - if autoAttachState == 0: - self.command('AT^AUTOATT=1', 'OK', 5) - logging.debug('\u001B[1m Auto-Attach enabled\u001B[0m') - else: - logging.debug('\u001B[1;37;41m Could not check Auto-Attach! \u001B[0m') - # Force closure of picocom but device might still be locked - self.close() - self.picocom_closure = False - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - self.checkDevTTYisUnlocked() - - def TerminateCatM(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - self.picocom_closure = True - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` - self.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) - self.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) - time.sleep(1) - # Calling twice AT to clear all buffers - self.command('AT', 'OK|ERROR', 5) - self.command('AT', 'OK', 5) - # Disabling the Radio - self.command('AT+CFUN=0', 'OK', 5) - logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') - self.close() - self.picocom_closure = False - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - self.checkDevTTYisUnlocked() - - def AttachCatM(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - self.picocom_closure = True - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` - self.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) - self.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) - time.sleep(1) - # Calling twice AT to clear all buffers - self.command('AT', 'OK|ERROR', 5) - self.command('AT', 'OK', 5) - # Enabling the Radio - self.command('AT+CFUN=1', 'SIMSTORE,READY', 5) - logging.debug('\u001B[1m Cellular Functionality enabled\u001B[0m') - time.sleep(4) - # We should check if we register - count = 0 - attach_cnt = 0 - attach_status = False - while count < 5: - self.command('AT+CEREG?', 'OK', 5) - result = re.search('CEREG: 2,(?P[0-9\-]+),', str(self.ssh.before)) - if result is not None: - mDataConnectionState = int(result.group('state')) - if mDataConnectionState is not None: - if mDataConnectionState == 1: - count = 10 - attach_status = True - result = re.search('CEREG: 2,1,"(?P[0-9A-Z]+)","(?P[0-9A-Z]+)"', str(self.ssh.before)) - if result is not None: - networky = result.group('networky') - networkz = result.group('networkz') - logging.debug('\u001B[1m CAT-M module attached to eNB (' + str(networky) + '/' + str(networkz) + ')\u001B[0m') - else: - logging.debug('\u001B[1m CAT-M module attached to eNB\u001B[0m') - else: - logging.debug('+CEREG: 2,' + str(mDataConnectionState)) - attach_cnt = attach_cnt + 1 - else: - logging.debug(str(self.ssh.before)) - attach_cnt = attach_cnt + 1 - count = count + 1 - time.sleep(1) - if attach_status: - self.command('AT+CESQ', 'OK', 5) - result = re.search('CESQ: 99,99,255,255,(?P[0-9]+),(?P[0-9]+)', str(self.ssh.before)) - if result is not None: - nRSRQ = int(result.group('rsrq')) - nRSRP = int(result.group('rsrp')) - if (nRSRQ is not None) and (nRSRP is not None): - logging.debug(' RSRQ = ' + str(-20+(nRSRQ/2)) + ' dB') - logging.debug(' RSRP = ' + str(-140+nRSRP) + ' dBm') - self.close() - self.picocom_closure = False - html_queue = SimpleQueue() - self.checkDevTTYisUnlocked() - if attach_status: - html_cell = '
CAT-M module Attachment Completed in ' + str(attach_cnt+4) + ' seconds'
-			if (nRSRQ is not None) and (nRSRP is not None):
-				html_cell += '\n   RSRQ = ' + str(-20+(nRSRQ/2)) + ' dB'
-				html_cell += '\n   RSRP = ' + str(-140+nRSRP) + ' dBm
' - else: - html_cell += '' - html_queue.put(html_cell) - self.CreateHtmlTestRowQueue('N/A', 'OK', 1, html_queue) - else: - logging.error('\u001B[1m CAT-M module Attachment Failed\u001B[0m') - html_cell = '
CAT-M module Attachment Failed
' - html_queue.put(html_cell) - self.CreateHtmlTestRowQueue('N/A', 'KO', 1, html_queue) - self.AutoTerminateUEandeNB() - - def PingCatM(self): - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - check_eNB = True - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - try: - statusQueue = SimpleQueue() - lock = Lock() - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('cd scripts', '\$', 5) - if re.match('OAI', self.EPCType, re.IGNORECASE): - logging.debug('Using the OAI EPC HSS: not implemented yet') - self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) - self.CreateHtmlTabFooter(False) - sys.exit(1) - else: - self.command('egrep --color=never "Allocated ipv4 addr" /opt/ltebox/var/log/xGwLog.0', '\$', 5) - result = re.search('Allocated ipv4 addr: (?P[0-9\.]+) from Pool', str(self.ssh.before)) - if result is not None: - moduleIPAddr = result.group('ipaddr') - else: - self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - ping_time = re.findall("-c (\d+)",str(self.ping_args)) - device_id = 'catm' - ping_status = self.command('stdbuf -o0 ping ' + self.ping_args + ' ' + str(moduleIPAddr) + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) - # TIMEOUT CASE - if ping_status < 0: - message = 'Ping with UE (' + str(moduleIPAddr) + ') crashed due to TIMEOUT!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() - self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) - return - result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', str(self.ssh.before)) - if result is None: - message = 'Packet Loss Not Found!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() - self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) - return - packetloss = result.group('packetloss') - if float(packetloss) == 100: - message = 'Packet Loss is 100%' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() - self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) - return - result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', str(self.ssh.before)) - if result is None: - message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() - self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) - return - rtt_min = result.group('rtt_min') - rtt_avg = result.group('rtt_avg') - rtt_max = result.group('rtt_max') - pal_msg = 'Packet Loss : ' + packetloss + '%' - min_msg = 'RTT(Min) : ' + rtt_min + ' ms' - avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms' - max_msg = 'RTT(Max) : ' + rtt_max + ' ms' - lock.acquire() - logging.debug('\u001B[1;37;44m ping result (' + moduleIPAddr + ') \u001B[0m') - logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') - qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg - packetLossOK = True - if packetloss is not None: - if float(packetloss) > float(self.ping_packetloss_threshold): - qMsg += '\nPacket Loss too high' - logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') - packetLossOK = False - elif float(packetloss) > 0: - qMsg += '\nPacket Loss is not 0%' - logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m') - lock.release() - self.close() - html_cell = '
CAT-M module\nIP Address  : ' + moduleIPAddr + '\n' + qMsg + '
' - statusQueue.put(html_cell) - if (packetLossOK): - self.CreateHtmlTestRowQueue(self.ping_args, 'OK', 1, statusQueue) - else: - self.CreateHtmlTestRowQueue(self.ping_args, 'KO', 1, statusQueue) - self.AutoTerminateUEandeNB() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def AttachUE_common(self, device_id, statusQueue, lock, idx): - try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - if self.ADBCentralized: - if device_id == '84B7N16418004022': - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/on"', '\$', 60) - else: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60) - else: - # airplane mode off // radio on - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) - time.sleep(2) - max_count = 45 - count = max_count - while count > 0: - if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry" | grep -m 1 mDataConnectionState', '\$', 15) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\' | grep -m 1 mDataConnectionState', '\$', 60) - result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', str(self.ssh.before)) - if result is None: - logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m') - lock.acquire() - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put('mDataConnectionState Not Found!') - lock.release() - break - mDataConnectionState = int(result.group('state')) - if mDataConnectionState == 2: - logging.debug('\u001B[1mUE (' + device_id + ') Attach Completed\u001B[0m') - lock.acquire() - statusQueue.put(max_count - count) - statusQueue.put(device_id) - statusQueue.put('Attach Completed') - lock.release() - break - count = count - 1 - if count == 15 or count == 30: - logging.debug('\u001B[1;30;43m Retry UE (' + device_id + ') Flight Mode Off \u001B[0m') - if self.ADBCentralized: - if device_id == '84B7N16418004022': - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) - else: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) - time.sleep(0.5) - if self.ADBCentralized: - if device_id == '84B7N16418004022': - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/on"', '\$', 60) - else: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) - time.sleep(0.5) - logging.debug('\u001B[1mWait UE (' + device_id + ') a second until mDataConnectionState=2 (' + str(max_count-count) + ' times)\u001B[0m') - time.sleep(1) - if count == 0: - logging.debug('\u001B[1;37;41m UE (' + device_id + ') Attach Failed \u001B[0m') - lock.acquire() - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put('Attach Failed') - lock.release() - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def AttachUE(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - check_eNB = True - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - self.CreateHtmlTestRow('N/A', 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - multi_jobs = [] - status_queue = SimpleQueue() - lock = Lock() - nb_ue_to_connect = 0 - for device_id in self.UEDevices: - if (self.nbMaxUEtoAttach == -1) or (nb_ue_to_connect < self.nbMaxUEtoAttach): - self.UEDevicesStatus[nb_ue_to_connect] = UE_STATUS_ATTACHING - p = Process(target = self.AttachUE_common, args = (device_id, status_queue, lock,nb_ue_to_connect,)) - p.daemon = True - p.start() - multi_jobs.append(p) - nb_ue_to_connect = nb_ue_to_connect + 1 - for job in multi_jobs: - job.join() - - if (status_queue.empty()): - self.CreateHtmlTestRow('N/A', 'KO', ALL_PROCESSES_OK) - self.AutoTerminateUEandeNB() - return - else: - attach_status = True - html_queue = SimpleQueue() - while (not status_queue.empty()): - count = status_queue.get() - if (count < 0): - attach_status = False - device_id = status_queue.get() - message = status_queue.get() - if (count < 0): - html_cell = '
UE (' + device_id + ')\n' + message + '
' - else: - html_cell = '
UE (' + device_id + ')\n' + message + ' in ' + str(count + 2) + ' seconds
' - html_queue.put(html_cell) - if (attach_status): - # cnt from index to object of a class - cnt = 0 - while cnt < len(self.UEDevices): - if self.UEDevicesStatus[cnt] == UE_STATUS_ATTACHING: - self.UEDevicesStatus[cnt] = UE_STATUS_ATTACHED - cnt += 1 - self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) - result = re.search('T_stdout', str(self.Initialize_eNB_args)) - if result is not None: - logging.debug('Waiting 5 seconds to fill up record file') - time.sleep(5) - else: - self.CreateHtmlTestRowQueue('N/A', 'KO', len(self.UEDevices), html_queue) - self.AutoTerminateUEandeNB() - - def DetachUE_common(self, device_id, idx): - try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - if self.ADBCentralized: - if device_id == '84B7N16418004022': - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) - else: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) - logging.debug('\u001B[1mUE (' + device_id + ') Detach Completed\u001B[0m') - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def DetachUE(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - check_eNB = True - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - self.CreateHtmlTestRow('N/A', 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - multi_jobs = [] - cnt = 0 - for device_id in self.UEDevices: - self.UEDevicesStatus[cnt] = UE_STATUS_DETACHING - p = Process(target = self.DetachUE_common, args = (device_id,cnt,)) - p.daemon = True - p.start() - multi_jobs.append(p) - cnt += 1 - for job in multi_jobs: - job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - result = re.search('T_stdout', str(self.Initialize_eNB_args)) - if result is not None: - logging.debug('Waiting 5 seconds to fill up record file') - time.sleep(5) - cnt = 0 - while cnt < len(self.UEDevices): - self.UEDevicesStatus[cnt] = UE_STATUS_DETACHED - cnt += 1 - - def RebootUE_common(self, device_id): - try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - previousmDataConnectionStates = [] - # Save mDataConnectionState - self.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) - self.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) - result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', str(self.ssh.before)) - if result is None: - logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m') - sys.exit(1) - previousmDataConnectionStates.append(int(result.group('state'))) - # Reboot UE - self.command('stdbuf -o0 adb -s ' + device_id + ' shell reboot', '\$', 10) - time.sleep(60) - previousmDataConnectionState = previousmDataConnectionStates.pop(0) - count = 180 - while count > 0: - count = count - 1 - self.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) - result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', str(self.ssh.before)) - if result is None: - mDataConnectionState = None - else: - mDataConnectionState = int(result.group('state')) - logging.debug('mDataConnectionState = ' + result.group('state')) - if mDataConnectionState is None or (previousmDataConnectionState == 2 and mDataConnectionState != 2): - logging.debug('\u001B[1mWait UE (' + device_id + ') a second until reboot completion (' + str(180-count) + ' times)\u001B[0m') - time.sleep(1) - else: - logging.debug('\u001B[1mUE (' + device_id + ') Reboot Completed\u001B[0m') - break - if count == 0: - logging.debug('\u001B[1;37;41m UE (' + device_id + ') Reboot Failed \u001B[0m') - sys.exit(1) - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def RebootUE(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - check_eNB = True - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - self.CreateHtmlTestRow('N/A', 'KO', pStatus) - self.CreateHtmlTabFooter(False) - sys.exit(1) - multi_jobs = [] - for device_id in self.UEDevices: - p = Process(target = self.RebootUE_common, args = (device_id,)) - p.daemon = True - p.start() - multi_jobs.append(p) - for job in multi_jobs: - job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def DataDisableUE_common(self, device_id, idx): - try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - # disable data service - if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data disable"', '\$', 60) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data disable"\'', '\$', 60) - logging.debug('\u001B[1mUE (' + device_id + ') Disabled Data Service\u001B[0m') - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def DataDisableUE(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - multi_jobs = [] - i = 0 - for device_id in self.UEDevices: - p = Process(target = self.DataDisableUE_common, args = (device_id,i,)) - p.daemon = True - p.start() - multi_jobs.append(p) - i += 1 - for job in multi_jobs: - job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def DataEnableUE_common(self, device_id, idx): - try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - # enable data service - if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data enable"', '\$', 60) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) - logging.debug('\u001B[1mUE (' + device_id + ') Enabled Data Service\u001B[0m') - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def DataEnableUE(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - multi_jobs = [] - i = 0 - for device_id in self.UEDevices: - p = Process(target = self.DataEnableUE_common, args = (device_id,i,)) - p.daemon = True - p.start() - multi_jobs.append(p) - i += 1 - for job in multi_jobs: - job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def GetAllUEDevices(self, terminate_ue_flag): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - if self.ADBCentralized: - self.command('adb devices', '\$', 15) - self.UEDevices = re.findall("\\\\r\\\\n([A-Za-z0-9]+)\\\\tdevice",str(self.ssh.before)) - self.close() - else: - if (os.path.isfile('./phones_list.txt')): - os.remove('./phones_list.txt') - self.command('ls /etc/*/phones*.txt', '\$', 5) - result = re.search('/etc/ci/phones_list.txt', str(self.ssh.before)) - self.close() - if (result is not None) and (len(self.UEDevices) == 0): - self.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, '/etc/ci/phones_list.txt', '.') - if (os.path.isfile('./phones_list.txt')): - phone_list_file = open('./phones_list.txt', 'r') - for line in phone_list_file.readlines(): - line = line.strip() - result = re.search('^#', line) - if result is not None: - continue - comma_split = line.split(",") - self.UEDevices.append(comma_split[0]) - self.UEDevicesRemoteServer.append(comma_split[1]) - self.UEDevicesRemoteUser.append(comma_split[2]) - self.UEDevicesOffCmd.append(comma_split[3]) - self.UEDevicesOnCmd.append(comma_split[4]) - self.UEDevicesRebootCmd.append(comma_split[5]) - phone_list_file.close() - - if terminate_ue_flag == False: - if len(self.UEDevices) == 0: - logging.debug('\u001B[1;37;41m UE Not Found! \u001B[0m') - sys.exit(1) - if len(self.UEDevicesStatus) == 0: - cnt = 0 - while cnt < len(self.UEDevices): - self.UEDevicesStatus.append(UE_STATUS_DETACHED) - cnt += 1 - - def GetAllCatMDevices(self, terminate_ue_flag): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - if self.ADBCentralized: - self.command('lsusb | egrep "Future Technology Devices International, Ltd FT2232C" | sed -e "s#:.*##" -e "s# #_#g"', '\$', 15) - self.CatMDevices = re.findall("\\\\r\\\\n([A-Za-z0-9_]+)",str(self.ssh.before)) - else: - if (os.path.isfile('./modules_list.txt')): - os.remove('./modules_list.txt') - self.command('ls /etc/*/modules*.txt', '\$', 5) - result = re.search('/etc/ci/modules_list.txt', str(self.ssh.before)) - self.close() - if result is not None: - logging.debug('Found a module list file on ADB server') - if terminate_ue_flag == False: - if len(self.CatMDevices) == 0: - logging.debug('\u001B[1;37;41m CAT-M UE Not Found! \u001B[0m') - sys.exit(1) - self.close() - - def CheckUEStatus_common(self, lock, device_id, statusQueue, idx): - try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry"', '\$', 15) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\'', '\$', 60) - result = re.search('mServiceState=(?P[0-9]+)', str(self.ssh.before)) - serviceState = 'Service State: UNKNOWN' - if result is not None: - lServiceState = int(result.group('serviceState')) - if lServiceState == 3: - serviceState = 'Service State: RADIO_POWERED_OFF' - if lServiceState == 1: - serviceState = 'Service State: OUT_OF_SERVICE' - if lServiceState == 0: - serviceState = 'Service State: IN_SERVICE' - if lServiceState == 2: - serviceState = 'Service State: EMERGENCY_ONLY' - result = re.search('mDataConnectionState=(?P[0-9]+)', str(self.ssh.before)) - dataConnectionState = 'Data State: UNKNOWN' - if result is not None: - lDataConnectionState = int(result.group('dataConnectionState')) - if lDataConnectionState == 0: - dataConnectionState = 'Data State: DISCONNECTED' - if lDataConnectionState == 1: - dataConnectionState = 'Data State: CONNECTING' - if lDataConnectionState == 2: - dataConnectionState = 'Data State: CONNECTED' - if lDataConnectionState == 3: - dataConnectionState = 'Data State: SUSPENDED' - result = re.search('mDataConnectionReason=(?P[0-9a-zA-Z_]+)', str(self.ssh.before)) - dataConnectionReason = 'Data Reason: UNKNOWN' - if result is not None: - dataConnectionReason = 'Data Reason: ' + result.group('dataConnectionReason') - lock.acquire() - logging.debug('\u001B[1;37;44m Status Check (' + str(device_id) + ') \u001B[0m') - logging.debug('\u001B[1;34m ' + serviceState + '\u001B[0m') - logging.debug('\u001B[1;34m ' + dataConnectionState + '\u001B[0m') - logging.debug('\u001B[1;34m ' + dataConnectionReason + '\u001B[0m') - statusQueue.put(0) - statusQueue.put(device_id) - qMsg = serviceState + '\n' + dataConnectionState + '\n' + dataConnectionReason - statusQueue.put(qMsg) - lock.release() - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def CheckStatusUE(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - check_eNB = True - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - self.CreateHtmlTestRow('N/A', 'KO', pStatus) - self.CreateHtmlTabFooter(False) - sys.exit(1) - multi_jobs = [] - lock = Lock() - status_queue = SimpleQueue() - i = 0 - for device_id in self.UEDevices: - p = Process(target = self.CheckUEStatus_common, args = (lock,device_id,status_queue,i,)) - p.daemon = True - p.start() - multi_jobs.append(p) - i += 1 - for job in multi_jobs: - job.join() - if self.flexranCtrlInstalled and self.flexranCtrlStarted: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd /opt/flexran_rtc', '\$', 5) - self.command('curl http://localhost:9999/stats | jq \'.\' > log/check_status_' + self.testCase_id + '.log 2>&1', '\$', 5) - self.command('cat log/check_status_' + self.testCase_id + '.log | jq \'.eNB_config[0].UE\' | grep -c rnti | sed -e "s#^#Nb Connected UE = #"', '\$', 5) - result = re.search('Nb Connected UE = (?P[0-9]+)', str(self.ssh.before)) - passStatus = True - if result is not None: - nb_ues = int(result.group('nb_ues')) - htmlOptions = 'Nb Connected UE(s) to eNB = ' + str(nb_ues) - logging.debug('\u001B[1;37;44m ' + htmlOptions + ' \u001B[0m') - if self.expectedNbOfConnectedUEs > -1: - if nb_ues != self.expectedNbOfConnectedUEs: - passStatus = False - else: - htmlOptions = 'N/A' - self.close() - else: - passStatus = True - htmlOptions = 'N/A' - - if (status_queue.empty()): - self.CreateHtmlTestRow(htmlOptions, 'KO', ALL_PROCESSES_OK) - self.AutoTerminateUEandeNB() - else: - check_status = True - html_queue = SimpleQueue() - while (not status_queue.empty()): - count = status_queue.get() - if (count < 0): - check_status = False - device_id = status_queue.get() - message = status_queue.get() - html_cell = '
UE (' + device_id + ')\n' + message + '
' - html_queue.put(html_cell) - if check_status and passStatus: - self.CreateHtmlTestRowQueue(htmlOptions, 'OK', len(self.UEDevices), html_queue) - else: - self.CreateHtmlTestRowQueue(htmlOptions, 'KO', len(self.UEDevices), html_queue) - self.AutoTerminateUEandeNB() - - def GetAllUEIPAddresses(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - ue_ip_status = 0 - self.UEIPAddresses = [] - if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): - if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('ifconfig oaitun_ue1', '\$', 4) - result = re.search('inet addr:(?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)|inet (?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)', str(self.ssh.before)) - if result is not None: - if result.group('ueipaddress') is not None: - UE_IPAddress = result.group('ueipaddress') - else: - UE_IPAddress = result.group('ueipaddress2') - logging.debug('\u001B[1mUE (' + self.UEDevices[0] + ') IP Address is ' + UE_IPAddress + '\u001B[0m') - self.UEIPAddresses.append(UE_IPAddress) - else: - logging.debug('\u001B[1;37;41m UE IP Address Not Found! \u001B[0m') - ue_ip_status -= 1 - self.close() - return ue_ip_status - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - idx = 0 - for device_id in self.UEDevices: - if self.UEDevicesStatus[idx] != UE_STATUS_ATTACHED: - idx += 1 - continue - count = 0 - while count < 4: - if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "ip addr show | grep rmnet"', '\$', 15) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ip addr show | grep rmnet"\'', '\$', 60) - result = re.search('inet (?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\/[0-9]+[0-9a-zA-Z\.\s]+', str(self.ssh.before)) - if result is None: - logging.debug('\u001B[1;37;41m UE IP Address Not Found! \u001B[0m') - time.sleep(1) - count += 1 - else: - count = 10 - if count < 9: - ue_ip_status -= 1 - continue - UE_IPAddress = result.group('ueipaddress') - logging.debug('\u001B[1mUE (' + device_id + ') IP Address is ' + UE_IPAddress + '\u001B[0m') - for ueipaddress in self.UEIPAddresses: - if ueipaddress == UE_IPAddress: - logging.debug('\u001B[1mUE (' + device_id + ') IP Address ' + UE_IPAddress + ': has already been allocated to another device !' + '\u001B[0m') - ue_ip_status -= 1 - continue - self.UEIPAddresses.append(UE_IPAddress) - idx += 1 - self.close() - return ue_ip_status - - def ping_iperf_wrong_exit(self, lock, UE_IPAddress, device_id, statusQueue, message): - lock.acquire() - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - statusQueue.put(message) - lock.release() - - def Ping_common(self, lock, UE_IPAddress, device_id, statusQueue): - try: - # Launch ping on the EPC side (true for ltebox and old open-air-cn) - # But for OAI-Rel14-CUPS, we launch from python executor - launchFromEpc = True - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - launchFromEpc = False - ping_time = re.findall("-c (\d+)",str(self.ping_args)) - - if launchFromEpc: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('cd scripts', '\$', 5) - ping_status = self.command('stdbuf -o0 ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) - else: - cmd = 'ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 > ping_' + self.testCase_id + '_' + device_id + '.log' - message = cmd + '\n' - logging.debug(cmd) - ret = subprocess.run(cmd, shell=True) - ping_status = ret.returncode - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'ping_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cat ' + self.EPCSourceCodePath + '/scripts/ping_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - # TIMEOUT CASE - if ping_status < 0: - message = 'Ping with UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) - return - result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', str(self.ssh.before)) - if result is None: - message = 'Packet Loss Not Found!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) - return - packetloss = result.group('packetloss') - if float(packetloss) == 100: - message = 'Packet Loss is 100%' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) - return - result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', str(self.ssh.before)) - if result is None: - message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) - return - rtt_min = result.group('rtt_min') - rtt_avg = result.group('rtt_avg') - rtt_max = result.group('rtt_max') - pal_msg = 'Packet Loss : ' + packetloss + '%' - min_msg = 'RTT(Min) : ' + rtt_min + ' ms' - avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms' - max_msg = 'RTT(Max) : ' + rtt_max + ' ms' - lock.acquire() - logging.debug('\u001B[1;37;44m ping result (' + UE_IPAddress + ') \u001B[0m') - logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') - qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg - packetLossOK = True - if packetloss is not None: - if float(packetloss) > float(self.ping_packetloss_threshold): - qMsg += '\nPacket Loss too high' - logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') - packetLossOK = False - elif float(packetloss) > 0: - qMsg += '\nPacket Loss is not 0%' - logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m') - if (packetLossOK): - statusQueue.put(0) - else: - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - statusQueue.put(qMsg) - lock.release() - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def PingNoS1_wrong_exit(self, qMsg): - html_queue = SimpleQueue() - html_cell = '
OAI UE ping result\n' + qMsg + '
' - html_queue.put(html_cell) - self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) - - def PingNoS1(self): - check_eNB = True - check_OAI_UE = True - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - ping_from_eNB = re.search('oaitun_enb1', str(self.ping_args)) - if ping_from_eNB is not None: - if self.eNBIPAddress == '' or self.eNBUserName == '' or self.eNBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - else: - if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': - Usage() - sys.exit('Insufficient Parameter') - try: - if ping_from_eNB is not None: - self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) - self.command('cd ' + self.eNBSourceCodePath + '/cmake_targets/', '\$', 5) - else: - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('cd ' + self.UESourceCodePath + '/cmake_targets/', '\$', 5) - self.command('cd cmake_targets', '\$', 5) - ping_time = re.findall("-c (\d+)",str(self.ping_args)) - ping_status = self.command('stdbuf -o0 ping ' + self.ping_args + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '.log', '\$', int(ping_time[0])*1.5) - # TIMEOUT CASE - if ping_status < 0: - message = 'Ping with OAI UE crashed due to TIMEOUT!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.PingNoS1_wrong_exit(message) - return - result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', str(self.ssh.before)) - if result is None: - message = 'Packet Loss Not Found!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.PingNoS1_wrong_exit(message) - return - packetloss = result.group('packetloss') - if float(packetloss) == 100: - message = 'Packet Loss is 100%' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.PingNoS1_wrong_exit(message) - return - result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', str(self.ssh.before)) - if result is None: - message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.PingNoS1_wrong_exit(message) - return - rtt_min = result.group('rtt_min') - rtt_avg = result.group('rtt_avg') - rtt_max = result.group('rtt_max') - pal_msg = 'Packet Loss : ' + packetloss + '%' - min_msg = 'RTT(Min) : ' + rtt_min + ' ms' - avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms' - max_msg = 'RTT(Max) : ' + rtt_max + ' ms' - logging.debug('\u001B[1;37;44m OAI UE ping result \u001B[0m') - logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') - qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg - packetLossOK = True - if packetloss is not None: - if float(packetloss) > float(self.ping_packetloss_threshold): - qMsg += '\nPacket Loss too high' - logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') - packetLossOK = False - elif float(packetloss) > 0: - qMsg += '\nPacket Loss is not 0%' - logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m') - self.close() - html_queue = SimpleQueue() - ip_addr = 'TBD' - html_cell = '
OAI UE ping result\n' + qMsg + '
' - html_queue.put(html_cell) - if packetLossOK: - self.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) - else: - self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) - - # copying on the EPC server for logCollection - if ping_from_eNB is not None: - copyin_res = self.copyin(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.eNBSourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') - else: - copyin_res = self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') - if (copyin_res == 0): - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'ping_' + self.testCase_id + '.log', self.EPCSourceCodePath + '/scripts') - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def Ping(self): - result = re.search('noS1', str(self.Initialize_eNB_args)) - if result is not None: - self.PingNoS1() - return - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - check_eNB = True - if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): - check_OAI_UE = True - else: - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - ueIpStatus = self.GetAllUEIPAddresses() - if (ueIpStatus < 0): - self.CreateHtmlTestRow(self.ping_args, 'KO', UE_IP_ADDRESS_ISSUE) - self.AutoTerminateUEandeNB() - return - multi_jobs = [] - i = 0 - lock = Lock() - status_queue = SimpleQueue() - for UE_IPAddress in self.UEIPAddresses: - device_id = self.UEDevices[i] - p = Process(target = self.Ping_common, args = (lock,UE_IPAddress,device_id,status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - i = i + 1 - for job in multi_jobs: - job.join() - - if (status_queue.empty()): - self.CreateHtmlTestRow(self.ping_args, 'KO', ALL_PROCESSES_OK) - self.AutoTerminateUEandeNB() - else: - ping_status = True - html_queue = SimpleQueue() - while (not status_queue.empty()): - count = status_queue.get() - if (count < 0): - ping_status = False - device_id = status_queue.get() - ip_addr = status_queue.get() - message = status_queue.get() - html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' - html_queue.put(html_cell) - if (ping_status): - self.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) - else: - self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) - self.AutoTerminateUEandeNB() - - def Iperf_ComputeTime(self): - result = re.search('-t (?P\d+)', str(self.iperf_args)) - if result is None: - logging.debug('\u001B[1;37;41m Iperf time Not Found! \u001B[0m') - sys.exit(1) - return result.group('iperf_time') - - def Iperf_ComputeModifiedBW(self, idx, ue_num): - result = re.search('-b (?P[0-9\.]+)[KMG]', str(self.iperf_args)) - if result is None: - logging.debug('\u001B[1;37;41m Iperf bandwidth Not Found! \u001B[0m') - sys.exit(1) - iperf_bandwidth = result.group('iperf_bandwidth') - if self.iperf_profile == 'balanced': - iperf_bandwidth_new = float(iperf_bandwidth)/ue_num - if self.iperf_profile == 'single-ue': - iperf_bandwidth_new = float(iperf_bandwidth) - if self.iperf_profile == 'unbalanced': - # residual is 2% of max bw - residualBW = float(iperf_bandwidth) / 50 - if idx == 0: - iperf_bandwidth_new = float(iperf_bandwidth) - ((ue_num - 1) * residualBW) - else: - iperf_bandwidth_new = residualBW - iperf_bandwidth_str = '-b ' + iperf_bandwidth - iperf_bandwidth_str_new = '-b ' + ('%.2f' % iperf_bandwidth_new) - result = re.sub(iperf_bandwidth_str, iperf_bandwidth_str_new, str(self.iperf_args)) - if result is None: - logging.debug('\u001B[1;37;41m Calculate Iperf bandwidth Failed! \u001B[0m') - sys.exit(1) - return result - - def Iperf_analyzeV2TCPOutput(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): - self.command('awk -f /tmp/tcp_iperf_stats.awk /tmp/CI-eNB/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - result = re.search('Avg Bitrate : (?P[0-9\.]+ Mbits\/sec) Max Bitrate : (?P[0-9\.]+ Mbits\/sec) Min Bitrate : (?P[0-9\.]+ Mbits\/sec)', str(self.ssh.before)) - if result is not None: - avgbitrate = result.group('average') - maxbitrate = result.group('maximum') - minbitrate = result.group('minimum') - lock.acquire() - logging.debug('\u001B[1;37;44m TCP iperf result (' + UE_IPAddress + ') \u001B[0m') - msg = 'TCP Stats :\n' - if avgbitrate is not None: - logging.debug('\u001B[1;34m Avg Bitrate : ' + avgbitrate + '\u001B[0m') - msg += 'Avg Bitrate : ' + avgbitrate + '\n' - if maxbitrate is not None: - logging.debug('\u001B[1;34m Max Bitrate : ' + maxbitrate + '\u001B[0m') - msg += 'Max Bitrate : ' + maxbitrate + '\n' - if minbitrate is not None: - logging.debug('\u001B[1;34m Min Bitrate : ' + minbitrate + '\u001B[0m') - msg += 'Min Bitrate : ' + minbitrate + '\n' - statusQueue.put(0) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - statusQueue.put(msg) - lock.release() - return 0 - - def Iperf_analyzeV2Output(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): - result = re.search('-u', str(iperf_real_options)) - if result is None: - return self.Iperf_analyzeV2TCPOutput(lock, UE_IPAddress, device_id, statusQueue, iperf_real_options) - - result = re.search('Server Report:', str(self.ssh.before)) - if result is None: - result = re.search('read failed: Connection refused', str(self.ssh.before)) - if result is not None: - logging.debug('\u001B[1;37;41m Could not connect to iperf server! \u001B[0m') - else: - logging.debug('\u001B[1;37;41m Server Report and Connection refused Not Found! \u001B[0m') - return -1 - # Computing the requested bandwidth in float - result = re.search('-b (?P[0-9\.]+)[KMG]', str(iperf_real_options)) - if result is not None: - req_bandwidth = result.group('iperf_bandwidth') - req_bw = float(req_bandwidth) - result = re.search('-b [0-9\.]+K', str(iperf_real_options)) - if result is not None: - req_bandwidth = '%.1f Kbits/sec' % req_bw - req_bw = req_bw * 1000 - result = re.search('-b [0-9\.]+M', str(iperf_real_options)) - if result is not None: - req_bandwidth = '%.1f Mbits/sec' % req_bw - req_bw = req_bw * 1000000 - result = re.search('-b [0-9\.]+G', str(iperf_real_options)) - if result is not None: - req_bandwidth = '%.1f Gbits/sec' % req_bw - req_bw = req_bw * 1000000000 - - result = re.search('Server Report:\\\\r\\\\n(?:|\[ *\d+\].*) (?P[0-9\.]+ [KMG]bits\/sec) +(?P[0-9\.]+ ms) +(\d+\/..\d+) +(\((?P[0-9\.]+)%\))', str(self.ssh.before)) - if result is not None: - bitrate = result.group('bitrate') - packetloss = result.group('packetloss') - jitter = result.group('jitter') - lock.acquire() - logging.debug('\u001B[1;37;44m iperf result (' + UE_IPAddress + ') \u001B[0m') - iperfStatus = True - msg = 'Req Bitrate : ' + req_bandwidth + '\n' - logging.debug('\u001B[1;34m Req Bitrate : ' + req_bandwidth + '\u001B[0m') - if bitrate is not None: - msg += 'Bitrate : ' + bitrate + '\n' - logging.debug('\u001B[1;34m Bitrate : ' + bitrate + '\u001B[0m') - result = re.search('(?P[0-9\.]+) [KMG]bits/sec', str(bitrate)) - if result is not None: - actual_bw = float(str(result.group('real_bw'))) - result = re.search('[0-9\.]+ K', bitrate) - if result is not None: - actual_bw = actual_bw * 1000 - result = re.search('[0-9\.]+ M', bitrate) - if result is not None: - actual_bw = actual_bw * 1000000 - result = re.search('[0-9\.]+ G', bitrate) - if result is not None: - actual_bw = actual_bw * 1000000000 - br_loss = 100 * actual_bw / req_bw - bitperf = '%.2f ' % br_loss - msg += 'Bitrate Perf: ' + bitperf + '%\n' - logging.debug('\u001B[1;34m Bitrate Perf: ' + bitperf + '%\u001B[0m') - if packetloss is not None: - msg += 'Packet Loss : ' + packetloss + '%\n' - logging.debug('\u001B[1;34m Packet Loss : ' + packetloss + '%\u001B[0m') - if float(packetloss) > float(self.iperf_packetloss_threshold): - msg += 'Packet Loss too high!\n' - logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') - iperfStatus = False - if jitter is not None: - msg += 'Jitter : ' + jitter + '\n' - logging.debug('\u001B[1;34m Jitter : ' + jitter + '\u001B[0m') - if (iperfStatus): - statusQueue.put(0) - else: - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - statusQueue.put(msg) - lock.release() - return 0 - else: - return -2 - - def Iperf_analyzeV2Server(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): - if (not os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not analyze from server log') - return - # Computing the requested bandwidth in float - result = re.search('-b (?P[0-9\.]+)[KMG]', str(iperf_real_options)) - if result is None: - logging.debug('Iperf bandwidth Not Found!') - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not compute Iperf bandwidth!') - return - else: - req_bandwidth = result.group('iperf_bandwidth') - req_bw = float(req_bandwidth) - result = re.search('-b [0-9\.]+K', str(iperf_real_options)) - if result is not None: - req_bandwidth = '%.1f Kbits/sec' % req_bw - req_bw = req_bw * 1000 - result = re.search('-b [0-9\.]+M', str(iperf_real_options)) - if result is not None: - req_bandwidth = '%.1f Mbits/sec' % req_bw - req_bw = req_bw * 1000000 - result = re.search('-b [0-9\.]+G', str(iperf_real_options)) - if result is not None: - req_bandwidth = '%.1f Gbits/sec' % req_bw - req_bw = req_bw * 1000000000 - - server_file = open('iperf_server_' + self.testCase_id + '_' + device_id + '.log', 'r') - br_sum = 0.0 - ji_sum = 0.0 - pl_sum = 0 - ps_sum = 0 - row_idx = 0 - for line in server_file.readlines(): - result = re.search('(?P[0-9\.]+ [KMG]bits\/sec) +(?P[0-9\.]+ ms) +(?P[0-9]+)/ +(?P[0-9]+)', str(line)) - if result is not None: - bitrate = result.group('bitrate') - jitter = result.group('jitter') - packetlost = result.group('lostPack') - packetsent = result.group('sentPack') - br = bitrate.split(' ') - ji = jitter.split(' ') - row_idx = row_idx + 1 - curr_br = float(br[0]) - pl_sum = pl_sum + int(packetlost) - ps_sum = ps_sum + int(packetsent) - if (br[1] == 'Kbits/sec'): - curr_br = curr_br * 1000 - if (br[1] == 'Mbits/sec'): - curr_br = curr_br * 1000 * 1000 - br_sum = curr_br + br_sum - ji_sum = float(ji[0]) + ji_sum - if (row_idx > 0): - br_sum = br_sum / row_idx - ji_sum = ji_sum / row_idx - br_loss = 100 * br_sum / req_bw - if (br_sum > 1000): - br_sum = br_sum / 1000 - if (br_sum > 1000): - br_sum = br_sum / 1000 - bitrate = '%.2f Mbits/sec' % br_sum - else: - bitrate = '%.2f Kbits/sec' % br_sum - else: - bitrate = '%.2f bits/sec' % br_sum - bitperf = '%.2f ' % br_loss - bitperf += '%' - jitter = '%.2f ms' % (ji_sum) - if (ps_sum > 0): - pl = float(100 * pl_sum / ps_sum) - packetloss = '%2.1f ' % (pl) - packetloss += '%' - else: - packetloss = 'unknown' - lock.acquire() - if (br_loss < 90): - statusQueue.put(1) - else: - statusQueue.put(0) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - req_msg = 'Req Bitrate : ' + req_bandwidth - bir_msg = 'Bitrate : ' + bitrate - brl_msg = 'Bitrate Perf: ' + bitperf - jit_msg = 'Jitter : ' + jitter - pal_msg = 'Packet Loss : ' + packetloss - statusQueue.put(req_msg + '\n' + bir_msg + '\n' + brl_msg + '\n' + jit_msg + '\n' + pal_msg + '\n') - logging.debug('\u001B[1;37;45m iperf result (' + UE_IPAddress + ') \u001B[0m') - logging.debug('\u001B[1;35m ' + req_msg + '\u001B[0m') - logging.debug('\u001B[1;35m ' + bir_msg + '\u001B[0m') - logging.debug('\u001B[1;35m ' + brl_msg + '\u001B[0m') - logging.debug('\u001B[1;35m ' + jit_msg + '\u001B[0m') - logging.debug('\u001B[1;35m ' + pal_msg + '\u001B[0m') - lock.release() - else: - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not analyze from server log') - - server_file.close() - - - def Iperf_analyzeV3Output(self, lock, UE_IPAddress, device_id, statusQueue): - result = re.search('(?P[0-9\.]+ [KMG]bits\/sec) +(?:|[0-9\.]+ ms +\d+\/\d+ \((?P[0-9\.]+)%\)) +(?:|receiver)\\\\r\\\\n(?:|\[ *\d+\] Sent \d+ datagrams)\\\\r\\\\niperf Done\.', str(self.ssh.before)) - if result is None: - result = re.search('(?Piperf: error - [a-zA-Z0-9 :]+)', str(self.ssh.before)) - lock.acquire() - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - if result is not None: - logging.debug('\u001B[1;37;41m ' + result.group('error') + ' \u001B[0m') - statusQueue.put(result.group('error')) - else: - logging.debug('\u001B[1;37;41m Bitrate and/or Packet Loss Not Found! \u001B[0m') - statusQueue.put('Bitrate and/or Packet Loss Not Found!') - lock.release() - - bitrate = result.group('bitrate') - packetloss = result.group('packetloss') - lock.acquire() - logging.debug('\u001B[1;37;44m iperf result (' + UE_IPAddress + ') \u001B[0m') - logging.debug('\u001B[1;34m Bitrate : ' + bitrate + '\u001B[0m') - msg = 'Bitrate : ' + bitrate + '\n' - iperfStatus = True - if packetloss is not None: - logging.debug('\u001B[1;34m Packet Loss : ' + packetloss + '%\u001B[0m') - msg += 'Packet Loss : ' + packetloss + '%\n' - if float(packetloss) > float(self.iperf_packetloss_threshold): - logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') - msg += 'Packet Loss too high!\n' - iperfStatus = False - if (iperfStatus): - statusQueue.put(0) - else: - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - statusQueue.put(msg) - lock.release() - - def Iperf_UL_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue): - udpIperf = True - result = re.search('-u', str(self.iperf_args)) - if result is None: - udpIperf = False - ipnumbers = UE_IPAddress.split('.') - if (len(ipnumbers) == 4): - ipnumbers[3] = '1' - EPC_Iperf_UE_IPAddress = ipnumbers[0] + '.' + ipnumbers[1] + '.' + ipnumbers[2] + '.' + ipnumbers[3] - - # Launch iperf server on EPC side (true for ltebox and old open-air-cn0 - # But for OAI-Rel14-CUPS, we launch from python executor and we are using its IP address as iperf client address - launchFromEpc = True - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - launchFromEpc = False - cmd = 'hostname -I' - ret = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, encoding='utf-8') - if ret.stdout is not None: - EPC_Iperf_UE_IPAddress = ret.stdout.strip() - port = 5001 + idx - if launchFromEpc: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - if udpIperf: - self.command('echo $USER; nohup iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.EPCUserName, 5) - else: - self.command('echo $USER; nohup iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.EPCUserName, 5) - self.close() - else: - if self.ueIperfVersion == self.dummyIperfVersion: - prefix = '' - else: - prefix = '' - if self.ueIperfVersion == '2.0.5': - prefix = '/opt/iperf-2.0.5/bin/' - if udpIperf: - cmd = 'nohup ' + prefix + 'iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log 2>&1 &' - else: - cmd = 'nohup ' + prefix + 'iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log 2>&1 &' - logging.debug(cmd) - subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, encoding='utf-8') - time.sleep(0.5) - - # Launch iperf client on UE - if (device_id == 'OAI-UE'): - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) - else: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - iperf_time = self.Iperf_ComputeTime() - time.sleep(0.5) - - if udpIperf: - modified_options = self.Iperf_ComputeModifiedBW(idx, ue_num) - else: - modified_options = str(self.iperf_args) - modified_options = modified_options.replace('-R','') - time.sleep(0.5) - - self.command('rm -f iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - if (device_id == 'OAI-UE'): - iperf_status = self.command('iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + ' -B ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) - else: - if self.ADBCentralized: - iperf_status = self.command('stdbuf -o0 adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '" 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) - else: - iperf_status = self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '"\' 2>&1 > iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) - self.command('fromdos -o iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - self.command('cat iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - # TIMEOUT Case - if iperf_status < 0: - self.close() - message = 'iperf on UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT !' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) - return - clientStatus = self.Iperf_analyzeV2Output(lock, UE_IPAddress, device_id, statusQueue, modified_options) - self.close() - - # Kill iperf server on EPC side - if launchFromEpc: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('killall --signal SIGKILL iperf', self.EPCUserName, 5) - self.close() - else: - cmd = 'killall --signal SIGKILL iperf' - logging.debug(cmd) - subprocess.run(cmd, shell=True) - time.sleep(1) - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') - # in case of failure, retrieve server log - if (clientStatus == -1) or (clientStatus == -2): - if launchFromEpc: - time.sleep(1) - if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): - os.remove('iperf_server_' + self.testCase_id + '_' + device_id + '.log') - self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, self.EPCSourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') - self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) - # in case of OAI-UE - if (device_id == 'OAI-UE'): - self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_' + self.testCase_id + '_' + device_id + '.log', '.') - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') - - def Iperf_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue): - try: - # Single-UE profile -- iperf only on one UE - if self.iperf_profile == 'single-ue' and idx != 0: - return - useIperf3 = False - udpIperf = True - - self.ueIperfVersion = '2.0.5' - if (device_id != 'OAI-UE'): - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - # if by chance ADB server and EPC are on the same remote host, at least log collection will take care of it - self.command('if [ ! -d ' + self.EPCSourceCodePath + '/scripts ]; then mkdir -p ' + self.EPCSourceCodePath + '/scripts ; fi', '\$', 5) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - # Checking if iperf / iperf3 are installed - if self.ADBCentralized: - self.command('adb -s ' + device_id + ' shell "ls /data/local/tmp"', '\$', 5) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ls /data/local/tmp"\'', '\$', 60) - result = re.search('iperf3', str(self.ssh.before)) - if result is None: - result = re.search('iperf', str(self.ssh.before)) - if result is None: - message = 'Neither iperf nor iperf3 installed on UE!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.close() - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) - return - else: - if self.ADBCentralized: - self.command('adb -s ' + device_id + ' shell "/data/local/tmp/iperf --version"', '\$', 5) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf --version"\'', '\$', 60) - result = re.search('iperf version 2.0.5', str(self.ssh.before)) - if result is not None: - self.ueIperfVersion = '2.0.5' - result = re.search('iperf version 2.0.10', str(self.ssh.before)) - if result is not None: - self.ueIperfVersion = '2.0.10' - else: - useIperf3 = True - self.close() - else: - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('iperf --version', '\$', 5) - result = re.search('iperf version 2.0.5', str(self.ssh.before)) - if result is not None: - self.ueIperfVersion = '2.0.5' - result = re.search('iperf version 2.0.10', str(self.ssh.before)) - if result is not None: - self.ueIperfVersion = '2.0.10' - self.close() - # in case of iperf, UL has its own function - if (not useIperf3): - result = re.search('-R', str(self.iperf_args)) - if result is not None: - self.Iperf_UL_common(lock, UE_IPAddress, device_id, idx, ue_num, statusQueue) - return - - # Launch the IPERF server on the UE side for DL - if (device_id == 'OAI-UE'): - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) - self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - result = re.search('-u', str(self.iperf_args)) - if result is None: - self.command('echo $USER; nohup iperf -B ' + UE_IPAddress + ' -s -i 1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.UEUserName, 5) - udpIperf = False - else: - self.command('echo $USER; nohup iperf -B ' + UE_IPAddress + ' -u -s -i 1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.UEUserName, 5) - else: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - if self.ADBCentralized: - if (useIperf3): - self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/iperf3 -s &', '\$', 5) - else: - self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - result = re.search('-u', str(self.iperf_args)) - if result is None: - self.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) - udpIperf = False - else: - self.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) - else: - self.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - self.command('echo $USER; nohup ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" \' 2>&1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 60) - - time.sleep(0.5) - self.close() - - # Launch the IPERF client on the EPC side for DL (true for ltebox and old open-air-cn - # But for OAI-Rel14-CUPS, we launch from python executor - launchFromEpc = True - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - launchFromEpc = False - if launchFromEpc: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - iperf_time = self.Iperf_ComputeTime() - time.sleep(0.5) - - if udpIperf: - modified_options = self.Iperf_ComputeModifiedBW(idx, ue_num) - else: - modified_options = str(self.iperf_args) - time.sleep(0.5) - - if launchFromEpc: - self.command('rm -f iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - else: - if (os.path.isfile('iperf_' + self.testCase_id + '_' + device_id + '.log')): - os.remove('iperf_' + self.testCase_id + '_' + device_id + '.log') - if (useIperf3): - self.command('stdbuf -o0 iperf3 -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) - - clientStatus = 0 - self.Iperf_analyzeV3Output(lock, UE_IPAddress, device_id, statusQueue) - else: - if launchFromEpc: - iperf_status = self.command('stdbuf -o0 iperf -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) - else: - if self.ueIperfVersion == self.dummyIperfVersion: - prefix = '' - else: - prefix = '' - if self.ueIperfVersion == '2.0.5': - prefix = '/opt/iperf-2.0.5/bin/' - cmd = prefix + 'iperf -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 > iperf_' + self.testCase_id + '_' + device_id + '.log' - message = cmd + '\n' - logging.debug(cmd) - ret = subprocess.run(cmd, shell=True) - iperf_status = ret.returncode - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cat ' + self.EPCSourceCodePath + '/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - if iperf_status < 0: - if launchFromEpc: - self.close() - message = 'iperf on UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT !' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) - return - clientStatus = self.Iperf_analyzeV2Output(lock, UE_IPAddress, device_id, statusQueue, modified_options) - self.close() - - # Kill the IPERF server that runs in background - if (device_id == 'OAI-UE'): - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('killall iperf', '\$', 5) - else: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell ps | grep --color=never iperf | grep -v grep', '\$', 5) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ps" | grep --color=never iperf | grep -v grep\'', '\$', 60) - result = re.search('shell +(?P\d+)', str(self.ssh.before)) - if result is not None: - pid_iperf = result.group('pid') - if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell kill -KILL ' + pid_iperf, '\$', 5) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"\'', '\$', 60) - self.close() - # if the client report is absent, try to analyze the server log file - if (clientStatus == -1): - time.sleep(1) - if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): - os.remove('iperf_server_' + self.testCase_id + '_' + device_id + '.log') - if (device_id == 'OAI-UE'): - self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') - else: - self.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, self.EPCSourceCodePath + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') - self.command('fromdos -o iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) - - # in case of OAI UE: - if (device_id == 'OAI-UE'): - if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): - if not launchFromEpc: - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') - else: - self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', self.EPCSourceCodePath + '/scripts') - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def IperfNoS1(self): - if self.eNBIPAddress == '' or self.eNBUserName == '' or self.eNBPassword == '' or self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': - Usage() - sys.exit('Insufficient Parameter') - check_eNB = True - check_OAI_UE = True - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - self.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - server_on_enb = re.search('-R', str(self.iperf_args)) - if server_on_enb is not None: - iServerIPAddr = self.eNBIPAddress - iServerUser = self.eNBUserName - iServerPasswd = self.eNBPassword - iClientIPAddr = self.UEIPAddress - iClientUser = self.UEUserName - iClientPasswd = self.UEPassword - else: - iServerIPAddr = self.UEIPAddress - iServerUser = self.UEUserName - iServerPasswd = self.UEPassword - iClientIPAddr = self.eNBIPAddress - iClientUser = self.eNBUserName - iClientPasswd = self.eNBPassword - # Starting the iperf server - self.open(iServerIPAddr, iServerUser, iServerPasswd) - # args SHALL be "-c client -u any" - # -c 10.0.1.2 -u -b 1M -t 30 -i 1 -fm -B 10.0.1.1 - # -B 10.0.1.1 -u -s -i 1 -fm - server_options = re.sub('-u.*$', '-u -s -i 1 -fm', str(self.iperf_args)) - server_options = server_options.replace('-c','-B') - self.command('rm -f /tmp/tmp_iperf_server_' + self.testCase_id + '.log', '\$', 5) - self.command('echo $USER; nohup iperf ' + server_options + ' > /tmp/tmp_iperf_server_' + self.testCase_id + '.log 2>&1 &', iServerUser, 5) - time.sleep(0.5) - self.close() - - # Starting the iperf client - modified_options = self.Iperf_ComputeModifiedBW(0, 1) - modified_options = modified_options.replace('-R','') - iperf_time = self.Iperf_ComputeTime() - self.open(iClientIPAddr, iClientUser, iClientPasswd) - self.command('rm -f /tmp/tmp_iperf_' + self.testCase_id + '.log', '\$', 5) - iperf_status = self.command('stdbuf -o0 iperf ' + modified_options + ' 2>&1 | stdbuf -o0 tee /tmp/tmp_iperf_' + self.testCase_id + '.log', '\$', int(iperf_time)*5.0) - status_queue = SimpleQueue() - lock = Lock() - if iperf_status < 0: - message = 'iperf on OAI UE crashed due to TIMEOUT !' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - clientStatus = -2 - else: - clientStatus = self.Iperf_analyzeV2Output(lock, '10.0.1.2', 'OAI-UE', status_queue, modified_options) - self.close() - - # Stopping the iperf server - self.open(iServerIPAddr, iServerUser, iServerPasswd) - self.command('killall --signal SIGKILL iperf', '\$', 5) - time.sleep(0.5) - self.close() - if (clientStatus == -1): - if (os.path.isfile('iperf_server_' + self.testCase_id + '.log')): - os.remove('iperf_server_' + self.testCase_id + '.log') - self.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log') - self.Iperf_analyzeV2Server(lock, '10.0.1.2', 'OAI-UE', status_queue, modified_options) - - # copying on the EPC server for logCollection - copyin_res = self.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log') - if (copyin_res == 0): - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_server_' + self.testCase_id + '_OAI-UE.log', self.EPCSourceCodePath + '/scripts') - copyin_res = self.copyin(iClientIPAddr, iClientUser, iClientPasswd, '/tmp/tmp_iperf_' + self.testCase_id + '.log', 'iperf_' + self.testCase_id + '_OAI-UE.log') - if (copyin_res == 0): - self.copyout(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, 'iperf_' + self.testCase_id + '_OAI-UE.log', self.EPCSourceCodePath + '/scripts') - iperf_noperf = False - if status_queue.empty(): - iperf_status = False - else: - iperf_status = True - html_queue = SimpleQueue() - while (not status_queue.empty()): - count = status_queue.get() - if (count < 0): - iperf_status = False - if (count > 0): - iperf_noperf = True - device_id = status_queue.get() - ip_addr = status_queue.get() - message = status_queue.get() - html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' - html_queue.put(html_cell) - if (iperf_noperf and iperf_status): - self.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) - elif (iperf_status): - self.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) - else: - self.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) - self.AutoTerminateUEandeNB() - - def Iperf(self): - result = re.search('noS1', str(self.Initialize_eNB_args)) - if result is not None: - self.IperfNoS1() - return - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - check_eNB = True - if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): - check_OAI_UE = True - else: - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - self.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - ueIpStatus = self.GetAllUEIPAddresses() - if (ueIpStatus < 0): - self.CreateHtmlTestRow(self.iperf_args, 'KO', UE_IP_ADDRESS_ISSUE) - self.AutoTerminateUEandeNB() - return - - self.dummyIperfVersion = '2.0.10' - #cmd = 'iperf --version' - #logging.debug(cmd + '\n') - #iperfStdout = subprocess.check_output(cmd, shell=True, universal_newlines=True) - #result = re.search('iperf version 2.0.5', str(iperfStdout.strip())) - #if result is not None: - # dummyIperfVersion = '2.0.5' - #result = re.search('iperf version 2.0.10', str(iperfStdout.strip())) - #if result is not None: - # dummyIperfVersion = '2.0.10' - - multi_jobs = [] - i = 0 - ue_num = len(self.UEIPAddresses) - lock = Lock() - status_queue = SimpleQueue() - for UE_IPAddress in self.UEIPAddresses: - device_id = self.UEDevices[i] - p = Process(target = SSH.Iperf_common, args = (lock,UE_IPAddress,device_id,i,ue_num,status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - i = i + 1 - for job in multi_jobs: - job.join() - - if (status_queue.empty()): - self.CreateHtmlTestRow(self.iperf_args, 'KO', ALL_PROCESSES_OK) - self.AutoTerminateUEandeNB() - else: - iperf_status = True - iperf_noperf = False - html_queue = SimpleQueue() - while (not status_queue.empty()): - count = status_queue.get() - if (count < 0): - iperf_status = False - if (count > 0): - iperf_noperf = True - device_id = status_queue.get() - ip_addr = status_queue.get() - message = status_queue.get() - html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' - html_queue.put(html_cell) - if (iperf_noperf and iperf_status): - self.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) - elif (iperf_status): - self.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) - else: - self.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) - self.AutoTerminateUEandeNB() - - def CheckProcessExist(self, check_eNB, check_OAI_UE): - multi_jobs = [] - status_queue = SimpleQueue() - # in noS1 config, no need to check status from EPC - result = re.search('noS1', str(self.Initialize_eNB_args)) - if result is None: - p = Process(target = SSH.CheckHSSProcess, args = (status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - p = Process(target = SSH.CheckMMEProcess, args = (status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - p = Process(target = SSH.CheckSPGWProcess, args = (status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - else: - if (check_eNB == False) and (check_OAI_UE == False): - return 0 - if check_eNB: - p = Process(target = SSH.CheckeNBProcess, args = (status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - if check_OAI_UE: - p = Process(target = SSH.CheckOAIUEProcess, args = (status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - for job in multi_jobs: - job.join() - - if (status_queue.empty()): - return -15 - else: - result = 0 - while (not status_queue.empty()): - status = status_queue.get() - if (status < 0): - result = status - if result == ENB_PROCESS_FAILED: - fileCheck = re.search('enb_', str(self.eNBLogFiles[0])) - if fileCheck is not None: - self.copyin(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.eNBSourceCodePath + '/cmake_targets/' + self.eNBLogFiles[0], '.') - logStatus = self.AnalyzeLogFile_eNB(self.eNBLogFiles[0]) - if logStatus < 0: - result = logStatus - self.eNBLogFiles[0] = '' - if self.flexranCtrlInstalled and self.flexranCtrlStarted: - self.TerminateFlexranCtrl() - return result - - def CheckOAIUEProcessExist(self, initialize_OAI_UE_flag): - multi_jobs = [] - status_queue = SimpleQueue() - if initialize_OAI_UE_flag == False: - p = Process(target = SSH.CheckOAIUEProcess, args = (status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - for job in multi_jobs: - job.join() - - if (status_queue.empty()): - return -15 - else: - result = 0 - while (not status_queue.empty()): - status = status_queue.get() - if (status < 0): - result = status - if result == OAI_UE_PROCESS_FAILED: - fileCheck = re.search('ue_', str(self.UELogFile)) - if fileCheck is not None: - self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.') - logStatus = self.AnalyzeLogFile_UE(self.UELogFile) - if logStatus < 0: - result = logStatus - return result - - def CheckOAIUEProcess(self, status_queue): - try: - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('lte-uesoftmodem', str(self.ssh.before)) - if result is None: - logging.debug('\u001B[1;37;41m OAI UE Process Not Found! \u001B[0m') - status_queue.put(OAI_UE_PROCESS_FAILED) - else: - status_queue.put(OAI_UE_PROCESS_OK) - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def CheckeNBProcess(self, status_queue): - try: - self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) - self.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('lte-softmodem', str(self.ssh.before)) - if result is None: - logging.debug('\u001B[1;37;41m eNB Process Not Found! \u001B[0m') - status_queue.put(ENB_PROCESS_FAILED) - else: - status_queue.put(ENB_PROCESS_OK) - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def CheckHSSProcess(self, status_queue): - try: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('stdbuf -o0 ps -aux | grep --color=never hss | grep -v grep', '\$', 5) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - result = re.search('oai_hss -j', str(self.ssh.before)) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - result = re.search('hss_sim s6as diam_hss', str(self.ssh.before)) - else: - logging.error('This should not happen!') - if result is None: - logging.debug('\u001B[1;37;41m HSS Process Not Found! \u001B[0m') - status_queue.put(HSS_PROCESS_FAILED) - else: - status_queue.put(HSS_PROCESS_OK) - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def CheckMMEProcess(self, status_queue): - try: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('stdbuf -o0 ps -aux | grep --color=never mme | grep -v grep', '\$', 5) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - result = re.search('mme -c', str(self.ssh.before)) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - result = re.search('mme', str(self.ssh.before)) - else: - logging.error('This should not happen!') - if result is None: - logging.debug('\u001B[1;37;41m MME Process Not Found! \u001B[0m') - status_queue.put(MME_PROCESS_FAILED) - else: - status_queue.put(MME_PROCESS_OK) - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def CheckSPGWProcess(self, status_queue): - try: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('stdbuf -o0 ps -aux | grep --color=never spgw | grep -v grep', '\$', 5) - result = re.search('spgwu -c ', str(self.ssh.before)) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - self.command('stdbuf -o0 ps -aux | grep --color=never spgw | grep -v grep', '\$', 5) - result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('stdbuf -o0 ps -aux | grep --color=never xGw | grep -v grep', '\$', 5) - result = re.search('xGw', str(self.ssh.before)) - else: - logging.error('This should not happen!') - if result is None: - logging.debug('\u001B[1;37;41m SPGW Process Not Found! \u001B[0m') - status_queue.put(SPGW_PROCESS_FAILED) - else: - status_queue.put(SPGW_PROCESS_OK) - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def AnalyzeLogFile_eNB(self, eNBlogFile): - if (not os.path.isfile('./' + eNBlogFile)): - return -1 - enb_log_file = open('./' + eNBlogFile, 'r') - exitSignalReceived = False - foundAssertion = False - msgAssertion = '' - msgLine = 0 - foundSegFault = False - foundRealTimeIssue = False - rrcSetupComplete = 0 - rrcReleaseRequest = 0 - rrcReconfigRequest = 0 - rrcReconfigComplete = 0 - rrcReestablishRequest = 0 - rrcReestablishComplete = 0 - rrcReestablishReject = 0 - rlcDiscardBuffer = 0 - rachCanceledProcedure = 0 - uciStatMsgCount = 0 - pdcpFailure = 0 - ulschFailure = 0 - cdrxActivationMessageCount = 0 - dropNotEnoughRBs = 0 - self.htmleNBFailureMsg = '' - isRRU = False - isSlave = False - slaveReceivesFrameResyncCmd = False - X2HO_state = X2_HO_REQ_STATE__IDLE - X2HO_inNbProcedures = 0 - X2HO_outNbProcedures = 0 - for line in enb_log_file.readlines(): - if X2HO_state == X2_HO_REQ_STATE__IDLE: - result = re.search('target eNB Receives X2 HO Req X2AP_HANDOVER_REQ', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__TARGET_RECEIVES_REQ - result = re.search('source eNB receives the X2 HO ACK X2AP_HANDOVER_REQ_ACK', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK - if X2HO_state == X2_HO_REQ_STATE__TARGET_RECEIVES_REQ: - result = re.search('Received LTE_RRCConnectionReconfigurationComplete from UE', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE - if X2HO_state == X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE: - result = re.search('issue rrc_eNB_send_PATH_SWITCH_REQ', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ - if X2HO_state == X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ: - result = re.search('received path switch ack S1AP_PATH_SWITCH_REQ_ACK', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__IDLE - X2HO_inNbProcedures += 1 - if X2HO_state == X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK: - result = re.search('source eNB receives the X2 UE CONTEXT RELEASE X2AP_UE_CONTEXT_RELEASE', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__IDLE - X2HO_outNbProcedures += 1 - - if self.eNBOptions[int(self.eNB_instance)] != '': - res1 = re.search('max_rxgain (?P[0-9]+)', self.eNBOptions[int(self.eNB_instance)]) - res2 = re.search('max_rxgain (?P[0-9]+)', str(line)) - if res1 is not None and res2 is not None: - requested_option = int(res1.group('requested_option')) - applied_option = int(res2.group('applied_option')) - if requested_option == applied_option: - self.htmleNBFailureMsg += ' Command line option(s) correctly applied ' + self.eNBOptions[int(self.eNB_instance)] + '\n\n' - else: - self.htmleNBFailureMsg += ' Command line option(s) NOT applied ' + self.eNBOptions[int(self.eNB_instance)] + '\n\n' - result = re.search('Exiting OAI softmodem', str(line)) - if result is not None: - exitSignalReceived = True - result = re.search('[Ss]egmentation [Ff]ault', str(line)) - 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)) - if result is not None and not exitSignalReceived: - foundAssertion = True - result = re.search('LLL', str(line)) - if result is not None and not exitSignalReceived: - foundRealTimeIssue = True - if foundAssertion and (msgLine < 3): - msgLine += 1 - msgAssertion += str(line) - result = re.search('Setting function for RU', str(line)) - if result is not None: - isRRU = True - if isRRU: - result = re.search('RU 0 is_slave=yes', str(line)) - if result is not None: - isSlave = True - if isSlave: - result = re.search('Received RRU_frame_resynch command', str(line)) - if result is not None: - slaveReceivesFrameResyncCmd = True - result = re.search('LTE_RRCConnectionSetupComplete from UE', str(line)) - if result is not None: - rrcSetupComplete += 1 - result = re.search('Generate LTE_RRCConnectionRelease|Generate RRCConnectionRelease', str(line)) - if result is not None: - rrcReleaseRequest += 1 - result = re.search('Generate LTE_RRCConnectionReconfiguration', str(line)) - if result is not None: - rrcReconfigRequest += 1 - result = re.search('LTE_RRCConnectionReconfigurationComplete from UE rnti', str(line)) - if result is not None: - rrcReconfigComplete += 1 - result = re.search('LTE_RRCConnectionReestablishmentRequest', str(line)) - if result is not None: - rrcReestablishRequest += 1 - result = re.search('LTE_RRCConnectionReestablishmentComplete', str(line)) - if result is not None: - rrcReestablishComplete += 1 - result = re.search('LTE_RRCConnectionReestablishmentReject', str(line)) - if result is not None: - rrcReestablishReject += 1 - result = re.search('CDRX configuration activated after RRC Connection', str(line)) - if result is not None: - cdrxActivationMessageCount += 1 - result = re.search('uci->stat', str(line)) - if result is not None: - uciStatMsgCount += 1 - result = re.search('PDCP.*Out of Resources.*reason', str(line)) - if result is not None: - pdcpFailure += 1 - result = re.search('ULSCH in error in round', str(line)) - if result is not None: - ulschFailure += 1 - result = re.search('BAD all_segments_received', str(line)) - if result is not None: - rlcDiscardBuffer += 1 - 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: - statMsg = 'eNB showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmleNBFailureMsg += statMsg + '\n' - if pdcpFailure > 0: - statMsg = 'eNB showed ' + str(pdcpFailure) + ' "PDCP Out of Resources" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmleNBFailureMsg += statMsg + '\n' - if ulschFailure > 0: - 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') - self.htmleNBFailureMsg += rrcMsg + '\n' - if rrcReleaseRequest > 0: - rrcMsg = 'eNB requested ' + str(rrcReleaseRequest) + ' RRC Connection Release(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if rrcReconfigRequest > 0 or rrcReconfigComplete > 0: - rrcMsg = 'eNB requested ' + str(rrcReconfigRequest) + ' RRC Connection Reconfiguration(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - rrcMsg = ' -- ' + str(rrcReconfigComplete) + ' were completed' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if rrcReestablishRequest > 0 or rrcReestablishComplete > 0 or rrcReestablishReject > 0: - rrcMsg = 'eNB requested ' + str(rrcReestablishRequest) + ' RRC Connection Reestablishment(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - rrcMsg = ' -- ' + str(rrcReestablishComplete) + ' were completed' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - rrcMsg = ' -- ' + str(rrcReestablishReject) + ' were rejected' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if X2HO_inNbProcedures > 0: - rrcMsg = 'eNB completed ' + str(X2HO_inNbProcedures) + ' X2 Handover Connection procedure(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if X2HO_outNbProcedures > 0: - rrcMsg = 'eNB completed ' + str(X2HO_outNbProcedures) + ' X2 Handover Release procedure(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if self.eNBOptions[int(self.eNB_instance)] != '': - res1 = re.search('drx_Config_present prSetup', self.eNBOptions[int(self.eNB_instance)]) - if res1 is not None: - if cdrxActivationMessageCount > 0: - rrcMsg = 'eNB activated the CDRX Configuration for ' + str(cdrxActivationMessageCount) + ' time(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - else: - rrcMsg = 'eNB did NOT ACTIVATE the CDRX Configuration' - logging.debug('\u001B[1;37;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if rachCanceledProcedure > 0: - rachMsg = 'eNB cancelled ' + str(rachCanceledProcedure) + ' RA procedure(s)' - logging.debug('\u001B[1;30;43m ' + rachMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rachMsg + '\n' - if isRRU: - if isSlave: - if slaveReceivesFrameResyncCmd: - rruMsg = 'Slave RRU received the RRU_frame_resynch command from RAU' - logging.debug('\u001B[1;30;43m ' + rruMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rruMsg + '\n' - else: - rruMsg = 'Slave RRU DID NOT receive the RRU_frame_resynch command from RAU' - logging.debug('\u001B[1;37;41m ' + rruMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rruMsg + '\n' - self.prematureExit = True - return ENB_PROCESS_SLAVE_RRU_NOT_SYNCED - if foundSegFault: - logging.debug('\u001B[1;37;41m eNB ended with a Segmentation Fault! \u001B[0m') - return ENB_PROCESS_SEG_FAULT - if foundAssertion: - logging.debug('\u001B[1;37;41m eNB ended with an assertion! \u001B[0m') - self.htmleNBFailureMsg += msgAssertion - return ENB_PROCESS_ASSERTION - if foundRealTimeIssue: - logging.debug('\u001B[1;37;41m eNB faced real time issues! \u001B[0m') - self.htmleNBFailureMsg += 'eNB faced real time issues!\n' - #return ENB_PROCESS_REALTIME_ISSUE - if rlcDiscardBuffer > 0: - rlcMsg = 'eNB RLC discarded ' + str(rlcDiscardBuffer) + ' buffer(s)' - logging.debug('\u001B[1;37;41m ' + rlcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rlcMsg + '\n' - return ENB_PROCESS_REALTIME_ISSUE - return 0 - - def AnalyzeLogFile_UE(self, UElogFile): - if (not os.path.isfile('./' + UElogFile)): - return -1 - ue_log_file = open('./' + UElogFile, 'r') - exitSignalReceived = False - foundAssertion = False - msgAssertion = '' - msgLine = 0 - foundSegFault = False - foundRealTimeIssue = False - uciStatMsgCount = 0 - pdcpDataReqFailedCount = 0 - badDciCount = 0 - rrcConnectionRecfgComplete = 0 - no_cell_sync_found = False - mib_found = False - frequency_found = False - plmn_found = False - self.htmlUEFailureMsg = '' - for line in ue_log_file.readlines(): - result = re.search('Exiting OAI softmodem', str(line)) - if result is not None: - exitSignalReceived = True - result = re.search('System error|[Ss]egmentation [Ff]ault|======= Backtrace: =========|======= Memory map: ========', str(line)) - 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)) - if result is not None and not exitSignalReceived: - foundAssertion = True - result = re.search('LLL', str(line)) - if result is not None and not exitSignalReceived: - foundRealTimeIssue = True - if foundAssertion and (msgLine < 3): - msgLine += 1 - msgAssertion += str(line) - result = re.search('uci->stat', str(line)) - if result is not None and not exitSignalReceived: - uciStatMsgCount += 1 - result = re.search('PDCP data request failed', str(line)) - if result is not None and not exitSignalReceived: - pdcpDataReqFailedCount += 1 - result = re.search('bad DCI 1A', str(line)) - if result is not None and not exitSignalReceived: - badDciCount += 1 - result = re.search('Generating RRCConnectionReconfigurationComplete', str(line)) - if result is not None: - rrcConnectionRecfgComplete += 1 - # No cell synchronization found, abandoning - result = re.search('No cell synchronization found, abandoning', str(line)) - if result is not None: - no_cell_sync_found = True - result = re.search("MIB Information => ([a-zA-Z]{1,10}), ([a-zA-Z]{1,10}), NidCell (?P\d{1,3}), N_RB_DL (?P\d{1,3}), PHICH DURATION (?P\d), PHICH RESOURCE (?P.{1,4}), TX_ANT (?P\d)", str(line)) - if result is not None and (not mib_found): - try: - mibMsg = "MIB Information: " + result.group(1) + ', ' + result.group(2) - self.htmlUEFailureMsg += mibMsg + '\n' - logging.debug('\033[94m' + mibMsg + '\033[0m') - mibMsg = " nidcell = " + result.group('nidcell') - self.htmlUEFailureMsg += mibMsg - logging.debug('\033[94m' + mibMsg + '\033[0m') - mibMsg = " n_rb_dl = " + result.group('n_rb_dl') - self.htmlUEFailureMsg += mibMsg + '\n' - logging.debug('\033[94m' + mibMsg + '\033[0m') - mibMsg = " phich_duration = " + result.group('phich_duration') - self.htmlUEFailureMsg += mibMsg - logging.debug('\033[94m' + mibMsg + '\033[0m') - mibMsg = " phich_resource = " + result.group('phich_resource') - self.htmlUEFailureMsg += mibMsg + '\n' - logging.debug('\033[94m' + mibMsg + '\033[0m') - mibMsg = " tx_ant = " + result.group('tx_ant') - self.htmlUEFailureMsg += mibMsg + '\n' - logging.debug('\033[94m' + mibMsg + '\033[0m') - mib_found = True - except Exception as e: - logging.error('\033[91m' + "MIB marker was not found" + '\033[0m') - result = re.search("Measured Carrier Frequency (?P\d{1,15}) Hz", str(line)) - if result is not None and (not frequency_found): - try: - mibMsg = "Measured Carrier Frequency = " + result.group('measured_carrier_frequency') + ' Hz' - self.htmlUEFailureMsg += mibMsg + '\n' - logging.debug('\033[94m' + mibMsg + '\033[0m') - frequency_found = True - except Exception as e: - logging.error('\033[91m' + "Measured Carrier Frequency not found" + '\033[0m') - result = re.search("PLMN MCC (?P\d{1,3}), MNC (?P\d{1,3}), TAC", str(line)) - if result is not None and (not plmn_found): - try: - mibMsg = 'PLMN MCC = ' + result.group('mcc') + ' MNC = ' + result.group('mnc') - self.htmlUEFailureMsg += mibMsg + '\n' - logging.debug('\033[94m' + mibMsg + '\033[0m') - plmn_found = True - except Exception as e: - logging.error('\033[91m' + "PLMN not found" + '\033[0m') - result = re.search("Found (?P[\w,\s]{1,15}) \(name from internal table\)", str(line)) - if result is not None: - try: - mibMsg = "The operator is: " + result.group('operator') - self.htmlUEFailureMsg += mibMsg + '\n' - logging.debug('\033[94m' + mibMsg + '\033[0m') - except Exception as e: - logging.error('\033[91m' + "Operator name not found" + '\033[0m') - result = re.search("SIB5 InterFreqCarrierFreq element (.{1,4})/(.{1,4})", str(line)) - if result is not None: - try: - mibMsg = "SIB5 InterFreqCarrierFreq element " + result.group(1) + '/' + result.group(2) - self.htmlUEFailureMsg += mibMsg + ' -> ' - logging.debug('\033[94m' + mibMsg + '\033[0m') - except Exception as e: - logging.error('\033[91m' + "SIB5 InterFreqCarrierFreq element not found" + '\033[0m') - result = re.search("DL Carrier Frequency/ARFCN : (?P\d{1,15}/\d{1,4})", str(line)) - if result is not None: - try: - freq = result.group('carrier_frequency') - new_freq = re.sub('/[0-9]+','',freq) - float_freq = float(new_freq) / 1000000 - self.htmlUEFailureMsg += 'DL Freq: ' + ('%.1f' % float_freq) + ' MHz' - logging.debug('\033[94m' + " DL Carrier Frequency is: " + freq + '\033[0m') - except Exception as e: - logging.error('\033[91m' + " DL Carrier Frequency not found" + '\033[0m') - result = re.search("AllowedMeasBandwidth : (?P\d{1,7})", str(line)) - if result is not None: - try: - prb = result.group('allowed_bandwidth') - self.htmlUEFailureMsg += ' -- PRB: ' + prb + '\n' - logging.debug('\033[94m' + " AllowedMeasBandwidth: " + prb + '\033[0m') - except Exception as e: - logging.error('\033[91m' + " AllowedMeasBandwidth not found" + '\033[0m') - ue_log_file.close() - if rrcConnectionRecfgComplete > 0: - statMsg = 'UE connected to eNB (' + str(rrcConnectionRecfgComplete) + ' RRCConnectionReconfigurationComplete message(s) generated)' - logging.debug('\033[94m' + statMsg + '\033[0m') - self.htmlUEFailureMsg += statMsg + '\n' - if uciStatMsgCount > 0: - statMsg = 'UE showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' - if pdcpDataReqFailedCount > 0: - statMsg = 'UE showed ' + str(pdcpDataReqFailedCount) + ' "PDCP data request failed" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' - if badDciCount > 0: - statMsg = 'UE showed ' + str(badDciCount) + ' "bad DCI 1A" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' - if foundSegFault: - logging.debug('\u001B[1;37;41m UE ended with a Segmentation Fault! \u001B[0m') - return ENB_PROCESS_SEG_FAULT - if foundAssertion: - logging.debug('\u001B[1;30;43m UE showed an assertion! \u001B[0m') - self.htmlUEFailureMsg += 'UE showed an assertion!\n' - if not mib_found or not frequency_found: - return OAI_UE_PROCESS_ASSERTION - if foundRealTimeIssue: - logging.debug('\u001B[1;37;41m UE faced real time issues! \u001B[0m') - self.htmlUEFailureMsg += 'UE faced real time issues!\n' - #return ENB_PROCESS_REALTIME_ISSUE - if no_cell_sync_found and not mib_found: - logging.debug('\u001B[1;37;41m UE could not synchronize ! \u001B[0m') - self.htmlUEFailureMsg += 'UE could not synchronize!\n' - return OAI_UE_PROCESS_COULD_NOT_SYNC - return 0 - - def TerminateeNB(self): - if self.eNB_serverId == '0': - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - lSourcePath = self.eNBSourceCodePath - elif self.eNB_serverId == '1': - lIpAddr = self.eNB1IPAddress - lUserName = self.eNB1UserName - lPassWord = self.eNB1Password - lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId == '2': - lIpAddr = self.eNB2IPAddress - lUserName = self.eNB2UserName - lPassWord = self.eNB2Password - lSourcePath = self.eNB2SourceCodePath - if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(lIpAddr, lUserName, lPassWord) - self.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) - self.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('lte-softmodem', str(self.ssh.before)) - if result is not None: - self.command('echo ' + lPassWord + ' | sudo -S daemon --name=enb' + str(self.eNB_instance) + '_daemon --stop', '\$', 5) - self.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGINT lte-softmodem || true', '\$', 5) - time.sleep(10) - self.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('lte-softmodem', str(self.ssh.before)) - if result is not None: - self.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGKILL lte-softmodem || true', '\$', 5) - time.sleep(5) - self.command('rm -f my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - self.close() - # If tracer options is on, stopping tshark on EPC side - result = re.search('T_stdout', str(self.Initialize_eNB_args)) - if result is not None: - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - logging.debug('\u001B[1m Stopping tshark \u001B[0m') - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) - time.sleep(1) - if self.EPC_PcapFileName != '': - self.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 /tmp/' + self.EPC_PcapFileName, '\$', 5) - self.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + self.EPC_PcapFileName, '.') - self.copyout(lIpAddr, lUserName, lPassWord, self.EPC_PcapFileName, lSourcePath + '/cmake_targets/.') - self.close() - logging.debug('\u001B[1m Replaying RAW record file\u001B[0m') - self.open(lIpAddr, lUserName, lPassWord) - self.command('cd ' + lSourcePath + '/common/utils/T/tracer/', '\$', 5) - enbLogFile = self.eNBLogFiles[int(self.eNB_instance)] - raw_record_file = enbLogFile.replace('.log', '_record.raw') - replay_log_file = enbLogFile.replace('.log', '_replay.log') - extracted_txt_file = enbLogFile.replace('.log', '_extracted_messages.txt') - extracted_log_file = enbLogFile.replace('.log', '_extracted_messages.log') - self.command('./extract_config -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + extracted_txt_file, '\$', 5) - self.command('echo $USER; nohup ./replay -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + replay_log_file + ' 2>&1 &', lUserName, 5) - self.command('./textlog -d ' + lSourcePath + '/cmake_targets/' + extracted_txt_file + ' -no-gui -ON -full > ' + lSourcePath + '/cmake_targets/' + extracted_log_file, '\$', 5) - self.close() - self.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + extracted_log_file, '.') - logging.debug('\u001B[1m Analyzing eNB replay logfile \u001B[0m') - logStatus = self.AnalyzeLogFile_eNB(extracted_log_file) - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - self.eNBLogFiles[int(self.eNB_instance)] = '' - else: - analyzeFile = False - if self.eNBLogFiles[int(self.eNB_instance)] != '': - analyzeFile = True - fileToAnalyze = self.eNBLogFiles[int(self.eNB_instance)] - self.eNBLogFiles[int(self.eNB_instance)] = '' - if analyzeFile: - copyin_res = self.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + fileToAnalyze, '.') - if (copyin_res == -1): - logging.debug('\u001B[1;37;41m Could not copy eNB logfile to analyze it! \u001B[0m') - self.htmleNBFailureMsg = 'Could not copy eNB logfile to analyze it!' - self.CreateHtmlTestRow('N/A', 'KO', ENB_PROCESS_NOLOGFILE_TO_ANALYZE) - return - if self.eNB_serverId != '0': - self.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './' + fileToAnalyze, self.eNBSourceCodePath + '/cmake_targets/') - logging.debug('\u001B[1m Analyzing eNB logfile \u001B[0m ' + fileToAnalyze) - logStatus = self.AnalyzeLogFile_eNB(fileToAnalyze) - if (logStatus < 0): - self.CreateHtmlTestRow('N/A', 'KO', logStatus) - self.preamtureExit = True - return - else: - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - else: - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def TerminateHSS(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT oai_hss || true', '\$', 5) - time.sleep(2) - self.command('stdbuf -o0 ps -aux | grep hss | grep -v grep', '\$', 5) - result = re.search('oai_hss -j', str(self.ssh.before)) - if result is not None: - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL oai_hss || true', '\$', 5) - self.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-hss.sh', '\$', 5) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_hss oai_hss || true', '\$', 5) - time.sleep(2) - self.command('stdbuf -o0 ps -aux | grep hss | grep -v grep', '\$', 5) - result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) - if result is not None: - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_hss oai_hss || true', '\$', 5) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('cd scripts', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S daemon --name=simulated_hss --stop', '\$', 5) - time.sleep(1) - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL hss_sim', '\$', 5) - else: - logging.error('This should not happen!') - self.close() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def TerminateMME(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_mme mme || true', '\$', 5) - time.sleep(2) - self.command('stdbuf -o0 ps -aux | grep mme | grep -v grep', '\$', 5) - result = re.search('mme -c', str(self.ssh.before)) - if result is not None: - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_mme mme || true', '\$', 5) - self.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-mme.sh', '\$', 5) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cd /opt/ltebox/tools', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S ./stop_mme', '\$', 5) - else: - logging.error('This should not happen!') - self.close() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def TerminateSPGW(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT spgwc spgwu || true', '\$', 5) - time.sleep(2) - self.command('stdbuf -o0 ps -aux | grep spgw | grep -v grep', '\$', 5) - result = re.search('spgwc -c |spgwu -c ', str(self.ssh.before)) - if result is not None: - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL spgwc spgwu || true', '\$', 5) - self.command('rm -f ' + self.EPCSourceCodePath + '/scripts/my-spgw*.sh', '\$', 5) - self.command('stdbuf -o0 ps -aux | grep tshark | grep -v grep', '\$', 5) - result = re.search('-w ', str(self.ssh.before)) - if result is not None: - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT tshark || true', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 ' + self.EPCSourceCodePath + '/scripts/*.pcap', '\$', 5) - elif re.match('OAI', self.EPCType, re.IGNORECASE): - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGINT run_spgw spgw || true', '\$', 5) - time.sleep(2) - self.command('stdbuf -o0 ps -aux | grep spgw | grep -v grep', '\$', 5) - result = re.search('\/bin\/bash .\/run_', str(self.ssh.before)) - if result is not None: - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL run_spgw spgw || true', '\$', 5) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cd /opt/ltebox/tools', '\$', 5) - self.command('echo ' + self.EPCPassword + ' | sudo -S ./stop_xGw', '\$', 5) - else: - logging.error('This should not happen!') - self.close() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def TerminateFlexranCtrl(self): - if self.flexranCtrlInstalled == False or self.flexranCtrlStarted == False: - return - if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '': - Usage() - sys.exit('Insufficient Parameter') - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('echo ' + self.EPCPassword + ' | sudo -S daemon --name=flexran_rtc_daemon --stop', '\$', 5) - time.sleep(1) - self.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL rt_controller', '\$', 5) - time.sleep(1) - self.close() - self.flexranCtrlStarted = False - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def TerminateUE_common(self, device_id, idx): - try: - self.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - # back in airplane mode on (ie radio off) - if self.ADBCentralized: - if device_id == '84B7N16418004022': - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) - else: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) - logging.debug('\u001B[1mUE (' + device_id + ') Detach Completed\u001B[0m') - - if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "ps | grep --color=never iperf | grep -v grep"', '\$', 5) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ps | grep --color=never iperf | grep -v grep"\'', '\$', 60) - result = re.search('shell +(?P\d+)', str(self.ssh.before)) - if result is not None: - pid_iperf = result.group('pid') - if self.ADBCentralized: - self.command('stdbuf -o0 adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"', '\$', 5) - else: - self.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"\'', '\$', 60) - self.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def TerminateUE(self): - terminate_ue_flag = True - self.GetAllUEDevices(terminate_ue_flag) - multi_jobs = [] - i = 0 - for device_id in self.UEDevices: - p = Process(target= SSH.TerminateUE_common, args = (device_id,i,)) - p.daemon = True - p.start() - multi_jobs.append(p) - i += 1 - for job in multi_jobs: - job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def TerminateOAIUE(self): - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) - self.command('ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('lte-uesoftmodem', str(self.ssh.before)) - if result is not None: - self.command('echo ' + self.UEPassword + ' | sudo -S daemon --name=ue' + str(self.UE_instance) + '_daemon --stop', '\$', 5) - self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGINT lte-uesoftmodem || true', '\$', 5) - time.sleep(10) - self.command('ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('lte-uesoftmodem', str(self.ssh.before)) - if result is not None: - self.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGKILL lte-uesoftmodem || true', '\$', 5) - time.sleep(5) - self.command('rm -f my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) - self.close() - result = re.search('ue_', str(self.UELogFile)) - if result is not None: - copyin_res = self.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.') - if (copyin_res == -1): - logging.debug('\u001B[1;37;41m Could not copy UE logfile to analyze it! \u001B[0m') - self.htmlUEFailureMsg = 'Could not copy UE logfile to analyze it!' - self.CreateHtmlTestRow('N/A', 'KO', OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE, 'UE') - self.UELogFile = '' - return - logging.debug('\u001B[1m Analyzing UE logfile \u001B[0m') - logStatus = self.AnalyzeLogFile_UE(self.UELogFile) - result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) - if result is not None: - ueAction = 'Sniffing' - else: - ueAction = 'Connection' - if (logStatus < 0): - logging.debug('\u001B[1m' + ueAction + ' Failed \u001B[0m') - self.htmlUEFailureMsg = '' + ueAction + ' Failed\n' + self.htmlUEFailureMsg - self.CreateHtmlTestRow('N/A', 'KO', logStatus, 'UE') - # In case of sniffing on commercial eNBs we have random results - # Not an error then - if (logStatus != OAI_UE_PROCESS_COULD_NOT_SYNC) or (ueAction != 'Sniffing'): - self.Initialize_OAI_UE_args = '' - self.AutoTerminateUEandeNB() - else: - logging.debug('\u001B[1m' + ueAction + ' Completed \u001B[0m') - self.htmlUEFailureMsg = '' + ueAction + ' Completed\n' + self.htmlUEFailureMsg - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - self.UELogFile = '' - else: - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def AutoTerminateUEandeNB(self): - if (self.ADBIPAddress != 'none'): - self.testCase_id = 'AUTO-KILL-UE' - self.desc = 'Automatic Termination of UE' - self.ShowTestID() - self.TerminateUE() - if (self.Initialize_OAI_UE_args != ''): - self.testCase_id = 'AUTO-KILL-UE' - self.desc = 'Automatic Termination of UE' - self.ShowTestID() - self.TerminateOAIUE() - if (self.Initialize_eNB_args != ''): - self.testCase_id = 'AUTO-KILL-eNB' - self.desc = 'Automatic Termination of eNB' - self.ShowTestID() - self.eNB_instance = '0' - self.TerminateeNB() - if self.flexranCtrlInstalled and self.flexranCtrlStarted: - self.testCase_id = 'AUTO-KILL-flexran-ctl' - self.desc = 'Automatic Termination of FlexRan CTL' - self.ShowTestID() - self.TerminateFlexranCtrl() - self.prematureExit = True - - def IdleSleep(self): - time.sleep(self.idle_sleep_time) - self.CreateHtmlTestRow(str(self.idle_sleep_time) + ' sec', 'OK', ALL_PROCESSES_OK) - - def X2_Status(self, idx, fileName): - cmd = "curl --silent http://" + self.EPCIPAddress + ":9999/stats | jq '.' > " + fileName - message = cmd + '\n' - logging.debug(cmd) - subprocess.run(cmd, shell=True) - if idx == 0: - cmd = "jq '.mac_stats | length' " + fileName - strNbEnbs = subprocess.check_output(cmd, shell=True, universal_newlines=True) - self.x2NbENBs = int(strNbEnbs.strip()) - cnt = 0 - while cnt < self.x2NbENBs: - cmd = "jq '.mac_stats[" + str(cnt) + "].bs_id' " + fileName - bs_id = subprocess.check_output(cmd, shell=True, universal_newlines=True) - self.x2ENBBsIds[idx].append(bs_id.strip()) - cmd = "jq '.mac_stats[" + str(cnt) + "].ue_mac_stats | length' " + fileName - stNbUEs = subprocess.check_output(cmd, shell=True, universal_newlines=True) - nbUEs = int(stNbUEs.strip()) - ueIdx = 0 - self.x2ENBConnectedUEs[idx].append([]) - while ueIdx < nbUEs: - cmd = "jq '.mac_stats[" + str(cnt) + "].ue_mac_stats[" + str(ueIdx) + "].rnti' " + fileName - rnti = subprocess.check_output(cmd, shell=True, universal_newlines=True) - self.x2ENBConnectedUEs[idx][cnt].append(rnti.strip()) - ueIdx += 1 - cnt += 1 - - msg = "FlexRan Controller is connected to " + str(self.x2NbENBs) + " eNB(s)" - logging.debug(msg) - message += msg + '\n' - cnt = 0 - while cnt < self.x2NbENBs: - msg = " -- eNB: " + str(self.x2ENBBsIds[idx][cnt]) + " is connected to " + str(len(self.x2ENBConnectedUEs[idx][self.cnt])) + " UE(s)" - logging.debug(msg) - message += msg + '\n' - ueIdx = 0 - while ueIdx < len(self.x2ENBConnectedUEs[idx][cnt]): - msg = " -- UE rnti: " + str(self.x2ENBConnectedUEs[idx][cnt][ueIdx]) - logging.debug(msg) - message += msg + '\n' - ueIdx += 1 - cnt += 1 - return message - - def Perform_X2_Handover(self): - html_queue = SimpleQueue() - fullMessage = '
'
-		msg = 'Doing X2 Handover w/ option ' + self.x2_ho_options
-		logging.debug(msg)
-		fullMessage += msg + '\n'
-		if self.x2_ho_options == 'network':
-			if self.flexranCtrlInstalled and self.flexranCtrlStarted:
-				self.x2ENBBsIds = []
-				self.x2ENBConnectedUEs = []
-				self.x2ENBBsIds.append([])
-				self.x2ENBBsIds.append([])
-				self.x2ENBConnectedUEs.append([])
-				self.x2ENBConnectedUEs.append([])
-				fullMessage += self.X2_Status(0, self.testCase_id + '_pre_ho.json') 
-
-				msg = "Activating the X2 Net control on each eNB"
-				logging.debug(msg)
-				fullMessage += msg + '\n'
-				eNB_cnt = self.x2NbENBs
-				cnt = 0
-				while cnt < eNB_cnt:
-					cmd = "curl -XPOST http://" + self.EPCIPAddress + ":9999/rrc/x2_ho_net_control/enb/" + str(self.x2ENBBsIds[0][cnt]) + "/1"
-					logging.debug(cmd)
-					fullMessage += cmd + '\n'
-					subprocess.run(cmd, shell=True)
-					cnt += 1
-				# Waiting for the activation to be active
-				time.sleep(10)
-				msg = "Switching UE(s) from eNB to eNB"
-				logging.debug(msg)
-				fullMessage += msg + '\n'
-				cnt = 0
-				while cnt < eNB_cnt:
-					ueIdx = 0
-					while ueIdx < len(self.x2ENBConnectedUEs[0][cnt]):
-						cmd = "curl -XPOST http://" + self.EPCIPAddress + ":9999/rrc/ho/senb/" + str(self.x2ENBBsIds[0][cnt]) + "/ue/" + str(self.x2ENBConnectedUEs[0][cnt][ueIdx]) + "/tenb/" + str(self.x2ENBBsIds[0][eNB_cnt - cnt - 1])
-						logging.debug(cmd)
-						fullMessage += cmd + '\n'
-						subprocess.run(cmd, shell=True)
-						ueIdx += 1
-					cnt += 1
-				time.sleep(10)
-				# check
-				logging.debug("Checking the Status after X2 Handover")
-				fullMessage += self.X2_Status(1, self.testCase_id + '_post_ho.json') 
-				cnt = 0
-				x2Status = True
-				while cnt < eNB_cnt:
-					if len(self.x2ENBConnectedUEs[0][cnt]) == len(self.x2ENBConnectedUEs[1][cnt]):
-						x2Status = False
-					cnt += 1
-				if x2Status:
-					msg = "X2 Handover was successful"
-					logging.debug(msg)
-					fullMessage += msg + '
' - html_queue.put(fullMessage) - self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) - else: - msg = "X2 Handover FAILED" - logging.error(msg) - fullMessage += msg + '' - html_queue.put(fullMessage) - self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) - else: - self.CreateHtmlTestRow('Cannot perform requested X2 Handover', 'KO', ALL_PROCESSES_OK) - - def LogCollectBuild(self): - if (self.eNBIPAddress != '' and self.eNBUserName != '' and self.eNBPassword != ''): - IPAddress = self.eNBIPAddress - UserName = self.eNBUserName - Password = self.eNBPassword - SourceCodePath = self.eNBSourceCodePath - elif (self.UEIPAddress != '' and self.UEUserName != '' and self.UEPassword != ''): - IPAddress = self.UEIPAddress - UserName = self.UEUserName - Password = self.UEPassword - SourceCodePath = self.UESourceCodePath - else: - sys.exit('Insufficient Parameter') - self.open(IPAddress, UserName, Password) - self.command('cd ' + SourceCodePath, '\$', 5) - self.command('cd cmake_targets', '\$', 5) - self.command('rm -f build.log.zip', '\$', 5) - self.command('zip build.log.zip build_log_*/*', '\$', 60) - self.close() - - def LogCollecteNB(self): - self.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) - self.command('cd ' + self.eNBSourceCodePath, '\$', 5) - self.command('cd cmake_targets', '\$', 5) - self.command('echo ' + self.eNBPassword + ' | sudo -S rm -f enb.log.zip', '\$', 5) - self.command('echo ' + self.eNBPassword + ' | sudo -S zip enb.log.zip enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 60) - self.command('echo ' + self.eNBPassword + ' | sudo -S rm enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 5) - self.close() - - def LogCollectPing(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('cd scripts', '\$', 5) - self.command('rm -f ping.log.zip', '\$', 5) - self.command('zip ping.log.zip ping*.log', '\$', 60) - self.command('rm ping*.log', '\$', 5) - self.close() - - def LogCollectIperf(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath, '\$', 5) - self.command('cd scripts', '\$', 5) - self.command('rm -f iperf.log.zip', '\$', 5) - self.command('zip iperf.log.zip iperf*.log', '\$', 60) - self.command('rm iperf*.log', '\$', 5) - self.close() - - def LogCollectHSS(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('rm -f hss.log.zip', '\$', 5) - if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('zip hss.log.zip hss*.log', '\$', 60) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm hss*.log', '\$', 5) - if re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('zip hss.log.zip logs/hss*.* *.pcap', '\$', 60) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm -f logs/hss*.* *.pcap', '\$', 5) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cp /opt/hss_sim0609/hss.log .', '\$', 60) - self.command('zip hss.log.zip hss.log', '\$', 60) - else: - logging.error('This option should not occur!') - self.close() - - def LogCollectMME(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('rm -f mme.log.zip', '\$', 5) - if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('zip mme.log.zip mme*.log', '\$', 60) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm mme*.log', '\$', 5) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cp /opt/ltebox/var/log/*Log.0 .', '\$', 5) - self.command('zip mme.log.zip mmeLog.0 s1apcLog.0 s1apsLog.0 s11cLog.0 libLog.0 s1apCodecLog.0', '\$', 60) - else: - logging.error('This option should not occur!') - self.close() - - def LogCollectSPGW(self): - self.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) - self.command('cd ' + self.EPCSourceCodePath + '/scripts', '\$', 5) - self.command('rm -f spgw.log.zip', '\$', 5) - if re.match('OAI', self.EPCType, re.IGNORECASE) or re.match('OAI-Rel14-CUPS', self.EPCType, re.IGNORECASE): - self.command('zip spgw.log.zip spgw*.log', '\$', 60) - self.command('echo ' + self.EPCPassword + ' | sudo -S rm spgw*.log', '\$', 5) - elif re.match('ltebox', self.EPCType, re.IGNORECASE): - self.command('cp /opt/ltebox/var/log/xGwLog.0 .', '\$', 5) - self.command('zip spgw.log.zip xGwLog.0', '\$', 60) - else: - logging.error('This option should not occur!') - self.close() - - def LogCollectOAIUE(self): - self.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - self.command('cd ' + self.UESourceCodePath, '\$', 5) - self.command('cd cmake_targets', '\$', 5) - self.command('echo ' + self.UEPassword + ' | sudo -S rm -f ue.log.zip', '\$', 5) - self.command('echo ' + self.UEPassword + ' | sudo -S zip ue.log.zip ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 60) - self.command('echo ' + self.UEPassword + ' | sudo -S rm ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 5) - self.close() - - def RetrieveSystemVersion(self, machine): - if self.eNBIPAddress == 'none' or self.UEIPAddress == 'none': - self.OsVersion = 'Ubuntu 16.04.5 LTS' - self.KernelVersion = '4.15.0-45-generic' - self.UhdVersion = '3.13.0.1-0' - self.UsrpBoard = 'B210' - self.CpuNb = '4' - self.CpuModel = 'Intel(R) Core(TM) i5-6200U' - self.CpuMHz = '2399.996 MHz' - return 0 - if machine == 'eNB': - if self.eNBIPAddress != '' and self.eNBUserName != '' and self.eNBPassword != '': - IPAddress = self.eNBIPAddress - UserName = self.eNBUserName - Password = self.eNBPassword - else: - return -1 - if machine == 'UE': - if self.UEIPAddress != '' and self.UEUserName != '' and self.UEPassword != '': - IPAddress = self.UEIPAddress - UserName = self.UEUserName - Password = self.UEPassword - else: - return -1 - - self.open(IPAddress, UserName, Password) - self.command('lsb_release -a', '\$', 5) - result = re.search('Description:\\\\t(?P[a-zA-Z0-9\-\_\.\ ]+)', str(self.ssh.before)) - if result is not None: - self.OsVersion = result.group('os_type') - logging.debug('OS is: ' + self.OsVersion) - self.command('uname -r', '\$', 5) - result = re.search('uname -r\\\\r\\\\n(?P[a-zA-Z0-9\-\_\.]+)', str(self.ssh.before)) - if result is not None: - self.KernelVersion = result.group('kernel_version') - logging.debug('Kernel Version is: ' + self.KernelVersion) - self.command('dpkg --list | egrep --color=never libuhd003', '\$', 5) - result = re.search('libuhd003:amd64 *(?P[0-9\.]+)', str(self.ssh.before)) - if result is not None: - self.UhdVersion = result.group('uhd_version') - logging.debug('UHD Version is: ' + self.UhdVersion) - self.command('echo ' + Password + ' | sudo -S uhd_find_devices', '\$', 15) - result = re.search('product: (?P[0-9A-Za-z]+)\\\\r\\\\n', str(self.ssh.before)) - if result is not None: - self.UsrpBoard = result.group('usrp_board') - logging.debug('USRP Board is: ' + self.UsrpBoard) - self.command('lscpu', '\$', 5) - result = re.search('CPU\(s\): *(?P[0-9]+).*Model name: *(?P[a-zA-Z0-9\-\_\.\ \(\)]+).*CPU MHz: *(?P[0-9\.]+)', str(self.ssh.before)) - if result is not None: - self.CpuNb = result.group('nb_cpus') - logging.debug('nb_cpus: ' + self.CpuNb) - self.CpuModel = result.group('model') - logging.debug('model: ' + self.CpuModel) - self.CpuMHz = result.group('cpu_mhz') + ' MHz' - logging.debug('cpu_mhz: ' + self.CpuMHz) - self.close() - -#----------------------------------------------------------- -# HTML Reporting.... -#----------------------------------------------------------- - def CreateHtmlHeader(self): - if (not self.htmlHeaderCreated): - logging.debug('\u001B[1m----------------------------------------\u001B[0m') - logging.debug('\u001B[1m Creating HTML header \u001B[0m') - logging.debug('\u001B[1m----------------------------------------\u001B[0m') - self.htmlFile = open('test_results.html', 'w') - self.htmlFile.write('\n') - self.htmlFile.write('\n') - self.htmlFile.write('\n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' Test Results for TEMPLATE_JOB_NAME job build #TEMPLATE_BUILD_ID\n') - self.htmlFile.write('\n') - self.htmlFile.write('
\n') - self.htmlFile.write('
\n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write('
\n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' Job Summary -- Job: TEMPLATE_JOB_NAME -- Build-ID: TEMPLATE_BUILD_ID\n') - self.htmlFile.write('
\n') - self.htmlFile.write('
\n') - self.htmlFile.write('
TEMPLATE_STAGE_NAME
\n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (self.ranAllowMerge): - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (self.ranAllowMerge): - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (self.ranAllowMerge): - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if self.ranAllowMerge != '': - commit_message = subprocess.check_output("git log -n1 --pretty=format:\"%s\" " + self.ranCommitID, shell=True, universal_newlines=True) - commit_message = commit_message.strip() - self.htmlFile.write(' \n') - if (self.ranAllowMerge): - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (self.ranAllowMerge): - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (self.ranTargetBranch == ''): - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write('
Build Start Time (UTC) TEMPLATE_BUILD_TIME
GIT Repository ' + self.ranRepository + '
Job Trigger Merge-RequestPush to Branch
Source Branch Branch' + self.ranBranch + '
Source Commit ID Commit ID ' + self.ranCommitID + '
Source Commit Message Commit Message ' + commit_message + '
Target Branch develop' + self.ranTargetBranch + '
\n') - - if (self.ADBIPAddress != 'none'): - terminate_ue_flag = True - self.GetAllUEDevices(terminate_ue_flag) - self.GetAllCatMDevices(terminate_ue_flag) - self.htmlUEConnected = len(self.UEDevices) - self.htmlFile.write('

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

\n') - self.htmlFile.write('

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

\n') - else: - self.UEDevices.append('OAI-UE') - self.htmlUEConnected = len(self.UEDevices) - self.htmlFile.write('

' + str(len(self.UEDevices)) + ' OAI UE(s) is(are) connected to CI bench

\n') - self.htmlFile.write('
\n') - self.htmlFile.write(' \n') - self.htmlFile.write('
\n') - self.htmlFile.close() - - def CreateHtmlTabHeader(self): - if (not self.htmlHeaderCreated): - if (not os.path.isfile('test_results.html')): - self.CreateHtmlHeader() - self.htmlFile = open('test_results.html', 'a') - if (self.nbTestXMLfiles == 1): - self.htmlFile.write('
\n') - self.htmlFile.write('

Test Summary for ' + self.testXMLfiles[0] + '

\n') - else: - self.htmlFile.write('
\n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (self.htmlUEConnected == -1): - terminate_ue_flag = True - if (self.ADBIPAddress != 'none'): - self.GetAllUEDevices(terminate_ue_flag) - self.GetAllCatMDevices(terminate_ue_flag) - else: - self.UEDevices.append('OAI-UE') - self.htmlUEConnected = len(self.UEDevices) - - i = 0 - while (i < self.htmlUEConnected): - self.htmlFile.write(' \n') - i += 1 - self.htmlFile.write(' \n') - self.htmlHeaderCreated = True - - def CreateHtmlTabFooter(self, passStatus): - if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if passStatus: - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write('
Relative Time (ms)Test IdTest DescTest OptionsTest StatusUE' + str(i) + ' Status
Final Tab StatusPASS FAIL
\n') - self.htmlFile.write('
\n') - self.htmlFile.close() - time.sleep(1) - if passStatus: - cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__//' test_results.html" - subprocess.run(cmd, shell=True) - else: - cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__/<\/span>/' test_results.html" - subprocess.run(cmd, shell=True) - self.htmlFooterCreated = False - - def CreateHtmlFooter(self, passStatus): - if (os.path.isfile('test_results.html')): - logging.debug('\u001B[1m----------------------------------------\u001B[0m') - logging.debug('\u001B[1m Creating HTML footer \u001B[0m') - logging.debug('\u001B[1m----------------------------------------\u001B[0m') - - self.htmlFile = open('test_results.html', 'a') - self.htmlFile.write('
\n') - self.htmlFile.write('

\n') - self.htmlFile.write(' \n') - - machines = [ 'eNB', 'UE' ] - for machine in machines: - res = self.RetrieveSystemVersion(machine) - if res == -1: - continue - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if passStatus: - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write('
' + str(machine) + ' Server Characteristics
OS Version' + self.OsVersion + 'Kernel Version' + self.KernelVersion + 'UHD Version' + self.UhdVersion + 'USRP Board' + self.UsrpBoard + '
Nb CPUs' + self.CpuNb + 'CPU Model Name' + self.CpuModel + 'CPU Frequency' + self.CpuMHz + '
Final StatusPASS FAIL
\n') - self.htmlFile.write('

\n') - self.htmlFile.write('
End of Test Report -- Copyright 2018 OpenAirInterface. All Rights Reserved.
\n') - self.htmlFile.write('
\n') - self.htmlFile.write('\n') - self.htmlFile.close() - - def CreateHtmlTestRow(self, options, status, processesStatus, machine='eNB'): - if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): - currentTime = int(round(time.time() * 1000)) - self.startTime - self.htmlFile.write(' \n') - self.htmlFile.write(' ' + format(currentTime / 1000, '.1f') + '\n') - self.htmlFile.write(' ' + self.testCase_id + '\n') - self.htmlFile.write(' ' + self.desc + '\n') - self.htmlFile.write(' ' + str(options) + '\n') - if (str(status) == 'OK'): - self.htmlFile.write(' ' + str(status) + '\n') - elif (str(status) == 'KO'): - if (processesStatus == 0): - self.htmlFile.write(' ' + str(status) + '\n') - elif (processesStatus == ENB_PROCESS_FAILED): - self.htmlFile.write(' KO - eNB process not found\n') - elif (processesStatus == OAI_UE_PROCESS_FAILED): - self.htmlFile.write(' KO - OAI UE process not found\n') - elif (processesStatus == ENB_PROCESS_SEG_FAULT): - self.htmlFile.write(' KO - ' + machine + ' process ended in Segmentation Fault\n') - elif (processesStatus == ENB_PROCESS_ASSERTION) or (processesStatus == OAI_UE_PROCESS_ASSERTION): - self.htmlFile.write(' KO - ' + machine + ' process ended in Assertion\n') - elif (processesStatus == ENB_PROCESS_REALTIME_ISSUE): - self.htmlFile.write(' KO - ' + machine + ' process faced Real Time issue(s)\n') - elif (processesStatus == ENB_PROCESS_NOLOGFILE_TO_ANALYZE) or (processesStatus == OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE): - self.htmlFile.write(' OK?\n') - elif (processesStatus == ENB_PROCESS_SLAVE_RRU_NOT_SYNCED): - self.htmlFile.write(' KO - ' + machine + ' Slave RRU could not synch\n') - elif (processesStatus == OAI_UE_PROCESS_COULD_NOT_SYNC): - self.htmlFile.write(' KO - UE could not sync\n') - elif (processesStatus == HSS_PROCESS_FAILED): - self.htmlFile.write(' KO - HSS process not found\n') - elif (processesStatus == MME_PROCESS_FAILED): - self.htmlFile.write(' KO - MME process not found\n') - elif (processesStatus == SPGW_PROCESS_FAILED): - self.htmlFile.write(' KO - SPGW process not found\n') - elif (processesStatus == UE_IP_ADDRESS_ISSUE): - self.htmlFile.write(' KO - Could not retrieve UE IP address\n') - else: - self.htmlFile.write(' ' + str(status) + '\n') - else: - self.htmlFile.write(' ' + str(status) + '\n') - if (len(str(self.htmleNBFailureMsg)) > 2): - cellBgColor = 'white' - result = re.search('ended with|faced real time issues', self.htmleNBFailureMsg) - if result is not None: - cellBgColor = 'red' - else: - result = re.search('showed|Reestablishment|Could not copy eNB logfile', self.htmleNBFailureMsg) - if result is not None: - cellBgColor = 'orange' - self.htmlFile.write('
' + self.htmleNBFailureMsg + '
\n') - self.htmleNBFailureMsg = '' - elif (len(str(self.htmlUEFailureMsg)) > 2): - cellBgColor = 'white' - result = re.search('ended with|faced real time issues', self.htmlUEFailureMsg) - if result is not None: - cellBgColor = 'red' - else: - result = re.search('showed|Could not copy UE logfile|oaitun_ue1 interface is either NOT mounted or NOT configured', self.htmlUEFailureMsg) - if result is not None: - cellBgColor = 'orange' - self.htmlFile.write('
' + self.htmlUEFailureMsg + '
\n') - self.htmlUEFailureMsg = '' - else: - i = 0 - while (i < self.htmlUEConnected): - self.htmlFile.write(' -\n') - i += 1 - self.htmlFile.write(' \n') - - def CreateHtmlTestRowQueue(self, options, status, ue_status, ue_queue): - if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): - currentTime = int(round(time.time() * 1000)) - self.startTime - addOrangeBK = False - self.htmlFile.write(' \n') - self.htmlFile.write(' ' + format(currentTime / 1000, '.1f') + '\n') - self.htmlFile.write(' ' + self.testCase_id + '\n') - self.htmlFile.write(' ' + self.desc + '\n') - self.htmlFile.write(' ' + str(options) + '\n') - if (str(status) == 'OK'): - self.htmlFile.write(' ' + str(status) + '\n') - elif (str(status) == 'KO'): - self.htmlFile.write(' ' + str(status) + '\n') - else: - addOrangeBK = True - self.htmlFile.write(' ' + str(status) + '\n') - i = 0 - while (i < self.htmlUEConnected): - if (i < ue_status): - if (not ue_queue.empty()): - if (addOrangeBK): - self.htmlFile.write(' ' + str(ue_queue.get()).replace('white', 'orange') + '\n') - else: - self.htmlFile.write(' ' + str(ue_queue.get()) + '\n') - else: - self.htmlFile.write(' -\n') - else: - self.htmlFile.write(' -\n') - i += 1 - self.htmlFile.write(' \n') - -#----------------------------------------------------------- -# ShowTestID() -#----------------------------------------------------------- - def ShowTestID(self): - logging.debug('\u001B[1m----------------------------------------\u001B[0m') - logging.debug('\u001B[1mTest ID:' + self.testCase_id + '\u001B[0m') - logging.debug('\u001B[1m' + self.desc + '\u001B[0m') - logging.debug('\u001B[1m----------------------------------------\u001B[0m') - -#----------------------------------------------------------- -# Usage() -#----------------------------------------------------------- -def Usage(): - print('----------------------------------------------------------------------------------------------------------------------') - print('main.py Ver:' + Version) - print('----------------------------------------------------------------------------------------------------------------------') - print('Usage: python main.py [options]') - print(' --help Show this help.') - print(' --mode=[Mode]') - print(' TesteNB') - print(' InitiateHtml, FinalizeHtml') - print(' TerminateeNB, TerminateUE, TerminateHSS, TerminateMME, TerminateSPGW') - print(' LogCollectBuild, LogCollecteNB, LogCollectHSS, LogCollectMME, LogCollectSPGW, LogCollectPing, LogCollectIperf') - print('---------------------------------------------------------------------------------------------------- Git Options --') - print(' --ranRepository=[OAI RAN Repository URL]') - print(' --ranBranch=[OAI RAN Repository Branch]') - print(' --ranCommitID=[OAI RAN Repository Commit SHA-1]') - print(' --ranAllowMerge=[Allow Merge Request (with target branch) (true or false)]') - print(' --ranTargetBranch=[Target Branch in case of a Merge Request]') - print('--------------------------------------------------------------------------------------------- eNB Server Options --') - print(' --eNBIPAddress=[eNB\'s IP Address]') - print(' --eNBUserName=[eNB\'s Login User Name]') - print(' --eNBPassword=[eNB\'s Login Password]') - print(' --eNBSourceCodePath=[eNB\'s Source Code Path]') - print('------------------------------------------------------------------------------------------ OAI UE Server Options --') - print(' --UEIPAddress=[UE\'s IP Address]') - print(' --UEUserName=[UE\'s Login User Name]') - print(' --UEPassword=[UE\'s Login Password]') - print(' --UESourceCodePath=[UE\'s Source Code Path]') - print('--------------------------------------------------------------------------------------------- EPC Server Options --') - print(' --EPCIPAddress=[EPC\'s IP Address]') - print(' --EPCUserName=[EPC\'s Login User Name]') - print(' --EPCPassword=[EPC\'s Login Password]') - print(' --EPCSourceCodePath=[EPC\'s Source Code Path]') - print(' --EPCType=[EPC\'s Type: OAI or ltebox or OAI-Rel14-CUPS]') - print('--------------------------------------------------------------------------------------------- ABD Server Options --') - print(' --ADBIPAddress=[ADB\'s IP Address]') - print(' --ADBUserName=[ADB\'s Login User Name]') - print(' --ADBPassword=[ADB\'s Login Password]') - print('----------------------------------------------------------------------------------------------------------------------') - print(' --XMLTestFile=[XML Test File to be run]') - print('----------------------------------------------------------------------------------------------------------------------') - -def CheckClassValidity(action,id): - if action != 'Build_eNB' and action != 'WaitEndBuild_eNB' and action != 'Initialize_eNB' and action != 'Terminate_eNB' and action != 'Initialize_UE' and action != 'Terminate_UE' and action != 'Attach_UE' and action != 'Detach_UE' and action != 'Build_OAI_UE' and action != 'Initialize_OAI_UE' and action != 'Terminate_OAI_UE' and action != 'DataDisable_UE' and action != 'DataEnable_UE' and action != 'CheckStatusUE' and action != 'Ping' and action != 'Iperf' and action != 'Reboot_UE' and action != 'Initialize_FlexranCtrl' and action != 'Terminate_FlexranCtrl' and action != 'Initialize_HSS' and action != 'Terminate_HSS' and action != 'Initialize_MME' and action != 'Terminate_MME' and action != 'Initialize_SPGW' and action != 'Terminate_SPGW' and action != 'Initialize_CatM_module' and action != 'Terminate_CatM_module' and action != 'Attach_CatM_module' and action != 'Detach_CatM_module' and action != 'Ping_CatM_module' and action != 'IdleSleep' and action != 'Perform_X2_Handover': - logging.debug('ERROR: test-case ' + id + ' has wrong class ' + action) - return False - return True - -def GetParametersFromXML(action): - if action == 'Build_eNB': - SSH.Build_eNB_args = test.findtext('Build_eNB_args') - SSH.eNB_instance = test.findtext('eNB_instance') - if (SSH.eNB_instance is None): - SSH.eNB_instance = '0' - SSH.eNB_serverId = test.findtext('eNB_serverId') - if (SSH.eNB_serverId is None): - SSH.eNB_serverId = '0' - xmlBgBuildField = test.findtext('backgroundBuild') - if (xmlBgBuildField is None): - SSH.backgroundBuild = False - else: - if re.match('true', xmlBgBuildField, re.IGNORECASE): - SSH.backgroundBuild = True - else: - SSH.backgroundBuild = False - - if action == 'WaitEndBuild_eNB': - SSH.Build_eNB_args = test.findtext('Build_eNB_args') - SSH.eNB_instance = test.findtext('eNB_instance') - if (SSH.eNB_instance is None): - SSH.eNB_instance = '0' - SSH.eNB_serverId = test.findtext('eNB_serverId') - if (SSH.eNB_serverId is None): - SSH.eNB_serverId = '0' - - if action == 'Initialize_eNB': - SSH.Initialize_eNB_args = test.findtext('Initialize_eNB_args') - SSH.eNB_instance = test.findtext('eNB_instance') - if (SSH.eNB_instance is None): - SSH.eNB_instance = '0' - SSH.eNB_serverId = test.findtext('eNB_serverId') - if (SSH.eNB_serverId is None): - SSH.eNB_serverId = '0' - - if action == 'Terminate_eNB': - SSH.eNB_instance = test.findtext('eNB_instance') - if (SSH.eNB_instance is None): - SSH.eNB_instance = '0' - SSH.eNB_serverId = test.findtext('eNB_serverId') - if (SSH.eNB_serverId is None): - SSH.eNB_serverId = '0' - - if action == 'Attach_UE': - nbMaxUEtoAttach = test.findtext('nbMaxUEtoAttach') - if (nbMaxUEtoAttach is None): - SSH.nbMaxUEtoAttach = -1 - else: - SSH.nbMaxUEtoAttach = int(nbMaxUEtoAttach) - - if action == 'CheckStatusUE': - expectedNBUE = test.findtext('expectedNbOfConnectedUEs') - if (expectedNBUE is None): - SSH.expectedNbOfConnectedUEs = -1 - else: - SSH.expectedNbOfConnectedUEs = int(expectedNBUE) - - if action == 'Build_OAI_UE': - SSH.Build_OAI_UE_args = test.findtext('Build_OAI_UE_args') - - if action == 'Initialize_OAI_UE': - SSH.Initialize_OAI_UE_args = test.findtext('Initialize_OAI_UE_args') - SSH.UE_instance = test.findtext('UE_instance') - if (SSH.UE_instance is None): - SSH.UE_instance = '0' - - if action == 'Terminate_OAI_UE': - SSH.eNB_instance = test.findtext('UE_instance') - if (SSH.UE_instance is None): - SSH.UE_instance = '0' - - if action == 'Ping' or action == 'Ping_CatM_module': - SSH.ping_args = test.findtext('ping_args') - SSH.ping_packetloss_threshold = test.findtext('ping_packetloss_threshold') - - if action == 'Iperf': - SSH.iperf_args = test.findtext('iperf_args') - SSH.iperf_packetloss_threshold = test.findtext('iperf_packetloss_threshold') - SSH.iperf_profile = test.findtext('iperf_profile') - if (SSH.iperf_profile is None): - SSH.iperf_profile = 'balanced' - else: - if SSH.iperf_profile != 'balanced' and SSH.iperf_profile != 'unbalanced' and SSH.iperf_profile != 'single-ue': - logging.debug('ERROR: test-case has wrong profile ' + SSH.iperf_profile) - SSH.iperf_profile = 'balanced' - - if action == 'IdleSleep': - string_field = test.findtext('idle_sleep_time_in_sec') - if (string_field is None): - SSH.idle_sleep_time = 5 - else: - SSH.idle_sleep_time = int(string_field) - - if action == 'Perform_X2_Handover': - string_field = test.findtext('x2_ho_options') - if (string_field is None): - SSH.x2_ho_options = 'network' - else: - if string_field != 'network': - logging.error('ERROR: test-case has wrong option ' + string_field) - SSH.x2_ho_options = 'network' - else: - SSH.x2_ho_options = string_field - - -#check if given test is in list -#it is in list if one of the strings in 'list' is at the beginning of 'test' -def test_in_list(test, list): - for check in list: - check=check.replace('+','') - if (test.startswith(check)): - return True - return False - -def receive_signal(signum, frame): - sys.exit(1) - -#----------------------------------------------------------- -# Parameter Check -#----------------------------------------------------------- -mode = '' -SSH = SSHConnection() - -argvs = sys.argv -argc = len(argvs) -cwd = os.getcwd() - -while len(argvs) > 1: - myArgv = argvs.pop(1) # 0th is this file's name - if re.match('^\-\-help$', myArgv, re.IGNORECASE): - Usage() - sys.exit(0) - elif re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE) - mode = matchReg.group(1) - elif re.match('^\-\-eNBRepository=(.+)$|^\-\-ranRepository(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE) - else: - matchReg = re.match('^\-\-ranRepository=(.+)$', myArgv, re.IGNORECASE) - SSH.ranRepository = matchReg.group(1) - elif re.match('^\-\-eNB_AllowMerge=(.+)$|^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE) - else: - matchReg = re.match('^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE) - doMerge = matchReg.group(1) - if ((doMerge == 'true') or (doMerge == 'True')): - SSH.ranAllowMerge = True - elif re.match('^\-\-eNBBranch=(.+)$|^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE) - else: - matchReg = re.match('^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE) - SSH.ranBranch = matchReg.group(1) - elif re.match('^\-\-eNBCommitID=(.*)$|^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE) - else: - matchReg = re.match('^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE) - SSH.ranCommitID = matchReg.group(1) - elif re.match('^\-\-eNBTargetBranch=(.*)$|^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE) - else: - matchReg = re.match('^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE) - SSH.ranTargetBranch = matchReg.group(1) - elif re.match('^\-\-eNBIPAddress=(.+)$|^\-\-eNB[1-2]IPAddress=(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE) - SSH.eNBIPAddress = matchReg.group(1) - elif re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB1IPAddress = matchReg.group(1) - elif re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB2IPAddress = matchReg.group(1) - elif re.match('^\-\-eNBUserName=(.+)$|^\-\-eNB[1-2]UserName=(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE) - SSH.eNBUserName = matchReg.group(1) - elif re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB1UserName = matchReg.group(1) - elif re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB2UserName = matchReg.group(1) - elif re.match('^\-\-eNBPassword=(.+)$|^\-\-eNB[1-2]Password=(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE) - SSH.eNBPassword = matchReg.group(1) - elif re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB1Password = matchReg.group(1) - elif re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB2Password = matchReg.group(1) - elif re.match('^\-\-eNBSourceCodePath=(.+)$|^\-\-eNB[1-2]SourceCodePath=(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE) - SSH.eNBSourceCodePath = matchReg.group(1) - elif re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB1SourceCodePath = matchReg.group(1) - elif re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE) - SSH.eNB2SourceCodePath = matchReg.group(1) - elif re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE) - SSH.EPCIPAddress = matchReg.group(1) - elif re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE) - SSH.EPCBranch = matchReg.group(1) - elif re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE) - SSH.EPCUserName = matchReg.group(1) - elif re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE) - SSH.EPCPassword = matchReg.group(1) - elif re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE) - SSH.EPCSourceCodePath = matchReg.group(1) - elif re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE) - if re.match('OAI', matchReg.group(1), re.IGNORECASE) or re.match('ltebox', matchReg.group(1), re.IGNORECASE) or re.match('OAI-Rel14-CUPS', matchReg.group(1), re.IGNORECASE): - SSH.EPCType = matchReg.group(1) - else: - sys.exit('Invalid EPC Type: ' + matchReg.group(1) + ' -- (should be OAI or ltebox or OAI-Rel14-CUPS)') - elif re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE) - SSH.ADBIPAddress = matchReg.group(1) - elif re.match('^\-\-ADBUserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-ADBUserName=(.+)$', myArgv, re.IGNORECASE) - SSH.ADBUserName = matchReg.group(1) - elif re.match('^\-\-ADBType=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-ADBType=(.+)$', myArgv, re.IGNORECASE) - if re.match('centralized', matchReg.group(1), re.IGNORECASE) or re.match('distributed', matchReg.group(1), re.IGNORECASE): - if re.match('distributed', matchReg.group(1), re.IGNORECASE): - SSH.ADBCentralized = False - else: - SSH.ADBCentralized = True - else: - sys.exit('Invalid ADB Type: ' + matchReg.group(1) + ' -- (should be centralized or distributed)') - elif re.match('^\-\-ADBPassword=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-ADBPassword=(.+)$', myArgv, re.IGNORECASE) - SSH.ADBPassword = matchReg.group(1) - elif re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE) - SSH.testXMLfiles.append(matchReg.group(1)) - SSH.nbTestXMLfiles += 1 - elif re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE) - SSH.UEIPAddress = matchReg.group(1) - elif re.match('^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE) - SSH.UEUserName = matchReg.group(1) - elif re.match('^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE) - SSH.UEPassword = matchReg.group(1) - elif re.match('^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE) - SSH.UESourceCodePath = matchReg.group(1) - elif re.match('^\-\-finalStatus=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-finalStatus=(.+)$', myArgv, re.IGNORECASE) - finalStatus = matchReg.group(1) - if ((finalStatus == 'true') or (finalStatus == 'True')): - SSH.finalStatus = True - else: - Usage() - sys.exit('Invalid Parameter: ' + myArgv) - -if re.match('^TerminateeNB$', mode, re.IGNORECASE): - if SSH.eNBIPAddress == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - SSH.eNB_serverId = '0' - SSH.eNB_instance = '0' - SSH.eNBSourceCodePath = '/tmp/' - SSH.TerminateeNB() -elif re.match('^TerminateUE$', mode, re.IGNORECASE): - if (SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == ''): - Usage() - sys.exit('Insufficient Parameter') - signal.signal(signal.SIGUSR1, receive_signal) - SSH.TerminateUE() -elif re.match('^TerminateOAIUE$', mode, re.IGNORECASE): - if SSH.UEIPAddress == '' or SSH.UEUserName == '' or SSH.UEPassword == '': - Usage() - sys.exit('Insufficient Parameter') - signal.signal(signal.SIGUSR1, receive_signal) - SSH.TerminateOAIUE() -elif re.match('^TerminateHSS$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - SSH.TerminateHSS() -elif re.match('^TerminateMME$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - SSH.TerminateMME() -elif re.match('^TerminateSPGW$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - SSH.TerminateSPGW() -elif re.match('^LogCollectBuild$', mode, re.IGNORECASE): - if (SSH.eNBIPAddress == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '' or SSH.eNBSourceCodePath == '') and (SSH.UEIPAddress == '' or SSH.UEUserName == '' or SSH.UEPassword == '' or SSH.UESourceCodePath == ''): - Usage() - sys.exit('Insufficient Parameter') - SSH.LogCollectBuild() -elif re.match('^LogCollecteNB$', mode, re.IGNORECASE): - if SSH.eNBIPAddress == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '' or SSH.eNBSourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - SSH.LogCollecteNB() -elif re.match('^LogCollectHSS$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - SSH.LogCollectHSS() -elif re.match('^LogCollectMME$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - SSH.LogCollectMME() -elif re.match('^LogCollectSPGW$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - SSH.LogCollectSPGW() -elif re.match('^LogCollectPing$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCSourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - SSH.LogCollectPing() -elif re.match('^LogCollectIperf$', mode, re.IGNORECASE): - if SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCSourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - SSH.LogCollectIperf() -elif re.match('^LogCollectOAIUE$', mode, re.IGNORECASE): - if SSH.UEIPAddress == '' or SSH.UEUserName == '' or SSH.UEPassword == '' or SSH.UESourceCodePath == '': - Usage() - sys.exit('Insufficient Parameter') - SSH.LogCollectOAIUE() -elif re.match('^InitiateHtml$', mode, re.IGNORECASE): - if (SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == ''): - Usage() - sys.exit('Insufficient Parameter') - count = 0 - foundCount = 0 - while (count < SSH.nbTestXMLfiles): - xml_test_file = cwd + "/" + SSH.testXMLfiles[count] - xml_test_file = sys.path[0] + "/" + SSH.testXMLfiles[count] - if (os.path.isfile(xml_test_file)): - xmlTree = ET.parse(xml_test_file) - xmlRoot = xmlTree.getroot() - SSH.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count))) - SSH.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-' + str(count))) - SSH.htmlTabIcons.append(xmlRoot.findtext('htmlTabIcon',default='info-sign')) - foundCount += 1 - count += 1 - if foundCount != SSH.nbTestXMLfiles: - SSH.nbTestXMLfiles = foundCount - SSH.CreateHtmlHeader() -elif re.match('^FinalizeHtml$', mode, re.IGNORECASE): - SSH.CreateHtmlFooter(SSH.finalStatus) -elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re.IGNORECASE): - if re.match('^TesteNB$', mode, re.IGNORECASE): - if SSH.eNBIPAddress == '' or SSH.ranRepository == '' or SSH.ranBranch == '' or SSH.eNBUserName == '' or SSH.eNBPassword == '' or SSH.eNBSourceCodePath == '' or SSH.EPCIPAddress == '' or SSH.EPCUserName == '' or SSH.EPCPassword == '' or SSH.EPCType == '' or SSH.EPCSourceCodePath == '' or SSH.ADBIPAddress == '' or SSH.ADBUserName == '' or SSH.ADBPassword == '': - Usage() - sys.exit('Insufficient Parameter') - - if (SSH.EPCIPAddress != '') and (SSH.EPCIPAddress != 'none'): - SSH.copyout(SSH.EPCIPAddress, SSH.EPCUserName, SSH.EPCPassword, cwd + "/tcp_iperf_stats.awk", "/tmp") - SSH.copyout(SSH.EPCIPAddress, SSH.EPCUserName, SSH.EPCPassword, cwd + "/active_net_interfaces.awk", "/tmp") - else: - if SSH.UEIPAddress == '' or SSH.ranRepository == '' or SSH.ranBranch == '' or SSH.UEUserName == '' or SSH.UEPassword == '' or SSH.UESourceCodePath == '': - Usage() - sys.exit('UE: Insufficient Parameter') - - #read test_case_list.xml file - # if no parameters for XML file, use default value - if (SSH.nbTestXMLfiles != 1): - xml_test_file = cwd + "/test_case_list.xml" - else: - xml_test_file = cwd + "/" + SSH.testXMLfiles[0] - - xmlTree = ET.parse(xml_test_file) - xmlRoot = xmlTree.getroot() - - exclusion_tests=xmlRoot.findtext('TestCaseExclusionList',default='') - requested_tests=xmlRoot.findtext('TestCaseRequestedList',default='') - if (SSH.nbTestXMLfiles == 1): - SSH.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-0')) - SSH.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-0')) - repeatCount = xmlRoot.findtext('repeatCount',default='1') - SSH.repeatCounts.append(int(repeatCount)) - all_tests=xmlRoot.findall('testCase') - - exclusion_tests=exclusion_tests.split() - requested_tests=requested_tests.split() - - #check that exclusion tests are well formatted - #(6 digits or less than 6 digits followed by +) - for test in exclusion_tests: - if (not re.match('^[0-9]{6}$', test) and - not re.match('^[0-9]{1,5}\+$', test)): - logging.debug('ERROR: exclusion test is invalidly formatted: ' + test) - sys.exit(1) - else: - logging.debug(test) - - #check that requested tests are well formatted - #(6 digits or less than 6 digits followed by +) - #be verbose - for test in requested_tests: - if (re.match('^[0-9]{6}$', test) or - re.match('^[0-9]{1,5}\+$', test)): - logging.debug('INFO: test group/case requested: ' + test) - else: - logging.debug('ERROR: requested test is invalidly formatted: ' + test) - sys.exit(1) - if (SSH.EPCIPAddress != '') and (SSH.EPCIPAddress != 'none'): - SSH.CheckFlexranCtrlInstallation() - - #get the list of tests to be done - todo_tests=[] - for test in requested_tests: - if (test_in_list(test, exclusion_tests)): - logging.debug('INFO: test will be skipped: ' + test) - else: - #logging.debug('INFO: test will be run: ' + test) - todo_tests.append(test) - - signal.signal(signal.SIGUSR1, receive_signal) - - SSH.CreateHtmlTabHeader() - - SSH.FailReportCnt = 0 - SSH.prematureExit = True - SSH.startTime = int(round(time.time() * 1000)) - while SSH.FailReportCnt < SSH.repeatCounts[0] and SSH.prematureExit: - SSH.prematureExit = False - for test_case_id in todo_tests: - if SSH.prematureExit: - break - for test in all_tests: - if SSH.prematureExit: - break - id = test.get('id') - if test_case_id != id: - continue - SSH.testCase_id = id - SSH.desc = test.findtext('desc') - action = test.findtext('class') - if (CheckClassValidity(action, id) == False): - continue - SSH.ShowTestID() - GetParametersFromXML(action) - if action == 'Initialize_UE' or action == 'Attach_UE' or action == 'Detach_UE' or action == 'Ping' or action == 'Iperf' or action == 'Reboot_UE' or action == 'DataDisable_UE' or action == 'DataEnable_UE' or action == 'CheckStatusUE': - if (SSH.ADBIPAddress != 'none'): - terminate_ue_flag = False - SSH.GetAllUEDevices(terminate_ue_flag) - if action == 'Build_eNB': - SSH.BuildeNB() - elif action == 'WaitEndBuild_eNB': - SSH.WaitBuildeNBisFinished() - elif action == 'Initialize_eNB': - SSH.InitializeeNB() - elif action == 'Terminate_eNB': - SSH.TerminateeNB() - elif action == 'Initialize_UE': - SSH.InitializeUE() - elif action == 'Terminate_UE': - SSH.TerminateUE() - elif action == 'Attach_UE': - SSH.AttachUE() - elif action == 'Detach_UE': - SSH.DetachUE() - elif action == 'DataDisable_UE': - SSH.DataDisableUE() - elif action == 'DataEnable_UE': - SSH.DataEnableUE() - elif action == 'CheckStatusUE': - SSH.CheckStatusUE() - elif action == 'Build_OAI_UE': - SSH.BuildOAIUE() - elif action == 'Initialize_OAI_UE': - SSH.InitializeOAIUE() - elif action == 'Terminate_OAI_UE': - SSH.TerminateOAIUE() - elif action == 'Initialize_CatM_module': - SSH.InitializeCatM() - elif action == 'Terminate_CatM_module': - SSH.TerminateCatM() - elif action == 'Attach_CatM_module': - SSH.AttachCatM() - elif action == 'Detach_CatM_module': - SSH.TerminateCatM() - elif action == 'Ping_CatM_module': - SSH.PingCatM() - elif action == 'Ping': - SSH.Ping() - elif action == 'Iperf': - SSH.Iperf() - elif action == 'Reboot_UE': - SSH.RebootUE() - elif action == 'Initialize_HSS': - SSH.InitializeHSS() - elif action == 'Terminate_HSS': - SSH.TerminateHSS() - elif action == 'Initialize_MME': - SSH.InitializeMME() - elif action == 'Terminate_MME': - SSH.TerminateMME() - elif action == 'Initialize_SPGW': - SSH.InitializeSPGW() - elif action == 'Terminate_SPGW': - SSH.TerminateSPGW() - elif action == 'Initialize_FlexranCtrl': - SSH.InitializeFlexranCtrl() - elif action == 'Terminate_FlexranCtrl': - SSH.TerminateFlexranCtrl() - elif action == 'IdleSleep': - SSH.IdleSleep() - elif action == 'Perform_X2_Handover': - SSH.Perform_X2_Handover() - else: - sys.exit('Invalid action') - SSH.FailReportCnt += 1 - if SSH.FailReportCnt == SSH.repeatCounts[0] and SSH.prematureExit: - logging.debug('Testsuite failed ' + str(SSH.FailReportCnt) + ' time(s)') - SSH.CreateHtmlTabFooter(False) - sys.exit('Failed Scenario') - else: - logging.info('Testsuite passed after ' + str(SSH.FailReportCnt) + ' time(s)') - SSH.CreateHtmlTabFooter(True) -else: - Usage() - sys.exit('Invalid mode') -sys.exit(0) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index c9da55041c..1dd8402250 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -28,48 +28,13 @@ # pexpect #--------------------------------------------------------------------- +import constants as CONST + #----------------------------------------------------------- # Version #----------------------------------------------------------- Version = '0.1' -#----------------------------------------------------------- -# Constants -#----------------------------------------------------------- -ALL_PROCESSES_OK = 0 -ENB_PROCESS_FAILED = -1 -ENB_PROCESS_OK = +1 -ENB_PROCESS_SEG_FAULT = -11 -ENB_PROCESS_ASSERTION = -12 -ENB_PROCESS_REALTIME_ISSUE = -13 -ENB_PROCESS_NOLOGFILE_TO_ANALYZE = -14 -ENB_PROCESS_SLAVE_RRU_NOT_SYNCED = -15 -HSS_PROCESS_FAILED = -2 -HSS_PROCESS_OK = +2 -MME_PROCESS_FAILED = -3 -MME_PROCESS_OK = +3 -SPGW_PROCESS_FAILED = -4 -SPGW_PROCESS_OK = +4 -UE_IP_ADDRESS_ISSUE = -5 -OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE = -20 -OAI_UE_PROCESS_COULD_NOT_SYNC = -21 -OAI_UE_PROCESS_ASSERTION = -22 -OAI_UE_PROCESS_FAILED = -23 -OAI_UE_PROCESS_NO_TUNNEL_INTERFACE = -24 -OAI_UE_PROCESS_SEG_FAULT = -25 -OAI_UE_PROCESS_OK = +6 - -UE_STATUS_DETACHED = 0 -UE_STATUS_DETACHING = 1 -UE_STATUS_ATTACHING = 2 -UE_STATUS_ATTACHED = 3 - -X2_HO_REQ_STATE__IDLE = 0 -X2_HO_REQ_STATE__TARGET_RECEIVES_REQ = 1 -X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE = 2 -X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ = 3 -X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK = 10 - #----------------------------------------------------------- # Import #----------------------------------------------------------- @@ -89,56 +54,22 @@ logging.basicConfig( format="[%(asctime)s] %(name)s:%(levelname)s: %(message)s" ) + #----------------------------------------------------------- # Class Declaration #----------------------------------------------------------- class OaiCiTest(): + def __init__(self): self.FailReportCnt = 0 - self.prematureExit = False - self.ranRepository = '' - self.ranBranch = '' - self.ranAllowMerge = False - self.ranCommitID = '' - self.ranTargetBranch = '' - self.eNBIPAddress = '' - self.eNBUserName = '' - self.eNBPassword = '' - self.eNBSourceCodePath = '' - #self.EPCIPAddress = '' - #self.EPCUserName = '' - #self.EPCPassword = '' - self.eNB1IPAddress = '' - self.eNB1UserName = '' - self.eNB1Password = '' - self.eNB1SourceCodePath = '' - self.eNB2IPAddress = '' - self.eNB2UserName = '' - self.eNB2Password = '' - self.eNB2SourceCodePath = '' - #self.EPCSourceCodePath = '' - #self.EPCType = '' - #self.EPC_PcapFileName = '' self.ADBIPAddress = '' self.ADBUserName = '' self.ADBPassword = '' self.ADBCentralized = True self.testCase_id = '' self.testXMLfiles = [] - self.nbTestXMLfiles = 0 + #self.nbTestXMLfiles = 0 self.desc = '' - self.Build_eNB_args = '' - self.backgroundBuild = False - self.backgroundBuildTestId = ['', '', ''] - self.Build_eNB_forced_workspace_cleanup = False - self.Initialize_eNB_args = '' - self.air_interface = 'lte' - self.eNB_instance = '' - self.eNB_serverId = '' - self.eNBLogFiles = ['', '', ''] - self.eNBOptions = ['', '', ''] - self.eNBmbmsEnables = [False, False, False] - self.eNBstatuses = [-1, -1, -1] self.ping_args = '' self.ping_packetloss_threshold = '' self.iperf_args = '' @@ -156,8 +87,8 @@ class OaiCiTest(): self.CatMDevices = [] self.UEIPAddresses = [] self.htmlFile = '' - self.htmlHeaderCreated = False - self.htmlFooterCreated = False + # self.htmlHeaderCreated = False + # self.htmlFooterCreated = False self.htmlUEConnected = -1 self.htmleNBFailureMsg = '' self.htmlUEFailureMsg = '' @@ -167,9 +98,6 @@ class OaiCiTest(): self.x2NbENBs = 0 self.x2ENBBsIds = [] self.x2ENBConnectedUEs = [] - self.htmlTabRefs = [] - self.htmlTabNames = [] - self.htmlTabIcons = [] self.repeatCounts = [] self.finalStatus = False self.OsVersion = '' @@ -193,214 +121,24 @@ class OaiCiTest(): self.expectedNbOfConnectedUEs = 0 self.startTime = 0 - def BuildeNB(self): - if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - if self.eNB_serverId == '0': - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - lSourcePath = self.eNBSourceCodePath - elif self.eNB_serverId == '1': - lIpAddr = self.eNB1IPAddress - lUserName = self.eNB1UserName - lPassWord = self.eNB1Password - lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId == '2': - lIpAddr = self.eNB2IPAddress - lUserName = self.eNB2UserName - lPassWord = self.eNB2Password - lSourcePath = self.eNB2SourceCodePath - if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - SSH.open(lIpAddr, lUserName, lPassWord) - # Check if we build an 5G-NR gNB or an LTE eNB - result = re.search('--gNB', self.Build_eNB_args) - if result is not None: - self.air_interface = 'nr' - else: - self.air_interface = 'lte' - # Worakround for some servers, we need to erase completely the workspace - if self.Build_eNB_forced_workspace_cleanup: - SSH.command('echo ' + lPassWord + ' | sudo -S rm -Rf ' + lSourcePath, '\$', 15) - # on RedHat/CentOS .git extension is mandatory - result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository) - if result is not None: - full_ran_repo_name = self.ranRepository - else: - full_ran_repo_name = self.ranRepository + '.git' - SSH.command('mkdir -p ' + lSourcePath, '\$', 5) - SSH.command('cd ' + lSourcePath, '\$', 5) - SSH.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + full_ran_repo_name + ' .; else stdbuf -o0 git fetch --prune; fi', '\$', 600) - # Raphael: here add a check if git clone or git fetch went smoothly - SSH.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) - SSH.command('git config user.name "OAI Jenkins"', '\$', 5) - # Checking the BUILD INFO file - if not self.backgroundBuild: - SSH.command('ls *.txt', '\$', 5) - result = re.search('LAST_BUILD_INFO', SSH.getBefore()) - if result is not None: - mismatch = False - SSH.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) - result = re.search(self.ranCommitID, SSH.getBefore()) - if result is None: - mismatch = True - SSH.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) - if (self.ranAllowMerge): - result = re.search('YES', SSH.getBefore()) - if result is None: - mismatch = True - SSH.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) - if self.ranTargetBranch == '': - result = re.search('develop', SSH.getBefore()) - else: - result = re.search(self.ranTargetBranch, SSH.getBefore()) - if result is None: - mismatch = True - else: - result = re.search('NO', SSH.getBefore()) - if result is None: - mismatch = True - if not mismatch: - SSH.close() - self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) - return - - SSH.command('echo ' + lPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30) - # if the commit ID is provided use it to point to it - if self.ranCommitID != '': - SSH.command('git checkout -f ' + self.ranCommitID, '\$', 5) - # if the branch is not develop, then it is a merge request and we need to do - # the potential merge. Note that merge conflicts should already been checked earlier - if (self.ranAllowMerge): - if self.ranTargetBranch == '': - if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'): - SSH.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) - else: - logging.debug('Merging with the target branch: ' + self.ranTargetBranch) - SSH.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5) - SSH.command('source oaienv', '\$', 5) - SSH.command('cd cmake_targets', '\$', 5) - SSH.command('mkdir -p log', '\$', 5) - SSH.command('chmod 777 log', '\$', 5) - # no need to remove in log (git clean did the trick) - if self.backgroundBuild: - SSH.command('echo "./build_oai ' + self.Build_eNB_args + '" > ./my-lte-softmodem-build.sh', '\$', 5) - SSH.command('chmod 775 ./my-lte-softmodem-build.sh', '\$', 5) - SSH.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=build_enb_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/compile_oai_enb.log ./my-lte-softmodem-build.sh', '\$', 5) - SSH.close() - self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) - self.backgroundBuildTestId[int(self.eNB_instance)] = self.testCase_id - return - SSH.command('stdbuf -o0 ./build_oai ' + self.Build_eNB_args + ' 2>&1 | stdbuf -o0 tee compile_oai_enb.log', 'Bypassing the Tests|build have failed', 1500) - self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.testCase_id) - - def WaitBuildeNBisFinished(self): - if self.eNB_serverId == '0': - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - lSourcePath = self.eNBSourceCodePath - elif self.eNB_serverId == '1': - lIpAddr = self.eNB1IPAddress - lUserName = self.eNB1UserName - lPassWord = self.eNB1Password - lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId == '2': - lIpAddr = self.eNB2IPAddress - lUserName = self.eNB2UserName - lPassWord = self.eNB2Password - lSourcePath = self.eNB2SourceCodePath - if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - SSH.open(lIpAddr, lUserName, lPassWord) - count = 40 - buildOAIprocess = True - while (count > 0) and buildOAIprocess: - SSH.command('ps aux | grep --color=never build_ | grep -v grep', '\$', 3) - result = re.search('build_oai', SSH.getBefore()) - if result is None: - buildOAIprocess = False - else: - count -= 1 - time.sleep(30) - self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.backgroundBuildTestId[int(self.eNB_instance)]) - - def checkBuildeNB(self, lIpAddr, lUserName, lPassWord, lSourcePath, testcaseId): - SSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 3) - SSH.command('ls ran_build/build', '\$', 3) - SSH.command('ls ran_build/build', '\$', 3) - if self.air_interface == 'nr': - nodeB_prefix = 'g' - else: - nodeB_prefix = 'e' - buildStatus = True - result = re.search(self.air_interface + '-softmodem', SSH.getBefore()) - if result is None: - buildStatus = False - else: - # Generating a BUILD INFO file - SSH.command('echo "SRC_BRANCH: ' + self.ranBranch + '" > ../LAST_BUILD_INFO.txt', '\$', 2) - SSH.command('echo "SRC_COMMIT: ' + self.ranCommitID + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) - if (self.ranAllowMerge): - SSH.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2) - if self.ranTargetBranch == '': - SSH.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2) - else: - SSH.command('echo "TGT_BRANCH: ' + self.ranTargetBranch + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) - else: - SSH.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) - SSH.command('mkdir -p build_log_' + testcaseId, '\$', 5) - SSH.command('mv log/* ' + 'build_log_' + testcaseId, '\$', 5) - SSH.command('mv compile_oai_enb.log ' + 'build_log_' + testcaseId, '\$', 5) - if self.eNB_serverId != '0': - SSH.command('cd cmake_targets', '\$', 5) - SSH.command('if [ -e tmp_build' + testcaseId + '.zip ]; then rm -f tmp_build' + testcaseId + '.zip; fi', '\$', 5) - SSH.command('zip -r -qq tmp_build' + testcaseId + '.zip build_log_' + testcaseId, '\$', 5) - SSH.close() - if (os.path.isfile('./tmp_build' + testcaseId + '.zip')): - os.remove('./tmp_build' + testcaseId + '.zip') - SSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/tmp_build' + testcaseId + '.zip', '.') - if (os.path.isfile('./tmp_build' + testcaseId + '.zip')): - SSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './tmp_build' + testcaseId + '.zip', self.eNBSourceCodePath + '/cmake_targets/.') - os.remove('./tmp_build' + testcaseId + '.zip') - SSH.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) - SSH.command('cd ' + self.eNBSourceCodePath + '/cmake_targets', '\$', 5) - SSH.command('unzip -qq -DD tmp_build' + testcaseId + '.zip', '\$', 5) - SSH.command('rm -f tmp_build' + testcaseId + '.zip', '\$', 5) - SSH.close() - else: - SSH.close() - - if buildStatus: - logging.info('\u001B[1m Building OAI ' + nodeB_prefix + 'NB Pass\u001B[0m') - self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) - else: - logging.error('\u001B[1m Building OAI ' + nodeB_prefix + 'NB Failed\u001B[0m') - self.CreateHtmlTestRow(self.Build_eNB_args, 'KO', ALL_PROCESSES_OK) - self.CreateHtmlTabFooter(False) - sys.exit(1) def BuildOAIUE(self): - if self.UEIPAddress == '' or self.ranRepository == '' or self.ranBranch == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': + if self.UEIPAddress == '' or RAN.GetranRepository() == '' or RAN.GetranBranch() == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': GenericHelp(Version) sys.exit('Insufficient Parameter') SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) result = re.search('--nrUE', self.Build_OAI_UE_args) if result is not None: - self.air_interface = 'nr' + RAN.Setair_interface('nr') ue_prefix = 'NR ' else: - self.air_interface = 'lte' + RAN.Setair_interface('lte') ue_prefix = '' - result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository) + result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', RAN.GetranRepository()) if result is not None: - full_ran_repo_name = self.ranRepository + full_ran_repo_name = RAN.GetranRepository() else: - full_ran_repo_name = self.ranRepository + '.git' + full_ran_repo_name = RAN.GetranRepository() + '.git' SSH.command('mkdir -p ' + self.UESourceCodePath, '\$', 5) SSH.command('cd ' + self.UESourceCodePath, '\$', 5) SSH.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + full_ran_repo_name + ' .; else stdbuf -o0 git fetch --prune; fi', '\$', 600) @@ -413,19 +151,19 @@ class OaiCiTest(): if result is not None: mismatch = False SSH.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) - result = re.search(self.ranCommitID, SSH.getBefore()) + result = re.search(RAN.GetranCommitID(), SSH.getBefore()) if result is None: mismatch = True SSH.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) - if (self.ranAllowMerge): + if (RAN.GetranAllowMerge()): result = re.search('YES', SSH.getBefore()) if result is None: mismatch = True SSH.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) - if self.ranTargetBranch == '': + if RAN.GetranTargetBranch() == '': result = re.search('develop', SSH.getBefore()) else: - result = re.search(self.ranTargetBranch, SSH.getBefore()) + result = re.search(RAN.GetranTargetBranch(), SSH.getBefore()) if result is None: mismatch = True else: @@ -434,23 +172,23 @@ class OaiCiTest(): mismatch = True if not mismatch: SSH.close() - self.CreateHtmlTestRow(self.Build_eNB_args, 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(RAN.GetBuild_eNB_args(), 'OK', CONST.ALL_PROCESSES_OK) return SSH.command('echo ' + self.UEPassword + ' | sudo -S git clean -x -d -ff', '\$', 30) # if the commit ID is provided use it to point to it - if self.ranCommitID != '': - SSH.command('git checkout -f ' + self.ranCommitID, '\$', 5) + if RAN.GetranCommitID() != '': + SSH.command('git checkout -f ' + RAN.GetranCommitID(), '\$', 5) # if the branch is not develop, then it is a merge request and we need to do # the potential merge. Note that merge conflicts should already been checked earlier - if (self.ranAllowMerge): - if self.ranTargetBranch == '': - if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'): + if (RAN.GetranAllowMerge()): + if RAN.GetranTargetBranch() == '': + if (RAN.GetranBranch() != 'develop') and (RAN.GetranBranch() != 'origin/develop'): SSH.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) else: - logging.debug('Merging with the target branch: ' + self.ranTargetBranch) - SSH.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5) + logging.debug('Merging with the target branch: ' + RAN.GetranTargetBranch()) + SSH.command('git merge --ff origin/' + RAN.GetranTargetBranch() + ' -m "Temporary merge for CI"', '\$', 5) SSH.command('source oaienv', '\$', 5) SSH.command('cd cmake_targets', '\$', 5) SSH.command('mkdir -p log', '\$', 5) @@ -460,7 +198,7 @@ class OaiCiTest(): SSH.command('ls ran_build/build', '\$', 3) SSH.command('ls ran_build/build', '\$', 3) buildStatus = True - result = re.search(self.air_interface + '-uesoftmodem', SSH.getBefore()) + result = re.search(RAN.Getair_interface() + '-uesoftmodem', SSH.getBefore()) if result is None: buildStatus = False SSH.command('mkdir -p build_log_' + self.testCase_id, '\$', 5) @@ -468,23 +206,23 @@ class OaiCiTest(): SSH.command('mv compile_oai_ue.log ' + 'build_log_' + self.testCase_id, '\$', 5) if buildStatus: # Generating a BUILD INFO file - SSH.command('echo "SRC_BRANCH: ' + self.ranBranch + '" > ../LAST_BUILD_INFO.txt', '\$', 2) - SSH.command('echo "SRC_COMMIT: ' + self.ranCommitID + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) - if (self.ranAllowMerge): + SSH.command('echo "SRC_BRANCH: ' + RAN.GetranBranch() + '" > ../LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('echo "SRC_COMMIT: ' + RAN.GetranCommitID() + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) + if (RAN.GetranAllowMerge()): SSH.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2) - if self.ranTargetBranch == '': + if RAN.GetranTargetBranch() == '': SSH.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2) else: - SSH.command('echo "TGT_BRANCH: ' + self.ranTargetBranch + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('echo "TGT_BRANCH: ' + RAN.GetranTargetBranch() + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) else: SSH.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) SSH.close() - self.CreateHtmlTestRow(self.Build_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE') + HTML.CreateHtmlTestRow(self.Build_OAI_UE_args, 'OK', CONST.ALL_PROCESSES_OK, 'OAI UE') else: SSH.close() logging.error('\u001B[1m Building OAI UE Failed\u001B[0m') - self.CreateHtmlTestRow(self.Build_OAI_UE_args, 'KO', ALL_PROCESSES_OK, 'OAI UE') - self.CreateHtmlTabFooter(False) + HTML.CreateHtmlTestRow(self.Build_OAI_UE_args, 'KO', CONST.ALL_PROCESSES_OK, 'OAI UE') + HTML.CreateHtmlTabFooter(False) sys.exit(1) def CheckFlexranCtrlInstallation(self): @@ -495,6 +233,7 @@ class OaiCiTest(): result = re.search('/opt/flexran_rtc/build/rt_controller', SSH.getBefore()) if result is not None: self.flexranCtrlInstalled = True + RAN.SetflexranCtrlInstalled(True) logging.debug('Flexran Controller is installed') SSH.close() @@ -515,187 +254,10 @@ class OaiCiTest(): if result is not None: logging.debug('\u001B[1m Initialize FlexRan Controller Completed\u001B[0m') self.flexranCtrlStarted = True + RAN.SetflexranCtrlStarted(True) SSH.close() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - - def InitializeeNB(self): - if self.eNB_serverId == '0': - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - lSourcePath = self.eNBSourceCodePath - elif self.eNB_serverId == '1': - lIpAddr = self.eNB1IPAddress - lUserName = self.eNB1UserName - lPassWord = self.eNB1Password - lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId == '2': - lIpAddr = self.eNB2IPAddress - lUserName = self.eNB2UserName - lPassWord = self.eNB2Password - lSourcePath = self.eNB2SourceCodePath - if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - check_eNB = False - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - self.CreateHtmlTestRow(self.Initialize_eNB_args, 'KO', pStatus) - self.CreateHtmlTabFooter(False) - sys.exit(1) - # If tracer options is on, running tshark on EPC side and capture traffic b/ EPC and eNB - result = re.search('T_stdout', str(self.Initialize_eNB_args)) - if result is not None: - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('ip addr show | awk -f /tmp/active_net_interfaces.awk | egrep -v "lo|tun"', '\$', 5) - result = re.search('interfaceToUse=(?P[a-zA-Z0-9\-\_]+)done', SSH.getBefore()) - if result is not None: - eth_interface = result.group('eth_interface') - logging.debug('\u001B[1m Launching tshark on interface ' + eth_interface + '\u001B[0m') - EPC.EPC_PcapFileName = 'enb_' + self.testCase_id + '_s1log.pcap' - SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S rm -f /tmp/' + EPC.EPC_PcapFileName , '\$', 5) - SSH.command('echo $USER; nohup sudo tshark -f "host ' + lIpAddr +'" -i ' + eth_interface + ' -w /tmp/' + EPC.EPC_PcapFileName + ' > /tmp/tshark.log 2>&1 &', EPC.GetUserName(), 5) - SSH.close() - SSH.open(lIpAddr, lUserName, lPassWord) - SSH.command('cd ' + lSourcePath, '\$', 5) - # Initialize_eNB_args usually start with -O and followed by the location in repository - full_config_file = self.Initialize_eNB_args.replace('-O ','') - extra_options = '' - extIdx = full_config_file.find('.conf') - if (extIdx > 0): - extra_options = full_config_file[extIdx + 5:] - # if tracer options is on, compiling and running T Tracer - result = re.search('T_stdout', str(extra_options)) - if result is not None: - logging.debug('\u001B[1m Compiling and launching T Tracer\u001B[0m') - SSH.command('cd common/utils/T/tracer', '\$', 5) - SSH.command('make', '\$', 10) - SSH.command('echo $USER; nohup ./record -d ../T_messages.txt -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.raw -ON -off VCD -off HEAVY -off LEGACY_GROUP_TRACE -off LEGACY_GROUP_DEBUG > ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '_record.log 2>&1 &', lUserName, 5) - SSH.command('cd ' + lSourcePath, '\$', 5) - full_config_file = full_config_file[:extIdx + 5] - config_path, config_file = os.path.split(full_config_file) - else: - sys.exit('Insufficient Parameter') - ci_full_config_file = config_path + '/ci-' + config_file - rruCheck = False - result = re.search('^rru|^rcc|^du.band', str(config_file)) - if result is not None: - rruCheck = True - # do not reset board twice in IF4.5 case - result = re.search('^rru|^enb|^du.band', str(config_file)) - if result is not None: - SSH.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 60) - result = re.search('type: b200', SSH.getBefore()) - if result is not None: - logging.debug('Found a B2xx device --> resetting it') - SSH.command('echo ' + lPassWord + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10) - # Reloading FGPA bin firmware - SSH.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 60) - # Make a copy and adapt to EPC / eNB IP addresses - SSH.command('cp ' + full_config_file + ' ' + ci_full_config_file, '\$', 5) - SSH.command('sed -i -e \'s/CI_MME_IP_ADDR/' + EPC.GetIPAddress() + '/\' ' + ci_full_config_file, '\$', 2); - SSH.command('sed -i -e \'s/CI_ENB_IP_ADDR/' + lIpAddr + '/\' ' + ci_full_config_file, '\$', 2); - SSH.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2); - SSH.command('sed -i -e \'s/CI_RRU1_IP_ADDR/' + self.eNB1IPAddress + '/\' ' + ci_full_config_file, '\$', 2); - SSH.command('sed -i -e \'s/CI_RRU2_IP_ADDR/' + self.eNB2IPAddress + '/\' ' + ci_full_config_file, '\$', 2); - if self.flexranCtrlInstalled and self.flexranCtrlStarted: - SSH.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "yes";/\' ' + ci_full_config_file, '\$', 2); - else: - SSH.command('sed -i -e \'s/FLEXRAN_ENABLED.*;/FLEXRAN_ENABLED = "no";/\' ' + ci_full_config_file, '\$', 2); - self.eNBmbmsEnables[int(self.eNB_instance)] = False - SSH.command('grep enable_enb_m2 ' + ci_full_config_file, '\$', 2); - result = re.search('yes', SSH.getBefore()) - if result is not None: - self.eNBmbmsEnables[int(self.eNB_instance)] = True - logging.debug('\u001B[1m MBMS is enabled on this eNB\u001B[0m') - result = re.search('noS1', str(self.Initialize_eNB_args)) - eNBinNoS1 = False - if result is not None: - eNBinNoS1 = True - logging.debug('\u001B[1m eNB is in noS1 configuration \u001B[0m') - # Launch eNB with the modified config file - SSH.command('source oaienv', '\$', 5) - SSH.command('cd cmake_targets', '\$', 5) - SSH.command('echo "ulimit -c unlimited && ./ran_build/build/' + self.air_interface + '-softmodem -O ' + lSourcePath + '/' + ci_full_config_file + extra_options + '" > ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - SSH.command('chmod 775 ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - SSH.command('echo ' + lPassWord + ' | sudo -S rm -Rf enb_' + self.testCase_id + '.log', '\$', 5) - SSH.command('hostnamectl','\$', 5) - result = re.search('CentOS Linux 7', SSH.getBefore()) - if result is not None: - SSH.command('echo $USER; nohup sudo ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh > ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log 2>&1 &', lUserName, 10) - else: - SSH.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=enb' + str(self.eNB_instance) + '_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/enb_' + self.testCase_id + '.log ./my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - self.eNBLogFiles[int(self.eNB_instance)] = 'enb_' + self.testCase_id + '.log' - if extra_options != '': - self.eNBOptions[int(self.eNB_instance)] = extra_options - time.sleep(6) - doLoop = True - loopCounter = 20 - enbDidSync = False - while (doLoop): - loopCounter = loopCounter - 1 - if (loopCounter == 0): - # In case of T tracer recording, we may need to kill it - result = re.search('T_stdout', str(self.Initialize_eNB_args)) - if result is not None: - SSH.command('killall --signal SIGKILL record', '\$', 5) - SSH.close() - doLoop = False - logging.error('\u001B[1;37;41m eNB logging system did not show got sync! \u001B[0m') - self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'KO', ALL_PROCESSES_OK) - # In case of T tracer recording, we need to kill tshark on EPC side - result = re.search('T_stdout', str(self.Initialize_eNB_args)) - if result is not None: - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - logging.debug('\u001B[1m Stopping tshark \u001B[0m') - SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) - if EPC.EPC_PcapFileName != '': - time.sleep(0.5) - SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S chmod 666 /tmp/' + EPC.EPC_PcapFileName , '\$', 5) - SSH.close() - time.sleep(1) - if EPC.EPC_PcapFileName != '': - copyin_res = SSH.copyin(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), '/tmp/' + EPC.EPC_PcapFileName , '.') - if (copyin_res == 0): - SSH.copyout(lIpAddr, lUserName, lPassWord, EPC.EPC_PcapFileName , lSourcePath + '/cmake_targets/.') - self.prematureExit = True - return - else: - SSH.command('stdbuf -o0 cat enb_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync|Starting"', '\$', 4) - if rruCheck: - result = re.search('wait RUs', SSH.getBefore()) - else: - result = re.search('got sync|Starting F1AP at CU', SSH.getBefore()) - if result is None: - time.sleep(6) - else: - doLoop = False - enbDidSync = True - time.sleep(10) - - if enbDidSync and eNBinNoS1: - SSH.command('ifconfig oaitun_enb1', '\$', 4) - SSH.command('ifconfig oaitun_enb1', '\$', 4) - result = re.search('inet addr:1|inet 1', SSH.getBefore()) - if result is not None: - logging.debug('\u001B[1m oaitun_enb1 interface is mounted and configured\u001B[0m') - else: - logging.error('\u001B[1m oaitun_enb1 interface is either NOT mounted or NOT configured\u001B[0m') - if self.eNBmbmsEnables[int(self.eNB_instance)]: - SSH.command('ifconfig oaitun_enm1', '\$', 4) - result = re.search('inet addr', SSH.getBefore()) - if result is not None: - logging.debug('\u001B[1m oaitun_enm1 interface is mounted and configured\u001B[0m') - else: - logging.error('\u001B[1m oaitun_enm1 interface is either NOT mounted or NOT configured\u001B[0m') - if enbDidSync: - self.eNBstatuses[int(self.eNB_instance)] = int(self.eNB_serverId) - - SSH.close() - self.CreateHtmlTestRow('-O ' + config_file + extra_options, 'OK', ALL_PROCESSES_OK) - logging.debug('\u001B[1m Initialize eNB Completed\u001B[0m') - + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + def InitializeUE_common(self, device_id, idx): try: SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) @@ -757,21 +319,21 @@ class OaiCiTest(): i += 1 for job in multi_jobs: job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def InitializeOAIUE(self): if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': GenericHelp(Version) sys.exit('Insufficient Parameter') - if self.air_interface == 'lte': + if RAN.Getair_interface() == 'lte': result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) if result is None: check_eNB = True check_OAI_UE = False pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', pStatus) - self.CreateHtmlTabFooter(False) + HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', pStatus) + HTML.CreateHtmlTabFooter(False) sys.exit(1) UE_prefix = '' else: @@ -792,7 +354,7 @@ class OaiCiTest(): # Initialize_OAI_UE_args usually start with -C and followed by the location in repository SSH.command('source oaienv', '\$', 5) SSH.command('cd cmake_targets/ran_build/build', '\$', 5) - if self.air_interface == 'lte': + if RAN.Getair_interface() == 'lte': result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) # We may have to regenerate the .u* files if result is None: @@ -804,7 +366,7 @@ class OaiCiTest(): SSH.command('sed -e "s#93#92#" -e "s#8baf473f2f8fd09487cccbd7097c6862#fec86ba6eb707ed08905757b1bb44b8f#" -e "s#e734f8734007d6c5ce7a0508809e7e9c#C42449363BBAD02B66D16BC975D77CC1#" ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5) SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf .u*', '\$', 5) SSH.command('echo ' + self.UEPassword + ' | sudo -S ../../../targets/bin/conf2uedata -c ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf -o .', '\$', 5) - SSH.command('echo "ulimit -c unlimited && ./'+ self.air_interface +'-uesoftmodem ' + self.Initialize_OAI_UE_args + '" > ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) + SSH.command('echo "ulimit -c unlimited && ./'+ RAN.Getair_interface() +'-uesoftmodem ' + self.Initialize_OAI_UE_args + '" > ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) SSH.command('chmod 775 ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log', '\$', 5) self.UELogFile = 'ue_' + self.testCase_id + '.log' @@ -835,7 +397,7 @@ class OaiCiTest(): doLoop = False continue SSH.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4) - if self.air_interface == 'nr': + if RAN.Getair_interface() == 'nr': result = re.search('Starting sync detection', SSH.getBefore()) else: result = re.search('got sync', SSH.getBefore()) @@ -852,7 +414,7 @@ class OaiCiTest(): SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT -r *-uesoftmodem', '\$', 4) time.sleep(3) continue - if self.air_interface == 'nr': + if RAN.Getair_interface() == 'nr': fullSyncStatus = True doOutterLoop = False else: @@ -885,7 +447,7 @@ class OaiCiTest(): if (outterLoopCounter == 0): doOutterLoop = False - if fullSyncStatus and gotSyncStatus and self.air_interface == 'lte': + if fullSyncStatus and gotSyncStatus and RAN.Getair_interface() == 'lte': result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) if result is None: SSH.command('ifconfig oaitun_ue1', '\$', 4) @@ -899,7 +461,7 @@ class OaiCiTest(): logging.debug(SSH.getBefore()) logging.error('\u001B[1m oaitun_ue1 interface is either NOT mounted or NOT configured\u001B[0m') tunnelInterfaceStatus = False - if self.eNBmbmsEnables[0]: + if RAN.GeteNBmbmsEnables[0]: self.command('ifconfig oaitun_uem1', '\$', 4) result = re.search('inet addr', SSH.getBefore()) if result is not None: @@ -915,23 +477,23 @@ class OaiCiTest(): SSH.close() if fullSyncStatus and gotSyncStatus and tunnelInterfaceStatus: - self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'OK', ALL_PROCESSES_OK, 'OAI UE') + HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'OK', CONST.ALL_PROCESSES_OK, 'OAI UE') logging.debug('\u001B[1m Initialize OAI UE Completed\u001B[0m') if (self.ADBIPAddress != 'none'): self.UEDevices = [] self.UEDevices.append('OAI-UE') self.UEDevicesStatus = [] - self.UEDevicesStatus.append(UE_STATUS_DETACHED) + self.UEDevicesStatus.append(CONST.UE_STATUS_DETACHED) else: - if self.air_interface == 'lte': - if self.eNBmbmsEnables[0]: + if RAN.Getair_interface() == 'lte': + if RAN.GeteNBmbmsEnables[0]: self.htmlUEFailureMsg = 'oaitun_ue1/oaitun_uem1 interfaces are either NOT mounted or NOT configured' else: self.htmlUEFailureMsg = 'oaitun_ue1 interface is either NOT mounted or NOT configured' - self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', OAI_UE_PROCESS_NO_TUNNEL_INTERFACE, 'OAI UE') + HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', CONST.OAI_UE_PROCESS_NO_TUNNEL_INTERFACE, 'OAI UE') else: self.htmlUEFailureMsg = 'nr-uesoftmodem did NOT synced' - self.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', OAI_UE_PROCESS_COULD_NOT_SYNC, 'OAI UE') + HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', CONST.OAI_UE_PROCESS_COULD_NOT_SYNC, 'OAI UE') logging.error('\033[91mInitialize OAI UE Failed! \033[0m') self.AutoTerminateUEandeNB() @@ -961,6 +523,11 @@ class OaiCiTest(): # Calling twice AT to clear all buffers SSH.command('AT', 'OK|ERROR', 5) SSH.command('AT', 'OK', 5) + # Doing a power cycle + self.command('AT^RESET', 'SIMSTORE,READY', 15) + self.command('AT', 'OK|ERROR', 5) + self.command('AT', 'OK', 5) + self.command('ATE1', 'OK', 5) # Disabling the Radio SSH.command('AT+CFUN=0', 'OK', 5) logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') @@ -979,7 +546,7 @@ class OaiCiTest(): # Force closure of picocom but device might still be locked SSH.close() self.picocom_closure = False - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) self.checkDevTTYisUnlocked() def TerminateCatM(self): @@ -1000,7 +567,7 @@ class OaiCiTest(): logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') SSH.close() self.picocom_closure = False - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) self.checkDevTTYisUnlocked() def AttachCatM(self): @@ -1069,12 +636,12 @@ class OaiCiTest(): else: html_cell += '' html_queue.put(html_cell) - self.CreateHtmlTestRowQueue('N/A', 'OK', 1, html_queue) + HTML.CreateHtmlTestRowQueue('N/A', 'OK', 1, html_queue) else: logging.error('\u001B[1m CAT-M module Attachment Failed\u001B[0m') html_cell = '
CAT-M module Attachment Failed
' html_queue.put(html_cell) - self.CreateHtmlTestRowQueue('N/A', 'KO', 1, html_queue) + HTML.CreateHtmlTestRowQueue('N/A', 'KO', 1, html_queue) self.AutoTerminateUEandeNB() def PingCatM(self): @@ -1085,7 +652,7 @@ class OaiCiTest(): check_OAI_UE = False pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) self.AutoTerminateUEandeNB() return try: @@ -1096,8 +663,8 @@ class OaiCiTest(): SSH.command('cd scripts', '\$', 5) if re.match('OAI', EPC.GetType(), re.IGNORECASE): logging.debug('Using the OAI EPC HSS: not implemented yet') - self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) - self.CreateHtmlTabFooter(False) + HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + HTML.CreateHtmlTabFooter(False) sys.exit(1) else: SSH.command('egrep --color=never "Allocated ipv4 addr" /opt/ltebox/var/log/xGwLog.0', '\$', 5) @@ -1105,7 +672,7 @@ class OaiCiTest(): if result is not None: moduleIPAddr = result.group('ipaddr') else: - self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) self.AutoTerminateUEandeNB() return ping_time = re.findall("-c (\d+)",str(self.ping_args)) @@ -1167,9 +734,9 @@ class OaiCiTest(): html_cell = '
CAT-M module\nIP Address  : ' + moduleIPAddr + '\n' + qMsg + '
' statusQueue.put(html_cell) if (packetLossOK): - self.CreateHtmlTestRowQueue(self.ping_args, 'OK', 1, statusQueue) + HTML.CreateHtmlTestRowQueue(self.ping_args, 'OK', 1, statusQueue) else: - self.CreateHtmlTestRowQueue(self.ping_args, 'KO', 1, statusQueue) + HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', 1, statusQueue) self.AutoTerminateUEandeNB() except: os.kill(os.getppid(),signal.SIGUSR1) @@ -1193,6 +760,7 @@ class OaiCiTest(): SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry" | grep -m 1 mDataConnectionState', '\$', 15) else: SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\' | grep -m 1 mDataConnectionState', '\$', 60) + print('#GP: in SSH.getBefore() K=0 (it was K=2 in main.py)') result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', SSH.getBefore()) if result is None: logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m') @@ -1251,7 +819,7 @@ class OaiCiTest(): check_OAI_UE = False pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow('N/A', 'KO', pStatus) + HTML.CreateHtmlTestRow('N/A', 'KO', pStatus) self.AutoTerminateUEandeNB() return multi_jobs = [] @@ -1260,7 +828,7 @@ class OaiCiTest(): nb_ue_to_connect = 0 for device_id in self.UEDevices: if (self.nbMaxUEtoAttach == -1) or (nb_ue_to_connect < self.nbMaxUEtoAttach): - self.UEDevicesStatus[nb_ue_to_connect] = UE_STATUS_ATTACHING + self.UEDevicesStatus[nb_ue_to_connect] = CONST.UE_STATUS_ATTACHING p = Process(target = self.AttachUE_common, args = (device_id, status_queue, lock,nb_ue_to_connect,)) p.daemon = True p.start() @@ -1270,7 +838,7 @@ class OaiCiTest(): job.join() if (status_queue.empty()): - self.CreateHtmlTestRow('N/A', 'KO', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ALL_PROCESSES_OK) self.AutoTerminateUEandeNB() return else: @@ -1290,16 +858,16 @@ class OaiCiTest(): if (attach_status): cnt = 0 while cnt < len(self.UEDevices): - if self.UEDevicesStatus[cnt] == UE_STATUS_ATTACHING: - self.UEDevicesStatus[cnt] = UE_STATUS_ATTACHED + if self.UEDevicesStatus[cnt] == CONST.UE_STATUS_ATTACHING: + self.UEDevicesStatus[cnt] = CONST.UE_STATUS_ATTACHED cnt += 1 - self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) - result = re.search('T_stdout', str(self.Initialize_eNB_args)) + HTML.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) + result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args())) if result is not None: logging.debug('Waiting 5 seconds to fill up record file') time.sleep(5) else: - self.CreateHtmlTestRowQueue('N/A', 'KO', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue('N/A', 'KO', len(self.UEDevices), html_queue) self.AutoTerminateUEandeNB() def DetachUE_common(self, device_id, idx): @@ -1325,13 +893,13 @@ class OaiCiTest(): check_OAI_UE = False pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow('N/A', 'KO', pStatus) + HTML.CreateHtmlTestRow('N/A', 'KO', pStatus) self.AutoTerminateUEandeNB() return multi_jobs = [] cnt = 0 for device_id in self.UEDevices: - self.UEDevicesStatus[cnt] = UE_STATUS_DETACHING + self.UEDevicesStatus[cnt] = CONST.UE_STATUS_DETACHING p = Process(target = self.DetachUE_common, args = (device_id,cnt,)) p.daemon = True p.start() @@ -1339,14 +907,14 @@ class OaiCiTest(): cnt += 1 for job in multi_jobs: job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - result = re.search('T_stdout', str(self.Initialize_eNB_args)) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args())) if result is not None: logging.debug('Waiting 5 seconds to fill up record file') time.sleep(5) cnt = 0 while cnt < len(self.UEDevices): - self.UEDevicesStatus[cnt] = UE_STATUS_DETACHED + self.UEDevicesStatus[cnt] = CONST.UE_STATUS_DETACHED cnt += 1 def RebootUE_common(self, device_id): @@ -1396,8 +964,8 @@ class OaiCiTest(): check_OAI_UE = False pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow('N/A', 'KO', pStatus) - self.CreateHtmlTabFooter(False) + HTML.CreateHtmlTestRow('N/A', 'KO', pStatus) + HTML.CreateHtmlTabFooter(False) sys.exit(1) multi_jobs = [] for device_id in self.UEDevices: @@ -1407,7 +975,7 @@ class OaiCiTest(): multi_jobs.append(p) for job in multi_jobs: job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def DataDisableUE_common(self, device_id, idx): try: @@ -1436,7 +1004,7 @@ class OaiCiTest(): i += 1 for job in multi_jobs: job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def DataEnableUE_common(self, device_id, idx): try: @@ -1465,7 +1033,7 @@ class OaiCiTest(): i += 1 for job in multi_jobs: job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def GetAllUEDevices(self, terminate_ue_flag): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': @@ -1501,14 +1069,16 @@ class OaiCiTest(): self.UEDevicesRebootCmd.append(comma_split[5]) phone_list_file.close() - if terminate_ue_flag == False: + if terminate_ue_flag == True: + print('terminate_ue_flag == True') if len(self.UEDevices) == 0: logging.debug('\u001B[1;37;41m UE Not Found! \u001B[0m') sys.exit(1) if len(self.UEDevicesStatus) == 0: + print('len(self.UEDevicesStatus) == 0') cnt = 0 while cnt < len(self.UEDevices): - self.UEDevicesStatus.append(UE_STATUS_DETACHED) + self.UEDevicesStatus.append(CONST.UE_STATUS_DETACHED) cnt += 1 def GetAllCatMDevices(self, terminate_ue_flag): @@ -1528,7 +1098,7 @@ class OaiCiTest(): SSH.close() if result is not None: logging.debug('Found a module list file on ADB server') - if terminate_ue_flag == False: + if terminate_ue_flag == True: if len(self.CatMDevices) == 0: logging.debug('\u001B[1;37;41m CAT-M UE Not Found! \u001B[0m') sys.exit(1) @@ -1591,8 +1161,8 @@ class OaiCiTest(): check_OAI_UE = False pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow('N/A', 'KO', pStatus) - self.CreateHtmlTabFooter(False) + HTML.CreateHtmlTestRow('N/A', 'KO', pStatus) + HTML.CreateHtmlTabFooter(False) sys.exit(1) multi_jobs = [] lock = Lock() @@ -1628,7 +1198,7 @@ class OaiCiTest(): htmlOptions = 'N/A' if (status_queue.empty()): - self.CreateHtmlTestRow(htmlOptions, 'KO', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(htmlOptions, 'KO', CONST.ALL_PROCESSES_OK) self.AutoTerminateUEandeNB() else: check_status = True @@ -1642,9 +1212,9 @@ class OaiCiTest(): html_cell = '
UE (' + device_id + ')\n' + message + '
' html_queue.put(html_cell) if check_status and passStatus: - self.CreateHtmlTestRowQueue(htmlOptions, 'OK', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(htmlOptions, 'OK', len(self.UEDevices), html_queue) else: - self.CreateHtmlTestRowQueue(htmlOptions, 'KO', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(htmlOptions, 'KO', len(self.UEDevices), html_queue) self.AutoTerminateUEandeNB() def GetAllUEIPAddresses(self): @@ -1675,7 +1245,8 @@ class OaiCiTest(): SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) idx = 0 for device_id in self.UEDevices: - if self.UEDevicesStatus[idx] != UE_STATUS_ATTACHED: + print('UE status attched'+CONST.UE_STATUS_ATTACHED) + if self.UEDevicesStatus[idx] != CONST.UE_STATUS_ATTACHED: idx += 1 continue count = 0 @@ -1804,19 +1375,19 @@ class OaiCiTest(): html_queue = SimpleQueue() html_cell = '
OAI UE ping result\n' + qMsg + '
' html_queue.put(html_cell) - self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) def PingNoS1(self): check_eNB = True check_OAI_UE = True pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) self.AutoTerminateUEandeNB() return ping_from_eNB = re.search('oaitun_enb1', str(self.ping_args)) if ping_from_eNB is not None: - if self.eNBIPAddress == '' or self.eNBUserName == '' or self.eNBPassword == '': + if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '': GenericHelp(Version) sys.exit('Insufficient Parameter') else: @@ -1825,8 +1396,8 @@ class OaiCiTest(): sys.exit('Insufficient Parameter') try: if ping_from_eNB is not None: - SSH.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) - SSH.command('cd ' + self.eNBSourceCodePath + '/cmake_targets/', '\$', 5) + SSH.open(RAN.GeteNBIPAddress, RAN.GeteNBUserName, RAN.GeteNBPassword) + SSH.command('cd ' + RAN.GeteNBSourceCodePath() + '/cmake_targets/', '\$', 5) else: SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets/', '\$', 5) @@ -1884,13 +1455,13 @@ class OaiCiTest(): html_cell = '
OAI UE ping result\n' + qMsg + '
' html_queue.put(html_cell) if packetLossOK: - self.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) else: - self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) # copying on the EPC server for logCollection if ping_from_eNB is not None: - copyin_res = SSH.copyin(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.eNBSourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') + copyin_res = SSH.copyin(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath() + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') else: copyin_res = SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') if (copyin_res == 0): @@ -1899,7 +1470,7 @@ class OaiCiTest(): os.kill(os.getppid(),signal.SIGUSR1) def Ping(self): - result = re.search('noS1', str(self.Initialize_eNB_args)) + result = re.search('noS1', str(RAN.GetInitialize_eNB_args())) if result is not None: self.PingNoS1() return @@ -1913,12 +1484,12 @@ class OaiCiTest(): check_OAI_UE = False pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) + HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) self.AutoTerminateUEandeNB() return ueIpStatus = self.GetAllUEIPAddresses() if (ueIpStatus < 0): - self.CreateHtmlTestRow(self.ping_args, 'KO', UE_IP_ADDRESS_ISSUE) + HTML.CreateHtmlTestRow(self.ping_args, 'KO', CONST.UE_IP_ADDRESS_ISSUE) self.AutoTerminateUEandeNB() return multi_jobs = [] @@ -1936,7 +1507,7 @@ class OaiCiTest(): job.join() if (status_queue.empty()): - self.CreateHtmlTestRow(self.ping_args, 'KO', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.ping_args, 'KO', CONST.ALL_PROCESSES_OK) self.AutoTerminateUEandeNB() else: ping_status = True @@ -1951,9 +1522,9 @@ class OaiCiTest(): html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' html_queue.put(html_cell) if (ping_status): - self.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) else: - self.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) self.AutoTerminateUEandeNB() def Iperf_ComputeTime(self): @@ -2342,6 +1913,7 @@ class OaiCiTest(): def Iperf_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue): try: + logging.debug('entring Iperf_common') # Single-UE profile -- iperf only on one UE if self.iperf_profile == 'single-ue' and idx != 0: return @@ -2352,7 +1924,7 @@ class OaiCiTest(): if (device_id != 'OAI-UE'): SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) # if by chance ADB server and EPC are on the same remote host, at least log collection will take care of it - SSH.command('if [ ! -d ' + EPC.GetSourceCodePath() + '/scripts ]; then mkdir -p ' + self.EPCSourceCodePath + '/scripts ; fi', '\$', 5) + SSH.command('if [ ! -d ' + EPC.GetSourceCodePath() + '/scripts ]; then mkdir -p ' + EPC.GetSourceCodePath() + '/scripts ; fi', '\$', 5) SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) # Checking if iperf / iperf3 are installed if self.ADBCentralized: @@ -2514,6 +2086,9 @@ class OaiCiTest(): else: SSH.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, EPC.GetSourceCodePath() + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') SSH.command('fromdos -o iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) + # fromdos has to be called on the python executor not on ADB server + cmd = 'fromdos -o iperf_server_' + self.testCase_id + '_' + device_id + '.log' + subprocess.run(cmd, shell=True) self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) # in case of OAI UE: @@ -2528,21 +2103,21 @@ class OaiCiTest(): os.kill(os.getppid(),signal.SIGUSR1) def IperfNoS1(self): - if self.eNBIPAddress == '' or self.eNBUserName == '' or self.eNBPassword == '' or self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': + if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': GenericHelp(Version) sys.exit('Insufficient Parameter') check_eNB = True check_OAI_UE = True pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) + HTML.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) self.AutoTerminateUEandeNB() return server_on_enb = re.search('-R', str(self.iperf_args)) if server_on_enb is not None: - iServerIPAddr = self.eNBIPAddress - iServerUser = self.eNBUserName - iServerPasswd = self.eNBPassword + iServerIPAddr = RAN.GeteNBIPAddress() + iServerUser = RAN.GeteNBUserName() + iServerPasswd = RAN.GeteNBPassword() iClientIPAddr = self.UEIPAddress iClientUser = self.UEUserName iClientPasswd = self.UEPassword @@ -2550,9 +2125,9 @@ class OaiCiTest(): iServerIPAddr = self.UEIPAddress iServerUser = self.UEUserName iServerPasswd = self.UEPassword - iClientIPAddr = self.eNBIPAddress - iClientUser = self.eNBUserName - iClientPasswd = self.eNBPassword + iClientIPAddr = RAN.GeteNBIPAddress() + iClientUser = RAN.GeteNBUserName() + iClientPasswd = RAN.GeteNBPassword() if self.iperf_options != 'sink': # Starting the iperf server SSH.open(iServerIPAddr, iServerUser, iServerPasswd) @@ -2629,15 +2204,15 @@ class OaiCiTest(): html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' html_queue.put(html_cell) if (iperf_noperf and iperf_status): - self.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) elif (iperf_status): - self.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) else: - self.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) self.AutoTerminateUEandeNB() def Iperf(self): - result = re.search('noS1', str(self.Initialize_eNB_args)) + result = re.search('noS1', str(RAN.GetInitialize_eNB_args())) if result is not None: self.IperfNoS1() return @@ -2651,12 +2226,13 @@ class OaiCiTest(): check_OAI_UE = False pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) if (pStatus < 0): - self.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) + HTML.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) self.AutoTerminateUEandeNB() return ueIpStatus = self.GetAllUEIPAddresses() if (ueIpStatus < 0): - self.CreateHtmlTestRow(self.iperf_args, 'KO', UE_IP_ADDRESS_ISSUE) + logging.debug('going here') + HTML.CreateHtmlTestRow(self.iperf_args, 'KO', CONST.UE_IP_ADDRESS_ISSUE) self.AutoTerminateUEandeNB() return @@ -2676,9 +2252,10 @@ class OaiCiTest(): ue_num = len(self.UEIPAddresses) lock = Lock() status_queue = SimpleQueue() + logging.debug('ue_num = ' + str(ue_num)) for UE_IPAddress in self.UEIPAddresses: device_id = self.UEDevices[i] - p = Process(target = CiTestObj.Iperf_common, args = (lock,UE_IPAddress,device_id,i,ue_num,status_queue,)) + p = Process(target = self.Iperf_common, args = (lock,UE_IPAddress,device_id,i,ue_num,status_queue,)) p.daemon = True p.start() multi_jobs.append(p) @@ -2687,7 +2264,7 @@ class OaiCiTest(): job.join() if (status_queue.empty()): - self.CreateHtmlTestRow(self.iperf_args, 'KO', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(self.iperf_args, 'KO', CONST.ALL_PROCESSES_OK) self.AutoTerminateUEandeNB() else: iperf_status = True @@ -2705,11 +2282,11 @@ class OaiCiTest(): html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' html_queue.put(html_cell) if (iperf_noperf and iperf_status): - self.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) elif (iperf_status): - self.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) else: - self.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) self.AutoTerminateUEandeNB() def CheckProcessExist(self, check_eNB, check_OAI_UE): @@ -2717,7 +2294,7 @@ class OaiCiTest(): status_queue = SimpleQueue() # in noS1 config, no need to check status from EPC # in gNB also currently no need to check - result = re.search('noS1|band78', str(self.Initialize_eNB_args)) + result = re.search('noS1|band78', str(RAN.GetInitialize_eNB_args())) if result is None: p = Process(target = EPC.CheckHSSProcess, args = (status_queue,)) p.daemon = True @@ -2735,12 +2312,12 @@ class OaiCiTest(): if (check_eNB == False) and (check_OAI_UE == False): return 0 if check_eNB: - p = Process(target = CiTestObj.CheckeNBProcess, args = (status_queue,)) + p = Process(target = RAN.CheckeNBProcess, args = (status_queue,)) p.daemon = True p.start() multi_jobs.append(p) if check_OAI_UE: - p = Process(target = CiTestObj.CheckOAIUEProcess, args = (status_queue,)) + p = Process(target = self.CheckOAIUEProcess, args = (status_queue,)) p.daemon = True p.start() multi_jobs.append(p) @@ -2755,14 +2332,14 @@ class OaiCiTest(): status = status_queue.get() if (status < 0): result = status - if result == ENB_PROCESS_FAILED: - fileCheck = re.search('enb_', str(self.eNBLogFiles[0])) + if result == CONST.ENB_PROCESS_FAILED: + fileCheck = re.search('enb_', str(RAN.GeteNBLogFiles[0])) if fileCheck is not None: - SSH.copyin(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, self.eNBSourceCodePath + '/cmake_targets/' + self.eNBLogFiles[0], '.') - logStatus = self.AnalyzeLogFile_eNB(self.eNBLogFiles[0]) + SSH.copyin(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath() + '/cmake_targets/' + RAN.GeteNBLogFiles[0], '.') + logStatus = self.AnalyzeLogFile_eNB(RAN.GeteNBLogFiles[0]) if logStatus < 0: result = logStatus - self.eNBLogFiles[0] = '' + RAN.SeteNBLogFiles[0] = '' if self.flexranCtrlInstalled and self.flexranCtrlStarted: self.TerminateFlexranCtrl() return result @@ -2771,7 +2348,7 @@ class OaiCiTest(): multi_jobs = [] status_queue = SimpleQueue() if initialize_OAI_UE_flag == False: - p = Process(target = CiTestObj.CheckOAIUEProcess, args = (status_queue,)) + p = Process(target = self.CheckOAIUEProcess, args = (status_queue,)) p.daemon = True p.start() multi_jobs.append(p) @@ -2786,7 +2363,7 @@ class OaiCiTest(): status = status_queue.get() if (status < 0): result = status - if result == OAI_UE_PROCESS_FAILED: + if result == CONST.OAI_UE_PROCESS_FAILED: fileCheck = re.search('ue_', str(self.UELogFile)) if fileCheck is not None: SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.') @@ -2798,303 +2375,20 @@ class OaiCiTest(): def CheckOAIUEProcess(self, status_queue): try: SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - SSH.command('stdbuf -o0 ps -aux | grep --color=never ' + self.air_interface + '-uesoftmodem | grep -v grep', '\$', 5) - result = re.search(self.air_interface + '-uesoftmodem', SSH.getBefore()) + SSH.command('stdbuf -o0 ps -aux | grep --color=never ' + RAN.Getair_interface() + '-uesoftmodem | grep -v grep', '\$', 5) + result = re.search(RAN.Getair_interface() + '-uesoftmodem', SSH.getBefore()) if result is None: logging.debug('\u001B[1;37;41m OAI UE Process Not Found! \u001B[0m') - status_queue.put(OAI_UE_PROCESS_FAILED) + status_queue.put(CONST.OAI_UE_PROCESS_FAILED) else: - status_queue.put(OAI_UE_PROCESS_OK) + status_queue.put(CONST.OAI_UE_PROCESS_OK) SSH.close() except: os.kill(os.getppid(),signal.SIGUSR1) - def CheckeNBProcess(self, status_queue): - try: - # At least the instance 0 SHALL be on! - if self.eNBstatuses[0] == 0: - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - elif self.eNBstatuses[0] == 1: - lIpAddr = self.eNB1IPAddress - lUserName = self.eNB1UserName - lPassWord = self.eNB1Password - elif self.eNBstatuses[0] == 2: - lIpAddr = self.eNB2IPAddress - lUserName = self.eNB2UserName - lPassWord = self.eNB2Password - else: - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - SSH.open(lIpAddr, lUserName, lPassWord) - SSH.command('stdbuf -o0 ps -aux | grep --color=never ' + self.air_interface + '-softmodem | grep -v grep', '\$', 5) - result = re.search(self.air_interface + '-softmodem', SSH.getBefore()) - if result is None: - logging.debug('\u001B[1;37;41m eNB Process Not Found! \u001B[0m') - status_queue.put(ENB_PROCESS_FAILED) - else: - status_queue.put(ENB_PROCESS_OK) - SSH.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def AnalyzeLogFile_eNB(self, eNBlogFile): - if (not os.path.isfile('./' + eNBlogFile)): - return -1 - enb_log_file = open('./' + eNBlogFile, 'r') - exitSignalReceived = False - foundAssertion = False - msgAssertion = '' - msgLine = 0 - foundSegFault = False - foundRealTimeIssue = False - rrcSetupComplete = 0 - rrcReleaseRequest = 0 - rrcReconfigRequest = 0 - rrcReconfigComplete = 0 - rrcReestablishRequest = 0 - rrcReestablishComplete = 0 - rrcReestablishReject = 0 - rlcDiscardBuffer = 0 - rachCanceledProcedure = 0 - uciStatMsgCount = 0 - pdcpFailure = 0 - ulschFailure = 0 - cdrxActivationMessageCount = 0 - dropNotEnoughRBs = 0 - mbmsRequestMsg = 0 - self.htmleNBFailureMsg = '' - isRRU = False - isSlave = False - slaveReceivesFrameResyncCmd = False - X2HO_state = X2_HO_REQ_STATE__IDLE - X2HO_inNbProcedures = 0 - X2HO_outNbProcedures = 0 - for line in enb_log_file.readlines(): - if X2HO_state == X2_HO_REQ_STATE__IDLE: - result = re.search('target eNB Receives X2 HO Req X2AP_HANDOVER_REQ', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__TARGET_RECEIVES_REQ - result = re.search('source eNB receives the X2 HO ACK X2AP_HANDOVER_REQ_ACK', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK - if X2HO_state == X2_HO_REQ_STATE__TARGET_RECEIVES_REQ: - result = re.search('Received LTE_RRCConnectionReconfigurationComplete from UE', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE - if X2HO_state == X2_HO_REQ_STATE__TARGET_RRC_RECFG_COMPLETE: - result = re.search('issue rrc_eNB_send_PATH_SWITCH_REQ', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ - if X2HO_state == X2_HO_REQ_STATE__TARGET_SENDS_SWITCH_REQ: - result = re.search('received path switch ack S1AP_PATH_SWITCH_REQ_ACK', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__IDLE - X2HO_inNbProcedures += 1 - if X2HO_state == X2_HO_REQ_STATE__SOURCE_RECEIVES_REQ_ACK: - result = re.search('source eNB receives the X2 UE CONTEXT RELEASE X2AP_UE_CONTEXT_RELEASE', str(line)) - if result is not None: - X2HO_state = X2_HO_REQ_STATE__IDLE - X2HO_outNbProcedures += 1 - if self.eNBOptions[int(self.eNB_instance)] != '': - res1 = re.search('max_rxgain (?P[0-9]+)', self.eNBOptions[int(self.eNB_instance)]) - res2 = re.search('max_rxgain (?P[0-9]+)', str(line)) - if res1 is not None and res2 is not None: - requested_option = int(res1.group('requested_option')) - applied_option = int(res2.group('applied_option')) - if requested_option == applied_option: - self.htmleNBFailureMsg += ' Command line option(s) correctly applied ' + self.eNBOptions[int(self.eNB_instance)] + '\n\n' - else: - self.htmleNBFailureMsg += ' Command line option(s) NOT applied ' + self.eNBOptions[int(self.eNB_instance)] + '\n\n' - result = re.search('Exiting OAI softmodem', str(line)) - if result is not None: - exitSignalReceived = True - result = re.search('[Ss]egmentation [Ff]ault', str(line)) - 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('./ran_build/build/lte-softmodem', str(line)) - if result is not None and not exitSignalReceived: - foundSegFault = True - result = re.search('[Aa]ssertion', str(line)) - if result is not None and not exitSignalReceived: - foundAssertion = True - result = re.search('LLL', str(line)) - if result is not None and not exitSignalReceived: - foundRealTimeIssue = True - if foundAssertion and (msgLine < 3): - msgLine += 1 - msgAssertion += str(line) - result = re.search('Setting function for RU', str(line)) - if result is not None: - isRRU = True - if isRRU: - result = re.search('RU 0 is_slave=yes', str(line)) - if result is not None: - isSlave = True - if isSlave: - result = re.search('Received RRU_frame_resynch command', str(line)) - if result is not None: - slaveReceivesFrameResyncCmd = True - result = re.search('LTE_RRCConnectionSetupComplete from UE', str(line)) - if result is not None: - rrcSetupComplete += 1 - result = re.search('Generate LTE_RRCConnectionRelease|Generate RRCConnectionRelease', str(line)) - if result is not None: - rrcReleaseRequest += 1 - result = re.search('Generate LTE_RRCConnectionReconfiguration', str(line)) - if result is not None: - rrcReconfigRequest += 1 - result = re.search('LTE_RRCConnectionReconfigurationComplete from UE rnti', str(line)) - if result is not None: - rrcReconfigComplete += 1 - result = re.search('LTE_RRCConnectionReestablishmentRequest', str(line)) - if result is not None: - rrcReestablishRequest += 1 - result = re.search('LTE_RRCConnectionReestablishmentComplete', str(line)) - if result is not None: - rrcReestablishComplete += 1 - result = re.search('LTE_RRCConnectionReestablishmentReject', str(line)) - if result is not None: - rrcReestablishReject += 1 - result = re.search('CDRX configuration activated after RRC Connection', str(line)) - if result is not None: - cdrxActivationMessageCount += 1 - result = re.search('uci->stat', str(line)) - if result is not None: - uciStatMsgCount += 1 - result = re.search('PDCP.*Out of Resources.*reason', str(line)) - if result is not None: - pdcpFailure += 1 - result = re.search('ULSCH in error in round', str(line)) - if result is not None: - ulschFailure += 1 - result = re.search('BAD all_segments_received', str(line)) - if result is not None: - rlcDiscardBuffer += 1 - 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 - if self.eNBmbmsEnables[int(self.eNB_instance)]: - result = re.search('MBMS USER-PLANE.*Requesting.*bytes from RLC', str(line)) - if result is not None: - mbmsRequestMsg += 1 - enb_log_file.close() - logging.debug(' File analysis completed') - self.htmleNBFailureMsg = '' - if self.air_interface == 'lte': - nodeB_prefix = 'e' - else: - nodeB_prefix = 'g' - if uciStatMsgCount > 0: - statMsg = nodeB_prefix + 'NB showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmleNBFailureMsg += statMsg + '\n' - if pdcpFailure > 0: - statMsg = nodeB_prefix + 'NB showed ' + str(pdcpFailure) + ' "PDCP Out of Resources" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmleNBFailureMsg += statMsg + '\n' - if ulschFailure > 0: - statMsg = nodeB_prefix + 'NB 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 = nodeB_prefix + 'NB completed ' + str(rrcSetupComplete) + ' RRC Connection Setup(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - rrcMsg = ' -- ' + str(rrcSetupComplete) + ' were completed' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if rrcReleaseRequest > 0: - rrcMsg = nodeB_prefix + 'NB requested ' + str(rrcReleaseRequest) + ' RRC Connection Release(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if rrcReconfigRequest > 0 or rrcReconfigComplete > 0: - rrcMsg = nodeB_prefix + 'NB requested ' + str(rrcReconfigRequest) + ' RRC Connection Reconfiguration(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - rrcMsg = ' -- ' + str(rrcReconfigComplete) + ' were completed' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if rrcReestablishRequest > 0 or rrcReestablishComplete > 0 or rrcReestablishReject > 0: - rrcMsg = nodeB_prefix + 'NB requested ' + str(rrcReestablishRequest) + ' RRC Connection Reestablishment(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - rrcMsg = ' -- ' + str(rrcReestablishComplete) + ' were completed' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - rrcMsg = ' -- ' + str(rrcReestablishReject) + ' were rejected' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if self.eNBmbmsEnables[int(self.eNB_instance)]: - if mbmsRequestMsg > 0: - rrcMsg = 'eNB requested ' + str(mbmsRequestMsg) + ' times the RLC for MBMS USER-PLANE' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if X2HO_inNbProcedures > 0: - rrcMsg = 'eNB completed ' + str(X2HO_inNbProcedures) + ' X2 Handover Connection procedure(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if X2HO_outNbProcedures > 0: - rrcMsg = 'eNB completed ' + str(X2HO_outNbProcedures) + ' X2 Handover Release procedure(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if self.eNBOptions[int(self.eNB_instance)] != '': - res1 = re.search('drx_Config_present prSetup', self.eNBOptions[int(self.eNB_instance)]) - if res1 is not None: - if cdrxActivationMessageCount > 0: - rrcMsg = 'eNB activated the CDRX Configuration for ' + str(cdrxActivationMessageCount) + ' time(s)' - logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - else: - rrcMsg = 'eNB did NOT ACTIVATE the CDRX Configuration' - logging.debug('\u001B[1;37;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' - if rachCanceledProcedure > 0: - rachMsg = nodeB_prefix + 'NB cancelled ' + str(rachCanceledProcedure) + ' RA procedure(s)' - logging.debug('\u001B[1;30;43m ' + rachMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rachMsg + '\n' - if isRRU: - if isSlave: - if slaveReceivesFrameResyncCmd: - rruMsg = 'Slave RRU received the RRU_frame_resynch command from RAU' - logging.debug('\u001B[1;30;43m ' + rruMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rruMsg + '\n' - else: - rruMsg = 'Slave RRU DID NOT receive the RRU_frame_resynch command from RAU' - logging.debug('\u001B[1;37;41m ' + rruMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rruMsg + '\n' - self.prematureExit = True - return ENB_PROCESS_SLAVE_RRU_NOT_SYNCED - if foundSegFault: - logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB ended with a Segmentation Fault! \u001B[0m') - return ENB_PROCESS_SEG_FAULT - if foundAssertion: - logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB ended with an assertion! \u001B[0m') - self.htmleNBFailureMsg += msgAssertion - return ENB_PROCESS_ASSERTION - if foundRealTimeIssue: - logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB faced real time issues! \u001B[0m') - self.htmleNBFailureMsg += nodeB_prefix + 'NB faced real time issues!\n' - #return ENB_PROCESS_REALTIME_ISSUE - if rlcDiscardBuffer > 0: - rlcMsg = nodeB_prefix + 'NB RLC discarded ' + str(rlcDiscardBuffer) + ' buffer(s)' - logging.debug('\u001B[1;37;41m ' + rlcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rlcMsg + '\n' - return ENB_PROCESS_REALTIME_ISSUE - return 0 +# def AnalyzeLogFile_eNB(self, eNBlogFile): +# ... def AnalyzeLogFile_UE(self, UElogFile): if (not os.path.isfile('./' + UElogFile)): @@ -3183,7 +2477,7 @@ class OaiCiTest(): result = re.search('No cell synchronization found, abandoning', str(line)) if result is not None: no_cell_sync_found = True - if self.eNBmbmsEnables[0]: + if RAN.GeteNBmbmsEnables[0]: result = re.search('TRIED TO PUSH MBMS DATA', str(line)) if result is not None: mbms_messages += 1 @@ -3309,7 +2603,7 @@ class OaiCiTest(): statMsg = 'UE showed ' + str(fatalErrorCount) + ' "MAC BSR Triggered ReTxBSR Timer expiry" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') self.htmlUEFailureMsg += statMsg + '\n' - if self.eNBmbmsEnables[0]: + if RAN.GeteNBmbmsEnables[0]: if mbms_messages > 0: statMsg = 'UE showed ' + str(mbms_messages) + ' "TRIED TO PUSH MBMS DATA" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') @@ -3320,130 +2614,34 @@ class OaiCiTest(): if foundSegFault: logging.debug('\u001B[1;37;41m UE ended with a Segmentation Fault! \u001B[0m') if not nrUEFlag: - return OAI_UE_PROCESS_SEG_FAULT + return CONST.OAI_UE_PROCESS_SEG_FAULT else: if not frequency_found: - return OAI_UE_PROCESS_SEG_FAULT + return CONST.OAI_UE_PROCESS_SEG_FAULT if foundAssertion: logging.debug('\u001B[1;30;43m UE showed an assertion! \u001B[0m') self.htmlUEFailureMsg += 'UE showed an assertion!\n' if not nrUEFlag: if not mib_found or not frequency_found: - return OAI_UE_PROCESS_ASSERTION + return CONST.OAI_UE_PROCESS_ASSERTION else: if not frequency_found: - return OAI_UE_PROCESS_ASSERTION + return CONST.OAI_UE_PROCESS_ASSERTION if foundRealTimeIssue: logging.debug('\u001B[1;37;41m UE faced real time issues! \u001B[0m') self.htmlUEFailureMsg += 'UE faced real time issues!\n' - #return ENB_PROCESS_REALTIME_ISSUE + #return CONST.ENB_PROCESS_REALTIME_ISSUE if nrUEFlag: if not frequency_found: - return OAI_UE_PROCESS_COULD_NOT_SYNC + return CONST.OAI_UE_PROCESS_COULD_NOT_SYNC else: if no_cell_sync_found and not mib_found: logging.debug('\u001B[1;37;41m UE could not synchronize ! \u001B[0m') self.htmlUEFailureMsg += 'UE could not synchronize!\n' - return OAI_UE_PROCESS_COULD_NOT_SYNC + return CONST.OAI_UE_PROCESS_COULD_NOT_SYNC return 0 - def TerminateeNB(self): - if self.eNB_serverId == '0': - lIpAddr = self.eNBIPAddress - lUserName = self.eNBUserName - lPassWord = self.eNBPassword - lSourcePath = self.eNBSourceCodePath - elif self.eNB_serverId == '1': - lIpAddr = self.eNB1IPAddress - lUserName = self.eNB1UserName - lPassWord = self.eNB1Password - lSourcePath = self.eNB1SourceCodePath - elif self.eNB_serverId == '2': - lIpAddr = self.eNB2IPAddress - lUserName = self.eNB2UserName - lPassWord = self.eNB2Password - lSourcePath = self.eNB2SourceCodePath - if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - SSH.open(lIpAddr, lUserName, lPassWord) - SSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 5) - if self.air_interface == 'lte': - nodeB_prefix = 'e' - else: - nodeB_prefix = 'g' - SSH.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('-softmodem', SSH.getBefore()) - if result is not None: - SSH.command('echo ' + lPassWord + ' | sudo -S daemon --name=enb' + str(self.eNB_instance) + '_daemon --stop', '\$', 5) - SSH.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGINT -r .*-softmodem || true', '\$', 5) - time.sleep(10) - SSH.command('stdbuf -o0 ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('-softmodem', SSH.getBefore()) - if result is not None: - SSH.command('echo ' + lPassWord + ' | sudo -S killall --signal SIGKILL -r .*-softmodem || true', '\$', 5) - time.sleep(5) - SSH.command('rm -f my-lte-softmodem-run' + str(self.eNB_instance) + '.sh', '\$', 5) - SSH.close() - # If tracer options is on, stopping tshark on EPC side - result = re.search('T_stdout', str(self.Initialize_eNB_args)) - if result is not None: - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - logging.debug('\u001B[1m Stopping tshark \u001B[0m') - SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) - time.sleep(1) - if EPC.EPC_PcapFileName != '': - SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S chmod 666 /tmp/' + EPC.EPC_PcapFileName , '\$', 5) - SSH.copyin(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), '/tmp/' + EPC.EPC_PcapFileName , '.') - SSH.copyout(lIpAddr, lUserName, lPassWord, EPC.EPC_PcapFileName , lSourcePath + '/cmake_targets/.') - SSH.close() - logging.debug('\u001B[1m Replaying RAW record file\u001B[0m') - SSH.open(lIpAddr, lUserName, lPassWord) - SSH.command('cd ' + lSourcePath + '/common/utils/T/tracer/', '\$', 5) - enbLogFile = self.eNBLogFiles[int(self.eNB_instance)] - raw_record_file = enbLogFile.replace('.log', '_record.raw') - replay_log_file = enbLogFile.replace('.log', '_replay.log') - extracted_txt_file = enbLogFile.replace('.log', '_extracted_messages.txt') - extracted_log_file = enbLogFile.replace('.log', '_extracted_messages.log') - SSH.command('./extract_config -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + extracted_txt_file, '\$', 5) - SSH.command('echo $USER; nohup ./replay -i ' + lSourcePath + '/cmake_targets/' + raw_record_file + ' > ' + lSourcePath + '/cmake_targets/' + replay_log_file + ' 2>&1 &', lUserName, 5) - SSH.command('./textlog -d ' + lSourcePath + '/cmake_targets/' + extracted_txt_file + ' -no-gui -ON -full > ' + lSourcePath + '/cmake_targets/' + extracted_log_file, '\$', 5) - SSH.close() - SSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + extracted_log_file, '.') - logging.debug('\u001B[1m Analyzing eNB replay logfile \u001B[0m') - logStatus = self.AnalyzeLogFile_eNB(extracted_log_file) - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - self.eNBLogFiles[int(self.eNB_instance)] = '' - else: - analyzeFile = False - if self.eNBLogFiles[int(self.eNB_instance)] != '': - analyzeFile = True - fileToAnalyze = self.eNBLogFiles[int(self.eNB_instance)] - self.eNBLogFiles[int(self.eNB_instance)] = '' - if analyzeFile: - copyin_res = SSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + fileToAnalyze, '.') - if (copyin_res == -1): - logging.debug('\u001B[1;37;41m Could not copy ' + nodeB_prefix + 'NB logfile to analyze it! \u001B[0m') - self.htmleNBFailureMsg = 'Could not copy ' + nodeB_prefix + 'NB logfile to analyze it!' - self.CreateHtmlTestRow('N/A', 'KO', ENB_PROCESS_NOLOGFILE_TO_ANALYZE) - self.eNBmbmsEnables[int(self.eNB_instance)] = False - return - if self.eNB_serverId != '0': - SSH.copyout(self.eNBIPAddress, self.eNBUserName, self.eNBPassword, './' + fileToAnalyze, self.eNBSourceCodePath + '/cmake_targets/') - logging.debug('\u001B[1m Analyzing ' + nodeB_prefix + 'NB logfile \u001B[0m ' + fileToAnalyze) - logStatus = self.AnalyzeLogFile_eNB(fileToAnalyze) - if (logStatus < 0): - self.CreateHtmlTestRow('N/A', 'KO', logStatus) - self.preamtureExit = True - self.eNBmbmsEnables[int(self.eNB_instance)] = False - return - else: - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - else: - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) - self.eNBmbmsEnables[int(self.eNB_instance)] = False - self.eNBstatuses[int(self.eNB_instance)] = -1 - + def TerminateFlexranCtrl(self): if self.flexranCtrlInstalled == False or self.flexranCtrlStarted == False: return @@ -3457,7 +2655,7 @@ class OaiCiTest(): time.sleep(1) SSH.close() self.flexranCtrlStarted = False - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def TerminateUE_common(self, device_id, idx): try: @@ -3488,19 +2686,19 @@ class OaiCiTest(): os.kill(os.getppid(),signal.SIGUSR1) def TerminateUE(self): - terminate_ue_flag = True + terminate_ue_flag = False self.GetAllUEDevices(terminate_ue_flag) multi_jobs = [] i = 0 for device_id in self.UEDevices: - p = Process(target= CiTestObj.TerminateUE_common, args = (device_id,i,)) + p = Process(target= self.TerminateUE_common, args = (device_id,i,)) p.daemon = True p.start() multi_jobs.append(p) i += 1 for job in multi_jobs: job.join() - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def TerminateOAIUE(self): SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) @@ -3523,7 +2721,7 @@ class OaiCiTest(): if (copyin_res == -1): logging.debug('\u001B[1;37;41m Could not copy UE logfile to analyze it! \u001B[0m') self.htmlUEFailureMsg = 'Could not copy UE logfile to analyze it!' - self.CreateHtmlTestRow('N/A', 'KO', OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE, 'UE') + HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE, 'UE') self.UELogFile = '' return logging.debug('\u001B[1m Analyzing UE logfile \u001B[0m') @@ -3536,52 +2734,56 @@ class OaiCiTest(): if (logStatus < 0): logging.debug('\u001B[1m' + ueAction + ' Failed \u001B[0m') self.htmlUEFailureMsg = '' + ueAction + ' Failed\n' + self.htmlUEFailureMsg - self.CreateHtmlTestRow('N/A', 'KO', logStatus, 'UE') - if self.air_interface == 'lte': + HTML.CreateHtmlTestRow('N/A', 'KO', logStatus, 'UE') + if RAN.Getair_interface() == 'lte': # In case of sniffing on commercial eNBs we have random results # Not an error then - if (logStatus != OAI_UE_PROCESS_COULD_NOT_SYNC) or (ueAction != 'Sniffing'): + if (logStatus != CONST.OAI_UE_PROCESS_COULD_NOT_SYNC) or (ueAction != 'Sniffing'): self.Initialize_OAI_UE_args = '' self.AutoTerminateUEandeNB() else: - if (logStatus == OAI_UE_PROCESS_COULD_NOT_SYNC): + if (logStatus == CONST.OAI_UE_PROCESS_COULD_NOT_SYNC): self.Initialize_OAI_UE_args = '' self.AutoTerminateUEandeNB() else: logging.debug('\u001B[1m' + ueAction + ' Completed \u001B[0m') self.htmlUEFailureMsg = '' + ueAction + ' Completed\n' + self.htmlUEFailureMsg - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) self.UELogFile = '' else: - self.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def AutoTerminateUEandeNB(self): if (self.ADBIPAddress != 'none'): self.testCase_id = 'AUTO-KILL-UE' + RAN.SettestCase_id(self.testCase_id) self.desc = 'Automatic Termination of UE' self.ShowTestID() self.TerminateUE() if (self.Initialize_OAI_UE_args != ''): self.testCase_id = 'AUTO-KILL-UE' + RAN.SettestCase_id(self.testCase_id) self.desc = 'Automatic Termination of UE' self.ShowTestID() self.TerminateOAIUE() - if (self.Initialize_eNB_args != ''): + if (RAN.GetInitialize_eNB_args() != ''): self.testCase_id = 'AUTO-KILL-eNB' + RAN.SettestCase_id(self.testCase_id) self.desc = 'Automatic Termination of eNB' self.ShowTestID() - self.eNB_instance = '0' - self.TerminateeNB() + RAN.SeteNB_instance('0') + RAN.TerminateeNB() if self.flexranCtrlInstalled and self.flexranCtrlStarted: self.testCase_id = 'AUTO-KILL-flexran-ctl' + RAN.SettestCase_id(self.testCase_id) self.desc = 'Automatic Termination of FlexRan CTL' self.ShowTestID() self.TerminateFlexranCtrl() - self.prematureExit = True + RAN.SetprematureExit(True) def IdleSleep(self): time.sleep(self.idle_sleep_time) - self.CreateHtmlTestRow(str(self.idle_sleep_time) + ' sec', 'OK', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow(str(self.idle_sleep_time) + ' sec', 'OK', CONST.ALL_PROCESSES_OK) def X2_Status(self, idx, fileName): cmd = "curl --silent http://" + EPC.GetIPAddress() + ":9999/stats | jq '.' > " + fileName @@ -3683,22 +2885,22 @@ class OaiCiTest(): logging.debug(msg) fullMessage += msg + '' html_queue.put(fullMessage) - self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) else: msg = "X2 Handover FAILED" logging.error(msg) fullMessage += msg + '' html_queue.put(fullMessage) - self.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) + HTML.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) else: - self.CreateHtmlTestRow('Cannot perform requested X2 Handover', 'KO', ALL_PROCESSES_OK) + HTML.CreateHtmlTestRow('Cannot perform requested X2 Handover', 'KO', CONST.ALL_PROCESSES_OK) def LogCollectBuild(self): - if (self.eNBIPAddress != '' and self.eNBUserName != '' and self.eNBPassword != ''): - IPAddress = self.eNBIPAddress - UserName = self.eNBUserName - Password = self.eNBPassword - SourceCodePath = self.eNBSourceCodePath + if (RAN.GeteNBIPAddress() != '' and RAN.GeteNBUserName() != '' and RAN.GeteNBPassword() != ''): + IPAddress = RAN.GeteNBIPAddress() + UserName = RAN.GeteNBUserName() + Password = RAN.GeteNBPassword() + SourceCodePath = RAN.GeteNBSourceCodePath() elif (self.UEIPAddress != '' and self.UEUserName != '' and self.UEPassword != ''): IPAddress = self.UEIPAddress UserName = self.UEUserName @@ -3712,16 +2914,6 @@ class OaiCiTest(): SSH.command('rm -f build.log.zip', '\$', 5) SSH.command('zip build.log.zip build_log_*/*', '\$', 60) SSH.close() - - def LogCollecteNB(self): - SSH.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) - SSH.command('cd ' + self.eNBSourceCodePath, '\$', 5) - SSH.command('cd cmake_targets', '\$', 5) - SSH.command('echo ' + self.eNBPassword + ' | sudo -S rm -f enb.log.zip', '\$', 5) - SSH.command('echo ' + self.eNBPassword + ' | sudo -S zip enb.log.zip enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 60) - SSH.command('echo ' + self.eNBPassword + ' | sudo -S rm enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 5) - SSH.close() - def LogCollectPing(self): SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) SSH.command('cd ' + EPC.GetSourceCodePath(), '\$', 5) @@ -3750,7 +2942,7 @@ class OaiCiTest(): SSH.close() def RetrieveSystemVersion(self, machine): - if self.eNBIPAddress == 'none' or self.UEIPAddress == 'none': + if RAN.GeteNBIPAddress() == 'none' or self.UEIPAddress == 'none': self.OsVersion = 'Ubuntu 16.04.5 LTS' self.KernelVersion = '4.15.0-45-generic' self.UhdVersion = '3.13.0.1-0' @@ -3760,10 +2952,10 @@ class OaiCiTest(): self.CpuMHz = '2399.996 MHz' return 0 if machine == 'eNB': - if self.eNBIPAddress != '' and self.eNBUserName != '' and self.eNBPassword != '': - IPAddress = self.eNBIPAddress - UserName = self.eNBUserName - Password = self.eNBPassword + if RAN.GeteNBIPAddress() != '' and RAN.GeteNBUserName() != '' and RAN.GeteNBPassword() != '': + IPAddress = RAN.GeteNBIPAddress() + UserName = RAN.GeteNBUserName() + Password = RAN.GeteNBPassword() else: return -1 if machine == 'UE': @@ -3829,335 +3021,6 @@ class OaiCiTest(): logging.debug('cpu_mhz: ' + self.CpuMHz) SSH.close() -#----------------------------------------------------------- -# HTML Reporting.... -#----------------------------------------------------------- - def CreateHtmlHeader(self): - if (not self.htmlHeaderCreated): - logging.debug('\u001B[1m----------------------------------------\u001B[0m') - logging.debug('\u001B[1m Creating HTML header \u001B[0m') - logging.debug('\u001B[1m----------------------------------------\u001B[0m') - self.htmlFile = open('test_results.html', 'w') - self.htmlFile.write('\n') - self.htmlFile.write('\n') - self.htmlFile.write('\n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' Test Results for TEMPLATE_JOB_NAME job build #TEMPLATE_BUILD_ID\n') - self.htmlFile.write('\n') - self.htmlFile.write('
\n') - self.htmlFile.write('
\n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write('
\n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' Job Summary -- Job: TEMPLATE_JOB_NAME -- Build-ID: TEMPLATE_BUILD_ID\n') - self.htmlFile.write('
\n') - self.htmlFile.write('
\n') - self.htmlFile.write('
TEMPLATE_STAGE_NAME
\n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (self.ranAllowMerge): - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (self.ranAllowMerge): - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (self.ranAllowMerge): - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if self.ranAllowMerge != '': - commit_message = subprocess.check_output("git log -n1 --pretty=format:\"%s\" " + self.ranCommitID, shell=True, universal_newlines=True) - commit_message = commit_message.strip() - self.htmlFile.write(' \n') - if (self.ranAllowMerge): - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (self.ranAllowMerge): - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (self.ranTargetBranch == ''): - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write('
Build Start Time (UTC) TEMPLATE_BUILD_TIME
GIT Repository ' + self.ranRepository + '
Job Trigger Merge-RequestPush to Branch
Source Branch Branch' + self.ranBranch + '
Source Commit ID Commit ID ' + self.ranCommitID + '
Source Commit Message Commit Message ' + commit_message + '
Target Branch develop' + self.ranTargetBranch + '
\n') - - if (self.ADBIPAddress != 'none'): - terminate_ue_flag = True - self.GetAllUEDevices(terminate_ue_flag) - self.GetAllCatMDevices(terminate_ue_flag) - self.htmlUEConnected = len(self.UEDevices) - self.htmlFile.write('

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

\n') - self.htmlFile.write('

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

\n') - else: - self.UEDevices.append('OAI-UE') - self.htmlUEConnected = len(self.UEDevices) - self.htmlFile.write('

' + str(len(self.UEDevices)) + ' OAI UE(s) is(are) connected to CI bench

\n') - self.htmlFile.write('
\n') - self.htmlFile.write(' \n') - self.htmlFile.write('
\n') - self.htmlFile.close() - - def CreateHtmlTabHeader(self): - if (not self.htmlHeaderCreated): - if (not os.path.isfile('test_results.html')): - self.CreateHtmlHeader() - self.htmlFile = open('test_results.html', 'a') - if (self.nbTestXMLfiles == 1): - self.htmlFile.write('
\n') - self.htmlFile.write('

Test Summary for ' + self.testXMLfiles[0] + '

\n') - else: - self.htmlFile.write('
\n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if (self.htmlUEConnected == -1): - terminate_ue_flag = True - if (self.ADBIPAddress != 'none'): - self.GetAllUEDevices(terminate_ue_flag) - self.GetAllCatMDevices(terminate_ue_flag) - else: - self.UEDevices.append('OAI-UE') - self.htmlUEConnected = len(self.UEDevices) - - i = 0 - while (i < self.htmlUEConnected): - self.htmlFile.write(' \n') - i += 1 - self.htmlFile.write(' \n') - self.htmlHeaderCreated = True - - def CreateHtmlTabFooter(self, passStatus): - if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if passStatus: - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write('
Relative Time (ms)Test IdTest DescTest OptionsTest StatusUE' + str(i) + ' Status
Final Tab StatusPASS FAIL
\n') - self.htmlFile.write('
\n') - self.htmlFile.close() - time.sleep(1) - if passStatus: - cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__//' test_results.html" - subprocess.run(cmd, shell=True) - else: - cmd = "sed -i -e 's/__STATE_" + self.htmlTabNames[0] + "__/<\/span>/' test_results.html" - subprocess.run(cmd, shell=True) - self.htmlFooterCreated = False - - def CreateHtmlFooter(self, passStatus): - if (os.path.isfile('test_results.html')): - logging.debug('\u001B[1m----------------------------------------\u001B[0m') - logging.debug('\u001B[1m Creating HTML footer \u001B[0m') - logging.debug('\u001B[1m----------------------------------------\u001B[0m') - - self.htmlFile = open('test_results.html', 'a') - self.htmlFile.write('
\n') - self.htmlFile.write('

\n') - self.htmlFile.write(' \n') - - machines = [ 'eNB', 'UE' ] - for machine in machines: - res = self.RetrieveSystemVersion(machine) - if res == -1: - continue - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - if passStatus: - self.htmlFile.write(' \n') - else: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write('
' + str(machine) + ' Server Characteristics
OS Version' + self.OsVersion + 'Kernel Version' + self.KernelVersion + 'UHD Version' + self.UhdVersion + 'USRP Board' + self.UsrpBoard + '
Nb CPUs' + self.CpuNb + 'CPU Model Name' + self.CpuModel + 'CPU Frequency' + self.CpuMHz + '
Final StatusPASS FAIL
\n') - self.htmlFile.write('

\n') - self.htmlFile.write('
End of Test Report -- Copyright 2018 OpenAirInterface. All Rights Reserved.
\n') - self.htmlFile.write('
\n') - self.htmlFile.write('\n') - self.htmlFile.close() - - def CreateHtmlRetrySeparator(self): - if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): - self.htmlFile.write(' \n') - self.htmlFile.write(' Try Run #' + str(self.FailReportCnt) + '\n') - self.htmlFile.write(' \n') - - def CreateHtmlTestRow(self, options, status, processesStatus, machine='eNB'): - if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): - currentTime = int(round(time.time() * 1000)) - self.startTime - self.htmlFile.write(' \n') - self.htmlFile.write(' ' + format(currentTime / 1000, '.1f') + '\n') - self.htmlFile.write(' ' + self.testCase_id + '\n') - self.htmlFile.write(' ' + self.desc + '\n') - self.htmlFile.write(' ' + str(options) + '\n') - if (str(status) == 'OK'): - self.htmlFile.write(' ' + str(status) + '\n') - elif (str(status) == 'KO'): - if (processesStatus == 0): - self.htmlFile.write(' ' + str(status) + '\n') - elif (processesStatus == ENB_PROCESS_FAILED): - self.htmlFile.write(' KO - eNB process not found\n') - elif (processesStatus == OAI_UE_PROCESS_FAILED): - self.htmlFile.write(' KO - OAI UE process not found\n') - elif (processesStatus == ENB_PROCESS_SEG_FAULT) or (processesStatus == OAI_UE_PROCESS_SEG_FAULT): - self.htmlFile.write(' KO - ' + machine + ' process ended in Segmentation Fault\n') - elif (processesStatus == ENB_PROCESS_ASSERTION) or (processesStatus == OAI_UE_PROCESS_ASSERTION): - self.htmlFile.write(' KO - ' + machine + ' process ended in Assertion\n') - elif (processesStatus == ENB_PROCESS_REALTIME_ISSUE): - self.htmlFile.write(' KO - ' + machine + ' process faced Real Time issue(s)\n') - elif (processesStatus == ENB_PROCESS_NOLOGFILE_TO_ANALYZE) or (processesStatus == OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE): - self.htmlFile.write(' OK?\n') - elif (processesStatus == ENB_PROCESS_SLAVE_RRU_NOT_SYNCED): - self.htmlFile.write(' KO - ' + machine + ' Slave RRU could not synch\n') - elif (processesStatus == OAI_UE_PROCESS_COULD_NOT_SYNC): - self.htmlFile.write(' KO - UE could not sync\n') - elif (processesStatus == HSS_PROCESS_FAILED): - self.htmlFile.write(' KO - HSS process not found\n') - elif (processesStatus == MME_PROCESS_FAILED): - self.htmlFile.write(' KO - MME process not found\n') - elif (processesStatus == SPGW_PROCESS_FAILED): - self.htmlFile.write(' KO - SPGW process not found\n') - elif (processesStatus == UE_IP_ADDRESS_ISSUE): - self.htmlFile.write(' KO - Could not retrieve UE IP address\n') - else: - self.htmlFile.write(' ' + str(status) + '\n') - else: - self.htmlFile.write(' ' + str(status) + '\n') - if (len(str(self.htmleNBFailureMsg)) > 2): - cellBgColor = 'white' - result = re.search('ended with|faced real time issues', self.htmleNBFailureMsg) - if result is not None: - cellBgColor = 'red' - else: - result = re.search('showed|Reestablishment|Could not copy eNB logfile', self.htmleNBFailureMsg) - if result is not None: - cellBgColor = 'orange' - self.htmlFile.write('
' + self.htmleNBFailureMsg + '
\n') - self.htmleNBFailureMsg = '' - elif (len(str(self.htmlUEFailureMsg)) > 2): - cellBgColor = 'white' - result = re.search('ended with|faced real time issues', self.htmlUEFailureMsg) - if result is not None: - cellBgColor = 'red' - else: - result = re.search('showed|Could not copy UE logfile|oaitun_ue1 interface is either NOT mounted or NOT configured', self.htmlUEFailureMsg) - if result is not None: - cellBgColor = 'orange' - self.htmlFile.write('
' + self.htmlUEFailureMsg + '
\n') - self.htmlUEFailureMsg = '' - else: - i = 0 - while (i < self.htmlUEConnected): - self.htmlFile.write(' -\n') - i += 1 - self.htmlFile.write(' \n') - - def CreateHtmlTestRowQueue(self, options, status, ue_status, ue_queue): - if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): - currentTime = int(round(time.time() * 1000)) - self.startTime - addOrangeBK = False - self.htmlFile.write(' \n') - self.htmlFile.write(' ' + format(currentTime / 1000, '.1f') + '\n') - self.htmlFile.write(' ' + self.testCase_id + '\n') - self.htmlFile.write(' ' + self.desc + '\n') - self.htmlFile.write(' ' + str(options) + '\n') - if (str(status) == 'OK'): - self.htmlFile.write(' ' + str(status) + '\n') - elif (str(status) == 'KO'): - self.htmlFile.write(' ' + str(status) + '\n') - else: - addOrangeBK = True - self.htmlFile.write(' ' + str(status) + '\n') - i = 0 - while (i < self.htmlUEConnected): - if (i < ue_status): - if (not ue_queue.empty()): - if (addOrangeBK): - self.htmlFile.write(' ' + str(ue_queue.get()).replace('white', 'orange') + '\n') - else: - self.htmlFile.write(' ' + str(ue_queue.get()) + '\n') - else: - self.htmlFile.write(' -\n') - else: - self.htmlFile.write(' -\n') - i += 1 - self.htmlFile.write(' \n') - #----------------------------------------------------------- # ShowTestID() #----------------------------------------------------------- @@ -4175,47 +3038,47 @@ def CheckClassValidity(action,id): def GetParametersFromXML(action): if action == 'Build_eNB': - CiTestObj.Build_eNB_args = test.findtext('Build_eNB_args') + RAN.SetBuild_eNB_args(test.findtext('Build_eNB_args')) forced_workspace_cleanup = test.findtext('forced_workspace_cleanup') if (forced_workspace_cleanup is None): - CiTestObj.Build_eNB_forced_workspace_cleanup = False + RAN.SetBuild_eNB_forced_workspace_cleanup(False) else: if re.match('true', forced_workspace_cleanup, re.IGNORECASE): - CiTestObj.Build_eNB_forced_workspace_cleanup = True + RAN.SetBuild_eNB_forced_workspace_cleanup(True) else: - CiTestObj.Build_eNB_forced_workspace_cleanup = False - CiTestObj.eNB_instance = test.findtext('eNB_instance') - if (CiTestObj.eNB_instance is None): - CiTestObj.eNB_instance = '0' - CiTestObj.eNB_serverId = test.findtext('eNB_serverId') - if (CiTestObj.eNB_serverId is None): - CiTestObj.eNB_serverId = '0' + RAN.SetBuild_eNB_forced_workspace_cleanup(False) + RAN.SeteNB_instance(test.findtext('eNB_instance')) + if (RAN.GeteNB_instance() is None): + RAN.SeteNB_instance('0') + RAN.SeteNB_serverId(test.findtext('eNB_serverId')) + if (RAN.GeteNB_serverId() is None): + RAN.SeteNB_serverId('0') xmlBgBuildField = test.findtext('backgroundBuild') if (xmlBgBuildField is None): - CiTestObj.backgroundBuild = False + RAN.SetbackgroundBuild(False) else: if re.match('true', xmlBgBuildField, re.IGNORECASE): - CiTestObj.backgroundBuild = True + RAN.SetbackgroundBuild(True) else: - CiTestObj.backgroundBuild = False + RAN.SetbackgroundBuild(False) if action == 'WaitEndBuild_eNB': - CiTestObj.Build_eNB_args = test.findtext('Build_eNB_args') - CiTestObj.eNB_instance = test.findtext('eNB_instance') - if (CiTestObj.eNB_instance is None): - CiTestObj.eNB_instance = '0' - CiTestObj.eNB_serverId = test.findtext('eNB_serverId') - if (CiTestObj.eNB_serverId is None): - CiTestObj.eNB_serverId = '0' + RAN.SetBuild_eNB_args(test.findtext('Build_eNB_args')) + RAN.SeteNB_instance(test.findtext('eNB_instance')) + if (RAN.GeteNB_instance() is None): + RAN.SeteNB_instance('0') + RAN.SeteNB_serverId(test.findtext('eNB_serverId')) + if (RAN.GeteNB_serverId() is None): + RAN.SeteNB_serverId('0') if action == 'Initialize_eNB': - CiTestObj.Initialize_eNB_args = test.findtext('Initialize_eNB_args') - CiTestObj.eNB_instance = test.findtext('eNB_instance') - if (CiTestObj.eNB_instance is None): - CiTestObj.eNB_instance = '0' - CiTestObj.eNB_serverId = test.findtext('eNB_serverId') - if (CiTestObj.eNB_serverId is None): - CiTestObj.eNB_serverId = '0' + RAN.SetInitialize_eNB_args(test.findtext('Initialize_eNB_args')) + RAN.SeteNB_instance(test.findtext('eNB_instance')) + if (RAN.GeteNB_instance() is None): + RAN.SeteNB_instance('0') + RAN.SeteNB_serverId(test.findtext('eNB_serverId')) + if (RAN.GeteNB_serverId() is None): + RAN.SeteNB_serverId('0') CiTestObj.air_interface = test.findtext('air_interface') if (CiTestObj.air_interface is None): CiTestObj.air_interface = 'lte' @@ -4223,12 +3086,12 @@ def GetParametersFromXML(action): CiTestObj.air_interface = CiTestObj.air_interface.lower() if action == 'Terminate_eNB': - CiTestObj.eNB_instance = test.findtext('eNB_instance') - if (CiTestObj.eNB_instance is None): - CiTestObj.eNB_instance = '0' - CiTestObj.eNB_serverId = test.findtext('eNB_serverId') - if (CiTestObj.eNB_serverId is None): - CiTestObj.eNB_serverId = '0' + RAN.SeteNB_instance(test.findtext('eNB_instance')) + if (RAN.GeteNB_instance() is None): + RAN.SeteNB_instance('0') + RAN.SeteNB_serverId(test.findtext('eNB_serverId')) + if (RAN.GeteNB_serverId() is None): + RAN.SeteNB_serverId('0') CiTestObj.air_interface = test.findtext('air_interface') if (CiTestObj.air_interface is None): CiTestObj.air_interface = 'lte' @@ -4269,7 +3132,7 @@ def GetParametersFromXML(action): CiTestObj.air_interface = SSH.air_interface.lower() if action == 'Terminate_OAI_UE': - CiTestObj.eNB_instance = test.findtext('UE_instance') + RAN.SeteNB_instance(test.findtext('UE_instance')) if (CiTestObj.UE_instance is None): CiTestObj.UE_instance = '0' @@ -4332,13 +3195,18 @@ def receive_signal(signum, frame): mode = '' CiTestObj = OaiCiTest() -from sshconnection import * -from epc import * -from helpreadme import * -SSH = SSHConnection() -EPC = EPCManagement() -#HELP = HelpReadme() -#HELP.GenericHelp() +import sshconnection +import epc +import helpreadme +import ran +import html +import constants + +SSH = sshconnection.SSHConnection() +EPC = epc.EPCManagement() +RAN = ran.RANManagement() +HTML = html.HTMLManagement() + argvs = sys.argv argc = len(argvs) @@ -4346,6 +3214,7 @@ cwd = os.getcwd() while len(argvs) > 1: myArgv = argvs.pop(1) # 0th is this file's name + if re.match('^\-\-help$', myArgv, re.IGNORECASE): GenericHelp(Version) sys.exit(0) @@ -4357,7 +3226,8 @@ while len(argvs) > 1: matchReg = re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE) else: matchReg = re.match('^\-\-ranRepository=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.ranRepository = matchReg.group(1) + RAN.SetranRepository(matchReg.group(1)) + HTML.SetranRepository(matchReg.group(1)) elif re.match('^\-\-eNB_AllowMerge=(.+)$|^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE) @@ -4365,68 +3235,72 @@ while len(argvs) > 1: matchReg = re.match('^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE) doMerge = matchReg.group(1) if ((doMerge == 'true') or (doMerge == 'True')): - CiTestObj.ranAllowMerge = True + RAN.SetranAllowMerge(True) + HTML.SetranAllowMerge(True) elif re.match('^\-\-eNBBranch=(.+)$|^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE) else: matchReg = re.match('^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.ranBranch = matchReg.group(1) + RAN.SetranBranch(matchReg.group(1)) + HTML.SetranBranch(matchReg.group(1)) elif re.match('^\-\-eNBCommitID=(.*)$|^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE) else: matchReg = re.match('^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE) - CiTestObj.ranCommitID = matchReg.group(1) + RAN.SetranCommitID(matchReg.group(1)) + HTML.SetranCommitID(matchReg.group(1)) elif re.match('^\-\-eNBTargetBranch=(.*)$|^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE) else: matchReg = re.match('^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE) - CiTestObj.ranTargetBranch = matchReg.group(1) + RAN.SetranTargetBranch(matchReg.group(1)) elif re.match('^\-\-eNBIPAddress=(.+)$|^\-\-eNB[1-2]IPAddress=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.eNBIPAddress = matchReg.group(1) + RAN.SeteNBIPAddress(matchReg.group(1)) elif re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.eNB1IPAddress = matchReg.group(1) + RAN.SeteNB1IPAddress(matchReg.group(1)) elif re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.eNB2IPAddress = matchReg.group(1) + RAN.SeteNB2IPAddress(matchReg.group(1)) elif re.match('^\-\-eNBUserName=(.+)$|^\-\-eNB[1-2]UserName=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.eNBUserName = matchReg.group(1) + RAN.SeteNBUserName(matchReg.group(1)) elif re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.eNB1UserName = matchReg.group(1) + RAN.SeteNB1UserName(matchReg.group(1)) elif re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.eNB2UserName = matchReg.group(1) + RAN.SeteNB2UserName(matchReg.group(1)) elif re.match('^\-\-eNBPassword=(.+)$|^\-\-eNB[1-2]Password=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.eNBPassword = matchReg.group(1) + RAN.SeteNBPassword(matchReg.group(1)) elif re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.eNB1Password = matchReg.group(1) + RAN.SeteNB1Password(matchReg.group(1)) elif re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.eNB2Password = matchReg.group(1) + RAN.SeteNB2Password(matchReg.group(1)) elif re.match('^\-\-eNBSourceCodePath=(.+)$|^\-\-eNB[1-2]SourceCodePath=(.+)$', myArgv, re.IGNORECASE): if re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.eNBSourceCodePath = matchReg.group(1) + RAN.SeteNBSourceCodePath(matchReg.group(1)) elif re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.eNB1SourceCodePath = matchReg.group(1) + RAN.SeteNB1SourceCodePath(matchReg.group(1)) elif re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.eNB2SourceCodePath = matchReg.group(1) + RAN.SeteNB2SourceCodePath(matchReg.group(1)) elif re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE) EPC.SetIPAddress(matchReg.group(1)) +#GP250220: do we still need EPCBranch? it's not used anywhere elif re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE) CiTestObj.EPCBranch = matchReg.group(1) @@ -4466,7 +3340,8 @@ while len(argvs) > 1: elif re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE) CiTestObj.testXMLfiles.append(matchReg.group(1)) - CiTestObj.nbTestXMLfiles += 1 + HTML.SettestXMLfiles(matchReg.group(1)) + HTML.SetnbTestXMLfiles(HTML.GetnbTestXMLfiles()+1) elif re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE) CiTestObj.UEIPAddress = matchReg.group(1) @@ -4489,12 +3364,12 @@ while len(argvs) > 1: sys.exit('Invalid Parameter: ' + myArgv) if re.match('^TerminateeNB$', mode, re.IGNORECASE): - if CiTestObj.eNBIPAddress == '' or CiTestObj.eNBUserName == '' or CiTestObj.eNBPassword == '': + if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '': GenericHelp(Version) sys.exit('Insufficient Parameter') - CiTestObj.eNB_serverId = '0' - CiTestObj.eNB_instance = '0' - CiTestObj.eNBSourceCodePath = '/tmp/' + RAN.SeteNB_serverId('0') + RAN.SeteNB_instance('0') + RAN.SeteNBSourceCodePath('/tmp/') CiTestObj.TerminateeNB() elif re.match('^TerminateUE$', mode, re.IGNORECASE): if (CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == ''): @@ -4524,12 +3399,12 @@ elif re.match('^TerminateSPGW$', mode, re.IGNORECASE): sys.exit('Insufficient Parameter') CiTestObj.TerminateSPGW() elif re.match('^LogCollectBuild$', mode, re.IGNORECASE): - if (CiTestObj.eNBIPAddress == '' or CiTestObj.eNBUserName == '' or CiTestObj.eNBPassword == '' or CiTestObj.eNBSourceCodePath == '') and (CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == ''): + if (RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '') and (CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == ''): GenericHelp(Version) sys.exit('Insufficient Parameter') CiTestObj.LogCollectBuild() elif re.match('^LogCollecteNB$', mode, re.IGNORECASE): - if CiTestObj.eNBIPAddress == '' or CiTestObj.eNBUserName == '' or CiTestObj.eNBPassword == '' or CiTestObj.eNBSourceCodePath == '': + if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '': GenericHelp(Version) sys.exit('Insufficient Parameter') CiTestObj.LogCollecteNB() @@ -4569,7 +3444,7 @@ elif re.match('^InitiateHtml$', mode, re.IGNORECASE): sys.exit('Insufficient Parameter') count = 0 foundCount = 0 - while (count < CiTestObj.nbTestXMLfiles): + while (count < HTML.GetnbTestXMLfiles()): #xml_test_file = cwd + "/" + CiTestObj.testXMLfiles[count] xml_test_file = sys.path[0] + "/" + CiTestObj.testXMLfiles[count] if (os.path.isfile(xml_test_file)): @@ -4578,36 +3453,52 @@ elif re.match('^InitiateHtml$', mode, re.IGNORECASE): except: print("Error while parsing file: " + xml_test_file) xmlRoot = xmlTree.getroot() - CiTestObj.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count))) - CiTestObj.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-' + str(count))) - CiTestObj.htmlTabIcons.append(xmlRoot.findtext('htmlTabIcon',default='info-sign')) + HTML.SethtmlTabRefs(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count))) + HTML.SethtmlTabNames(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count))) + HTML.SethtmlTabIcons(xmlRoot.findtext('htmlTabIcon',default='info-sign')) + #CiTestObj.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count))) + #CiTestObj.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-' + str(count))) + #CiTestObj.htmlTabIcons.append(xmlRoot.findtext('htmlTabIcon',default='info-sign')) foundCount += 1 count += 1 - if foundCount != CiTestObj.nbTestXMLfiles: - CiTestObj.nbTestXMLfiles = foundCount - CiTestObj.CreateHtmlHeader() + if foundCount != HTML.GetnbTestXMLfiles(): + HTML.SetnbTestXMLfiles(foundcount) + + if (CiTestObj.ADBIPAddress != 'none'): + terminate_ue_flag = False + CiTestObj.GetAllUEDevices(terminate_ue_flag) + CiTestObj.GetAllCatMDevices(terminate_ue_flag) + HTML.SethtmlUEConnected(len(CiTestObj.UEDevices) + len(CiTestObj.CatMDevices)) + HTML.SethtmlNb_Smartphones(len(CiTestObj.UEDevices)) + HTML.SethtmlNb_CATM_Modules(len(CiTestObj.CatMDevices)) + HTML.CreateHtmlHeader(CiTestObj.ADBIPAddress) elif re.match('^FinalizeHtml$', mode, re.IGNORECASE): - CiTestObj.CreateHtmlFooter(CiTestObj.finalStatus) + HTML.SetreseNB(RetrieveSystemVersion('eNB')) + HTML.SetresUE(RetrieveSystemVersion('UE')) + HTML.CreateHtmlFooter(CiTestObj.finalStatus) elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re.IGNORECASE): if re.match('^TesteNB$', mode, re.IGNORECASE): - if CiTestObj.eNBIPAddress == '' or CiTestObj.ranRepository == '' or CiTestObj.ranBranch == '' or CiTestObj.eNBUserName == '' or CiTestObj.eNBPassword == '' or CiTestObj.eNBSourceCodePath == '' or EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '' or CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == '': + if RAN.GeteNBIPAddress() == '' or RAN.GetranRepository() == '' or RAN.GetranBranch() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '' or EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '' or CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == '': GenericHelp(Version) if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '' or EPC.GetType() == '': EPCSrvHelp(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), EPC.GetSourceCodePath(), EPC.GetType()) - # Gabriele: other if conditions relevant to eNB etc. to be added + if RAN.GetranRepository() == '': + GitSrvHelp(RAN.GetranRepository(),RAN.GetranBranch(),RAN.GetranCommitID(),RAN.GetranAllowMerge(),RAN.GetranTargetBranch()) + if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '': + eNBSrvHelp(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath()) sys.exit('Insufficient Parameter') if (EPC.GetIPAddress() != '') and (EPC.GetIPAddress() != 'none'): SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), cwd + "/tcp_iperf_stats.awk", "/tmp") SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), cwd + "/active_net_interfaces.awk", "/tmp") else: - if CiTestObj.UEIPAddress == '' or CiTestObj.ranRepository == '' or CiTestObj.ranBranch == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == '': + if CiTestObj.UEIPAddress == '' or RAN.GetranRepository() == '' or RAN.GetranBranch() == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == '': GenericHelp(Version) sys.exit('UE: Insufficient Parameter') #read test_case_list.xml file # if no parameters for XML file, use default value - if (CiTestObj.nbTestXMLfiles != 1): + if (HTML.GetnbTestXMLfiles() != 1): xml_test_file = cwd + "/test_case_list.xml" else: xml_test_file = cwd + "/" + CiTestObj.testXMLfiles[0] @@ -4617,9 +3508,11 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re exclusion_tests=xmlRoot.findtext('TestCaseExclusionList',default='') requested_tests=xmlRoot.findtext('TestCaseRequestedList',default='') - if (CiTestObj.nbTestXMLfiles == 1): - CiTestObj.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-0')) - CiTestObj.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-0')) + if (HTML.GetnbTestXMLfiles() == 1): + HTML.SethtmlTabRefs(xmlRoot.findtext('htmlTabRef',default='test-tab-0')) + HTML.SethtmlTabNames(xmlRoot.findtext('htmlTabName',default='Test-0')) + #CiTestObj.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-0')) + #CiTestObj.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-0')) repeatCount = xmlRoot.findtext('repeatCount',default='1') CiTestObj.repeatCounts.append(int(repeatCount)) all_tests=xmlRoot.findall('testCase') @@ -4661,26 +3554,38 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re signal.signal(signal.SIGUSR1, receive_signal) - CiTestObj.CreateHtmlTabHeader() + if (CiTestObj.ADBIPAddress != 'none'): + terminate_ue_flag = False + CiTestObj.GetAllUEDevices(terminate_ue_flag) + CiTestObj.GetAllCatMDevices(terminate_ue_flag) + else: + CiTestObj.UEDevices.append('OAI-UE') + HTML.SethtmlUEConnected(len(CiTestObj.UEDevices) + len(CiTestObj.CatMDevices)) + HTML.CreateHtmlTabHeader() CiTestObj.FailReportCnt = 0 - CiTestObj.prematureExit = True + RAN.SetprematureExit(True) CiTestObj.startTime = int(round(time.time() * 1000)) - while CiTestObj.FailReportCnt < CiTestObj.repeatCounts[0] and CiTestObj.prematureExit: - CiTestObj.prematureExit = False + HTML.SetstartTime(CiTestObj.startTime) + while CiTestObj.FailReportCnt < CiTestObj.repeatCounts[0] and RAN.GetprematureExit(): + RAN.SetprematureExit(False) # At every iteratin of the retry loop, a separator will be added - CiTestObj.CreateHtmlRetrySeparator() + # pass CiTestObj.FailReportCnt as parameter of HTML.CreateHtmlRetrySeparator + HTML.CreateHtmlRetrySeparator(CiTestObj.FailReportCnt) for test_case_id in todo_tests: - if CiTestObj.prematureExit: + if RAN.GetprematureExit(): break for test in all_tests: - if CiTestObj.prematureExit: + if RAN.GetprematureExit(): break id = test.get('id') if test_case_id != id: continue CiTestObj.testCase_id = id + RAN.SettestCase_id(CiTestObj.testCase_id) + HTML.SettestCase_id(CiTestObj.testCase_id) CiTestObj.desc = test.findtext('desc') + HTML.Setdesc(CiTestObj.desc) action = test.findtext('class') if (CheckClassValidity(action, id) == False): continue @@ -4691,13 +3596,17 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re terminate_ue_flag = False CiTestObj.GetAllUEDevices(terminate_ue_flag) if action == 'Build_eNB': - CiTestObj.BuildeNB() + RAN.BuildeNB() elif action == 'WaitEndBuild_eNB': - CiTestObj.WaitBuildeNBisFinished() + RAN.WaitBuildeNBisFinished() elif action == 'Initialize_eNB': - CiTestObj.InitializeeNB() + check_eNB = False + check_OAI_UE = False + RAN.SetpStatus(CiTestObj.CheckProcessExist(check_eNB, check_OAI_UE)) + + RAN.InitializeeNB() elif action == 'Terminate_eNB': - CiTestObj.TerminateeNB() + RAN.TerminateeNB() elif action == 'Initialize_UE': CiTestObj.InitializeUE() elif action == 'Terminate_UE': @@ -4757,13 +3666,13 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re else: sys.exit('Invalid action') CiTestObj.FailReportCnt += 1 - if CiTestObj.FailReportCnt == CiTestObj.repeatCounts[0] and CiTestObj.prematureExit: + if CiTestObj.FailReportCnt == CiTestObj.repeatCounts[0] and RAN.GetprematureExit(): logging.debug('Testsuite failed ' + str(CiTestObj.FailReportCnt) + ' time(s)') - CiTestObj.CreateHtmlTabFooter(False) + HTML.CreateHtmlTabFooter(False) sys.exit('Failed Scenario') else: logging.info('Testsuite passed after ' + str(CiTestObj.FailReportCnt) + ' time(s)') - CiTestObj.CreateHtmlTabFooter(True) + HTML.CreateHtmlTabFooter(True) else: GenericHelp(Version) sys.exit('Invalid mode') diff --git a/ci-scripts/main_enb.py b/ci-scripts/main_enb.py deleted file mode 100644 index 3b3428eec4..0000000000 --- a/ci-scripts/main_enb.py +++ /dev/null @@ -1,3680 +0,0 @@ - -# * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more -# * contributor license agreements. See the NOTICE file distributed with -# * this work for additional information regarding copyright ownership. -# * The OpenAirInterface Software Alliance licenses this file to You under -# * the OAI Public License, Version 1.1 (the "License"); you may not use this file -# * except in compliance with the License. -# * You may obtain a copy of the License at -# * -# * http://www.openairinterface.org/?page_id=698 -# * -# * Unless required by applicable law or agreed to in writing, software -# * distributed under the License is distributed on an "AS IS" BASIS, -# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# * See the License for the specific language governing permissions and -# * limitations under the License. -# *------------------------------------------------------------------------------- -# * For more information about the OpenAirInterface (OAI) Software Alliance: -# * contact@openairinterface.org -# */ -#--------------------------------------------------------------------- -# Python for CI of OAI-eNB + COTS-UE -# -# Required Python Version -# Python 3.x -# -# Required Python Package -# pexpect -#--------------------------------------------------------------------- - -import constants as CONST - -#----------------------------------------------------------- -# Version -#----------------------------------------------------------- -Version = '0.1' - -#----------------------------------------------------------- -# Import -#----------------------------------------------------------- -import sys # arg -import re # reg -import pexpect # pexpect -import time # sleep -import os -import subprocess -import xml.etree.ElementTree as ET -import logging -import datetime -import signal -from multiprocessing import Process, Lock, SimpleQueue -logging.basicConfig( - level=logging.DEBUG, - format="[%(asctime)s] %(name)s:%(levelname)s: %(message)s" -) - - -#----------------------------------------------------------- -# Class Declaration -#----------------------------------------------------------- -class OaiCiTest(): - - def __init__(self): - self.FailReportCnt = 0 - self.ADBIPAddress = '' - self.ADBUserName = '' - self.ADBPassword = '' - self.ADBCentralized = True - self.testCase_id = '' - self.testXMLfiles = [] - self.nbTestXMLfiles = 0 - self.desc = '' - self.ping_args = '' - self.ping_packetloss_threshold = '' - self.iperf_args = '' - self.iperf_packetloss_threshold = '' - self.iperf_profile = '' - self.iperf_options = '' - self.nbMaxUEtoAttach = -1 - self.UEDevices = [] - self.UEDevicesStatus = [] - self.UEDevicesRemoteServer = [] - self.UEDevicesRemoteUser = [] - self.UEDevicesOffCmd = [] - self.UEDevicesOnCmd = [] - self.UEDevicesRebootCmd = [] - self.CatMDevices = [] - self.UEIPAddresses = [] - self.htmlFile = '' - # self.htmlHeaderCreated = False - # self.htmlFooterCreated = False - self.htmlUEConnected = -1 - self.htmleNBFailureMsg = '' - self.htmlUEFailureMsg = '' - self.picocom_closure = False - self.idle_sleep_time = 0 - self.x2_ho_options = 'network' - self.x2NbENBs = 0 - self.x2ENBBsIds = [] - self.x2ENBConnectedUEs = [] - self.repeatCounts = [] - self.finalStatus = False - self.OsVersion = '' - self.KernelVersion = '' - self.UhdVersion = '' - self.UsrpBoard = '' - self.CpuNb = '' - self.CpuModel = '' - self.CpuMHz = '' - self.UEIPAddress = '' - self.UEUserName = '' - self.UEPassword = '' - self.UE_instance = '' - self.UESourceCodePath = '' - self.UELogFile = '' - self.Build_OAI_UE_args = '' - self.Initialize_OAI_UE_args = '' - self.clean_repository = True - self.flexranCtrlInstalled = False - self.flexranCtrlStarted = False - self.expectedNbOfConnectedUEs = 0 - self.startTime = 0 - - - def BuildOAIUE(self): - if self.UEIPAddress == '' or RAN.GetranRepository() == '' or RAN.GetranBranch() == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - result = re.search('--nrUE', self.Build_OAI_UE_args) - if result is not None: - RAN.Setair_interface('nr') - ue_prefix = 'NR ' - else: - RAN.Setair_interface('lte') - ue_prefix = '' - result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', RAN.GetranRepository()) - if result is not None: - full_ran_repo_name = RAN.GetranRepository() - else: - full_ran_repo_name = RAN.GetranRepository() + '.git' - SSH.command('mkdir -p ' + self.UESourceCodePath, '\$', 5) - SSH.command('cd ' + self.UESourceCodePath, '\$', 5) - SSH.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + full_ran_repo_name + ' .; else stdbuf -o0 git fetch --prune; fi', '\$', 600) - # here add a check if git clone or git fetch went smoothly - SSH.command('git config user.email "jenkins@openairinterface.org"', '\$', 5) - SSH.command('git config user.name "OAI Jenkins"', '\$', 5) - if self.clean_repository: - SSH.command('ls *.txt', '\$', 5) - result = re.search('LAST_BUILD_INFO', SSH.getBefore()) - if result is not None: - mismatch = False - SSH.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) - result = re.search(RAN.GetranCommitID(), SSH.getBefore()) - if result is None: - mismatch = True - SSH.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) - if (RAN.GetranAllowMerge()): - result = re.search('YES', SSH.getBefore()) - if result is None: - mismatch = True - SSH.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) - if RAN.GetranTargetBranch() == '': - result = re.search('develop', SSH.getBefore()) - else: - result = re.search(RAN.GetranTargetBranch(), SSH.getBefore()) - if result is None: - mismatch = True - else: - result = re.search('NO', SSH.getBefore()) - if result is None: - mismatch = True - if not mismatch: - SSH.close() - HTML.CreateHtmlTestRow(RAN.GetBuild_eNB_args(), 'OK', CONST.ALL_PROCESSES_OK) - return - - SSH.command('echo ' + self.UEPassword + ' | sudo -S git clean -x -d -ff', '\$', 30) - - # if the commit ID is provided use it to point to it - if RAN.GetranCommitID() != '': - SSH.command('git checkout -f ' + RAN.GetranCommitID(), '\$', 5) - # if the branch is not develop, then it is a merge request and we need to do - # the potential merge. Note that merge conflicts should already been checked earlier - if (RAN.GetranAllowMerge()): - if RAN.GetranTargetBranch() == '': - if (RAN.GetranBranch() != 'develop') and (RAN.GetranBranch() != 'origin/develop'): - SSH.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) - else: - logging.debug('Merging with the target branch: ' + RAN.GetranTargetBranch()) - SSH.command('git merge --ff origin/' + RAN.GetranTargetBranch() + ' -m "Temporary merge for CI"', '\$', 5) - SSH.command('source oaienv', '\$', 5) - SSH.command('cd cmake_targets', '\$', 5) - SSH.command('mkdir -p log', '\$', 5) - SSH.command('chmod 777 log', '\$', 5) - # no need to remove in log (git clean did the trick) - SSH.command('stdbuf -o0 ./build_oai ' + self.Build_OAI_UE_args + ' 2>&1 | stdbuf -o0 tee compile_oai_ue.log', 'Bypassing the Tests|build have failed', 600) - SSH.command('ls ran_build/build', '\$', 3) - SSH.command('ls ran_build/build', '\$', 3) - buildStatus = True - result = re.search(RAN.Getair_interface() + '-uesoftmodem', SSH.getBefore()) - if result is None: - buildStatus = False - SSH.command('mkdir -p build_log_' + self.testCase_id, '\$', 5) - SSH.command('mv log/* ' + 'build_log_' + self.testCase_id, '\$', 5) - SSH.command('mv compile_oai_ue.log ' + 'build_log_' + self.testCase_id, '\$', 5) - if buildStatus: - # Generating a BUILD INFO file - SSH.command('echo "SRC_BRANCH: ' + RAN.GetranBranch() + '" > ../LAST_BUILD_INFO.txt', '\$', 2) - SSH.command('echo "SRC_COMMIT: ' + RAN.GetranCommitID() + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) - if (RAN.GetranAllowMerge()): - SSH.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2) - if RAN.GetranTargetBranch() == '': - SSH.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2) - else: - SSH.command('echo "TGT_BRANCH: ' + RAN.GetranTargetBranch() + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) - else: - SSH.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) - SSH.close() - HTML.CreateHtmlTestRow(self.Build_OAI_UE_args, 'OK', CONST.ALL_PROCESSES_OK, 'OAI UE') - else: - SSH.close() - logging.error('\u001B[1m Building OAI UE Failed\u001B[0m') - HTML.CreateHtmlTestRow(self.Build_OAI_UE_args, 'KO', CONST.ALL_PROCESSES_OK, 'OAI UE') - HTML.CreateHtmlTabFooter(False) - sys.exit(1) - - def CheckFlexranCtrlInstallation(self): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '': - return - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('ls -ls /opt/flexran_rtc/*/rt_controller', '\$', 5) - result = re.search('/opt/flexran_rtc/build/rt_controller', SSH.getBefore()) - if result is not None: - self.flexranCtrlInstalled = True - RAN.SetflexranCtrlInstalled(True) - logging.debug('Flexran Controller is installed') - SSH.close() - - def InitializeFlexranCtrl(self): - if self.flexranCtrlInstalled == False: - return - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('cd /opt/flexran_rtc', '\$', 5) - SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S rm -f log/*.log', '\$', 5) - SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S echo "build/rt_controller -c log_config/basic_log" > ./my-flexran-ctl.sh', '\$', 5) - SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S chmod 755 ./my-flexran-ctl.sh', '\$', 5) - SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S daemon --unsafe --name=flexran_rtc_daemon --chdir=/opt/flexran_rtc -o /opt/flexran_rtc/log/flexranctl_' + self.testCase_id + '.log ././my-flexran-ctl.sh', '\$', 5) - SSH.command('ps -aux | grep --color=never rt_controller', '\$', 5) - result = re.search('rt_controller -c ', SSH.getBefore()) - if result is not None: - logging.debug('\u001B[1m Initialize FlexRan Controller Completed\u001B[0m') - self.flexranCtrlStarted = True - RAN.SetflexranCtrlStarted(True) - SSH.close() - HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - - def InitializeUE_common(self, device_id, idx): - try: - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - if not self.ADBCentralized: - # Reboot UE - #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesRebootCmd[idx], '\$', 60) - # Wait - #time.sleep(60) - # Put in LTE-Mode only - #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode 11"\'', '\$', 60) - #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode1 11"\'', '\$', 60) - #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode2 11"\'', '\$', 60) - #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "settings put global preferred_network_mode3 11"\'', '\$', 60) - # enable data service - #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) - # we need to do radio on/off cycle to make sure of above changes - # airplane mode off // radio on - #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) - #time.sleep(10) - # airplane mode on // radio off - #SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) - - # normal procedure without reboot - # enable data service - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) - # airplane mode on // radio off - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) - SSH.close() - return - # enable data service - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data enable"', '\$', 60) - - # The following commands are deprecated since we no longer work on Android 7+ - # SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell settings put global airplane_mode_on 1', '\$', 10) - # SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true', '\$', 60) - # a dedicated script has to be installed inside the UE - # airplane mode on means call /data/local/tmp/off - if device_id == '84B7N16418004022': - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) - else: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) - #airplane mode off means call /data/local/tmp/on - logging.debug('\u001B[1mUE (' + device_id + ') Initialize Completed\u001B[0m') - SSH.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def InitializeUE(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - multi_jobs = [] - i = 0 - for device_id in self.UEDevices: - p = Process(target = self.InitializeUE_common, args = (device_id,i,)) - p.daemon = True - p.start() - multi_jobs.append(p) - i += 1 - for job in multi_jobs: - job.join() - HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - - def InitializeOAIUE(self): - if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - if RAN.Getair_interface() == 'lte': - result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) - if result is None: - check_eNB = True - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', pStatus) - HTML.CreateHtmlTabFooter(False) - sys.exit(1) - UE_prefix = '' - else: - UE_prefix = 'NR ' - SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - # b2xx_fx3_utils reset procedure - SSH.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 60) - result = re.search('type: b200', SSH.getBefore()) - if result is not None: - logging.debug('Found a B2xx device --> resetting it') - SSH.command('echo ' + self.UEPassword + ' | sudo -S b2xx_fx3_utils --reset-device', '\$', 10) - # Reloading FGPA bin firmware - SSH.command('echo ' + self.UEPassword + ' | sudo -S uhd_find_devices', '\$', 30) - result = re.search('type: n3xx', SSH.getBefore()) - if result is not None: - logging.debug('Found a N3xx device --> resetting it') - SSH.command('cd ' + self.UESourceCodePath, '\$', 5) - # Initialize_OAI_UE_args usually start with -C and followed by the location in repository - SSH.command('source oaienv', '\$', 5) - SSH.command('cd cmake_targets/ran_build/build', '\$', 5) - if RAN.Getair_interface() == 'lte': - result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) - # We may have to regenerate the .u* files - if result is None: - SSH.command('ls /tmp/*.sed', '\$', 5) - result = re.search('adapt_usim_parameters', SSH.getBefore()) - if result is not None: - SSH.command('sed -f /tmp/adapt_usim_parameters.sed ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5) - else: - SSH.command('sed -e "s#93#92#" -e "s#8baf473f2f8fd09487cccbd7097c6862#fec86ba6eb707ed08905757b1bb44b8f#" -e "s#e734f8734007d6c5ce7a0508809e7e9c#C42449363BBAD02B66D16BC975D77CC1#" ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5) - SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf .u*', '\$', 5) - SSH.command('echo ' + self.UEPassword + ' | sudo -S ../../../targets/bin/conf2uedata -c ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf -o .', '\$', 5) - SSH.command('echo "ulimit -c unlimited && ./'+ RAN.Getair_interface() +'-uesoftmodem ' + self.Initialize_OAI_UE_args + '" > ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) - SSH.command('chmod 775 ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) - SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log', '\$', 5) - self.UELogFile = 'ue_' + self.testCase_id + '.log' - - # We are now looping several times to hope we really sync w/ an eNB - doOutterLoop = True - outterLoopCounter = 5 - gotSyncStatus = True - fullSyncStatus = True - while (doOutterLoop): - SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets/ran_build/build', '\$', 5) - SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log', '\$', 5) - #use nohup instead of daemon - #SSH.command('echo ' + self.UEPassword + ' | sudo -S -E daemon --inherit --unsafe --name=ue' + str(self.UE_instance) + '_daemon --chdir=' + self.UESourceCodePath + '/cmake_targets/ran_build/build -o ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) - SSH.command('echo $USER; nohup sudo ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh' + ' > ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log ' + ' 2>&1 &', self.UEUserName, 5) - time.sleep(6) - SSH.command('cd ../..', '\$', 5) - doLoop = True - loopCounter = 10 - gotSyncStatus = True - # the 'got sync' message is for the UE threads synchronization - while (doLoop): - loopCounter = loopCounter - 1 - if (loopCounter == 0): - # Here should never occur - logging.error('"got sync" message never showed!') - gotSyncStatus = False - doLoop = False - continue - SSH.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4) - if RAN.Getair_interface() == 'nr': - result = re.search('Starting sync detection', SSH.getBefore()) - else: - result = re.search('got sync', SSH.getBefore()) - if result is None: - time.sleep(10) - else: - doLoop = False - logging.debug('Found "got sync" message!') - if gotSyncStatus == False: - # we certainly need to stop the lte-uesoftmodem process if it is still running! - SSH.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4) - result = re.search('-uesoftmodem', SSH.getBefore()) - if result is not None: - SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT -r *-uesoftmodem', '\$', 4) - time.sleep(3) - continue - if RAN.Getair_interface() == 'nr': - fullSyncStatus = True - doOutterLoop = False - else: - # We are now checking if sync w/ eNB DOES NOT OCCUR - # Usually during the cell synchronization stage, the UE returns with No cell synchronization message - doLoop = True - loopCounter = 10 - while (doLoop): - loopCounter = loopCounter - 1 - if (loopCounter == 0): - # Here we do have a great chance that the UE did cell-sync w/ eNB - doLoop = False - doOutterLoop = False - fullSyncStatus = True - continue - SSH.command('stdbuf -o0 cat ue_' + self.testCase_id + '.log | egrep --text --color=never -i "wait|sync"', '\$', 4) - result = re.search('No cell synchronization found', SSH.getBefore()) - if result is None: - time.sleep(6) - else: - doLoop = False - fullSyncStatus = False - logging.debug('Found: "No cell synchronization" message! --> try again') - time.sleep(6) - SSH.command('ps -aux | grep --text --color=never softmodem | grep -v grep', '\$', 4) - result = re.search('lte-uesoftmodem', SSH.getBefore()) - if result is not None: - SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal=SIGINT lte-uesoftmodem', '\$', 4) - outterLoopCounter = outterLoopCounter - 1 - if (outterLoopCounter == 0): - doOutterLoop = False - - if fullSyncStatus and gotSyncStatus and RAN.Getair_interface() == 'lte': - result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) - if result is None: - SSH.command('ifconfig oaitun_ue1', '\$', 4) - SSH.command('ifconfig oaitun_ue1', '\$', 4) - # ifconfig output is different between ubuntu 16 and ubuntu 18 - result = re.search('inet addr:1|inet 1', SSH.getBefore()) - if result is not None: - logging.debug('\u001B[1m oaitun_ue1 interface is mounted and configured\u001B[0m') - tunnelInterfaceStatus = True - else: - logging.debug(SSH.getBefore()) - logging.error('\u001B[1m oaitun_ue1 interface is either NOT mounted or NOT configured\u001B[0m') - tunnelInterfaceStatus = False - if RAN.GeteNBmbmsEnables[0]: - self.command('ifconfig oaitun_uem1', '\$', 4) - result = re.search('inet addr', SSH.getBefore()) - if result is not None: - logging.debug('\u001B[1m oaitun_uem1 interface is mounted and configured\u001B[0m') - tunnelInterfaceStatus = tunnelInterfaceStatus and True - else: - logging.error('\u001B[1m oaitun_uem1 interface is either NOT mounted or NOT configured\u001B[0m') - tunnelInterfaceStatus = False - else: - tunnelInterfaceStatus = True - else: - tunnelInterfaceStatus = True - - SSH.close() - if fullSyncStatus and gotSyncStatus and tunnelInterfaceStatus: - HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'OK', CONST.ALL_PROCESSES_OK, 'OAI UE') - logging.debug('\u001B[1m Initialize OAI UE Completed\u001B[0m') - if (self.ADBIPAddress != 'none'): - self.UEDevices = [] - self.UEDevices.append('OAI-UE') - self.UEDevicesStatus = [] - self.UEDevicesStatus.append(CONST.UE_STATUS_DETACHED) - else: - if RAN.Getair_interface() == 'lte': - if RAN.GeteNBmbmsEnables[0]: - self.htmlUEFailureMsg = 'oaitun_ue1/oaitun_uem1 interfaces are either NOT mounted or NOT configured' - else: - self.htmlUEFailureMsg = 'oaitun_ue1 interface is either NOT mounted or NOT configured' - HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', CONST.OAI_UE_PROCESS_NO_TUNNEL_INTERFACE, 'OAI UE') - else: - self.htmlUEFailureMsg = 'nr-uesoftmodem did NOT synced' - HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', CONST.OAI_UE_PROCESS_COULD_NOT_SYNC, 'OAI UE') - logging.error('\033[91mInitialize OAI UE Failed! \033[0m') - self.AutoTerminateUEandeNB() - - def checkDevTTYisUnlocked(self): - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - count = 0 - while count < 5: - SSH.command('echo ' + self.ADBPassword + ' | sudo -S lsof | grep ttyUSB0', '\$', 10) - result = re.search('picocom', SSH.getBefore()) - if result is None: - count = 10 - else: - time.sleep(5) - count = count + 1 - SSH.close() - - def InitializeCatM(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - self.picocom_closure = True - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` - SSH.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) - SSH.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) - time.sleep(1) - # Calling twice AT to clear all buffers - SSH.command('AT', 'OK|ERROR', 5) - SSH.command('AT', 'OK', 5) - # Doing a power cycle - self.command('AT^RESET', 'SIMSTORE,READY', 15) - self.command('AT', 'OK|ERROR', 5) - self.command('AT', 'OK', 5) - self.command('ATE1', 'OK', 5) - # Disabling the Radio - SSH.command('AT+CFUN=0', 'OK', 5) - logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') - # Checking if auto-attach is enabled - SSH.command('AT^AUTOATT?', 'OK', 5) - result = re.search('AUTOATT: (?P[0-9\-]+)', SSH.getBefore()) - if result is not None: - if result.group('state') is not None: - autoAttachState = int(result.group('state')) - if autoAttachState is not None: - if autoAttachState == 0: - SSH.command('AT^AUTOATT=1', 'OK', 5) - logging.debug('\u001B[1m Auto-Attach enabled\u001B[0m') - else: - logging.debug('\u001B[1;37;41m Could not check Auto-Attach! \u001B[0m') - # Force closure of picocom but device might still be locked - SSH.close() - self.picocom_closure = False - HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - self.checkDevTTYisUnlocked() - - def TerminateCatM(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - self.picocom_closure = True - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` - SSH.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) - SSH.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) - time.sleep(1) - # Calling twice AT to clear all buffers - SSH.command('AT', 'OK|ERROR', 5) - SSH.command('AT', 'OK', 5) - # Disabling the Radio - SSH.command('AT+CFUN=0', 'OK', 5) - logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') - SSH.close() - self.picocom_closure = False - HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - self.checkDevTTYisUnlocked() - - def AttachCatM(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - self.picocom_closure = True - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` - SSH.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) - SSH.command('sudo picocom --baud 921600 --flow n --databits 8 /dev/ttyUSB0', 'Terminal ready', 10) - time.sleep(1) - # Calling twice AT to clear all buffers - SSH.command('AT', 'OK|ERROR', 5) - SSH.command('AT', 'OK', 5) - # Enabling the Radio - SSH.command('AT+CFUN=1', 'SIMSTORE,READY', 5) - logging.debug('\u001B[1m Cellular Functionality enabled\u001B[0m') - time.sleep(4) - # We should check if we register - count = 0 - attach_cnt = 0 - attach_status = False - while count < 5: - SSH.command('AT+CEREG?', 'OK', 5) - result = re.search('CEREG: 2,(?P[0-9\-]+),', SSH.getBefore()) - if result is not None: - mDataConnectionState = int(result.group('state')) - if mDataConnectionState is not None: - if mDataConnectionState == 1: - count = 10 - attach_status = True - result = re.search('CEREG: 2,1,"(?P[0-9A-Z]+)","(?P[0-9A-Z]+)"', SSH.getBefore()) - if result is not None: - networky = result.group('networky') - networkz = result.group('networkz') - logging.debug('\u001B[1m CAT-M module attached to eNB (' + str(networky) + '/' + str(networkz) + ')\u001B[0m') - else: - logging.debug('\u001B[1m CAT-M module attached to eNB\u001B[0m') - else: - logging.debug('+CEREG: 2,' + str(mDataConnectionState)) - attach_cnt = attach_cnt + 1 - else: - logging.debug(SSH.getBefore()) - attach_cnt = attach_cnt + 1 - count = count + 1 - time.sleep(1) - if attach_status: - SSH.command('AT+CESQ', 'OK', 5) - result = re.search('CESQ: 99,99,255,255,(?P[0-9]+),(?P[0-9]+)', SSH.getBefore()) - if result is not None: - nRSRQ = int(result.group('rsrq')) - nRSRP = int(result.group('rsrp')) - if (nRSRQ is not None) and (nRSRP is not None): - logging.debug(' RSRQ = ' + str(-20+(nRSRQ/2)) + ' dB') - logging.debug(' RSRP = ' + str(-140+nRSRP) + ' dBm') - SSH.close() - self.picocom_closure = False - html_queue = SimpleQueue() - self.checkDevTTYisUnlocked() - if attach_status: - html_cell = '
CAT-M module Attachment Completed in ' + str(attach_cnt+4) + ' seconds'
-			if (nRSRQ is not None) and (nRSRP is not None):
-				html_cell += '\n   RSRQ = ' + str(-20+(nRSRQ/2)) + ' dB'
-				html_cell += '\n   RSRP = ' + str(-140+nRSRP) + ' dBm
' - else: - html_cell += '' - html_queue.put(html_cell) - HTML.CreateHtmlTestRowQueue('N/A', 'OK', 1, html_queue) - else: - logging.error('\u001B[1m CAT-M module Attachment Failed\u001B[0m') - html_cell = '
CAT-M module Attachment Failed
' - html_queue.put(html_cell) - HTML.CreateHtmlTestRowQueue('N/A', 'KO', 1, html_queue) - self.AutoTerminateUEandeNB() - - def PingCatM(self): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - check_eNB = True - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - try: - statusQueue = SimpleQueue() - lock = Lock() - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('cd ' + EPC.GetSourceCodePath(), '\$', 5) - SSH.command('cd scripts', '\$', 5) - if re.match('OAI', EPC.GetType(), re.IGNORECASE): - logging.debug('Using the OAI EPC HSS: not implemented yet') - HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) - HTML.CreateHtmlTabFooter(False) - sys.exit(1) - else: - SSH.command('egrep --color=never "Allocated ipv4 addr" /opt/ltebox/var/log/xGwLog.0', '\$', 5) - result = re.search('Allocated ipv4 addr: (?P[0-9\.]+) from Pool', SSH.getBefore()) - if result is not None: - moduleIPAddr = result.group('ipaddr') - else: - HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - ping_time = re.findall("-c (\d+)",str(self.ping_args)) - device_id = 'catm' - ping_status = SSH.command('stdbuf -o0 ping ' + self.ping_args + ' ' + str(moduleIPAddr) + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) - # TIMEOUT CASE - if ping_status < 0: - message = 'Ping with UE (' + str(moduleIPAddr) + ') crashed due to TIMEOUT!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - SSH.close() - self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) - return - result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', SSH.getBefore()) - if result is None: - message = 'Packet Loss Not Found!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - SSH.close() - self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) - return - packetloss = result.group('packetloss') - if float(packetloss) == 100: - message = 'Packet Loss is 100%' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - SSH.close() - self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) - return - result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', SSH.getBefore()) - if result is None: - message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - SSH.close() - self.ping_iperf_wrong_exit(lock, moduleIPAddr, device_id, statusQueue, message) - return - rtt_min = result.group('rtt_min') - rtt_avg = result.group('rtt_avg') - rtt_max = result.group('rtt_max') - pal_msg = 'Packet Loss : ' + packetloss + '%' - min_msg = 'RTT(Min) : ' + rtt_min + ' ms' - avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms' - max_msg = 'RTT(Max) : ' + rtt_max + ' ms' - lock.acquire() - logging.debug('\u001B[1;37;44m ping result (' + moduleIPAddr + ') \u001B[0m') - logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') - qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg - packetLossOK = True - if packetloss is not None: - if float(packetloss) > float(self.ping_packetloss_threshold): - qMsg += '\nPacket Loss too high' - logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') - packetLossOK = False - elif float(packetloss) > 0: - qMsg += '\nPacket Loss is not 0%' - logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m') - lock.release() - SSH.close() - html_cell = '
CAT-M module\nIP Address  : ' + moduleIPAddr + '\n' + qMsg + '
' - statusQueue.put(html_cell) - if (packetLossOK): - HTML.CreateHtmlTestRowQueue(self.ping_args, 'OK', 1, statusQueue) - else: - HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', 1, statusQueue) - self.AutoTerminateUEandeNB() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def AttachUE_common(self, device_id, statusQueue, lock, idx): - try: - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - if self.ADBCentralized: - if device_id == '84B7N16418004022': - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/on"', '\$', 60) - else: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60) - else: - # airplane mode off // radio on - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) - time.sleep(2) - max_count = 45 - count = max_count - while count > 0: - if self.ADBCentralized: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry" | grep -m 1 mDataConnectionState', '\$', 15) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\' | grep -m 1 mDataConnectionState', '\$', 60) - print('#GP: in SSH.getBefore() K=0 (it was K=2 in main.py)') - result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', SSH.getBefore()) - if result is None: - logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m') - lock.acquire() - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put('mDataConnectionState Not Found!') - lock.release() - break - mDataConnectionState = int(result.group('state')) - if mDataConnectionState == 2: - logging.debug('\u001B[1mUE (' + device_id + ') Attach Completed\u001B[0m') - lock.acquire() - statusQueue.put(max_count - count) - statusQueue.put(device_id) - statusQueue.put('Attach Completed') - lock.release() - break - count = count - 1 - if count == 15 or count == 30: - logging.debug('\u001B[1;30;43m Retry UE (' + device_id + ') Flight Mode Off \u001B[0m') - if self.ADBCentralized: - if device_id == '84B7N16418004022': - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) - else: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) - time.sleep(0.5) - if self.ADBCentralized: - if device_id == '84B7N16418004022': - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/on"', '\$', 60) - else: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/on', '\$', 60) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOnCmd[idx], '\$', 60) - time.sleep(0.5) - logging.debug('\u001B[1mWait UE (' + device_id + ') a second until mDataConnectionState=2 (' + str(max_count-count) + ' times)\u001B[0m') - time.sleep(1) - if count == 0: - logging.debug('\u001B[1;37;41m UE (' + device_id + ') Attach Failed \u001B[0m') - lock.acquire() - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put('Attach Failed') - lock.release() - SSH.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def AttachUE(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - check_eNB = True - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - HTML.CreateHtmlTestRow('N/A', 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - multi_jobs = [] - status_queue = SimpleQueue() - lock = Lock() - nb_ue_to_connect = 0 - for device_id in self.UEDevices: - if (self.nbMaxUEtoAttach == -1) or (nb_ue_to_connect < self.nbMaxUEtoAttach): - self.UEDevicesStatus[nb_ue_to_connect] = CONST.UE_STATUS_ATTACHING - p = Process(target = self.AttachUE_common, args = (device_id, status_queue, lock,nb_ue_to_connect,)) - p.daemon = True - p.start() - multi_jobs.append(p) - nb_ue_to_connect = nb_ue_to_connect + 1 - for job in multi_jobs: - job.join() - - if (status_queue.empty()): - HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ALL_PROCESSES_OK) - self.AutoTerminateUEandeNB() - return - else: - attach_status = True - html_queue = SimpleQueue() - while (not status_queue.empty()): - count = status_queue.get() - if (count < 0): - attach_status = False - device_id = status_queue.get() - message = status_queue.get() - if (count < 0): - html_cell = '
UE (' + device_id + ')\n' + message + '
' - else: - html_cell = '
UE (' + device_id + ')\n' + message + ' in ' + str(count + 2) + ' seconds
' - html_queue.put(html_cell) - if (attach_status): - cnt = 0 - while cnt < len(self.UEDevices): - if self.UEDevicesStatus[cnt] == CONST.UE_STATUS_ATTACHING: - self.UEDevicesStatus[cnt] = CONST.UE_STATUS_ATTACHED - cnt += 1 - HTML.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) - result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args())) - if result is not None: - logging.debug('Waiting 5 seconds to fill up record file') - time.sleep(5) - else: - HTML.CreateHtmlTestRowQueue('N/A', 'KO', len(self.UEDevices), html_queue) - self.AutoTerminateUEandeNB() - - def DetachUE_common(self, device_id, idx): - try: - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - if self.ADBCentralized: - if device_id == '84B7N16418004022': - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) - else: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) - logging.debug('\u001B[1mUE (' + device_id + ') Detach Completed\u001B[0m') - SSH.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def DetachUE(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - check_eNB = True - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - HTML.CreateHtmlTestRow('N/A', 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - multi_jobs = [] - cnt = 0 - for device_id in self.UEDevices: - self.UEDevicesStatus[cnt] = CONST.UE_STATUS_DETACHING - p = Process(target = self.DetachUE_common, args = (device_id,cnt,)) - p.daemon = True - p.start() - multi_jobs.append(p) - cnt += 1 - for job in multi_jobs: - job.join() - HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - result = re.search('T_stdout', str(RAN.GetInitialize_eNB_args())) - if result is not None: - logging.debug('Waiting 5 seconds to fill up record file') - time.sleep(5) - cnt = 0 - while cnt < len(self.UEDevices): - self.UEDevicesStatus[cnt] = CONST.UE_STATUS_DETACHED - cnt += 1 - - def RebootUE_common(self, device_id): - try: - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - previousmDataConnectionStates = [] - # Save mDataConnectionState - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) - result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', SSH.getBefore()) - if result is None: - logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m') - sys.exit(1) - previousmDataConnectionStates.append(int(result.group('state'))) - # Reboot UE - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell reboot', '\$', 10) - time.sleep(60) - previousmDataConnectionState = previousmDataConnectionStates.pop(0) - count = 180 - while count > 0: - count = count - 1 - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell dumpsys telephony.registry | grep mDataConnectionState', '\$', 15) - result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', SSH.getBefore()) - if result is None: - mDataConnectionState = None - else: - mDataConnectionState = int(result.group('state')) - logging.debug('mDataConnectionState = ' + result.group('state')) - if mDataConnectionState is None or (previousmDataConnectionState == 2 and mDataConnectionState != 2): - logging.debug('\u001B[1mWait UE (' + device_id + ') a second until reboot completion (' + str(180-count) + ' times)\u001B[0m') - time.sleep(1) - else: - logging.debug('\u001B[1mUE (' + device_id + ') Reboot Completed\u001B[0m') - break - if count == 0: - logging.debug('\u001B[1;37;41m UE (' + device_id + ') Reboot Failed \u001B[0m') - sys.exit(1) - SSH.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def RebootUE(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - check_eNB = True - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - HTML.CreateHtmlTestRow('N/A', 'KO', pStatus) - HTML.CreateHtmlTabFooter(False) - sys.exit(1) - multi_jobs = [] - for device_id in self.UEDevices: - p = Process(target = self.RebootUE_common, args = (device_id,)) - p.daemon = True - p.start() - multi_jobs.append(p) - for job in multi_jobs: - job.join() - HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - - def DataDisableUE_common(self, device_id, idx): - try: - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - # disable data service - if self.ADBCentralized: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data disable"', '\$', 60) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data disable"\'', '\$', 60) - logging.debug('\u001B[1mUE (' + device_id + ') Disabled Data Service\u001B[0m') - SSH.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def DataDisableUE(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - multi_jobs = [] - i = 0 - for device_id in self.UEDevices: - p = Process(target = self.DataDisableUE_common, args = (device_id,i,)) - p.daemon = True - p.start() - multi_jobs.append(p) - i += 1 - for job in multi_jobs: - job.join() - HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - - def DataEnableUE_common(self, device_id, idx): - try: - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - # enable data service - if self.ADBCentralized: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "svc data enable"', '\$', 60) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "svc data enable"\'', '\$', 60) - logging.debug('\u001B[1mUE (' + device_id + ') Enabled Data Service\u001B[0m') - SSH.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def DataEnableUE(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - multi_jobs = [] - i = 0 - for device_id in self.UEDevices: - p = Process(target = self.DataEnableUE_common, args = (device_id,i,)) - p.daemon = True - p.start() - multi_jobs.append(p) - i += 1 - for job in multi_jobs: - job.join() - HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - - def GetAllUEDevices(self, terminate_ue_flag): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - if self.ADBCentralized: - SSH.command('adb devices', '\$', 15) - #self.UEDevices = re.findall("\\\\r\\\\n([A-Za-z0-9]+)\\\\tdevice",SSH.getBefore()) - self.UEDevices = re.findall("\\\\r\\\\n([A-Za-z0-9]+)\\\\tdevice",SSH.getBefore()) - SSH.close() - else: - if (os.path.isfile('./phones_list.txt')): - os.remove('./phones_list.txt') - SSH.command('ls /etc/*/phones*.txt', '\$', 5) - result = re.search('/etc/ci/phones_list.txt', SSH.getBefore()) - SSH.close() - if (result is not None) and (len(self.UEDevices) == 0): - SSH.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, '/etc/ci/phones_list.txt', '.') - if (os.path.isfile('./phones_list.txt')): - phone_list_file = open('./phones_list.txt', 'r') - for line in phone_list_file.readlines(): - line = line.strip() - result = re.search('^#', line) - if result is not None: - continue - comma_split = line.split(",") - self.UEDevices.append(comma_split[0]) - self.UEDevicesRemoteServer.append(comma_split[1]) - self.UEDevicesRemoteUser.append(comma_split[2]) - self.UEDevicesOffCmd.append(comma_split[3]) - self.UEDevicesOnCmd.append(comma_split[4]) - self.UEDevicesRebootCmd.append(comma_split[5]) - phone_list_file.close() - - if terminate_ue_flag == True: - print('terminate_ue_flag == True') - if len(self.UEDevices) == 0: - logging.debug('\u001B[1;37;41m UE Not Found! \u001B[0m') - sys.exit(1) - if len(self.UEDevicesStatus) == 0: - print('len(self.UEDevicesStatus) == 0') - cnt = 0 - while cnt < len(self.UEDevices): - self.UEDevicesStatus.append(CONST.UE_STATUS_DETACHED) - cnt += 1 - - def GetAllCatMDevices(self, terminate_ue_flag): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - if self.ADBCentralized: - SSH.command('lsusb | egrep "Future Technology Devices International, Ltd FT2232C" | sed -e "s#:.*##" -e "s# #_#g"', '\$', 15) - #self.CatMDevices = re.findall("\\\\r\\\\n([A-Za-z0-9_]+)",SSH.getBefore()) - self.CatMDevices = re.findall("\\\\r\\\\n([A-Za-z0-9_]+)",SSH.getBefore()) - else: - if (os.path.isfile('./modules_list.txt')): - os.remove('./modules_list.txt') - SSH.command('ls /etc/*/modules*.txt', '\$', 5) - result = re.search('/etc/ci/modules_list.txt', SSH.getBefore()) - SSH.close() - if result is not None: - logging.debug('Found a module list file on ADB server') - if terminate_ue_flag == True: - if len(self.CatMDevices) == 0: - logging.debug('\u001B[1;37;41m CAT-M UE Not Found! \u001B[0m') - sys.exit(1) - SSH.close() - - def CheckUEStatus_common(self, lock, device_id, statusQueue, idx): - try: - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - if self.ADBCentralized: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry"', '\$', 15) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\'', '\$', 60) - result = re.search('mServiceState=(?P[0-9]+)', SSH.getBefore()) - serviceState = 'Service State: UNKNOWN' - if result is not None: - lServiceState = int(result.group('serviceState')) - if lServiceState == 3: - serviceState = 'Service State: RADIO_POWERED_OFF' - if lServiceState == 1: - serviceState = 'Service State: OUT_OF_SERVICE' - if lServiceState == 0: - serviceState = 'Service State: IN_SERVICE' - if lServiceState == 2: - serviceState = 'Service State: EMERGENCY_ONLY' - result = re.search('mDataConnectionState=(?P[0-9]+)', SSH.getBefore()) - dataConnectionState = 'Data State: UNKNOWN' - if result is not None: - lDataConnectionState = int(result.group('dataConnectionState')) - if lDataConnectionState == 0: - dataConnectionState = 'Data State: DISCONNECTED' - if lDataConnectionState == 1: - dataConnectionState = 'Data State: CONNECTING' - if lDataConnectionState == 2: - dataConnectionState = 'Data State: CONNECTED' - if lDataConnectionState == 3: - dataConnectionState = 'Data State: SUSPENDED' - result = re.search('mDataConnectionReason=(?P[0-9a-zA-Z_]+)', SSH.getBefore()) - dataConnectionReason = 'Data Reason: UNKNOWN' - if result is not None: - dataConnectionReason = 'Data Reason: ' + result.group('dataConnectionReason') - lock.acquire() - logging.debug('\u001B[1;37;44m Status Check (' + str(device_id) + ') \u001B[0m') - logging.debug('\u001B[1;34m ' + serviceState + '\u001B[0m') - logging.debug('\u001B[1;34m ' + dataConnectionState + '\u001B[0m') - logging.debug('\u001B[1;34m ' + dataConnectionReason + '\u001B[0m') - statusQueue.put(0) - statusQueue.put(device_id) - qMsg = serviceState + '\n' + dataConnectionState + '\n' + dataConnectionReason - statusQueue.put(qMsg) - lock.release() - SSH.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def CheckStatusUE(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - check_eNB = True - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - HTML.CreateHtmlTestRow('N/A', 'KO', pStatus) - HTML.CreateHtmlTabFooter(False) - sys.exit(1) - multi_jobs = [] - lock = Lock() - status_queue = SimpleQueue() - i = 0 - for device_id in self.UEDevices: - p = Process(target = self.CheckUEStatus_common, args = (lock,device_id,status_queue,i,)) - p.daemon = True - p.start() - multi_jobs.append(p) - i += 1 - for job in multi_jobs: - job.join() - if self.flexranCtrlInstalled and self.flexranCtrlStarted: - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('cd /opt/flexran_rtc', '\$', 5) - SSH.command('curl http://localhost:9999/stats | jq \'.\' > log/check_status_' + self.testCase_id + '.log 2>&1', '\$', 5) - SSH.command('cat log/check_status_' + self.testCase_id + '.log | jq \'.eNB_config[0].UE\' | grep -c rnti | sed -e "s#^#Nb Connected UE = #"', '\$', 5) - result = re.search('Nb Connected UE = (?P[0-9]+)', SSH.getBefore()) - passStatus = True - if result is not None: - nb_ues = int(result.group('nb_ues')) - htmlOptions = 'Nb Connected UE(s) to eNB = ' + str(nb_ues) - logging.debug('\u001B[1;37;44m ' + htmlOptions + ' \u001B[0m') - if self.expectedNbOfConnectedUEs > -1: - if nb_ues != self.expectedNbOfConnectedUEs: - passStatus = False - else: - htmlOptions = 'N/A' - SSH.close() - else: - passStatus = True - htmlOptions = 'N/A' - - if (status_queue.empty()): - HTML.CreateHtmlTestRow(htmlOptions, 'KO', CONST.ALL_PROCESSES_OK) - self.AutoTerminateUEandeNB() - else: - check_status = True - html_queue = SimpleQueue() - while (not status_queue.empty()): - count = status_queue.get() - if (count < 0): - check_status = False - device_id = status_queue.get() - message = status_queue.get() - html_cell = '
UE (' + device_id + ')\n' + message + '
' - html_queue.put(html_cell) - if check_status and passStatus: - HTML.CreateHtmlTestRowQueue(htmlOptions, 'OK', len(self.UEDevices), html_queue) - else: - HTML.CreateHtmlTestRowQueue(htmlOptions, 'KO', len(self.UEDevices), html_queue) - self.AutoTerminateUEandeNB() - - def GetAllUEIPAddresses(self): - if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - ue_ip_status = 0 - self.UEIPAddresses = [] - if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): - if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - SSH.command('ifconfig oaitun_ue1', '\$', 4) - result = re.search('inet addr:(?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)|inet (?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)', SSH.getBefore()) - if result is not None: - if result.group('ueipaddress') is not None: - UE_IPAddress = result.group('ueipaddress') - else: - UE_IPAddress = result.group('ueipaddress2') - logging.debug('\u001B[1mUE (' + self.UEDevices[0] + ') IP Address is ' + UE_IPAddress + '\u001B[0m') - self.UEIPAddresses.append(UE_IPAddress) - else: - logging.debug('\u001B[1;37;41m UE IP Address Not Found! \u001B[0m') - ue_ip_status -= 1 - SSH.close() - return ue_ip_status - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - idx = 0 - for device_id in self.UEDevices: - print('UE status attched'+CONST.UE_STATUS_ATTACHED) - if self.UEDevicesStatus[idx] != CONST.UE_STATUS_ATTACHED: - idx += 1 - continue - count = 0 - while count < 4: - if self.ADBCentralized: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "ip addr show | grep rmnet"', '\$', 15) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ip addr show | grep rmnet"\'', '\$', 60) - result = re.search('inet (?P[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\/[0-9]+[0-9a-zA-Z\.\s]+', SSH.getBefore()) - if result is None: - logging.debug('\u001B[1;37;41m UE IP Address Not Found! \u001B[0m') - time.sleep(1) - count += 1 - else: - count = 10 - if count < 9: - ue_ip_status -= 1 - continue - UE_IPAddress = result.group('ueipaddress') - logging.debug('\u001B[1mUE (' + device_id + ') IP Address is ' + UE_IPAddress + '\u001B[0m') - for ueipaddress in self.UEIPAddresses: - if ueipaddress == UE_IPAddress: - logging.debug('\u001B[1mUE (' + device_id + ') IP Address ' + UE_IPAddress + ': has already been allocated to another device !' + '\u001B[0m') - ue_ip_status -= 1 - continue - self.UEIPAddresses.append(UE_IPAddress) - idx += 1 - SSH.close() - return ue_ip_status - - def ping_iperf_wrong_exit(self, lock, UE_IPAddress, device_id, statusQueue, message): - lock.acquire() - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - statusQueue.put(message) - lock.release() - - def Ping_common(self, lock, UE_IPAddress, device_id, statusQueue): - try: - # Launch ping on the EPC side (true for ltebox and old open-air-cn) - # But for OAI-Rel14-CUPS, we launch from python executor - launchFromEpc = True - if re.match('OAI-Rel14-CUPS', EPC.GetType(), re.IGNORECASE): - launchFromEpc = False - ping_time = re.findall("-c (\d+)",str(self.ping_args)) - - if launchFromEpc: - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('cd ' + EPC.GetSourceCodePath(), '\$', 5) - SSH.command('cd scripts', '\$', 5) - ping_status = SSH.command('stdbuf -o0 ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '_' + device_id + '.log', '\$', int(ping_time[0])*1.5) - else: - cmd = 'ping ' + self.ping_args + ' ' + UE_IPAddress + ' 2>&1 > ping_' + self.testCase_id + '_' + device_id + '.log' - message = cmd + '\n' - logging.debug(cmd) - ret = subprocess.run(cmd, shell=True) - ping_status = ret.returncode - SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'ping_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('cat ' + EPC.GetSourceCodePath() + '/scripts/ping_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - # TIMEOUT CASE - if ping_status < 0: - message = 'Ping with UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - SSH.close() - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) - return - result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', SSH.getBefore()) - if result is None: - message = 'Packet Loss Not Found!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - SSH.close() - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) - return - packetloss = result.group('packetloss') - if float(packetloss) == 100: - message = 'Packet Loss is 100%' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - SSH.close() - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) - return - result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', SSH.getBefore()) - if result is None: - message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - SSH.close() - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) - return - rtt_min = result.group('rtt_min') - rtt_avg = result.group('rtt_avg') - rtt_max = result.group('rtt_max') - pal_msg = 'Packet Loss : ' + packetloss + '%' - min_msg = 'RTT(Min) : ' + rtt_min + ' ms' - avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms' - max_msg = 'RTT(Max) : ' + rtt_max + ' ms' - lock.acquire() - logging.debug('\u001B[1;37;44m ping result (' + UE_IPAddress + ') \u001B[0m') - logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') - qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg - packetLossOK = True - if packetloss is not None: - if float(packetloss) > float(self.ping_packetloss_threshold): - qMsg += '\nPacket Loss too high' - logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') - packetLossOK = False - elif float(packetloss) > 0: - qMsg += '\nPacket Loss is not 0%' - logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m') - if (packetLossOK): - statusQueue.put(0) - else: - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - statusQueue.put(qMsg) - lock.release() - SSH.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def PingNoS1_wrong_exit(self, qMsg): - html_queue = SimpleQueue() - html_cell = '
OAI UE ping result\n' + qMsg + '
' - html_queue.put(html_cell) - HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) - - def PingNoS1(self): - check_eNB = True - check_OAI_UE = True - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - ping_from_eNB = re.search('oaitun_enb1', str(self.ping_args)) - if ping_from_eNB is not None: - if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - else: - if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - try: - if ping_from_eNB is not None: - SSH.open(RAN.GeteNBIPAddress, RAN.GeteNBUserName, RAN.GeteNBPassword) - SSH.command('cd ' + RAN.GeteNBSourceCodePath() + '/cmake_targets/', '\$', 5) - else: - SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets/', '\$', 5) - ping_time = re.findall("-c (\d+)",str(self.ping_args)) - ping_status = SSH.command('stdbuf -o0 ping ' + self.ping_args + ' 2>&1 | stdbuf -o0 tee ping_' + self.testCase_id + '.log', '\$', int(ping_time[0])*1.5) - # TIMEOUT CASE - if ping_status < 0: - message = 'Ping with OAI UE crashed due to TIMEOUT!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.PingNoS1_wrong_exit(message) - return - result = re.search(', (?P[0-9\.]+)% packet loss, time [0-9\.]+ms', SSH.getBefore()) - if result is None: - message = 'Packet Loss Not Found!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.PingNoS1_wrong_exit(message) - return - packetloss = result.group('packetloss') - if float(packetloss) == 100: - message = 'Packet Loss is 100%' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.PingNoS1_wrong_exit(message) - return - result = re.search('rtt min\/avg\/max\/mdev = (?P[0-9\.]+)\/(?P[0-9\.]+)\/(?P[0-9\.]+)\/[0-9\.]+ ms', SSH.getBefore()) - if result is None: - message = 'Ping RTT_Min RTT_Avg RTT_Max Not Found!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.PingNoS1_wrong_exit(message) - return - rtt_min = result.group('rtt_min') - rtt_avg = result.group('rtt_avg') - rtt_max = result.group('rtt_max') - pal_msg = 'Packet Loss : ' + packetloss + '%' - min_msg = 'RTT(Min) : ' + rtt_min + ' ms' - avg_msg = 'RTT(Avg) : ' + rtt_avg + ' ms' - max_msg = 'RTT(Max) : ' + rtt_max + ' ms' - logging.debug('\u001B[1;37;44m OAI UE ping result \u001B[0m') - logging.debug('\u001B[1;34m ' + pal_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + min_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + avg_msg + '\u001B[0m') - logging.debug('\u001B[1;34m ' + max_msg + '\u001B[0m') - qMsg = pal_msg + '\n' + min_msg + '\n' + avg_msg + '\n' + max_msg - packetLossOK = True - if packetloss is not None: - if float(packetloss) > float(self.ping_packetloss_threshold): - qMsg += '\nPacket Loss too high' - logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') - packetLossOK = False - elif float(packetloss) > 0: - qMsg += '\nPacket Loss is not 0%' - logging.debug('\u001B[1;30;43m Packet Loss is not 0% \u001B[0m') - SSH.close() - html_queue = SimpleQueue() - ip_addr = 'TBD' - html_cell = '
OAI UE ping result\n' + qMsg + '
' - html_queue.put(html_cell) - if packetLossOK: - HTML.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) - else: - HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) - - # copying on the EPC server for logCollection - if ping_from_eNB is not None: - copyin_res = SSH.copyin(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath() + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') - else: - copyin_res = SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/ping_' + self.testCase_id + '.log', '.') - if (copyin_res == 0): - SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'ping_' + self.testCase_id + '.log', EPC.GetSourceCodePath() + '/scripts') - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def Ping(self): - result = re.search('noS1', str(RAN.GetInitialize_eNB_args())) - if result is not None: - self.PingNoS1() - return - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - check_eNB = True - if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): - check_OAI_UE = True - else: - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - HTML.CreateHtmlTestRow(self.ping_args, 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - ueIpStatus = self.GetAllUEIPAddresses() - if (ueIpStatus < 0): - HTML.CreateHtmlTestRow(self.ping_args, 'KO', CONST.UE_IP_ADDRESS_ISSUE) - self.AutoTerminateUEandeNB() - return - multi_jobs = [] - i = 0 - lock = Lock() - status_queue = SimpleQueue() - for UE_IPAddress in self.UEIPAddresses: - device_id = self.UEDevices[i] - p = Process(target = self.Ping_common, args = (lock,UE_IPAddress,device_id,status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - i = i + 1 - for job in multi_jobs: - job.join() - - if (status_queue.empty()): - HTML.CreateHtmlTestRow(self.ping_args, 'KO', CONST.ALL_PROCESSES_OK) - self.AutoTerminateUEandeNB() - else: - ping_status = True - html_queue = SimpleQueue() - while (not status_queue.empty()): - count = status_queue.get() - if (count < 0): - ping_status = False - device_id = status_queue.get() - ip_addr = status_queue.get() - message = status_queue.get() - html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' - html_queue.put(html_cell) - if (ping_status): - HTML.CreateHtmlTestRowQueue(self.ping_args, 'OK', len(self.UEDevices), html_queue) - else: - HTML.CreateHtmlTestRowQueue(self.ping_args, 'KO', len(self.UEDevices), html_queue) - self.AutoTerminateUEandeNB() - - def Iperf_ComputeTime(self): - result = re.search('-t (?P\d+)', str(self.iperf_args)) - if result is None: - logging.debug('\u001B[1;37;41m Iperf time Not Found! \u001B[0m') - sys.exit(1) - return result.group('iperf_time') - - def Iperf_ComputeModifiedBW(self, idx, ue_num): - result = re.search('-b (?P[0-9\.]+)[KMG]', str(self.iperf_args)) - if result is None: - logging.debug('\u001B[1;37;41m Iperf bandwidth Not Found! \u001B[0m') - sys.exit(1) - iperf_bandwidth = result.group('iperf_bandwidth') - if self.iperf_profile == 'balanced': - iperf_bandwidth_new = float(iperf_bandwidth)/ue_num - if self.iperf_profile == 'single-ue': - iperf_bandwidth_new = float(iperf_bandwidth) - if self.iperf_profile == 'unbalanced': - # residual is 2% of max bw - residualBW = float(iperf_bandwidth) / 50 - if idx == 0: - iperf_bandwidth_new = float(iperf_bandwidth) - ((ue_num - 1) * residualBW) - else: - iperf_bandwidth_new = residualBW - iperf_bandwidth_str = '-b ' + iperf_bandwidth - iperf_bandwidth_str_new = '-b ' + ('%.2f' % iperf_bandwidth_new) - result = re.sub(iperf_bandwidth_str, iperf_bandwidth_str_new, str(self.iperf_args)) - if result is None: - logging.debug('\u001B[1;37;41m Calculate Iperf bandwidth Failed! \u001B[0m') - sys.exit(1) - return result - - def Iperf_analyzeV2TCPOutput(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): - SSH.command('awk -f /tmp/tcp_iperf_stats.awk /tmp/CI-eNB/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - result = re.search('Avg Bitrate : (?P[0-9\.]+ Mbits\/sec) Max Bitrate : (?P[0-9\.]+ Mbits\/sec) Min Bitrate : (?P[0-9\.]+ Mbits\/sec)', SSH.getBefore()) - if result is not None: - avgbitrate = result.group('average') - maxbitrate = result.group('maximum') - minbitrate = result.group('minimum') - lock.acquire() - logging.debug('\u001B[1;37;44m TCP iperf result (' + UE_IPAddress + ') \u001B[0m') - msg = 'TCP Stats :\n' - if avgbitrate is not None: - logging.debug('\u001B[1;34m Avg Bitrate : ' + avgbitrate + '\u001B[0m') - msg += 'Avg Bitrate : ' + avgbitrate + '\n' - if maxbitrate is not None: - logging.debug('\u001B[1;34m Max Bitrate : ' + maxbitrate + '\u001B[0m') - msg += 'Max Bitrate : ' + maxbitrate + '\n' - if minbitrate is not None: - logging.debug('\u001B[1;34m Min Bitrate : ' + minbitrate + '\u001B[0m') - msg += 'Min Bitrate : ' + minbitrate + '\n' - statusQueue.put(0) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - statusQueue.put(msg) - lock.release() - return 0 - - def Iperf_analyzeV2Output(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): - result = re.search('-u', str(iperf_real_options)) - if result is None: - return self.Iperf_analyzeV2TCPOutput(lock, UE_IPAddress, device_id, statusQueue, iperf_real_options) - - result = re.search('Server Report:', SSH.getBefore()) - if result is None: - result = re.search('read failed: Connection refused', SSH.getBefore()) - if result is not None: - logging.debug('\u001B[1;37;41m Could not connect to iperf server! \u001B[0m') - else: - logging.debug('\u001B[1;37;41m Server Report and Connection refused Not Found! \u001B[0m') - return -1 - # Computing the requested bandwidth in float - result = re.search('-b (?P[0-9\.]+)[KMG]', str(iperf_real_options)) - if result is not None: - req_bandwidth = result.group('iperf_bandwidth') - req_bw = float(req_bandwidth) - result = re.search('-b [0-9\.]+K', str(iperf_real_options)) - if result is not None: - req_bandwidth = '%.1f Kbits/sec' % req_bw - req_bw = req_bw * 1000 - result = re.search('-b [0-9\.]+M', str(iperf_real_options)) - if result is not None: - req_bandwidth = '%.1f Mbits/sec' % req_bw - req_bw = req_bw * 1000000 - result = re.search('-b [0-9\.]+G', str(iperf_real_options)) - if result is not None: - req_bandwidth = '%.1f Gbits/sec' % req_bw - req_bw = req_bw * 1000000000 - - result = re.search('Server Report:\\\\r\\\\n(?:|\[ *\d+\].*) (?P[0-9\.]+ [KMG]bits\/sec) +(?P[0-9\.]+ ms) +(\d+\/..\d+) +(\((?P[0-9\.]+)%\))', SSH.getBefore()) - if result is not None: - bitrate = result.group('bitrate') - packetloss = result.group('packetloss') - jitter = result.group('jitter') - lock.acquire() - logging.debug('\u001B[1;37;44m iperf result (' + UE_IPAddress + ') \u001B[0m') - iperfStatus = True - msg = 'Req Bitrate : ' + req_bandwidth + '\n' - logging.debug('\u001B[1;34m Req Bitrate : ' + req_bandwidth + '\u001B[0m') - if bitrate is not None: - msg += 'Bitrate : ' + bitrate + '\n' - logging.debug('\u001B[1;34m Bitrate : ' + bitrate + '\u001B[0m') - result = re.search('(?P[0-9\.]+) [KMG]bits/sec', str(bitrate)) - if result is not None: - actual_bw = float(str(result.group('real_bw'))) - result = re.search('[0-9\.]+ K', bitrate) - if result is not None: - actual_bw = actual_bw * 1000 - result = re.search('[0-9\.]+ M', bitrate) - if result is not None: - actual_bw = actual_bw * 1000000 - result = re.search('[0-9\.]+ G', bitrate) - if result is not None: - actual_bw = actual_bw * 1000000000 - br_loss = 100 * actual_bw / req_bw - bitperf = '%.2f ' % br_loss - msg += 'Bitrate Perf: ' + bitperf + '%\n' - logging.debug('\u001B[1;34m Bitrate Perf: ' + bitperf + '%\u001B[0m') - if packetloss is not None: - msg += 'Packet Loss : ' + packetloss + '%\n' - logging.debug('\u001B[1;34m Packet Loss : ' + packetloss + '%\u001B[0m') - if float(packetloss) > float(self.iperf_packetloss_threshold): - msg += 'Packet Loss too high!\n' - logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') - iperfStatus = False - if jitter is not None: - msg += 'Jitter : ' + jitter + '\n' - logging.debug('\u001B[1;34m Jitter : ' + jitter + '\u001B[0m') - if (iperfStatus): - statusQueue.put(0) - else: - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - statusQueue.put(msg) - lock.release() - return 0 - else: - return -2 - - def Iperf_analyzeV2Server(self, lock, UE_IPAddress, device_id, statusQueue, iperf_real_options): - if (not os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not analyze from server log') - return - # Computing the requested bandwidth in float - result = re.search('-b (?P[0-9\.]+)[KMG]', str(iperf_real_options)) - if result is None: - logging.debug('Iperf bandwidth Not Found!') - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not compute Iperf bandwidth!') - return - else: - req_bandwidth = result.group('iperf_bandwidth') - req_bw = float(req_bandwidth) - result = re.search('-b [0-9\.]+K', str(iperf_real_options)) - if result is not None: - req_bandwidth = '%.1f Kbits/sec' % req_bw - req_bw = req_bw * 1000 - result = re.search('-b [0-9\.]+M', str(iperf_real_options)) - if result is not None: - req_bandwidth = '%.1f Mbits/sec' % req_bw - req_bw = req_bw * 1000000 - result = re.search('-b [0-9\.]+G', str(iperf_real_options)) - if result is not None: - req_bandwidth = '%.1f Gbits/sec' % req_bw - req_bw = req_bw * 1000000000 - - server_file = open('iperf_server_' + self.testCase_id + '_' + device_id + '.log', 'r') - br_sum = 0.0 - ji_sum = 0.0 - pl_sum = 0 - ps_sum = 0 - row_idx = 0 - for line in server_file.readlines(): - result = re.search('(?P[0-9\.]+ [KMG]bits\/sec) +(?P[0-9\.]+ ms) +(?P[0-9]+)/ +(?P[0-9]+)', str(line)) - if result is not None: - bitrate = result.group('bitrate') - jitter = result.group('jitter') - packetlost = result.group('lostPack') - packetsent = result.group('sentPack') - br = bitrate.split(' ') - ji = jitter.split(' ') - row_idx = row_idx + 1 - curr_br = float(br[0]) - pl_sum = pl_sum + int(packetlost) - ps_sum = ps_sum + int(packetsent) - if (br[1] == 'Kbits/sec'): - curr_br = curr_br * 1000 - if (br[1] == 'Mbits/sec'): - curr_br = curr_br * 1000 * 1000 - br_sum = curr_br + br_sum - ji_sum = float(ji[0]) + ji_sum - if (row_idx > 0): - br_sum = br_sum / row_idx - ji_sum = ji_sum / row_idx - br_loss = 100 * br_sum / req_bw - if (br_sum > 1000): - br_sum = br_sum / 1000 - if (br_sum > 1000): - br_sum = br_sum / 1000 - bitrate = '%.2f Mbits/sec' % br_sum - else: - bitrate = '%.2f Kbits/sec' % br_sum - else: - bitrate = '%.2f bits/sec' % br_sum - bitperf = '%.2f ' % br_loss - bitperf += '%' - jitter = '%.2f ms' % (ji_sum) - if (ps_sum > 0): - pl = float(100 * pl_sum / ps_sum) - packetloss = '%2.1f ' % (pl) - packetloss += '%' - else: - packetloss = 'unknown' - lock.acquire() - if (br_loss < 90): - statusQueue.put(1) - else: - statusQueue.put(0) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - req_msg = 'Req Bitrate : ' + req_bandwidth - bir_msg = 'Bitrate : ' + bitrate - brl_msg = 'Bitrate Perf: ' + bitperf - jit_msg = 'Jitter : ' + jitter - pal_msg = 'Packet Loss : ' + packetloss - statusQueue.put(req_msg + '\n' + bir_msg + '\n' + brl_msg + '\n' + jit_msg + '\n' + pal_msg + '\n') - logging.debug('\u001B[1;37;45m iperf result (' + UE_IPAddress + ') \u001B[0m') - logging.debug('\u001B[1;35m ' + req_msg + '\u001B[0m') - logging.debug('\u001B[1;35m ' + bir_msg + '\u001B[0m') - logging.debug('\u001B[1;35m ' + brl_msg + '\u001B[0m') - logging.debug('\u001B[1;35m ' + jit_msg + '\u001B[0m') - logging.debug('\u001B[1;35m ' + pal_msg + '\u001B[0m') - lock.release() - else: - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, 'Could not analyze from server log') - - server_file.close() - - - def Iperf_analyzeV3Output(self, lock, UE_IPAddress, device_id, statusQueue): - result = re.search('(?P[0-9\.]+ [KMG]bits\/sec) +(?:|[0-9\.]+ ms +\d+\/\d+ \((?P[0-9\.]+)%\)) +(?:|receiver)\\\\r\\\\n(?:|\[ *\d+\] Sent \d+ datagrams)\\\\r\\\\niperf Done\.', SSH.getBefore()) - if result is None: - result = re.search('(?Piperf: error - [a-zA-Z0-9 :]+)', SSH.getBefore()) - lock.acquire() - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - if result is not None: - logging.debug('\u001B[1;37;41m ' + result.group('error') + ' \u001B[0m') - statusQueue.put(result.group('error')) - else: - logging.debug('\u001B[1;37;41m Bitrate and/or Packet Loss Not Found! \u001B[0m') - statusQueue.put('Bitrate and/or Packet Loss Not Found!') - lock.release() - - bitrate = result.group('bitrate') - packetloss = result.group('packetloss') - lock.acquire() - logging.debug('\u001B[1;37;44m iperf result (' + UE_IPAddress + ') \u001B[0m') - logging.debug('\u001B[1;34m Bitrate : ' + bitrate + '\u001B[0m') - msg = 'Bitrate : ' + bitrate + '\n' - iperfStatus = True - if packetloss is not None: - logging.debug('\u001B[1;34m Packet Loss : ' + packetloss + '%\u001B[0m') - msg += 'Packet Loss : ' + packetloss + '%\n' - if float(packetloss) > float(self.iperf_packetloss_threshold): - logging.debug('\u001B[1;37;41m Packet Loss too high \u001B[0m') - msg += 'Packet Loss too high!\n' - iperfStatus = False - if (iperfStatus): - statusQueue.put(0) - else: - statusQueue.put(-1) - statusQueue.put(device_id) - statusQueue.put(UE_IPAddress) - statusQueue.put(msg) - lock.release() - - def Iperf_UL_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue): - udpIperf = True - result = re.search('-u', str(self.iperf_args)) - if result is None: - udpIperf = False - ipnumbers = UE_IPAddress.split('.') - if (len(ipnumbers) == 4): - ipnumbers[3] = '1' - EPC_Iperf_UE_IPAddress = ipnumbers[0] + '.' + ipnumbers[1] + '.' + ipnumbers[2] + '.' + ipnumbers[3] - - # Launch iperf server on EPC side (true for ltebox and old open-air-cn0 - # But for OAI-Rel14-CUPS, we launch from python executor and we are using its IP address as iperf client address - launchFromEpc = True - if re.match('OAI-Rel14-CUPS', EPC.GetType(), re.IGNORECASE): - launchFromEpc = False - cmd = 'hostname -I' - ret = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, encoding='utf-8') - if ret.stdout is not None: - EPC_Iperf_UE_IPAddress = ret.stdout.strip() - port = 5001 + idx - if launchFromEpc: - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) - SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - if udpIperf: - SSH.command('echo $USER; nohup iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', EPC.GetUserName(), 5) - else: - SSH.command('echo $USER; nohup iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', EPC.GetUserName(), 5) - SSH.close() - else: - if self.ueIperfVersion == self.dummyIperfVersion: - prefix = '' - else: - prefix = '' - if self.ueIperfVersion == '2.0.5': - prefix = '/opt/iperf-2.0.5/bin/' - if udpIperf: - cmd = 'nohup ' + prefix + 'iperf -u -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log 2>&1 &' - else: - cmd = 'nohup ' + prefix + 'iperf -s -i 1 -p ' + str(port) + ' > iperf_server_' + self.testCase_id + '_' + device_id + '.log 2>&1 &' - logging.debug(cmd) - subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, encoding='utf-8') - time.sleep(0.5) - - # Launch iperf client on UE - if (device_id == 'OAI-UE'): - SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) - else: - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) - iperf_time = self.Iperf_ComputeTime() - time.sleep(0.5) - - if udpIperf: - modified_options = self.Iperf_ComputeModifiedBW(idx, ue_num) - else: - modified_options = str(self.iperf_args) - modified_options = modified_options.replace('-R','') - time.sleep(0.5) - - SSH.command('rm -f iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - if (device_id == 'OAI-UE'): - iperf_status = SSH.command('iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + ' -B ' + UE_IPAddress + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) - else: - if self.ADBCentralized: - iperf_status = SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '" 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) - else: - iperf_status = SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf -c ' + EPC_Iperf_UE_IPAddress + ' ' + modified_options + ' -p ' + str(port) + '"\' 2>&1 > iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) - SSH.command('fromdos -o iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - SSH.command('cat iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - # TIMEOUT Case - if iperf_status < 0: - SSH.close() - message = 'iperf on UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT !' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - SSH.close() - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) - return - clientStatus = self.Iperf_analyzeV2Output(lock, UE_IPAddress, device_id, statusQueue, modified_options) - SSH.close() - - # Kill iperf server on EPC side - if launchFromEpc: - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('killall --signal SIGKILL iperf', EPC.GetUserName(), 5) - SSH.close() - else: - cmd = 'killall --signal SIGKILL iperf' - logging.debug(cmd) - subprocess.run(cmd, shell=True) - time.sleep(1) - SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') - # in case of failure, retrieve server log - if (clientStatus == -1) or (clientStatus == -2): - if launchFromEpc: - time.sleep(1) - if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): - os.remove('iperf_server_' + self.testCase_id + '_' + device_id + '.log') - SSH.copyin(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), EPC.GetSourceCodePath() + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') - self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) - # in case of OAI-UE - if (device_id == 'OAI-UE'): - SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_' + self.testCase_id + '_' + device_id + '.log', '.') - SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') - - def Iperf_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue): - try: - logging.debug('entring Iperf_common') - # Single-UE profile -- iperf only on one UE - if self.iperf_profile == 'single-ue' and idx != 0: - return - useIperf3 = False - udpIperf = True - - self.ueIperfVersion = '2.0.5' - if (device_id != 'OAI-UE'): - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - # if by chance ADB server and EPC are on the same remote host, at least log collection will take care of it - SSH.command('if [ ! -d ' + EPC.GetSourceCodePath() + '/scripts ]; then mkdir -p ' + EPC.GetSourceCodePath() + '/scripts ; fi', '\$', 5) - SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) - # Checking if iperf / iperf3 are installed - if self.ADBCentralized: - SSH.command('adb -s ' + device_id + ' shell "ls /data/local/tmp"', '\$', 5) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ls /data/local/tmp"\'', '\$', 60) - result = re.search('iperf3', SSH.getBefore()) - if result is None: - result = re.search('iperf', SSH.getBefore()) - if result is None: - message = 'Neither iperf nor iperf3 installed on UE!' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - SSH.close() - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) - return - else: - if self.ADBCentralized: - SSH.command('adb -s ' + device_id + ' shell "/data/local/tmp/iperf --version"', '\$', 5) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf --version"\'', '\$', 60) - result = re.search('iperf version 2.0.5', SSH.getBefore()) - if result is not None: - self.ueIperfVersion = '2.0.5' - result = re.search('iperf version 2.0.10', SSH.getBefore()) - if result is not None: - self.ueIperfVersion = '2.0.10' - else: - useIperf3 = True - SSH.close() - else: - SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - SSH.command('iperf --version', '\$', 5) - result = re.search('iperf version 2.0.5', SSH.getBefore()) - if result is not None: - self.ueIperfVersion = '2.0.5' - result = re.search('iperf version 2.0.10', SSH.getBefore()) - if result is not None: - self.ueIperfVersion = '2.0.10' - SSH.close() - # in case of iperf, UL has its own function - if (not useIperf3): - result = re.search('-R', str(self.iperf_args)) - if result is not None: - self.Iperf_UL_common(lock, UE_IPAddress, device_id, idx, ue_num, statusQueue) - return - - # Launch the IPERF server on the UE side for DL - if (device_id == 'OAI-UE'): - SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) - SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - result = re.search('-u', str(self.iperf_args)) - if result is None: - SSH.command('echo $USER; nohup iperf -B ' + UE_IPAddress + ' -s -i 1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.UEUserName, 5) - udpIperf = False - else: - SSH.command('echo $USER; nohup iperf -B ' + UE_IPAddress + ' -u -s -i 1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.UEUserName, 5) - else: - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) - if self.ADBCentralized: - if (useIperf3): - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/iperf3 -s &', '\$', 5) - else: - SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - result = re.search('-u', str(self.iperf_args)) - if result is None: - SSH.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) - udpIperf = False - else: - SSH.command('echo $USER; nohup adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 5) - else: - SSH.command('rm -f iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - SSH.command('echo $USER; nohup ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "/data/local/tmp/iperf -u -s -i 1" \' 2>&1 > iperf_server_' + self.testCase_id + '_' + device_id + '.log &', self.ADBUserName, 60) - - time.sleep(0.5) - SSH.close() - - # Launch the IPERF client on the EPC side for DL (true for ltebox and old open-air-cn - # But for OAI-Rel14-CUPS, we launch from python executor - launchFromEpc = True - if re.match('OAI-Rel14-CUPS', EPC.GetType(), re.IGNORECASE): - launchFromEpc = False - if launchFromEpc: - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('cd ' + EPC.GetSourceCodePath() + '/scripts', '\$', 5) - iperf_time = self.Iperf_ComputeTime() - time.sleep(0.5) - - if udpIperf: - modified_options = self.Iperf_ComputeModifiedBW(idx, ue_num) - else: - modified_options = str(self.iperf_args) - time.sleep(0.5) - - if launchFromEpc: - SSH.command('rm -f iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - else: - if (os.path.isfile('iperf_' + self.testCase_id + '_' + device_id + '.log')): - os.remove('iperf_' + self.testCase_id + '_' + device_id + '.log') - if (useIperf3): - SSH.command('stdbuf -o0 iperf3 -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) - - clientStatus = 0 - self.Iperf_analyzeV3Output(lock, UE_IPAddress, device_id, statusQueue) - else: - if launchFromEpc: - iperf_status = SSH.command('stdbuf -o0 iperf -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 | stdbuf -o0 tee iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', int(iperf_time)*5.0) - else: - if self.ueIperfVersion == self.dummyIperfVersion: - prefix = '' - else: - prefix = '' - if self.ueIperfVersion == '2.0.5': - prefix = '/opt/iperf-2.0.5/bin/' - cmd = prefix + 'iperf -c ' + UE_IPAddress + ' ' + modified_options + ' 2>&1 > iperf_' + self.testCase_id + '_' + device_id + '.log' - message = cmd + '\n' - logging.debug(cmd) - ret = subprocess.run(cmd, shell=True) - iperf_status = ret.returncode - SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('cat ' + EPC.GetSourceCodePath() + '/scripts/iperf_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - if iperf_status < 0: - if launchFromEpc: - SSH.close() - message = 'iperf on UE (' + str(UE_IPAddress) + ') crashed due to TIMEOUT !' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - self.ping_iperf_wrong_exit(lock, UE_IPAddress, device_id, statusQueue, message) - return - clientStatus = self.Iperf_analyzeV2Output(lock, UE_IPAddress, device_id, statusQueue, modified_options) - SSH.close() - - # Kill the IPERF server that runs in background - if (device_id == 'OAI-UE'): - SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - SSH.command('killall iperf', '\$', 5) - else: - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - if self.ADBCentralized: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell ps | grep --color=never iperf | grep -v grep', '\$', 5) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ps" | grep --color=never iperf | grep -v grep\'', '\$', 60) - result = re.search('shell +(?P\d+)', SSH.getBefore()) - if result is not None: - pid_iperf = result.group('pid') - if self.ADBCentralized: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell kill -KILL ' + pid_iperf, '\$', 5) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"\'', '\$', 60) - SSH.close() - # if the client report is absent, try to analyze the server log file - if (clientStatus == -1): - time.sleep(1) - if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): - os.remove('iperf_server_' + self.testCase_id + '_' + device_id + '.log') - if (device_id == 'OAI-UE'): - SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') - else: - SSH.copyin(self.ADBIPAddress, self.ADBUserName, self.ADBPassword, EPC.GetSourceCodePath() + '/scripts/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') - SSH.command('fromdos -o iperf_server_' + self.testCase_id + '_' + device_id + '.log', '\$', 5) - # fromdos has to be called on the python executor not on ADB server - cmd = 'fromdos -o iperf_server_' + self.testCase_id + '_' + device_id + '.log' - subprocess.run(cmd, shell=True) - self.Iperf_analyzeV2Server(lock, UE_IPAddress, device_id, statusQueue, modified_options) - - # in case of OAI UE: - if (device_id == 'OAI-UE'): - if (os.path.isfile('iperf_server_' + self.testCase_id + '_' + device_id + '.log')): - if not launchFromEpc: - SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') - else: - SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/iperf_server_' + self.testCase_id + '_' + device_id + '.log', '.') - SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_server_' + self.testCase_id + '_' + device_id + '.log', EPC.GetSourceCodePath() + '/scripts') - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def IperfNoS1(self): - if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - check_eNB = True - check_OAI_UE = True - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - HTML.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - server_on_enb = re.search('-R', str(self.iperf_args)) - if server_on_enb is not None: - iServerIPAddr = RAN.GeteNBIPAddress() - iServerUser = RAN.GeteNBUserName() - iServerPasswd = RAN.GeteNBPassword() - iClientIPAddr = self.UEIPAddress - iClientUser = self.UEUserName - iClientPasswd = self.UEPassword - else: - iServerIPAddr = self.UEIPAddress - iServerUser = self.UEUserName - iServerPasswd = self.UEPassword - iClientIPAddr = RAN.GeteNBIPAddress() - iClientUser = RAN.GeteNBUserName() - iClientPasswd = RAN.GeteNBPassword() - if self.iperf_options != 'sink': - # Starting the iperf server - SSH.open(iServerIPAddr, iServerUser, iServerPasswd) - # args SHALL be "-c client -u any" - # -c 10.0.1.2 -u -b 1M -t 30 -i 1 -fm -B 10.0.1.1 - # -B 10.0.1.1 -u -s -i 1 -fm - server_options = re.sub('-u.*$', '-u -s -i 1 -fm', str(self.iperf_args)) - server_options = server_options.replace('-c','-B') - SSH.command('rm -f /tmp/tmp_iperf_server_' + self.testCase_id + '.log', '\$', 5) - SSH.command('echo $USER; nohup iperf ' + server_options + ' > /tmp/tmp_iperf_server_' + self.testCase_id + '.log 2>&1 &', iServerUser, 5) - time.sleep(0.5) - SSH.close() - - # Starting the iperf client - modified_options = self.Iperf_ComputeModifiedBW(0, 1) - modified_options = modified_options.replace('-R','') - iperf_time = self.Iperf_ComputeTime() - SSH.open(iClientIPAddr, iClientUser, iClientPasswd) - SSH.command('rm -f /tmp/tmp_iperf_' + self.testCase_id + '.log', '\$', 5) - iperf_status = SSH.command('stdbuf -o0 iperf ' + modified_options + ' 2>&1 | stdbuf -o0 tee /tmp/tmp_iperf_' + self.testCase_id + '.log', '\$', int(iperf_time)*5.0) - status_queue = SimpleQueue() - lock = Lock() - if iperf_status < 0: - message = 'iperf on OAI UE crashed due to TIMEOUT !' - logging.debug('\u001B[1;37;41m ' + message + ' \u001B[0m') - clientStatus = -2 - else: - if self.iperf_options == 'sink': - clientStatus = 0 - status_queue.put(0) - status_queue.put('OAI-UE') - status_queue.put('10.0.1.2') - status_queue.put('Sink Test : no check') - else: - clientStatus = self.Iperf_analyzeV2Output(lock, '10.0.1.2', 'OAI-UE', status_queue, modified_options) - SSH.close() - - # Stopping the iperf server - if self.iperf_options != 'sink': - SSH.open(iServerIPAddr, iServerUser, iServerPasswd) - SSH.command('killall --signal SIGKILL iperf', '\$', 5) - time.sleep(0.5) - SSH.close() - - if (clientStatus == -1): - if (os.path.isfile('iperf_server_' + self.testCase_id + '.log')): - os.remove('iperf_server_' + self.testCase_id + '.log') - SSH.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log') - self.Iperf_analyzeV2Server(lock, '10.0.1.2', 'OAI-UE', status_queue, modified_options) - - # copying on the EPC server for logCollection - if (clientStatus == -1): - copyin_res = SSH.copyin(iServerIPAddr, iServerUser, iServerPasswd, '/tmp/tmp_iperf_server_' + self.testCase_id + '.log', 'iperf_server_' + self.testCase_id + '_OAI-UE.log') - if (copyin_res == 0): - SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_server_' + self.testCase_id + '_OAI-UE.log', EPC.GetSourceCodePath() + '/scripts') - copyin_res = SSH.copyin(iClientIPAddr, iClientUser, iClientPasswd, '/tmp/tmp_iperf_' + self.testCase_id + '.log', 'iperf_' + self.testCase_id + '_OAI-UE.log') - if (copyin_res == 0): - SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), 'iperf_' + self.testCase_id + '_OAI-UE.log', EPC.GetSourceCodePath() + '/scripts') - iperf_noperf = False - if status_queue.empty(): - iperf_status = False - else: - iperf_status = True - html_queue = SimpleQueue() - while (not status_queue.empty()): - count = status_queue.get() - if (count < 0): - iperf_status = False - if (count > 0): - iperf_noperf = True - device_id = status_queue.get() - ip_addr = status_queue.get() - message = status_queue.get() - html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' - html_queue.put(html_cell) - if (iperf_noperf and iperf_status): - HTML.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) - elif (iperf_status): - HTML.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) - else: - HTML.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) - self.AutoTerminateUEandeNB() - - def Iperf(self): - result = re.search('noS1', str(RAN.GetInitialize_eNB_args())) - if result is not None: - self.IperfNoS1() - return - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '' or self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - check_eNB = True - if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): - check_OAI_UE = True - else: - check_OAI_UE = False - pStatus = self.CheckProcessExist(check_eNB, check_OAI_UE) - if (pStatus < 0): - HTML.CreateHtmlTestRow(self.iperf_args, 'KO', pStatus) - self.AutoTerminateUEandeNB() - return - ueIpStatus = self.GetAllUEIPAddresses() - if (ueIpStatus < 0): - logging.debug('going here') - HTML.CreateHtmlTestRow(self.iperf_args, 'KO', CONST.UE_IP_ADDRESS_ISSUE) - self.AutoTerminateUEandeNB() - return - - self.dummyIperfVersion = '2.0.10' - #cmd = 'iperf --version' - #logging.debug(cmd + '\n') - #iperfStdout = subprocess.check_output(cmd, shell=True, universal_newlines=True) - #result = re.search('iperf version 2.0.5', str(iperfStdout.strip())) - #if result is not None: - # dummyIperfVersion = '2.0.5' - #result = re.search('iperf version 2.0.10', str(iperfStdout.strip())) - #if result is not None: - # dummyIperfVersion = '2.0.10' - - multi_jobs = [] - i = 0 - ue_num = len(self.UEIPAddresses) - lock = Lock() - status_queue = SimpleQueue() - logging.debug('ue_num = ' + str(ue_num)) - for UE_IPAddress in self.UEIPAddresses: - device_id = self.UEDevices[i] - p = Process(target = self.Iperf_common, args = (lock,UE_IPAddress,device_id,i,ue_num,status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - i = i + 1 - for job in multi_jobs: - job.join() - - if (status_queue.empty()): - HTML.CreateHtmlTestRow(self.iperf_args, 'KO', CONST.ALL_PROCESSES_OK) - self.AutoTerminateUEandeNB() - else: - iperf_status = True - iperf_noperf = False - html_queue = SimpleQueue() - while (not status_queue.empty()): - count = status_queue.get() - if (count < 0): - iperf_status = False - if (count > 0): - iperf_noperf = True - device_id = status_queue.get() - ip_addr = status_queue.get() - message = status_queue.get() - html_cell = '
UE (' + device_id + ')\nIP Address  : ' + ip_addr + '\n' + message + '
' - html_queue.put(html_cell) - if (iperf_noperf and iperf_status): - HTML.CreateHtmlTestRowQueue(self.iperf_args, 'PERF NOT MET', len(self.UEDevices), html_queue) - elif (iperf_status): - HTML.CreateHtmlTestRowQueue(self.iperf_args, 'OK', len(self.UEDevices), html_queue) - else: - HTML.CreateHtmlTestRowQueue(self.iperf_args, 'KO', len(self.UEDevices), html_queue) - self.AutoTerminateUEandeNB() - - def CheckProcessExist(self, check_eNB, check_OAI_UE): - multi_jobs = [] - status_queue = SimpleQueue() - # in noS1 config, no need to check status from EPC - # in gNB also currently no need to check - result = re.search('noS1|band78', str(RAN.GetInitialize_eNB_args())) - if result is None: - p = Process(target = EPC.CheckHSSProcess, args = (status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - p = Process(target = EPC.CheckMMEProcess, args = (status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - p = Process(target = EPC.CheckSPGWProcess, args = (status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - else: - if (check_eNB == False) and (check_OAI_UE == False): - return 0 - if check_eNB: - p = Process(target = RAN.CheckeNBProcess, args = (status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - if check_OAI_UE: - p = Process(target = self.CheckOAIUEProcess, args = (status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - for job in multi_jobs: - job.join() - - if (status_queue.empty()): - return -15 - else: - result = 0 - while (not status_queue.empty()): - status = status_queue.get() - if (status < 0): - result = status - if result == CONST.ENB_PROCESS_FAILED: - fileCheck = re.search('enb_', str(RAN.GeteNBLogFiles[0])) - if fileCheck is not None: - SSH.copyin(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath() + '/cmake_targets/' + RAN.GeteNBLogFiles[0], '.') - logStatus = self.AnalyzeLogFile_eNB(RAN.GeteNBLogFiles[0]) - if logStatus < 0: - result = logStatus - RAN.SeteNBLogFiles[0] = '' - if self.flexranCtrlInstalled and self.flexranCtrlStarted: - self.TerminateFlexranCtrl() - return result - - def CheckOAIUEProcessExist(self, initialize_OAI_UE_flag): - multi_jobs = [] - status_queue = SimpleQueue() - if initialize_OAI_UE_flag == False: - p = Process(target = self.CheckOAIUEProcess, args = (status_queue,)) - p.daemon = True - p.start() - multi_jobs.append(p) - for job in multi_jobs: - job.join() - - if (status_queue.empty()): - return -15 - else: - result = 0 - while (not status_queue.empty()): - status = status_queue.get() - if (status < 0): - result = status - if result == CONST.OAI_UE_PROCESS_FAILED: - fileCheck = re.search('ue_', str(self.UELogFile)) - if fileCheck is not None: - SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.') - logStatus = self.AnalyzeLogFile_UE(self.UELogFile) - if logStatus < 0: - result = logStatus - return result - - def CheckOAIUEProcess(self, status_queue): - try: - SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - SSH.command('stdbuf -o0 ps -aux | grep --color=never ' + RAN.Getair_interface() + '-uesoftmodem | grep -v grep', '\$', 5) - result = re.search(RAN.Getair_interface() + '-uesoftmodem', SSH.getBefore()) - if result is None: - logging.debug('\u001B[1;37;41m OAI UE Process Not Found! \u001B[0m') - status_queue.put(CONST.OAI_UE_PROCESS_FAILED) - else: - status_queue.put(CONST.OAI_UE_PROCESS_OK) - SSH.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - -# def AnalyzeLogFile_eNB(self, eNBlogFile): -# ... - - def AnalyzeLogFile_UE(self, UElogFile): - if (not os.path.isfile('./' + UElogFile)): - return -1 - ue_log_file = open('./' + UElogFile, 'r') - exitSignalReceived = False - foundAssertion = False - msgAssertion = '' - msgLine = 0 - foundSegFault = False - foundRealTimeIssue = False - uciStatMsgCount = 0 - pdcpDataReqFailedCount = 0 - badDciCount = 0 - f1aRetransmissionCount = 0 - fatalErrorCount = 0 - macBsrTimerExpiredCount = 0 - rrcConnectionRecfgComplete = 0 - no_cell_sync_found = False - mib_found = False - frequency_found = False - plmn_found = False - nrUEFlag = False - nrDecodeMib = 0 - nrFoundDCI = 0 - nrCRCOK = 0 - mbms_messages = 0 - self.htmlUEFailureMsg = '' - for line in ue_log_file.readlines(): - result = re.search('nr_synchro_time', str(line)) - if result is not None: - nrUEFlag = True - if nrUEFlag: - result = re.search('decode mib', str(line)) - if result is not None: - nrDecodeMib += 1 - result = re.search('found 1 DCIs', str(line)) - if result is not None: - nrFoundDCI += 1 - result = re.search('CRC OK', str(line)) - if result is not None: - nrCRCOK += 1 - result = re.search('Exiting OAI softmodem', str(line)) - if result is not None: - exitSignalReceived = True - result = re.search('System error|[Ss]egmentation [Ff]ault|======= Backtrace: =========|======= Memory map: ========', str(line)) - 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)) - if result is not None and not exitSignalReceived: - foundAssertion = True - result = re.search('LLL', str(line)) - if result is not None and not exitSignalReceived: - foundRealTimeIssue = True - if foundAssertion and (msgLine < 3): - msgLine += 1 - msgAssertion += str(line) - result = re.search('uci->stat', str(line)) - if result is not None and not exitSignalReceived: - uciStatMsgCount += 1 - result = re.search('PDCP data request failed', str(line)) - if result is not None and not exitSignalReceived: - pdcpDataReqFailedCount += 1 - result = re.search('bad DCI 1', str(line)) - if result is not None and not exitSignalReceived: - badDciCount += 1 - result = re.search('Format1A Retransmission but TBS are different', str(line)) - if result is not None and not exitSignalReceived: - f1aRetransmissionCount += 1 - result = re.search('FATAL ERROR', str(line)) - if result is not None and not exitSignalReceived: - fatalErrorCount += 1 - result = re.search('MAC BSR Triggered ReTxBSR Timer expiry', str(line)) - if result is not None and not exitSignalReceived: - macBsrTimerExpiredCount += 1 - result = re.search('Generating RRCConnectionReconfigurationComplete', str(line)) - if result is not None: - rrcConnectionRecfgComplete += 1 - # No cell synchronization found, abandoning - result = re.search('No cell synchronization found, abandoning', str(line)) - if result is not None: - no_cell_sync_found = True - if RAN.GeteNBmbmsEnables[0]: - result = re.search('TRIED TO PUSH MBMS DATA', str(line)) - if result is not None: - mbms_messages += 1 - result = re.search("MIB Information => ([a-zA-Z]{1,10}), ([a-zA-Z]{1,10}), NidCell (?P\d{1,3}), N_RB_DL (?P\d{1,3}), PHICH DURATION (?P\d), PHICH RESOURCE (?P.{1,4}), TX_ANT (?P\d)", str(line)) - if result is not None and (not mib_found): - try: - mibMsg = "MIB Information: " + result.group(1) + ', ' + result.group(2) - self.htmlUEFailureMsg += mibMsg + '\n' - logging.debug('\033[94m' + mibMsg + '\033[0m') - mibMsg = " nidcell = " + result.group('nidcell') - self.htmlUEFailureMsg += mibMsg - logging.debug('\033[94m' + mibMsg + '\033[0m') - mibMsg = " n_rb_dl = " + result.group('n_rb_dl') - self.htmlUEFailureMsg += mibMsg + '\n' - logging.debug('\033[94m' + mibMsg + '\033[0m') - mibMsg = " phich_duration = " + result.group('phich_duration') - self.htmlUEFailureMsg += mibMsg - logging.debug('\033[94m' + mibMsg + '\033[0m') - mibMsg = " phich_resource = " + result.group('phich_resource') - self.htmlUEFailureMsg += mibMsg + '\n' - logging.debug('\033[94m' + mibMsg + '\033[0m') - mibMsg = " tx_ant = " + result.group('tx_ant') - self.htmlUEFailureMsg += mibMsg + '\n' - logging.debug('\033[94m' + mibMsg + '\033[0m') - mib_found = True - except Exception as e: - logging.error('\033[91m' + "MIB marker was not found" + '\033[0m') - result = re.search("Measured Carrier Frequency (?P\d{1,15}) Hz", str(line)) - if result is not None and (not frequency_found): - try: - mibMsg = "Measured Carrier Frequency = " + result.group('measured_carrier_frequency') + ' Hz' - self.htmlUEFailureMsg += mibMsg + '\n' - logging.debug('\033[94m' + mibMsg + '\033[0m') - frequency_found = True - except Exception as e: - logging.error('\033[91m' + "Measured Carrier Frequency not found" + '\033[0m') - result = re.search("PLMN MCC (?P\d{1,3}), MNC (?P\d{1,3}), TAC", str(line)) - if result is not None and (not plmn_found): - try: - mibMsg = 'PLMN MCC = ' + result.group('mcc') + ' MNC = ' + result.group('mnc') - self.htmlUEFailureMsg += mibMsg + '\n' - logging.debug('\033[94m' + mibMsg + '\033[0m') - plmn_found = True - except Exception as e: - logging.error('\033[91m' + "PLMN not found" + '\033[0m') - result = re.search("Found (?P[\w,\s]{1,15}) \(name from internal table\)", str(line)) - if result is not None: - try: - mibMsg = "The operator is: " + result.group('operator') - self.htmlUEFailureMsg += mibMsg + '\n' - logging.debug('\033[94m' + mibMsg + '\033[0m') - except Exception as e: - logging.error('\033[91m' + "Operator name not found" + '\033[0m') - result = re.search("SIB5 InterFreqCarrierFreq element (.{1,4})/(.{1,4})", str(line)) - if result is not None: - try: - mibMsg = "SIB5 InterFreqCarrierFreq element " + result.group(1) + '/' + result.group(2) - self.htmlUEFailureMsg += mibMsg + ' -> ' - logging.debug('\033[94m' + mibMsg + '\033[0m') - except Exception as e: - logging.error('\033[91m' + "SIB5 InterFreqCarrierFreq element not found" + '\033[0m') - result = re.search("DL Carrier Frequency/ARFCN : (?P\d{1,15}/\d{1,4})", str(line)) - if result is not None: - try: - freq = result.group('carrier_frequency') - new_freq = re.sub('/[0-9]+','',freq) - float_freq = float(new_freq) / 1000000 - self.htmlUEFailureMsg += 'DL Freq: ' + ('%.1f' % float_freq) + ' MHz' - logging.debug('\033[94m' + " DL Carrier Frequency is: " + freq + '\033[0m') - except Exception as e: - logging.error('\033[91m' + " DL Carrier Frequency not found" + '\033[0m') - result = re.search("AllowedMeasBandwidth : (?P\d{1,7})", str(line)) - if result is not None: - try: - prb = result.group('allowed_bandwidth') - self.htmlUEFailureMsg += ' -- PRB: ' + prb + '\n' - logging.debug('\033[94m' + " AllowedMeasBandwidth: " + prb + '\033[0m') - except Exception as e: - logging.error('\033[91m' + " AllowedMeasBandwidth not found" + '\033[0m') - ue_log_file.close() - if rrcConnectionRecfgComplete > 0: - statMsg = 'UE connected to eNB (' + str(rrcConnectionRecfgComplete) + ' RRCConnectionReconfigurationComplete message(s) generated)' - logging.debug('\033[94m' + statMsg + '\033[0m') - self.htmlUEFailureMsg += statMsg + '\n' - if nrUEFlag: - if nrDecodeMib > 0: - statMsg = 'UE showed ' + str(nrDecodeMib) + ' MIB decode message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' - if nrFoundDCI > 0: - statMsg = 'UE showed ' + str(nrFoundDCI) + ' DCI found message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' - if nrCRCOK > 0: - statMsg = 'UE showed ' + str(nrCRCOK) + ' PDSCH decoding message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' - if not frequency_found: - statMsg = 'NR-UE could NOT synch!' - logging.error('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' - if uciStatMsgCount > 0: - statMsg = 'UE showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' - if pdcpDataReqFailedCount > 0: - statMsg = 'UE showed ' + str(pdcpDataReqFailedCount) + ' "PDCP data request failed" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' - if badDciCount > 0: - statMsg = 'UE showed ' + str(badDciCount) + ' "bad DCI 1(A)" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' - if f1aRetransmissionCount > 0: - statMsg = 'UE showed ' + str(f1aRetransmissionCount) + ' "Format1A Retransmission but TBS are different" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' - if fatalErrorCount > 0: - statMsg = 'UE showed ' + str(fatalErrorCount) + ' "FATAL ERROR:" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' - if macBsrTimerExpiredCount > 0: - statMsg = 'UE showed ' + str(fatalErrorCount) + ' "MAC BSR Triggered ReTxBSR Timer expiry" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' - if RAN.GeteNBmbmsEnables[0]: - if mbms_messages > 0: - statMsg = 'UE showed ' + str(mbms_messages) + ' "TRIED TO PUSH MBMS DATA" message(s)' - logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - else: - statMsg = 'UE did NOT SHOW "TRIED TO PUSH MBMS DATA" message(s)' - logging.debug('\u001B[1;30;41m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' - if foundSegFault: - logging.debug('\u001B[1;37;41m UE ended with a Segmentation Fault! \u001B[0m') - if not nrUEFlag: - return CONST.OAI_UE_PROCESS_SEG_FAULT - else: - if not frequency_found: - return CONST.OAI_UE_PROCESS_SEG_FAULT - if foundAssertion: - logging.debug('\u001B[1;30;43m UE showed an assertion! \u001B[0m') - self.htmlUEFailureMsg += 'UE showed an assertion!\n' - if not nrUEFlag: - if not mib_found or not frequency_found: - return CONST.OAI_UE_PROCESS_ASSERTION - else: - if not frequency_found: - return CONST.OAI_UE_PROCESS_ASSERTION - if foundRealTimeIssue: - logging.debug('\u001B[1;37;41m UE faced real time issues! \u001B[0m') - self.htmlUEFailureMsg += 'UE faced real time issues!\n' - #return CONST.ENB_PROCESS_REALTIME_ISSUE - if nrUEFlag: - if not frequency_found: - return CONST.OAI_UE_PROCESS_COULD_NOT_SYNC - else: - if no_cell_sync_found and not mib_found: - logging.debug('\u001B[1;37;41m UE could not synchronize ! \u001B[0m') - self.htmlUEFailureMsg += 'UE could not synchronize!\n' - return CONST.OAI_UE_PROCESS_COULD_NOT_SYNC - return 0 - - - def TerminateFlexranCtrl(self): - if self.flexranCtrlInstalled == False or self.flexranCtrlStarted == False: - return - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S daemon --name=flexran_rtc_daemon --stop', '\$', 5) - time.sleep(1) - SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S killall --signal SIGKILL rt_controller', '\$', 5) - time.sleep(1) - SSH.close() - self.flexranCtrlStarted = False - HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - - def TerminateUE_common(self, device_id, idx): - try: - SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) - # back in airplane mode on (ie radio off) - if self.ADBCentralized: - if device_id == '84B7N16418004022': - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "su - root -c /data/local/tmp/off"', '\$', 60) - else: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell /data/local/tmp/off', '\$', 60) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' ' + self.UEDevicesOffCmd[idx], '\$', 60) - logging.debug('\u001B[1mUE (' + device_id + ') Detach Completed\u001B[0m') - - if self.ADBCentralized: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "ps | grep --color=never iperf | grep -v grep"', '\$', 5) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "ps | grep --color=never iperf | grep -v grep"\'', '\$', 60) - result = re.search('shell +(?P\d+)', SSH.getBefore()) - if result is not None: - pid_iperf = result.group('pid') - if self.ADBCentralized: - SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"', '\$', 5) - else: - SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "kill -KILL ' + pid_iperf + '"\'', '\$', 60) - SSH.close() - except: - os.kill(os.getppid(),signal.SIGUSR1) - - def TerminateUE(self): - terminate_ue_flag = False - self.GetAllUEDevices(terminate_ue_flag) - multi_jobs = [] - i = 0 - for device_id in self.UEDevices: - p = Process(target= self.TerminateUE_common, args = (device_id,i,)) - p.daemon = True - p.start() - multi_jobs.append(p) - i += 1 - for job in multi_jobs: - job.join() - HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - - def TerminateOAIUE(self): - SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - SSH.command('cd ' + self.UESourceCodePath + '/cmake_targets', '\$', 5) - SSH.command('ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('-uesoftmodem', SSH.getBefore()) - if result is not None: - SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGINT -r .*-uesoftmodem || true', '\$', 5) - time.sleep(10) - SSH.command('ps -aux | grep --color=never softmodem | grep -v grep', '\$', 5) - result = re.search('-uesoftmodem', SSH.getBefore()) - if result is not None: - SSH.command('echo ' + self.UEPassword + ' | sudo -S killall --signal SIGKILL -r .*-uesoftmodem || true', '\$', 5) - time.sleep(5) - SSH.command('rm -f my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) - SSH.close() - result = re.search('ue_', str(self.UELogFile)) - if result is not None: - copyin_res = SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.') - if (copyin_res == -1): - logging.debug('\u001B[1;37;41m Could not copy UE logfile to analyze it! \u001B[0m') - self.htmlUEFailureMsg = 'Could not copy UE logfile to analyze it!' - HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE, 'UE') - self.UELogFile = '' - return - logging.debug('\u001B[1m Analyzing UE logfile \u001B[0m') - logStatus = self.AnalyzeLogFile_UE(self.UELogFile) - result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) - if result is not None: - ueAction = 'Sniffing' - else: - ueAction = 'Connection' - if (logStatus < 0): - logging.debug('\u001B[1m' + ueAction + ' Failed \u001B[0m') - self.htmlUEFailureMsg = '' + ueAction + ' Failed\n' + self.htmlUEFailureMsg - HTML.CreateHtmlTestRow('N/A', 'KO', logStatus, 'UE') - if RAN.Getair_interface() == 'lte': - # In case of sniffing on commercial eNBs we have random results - # Not an error then - if (logStatus != CONST.OAI_UE_PROCESS_COULD_NOT_SYNC) or (ueAction != 'Sniffing'): - self.Initialize_OAI_UE_args = '' - self.AutoTerminateUEandeNB() - else: - if (logStatus == CONST.OAI_UE_PROCESS_COULD_NOT_SYNC): - self.Initialize_OAI_UE_args = '' - self.AutoTerminateUEandeNB() - else: - logging.debug('\u001B[1m' + ueAction + ' Completed \u001B[0m') - self.htmlUEFailureMsg = '' + ueAction + ' Completed\n' + self.htmlUEFailureMsg - HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - self.UELogFile = '' - else: - HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - - def AutoTerminateUEandeNB(self): - if (self.ADBIPAddress != 'none'): - self.testCase_id = 'AUTO-KILL-UE' - RAN.SettestCase_id(self.testCase_id) - self.desc = 'Automatic Termination of UE' - self.ShowTestID() - self.TerminateUE() - if (self.Initialize_OAI_UE_args != ''): - self.testCase_id = 'AUTO-KILL-UE' - RAN.SettestCase_id(self.testCase_id) - self.desc = 'Automatic Termination of UE' - self.ShowTestID() - self.TerminateOAIUE() - if (RAN.GetInitialize_eNB_args() != ''): - self.testCase_id = 'AUTO-KILL-eNB' - RAN.SettestCase_id(self.testCase_id) - self.desc = 'Automatic Termination of eNB' - self.ShowTestID() - RAN.SeteNB_instance('0') - RAN.TerminateeNB() - if self.flexranCtrlInstalled and self.flexranCtrlStarted: - self.testCase_id = 'AUTO-KILL-flexran-ctl' - RAN.SettestCase_id(self.testCase_id) - self.desc = 'Automatic Termination of FlexRan CTL' - self.ShowTestID() - self.TerminateFlexranCtrl() - RAN.SetprematureExit(True) - - def IdleSleep(self): - time.sleep(self.idle_sleep_time) - HTML.CreateHtmlTestRow(str(self.idle_sleep_time) + ' sec', 'OK', CONST.ALL_PROCESSES_OK) - - def X2_Status(self, idx, fileName): - cmd = "curl --silent http://" + EPC.GetIPAddress() + ":9999/stats | jq '.' > " + fileName - message = cmd + '\n' - logging.debug(cmd) - subprocess.run(cmd, shell=True) - if idx == 0: - cmd = "jq '.mac_stats | length' " + fileName - strNbEnbs = subprocess.check_output(cmd, shell=True, universal_newlines=True) - self.x2NbENBs = int(strNbEnbs.strip()) - cnt = 0 - while cnt < self.x2NbENBs: - cmd = "jq '.mac_stats[" + str(cnt) + "].bs_id' " + fileName - bs_id = subprocess.check_output(cmd, shell=True, universal_newlines=True) - self.x2ENBBsIds[idx].append(bs_id.strip()) - cmd = "jq '.mac_stats[" + str(cnt) + "].ue_mac_stats | length' " + fileName - stNbUEs = subprocess.check_output(cmd, shell=True, universal_newlines=True) - nbUEs = int(stNbUEs.strip()) - ueIdx = 0 - self.x2ENBConnectedUEs[idx].append([]) - while ueIdx < nbUEs: - cmd = "jq '.mac_stats[" + str(cnt) + "].ue_mac_stats[" + str(ueIdx) + "].rnti' " + fileName - rnti = subprocess.check_output(cmd, shell=True, universal_newlines=True) - self.x2ENBConnectedUEs[idx][cnt].append(rnti.strip()) - ueIdx += 1 - cnt += 1 - - msg = "FlexRan Controller is connected to " + str(self.x2NbENBs) + " eNB(s)" - logging.debug(msg) - message += msg + '\n' - cnt = 0 - while cnt < self.x2NbENBs: - msg = " -- eNB: " + str(self.x2ENBBsIds[idx][cnt]) + " is connected to " + str(len(self.x2ENBConnectedUEs[idx][cnt])) + " UE(s)" - logging.debug(msg) - message += msg + '\n' - ueIdx = 0 - while ueIdx < len(self.x2ENBConnectedUEs[idx][cnt]): - msg = " -- UE rnti: " + str(self.x2ENBConnectedUEs[idx][cnt][ueIdx]) - logging.debug(msg) - message += msg + '\n' - ueIdx += 1 - cnt += 1 - return message - - def Perform_X2_Handover(self): - html_queue = SimpleQueue() - fullMessage = '
'
-		msg = 'Doing X2 Handover w/ option ' + self.x2_ho_options
-		logging.debug(msg)
-		fullMessage += msg + '\n'
-		if self.x2_ho_options == 'network':
-			if self.flexranCtrlInstalled and self.flexranCtrlStarted:
-				self.x2ENBBsIds = []
-				self.x2ENBConnectedUEs = []
-				self.x2ENBBsIds.append([])
-				self.x2ENBBsIds.append([])
-				self.x2ENBConnectedUEs.append([])
-				self.x2ENBConnectedUEs.append([])
-				fullMessage += self.X2_Status(0, self.testCase_id + '_pre_ho.json') 
-
-				msg = "Activating the X2 Net control on each eNB"
-				logging.debug(msg)
-				fullMessage += msg + '\n'
-				eNB_cnt = self.x2NbENBs
-				cnt = 0
-				while cnt < eNB_cnt:
-					cmd = "curl -XPOST http://" + EPC.GetIPAddress() + ":9999/rrc/x2_ho_net_control/enb/" + str(self.x2ENBBsIds[0][cnt]) + "/1"
-					logging.debug(cmd)
-					fullMessage += cmd + '\n'
-					subprocess.run(cmd, shell=True)
-					cnt += 1
-				# Waiting for the activation to be active
-				time.sleep(10)
-				msg = "Switching UE(s) from eNB to eNB"
-				logging.debug(msg)
-				fullMessage += msg + '\n'
-				cnt = 0
-				while cnt < eNB_cnt:
-					ueIdx = 0
-					while ueIdx < len(self.x2ENBConnectedUEs[0][cnt]):
-						cmd = "curl -XPOST http://" + EPC.GetIPAddress() + ":9999/rrc/ho/senb/" + str(self.x2ENBBsIds[0][cnt]) + "/ue/" + str(self.x2ENBConnectedUEs[0][cnt][ueIdx]) + "/tenb/" + str(self.x2ENBBsIds[0][eNB_cnt - cnt - 1])
-						logging.debug(cmd)
-						fullMessage += cmd + '\n'
-						subprocess.run(cmd, shell=True)
-						ueIdx += 1
-					cnt += 1
-				time.sleep(10)
-				# check
-				logging.debug("Checking the Status after X2 Handover")
-				fullMessage += self.X2_Status(1, self.testCase_id + '_post_ho.json') 
-				cnt = 0
-				x2Status = True
-				while cnt < eNB_cnt:
-					if len(self.x2ENBConnectedUEs[0][cnt]) == len(self.x2ENBConnectedUEs[1][cnt]):
-						x2Status = False
-					cnt += 1
-				if x2Status:
-					msg = "X2 Handover was successful"
-					logging.debug(msg)
-					fullMessage += msg + '
' - html_queue.put(fullMessage) - HTML.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) - else: - msg = "X2 Handover FAILED" - logging.error(msg) - fullMessage += msg + '' - html_queue.put(fullMessage) - HTML.CreateHtmlTestRowQueue('N/A', 'OK', len(self.UEDevices), html_queue) - else: - HTML.CreateHtmlTestRow('Cannot perform requested X2 Handover', 'KO', CONST.ALL_PROCESSES_OK) - - def LogCollectBuild(self): - if (RAN.GeteNBIPAddress() != '' and RAN.GeteNBUserName() != '' and RAN.GeteNBPassword() != ''): - IPAddress = RAN.GeteNBIPAddress() - UserName = RAN.GeteNBUserName() - Password = RAN.GeteNBPassword() - SourceCodePath = RAN.GeteNBSourceCodePath() - elif (self.UEIPAddress != '' and self.UEUserName != '' and self.UEPassword != ''): - IPAddress = self.UEIPAddress - UserName = self.UEUserName - Password = self.UEPassword - SourceCodePath = self.UESourceCodePath - else: - sys.exit('Insufficient Parameter') - SSH.open(IPAddress, UserName, Password) - SSH.command('cd ' + SourceCodePath, '\$', 5) - SSH.command('cd cmake_targets', '\$', 5) - SSH.command('rm -f build.log.zip', '\$', 5) - SSH.command('zip build.log.zip build_log_*/*', '\$', 60) - SSH.close() - def LogCollectPing(self): - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('cd ' + EPC.GetSourceCodePath(), '\$', 5) - SSH.command('cd scripts', '\$', 5) - SSH.command('rm -f ping.log.zip', '\$', 5) - SSH.command('zip ping.log.zip ping*.log', '\$', 60) - SSH.command('rm ping*.log', '\$', 5) - SSH.close() - - def LogCollectIperf(self): - SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) - SSH.command('cd ' + EPC.GetSourceCodePath(), '\$', 5) - SSH.command('cd scripts', '\$', 5) - SSH.command('rm -f iperf.log.zip', '\$', 5) - SSH.command('zip iperf.log.zip iperf*.log', '\$', 60) - SSH.command('rm iperf*.log', '\$', 5) - SSH.close() - - def LogCollectOAIUE(self): - SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) - SSH.command('cd ' + self.UESourceCodePath, '\$', 5) - SSH.command('cd cmake_targets', '\$', 5) - SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -f ue.log.zip', '\$', 5) - SSH.command('echo ' + self.UEPassword + ' | sudo -S zip ue.log.zip ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 60) - SSH.command('echo ' + self.UEPassword + ' | sudo -S rm ue*.log core* ue_*record.raw ue_*.pcap ue_*txt', '\$', 5) - SSH.close() - - def RetrieveSystemVersion(self, machine): - if RAN.GeteNBIPAddress() == 'none' or self.UEIPAddress == 'none': - self.OsVersion = 'Ubuntu 16.04.5 LTS' - self.KernelVersion = '4.15.0-45-generic' - self.UhdVersion = '3.13.0.1-0' - self.UsrpBoard = 'B210' - self.CpuNb = '4' - self.CpuModel = 'Intel(R) Core(TM) i5-6200U' - self.CpuMHz = '2399.996 MHz' - return 0 - if machine == 'eNB': - if RAN.GeteNBIPAddress() != '' and RAN.GeteNBUserName() != '' and RAN.GeteNBPassword() != '': - IPAddress = RAN.GeteNBIPAddress() - UserName = RAN.GeteNBUserName() - Password = RAN.GeteNBPassword() - else: - return -1 - if machine == 'UE': - if self.UEIPAddress != '' and self.UEUserName != '' and self.UEPassword != '': - IPAddress = self.UEIPAddress - UserName = self.UEUserName - Password = self.UEPassword - else: - return -1 - - SSH.open(IPAddress, UserName, Password) - SSH.command('lsb_release -a', '\$', 5) - result = re.search('Description:\\\\t(?P[a-zA-Z0-9\-\_\.\ ]+)', SSH.getBefore()) - if result is not None: - self.OsVersion = result.group('os_type') - logging.debug('OS is: ' + self.OsVersion) - else: - SSH.command('hostnamectl', '\$', 5) - result = re.search('Operating System: (?P[a-zA-Z0-9\-\_\.\ ]+)', SSH.getBefore()) - if result is not None: - self.OsVersion = result.group('os_type') - if self.OsVersion == 'CentOS Linux 7 ': - SSH.command('cat /etc/redhat-release', '\$', 5) - result = re.search('CentOS Linux release (?P[0-9\.]+)', SSH.getBefore()) - if result is not None: - self.OsVersion = self.OsVersion.replace('7 ', result.group('os_version')) - logging.debug('OS is: ' + self.OsVersion) - SSH.command('uname -r', '\$', 5) - result = re.search('uname -r\\\\r\\\\n(?P[a-zA-Z0-9\-\_\.]+)', SSH.getBefore()) - if result is not None: - self.KernelVersion = result.group('kernel_version') - logging.debug('Kernel Version is: ' + self.KernelVersion) - SSH.command('dpkg --list | egrep --color=never libuhd003', '\$', 5) - result = re.search('libuhd003:amd64 *(?P[0-9\.]+)', SSH.getBefore()) - if result is not None: - self.UhdVersion = result.group('uhd_version') - logging.debug('UHD Version is: ' + self.UhdVersion) - else: - SSH.command('uhd_config_info --version', '\$', 5) - result = re.search('UHD (?P[a-zA-Z0-9\.\-]+)', SSH.getBefore()) - if result is not None: - self.UhdVersion = result.group('uhd_version') - logging.debug('UHD Version is: ' + self.UhdVersion) - SSH.command('echo ' + Password + ' | sudo -S uhd_find_devices', '\$', 30) - usrp_boards = re.findall('product: ([0-9A-Za-z]+)\\\\r\\\\n', SSH.getBefore()) - count = 0 - for board in usrp_boards: - if count == 0: - self.UsrpBoard = board - else: - self.UsrpBoard += ',' + board - count += 1 - if count > 0: - logging.debug('USRP Board(s) : ' + self.UsrpBoard) - SSH.command('lscpu', '\$', 5) - result = re.search('CPU\(s\): *(?P[0-9]+).*Model name: *(?P[a-zA-Z0-9\-\_\.\ \(\)]+).*CPU MHz: *(?P[0-9\.]+)', SSH.getBefore()) - if result is not None: - self.CpuNb = result.group('nb_cpus') - logging.debug('nb_cpus: ' + self.CpuNb) - self.CpuModel = result.group('model') - logging.debug('model: ' + self.CpuModel) - self.CpuMHz = result.group('cpu_mhz') + ' MHz' - logging.debug('cpu_mhz: ' + self.CpuMHz) - SSH.close() - -#----------------------------------------------------------- -# ShowTestID() -#----------------------------------------------------------- - def ShowTestID(self): - logging.debug('\u001B[1m----------------------------------------\u001B[0m') - logging.debug('\u001B[1mTest ID:' + self.testCase_id + '\u001B[0m') - logging.debug('\u001B[1m' + self.desc + '\u001B[0m') - logging.debug('\u001B[1m----------------------------------------\u001B[0m') - -def CheckClassValidity(action,id): - if action != 'Build_eNB' and action != 'WaitEndBuild_eNB' and action != 'Initialize_eNB' and action != 'Terminate_eNB' and action != 'Initialize_UE' and action != 'Terminate_UE' and action != 'Attach_UE' and action != 'Detach_UE' and action != 'Build_OAI_UE' and action != 'Initialize_OAI_UE' and action != 'Terminate_OAI_UE' and action != 'DataDisable_UE' and action != 'DataEnable_UE' and action != 'CheckStatusUE' and action != 'Ping' and action != 'Iperf' and action != 'Reboot_UE' and action != 'Initialize_FlexranCtrl' and action != 'Terminate_FlexranCtrl' and action != 'Initialize_HSS' and action != 'Terminate_HSS' and action != 'Initialize_MME' and action != 'Terminate_MME' and action != 'Initialize_SPGW' and action != 'Terminate_SPGW' and action != 'Initialize_CatM_module' and action != 'Terminate_CatM_module' and action != 'Attach_CatM_module' and action != 'Detach_CatM_module' and action != 'Ping_CatM_module' and action != 'IdleSleep' and action != 'Perform_X2_Handover': - logging.debug('ERROR: test-case ' + id + ' has wrong class ' + action) - return False - return True - -def GetParametersFromXML(action): - if action == 'Build_eNB': - RAN.SetBuild_eNB_args(test.findtext('Build_eNB_args')) - forced_workspace_cleanup = test.findtext('forced_workspace_cleanup') - if (forced_workspace_cleanup is None): - RAN.SetBuild_eNB_forced_workspace_cleanup(False) - else: - if re.match('true', forced_workspace_cleanup, re.IGNORECASE): - RAN.SetBuild_eNB_forced_workspace_cleanup(True) - else: - RAN.SetBuild_eNB_forced_workspace_cleanup(False) - RAN.SeteNB_instance(test.findtext('eNB_instance')) - if (RAN.GeteNB_instance() is None): - RAN.SeteNB_instance('0') - RAN.SeteNB_serverId(test.findtext('eNB_serverId')) - if (RAN.GeteNB_serverId() is None): - RAN.SeteNB_serverId('0') - xmlBgBuildField = test.findtext('backgroundBuild') - if (xmlBgBuildField is None): - RAN.SetbackgroundBuild(False) - else: - if re.match('true', xmlBgBuildField, re.IGNORECASE): - RAN.SetbackgroundBuild(True) - else: - RAN.SetbackgroundBuild(False) - - if action == 'WaitEndBuild_eNB': - RAN.SetBuild_eNB_args(test.findtext('Build_eNB_args')) - RAN.SeteNB_instance(test.findtext('eNB_instance')) - if (RAN.GeteNB_instance() is None): - RAN.SeteNB_instance('0') - RAN.SeteNB_serverId(test.findtext('eNB_serverId')) - if (RAN.GeteNB_serverId() is None): - RAN.SeteNB_serverId('0') - - if action == 'Initialize_eNB': - RAN.SetInitialize_eNB_args(test.findtext('Initialize_eNB_args')) - RAN.SeteNB_instance(test.findtext('eNB_instance')) - if (RAN.GeteNB_instance() is None): - RAN.SeteNB_instance('0') - RAN.SeteNB_serverId(test.findtext('eNB_serverId')) - if (RAN.GeteNB_serverId() is None): - RAN.SeteNB_serverId('0') - CiTestObj.air_interface = test.findtext('air_interface') - if (CiTestObj.air_interface is None): - CiTestObj.air_interface = 'lte' - else: - CiTestObj.air_interface = CiTestObj.air_interface.lower() - - if action == 'Terminate_eNB': - RAN.SeteNB_instance(test.findtext('eNB_instance')) - if (RAN.GeteNB_instance() is None): - RAN.SeteNB_instance('0') - RAN.SeteNB_serverId(test.findtext('eNB_serverId')) - if (RAN.GeteNB_serverId() is None): - RAN.SeteNB_serverId('0') - CiTestObj.air_interface = test.findtext('air_interface') - if (CiTestObj.air_interface is None): - CiTestObj.air_interface = 'lte' - else: - CiTestObj.air_interface = CiTestObj.air_interface.lower() - - if action == 'Attach_UE': - nbMaxUEtoAttach = test.findtext('nbMaxUEtoAttach') - if (nbMaxUEtoAttach is None): - CiTestObj.nbMaxUEtoAttach = -1 - else: - CiTestObj.nbMaxUEtoAttach = int(nbMaxUEtoAttach) - - if action == 'CheckStatusUE': - expectedNBUE = test.findtext('expectedNbOfConnectedUEs') - if (expectedNBUE is None): - CiTestObj.expectedNbOfConnectedUEs = -1 - else: - CiTestObj.expectedNbOfConnectedUEs = int(expectedNBUE) - - if action == 'Build_OAI_UE': - CiTestObj.Build_OAI_UE_args = test.findtext('Build_OAI_UE_args') - CiTestObj.clean_repository = test.findtext('clean_repository') - if (CiTestObj.clean_repository == 'false'): - CiTestObj.clean_repository = False - else: - CiTestObj.clean_repository = True - - if action == 'Initialize_OAI_UE': - CiTestObj.Initialize_OAI_UE_args = test.findtext('Initialize_OAI_UE_args') - CiTestObj.UE_instance = test.findtext('UE_instance') - if (CiTestObj.UE_instance is None): - CiTestObj.UE_instance = '0' - CiTestObj.air_interface = test.findtext('air_interface') - if (CiTestObj.air_interface is None): - CiTestObj.air_interface = 'lte' - else: - CiTestObj.air_interface = SSH.air_interface.lower() - - if action == 'Terminate_OAI_UE': - RAN.SeteNB_instance(test.findtext('UE_instance')) - if (CiTestObj.UE_instance is None): - CiTestObj.UE_instance = '0' - - if action == 'Ping' or action == 'Ping_CatM_module': - CiTestObj.ping_args = test.findtext('ping_args') - CiTestObj.ping_packetloss_threshold = test.findtext('ping_packetloss_threshold') - - if action == 'Iperf': - CiTestObj.iperf_args = test.findtext('iperf_args') - CiTestObj.iperf_packetloss_threshold = test.findtext('iperf_packetloss_threshold') - CiTestObj.iperf_profile = test.findtext('iperf_profile') - if (CiTestObj.iperf_profile is None): - CiTestObj.iperf_profile = 'balanced' - else: - if CiTestObj.iperf_profile != 'balanced' and CiTestObj.iperf_profile != 'unbalanced' and CiTestObj.iperf_profile != 'single-ue': - logging.debug('ERROR: test-case has wrong profile ' + CiTestObj.iperf_profile) - CiTestObj.iperf_profile = 'balanced' - CiTestObj.iperf_options = test.findtext('iperf_options') - if (CiTestObj.iperf_options is None): - CiTestObj.iperf_options = 'check' - else: - if CiTestObj.iperf_options != 'check' and CiTestObj.iperf_options != 'sink': - logging.debug('ERROR: test-case has wrong option ' + CiTestObj.iperf_options) - CiTestObj.iperf_options = 'check' - - if action == 'IdleSleep': - string_field = test.findtext('idle_sleep_time_in_sec') - if (string_field is None): - CiTestObj.idle_sleep_time = 5 - else: - CiTestObj.idle_sleep_time = int(string_field) - - if action == 'Perform_X2_Handover': - string_field = test.findtext('x2_ho_options') - if (string_field is None): - CiTestObj.x2_ho_options = 'network' - else: - if string_field != 'network': - logging.error('ERROR: test-case has wrong option ' + string_field) - CiTestObj.x2_ho_options = 'network' - else: - CiTestObj.x2_ho_options = string_field - - -#check if given test is in list -#it is in list if one of the strings in 'list' is at the beginning of 'test' -def test_in_list(test, list): - for check in list: - check=check.replace('+','') - if (test.startswith(check)): - return True - return False - -def receive_signal(signum, frame): - sys.exit(1) - -#----------------------------------------------------------- -# Parameter Check -#----------------------------------------------------------- -mode = '' -CiTestObj = OaiCiTest() - -import sshconnection -import epc -import helpreadme -import ran -import html -import constants - -SSH = sshconnection.SSHConnection() -EPC = epc.EPCManagement() -RAN = ran.RANManagement() -HTML = html.HTMLManagement() - - -argvs = sys.argv -argc = len(argvs) -cwd = os.getcwd() - -while len(argvs) > 1: - myArgv = argvs.pop(1) # 0th is this file's name - - if re.match('^\-\-help$', myArgv, re.IGNORECASE): - GenericHelp(Version) - sys.exit(0) - elif re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE) - mode = matchReg.group(1) - elif re.match('^\-\-eNBRepository=(.+)$|^\-\-ranRepository(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE) - else: - matchReg = re.match('^\-\-ranRepository=(.+)$', myArgv, re.IGNORECASE) - RAN.SetranRepository(matchReg.group(1)) - HTML.SetranRepository(matchReg.group(1)) - elif re.match('^\-\-eNB_AllowMerge=(.+)$|^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB_AllowMerge=(.+)$', myArgv, re.IGNORECASE) - else: - matchReg = re.match('^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE) - doMerge = matchReg.group(1) - if ((doMerge == 'true') or (doMerge == 'True')): - RAN.SetranAllowMerge(True) - HTML.SetranAllowMerge(True) - elif re.match('^\-\-eNBBranch=(.+)$|^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE) - else: - matchReg = re.match('^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE) - RAN.SetranBranch(matchReg.group(1)) - HTML.SetranBranch(matchReg.group(1)) - elif re.match('^\-\-eNBCommitID=(.*)$|^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE) - else: - matchReg = re.match('^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE) - RAN.SetranCommitID(matchReg.group(1)) - HTML.SetranCommitID(matchReg.group(1)) - elif re.match('^\-\-eNBTargetBranch=(.*)$|^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE) - else: - matchReg = re.match('^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE) - RAN.SetranTargetBranch(matchReg.group(1)) - elif re.match('^\-\-eNBIPAddress=(.+)$|^\-\-eNB[1-2]IPAddress=(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBIPAddress=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNBIPAddress(matchReg.group(1)) - elif re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB1IPAddress=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB1IPAddress(matchReg.group(1)) - elif re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB2IPAddress=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB2IPAddress(matchReg.group(1)) - elif re.match('^\-\-eNBUserName=(.+)$|^\-\-eNB[1-2]UserName=(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBUserName=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNBUserName(matchReg.group(1)) - elif re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB1UserName=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB1UserName(matchReg.group(1)) - elif re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB2UserName=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB2UserName(matchReg.group(1)) - elif re.match('^\-\-eNBPassword=(.+)$|^\-\-eNB[1-2]Password=(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBPassword=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNBPassword(matchReg.group(1)) - elif re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB1Password=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB1Password(matchReg.group(1)) - elif re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB2Password=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB2Password(matchReg.group(1)) - elif re.match('^\-\-eNBSourceCodePath=(.+)$|^\-\-eNB[1-2]SourceCodePath=(.+)$', myArgv, re.IGNORECASE): - if re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNBSourceCodePath=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNBSourceCodePath(matchReg.group(1)) - elif re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB1SourceCodePath=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB1SourceCodePath(matchReg.group(1)) - elif re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-eNB2SourceCodePath=(.+)$', myArgv, re.IGNORECASE) - RAN.SeteNB2SourceCodePath(matchReg.group(1)) - elif re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE) - EPC.SetIPAddress(matchReg.group(1)) -#GP250220: do we still need EPCBranch? it's not used anywhere - elif re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.EPCBranch = matchReg.group(1) - elif re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE) - EPC.SetUserName(matchReg.group(1)) - elif re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE) - EPC.SetPassword(matchReg.group(1)) - elif re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE) - EPC.SetSourceCodePath(matchReg.group(1)) - elif re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE) - if re.match('OAI', matchReg.group(1), re.IGNORECASE) or re.match('ltebox', matchReg.group(1), re.IGNORECASE) or re.match('OAI-Rel14-CUPS', matchReg.group(1), re.IGNORECASE): - EPC.SetType(matchReg.group(1)) - else: - sys.exit('Invalid EPC Type: ' + matchReg.group(1) + ' -- (should be OAI or ltebox or OAI-Rel14-CUPS)') - elif re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-ADBIPAddress=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.ADBIPAddress = matchReg.group(1) - elif re.match('^\-\-ADBUserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-ADBUserName=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.ADBUserName = matchReg.group(1) - elif re.match('^\-\-ADBType=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-ADBType=(.+)$', myArgv, re.IGNORECASE) - if re.match('centralized', matchReg.group(1), re.IGNORECASE) or re.match('distributed', matchReg.group(1), re.IGNORECASE): - if re.match('distributed', matchReg.group(1), re.IGNORECASE): - CiTestObj.ADBCentralized = False - else: - CiTestObj.ADBCentralized = True - else: - sys.exit('Invalid ADB Type: ' + matchReg.group(1) + ' -- (should be centralized or distributed)') - elif re.match('^\-\-ADBPassword=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-ADBPassword=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.ADBPassword = matchReg.group(1) - elif re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-XMLTestFile=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.testXMLfiles.append(matchReg.group(1)) - HTML.SettestXMLfiles(matchReg.group(1)) - CiTestObj.nbTestXMLfiles += 1 - elif re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-UEIPAddress=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.UEIPAddress = matchReg.group(1) - elif re.match('^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-UEUserName=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.UEUserName = matchReg.group(1) - elif re.match('^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-UEPassword=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.UEPassword = matchReg.group(1) - elif re.match('^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-UESourceCodePath=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.UESourceCodePath = matchReg.group(1) - elif re.match('^\-\-finalStatus=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-finalStatus=(.+)$', myArgv, re.IGNORECASE) - finalStatus = matchReg.group(1) - if ((finalStatus == 'true') or (finalStatus == 'True')): - CiTestObj.finalStatus = True - else: - GenericHelp(Version) - sys.exit('Invalid Parameter: ' + myArgv) - -if re.match('^TerminateeNB$', mode, re.IGNORECASE): - if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - RAN.SeteNB_serverId('0') - RAN.SeteNB_instance('0') - RAN.SeteNBSourceCodePath('/tmp/') - CiTestObj.TerminateeNB() -elif re.match('^TerminateUE$', mode, re.IGNORECASE): - if (CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == ''): - GenericHelp(Version) - sys.exit('Insufficient Parameter') - signal.signal(signal.SIGUSR1, receive_signal) - CiTestObj.TerminateUE() -elif re.match('^TerminateOAIUE$', mode, re.IGNORECASE): - if CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - signal.signal(signal.SIGUSR1, receive_signal) - CiTestObj.TerminateOAIUE() -elif re.match('^TerminateHSS$', mode, re.IGNORECASE): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - CiTestObj.TerminateHSS() -elif re.match('^TerminateMME$', mode, re.IGNORECASE): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - CiTestObj.TerminateMME() -elif re.match('^TerminateSPGW$', mode, re.IGNORECASE): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - CiTestObj.TerminateSPGW() -elif re.match('^LogCollectBuild$', mode, re.IGNORECASE): - if (RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '') and (CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == ''): - GenericHelp(Version) - sys.exit('Insufficient Parameter') - CiTestObj.LogCollectBuild() -elif re.match('^LogCollecteNB$', mode, re.IGNORECASE): - if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - CiTestObj.LogCollecteNB() -elif re.match('^LogCollectHSS$', mode, re.IGNORECASE): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - EPC.LogCollectHSS() -elif re.match('^LogCollectMME$', mode, re.IGNORECASE): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - EPC.LogCollectMME() -elif re.match('^LogCollectSPGW$', mode, re.IGNORECASE): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - EPC.LogCollectSPGW() -elif re.match('^LogCollectPing$', mode, re.IGNORECASE): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - CiTestObj.LogCollectPing() -elif re.match('^LogCollectIperf$', mode, re.IGNORECASE): - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - CiTestObj.LogCollectIperf() -elif re.match('^LogCollectOAIUE$', mode, re.IGNORECASE): - if CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == '': - GenericHelp(Version) - sys.exit('Insufficient Parameter') - CiTestObj.LogCollectOAIUE() -elif re.match('^InitiateHtml$', mode, re.IGNORECASE): - if (CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == ''): - GenericHelp(Version) - sys.exit('Insufficient Parameter') - count = 0 - foundCount = 0 - while (count < CiTestObj.nbTestXMLfiles): - #xml_test_file = cwd + "/" + CiTestObj.testXMLfiles[count] - xml_test_file = sys.path[0] + "/" + CiTestObj.testXMLfiles[count] - if (os.path.isfile(xml_test_file)): - try: - xmlTree = ET.parse(xml_test_file) - except: - print("Error while parsing file: " + xml_test_file) - xmlRoot = xmlTree.getroot() - HTML.SethtmlTabRefs(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count))) - HTML.SethtmlTabNames(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count))) - HTML.SethtmlTabIcons(xmlRoot.findtext('htmlTabIcon',default='info-sign')) - #CiTestObj.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count))) - #CiTestObj.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-' + str(count))) - #CiTestObj.htmlTabIcons.append(xmlRoot.findtext('htmlTabIcon',default='info-sign')) - foundCount += 1 - count += 1 - if foundCount != CiTestObj.nbTestXMLfiles: - CiTestObj.nbTestXMLfiles = foundCount - HTML.SetnbTestXMLfiles(CiTestObj.nbTestXMLfiles) - - if (CiTestObj.ADBIPAddress != 'none'): - terminate_ue_flag = False - CiTestObj.GetAllUEDevices(terminate_ue_flag) - CiTestObj.GetAllCatMDevices(terminate_ue_flag) - HTML.SethtmlUEConnected(len(CiTestObj.UEDevices) + len(CiTestObj.CatMDevices)) - HTML.SethtmlNb_Smartphones(len(CiTestObj.UEDevices)) - HTML.SethtmlNb_CATM_Modules(len(CiTestObj.CatMDevices)) - HTML.CreateHtmlHeader(CiTestObj.ADBIPAddress) -elif re.match('^FinalizeHtml$', mode, re.IGNORECASE): - HTML.SetreseNB(RetrieveSystemVersion('eNB')) - HTML.SetresUE(RetrieveSystemVersion('UE')) - HTML.CreateHtmlFooter(CiTestObj.finalStatus) -elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re.IGNORECASE): - if re.match('^TesteNB$', mode, re.IGNORECASE): - if RAN.GeteNBIPAddress() == '' or RAN.GetranRepository() == '' or RAN.GetranBranch() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '' or EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '' or CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == '': - GenericHelp(Version) - if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '' or EPC.GetType() == '': - EPCSrvHelp(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), EPC.GetSourceCodePath(), EPC.GetType()) - if RAN.GetranRepository() == '': - GitSrvHelp(RAN.GetranRepository(),RAN.GetranBranch(),RAN.GetranCommitID(),RAN.GetranAllowMerge(),RAN.GetranTargetBranch()) - if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '': - eNBSrvHelp(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath()) - sys.exit('Insufficient Parameter') - - if (EPC.GetIPAddress() != '') and (EPC.GetIPAddress() != 'none'): - SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), cwd + "/tcp_iperf_stats.awk", "/tmp") - SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), cwd + "/active_net_interfaces.awk", "/tmp") - else: - if CiTestObj.UEIPAddress == '' or RAN.GetranRepository() == '' or RAN.GetranBranch() == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == '': - GenericHelp(Version) - sys.exit('UE: Insufficient Parameter') - - #read test_case_list.xml file - # if no parameters for XML file, use default value - if (CiTestObj.nbTestXMLfiles != 1): - xml_test_file = cwd + "/test_case_list.xml" - else: - xml_test_file = cwd + "/" + CiTestObj.testXMLfiles[0] - - xmlTree = ET.parse(xml_test_file) - xmlRoot = xmlTree.getroot() - - exclusion_tests=xmlRoot.findtext('TestCaseExclusionList',default='') - requested_tests=xmlRoot.findtext('TestCaseRequestedList',default='') - if (CiTestObj.nbTestXMLfiles == 1): - HTML.SethtmlTabRefs(xmlRoot.findtext('htmlTabRef',default='test-tab-0')) - HTML.SethtmlTabNames(xmlRoot.findtext('htmlTabName',default='Test-0')) - #CiTestObj.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-0')) - #CiTestObj.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-0')) - repeatCount = xmlRoot.findtext('repeatCount',default='1') - CiTestObj.repeatCounts.append(int(repeatCount)) - all_tests=xmlRoot.findall('testCase') - - exclusion_tests=exclusion_tests.split() - requested_tests=requested_tests.split() - - #check that exclusion tests are well formatted - #(6 digits or less than 6 digits followed by +) - for test in exclusion_tests: - if (not re.match('^[0-9]{6}$', test) and - not re.match('^[0-9]{1,5}\+$', test)): - logging.debug('ERROR: exclusion test is invalidly formatted: ' + test) - sys.exit(1) - else: - logging.debug(test) - - #check that requested tests are well formatted - #(6 digits or less than 6 digits followed by +) - #be verbose - for test in requested_tests: - if (re.match('^[0-9]{6}$', test) or - re.match('^[0-9]{1,5}\+$', test)): - logging.debug('INFO: test group/case requested: ' + test) - else: - logging.debug('ERROR: requested test is invalidly formatted: ' + test) - sys.exit(1) - if (EPC.GetIPAddress() != '') and (EPC.GetIPAddress() != 'none'): - CiTestObj.CheckFlexranCtrlInstallation() - - #get the list of tests to be done - todo_tests=[] - for test in requested_tests: - if (test_in_list(test, exclusion_tests)): - logging.debug('INFO: test will be skipped: ' + test) - else: - #logging.debug('INFO: test will be run: ' + test) - todo_tests.append(test) - - signal.signal(signal.SIGUSR1, receive_signal) - - if (CiTestObj.ADBIPAddress != 'none'): - terminate_ue_flag = False - CiTestObj.GetAllUEDevices(terminate_ue_flag) - CiTestObj.GetAllCatMDevices(terminate_ue_flag) - else: - CiTestObj.UEDevices.append('OAI-UE') - HTML.SethtmlUEConnected(len(CiTestObj.UEDevices) + len(CiTestObj.CatMDevices)) - HTML.CreateHtmlTabHeader() - - CiTestObj.FailReportCnt = 0 - RAN.SetprematureExit(True) - CiTestObj.startTime = int(round(time.time() * 1000)) - HTML.SetstartTime(CiTestObj.startTime) - while CiTestObj.FailReportCnt < CiTestObj.repeatCounts[0] and RAN.GetprematureExit(): - RAN.SetprematureExit(False) - # At every iteratin of the retry loop, a separator will be added - # pass CiTestObj.FailReportCnt as parameter of HTML.CreateHtmlRetrySeparator - HTML.CreateHtmlRetrySeparator(CiTestObj.FailReportCnt) - for test_case_id in todo_tests: - if RAN.GetprematureExit(): - break - for test in all_tests: - if RAN.GetprematureExit(): - break - id = test.get('id') - if test_case_id != id: - continue - CiTestObj.testCase_id = id - RAN.SettestCase_id(CiTestObj.testCase_id) - HTML.SettestCase_id(CiTestObj.testCase_id) - CiTestObj.desc = test.findtext('desc') - HTML.Setdesc(CiTestObj.desc) - action = test.findtext('class') - if (CheckClassValidity(action, id) == False): - continue - CiTestObj.ShowTestID() - GetParametersFromXML(action) - if action == 'Initialize_UE' or action == 'Attach_UE' or action == 'Detach_UE' or action == 'Ping' or action == 'Iperf' or action == 'Reboot_UE' or action == 'DataDisable_UE' or action == 'DataEnable_UE' or action == 'CheckStatusUE': - if (CiTestObj.ADBIPAddress != 'none'): - terminate_ue_flag = False - CiTestObj.GetAllUEDevices(terminate_ue_flag) - if action == 'Build_eNB': - RAN.BuildeNB() - elif action == 'WaitEndBuild_eNB': - RAN.WaitBuildeNBisFinished() - elif action == 'Initialize_eNB': - check_eNB = False - check_OAI_UE = False - RAN.SetpStatus(CiTestObj.CheckProcessExist(check_eNB, check_OAI_UE)) - - RAN.InitializeeNB() - elif action == 'Terminate_eNB': - RAN.TerminateeNB() - elif action == 'Initialize_UE': - CiTestObj.InitializeUE() - elif action == 'Terminate_UE': - CiTestObj.TerminateUE() - elif action == 'Attach_UE': - CiTestObj.AttachUE() - elif action == 'Detach_UE': - CiTestObj.DetachUE() - elif action == 'DataDisable_UE': - CiTestObj.DataDisableUE() - elif action == 'DataEnable_UE': - CiTestObj.DataEnableUE() - elif action == 'CheckStatusUE': - CiTestObj.CheckStatusUE() - elif action == 'Build_OAI_UE': - CiTestObj.BuildOAIUE() - elif action == 'Initialize_OAI_UE': - CiTestObj.InitializeOAIUE() - elif action == 'Terminate_OAI_UE': - CiTestObj.TerminateOAIUE() - elif action == 'Initialize_CatM_module': - CiTestObj.InitializeCatM() - elif action == 'Terminate_CatM_module': - CiTestObj.TerminateCatM() - elif action == 'Attach_CatM_module': - CiTestObj.AttachCatM() - elif action == 'Detach_CatM_module': - CiTestObj.TerminateCatM() - elif action == 'Ping_CatM_module': - CiTestObj.PingCatM() - elif action == 'Ping': - CiTestObj.Ping() - elif action == 'Iperf': - CiTestObj.Iperf() - elif action == 'Reboot_UE': - CiTestObj.RebootUE() - elif action == 'Initialize_HSS': - EPC.InitializeHSS() - elif action == 'Terminate_HSS': - EPC.TerminateHSS() - elif action == 'Initialize_MME': - EPC.InitializeMME() - elif action == 'Terminate_MME': - EPC.TerminateMME() - elif action == 'Initialize_SPGW': - EPC.InitializeSPGW() - elif action == 'Terminate_SPGW': - EPC.TerminateSPGW() - elif action == 'Initialize_FlexranCtrl': - CiTestObj.InitializeFlexranCtrl() - elif action == 'Terminate_FlexranCtrl': - CiTestObj.TerminateFlexranCtrl() - elif action == 'IdleSleep': - CiTestObj.IdleSleep() - elif action == 'Perform_X2_Handover': - CiTestObj.Perform_X2_Handover() - else: - sys.exit('Invalid action') - CiTestObj.FailReportCnt += 1 - if CiTestObj.FailReportCnt == CiTestObj.repeatCounts[0] and RAN.GetprematureExit(): - logging.debug('Testsuite failed ' + str(CiTestObj.FailReportCnt) + ' time(s)') - HTML.CreateHtmlTabFooter(False) - sys.exit('Failed Scenario') - else: - logging.info('Testsuite passed after ' + str(CiTestObj.FailReportCnt) + ' time(s)') - HTML.CreateHtmlTabFooter(True) -else: - GenericHelp(Version) - sys.exit('Invalid mode') -sys.exit(0) From 657a42fec3b1b48371c4030fe3fae7eb0fc0f07d Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Thu, 2 Apr 2020 14:33:37 +0200 Subject: [PATCH 114/240] CI: during VM builds, we often have connection issues. Adding retry options to wget Signed-off-by: Raphael Defosseux --- cmake_targets/tools/build_helper | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 818b1fd79c..8e4ae59a7f 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -217,7 +217,7 @@ install_protobuf_from_source(){ #tar -xzvf protobuf-2.6.1.tar.gz --owner $USER --group $USER --no-same-owner #cd protobuf-2.6.1/ rm -rf /tmp/protobuf-cpp-3.3.0.tar.gz* /tmp/protobuf-3.3.0 - wget https://github.com/google/protobuf/releases/download/v3.3.0/protobuf-cpp-3.3.0.tar.gz + wget --tries=3 --retry-connrefused https://github.com/google/protobuf/releases/download/v3.3.0/protobuf-cpp-3.3.0.tar.gz tar -xzvf protobuf-cpp-3.3.0.tar.gz --owner $USER --group $(groups | cut -d" " -f1) --no-same-owner cd protobuf-3.3.0/ ./configure @@ -353,8 +353,8 @@ install_bladerf_driver_from_source(){ $SUDO ldconfig echo "Downloading FPGA and firmware images" cd /tmp/bladeRF - wget https://www.nuand.com/fx3/bladeRF_fw_latest.img - wget https://www.nuand.com/fpga/hostedx40-latest.rbf + wget --tries=3 --retry-connrefused https://www.nuand.com/fx3/bladeRF_fw_latest.img + wget --tries=3 --retry-connrefused https://www.nuand.com/fpga/hostedx40-latest.rbf sudo mkdir -p /usr/share/Nuand/bladeRF sudo mv bladeRF_fw_latest.img /usr/share/Nuand/bladeRF/bladeRF_fw.img sudo mv hostedx40-latest.rbf /usr/share/Nuand/bladeRF/hostedx40.rbf @@ -567,7 +567,7 @@ check_install_additional_tools (){ echo_info "Installing Netinterfaces package. The logfile for installation is in $log_netiface" ( $SUDO rm -fr /tmp/netifaces-0.10.4.tar.gz /tmp/netifaces - wget -P /tmp https://pypi.python.org/packages/18/fa/dd13d4910aea339c0bb87d2b3838d8fd923c11869b1f6e741dbd0ff3bc00/netifaces-0.10.4.tar.gz + wget --tries=3 --retry-connrefused -P /tmp https://pypi.python.org/packages/18/fa/dd13d4910aea339c0bb87d2b3838d8fd923c11869b1f6e741dbd0ff3bc00/netifaces-0.10.4.tar.gz tar -xzvf /tmp/netifaces-0.10.4.tar.gz -C /tmp cd /tmp/netifaces-0.10.4 $SUDO python setup.py install From 9eab72b2bf8a78a86cb1f93194ae8450047f0760 Mon Sep 17 00:00:00 2001 From: Gabriele Perrone Date: Mon, 6 Apr 2020 09:18:42 +0200 Subject: [PATCH 115/240] aligning remote repository with local on starsky --- ci-scripts/epc.py | 20 ++++++---- ci-scripts/html.py | 11 +++++- ci-scripts/main.py | 99 ++++++++++++++++++++-------------------------- ci-scripts/ran.py | 22 +++++------ 4 files changed, 76 insertions(+), 76 deletions(-) diff --git a/ci-scripts/epc.py b/ci-scripts/epc.py index 6c48dcd15d..c297b3e3b7 100644 --- a/ci-scripts/epc.py +++ b/ci-scripts/epc.py @@ -55,7 +55,7 @@ class EPCManagement(): def __init__(self): - self.IPAddress = '' + self.EPCIPAddress = '' self.UserName = '' self.Password = '' self.SourceCodePath = '' @@ -130,7 +130,8 @@ class EPCManagement(): else: logging.error('This option should not occur!') mySSH.close() - HTML.CreateHtmlTestRow(self.EPCType, 'OK', CONST.ALL_PROCESSES_OK) + myHTML = HTML.HTMLManagement() + myHTML.CreateHtmlTestRow(self.EPCType, 'OK', CONST.ALL_PROCESSES_OK) def InitializeMME(self): if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': @@ -163,7 +164,8 @@ class EPCManagement(): else: logging.error('This option should not occur!') mySSH.close() - HTML.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) + myHTML = HTML.HTMLManagement() + myHTML.CreateHtmlTestRow(self.EPCType, 'OK', CONST.ALL_PROCESSES_OK) def InitializeSPGW(self): if self.EPCIPAddress == '' or self.EPCUserName == '' or self.EPCPassword == '' or self.EPCSourceCodePath == '' or self.EPCType == '': @@ -194,7 +196,8 @@ class EPCManagement(): else: logging.error('This option should not occur!') mySSH.close() - HTML.CreateHtmlTestRow(self.EPCType, 'OK', ALL_PROCESSES_OK) + myHTML = HTML.HTMLManagement() + myHTML.CreateHtmlTestRow(self.EPCType, 'OK', CONST.ALL_PROCESSES_OK) def CheckHSSProcess(self, status_queue): @@ -294,7 +297,8 @@ class EPCManagement(): else: logging.error('This should not happen!') mySSH.close() - HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + myHTML = HTML.HTMLManagement() + myHTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def TerminateMME(self): mySSH = SSH.SSHConnection() @@ -313,7 +317,8 @@ class EPCManagement(): else: logging.error('This should not happen!') mySSH.close() - HTML.CreateHtmlTestRow('N/A', 'OK', ALL_PROCESSES_OK) + myHTML = HTML.HTMLManagement() + myHTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def TerminateSPGW(self): mySSH = SSH.SSHConnection() @@ -344,7 +349,8 @@ class EPCManagement(): else: logging.error('This should not happen!') mySSH.close() - HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + myHTML = HTML.HTMLManagement() + myHTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def LogCollectHSS(self): diff --git a/ci-scripts/html.py b/ci-scripts/html.py index ccd89eb577..15acafd2ed 100644 --- a/ci-scripts/html.py +++ b/ci-scripts/html.py @@ -45,7 +45,8 @@ from multiprocessing import Process, Lock, SimpleQueue class HTMLManagement(): def __init__(self): - + + self.htmlFile = '' self.htmlHeaderCreated = False self.htmlFooterCreated = False self.ranAllowMerge = False @@ -54,10 +55,18 @@ class HTMLManagement(): self.htmlTabNames = [] self.htmlTabIcons = [] self.testXMLfiles = [] + self.htmleNBFailureMsg = '' + self.htmlUEFailureMsg = '' #----------------------------------------------------------- # Setters and Getters #----------------------------------------------------------- + def SethtmlUEFailureMsg(self,huefa): + self.htmlUEFailureMsg = huefa + def GethtmlUEFailureMsg(self): + return huefa + + def SetreseNB(self,rsenb): self.reseNB = rsenb def SetresUE(self,rsue): diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 1dd8402250..2c59b09f60 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -68,7 +68,6 @@ class OaiCiTest(): self.ADBCentralized = True self.testCase_id = '' self.testXMLfiles = [] - #self.nbTestXMLfiles = 0 self.desc = '' self.ping_args = '' self.ping_packetloss_threshold = '' @@ -86,12 +85,7 @@ class OaiCiTest(): self.UEDevicesRebootCmd = [] self.CatMDevices = [] self.UEIPAddresses = [] - self.htmlFile = '' - # self.htmlHeaderCreated = False - # self.htmlFooterCreated = False self.htmlUEConnected = -1 - self.htmleNBFailureMsg = '' - self.htmlUEFailureMsg = '' self.picocom_closure = False self.idle_sleep_time = 0 self.x2_ho_options = 'network' @@ -116,8 +110,6 @@ class OaiCiTest(): self.Build_OAI_UE_args = '' self.Initialize_OAI_UE_args = '' self.clean_repository = True - self.flexranCtrlInstalled = False - self.flexranCtrlStarted = False self.expectedNbOfConnectedUEs = 0 self.startTime = 0 @@ -232,13 +224,12 @@ class OaiCiTest(): SSH.command('ls -ls /opt/flexran_rtc/*/rt_controller', '\$', 5) result = re.search('/opt/flexran_rtc/build/rt_controller', SSH.getBefore()) if result is not None: - self.flexranCtrlInstalled = True RAN.SetflexranCtrlInstalled(True) logging.debug('Flexran Controller is installed') SSH.close() def InitializeFlexranCtrl(self): - if self.flexranCtrlInstalled == False: + if RAN.GetflexranCtrlInstalled() == False: return if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '': GenericHelp(Version) @@ -253,7 +244,6 @@ class OaiCiTest(): result = re.search('rt_controller -c ', SSH.getBefore()) if result is not None: logging.debug('\u001B[1m Initialize FlexRan Controller Completed\u001B[0m') - self.flexranCtrlStarted = True RAN.SetflexranCtrlStarted(True) SSH.close() HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) @@ -487,12 +477,12 @@ class OaiCiTest(): else: if RAN.Getair_interface() == 'lte': if RAN.GeteNBmbmsEnables[0]: - self.htmlUEFailureMsg = 'oaitun_ue1/oaitun_uem1 interfaces are either NOT mounted or NOT configured' + HTML.SethtmlUEFailureMsg('oaitun_ue1/oaitun_uem1 interfaces are either NOT mounted or NOT configured') else: - self.htmlUEFailureMsg = 'oaitun_ue1 interface is either NOT mounted or NOT configured' + HTML.SethtmlUEFailureMsg('oaitun_ue1 interface is either NOT mounted or NOT configured') HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', CONST.OAI_UE_PROCESS_NO_TUNNEL_INTERFACE, 'OAI UE') else: - self.htmlUEFailureMsg = 'nr-uesoftmodem did NOT synced' + HTML.SethtmlUEFailureMsg('nr-uesoftmodem did NOT synced') HTML.CreateHtmlTestRow(self.Initialize_OAI_UE_args, 'KO', CONST.OAI_UE_PROCESS_COULD_NOT_SYNC, 'OAI UE') logging.error('\033[91mInitialize OAI UE Failed! \033[0m') self.AutoTerminateUEandeNB() @@ -1176,7 +1166,7 @@ class OaiCiTest(): i += 1 for job in multi_jobs: job.join() - if self.flexranCtrlInstalled and self.flexranCtrlStarted: + if RAN.GetflexranCtrlInstalled() and RAN.GetflexranCtrlStarted(): SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) SSH.command('cd /opt/flexran_rtc', '\$', 5) SSH.command('curl http://localhost:9999/stats | jq \'.\' > log/check_status_' + self.testCase_id + '.log 2>&1', '\$', 5) @@ -2340,7 +2330,7 @@ class OaiCiTest(): if logStatus < 0: result = logStatus RAN.SeteNBLogFiles[0] = '' - if self.flexranCtrlInstalled and self.flexranCtrlStarted: + if RAN.GetflexranCtrlInstalled() and RAN.GetflexranCtrlStarted(): self.TerminateFlexranCtrl() return result @@ -2416,7 +2406,7 @@ class OaiCiTest(): nrFoundDCI = 0 nrCRCOK = 0 mbms_messages = 0 - self.htmlUEFailureMsg = '' + HTML.SethtmlUEFailureMsg('') for line in ue_log_file.readlines(): result = re.search('nr_synchro_time', str(line)) if result is not None: @@ -2485,22 +2475,22 @@ class OaiCiTest(): if result is not None and (not mib_found): try: mibMsg = "MIB Information: " + result.group(1) + ', ' + result.group(2) - self.htmlUEFailureMsg += mibMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + '\n') logging.debug('\033[94m' + mibMsg + '\033[0m') mibMsg = " nidcell = " + result.group('nidcell') - self.htmlUEFailureMsg += mibMsg + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg) logging.debug('\033[94m' + mibMsg + '\033[0m') mibMsg = " n_rb_dl = " + result.group('n_rb_dl') - self.htmlUEFailureMsg += mibMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + '\n') logging.debug('\033[94m' + mibMsg + '\033[0m') mibMsg = " phich_duration = " + result.group('phich_duration') - self.htmlUEFailureMsg += mibMsg + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg) logging.debug('\033[94m' + mibMsg + '\033[0m') mibMsg = " phich_resource = " + result.group('phich_resource') - self.htmlUEFailureMsg += mibMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + '\n') logging.debug('\033[94m' + mibMsg + '\033[0m') mibMsg = " tx_ant = " + result.group('tx_ant') - self.htmlUEFailureMsg += mibMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + '\n') logging.debug('\033[94m' + mibMsg + '\033[0m') mib_found = True except Exception as e: @@ -2509,7 +2499,7 @@ class OaiCiTest(): if result is not None and (not frequency_found): try: mibMsg = "Measured Carrier Frequency = " + result.group('measured_carrier_frequency') + ' Hz' - self.htmlUEFailureMsg += mibMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + '\n') logging.debug('\033[94m' + mibMsg + '\033[0m') frequency_found = True except Exception as e: @@ -2518,7 +2508,7 @@ class OaiCiTest(): if result is not None and (not plmn_found): try: mibMsg = 'PLMN MCC = ' + result.group('mcc') + ' MNC = ' + result.group('mnc') - self.htmlUEFailureMsg += mibMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + '\n') logging.debug('\033[94m' + mibMsg + '\033[0m') plmn_found = True except Exception as e: @@ -2527,7 +2517,7 @@ class OaiCiTest(): if result is not None: try: mibMsg = "The operator is: " + result.group('operator') - self.htmlUEFailureMsg += mibMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + '\n') logging.debug('\033[94m' + mibMsg + '\033[0m') except Exception as e: logging.error('\033[91m' + "Operator name not found" + '\033[0m') @@ -2535,7 +2525,7 @@ class OaiCiTest(): if result is not None: try: mibMsg = "SIB5 InterFreqCarrierFreq element " + result.group(1) + '/' + result.group(2) - self.htmlUEFailureMsg += mibMsg + ' -> ' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + mibMsg + ' -> ') logging.debug('\033[94m' + mibMsg + '\033[0m') except Exception as e: logging.error('\033[91m' + "SIB5 InterFreqCarrierFreq element not found" + '\033[0m') @@ -2545,7 +2535,7 @@ class OaiCiTest(): freq = result.group('carrier_frequency') new_freq = re.sub('/[0-9]+','',freq) float_freq = float(new_freq) / 1000000 - self.htmlUEFailureMsg += 'DL Freq: ' + ('%.1f' % float_freq) + ' MHz' + HTMLSethtmlUEFailureMsg(HTMLGethtmlUEFailureMsg() + 'DL Freq: ' + ('%.1f' % float_freq) + ' MHz') logging.debug('\033[94m' + " DL Carrier Frequency is: " + freq + '\033[0m') except Exception as e: logging.error('\033[91m' + " DL Carrier Frequency not found" + '\033[0m') @@ -2553,7 +2543,7 @@ class OaiCiTest(): if result is not None: try: prb = result.group('allowed_bandwidth') - self.htmlUEFailureMsg += ' -- PRB: ' + prb + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + ' -- PRB: ' + prb + '\n') logging.debug('\033[94m' + " AllowedMeasBandwidth: " + prb + '\033[0m') except Exception as e: logging.error('\033[91m' + " AllowedMeasBandwidth not found" + '\033[0m') @@ -2561,48 +2551,48 @@ class OaiCiTest(): if rrcConnectionRecfgComplete > 0: statMsg = 'UE connected to eNB (' + str(rrcConnectionRecfgComplete) + ' RRCConnectionReconfigurationComplete message(s) generated)' logging.debug('\033[94m' + statMsg + '\033[0m') - self.htmlUEFailureMsg += statMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') if nrUEFlag: if nrDecodeMib > 0: statMsg = 'UE showed ' + str(nrDecodeMib) + ' MIB decode message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') if nrFoundDCI > 0: statMsg = 'UE showed ' + str(nrFoundDCI) + ' DCI found message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') if nrCRCOK > 0: statMsg = 'UE showed ' + str(nrCRCOK) + ' PDSCH decoding message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') if not frequency_found: statMsg = 'NR-UE could NOT synch!' logging.error('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') if uciStatMsgCount > 0: statMsg = 'UE showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') if pdcpDataReqFailedCount > 0: statMsg = 'UE showed ' + str(pdcpDataReqFailedCount) + ' "PDCP data request failed" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') if badDciCount > 0: statMsg = 'UE showed ' + str(badDciCount) + ' "bad DCI 1(A)" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') if f1aRetransmissionCount > 0: statMsg = 'UE showed ' + str(f1aRetransmissionCount) + ' "Format1A Retransmission but TBS are different" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') if fatalErrorCount > 0: statMsg = 'UE showed ' + str(fatalErrorCount) + ' "FATAL ERROR:" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') if macBsrTimerExpiredCount > 0: statMsg = 'UE showed ' + str(fatalErrorCount) + ' "MAC BSR Triggered ReTxBSR Timer expiry" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') if RAN.GeteNBmbmsEnables[0]: if mbms_messages > 0: statMsg = 'UE showed ' + str(mbms_messages) + ' "TRIED TO PUSH MBMS DATA" message(s)' @@ -2610,7 +2600,7 @@ class OaiCiTest(): else: statMsg = 'UE did NOT SHOW "TRIED TO PUSH MBMS DATA" message(s)' logging.debug('\u001B[1;30;41m ' + statMsg + ' \u001B[0m') - self.htmlUEFailureMsg += statMsg + '\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') if foundSegFault: logging.debug('\u001B[1;37;41m UE ended with a Segmentation Fault! \u001B[0m') if not nrUEFlag: @@ -2620,7 +2610,7 @@ class OaiCiTest(): return CONST.OAI_UE_PROCESS_SEG_FAULT if foundAssertion: logging.debug('\u001B[1;30;43m UE showed an assertion! \u001B[0m') - self.htmlUEFailureMsg += 'UE showed an assertion!\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + 'UE showed an assertion!\n') if not nrUEFlag: if not mib_found or not frequency_found: return CONST.OAI_UE_PROCESS_ASSERTION @@ -2629,7 +2619,7 @@ class OaiCiTest(): return CONST.OAI_UE_PROCESS_ASSERTION if foundRealTimeIssue: logging.debug('\u001B[1;37;41m UE faced real time issues! \u001B[0m') - self.htmlUEFailureMsg += 'UE faced real time issues!\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + 'UE faced real time issues!\n') #return CONST.ENB_PROCESS_REALTIME_ISSUE if nrUEFlag: if not frequency_found: @@ -2637,13 +2627,13 @@ class OaiCiTest(): else: if no_cell_sync_found and not mib_found: logging.debug('\u001B[1;37;41m UE could not synchronize ! \u001B[0m') - self.htmlUEFailureMsg += 'UE could not synchronize!\n' + HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + 'UE could not synchronize!\n') return CONST.OAI_UE_PROCESS_COULD_NOT_SYNC return 0 def TerminateFlexranCtrl(self): - if self.flexranCtrlInstalled == False or self.flexranCtrlStarted == False: + if RAN.GetflexranCtrlInstalled() == False or RAN.GetflexranCtrlStarted() == False: return if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '': GenericHelp(Version) @@ -2654,7 +2644,7 @@ class OaiCiTest(): SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S killall --signal SIGKILL rt_controller', '\$', 5) time.sleep(1) SSH.close() - self.flexranCtrlStarted = False + RAN.SetflexranCtrlStarted(False) HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) def TerminateUE_common(self, device_id, idx): @@ -2720,7 +2710,7 @@ class OaiCiTest(): copyin_res = SSH.copyin(self.UEIPAddress, self.UEUserName, self.UEPassword, self.UESourceCodePath + '/cmake_targets/' + self.UELogFile, '.') if (copyin_res == -1): logging.debug('\u001B[1;37;41m Could not copy UE logfile to analyze it! \u001B[0m') - self.htmlUEFailureMsg = 'Could not copy UE logfile to analyze it!' + HTML.SethtmlUEFailureMsg('Could not copy UE logfile to analyze it!') HTML.CreateHtmlTestRow('N/A', 'KO', CONST.OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE, 'UE') self.UELogFile = '' return @@ -2733,7 +2723,7 @@ class OaiCiTest(): ueAction = 'Connection' if (logStatus < 0): logging.debug('\u001B[1m' + ueAction + ' Failed \u001B[0m') - self.htmlUEFailureMsg = '' + ueAction + ' Failed\n' + self.htmlUEFailureMsg + HTML.SethtmlUEFailureMsg('' + ueAction + ' Failed\n' + HTML.GethtmlUEFailureMsg()) HTML.CreateHtmlTestRow('N/A', 'KO', logStatus, 'UE') if RAN.Getair_interface() == 'lte': # In case of sniffing on commercial eNBs we have random results @@ -2747,7 +2737,7 @@ class OaiCiTest(): self.AutoTerminateUEandeNB() else: logging.debug('\u001B[1m' + ueAction + ' Completed \u001B[0m') - self.htmlUEFailureMsg = '' + ueAction + ' Completed\n' + self.htmlUEFailureMsg + HTML.SethtmlUEFailureMsg('' + ueAction + ' Completed\n' + HTML.GethtmlUEFailureMsg()) HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) self.UELogFile = '' else: @@ -2773,7 +2763,7 @@ class OaiCiTest(): self.ShowTestID() RAN.SeteNB_instance('0') RAN.TerminateeNB() - if self.flexranCtrlInstalled and self.flexranCtrlStarted: + if RAN.GetflexranCtrlInstalled() and RAN.GetflexranCtrlStarted(): self.testCase_id = 'AUTO-KILL-flexran-ctl' RAN.SettestCase_id(self.testCase_id) self.desc = 'Automatic Termination of FlexRan CTL' @@ -2835,7 +2825,7 @@ class OaiCiTest(): logging.debug(msg) fullMessage += msg + '\n' if self.x2_ho_options == 'network': - if self.flexranCtrlInstalled and self.flexranCtrlStarted: + if RAN.GetflexranCtrlInstalled() and RAN.GetflexranCtrlStarted(): self.x2ENBBsIds = [] self.x2ENBConnectedUEs = [] self.x2ENBBsIds.append([]) @@ -3207,7 +3197,6 @@ EPC = epc.EPCManagement() RAN = ran.RANManagement() HTML = html.HTMLManagement() - argvs = sys.argv argc = len(argvs) cwd = os.getcwd() @@ -3300,10 +3289,6 @@ while len(argvs) > 1: elif re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE) EPC.SetIPAddress(matchReg.group(1)) -#GP250220: do we still need EPCBranch? it's not used anywhere - elif re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE): - matchReg = re.match('^\-\-EPCBranch=(.+)$', myArgv, re.IGNORECASE) - CiTestObj.EPCBranch = matchReg.group(1) elif re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE) EPC.SetUserName(matchReg.group(1)) @@ -3370,7 +3355,7 @@ if re.match('^TerminateeNB$', mode, re.IGNORECASE): RAN.SeteNB_serverId('0') RAN.SeteNB_instance('0') RAN.SeteNBSourceCodePath('/tmp/') - CiTestObj.TerminateeNB() + RAN.TerminateeNB() elif re.match('^TerminateUE$', mode, re.IGNORECASE): if (CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == ''): GenericHelp(Version) diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py index 04c2e71c5f..454fe5cf5e 100644 --- a/ci-scripts/ran.py +++ b/ci-scripts/ran.py @@ -87,6 +87,9 @@ class RANManagement(): self.eNBLogFiles = ['', '', ''] self.eNBOptions = ['', '', ''] self.eNBmbmsEnables = [False, False, False] + self.eNBstatuses = [-1, -1, -1] + self.flexranCtrlInstalled = False + self.flexranCtrlStarted = False #----------------------------------------------------------- # Setters and Getters @@ -97,8 +100,12 @@ class RANManagement(): self.testCase_id = tcid def SetflexranCtrlInstalled(self,fxrctin): self.flexranCtrlInstalled = fxrctin + def GetflexranCtrlInstalled(self): + return self.flexranCtrlInstalled def SetflexranCtrlStarted(self,fxrctst): self.flexranCtrlStarted = fxrctst + def GetflexranCtrlStarted(self): + return self.flexranCtrlStarted def SetpStatus(self, pSt): self.pStatus = pSt def SetranRepository(self, repository): @@ -175,21 +182,11 @@ class RANManagement(): def GeteNBLogFiles(self): return self.eNBLogFiles - def SeteNBOptions(self, enbopt): - self.eNBOptions = enbopt - def GeteNBOptions(self): - return self.eNBOptions - def SeteNBmbmsEnables(self, enbmbms): self.eNBmbmsEnables = enbmbms def GeteNBmbmsEnables(self): return self.eNBmbmsEnables - def SeteNBstatuses(self, enbstatus): - self.eNBstatuses = enbstatus - def GeteNBstatuses(self): - return self.eNBstatuses - self.eNB1IPAddress = enb1ip def SeteNB1IPAddress(self,enb1ip): self.eNB1IPAddress = enb1ip def GeteNB1IPAddress(self): @@ -339,6 +336,7 @@ class RANManagement(): self.backgroundBuildTestId[int(self.eNB_instance)] = self.testCase_id return mySSH.command('stdbuf -o0 ./build_oai ' + self.Build_eNB_args + ' 2>&1 | stdbuf -o0 tee compile_oai_enb.log', 'Bypassing the Tests|build have failed', 1500) + mySSH.close() self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.testCase_id) @@ -374,11 +372,13 @@ class RANManagement(): else: count -= 1 time.sleep(30) + mySSH.close() self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.backgroundBuildTestId[int(self.eNB_instance)]) def checkBuildeNB(self, lIpAddr, lUserName, lPassWord, lSourcePath, testcaseId): myHTML = HTML.HTMLManagement() mySSH = SSH.SSHConnection() + mySSH.open(lIpAddr, lUserName, lPassWord) mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 3) mySSH.command('ls ran_build/build', '\$', 3) mySSH.command('ls ran_build/build', '\$', 3) @@ -909,7 +909,7 @@ class RANManagement(): enb_log_file.close() logging.debug(' File analysis completed') self.htmleNBFailureMsg = '' - if self.air_interface() == 'lte': + if self.air_interface == 'lte': nodeB_prefix = 'e' else: nodeB_prefix = 'g' From 2ea0070d4d4e2b67d95124bbc9c62b90f56f4537 Mon Sep 17 00:00:00 2001 From: Gabriele Perrone Date: Mon, 6 Apr 2020 12:04:07 +0200 Subject: [PATCH 116/240] further cleanup --- ci-scripts/main.py | 4 ++++ ci-scripts/ran.py | 33 +++++++++++++++++++++------------ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 2c59b09f60..94a7a52dc6 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -3289,15 +3289,19 @@ while len(argvs) > 1: elif re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE) EPC.SetIPAddress(matchReg.group(1)) + RAN.SetIPAddress(matchReg.group(1)) elif re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE) EPC.SetUserName(matchReg.group(1)) + RAN.SetUserName(matchReg.group(1)) elif re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE) EPC.SetPassword(matchReg.group(1)) + RAN.SetPassword(matchReg.group(1)) elif re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE) EPC.SetSourceCodePath(matchReg.group(1)) + RAN.SetSourceCodePath(matchReg.group(1)) elif re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE) if re.match('OAI', matchReg.group(1), re.IGNORECASE) or re.match('ltebox', matchReg.group(1), re.IGNORECASE) or re.match('OAI-Rel14-CUPS', matchReg.group(1), re.IGNORECASE): diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py index 454fe5cf5e..e7f27f7bc6 100644 --- a/ci-scripts/ran.py +++ b/ci-scripts/ran.py @@ -95,6 +95,15 @@ class RANManagement(): # Setters and Getters #----------------------------------------------------------- + def SetIPAddress(self, ipaddress): + self.EPCIPAddress = ipaddress + def SetUserName(self, username): + self.EPCUserName = username + def SetPassword(self, password): + self.EPCPassword = password + def SetSourceCodePath(self, sourcecodepath): + self.EPCSourceCodePath = sourcecodepath + def SettestCase_id(self,tcid): self.testCase_id = tcid @@ -463,15 +472,15 @@ class RANManagement(): # If tracer options is on, running tshark on EPC side and capture traffic b/ EPC and eNB result = re.search('T_stdout', str(self.Initialize_eNB_args)) if result is not None: - mySSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + mySSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) mySSH.command('ip addr show | awk -f /tmp/active_net_interfaces.awk | egrep -v "lo|tun"', '\$', 5) result = re.search('interfaceToUse=(?P[a-zA-Z0-9\-\_]+)done', mySSH.getBefore()) if result is not None: eth_interface = result.group('eth_interface') logging.debug('\u001B[1m Launching tshark on interface ' + eth_interface + '\u001B[0m') EPC.Set_PcapFileName('enb_' + self.testCase_id + '_s1log.pcap') - mySSH.command('echo ' + EPC.GetPassword() + ' | sudo -S rm -f /tmp/' + EPC.Get_PcapFileName() , '\$', 5) - mySSH.command('echo $USER; nohup sudo tshark -f "host ' + lIpAddr +'" -i ' + eth_interface + ' -w /tmp/' + EPC.Get_PcapFileName() + ' > /tmp/tshark.log 2>&1 &', EPC.GetUserName(), 5) + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f /tmp/' + EPC.Get_PcapFileName() , '\$', 5) + mySSH.command('echo $USER; nohup sudo tshark -f "host ' + lIpAddr +'" -i ' + eth_interface + ' -w /tmp/' + EPC.Get_PcapFileName() + ' > /tmp/tshark.log 2>&1 &', self.EPCUserName, 5) mySSH.close() mySSH.open(lIpAddr, lUserName, lPassWord) mySSH.command('cd ' + lSourcePath, '\$', 5) @@ -510,7 +519,7 @@ class RANManagement(): mySSH.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 60) # Make a copy and adapt to EPC / eNB IP addresses mySSH.command('cp ' + full_config_file + ' ' + ci_full_config_file, '\$', 5) - mySSH.command('sed -i -e \'s/CI_MME_IP_ADDR/' + EPC.GetIPAddress() + '/\' ' + ci_full_config_file, '\$', 2); + mySSH.command('sed -i -e \'s/CI_MME_IP_ADDR/' + self.EPCIPAddress + '/\' ' + ci_full_config_file, '\$', 2); mySSH.command('sed -i -e \'s/CI_ENB_IP_ADDR/' + lIpAddr + '/\' ' + ci_full_config_file, '\$', 2); mySSH.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2); mySSH.command('sed -i -e \'s/CI_RRU1_IP_ADDR/' + self.eNB1IPAddress + '/\' ' + ci_full_config_file, '\$', 2); @@ -563,16 +572,16 @@ class RANManagement(): # In case of T tracer recording, we need to kill tshark on EPC side result = re.search('T_stdout', str(self.Initialize_eNB_args)) if result is not None: - mySSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + mySSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) logging.debug('\u001B[1m Stopping tshark \u001B[0m') - mySSH.command('echo ' + EPC.GetPassword() + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) if EPC.Get_PcapFileName() != '': time.sleep(0.5) - mySSH.command('echo ' + EPC.GetPassword() + ' | sudo -S chmod 666 /tmp/' + EPC.Get_PcapFileName() , '\$', 5) + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 /tmp/' + EPC.Get_PcapFileName() , '\$', 5) mySSH.close() time.sleep(1) if EPC.Get_PcapFileName() != '': - copyin_res = mySSH.copyin(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), '/tmp/' + EPC.Get_PcapFileName() , '.') + copyin_res = mySSH.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + EPC.Get_PcapFileName() , '.') if (copyin_res == 0): mySSH.copyout(lIpAddr, lUserName, lPassWord, EPC.Get_PcapFileName() , lSourcePath + '/cmake_targets/.') self.prematureExit = True @@ -691,13 +700,13 @@ class RANManagement(): # If tracer options is on, stopping tshark on EPC side result = re.search('T_stdout', str(self.Initialize_eNB_args)) if result is not None: - mySSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) + mySSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) logging.debug('\u001B[1m Stopping tshark \u001B[0m') - mySSH.command('echo ' + EPC.GetPassword() + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) time.sleep(1) if EPC.Get_PcapFileName() != '': - mySSH.command('echo ' + EPC.GetPassword() + ' | sudo -S chmod 666 /tmp/' + EPC.Get_PcapFileName() , '\$', 5) - mySSH.copyin(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), '/tmp/' + EPC.Get_PcapFileName() , '.') + mySSH.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 /tmp/' + EPC.Get_PcapFileName() , '\$', 5) + mySSH.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + EPC.Get_PcapFileName() , '.') mySSH.copyout(lIpAddr, lUserName, lPassWord, EPC.Get_PcapFileName() , lSourcePath + '/cmake_targets/.') mySSH.close() logging.debug('\u001B[1m Replaying RAW record file\u001B[0m') From 2e9f391a0ae680514d3901e5cd0eba3af67f5ef4 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 29 Jan 2020 17:41:51 +0100 Subject: [PATCH 117/240] Store active LCs in MAC, remove unneeded headers --- openair2/ENB_APP/flexran_agent_ran_api.c | 4 +-- openair2/LAYER2/MAC/config.c | 28 +++++++++++++++++++++ openair2/LAYER2/MAC/mac.h | 32 ++++++------------------ 3 files changed, 38 insertions(+), 26 deletions(-) diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index 4fa7db3fd9..c2bf90ebd8 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -890,13 +890,13 @@ uint8_t flexran_get_rrc_status(mid_t mod_id, rnti_t rnti) { uint64_t flexran_get_ue_aggregated_max_bitrate_dl(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_info.UE_sched_ctrl[ue_id].ue_AggregatedMaximumBitrateDL; + return 0; //RC.mac[mod_id]->UE_info.UE_sched_ctrl[ue_id].ue_AggregatedMaximumBitrateDL; } uint64_t flexran_get_ue_aggregated_max_bitrate_ul(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return 0; - return RC.mac[mod_id]->UE_info.UE_sched_ctrl[ue_id].ue_AggregatedMaximumBitrateUL; + return 0; //RC.mac[mod_id]->UE_info.UE_sched_ctrl[ue_id].ue_AggregatedMaximumBitrateUL; } int flexran_get_half_duplex(mid_t mod_id, rnti_t rnti) { diff --git a/openair2/LAYER2/MAC/config.c b/openair2/LAYER2/MAC/config.c index 4c32ec53be..49949bd771 100644 --- a/openair2/LAYER2/MAC/config.c +++ b/openair2/LAYER2/MAC/config.c @@ -882,6 +882,34 @@ int rrc_mac_config_req_eNB(module_id_t Mod_idP, } } + if (logicalChannelIdentity > 0) { // is SRB1,2 or DRB + if ((UE_id = find_UE_id(Mod_idP, rntiP)) < 0) { + LOG_E(MAC,"Configuration received for unknown UE (%x), shouldn't happen\n",rntiP); + return(-1); + } + int idx = -1; + UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + for (int i = 0; i < sched_ctrl->dl_lc_num; ++i) { + if (sched_ctrl->dl_lc_ids[i] == logicalChannelIdentity) { + /* TODO this might also mean we have to remove it, not clear */ + idx = i; + break; + } + } + if (idx < 0) { + sched_ctrl->dl_lc_num++; + sched_ctrl->dl_lc_ids[sched_ctrl->dl_lc_num-1] = logicalChannelIdentity; + sched_ctrl->dl_lc_bytes[sched_ctrl->dl_lc_num-1] = 0; + LOG_I(MAC, "UE %d RNTI %x adding LC %ld idx %d to scheduling control (total %d)\n", UE_id, rntiP, logicalChannelIdentity, sched_ctrl->dl_lc_num-1, sched_ctrl->dl_lc_num); + if (logicalChannelIdentity == 1) { // if it is SRB1, add SRB2 directly because RRC does not indicate this separately + sched_ctrl->dl_lc_num++; + sched_ctrl->dl_lc_ids[sched_ctrl->dl_lc_num-1] = 2; + sched_ctrl->dl_lc_bytes[sched_ctrl->dl_lc_num-1] = 0; + LOG_I(MAC, "UE %d RNTI %x adding LC 2 idx %d to scheduling control (total %d)\n", UE_id, rntiP, sched_ctrl->dl_lc_num-1, sched_ctrl->dl_lc_num); + } + } + } + // SRB2_lchan_config->choice.explicitValue.ul_SpecificParameters->logicalChannelGroup if (logicalChannelConfig != NULL) { // check for eMTC specific things UE_id = find_UE_id(Mod_idP, rntiP); diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h index 3412aa52c5..6f445eabb7 100644 --- a/openair2/LAYER2/MAC/mac.h +++ b/openair2/LAYER2/MAC/mac.h @@ -852,10 +852,10 @@ typedef struct { // Logical channel info for link with RLC - /// LCGID mapping + /// LCGID mapping (UL) long lcgidmap[11]; - ///UE logical channel priority + ///UE logical channel priority (UL) long lcgidpriority[11]; /// phr information @@ -913,31 +913,15 @@ typedef struct { /*! \brief scheduling control information set through an API (not used)*/ typedef struct { - ///UL transmission bandwidth in RBs - uint8_t ul_bandwidth[MAX_NUM_LCID]; - ///DL transmission bandwidth in RBs - uint8_t dl_bandwidth[MAX_NUM_LCID]; - - //To do GBR bearer - uint8_t min_ul_bandwidth[MAX_NUM_LCID]; - - uint8_t min_dl_bandwidth[MAX_NUM_LCID]; - - ///aggregated bit rate of non-gbr bearer per UE - uint64_t ue_AggregatedMaximumBitrateDL; - ///aggregated bit rate of non-gbr bearer per UE - uint64_t ue_AggregatedMaximumBitrateUL; - ///CQI scheduling interval in subframes. - uint16_t cqiSchedInterval; - ///Contention resolution timer used during random access - uint8_t mac_ContentionResolutionTimer; + /// number of active DL LCs + uint8_t dl_lc_num; + /// order in which DLSCH scheduler should allocate LCs + uint8_t dl_lc_ids[MAX_NUM_LCID]; + /// number of bytes to schedule for each LC + uint32_t dl_lc_bytes[MAX_NUM_LCID]; uint16_t max_rbs_allowed_slice_uplink[NFAPI_CC_MAX][MAX_NUM_SLICES]; - uint8_t max_mcs[MAX_NUM_LCID]; - - uint16_t priority[MAX_NUM_LCID]; - // resource scheduling information /// Current DL harq round per harq_pid on each CC From 97a1bd105c6e5dbf516f7df28f222f53b12ed541 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 29 Jan 2020 17:42:25 +0100 Subject: [PATCH 118/240] store_dlsch_buffer() works per CC, checks only active LCs store_dlsch_buffer() puts the RLC buffer status results in the UE_TEMPLATE, which is per-CC. Since the DLSCH scheduler works per-CC, too, we pass the right CC. However, this is not strictly necessary, as we could do this once before every CC, and it might be updated. --- openair2/LAYER2/MAC/eNB_scheduler_fairRR.c | 4 +-- openair2/LAYER2/MAC/mac_proto.h | 2 +- openair2/LAYER2/MAC/pre_processor.c | 31 ++++++++++++---------- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c index 1cc54454fa..143bfcd37a 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c @@ -947,8 +947,8 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id, } #if (!defined(PRE_SCD_THREAD)) - // Store the DLSCH buffer for each logical channel - store_dlsch_buffer(Mod_id, frameP, subframeP); + // Store the DLSCH buffer for each logical channel and for PCCID (assume 0) + store_dlsch_buffer(Mod_id, 0, frameP, subframeP); // Calculate the number of RBs required by each UE on the basis of logical channel's buffer assign_rbs_required_fairRR(Mod_id, frameP, subframeP, nb_rbs_required); #else diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index c5eb16c5b3..a79c4a1f2a 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -682,7 +682,7 @@ int mac_init(void); int add_new_ue(module_id_t Mod_id, int CC_id, rnti_t rnti, int harq_pid, uint8_t rach_resource_type); int rrc_mac_remove_ue(module_id_t Mod_id, rnti_t rntiP); -void store_dlsch_buffer(module_id_t Mod_id, frame_t frameP, sub_frame_t subframeP); +void store_dlsch_buffer(module_id_t Mod_id, int CC_id, frame_t frameP, sub_frame_t subframeP); void assign_rbs_required(module_id_t Mod_id, int CC_id, uint16_t nb_rbs_required[MAX_MOBILES_PER_ENB]); int prev(UE_list_t *listP, int nodeP); diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 0f1e307222..2ce5fcc2e3 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -63,24 +63,23 @@ sort_ue_ul(module_id_t module_idP, // This function stores the downlink buffer for all the logical channels void store_dlsch_buffer(module_id_t Mod_id, + int CC_id, frame_t frameP, sub_frame_t subframeP) { UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; - for (int UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) { - if (UE_info->active[UE_id] != TRUE) - continue; + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { - /* TODO why UE_template per CC? */ - UE_TEMPLATE *UE_template = &UE_info->UE_template[UE_PCCID(Mod_id, UE_id)][UE_id]; + UE_TEMPLATE *UE_template = &UE_info->UE_template[CC_id][UE_id]; + UE_sched_ctrl_t *UE_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; UE_template->dl_buffer_total = 0; UE_template->dl_pdus_total = 0; - const rnti_t rnti = UE_RNTI(Mod_id, UE_id); - - for (int lcid = 0; lcid < MAX_NUM_LCID; ++lcid) { // loop over all the logical channels + /* loop over all activated logical channels */ + for (int i = 0; i < UE_sched_ctrl->dl_lc_num; ++i) { + const int lcid = UE_sched_ctrl->dl_lc_ids[i]; const mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(Mod_id, - rnti, + UE_template->rnti, Mod_id, frameP, subframeP, @@ -91,16 +90,21 @@ store_dlsch_buffer(module_id_t Mod_id, 0, 0 ); - UE_template->dl_buffer_info[lcid] = rlc_status.bytes_in_buffer; //storing the dlsch buffer for each logical channel + UE_template->dl_buffer_info[lcid] = rlc_status.bytes_in_buffer; UE_template->dl_pdus_in_buffer[lcid] = rlc_status.pdus_in_buffer; UE_template->dl_buffer_head_sdu_creation_time[lcid] = rlc_status.head_sdu_creation_time; UE_template->dl_buffer_head_sdu_creation_time_max = cmax(UE_template->dl_buffer_head_sdu_creation_time_max, rlc_status.head_sdu_creation_time); UE_template->dl_buffer_head_sdu_remaining_size_to_send[lcid] = rlc_status.head_sdu_remaining_size_to_send; UE_template->dl_buffer_head_sdu_is_segmented[lcid] = rlc_status.head_sdu_is_segmented; - UE_template->dl_buffer_total += UE_template->dl_buffer_info[lcid]; //storing the total dlsch buffer + UE_template->dl_buffer_total += UE_template->dl_buffer_info[lcid]; UE_template->dl_pdus_total += UE_template->dl_pdus_in_buffer[lcid]; + /* update the number of bytes in the UE_sched_ctrl. The DLSCH will use + * this to request the corresponding data from the RLC, and this might be + * limited in the preprocessor */ + UE_sched_ctrl->dl_lc_bytes[i] = rlc_status.bytes_in_buffer; + #ifdef DEBUG_eNB_SCHEDULER /* note for dl_buffer_head_sdu_remaining_size_to_send[lcid] : * 0 if head SDU has not been segmented (yet), else remaining size not already segmented and sent @@ -285,9 +289,8 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, CC_id, rballoc_sub); - store_dlsch_buffer(Mod_id, - frameP, - subframeP); + /* update all buffers. TODO move before CC scheduling */ + store_dlsch_buffer(Mod_id, CC_id, frameP, subframeP); // Calculate the number of RBs required by each UE on the basis of logical channel's buffer uint16_t nb_rbs_required[MAX_MOBILES_PER_ENB]; From 5c153ca0d269ac4dc62de83dcb15432c098af41a Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 29 Jan 2020 18:17:05 +0100 Subject: [PATCH 119/240] Move release and RA control to own function, call once for every UE --- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 142 +++++++++++----------- 1 file changed, 71 insertions(+), 71 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index e81754de19..289a48a80e 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -417,12 +417,80 @@ set_ul_DAI(int module_idP, return; } +void ue_rrc_release(rnti_t rnti) { + if(rrc_release_info.num_UEs == 0 || rlc_am_mui.rrc_mui_num == 0) { + return; + } + + while(pthread_mutex_trylock(&rrc_release_freelist)) { + /* spin... */ + } + + uint16_t release_total = 0; + + for (uint16_t n = 0; n < NUMBER_OF_UE_MAX; n++) { + RRC_release_ctrl_t *release_ctrl = &rrc_release_info.RRC_release_ctrl[n]; + if(release_ctrl->flag == 0) + continue; + + release_total++; + if(release_ctrl->flag == 1 && release_ctrl->rnti == rnti) { + for(uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) { + if(release_ctrl->rrc_eNB_mui == rlc_am_mui.rrc_mui[mui_num]) { + release_ctrl->flag = 3; + LOG_D(MAC, + "DLSCH Release send:index %d rnti %x mui %d mui_num %d flag 1->3\n", + n, rnti, rlc_am_mui.rrc_mui[mui_num], mui_num); + break; + } + } + } + + if(release_ctrl->flag == 2 && release_ctrl->rnti == rnti) { + for (uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) { + if(release_ctrl->rrc_eNB_mui == rlc_am_mui.rrc_mui[mui_num]) { + release_ctrl->flag = 4; + LOG_D(MAC, "DLSCH Release send:index %d rnti %x mui %d mui_num %d flag 2->4\n", + n, + rnti, + rlc_am_mui.rrc_mui[mui_num], + mui_num); + break; + } + } + } + + if(release_total >= rrc_release_info.num_UEs) + break; + } + + pthread_mutex_unlock(&rrc_release_freelist); +} + +void check_ra_rnti_mui(module_id_t mod_id, int CC_id, frame_t f, sub_frame_t sf, rnti_t rnti) { + LTE_TDD_Config_t *tdd_config = RC.mac[mod_id]->common_channels[CC_id].tdd_Config; + int harq_pid = frame_subframe2_dl_harq_pid(tdd_config, f, sf); + RA_t *ra = &RC.mac[mod_id]->common_channels[CC_id].ra[0]; + for (uint8_t ra_ii = 0; ra_ii < NB_RA_PROC_MAX; ra_ii++, ra++) { + if ((ra->rnti == rnti) && (ra->state == MSGCRNTI)) { + for (uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) { + if (ra->crnti_rrc_mui == rlc_am_mui.rrc_mui[mui_num]) { + ra->crnti_harq_pid = harq_pid; + ra->state = MSGCRNTI_ACK; + break; + } + } + } + } +} + //------------------------------------------------------------------------------ void schedule_dlsch(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP, int *mbsfn_flag) { for (int CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; CC_id++) { if (mbsfn_flag[CC_id] == 0) schedule_ue_spec(module_idP, CC_id, frameP, subframeP); + } } @@ -464,13 +532,9 @@ schedule_ue_spec(module_id_t module_idP, unsigned char dlsch_buffer[MAX_DLSCH_PAYLOAD_BYTES]; int round_DL = 0; int harq_pid = 0; - uint16_t release_num; - uint8_t ra_ii; eNB_UE_STATS *eNB_UE_stats = NULL; UE_TEMPLATE *ue_template = NULL; - RRC_release_ctrl_t *release_ctrl = NULL; DLSCH_PDU *dlsch_pdu = NULL; - RA_t *ra = NULL; int sdu_length_total = 0; eNB_MAC_INST *eNB = RC.mac[module_idP]; COMMON_channels_t *cc = eNB->common_channels; @@ -590,6 +654,9 @@ schedule_ue_spec(module_id_t module_idP, ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; ue_template = &UE_info->UE_template[CC_id][UE_id]; + ue_rrc_release(rnti); + check_ra_rnti_mui(module_idP, CC_id, frameP, subframeP, rnti); + if (ue_template->rach_resource_type > 0) { continue_flag = 1; } @@ -969,73 +1036,6 @@ schedule_ue_spec(module_id_t module_idP, 0 ); - if((rrc_release_info.num_UEs > 0) && (rlc_am_mui.rrc_mui_num > 0)) { - while(pthread_mutex_trylock(&rrc_release_freelist)) { - /* spin... */ - } - - uint16_t release_total = 0; - - for (release_num = 0, release_ctrl = &rrc_release_info.RRC_release_ctrl[0]; - release_num < NUMBER_OF_UE_MAX; - release_num++, release_ctrl++) { - if(release_ctrl->flag > 0) { - release_total++; - } else { - continue; - } - - if(release_ctrl->flag == 1) { - if(release_ctrl->rnti == rnti) { - for(uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) { - if(release_ctrl->rrc_eNB_mui == rlc_am_mui.rrc_mui[mui_num]) { - release_ctrl->flag = 3; - LOG_D(MAC,"DLSCH Release send:index %d rnti %x mui %d mui_num %d flag 1->3\n", - release_num, - rnti, - rlc_am_mui.rrc_mui[mui_num], - mui_num); - break; - } - } - } - } - - if(release_ctrl->flag == 2) { - if(release_ctrl->rnti == rnti) { - for (uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) { - if(release_ctrl->rrc_eNB_mui == rlc_am_mui.rrc_mui[mui_num]) { - release_ctrl->flag = 4; - LOG_D(MAC, "DLSCH Release send:index %d rnti %x mui %d mui_num %d flag 2->4\n", - release_num, - rnti, - rlc_am_mui.rrc_mui[mui_num], - mui_num); - break; - } - } - } - } - - if(release_total >= rrc_release_info.num_UEs) - break; - } - - pthread_mutex_unlock(&rrc_release_freelist); - } - - for (ra_ii = 0, ra = &eNB->common_channels[CC_id].ra[0]; ra_ii < NB_RA_PROC_MAX; ra_ii++, ra++) { - if ((ra->rnti == rnti) && (ra->state == MSGCRNTI)) { - for (uint16_t mui_num = 0; mui_num < rlc_am_mui.rrc_mui_num; mui_num++) { - if (ra->crnti_rrc_mui == rlc_am_mui.rrc_mui[mui_num]) { - ra->crnti_harq_pid = harq_pid; - ra->state = MSGCRNTI_ACK; - break; - } - } - } - } - T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), T_INT(CC_id), From eeaa5a99d08646a1ea3d7d5fae705827ef101be1 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 30 Jan 2020 12:35:17 +0100 Subject: [PATCH 120/240] RLC: _req() accepts max TB size, _ind() not Previously, the various rlc_*_ind() functions had a parameter to enable the MAC to specify the max TB size that a subsequent call to the corresponding rlc_*_req() (!) function would return. This patch removes this parameter from the rlc_*_ind() functions and makes the parameter working that is already in the rlc_*_req() functions. --- openair2/ENB_APP/flexran_agent_ran_api.c | 6 ++--- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 20 ++++++-------- openair2/LAYER2/MAC/eNB_scheduler_fairRR.c | 16 +++++++----- openair2/LAYER2/MAC/eNB_scheduler_mch.c | 14 +++++----- openair2/LAYER2/MAC/pre_processor.c | 1 - openair2/LAYER2/MAC/ra_procedures.c | 4 +-- openair2/LAYER2/MAC/ue_procedures.c | 3 +-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 3 +-- openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c | 26 +++---------------- openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.h | 12 ++------- openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.c | 3 --- openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.h | 4 +-- openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c | 15 ++--------- openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.h | 16 ++---------- openair2/LAYER2/RLC/rlc.h | 7 +++-- openair2/LAYER2/RLC/rlc_mac.c | 14 +++++----- openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c | 2 -- 17 files changed, 50 insertions(+), 116 deletions(-) diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index c2bf90ebd8..4a29a4ba5a 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -180,7 +180,7 @@ rlc_buffer_occupancy_t flexran_get_tx_queue_size(mid_t mod_id, mid_t ue_id, logi rnti_t rnti = flexran_get_mac_ue_crnti(mod_id, ue_id); frame_t frame = flexran_get_current_frame(mod_id); sub_frame_t subframe = flexran_get_current_subframe(mod_id); - mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id,rnti, mod_id, frame, subframe, ENB_FLAG_YES,MBMS_FLAG_NO, channel_id, 0,0, 0 + mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id,rnti, mod_id, frame, subframe, ENB_FLAG_YES,MBMS_FLAG_NO, channel_id, 0, 0 ); return rlc_status.bytes_in_buffer; } @@ -191,7 +191,7 @@ rlc_buffer_occupancy_t flexran_get_num_pdus_buffer(mid_t mod_id, mid_t ue_id, lo rnti_t rnti = flexran_get_mac_ue_crnti(mod_id,ue_id); frame_t frame = flexran_get_current_frame(mod_id); sub_frame_t subframe = flexran_get_current_subframe(mod_id); - mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id,rnti, mod_id, frame, subframe, ENB_FLAG_YES,MBMS_FLAG_NO, channel_id, 0,0, 0 + mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id,rnti, mod_id, frame, subframe, ENB_FLAG_YES,MBMS_FLAG_NO, channel_id, 0, 0 ); return rlc_status.pdus_in_buffer; } @@ -202,7 +202,7 @@ frame_t flexran_get_hol_delay(mid_t mod_id, mid_t ue_id, logical_chan_id_t chann rnti_t rnti = flexran_get_mac_ue_crnti(mod_id,ue_id); frame_t frame = flexran_get_current_frame(mod_id); sub_frame_t subframe = flexran_get_current_subframe(mod_id); - mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id, rnti, mod_id, frame, subframe, ENB_FLAG_YES, MBMS_FLAG_NO, channel_id, 0,0, 0 + mac_rlc_status_resp_t rlc_status = mac_rlc_status_ind(mod_id, rnti, mod_id, frame, subframe, ENB_FLAG_YES, MBMS_FLAG_NO, channel_id, 0, 0 ); return rlc_status.head_sdu_creation_time; } diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 289a48a80e..3a8ac5dad7 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -1010,7 +1010,6 @@ schedule_ue_spec(module_id_t module_idP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH, - TBS - ta_len - header_length_total - sdu_length_total - 3, 0, 0 ); @@ -1030,7 +1029,7 @@ schedule_ue_spec(module_id_t module_idP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH, - TBS, //not used + TBS - ta_len - header_length_total - sdu_length_total - 3, (char *)&dlsch_buffer[0], 0, 0 @@ -1084,7 +1083,6 @@ schedule_ue_spec(module_id_t module_idP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH + 1, - TBS - ta_len - header_length_total - sdu_length_total - 3, 0, 0 ); @@ -1101,7 +1099,7 @@ schedule_ue_spec(module_id_t module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH + 1, - TBS, //not used + TBS - ta_len - header_length_total - sdu_length_total - 3, (char *) &dlsch_buffer[sdu_length_total], 0, 0 @@ -1159,7 +1157,8 @@ schedule_ue_spec(module_id_t module_idP, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, - TBS - ta_len - header_length_total - sdu_length_total - 3, 0, 0 + 0, + 0 ); if (rlc_status.bytes_in_buffer > 0) { @@ -1176,7 +1175,7 @@ schedule_ue_spec(module_id_t module_idP, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, - TBS, //not used + TBS - ta_len - header_length_total - sdu_length_total - 3, (char *) &dlsch_buffer[sdu_length_total], 0, 0 @@ -1799,7 +1798,6 @@ schedule_ue_spec_br(module_id_t module_idP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH, - (TBS-ta_len-header_len_dcch), 0, 0); // transport block set size sdu_lengths[0] = 0; @@ -1817,7 +1815,7 @@ schedule_ue_spec_br(module_id_t module_idP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH, - TBS, //not used + TBS-ta_len-header_len_dcch, (char *)&dlsch_buffer[0], 0, 0); @@ -1855,7 +1853,6 @@ schedule_ue_spec_br(module_id_t module_idP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH + 1, - (TBS-ta_len-header_len_dcch-sdu_length_total), 0, 0); // transport block set size less allocations for timing advance and DCCH SDU sdu_lengths[num_sdus] = 0; @@ -1873,7 +1870,7 @@ schedule_ue_spec_br(module_id_t module_idP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH+1, - TBS, //not used + TBS-ta_len-header_len_dcch-sdu_length_total, (char *)&dlsch_buffer[sdu_length_total], 0, 0); @@ -1920,7 +1917,6 @@ schedule_ue_spec_br(module_id_t module_idP, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, - TBS - ta_len - header_len_dcch - sdu_length_total - header_len_dtch, 0, 0); @@ -1951,7 +1947,7 @@ schedule_ue_spec_br(module_id_t module_idP, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, - TBS, //not used + TBS - ta_len - header_len_dcch - sdu_length_total - header_len_dtch, (char *) &dlsch_buffer[sdu_length_total], 0, 0); diff --git a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c index 143bfcd37a..96eededc1a 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c @@ -134,7 +134,7 @@ void pre_scd_nb_rbs_required( module_id_t module_idP, for (lc_id = DCCH; lc_id <= DTCH; lc_id++) { rlc_status = mac_rlc_status_ind(module_idP, rnti, module_idP, frameP, subframeP, - ENB_FLAG_YES, MBMS_FLAG_NO, lc_id, 0,0, 0 + ENB_FLAG_YES, MBMS_FLAG_NO, lc_id, 0, 0 ); UE_template.dl_buffer_total += rlc_status.bytes_in_buffer; //storing the total dlsch buffer } @@ -1572,7 +1572,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, header_len_dcch = 2; // 2 bytes DCCH SDU subheader if (TBS - ta_len - header_len_dcch > 0) { - rlc_status = mac_rlc_status_ind(module_idP, rnti, module_idP, frameP, subframeP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH, (TBS - ta_len - header_len_dcch),0, 0); // transport block set size + rlc_status = mac_rlc_status_ind(module_idP, rnti, module_idP, frameP, subframeP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH, 0, 0); // transport block set size sdu_lengths[0] = 0; if (rlc_status.bytes_in_buffer > 0) { // There is DCCH to transmit @@ -1580,7 +1580,8 @@ schedule_ue_spec_fairRR(module_id_t module_idP, "[eNB %d] SFN/SF %d.%d, DL-DCCH->DLSCH CC_id %d, Requesting %d bytes from RLC (RRC message)\n", module_idP, frameP, subframeP, CC_id, TBS - header_len_dcch); - sdu_lengths[0] = mac_rlc_data_req(module_idP, rnti, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH, TBS, //not used + sdu_lengths[0] = mac_rlc_data_req(module_idP, rnti, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH, + TBS - ta_len - header_len_dcch, (char *) &dlsch_buffer[0],0, 0 ); @@ -1674,7 +1675,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, // check for DCCH1 and update header information (assume 2 byte sub-header) if (TBS - ta_len - header_len_dcch - sdu_length_total > 0) { - rlc_status = mac_rlc_status_ind(module_idP, rnti, module_idP, frameP, subframeP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH + 1, (TBS - ta_len - header_len_dcch - sdu_length_total),0, 0 + rlc_status = mac_rlc_status_ind(module_idP, rnti, module_idP, frameP, subframeP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH + 1, 0, 0 ); // transport block set size less allocations for timing advance and // DCCH SDU sdu_lengths[num_sdus] = 0; @@ -1684,7 +1685,8 @@ schedule_ue_spec_fairRR(module_id_t module_idP, "[eNB %d], Frame %d, DCCH1->DLSCH, CC_id %d, Requesting %d bytes from RLC (RRC message)\n", module_idP, frameP, CC_id, TBS - header_len_dcch - sdu_length_total); - sdu_lengths[num_sdus] += mac_rlc_data_req(module_idP, rnti, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH + 1, TBS, //not used + sdu_lengths[num_sdus] += mac_rlc_data_req(module_idP, rnti, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_NO, DCCH + 1, + TBS - ta_len - header_len_dcch - sdu_length_total, (char *) &dlsch_buffer[sdu_length_total],0, 0 ); T(T_ENB_MAC_UE_DL_SDU, T_INT(module_idP), @@ -1737,7 +1739,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, - TBS - ta_len - header_len_dcch - sdu_length_total - header_len_dtch, 0, 0 + 0, 0 ); if (rlc_status.bytes_in_buffer > 0) { @@ -1754,7 +1756,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, - TBS, //not used + TBS - ta_len - header_len_dcch - sdu_length_total - header_len_dtch, (char *)&dlsch_buffer[sdu_length_total], 0, 0 ); T(T_ENB_MAC_UE_DL_SDU, diff --git a/openair2/LAYER2/MAC/eNB_scheduler_mch.c b/openair2/LAYER2/MAC/eNB_scheduler_mch.c index 2953c8e70b..12cdb29f4c 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_mch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_mch.c @@ -718,9 +718,7 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP, module_idP, ENB_FLAG_YES, MBMS_FLAG_YES, cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9, //MTCH, - TBS - header_len_mcch - header_len_msi - - sdu_length_total - header_len_mtch - ,0, 0 + 0, 0 ); bytes_in_buffer = rlc_status.bytes_in_buffer; @@ -773,7 +771,8 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP, TBS - header_len_mcch - header_len_msi - sdu_length_total - header_len_mtch, header_len_mtch, rlc_status.bytes_in_buffer); - sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, 0/*0xfffd*/, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_YES,cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9, 0, //not used + sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, 0, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_YES,cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9, + TBS - header_len_mcch - header_len_msi - sdu_length_total - header_len_mtch, (char *) &mch_buffer[sdu_length_total] ,0, @@ -1558,9 +1557,7 @@ schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, module_idP, ENB_FLAG_YES, MBMS_FLAG_YES, cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9, //MTCH, - TBS - header_len_mcch - header_len_msi - - sdu_length_total - header_len_mtch - ,0, 0 + 0, 0 ); bytes_in_buffer = rlc_status.bytes_in_buffer; @@ -1579,7 +1576,8 @@ schedule_MBMS(module_id_t module_idP, uint8_t CC_id, frame_t frameP, TBS - header_len_mcch - header_len_msi - sdu_length_total - header_len_mtch, header_len_mtch, rlc_status.bytes_in_buffer); - sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, 0/*0xfffd*/, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_YES,cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9, 0, //not used + sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, 0, module_idP, frameP, ENB_FLAG_YES, MBMS_FLAG_YES,cc->mbms_SessionList[0]->list.array[0]->logicalChannelIdentity_r9, + TBS - header_len_mcch - header_len_msi - sdu_length_total - header_len_mtch, (char *) &mch_buffer[sdu_length_total] ,0, diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 2ce5fcc2e3..fed69a82b1 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -87,7 +87,6 @@ store_dlsch_buffer(module_id_t Mod_id, MBMS_FLAG_NO, lcid, 0, - 0, 0 ); UE_template->dl_buffer_info[lcid] = rlc_status.bytes_in_buffer; diff --git a/openair2/LAYER2/MAC/ra_procedures.c b/openair2/LAYER2/MAC/ra_procedures.c index 19b1c7708b..0d1afdf2a2 100644 --- a/openair2/LAYER2/MAC/ra_procedures.c +++ b/openair2/LAYER2/MAC/ra_procedures.c @@ -390,7 +390,7 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP, int CC_id, LOG_USEDINLOG_VAR(mac_rlc_status_resp_t,rlc_status)=mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti, eNB_indexP, frameP, subframeP, - ENB_FLAG_NO, MBMS_FLAG_NO, DCCH, 6,0, 0 + ENB_FLAG_NO, MBMS_FLAG_NO, DCCH, 0, 0 ); if (UE_mac_inst[module_idP].crnti_before_ho) @@ -406,7 +406,7 @@ PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP, int CC_id, module_idP, frameP, rlc_status.bytes_in_buffer, dcch_header_len); - sdu_lengths = mac_rlc_data_req(module_idP, UE_mac_inst[module_idP].crnti, eNB_indexP, frameP, ENB_FLAG_NO, MBMS_FLAG_NO, DCCH, 6, //not used + sdu_lengths = mac_rlc_data_req(module_idP, UE_mac_inst[module_idP].crnti, eNB_indexP, frameP, ENB_FLAG_NO, MBMS_FLAG_NO, DCCH, 6, (char *) &ulsch_buff[0],0, 0 ); diff --git a/openair2/LAYER2/MAC/ue_procedures.c b/openair2/LAYER2/MAC/ue_procedures.c index 1205851915..c151c061bd 100644 --- a/openair2/LAYER2/MAC/ue_procedures.c +++ b/openair2/LAYER2/MAC/ue_procedures.c @@ -2809,7 +2809,6 @@ update_bsr(module_id_t module_idP, frame_t frameP, rlc_status = mac_rlc_status_ind(module_idP, UE_mac_inst[module_idP].crnti,eNB_index,frameP,subframeP,ENB_FLAG_NO,MBMS_FLAG_NO, lcid, - 0xFFFF, //TBS is not used in RLC at this step, set a special value for debug 0, 0 ); lcid_bytes_in_buffer[lcid] = rlc_status.bytes_in_buffer; @@ -3176,7 +3175,7 @@ SLSCH_t *ue_get_slsch(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_ for (int j = 0; j < ue->numCommFlows; j++) { if ((ue->sourceL2Id > 0) && (ue->destinationList[j] >0) ) { rlc_status = mac_rlc_status_ind(module_idP, 0x1234,0,frameP,subframeP,ENB_FLAG_NO,MBMS_FLAG_NO, - ue->SL_LCID[i], 0xFFFF, ue->sourceL2Id, ue->destinationList[j]); + ue->SL_LCID[i], ue->sourceL2Id, ue->destinationList[j]); if (rlc_status.bytes_in_buffer > 2) { LOG_I(MAC,"SFN.SF %d.%d: Scheduling for %d bytes in Sidelink buffer\n",frameP,subframeP,rlc_status.bytes_in_buffer); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 1e0fd8d9a2..6aba6e7e63 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -562,7 +562,6 @@ void nr_schedule_uss_dlsch_phytest(module_id_t module_idP, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, - TBS_bytes - ta_len - header_length_total - sdu_length_total - 3, 0, 0); @@ -579,7 +578,7 @@ void nr_schedule_uss_dlsch_phytest(module_id_t module_idP, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, - TBS_bytes, + TBS_bytes - ta_len - header_length_total - sdu_length_total - 3, (char *)&mac_sdus[sdu_length_total], 0, 0); diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c index 865a815359..de947225bb 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c @@ -459,7 +459,6 @@ struct mac_status_resp rlc_am_mac_status_indication ( const protocol_ctxt_t *const ctxt_pP, void *const rlc_pP, - const uint16_t tb_sizeP, struct mac_status_ind tx_statusP, const eNB_flag_t enb_flagP) { struct mac_status_resp status_resp; @@ -491,10 +490,6 @@ rlc_am_mac_status_indication ( rlc->last_absolute_subframe_status_indication = PROTOCOL_CTXT_TIME_MILLI_SECONDS(ctxt_pP); - if (tb_sizeP > 0) { - rlc->nb_bytes_requested_by_mac = tb_sizeP; - } - status_resp.buffer_occupancy_in_bytes = rlc_am_get_buffer_occupancy_in_bytes(ctxt_pP, rlc); // For eNB scheduler : Add Max RLC header size for new PDU @@ -549,8 +544,7 @@ rlc_am_mac_status_indication ( NULL,0, MSC_AS_TIME_FMT" "PROTOCOL_RLC_AM_MSC_FMT" STATUS-IND %u", MSC_AS_TIME_ARGS(ctxt_pP), - PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP, rlc), - tb_sizeP); + PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP, rlc)); MSC_LOG_TX_MESSAGE( (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_ENB:MSC_RLC_UE, (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_MAC_ENB:MSC_MAC_UE, @@ -565,26 +559,14 @@ rlc_am_mac_status_indication ( } if (LOG_DEBUGFLAG(DEBUG_RLC)) { - if (tb_sizeP > 0) { - LOG_UI(RLC, PROTOCOL_RLC_AM_CTXT_FMT" MAC_STATUS_INDICATION (DATA) %d bytes -> %d bytes\n", - PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc), - tb_sizeP, - status_resp.buffer_occupancy_in_bytes); - } + LOG_UI(RLC, PROTOCOL_RLC_AM_CTXT_FMT" MAC_STATUS_INDICATION (DATA) -> %d bytes\n", + PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc), + status_resp.buffer_occupancy_in_bytes); } return status_resp; } -//----------------------------------------------------------------------------- -void -rlc_am_set_nb_bytes_requested_by_mac ( - void *const rlc_pP, - const tb_size_t tb_sizeP -) { - ((rlc_am_entity_t *) rlc_pP)->nb_bytes_requested_by_mac = tb_sizeP; -} - //----------------------------------------------------------------------------- struct mac_data_req rlc_am_mac_data_request ( diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.h b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.h index f2cb456e8c..3127f67eca 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.h +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.h @@ -255,23 +255,15 @@ rlc_am_get_pdus ( */ void rlc_am_rx (const protocol_ctxt_t* const ctxtP,void * const rlc_pP, struct mac_data_ind); -/*! \fn struct mac_status_resp rlc_am_mac_status_indication (const protocol_ctxt_t* const ctxtP,void * const rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP,const eNB_flag_t enb_flagP) +/*! \fn struct mac_status_resp rlc_am_mac_status_indication (const protocol_ctxt_t* const ctxtP,void * const rlc_pP, struct mac_status_ind tx_statusP,const eNB_flag_t enb_flagP) * \brief Request the maximum number of bytes that can be served by RLC instance to MAC and fix the amount of bytes requested by MAC for next RLC transmission. * \param[in] ctxt_pP Running context. * \param[in] rlc_pP RLC AM protocol instance pointer. -* \param[in] tbs_sizeP Number of bytes requested by MAC for next transmission. * \param[in] tx_statusP Transmission status given by MAC on previous MAC transmission of the PDU. * \param[in] enb_flagP eNB or UE flag indication. * \return The maximum number of bytes that can be served by RLC instance to MAC. */ -struct mac_status_resp rlc_am_mac_status_indication (const protocol_ctxt_t* const ctxtP, void * const rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP,const eNB_flag_t enb_flagP); - -/*! \fn void rlc_am_set_nb_bytes_requested_by_mac (void * const rlc_pP,const tb_size_t tb_sizeP) -* \brief Set available TBS for RLC Tx just before am_mac_data_request. Used for UE only. -* \param[in] rlc_pP RLC AM protocol instance pointer. -* \param[in] tb_sizeP Available Tx Transport Block size in bytes. -*/ -void rlc_am_set_nb_bytes_requested_by_mac (void * const rlc_pP,const tb_size_t tb_sizeP); +struct mac_status_resp rlc_am_mac_status_indication (const protocol_ctxt_t* const ctxtP, void * const rlc_pP, struct mac_status_ind tx_statusP,const eNB_flag_t enb_flagP); /*! \fn struct mac_data_req rlc_am_mac_data_request (const protocol_ctxt_t* const ctxtP,void * const rlc_pP,const eNB_flag_t enb_flagP) * \brief Gives PDUs to lower layer MAC. diff --git a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.c b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.c index e481550a46..4e3fffe176 100644 --- a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.c +++ b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.c @@ -151,13 +151,10 @@ struct mac_status_resp rlc_tm_mac_status_indication ( const protocol_ctxt_t* const ctxt_pP, void * const rlc_pP, - const tb_size_t tb_sizeP, struct mac_status_ind tx_statusP) { struct mac_status_resp status_resp; - ((rlc_tm_entity_t *) rlc_pP)->rlc_pdu_size = tb_sizeP; - status_resp.buffer_occupancy_in_bytes = ((rlc_tm_entity_t *) rlc_pP)->buffer_occupancy; status_resp.buffer_occupancy_in_pdus = status_resp.buffer_occupancy_in_bytes / ((rlc_tm_entity_t *) rlc_pP)->rlc_pdu_size; status_resp.rlc_info.rlc_protocol_state = ((rlc_tm_entity_t *) rlc_pP)->protocol_state; diff --git a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.h b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.h index 1ea9988707..d2bab33b1a 100644 --- a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.h +++ b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.h @@ -88,11 +88,10 @@ void rlc_tm_rx ( struct mac_data_ind data_indP); -/*! \fn struct mac_status_resp rlc_tm_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, void * const rlcP, const uint16_t tbs_sizeP, struct mac_status_ind tx_statusP) +/*! \fn struct mac_status_resp rlc_tm_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, void * const rlcP, struct mac_status_ind tx_statusP) * \brief Request the maximum number of bytes that can be served by RLC instance to MAC and fix the amount of bytes requested by MAC for next RLC transmission. * \param[in] ctxtP Running context. * \param[in] rlcP RLC TM protocol instance pointer. -* \param[in] tbs_sizeP Number of bytes requested by MAC for next transmission. * \param[in] tx_statusP Transmission status given by MAC on previous MAC transmission of the PDU. * \return The maximum number of bytes that can be served by RLC instance to MAC. */ @@ -100,7 +99,6 @@ struct mac_status_resp rlc_tm_mac_status_indication ( const protocol_ctxt_t* const ctxt_pP, void * const rlc_pP, - const tb_size_t tb_sizeP, struct mac_status_ind tx_statusP); diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c index c7dc11f51d..654ddb8da7 100644 --- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c +++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c @@ -370,7 +370,7 @@ rlc_um_rx (const protocol_ctxt_t *const ctxt_pP, void *argP, struct mac_data_ind //----------------------------------------------------------------------------- struct mac_status_resp -rlc_um_mac_status_indication (const protocol_ctxt_t *const ctxt_pP, void *rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP,const eNB_flag_t enb_flagP) { +rlc_um_mac_status_indication (const protocol_ctxt_t *const ctxt_pP, void *rlc_pP, struct mac_status_ind tx_statusP,const eNB_flag_t enb_flagP) { struct mac_status_resp status_resp; uint16_t sdu_size = 0; uint16_t sdu_remaining_size = 0; @@ -386,7 +386,6 @@ rlc_um_mac_status_indication (const protocol_ctxt_t *const ctxt_pP, void *rlc_pP if (rlc_pP) { status_resp.rlc_info.rlc_protocol_state = rlc_p->protocol_state; rlc_um_check_timer_dar_time_out(ctxt_pP, rlc_p); - rlc_p->nb_bytes_requested_by_mac = tbs_sizeP; status_resp.buffer_occupancy_in_bytes = rlc_um_get_buffer_occupancy (rlc_p); if ((status_resp.buffer_occupancy_in_bytes > 0) && ((mb_p = list_get_head(&rlc_p->input_sdus)) != NULL)) { @@ -416,9 +415,8 @@ rlc_um_mac_status_indication (const protocol_ctxt_t *const ctxt_pP, void *rlc_pP if (LOG_DEBUGFLAG(DEBUG_RLC)) { if (( rlc_p->rb_id > 0) && (status_resp.buffer_occupancy_in_bytes > 0)) { - LOG_UI(RLC, PROTOCOL_RLC_UM_CTXT_FMT"MAC_STATUS_INDICATION (DATA) %d bytes requested -> %d bytes available\n", + LOG_UI(RLC, PROTOCOL_RLC_UM_CTXT_FMT"MAC_STATUS_INDICATION (DATA) -> %d bytes available\n", PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_p), - tbs_sizeP, status_resp.buffer_occupancy_in_bytes); if ((tx_statusP.tx_status == MAC_TX_STATUS_SUCCESSFUL) && (tx_statusP.no_pdu)) { @@ -441,15 +439,6 @@ rlc_um_mac_status_indication (const protocol_ctxt_t *const ctxt_pP, void *rlc_pP return status_resp; } -//----------------------------------------------------------------------------- -void -rlc_um_set_nb_bytes_requested_by_mac ( - void *rlc_pP, - const tb_size_t tb_sizeP -) { - ((rlc_um_entity_t *) rlc_pP)->nb_bytes_requested_by_mac = tb_sizeP; -} - //----------------------------------------------------------------------------- struct mac_data_req rlc_um_mac_data_request (const protocol_ctxt_t *const ctxt_pP, void *rlc_pP,const eNB_flag_t enb_flagP) { diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.h b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.h index 8000196b32..be06551dde 100644 --- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.h +++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.h @@ -160,27 +160,15 @@ rlc_um_get_pdus (const protocol_ctxt_t* const ctxt_pP, void *argP); */ void rlc_um_rx (const protocol_ctxt_t* const ctxt_pP, void *argP, struct mac_data_ind data_indP); -/*! \fn struct mac_status_resp rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP) +/*! \fn struct mac_status_resp rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, struct mac_status_ind tx_statusP) * \brief Request the maximum number of bytes that can be served by RLC instance to MAC and fix the amount of bytes requested by MAC for next RLC transmission. * \param[in] ctxt_pP Running context. * \param[in] rlc_pP RLC UM protocol instance pointer. -* \param[in] tbs_sizeP Number of bytes requested by MAC for next transmission. * \param[in] tx_statusP Transmission status given by MAC on previous MAC transmission of the PDU. * \return The maximum number of bytes that can be served by RLC instance to MAC. */ struct mac_status_resp -rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP,const eNB_flag_t enb_flagP); - -/*! \fn void rlc_um_set_nb_bytes_requested_by_mac (rlc_um_entity_t * const rlc_pP, const tb_size_t tb_sizeP) -* \brief Set available TBS size for MAC Tx. -* \param[in] rlc_pP RLC UM protocol instance pointer. -* \param[in] tb_sizeP remaining TBS in bytes. -*/ -void -rlc_um_set_nb_bytes_requested_by_mac ( - void * rlc_pP, - const tb_size_t tb_sizeP -); +rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP, struct mac_status_ind tx_statusP,const eNB_flag_t enb_flagP); /*! \fn struct mac_data_req rlc_um_mac_data_request (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP,const eNB_flag_t enb_flagP) * \brief Gives PDUs to lower layer MAC. diff --git a/openair2/LAYER2/RLC/rlc.h b/openair2/LAYER2/RLC/rlc.h index dfdf527123..ca95211922 100644 --- a/openair2/LAYER2/RLC/rlc.h +++ b/openair2/LAYER2/RLC/rlc.h @@ -391,7 +391,7 @@ void rrc_rlc_register_rrc (rrc_data_ind_cb_t rrc_data_indP, rrc_data_conf_cb_t r * \param [in] eNB_flagP Flag to indicate eNB (1) or UE (0) * \param [in] MBMS_flagP Flag to indicate whether this is the MBMS service (1) or not (0) * \param [in] rb_idP Radio bearer identifier. -* \param [in] tb_sizeP Available Tx TBS in bytes. For UE only. +* \param [in] tb_sizeP Requested Tx TBS in bytes. * \param [in,out] bufferP Memory area to fill with the bytes requested by MAC. * \return A status about the processing, OK or error code. */ @@ -416,7 +416,7 @@ tbs_size_t mac_rlc_data_req (const module_id_t, const rnti_t, con void mac_rlc_data_ind (const module_id_t, const rnti_t, const eNB_index_t,const frame_t, const eNB_flag_t, const MBMS_flag_t, logical_chan_id_t, char *, tb_size_t, num_tb_t, crc_t * ); -/*! \fn mac_rlc_status_resp_t mac_rlc_status_ind (const module_id_t mod_idP, const rnti_t rntiP, const frame_t frameP, const sub_frame_t subframeP, const eNB_flag_t eNB_flagP, const MBMS_flag_t MBMS_flagP, logical_chan_id_t rb_idP, tb_size_t tb_sizeP) +/*! \fn mac_rlc_status_resp_t mac_rlc_status_ind (const module_id_t mod_idP, const rnti_t rntiP, const frame_t frameP, const sub_frame_t subframeP, const eNB_flag_t eNB_flagP, const MBMS_flag_t MBMS_flagP, logical_chan_id_t rb_idP) * \brief Interface with MAC layer, request and set the number of bytes scheduled for transmission by the RLC instance corresponding to the radio bearer identifier. * \param[in] mod_idP Virtualized module identifier. * \param[in] rntiP UE identifier. @@ -425,10 +425,9 @@ void mac_rlc_data_ind (const module_id_t, const rnti_t, con * \param[in] eNB_flagP Flag to indicate eNB operation (1 true, 0 false) * \param[in] MBMS_flagP Flag to indicate whether this is the MBMS service (1) or not (0) * \param[in] rb_idP Radio bearer identifier. -* \param[in] tb_sizeP Size of a transport block set in bytes. * \return The maximum number of bytes that the RLC instance can send in the next transmission sequence. */ -mac_rlc_status_resp_t mac_rlc_status_ind (const module_id_t, const rnti_t, const eNB_index_t, const frame_t, const sub_frame_t, const eNB_flag_t, const MBMS_flag_t, logical_chan_id_t, tb_size_t +mac_rlc_status_resp_t mac_rlc_status_ind (const module_id_t, const rnti_t, const eNB_index_t, const frame_t, const sub_frame_t, const eNB_flag_t, const MBMS_flag_t, logical_chan_id_t ,const uint32_t sourceL2Id ,const uint32_t destinationL2Id ); diff --git a/openair2/LAYER2/RLC/rlc_mac.c b/openair2/LAYER2/RLC/rlc_mac.c index 9cf6cb739a..89cbe4c406 100644 --- a/openair2/LAYER2/RLC/rlc_mac.c +++ b/openair2/LAYER2/RLC/rlc_mac.c @@ -191,20 +191,19 @@ tbs_size_t mac_rlc_data_req( case RLC_MODE_AM: rlc_am_mui.rrc_mui_num = 0; - if (!enb_flagP) rlc_am_set_nb_bytes_requested_by_mac(&rlc_union_p->rlc.am,tb_sizeP); - + ((rlc_am_entity_t *) &rlc_union_p->rlc.am)->nb_bytes_requested_by_mac = tb_sizeP; data_request = rlc_am_mac_data_request(&ctxt, &rlc_union_p->rlc.am,enb_flagP); ret_tb_size =mac_rlc_serialize_tb(buffer_pP, data_request.data); break; case RLC_MODE_UM: - if (!enb_flagP) rlc_um_set_nb_bytes_requested_by_mac(&rlc_union_p->rlc.um,tb_sizeP); - + ((rlc_um_entity_t *) &rlc_union_p->rlc.um)->nb_bytes_requested_by_mac = tb_sizeP; data_request = rlc_um_mac_data_request(&ctxt, &rlc_union_p->rlc.um,enb_flagP); ret_tb_size = mac_rlc_serialize_tb(buffer_pP, data_request.data); break; case RLC_MODE_TM: + ((rlc_tm_entity_t *) &rlc_union_p->rlc.tm)->rlc_pdu_size = tb_sizeP; data_request = rlc_tm_mac_data_request(&ctxt, &rlc_union_p->rlc.tm); ret_tb_size = mac_rlc_serialize_tb(buffer_pP, data_request.data); break; @@ -317,7 +316,6 @@ mac_rlc_status_resp_t mac_rlc_status_ind( const eNB_flag_t enb_flagP, const MBMS_flag_t MBMS_flagP, const logical_chan_id_t channel_idP, - const tb_size_t tb_sizeP, const uint32_t sourceL2Id, const uint32_t destinationL2Id ) { @@ -370,7 +368,7 @@ mac_rlc_status_resp_t mac_rlc_status_ind( break; case RLC_MODE_AM: - status_resp = rlc_am_mac_status_indication(&ctxt, &rlc_union_p->rlc.am, tb_sizeP, tx_status,enb_flagP); + status_resp = rlc_am_mac_status_indication(&ctxt, &rlc_union_p->rlc.am, tx_status,enb_flagP); mac_rlc_status_resp.bytes_in_buffer = status_resp.buffer_occupancy_in_bytes; mac_rlc_status_resp.head_sdu_creation_time = status_resp.head_sdu_creation_time; mac_rlc_status_resp.head_sdu_remaining_size_to_send = status_resp.head_sdu_remaining_size_to_send; @@ -379,7 +377,7 @@ mac_rlc_status_resp_t mac_rlc_status_ind( break; case RLC_MODE_UM: - status_resp = rlc_um_mac_status_indication(&ctxt, &rlc_union_p->rlc.um, tb_sizeP, tx_status, enb_flagP); + status_resp = rlc_um_mac_status_indication(&ctxt, &rlc_union_p->rlc.um, tx_status, enb_flagP); mac_rlc_status_resp.bytes_in_buffer = status_resp.buffer_occupancy_in_bytes; mac_rlc_status_resp.pdus_in_buffer = status_resp.buffer_occupancy_in_pdus; mac_rlc_status_resp.head_sdu_creation_time = status_resp.head_sdu_creation_time; @@ -389,7 +387,7 @@ mac_rlc_status_resp_t mac_rlc_status_ind( break; case RLC_MODE_TM: - status_resp = rlc_tm_mac_status_indication(&ctxt, &rlc_union_p->rlc.tm, tb_sizeP, tx_status); + status_resp = rlc_tm_mac_status_indication(&ctxt, &rlc_union_p->rlc.tm, tx_status); mac_rlc_status_resp.bytes_in_buffer = status_resp.buffer_occupancy_in_bytes; mac_rlc_status_resp.pdus_in_buffer = status_resp.buffer_occupancy_in_pdus; // return mac_rlc_status_resp; diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index 88bde65107..20311ef967 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -152,7 +152,6 @@ mac_rlc_status_resp_t mac_rlc_status_ind( const eNB_flag_t enb_flagP, const MBMS_flag_t MBMS_flagP, const logical_chan_id_t channel_idP, - const tb_size_t tb_sizeP, const uint32_t sourceL2Id, const uint32_t destinationL2Id ) @@ -189,7 +188,6 @@ mac_rlc_status_resp_t mac_rlc_status_ind( ret.bytes_in_buffer = buf_stat.status_size + buf_stat.retx_size + buf_stat.tx_size; - ue->saved_status_ind_tb_size[channel_idP - 1] = tb_sizeP; } else { ret.bytes_in_buffer = 0; } From eb0af3a5e0acae7c02154dde8a97f90d33542bcc Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 30 Jan 2020 13:32:41 +0100 Subject: [PATCH 121/240] Simplify DLSCH code * do not check rlc_ind() * Simplify retransmission part and remove nb_rb_available var * Simplify new transmission code * Simplify fill_DLSCH_dci(), avoid unnecessary copies * fix: first check No. RBs, then check CCE alloc --- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 604 +++++------------- .../LAYER2/MAC/eNB_scheduler_primitives.c | 2 +- openair2/LAYER2/MAC/mac_proto.h | 6 +- 3 files changed, 161 insertions(+), 451 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 3a8ac5dad7..a6a723d58a 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -519,43 +519,25 @@ schedule_ue_spec(module_id_t module_idP, sub_frame_t subframeP) //------------------------------------------------------------------------------ { - int UE_id; - int aggregation; - mac_rlc_status_resp_t rlc_status; + int aggregation = 2; int ta_len = 0; unsigned char sdu_lcids[NB_RB_MAX]; - int lcid, offset, num_sdus = 0; - int nb_rb, nb_rb_temp, nb_available_rb; - uint16_t sdu_lengths[NB_RB_MAX]; int TBS, j, padding = 0, post_padding = 0; - rnti_t rnti; unsigned char dlsch_buffer[MAX_DLSCH_PAYLOAD_BYTES]; - int round_DL = 0; - int harq_pid = 0; - eNB_UE_STATS *eNB_UE_stats = NULL; - UE_TEMPLATE *ue_template = NULL; DLSCH_PDU *dlsch_pdu = NULL; - int sdu_length_total = 0; eNB_MAC_INST *eNB = RC.mac[module_idP]; COMMON_channels_t *cc = eNB->common_channels; UE_info_t *UE_info = &eNB->UE_info; int continue_flag = 0; int32_t snr, target_snr; int tpc = 1; - UE_sched_ctrl_t *ue_sched_ctrl; - int mcs; - const int min_rb_unit = get_min_rb_unit(module_idP, CC_id); const int dl_Bandwidth = cc[CC_id].mib->message.dl_Bandwidth; const int N_RB_DL = to_prb(dl_Bandwidth); - const int N_RBG = to_rbg(dl_Bandwidth); int total_nb_available_rb = N_RB_DL; nfapi_dl_config_request_body_t *dl_req; nfapi_dl_config_request_pdu_t *dl_config_pdu; int tdd_sfa; int ta_update; - int header_length_last; - int header_length_total; - rrc_eNB_ue_context_t *ue_contextP = NULL; if(is_pmch_subframe(frameP,subframeP,&RC.eNB[module_idP][0]->frame_parms)){ //LOG_E(MAC,"Frame[%d] SF:%d This SF should not be allocated\n",frameP,subframeP); @@ -615,8 +597,6 @@ schedule_ue_spec(module_id_t module_idP, } } - aggregation = 2; - for (int i = 0; i < N_RB_DL; i++) if (cc[CC_id].vrb_map[i] != 0) total_nb_available_rb--; @@ -645,14 +625,16 @@ schedule_ue_spec(module_id_t module_idP, CC_id); dl_req = &eNB->DL_req[CC_id].dl_config_request_body; - for (UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { LOG_D(MAC, "doing schedule_ue_spec for CC_id %d UE %d\n", CC_id, UE_id); continue_flag = 0; // reset the flag to allow allocation for the remaining UEs - rnti = UE_RNTI(module_idP, UE_id); - ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; - ue_template = &UE_info->UE_template[CC_id][UE_id]; + UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + UE_TEMPLATE *ue_template = &UE_info->UE_template[CC_id][UE_id]; + eNB_UE_STATS *eNB_UE_stats = &UE_info->eNB_UE_stats[CC_id][UE_id]; + const rnti_t rnti = ue_template->rnti; + ue_rrc_release(rnti); check_ra_rnti_mui(module_idP, CC_id, frameP, subframeP, rnti); @@ -661,13 +643,6 @@ schedule_ue_spec(module_id_t module_idP, continue_flag = 1; } - if (&(UE_info->eNB_UE_stats[CC_id][UE_id]) == NULL) { - LOG_D(MAC, "[eNB] Cannot find eNB_UE_stats\n"); - continue_flag = 1; - } else { - eNB_UE_stats = &(UE_info->eNB_UE_stats[CC_id][UE_id]); - } - if (continue_flag != 1) { switch (get_tmode(module_idP, CC_id, @@ -696,18 +671,26 @@ schedule_ue_spec(module_id_t module_idP, } /* if (continue_flag != 1 */ - if (ue_sched_ctrl->pre_nb_available_rbs[CC_id] == 0 || // no RBs allocated - CCE_allocation_infeasible(module_idP, + if (ue_sched_ctrl->pre_nb_available_rbs[CC_id] == 0) { // no RBs allocated + LOG_D(MAC, "%d.%d: no RBs allocated for UE %d on CC_id %d\n", + frameP, + subframeP, + UE_id, + CC_id); + continue_flag = 1; + } + + if (CCE_allocation_infeasible(module_idP, CC_id, 1, subframeP, aggregation, rnti)) { - LOG_D(MAC, "[eNB %d] Frame %d : no RB allocated for UE %d on CC_id %d: continue \n", - module_idP, + LOG_W(MAC, "%d.%d: Dropping Allocation for RNTI 0x%04x/UE %d\n", frameP, - UE_id, - CC_id); + subframeP, + rnti, + UE_id); continue_flag = 1; //to next user (there might be rbs availiable for other UEs in TM5 } @@ -736,11 +719,10 @@ schedule_ue_spec(module_id_t module_idP, continue; } - nb_available_rb = ue_sched_ctrl->pre_nb_available_rbs[CC_id]; - harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, - frameP, - subframeP); - round_DL = ue_sched_ctrl->round[CC_id][harq_pid]; + const int harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, + frameP, + subframeP); + const int round_DL = ue_sched_ctrl->round[CC_id][harq_pid]; eNB_UE_stats->crnti = rnti; eNB_UE_stats->rrc_status = mac_eNB_get_rrc_status(module_idP, rnti); eNB_UE_stats->harq_pid = harq_pid; @@ -755,29 +737,12 @@ schedule_ue_spec(module_id_t module_idP, continue; } - header_length_total = 0; - sdu_length_total = 0; - num_sdus = 0; - - /* - DevCheck(((eNB_UE_stats->dl_cqi < MIN_CQI_VALUE) || - (eNB_UE_stats->dl_cqi > MAX_CQI_VALUE)), - eNB_UE_stats->dl_cqi, MIN_CQI_VALUE, MAX_CQI_VALUE); - */ - if (NFAPI_MODE != NFAPI_MONOLITHIC) { - eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[ue_sched_ctrl->dl_cqi[CC_id]]; - } else { // this operation is also done in the preprocessor - eNB_UE_stats->dlsch_mcs1 = cmin(eNB_UE_stats->dlsch_mcs1, - eNB->slice_info.dl[0/*slice_idxP*/].maxmcs); // cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs); - } - - // Store stats - // eNB_UE_stats->dl_cqi= eNB_UE_stats->dl_cqi; - - // Initializing the rb allocation indicator for each UE - for (j = 0; j < N_RBG; j++) { - ue_template->rballoc_subband[harq_pid][j] = 0; - } + //if (NFAPI_MODE != NFAPI_MONOLITHIC) { + // eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[ue_sched_ctrl->dl_cqi[CC_id]]; + //} else { // this operation is also done in the preprocessor + // eNB_UE_stats->dlsch_mcs1 = cmin(eNB_UE_stats->dlsch_mcs1, + // eNB->slice_info.dl[0/*slice_idxP*/].maxmcs); // cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs); + //} LOG_D(MAC, "[eNB %d] Frame %d: Scheduling UE %d on CC_id %d (rnti %x, harq_pid %d, round %d, rb %d, cqi %d, mcs %d, rrc %d)\n", module_idP, @@ -787,7 +752,7 @@ schedule_ue_spec(module_id_t module_idP, rnti, harq_pid, round_DL, - nb_available_rb, + ue_sched_ctrl->pre_nb_available_rbs[CC_id], ue_sched_ctrl->dl_cqi[CC_id], eNB_UE_stats->dlsch_mcs1, eNB_UE_stats->rrc_status); @@ -795,11 +760,11 @@ schedule_ue_spec(module_id_t module_idP, /* Process retransmission */ if (round_DL != 8) { // get freq_allocation - nb_rb = ue_template->nb_rb[harq_pid]; + const int nb_rb = ue_template->nb_rb[harq_pid]; TBS = get_TBS_DL(ue_template->oldmcs1[harq_pid], nb_rb); - if (nb_rb <= nb_available_rb) { + if (nb_rb <= ue_sched_ctrl->pre_nb_available_rbs[CC_id]) { /* CDRX */ ue_sched_ctrl->harq_rtt_timer[CC_id][harq_pid] = 1; // restart HARQ RTT timer @@ -828,32 +793,6 @@ schedule_ue_spec(module_id_t module_idP, ue_template->DAI); } - if (nb_rb == ue_sched_ctrl->pre_nb_available_rbs[CC_id]) { - for (j = 0; j < N_RBG; j++) { // for indicating the rballoc for each sub-band - ue_template->rballoc_subband[harq_pid][j] = ue_sched_ctrl->rballoc_sub_UE[CC_id][j]; - } - } else { - nb_rb_temp = nb_rb; - j = 0; - - while ((nb_rb_temp > 0) && (j < N_RBG)) { - if (ue_sched_ctrl->rballoc_sub_UE[CC_id][j] == 1) { - if (ue_template->rballoc_subband[harq_pid][j]) - LOG_W(MAC, "WARN: rballoc_subband not free for retrans?\n"); - - ue_template->rballoc_subband[harq_pid][j] = ue_sched_ctrl->rballoc_sub_UE[CC_id][j]; - nb_rb_temp -= min_rb_unit; - - if ((j == N_RBG - 1) && (N_RB_DL == 25 || N_RB_DL == 50)) - nb_rb_temp++; - } - - j++; - } - } - - nb_available_rb -= nb_rb; - switch (get_tmode(module_idP, CC_id, UE_id)) { case 1: case 2: @@ -975,12 +914,10 @@ schedule_ue_spec(module_id_t module_idP, UE_id); } } else { - /* This is a potentially new SDU opportunity */ - rlc_status.bytes_in_buffer = 0; // Now check RLC information to compute number of required RBs // get maximum TBS size for RLC request - TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, - nb_available_rb); + /* TODO this assumes that UE is allocated continuously, can we do better? */ + TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, ue_sched_ctrl->pre_nb_available_rbs[CC_id]); // add the length for all the control elements (timing adv, drx, etc) : header + payload @@ -1000,223 +937,88 @@ schedule_ue_spec(module_id_t module_idP, ta_len = (ta_update != 31) ? 2 : 0; - // RLC data on DCCH - if (TBS - ta_len - header_length_total - sdu_length_total - 3 > 0) { - rlc_status = mac_rlc_status_ind(module_idP, - rnti, - module_idP, - frameP, - subframeP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - DCCH, - 0, - 0 - ); - sdu_lengths[0] = 0; - if (rlc_status.bytes_in_buffer > 0) { - LOG_D(MAC, "[eNB %d] SFN/SF %d.%d, DL-DCCH->DLSCH CC_id %d, Requesting %d bytes from RLC (RRC message)\n", - module_idP, - frameP, - subframeP, - CC_id, - TBS - ta_len - header_length_total - sdu_length_total - 3); - sdu_lengths[0] = mac_rlc_data_req(module_idP, - rnti, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - DCCH, - TBS - ta_len - header_length_total - sdu_length_total - 3, - (char *)&dlsch_buffer[0], - 0, - 0 - ); + int num_sdus = 0; + uint16_t sdu_lengths[NB_RB_MAX]; + int sdu_length_total = 0; + int header_length_total = 0; + int header_length_last = 0; + for (int i = 0; i < ue_sched_ctrl->dl_lc_num; ++i) { + const int lcid = ue_sched_ctrl->dl_lc_ids[i]; // will match DCCH, DCCH1, DTCH - T(T_ENB_MAC_UE_DL_SDU, - T_INT(module_idP), - T_INT(CC_id), - T_INT(rnti), - T_INT(frameP), - T_INT(subframeP), - T_INT(harq_pid), - T_INT(DCCH), - T_INT(sdu_lengths[0])); - LOG_D(MAC, "[eNB %d][DCCH] CC_id %d Got %d bytes from RLC\n", - module_idP, - CC_id, - sdu_lengths[0]); - sdu_length_total = sdu_lengths[0]; - sdu_lcids[0] = DCCH; - eNB_UE_stats->lcid_sdu[0] = DCCH; - eNB_UE_stats->sdu_length_tx[DCCH] = sdu_lengths[0]; - eNB_UE_stats->num_pdu_tx[DCCH] += 1; - eNB_UE_stats->num_bytes_tx[DCCH] += sdu_lengths[0]; - header_length_last = 1 + 1 + (sdu_lengths[0] >= 128); - header_length_total += header_length_last; - num_sdus = 1; -#ifdef DEBUG_eNB_SCHEDULER - LOG_T(MAC, "[eNB %d][DCCH] CC_id %d Got %d bytes :", - module_idP, - CC_id, - sdu_lengths[0]); + if (TBS - ta_len - header_length_total - sdu_length_total - 3 <= 0) + break; - for (j = 0; j < sdu_lengths[0]; ++j) { - LOG_T(MAC, "%x ", - dlsch_buffer[j]); - } + if (ue_sched_ctrl->dl_lc_bytes[i] == 0) // no data in this LC! + continue; - LOG_T(MAC, "\n"); -#endif - } - } - - // RLC data on DCCH1 - if (TBS - ta_len - header_length_total - sdu_length_total - 3 > 0) { - rlc_status = mac_rlc_status_ind(module_idP, - rnti, - module_idP, - frameP, - subframeP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - DCCH + 1, - 0, - 0 - ); - // DCCH SDU - sdu_lengths[num_sdus] = 0; - - if (rlc_status.bytes_in_buffer > 0) { - LOG_D(MAC, "[eNB %d], Frame %d, DCCH1->DLSCH, CC_id %d, Requesting %d bytes from RLC (RRC message)\n", - module_idP, frameP, CC_id, - TBS - ta_len - header_length_total - sdu_length_total - 3); - sdu_lengths[num_sdus] += mac_rlc_data_req(module_idP, - rnti, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, DCCH + 1, - TBS - ta_len - header_length_total - sdu_length_total - 3, - (char *) &dlsch_buffer[sdu_length_total], - 0, - 0 - ); - T(T_ENB_MAC_UE_DL_SDU, - T_INT(module_idP), - T_INT(CC_id), - T_INT(rnti), - T_INT(frameP), - T_INT(subframeP), - T_INT(harq_pid), - T_INT(DCCH + 1), - T_INT(sdu_lengths[num_sdus])); - sdu_lcids[num_sdus] = DCCH1; - sdu_length_total += sdu_lengths[num_sdus]; - eNB_UE_stats->lcid_sdu[num_sdus] = DCCH1; - eNB_UE_stats->sdu_length_tx[DCCH1] = sdu_lengths[num_sdus]; - eNB_UE_stats->num_pdu_tx[DCCH1] += 1; - eNB_UE_stats->num_bytes_tx[DCCH1] += sdu_lengths[num_sdus]; - header_length_last = 1 + 1 + (sdu_lengths[num_sdus] >= 128); - header_length_total += header_length_last; - num_sdus++; -#ifdef DEBUG_eNB_SCHEDULER - LOG_T(MAC, "[eNB %d][DCCH1] CC_id %d Got %d bytes :", - module_idP, - CC_id, - sdu_lengths[num_sdus]); - - for (j = 0; j < sdu_lengths[num_sdus]; ++j) { - LOG_T(MAC, "%x ", - dlsch_buffer[j]); - } - - LOG_T(MAC, "\n"); -#endif - } - } - - // TODO: lcid has to be sorted before the actual allocation (similar struct as ue_list). - for (lcid = NB_RB_MAX - 1; lcid >= DTCH; lcid--) { - // TODO: check if the lcid is active - LOG_D(MAC, "[eNB %d], Frame %d, DTCH%d->DLSCH, Checking RLC status (tbs %d, len %d)\n", + LOG_D(MAC, "[eNB %d] SFN/SF %d.%d, LC%d->DLSCH CC_id %d, Requesting %d bytes from RLC (RRC message)\n", module_idP, frameP, + subframeP, lcid, - TBS, + CC_id, TBS - ta_len - header_length_total - sdu_length_total - 3); - if (TBS - ta_len - header_length_total - sdu_length_total - 3 > 0) { - rlc_status = mac_rlc_status_ind(module_idP, - rnti, - module_idP, - frameP, - subframeP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - lcid, - 0, - 0 - ); + sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, + rnti, + module_idP, + frameP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + lcid, + TBS - ta_len - header_length_total - sdu_length_total - 3, + (char *)&dlsch_buffer[sdu_length_total], + 0, + 0 + ); - if (rlc_status.bytes_in_buffer > 0) { - LOG_D(MAC, "[eNB %d][USER-PLANE DEFAULT DRB] Frame %d : DTCH->DLSCH, Requesting %d bytes from RLC (lcid %d total hdr len %d)\n", - module_idP, - frameP, - TBS - ta_len - header_length_total - sdu_length_total - 3, - lcid, - header_length_total); - sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, - rnti, - module_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - lcid, - TBS - ta_len - header_length_total - sdu_length_total - 3, - (char *) &dlsch_buffer[sdu_length_total], - 0, - 0 - ); - T(T_ENB_MAC_UE_DL_SDU, - T_INT(module_idP), - T_INT(CC_id), - T_INT(rnti), - T_INT(frameP), - T_INT(subframeP), - T_INT(harq_pid), - T_INT(lcid), - T_INT(sdu_lengths[num_sdus])); - LOG_D(MAC, "[eNB %d][USER-PLANE DEFAULT DRB] Got %d bytes for DTCH %d \n", - module_idP, - sdu_lengths[num_sdus], - lcid); - sdu_lcids[num_sdus] = lcid; - sdu_length_total += sdu_lengths[num_sdus]; - eNB_UE_stats->num_pdu_tx[lcid]++; - eNB_UE_stats->lcid_sdu[num_sdus] = lcid; - eNB_UE_stats->sdu_length_tx[lcid] = sdu_lengths[num_sdus]; - eNB_UE_stats->num_bytes_tx[lcid] += sdu_lengths[num_sdus]; - header_length_last = 1 + 1 + (sdu_lengths[num_sdus] >= 128); - header_length_total += header_length_last; - num_sdus++; +#ifdef DEBUG_eNB_SCHEDULER + LOG_T(MAC, "[eNB %d][%d] CC_id %d Got %d bytes :", + module_idP, + lcid, + CC_id, + sdu_lengths[num_sdus]); + for (j = 0; j < sdu_lengths[num_sdus]; ++j) + LOG_T(MAC, "%x ", dlsch_buffer[sdu_length_total+j]); + LOG_T(MAC, "\n"); +#endif + + T(T_ENB_MAC_UE_DL_SDU, + T_INT(module_idP), + T_INT(CC_id), + T_INT(rnti), + T_INT(frameP), + T_INT(subframeP), + T_INT(harq_pid), + T_INT(lcid), + T_INT(sdu_lengths[num_sdus])); + LOG_D(MAC, "[eNB %d][LC %d] CC_id %d Got %d bytes from RLC\n", + module_idP, + lcid, + CC_id, + sdu_lengths[num_sdus]); + sdu_lcids[num_sdus] = lcid; + sdu_length_total += sdu_lengths[num_sdus]; + eNB_UE_stats->num_pdu_tx[lcid] += 1; + eNB_UE_stats->lcid_sdu[num_sdus] = lcid; + eNB_UE_stats->sdu_length_tx[lcid] = sdu_lengths[num_sdus]; + eNB_UE_stats->num_bytes_tx[lcid] += sdu_lengths[num_sdus]; + header_length_last = 1 + 1 + (sdu_lengths[num_sdus] >= 128); + header_length_total += header_length_last; + num_sdus += 1; + + if (lcid >= 3) { // if this is DTCH ue_sched_ctrl->uplane_inactivity_timer = 0; - // reset RRC inactivity timer after uplane activity - ue_contextP = rrc_eNB_get_ue_context(RC.rrc[module_idP], rnti); - if (ue_contextP != NULL) { - ue_contextP->ue_context.ue_rrc_inactivity_timer = 1; - } else { + // reset RRC inactivity timer after uplane activity + rrc_eNB_ue_context_t *ue_contextP = rrc_eNB_get_ue_context(RC.rrc[module_idP], rnti); + if (ue_contextP == NULL) LOG_E(MAC, "[eNB %d] CC_id %d Couldn't find the context associated to UE (RNTI %d) and reset RRC inactivity timer\n", module_idP, CC_id, rnti); - } - } // end if (rlc_status.bytes_in_buffer > 0) - } else { // no TBS left - break; // break for (lcid = NB_RB_MAX - 1; lcid >= DTCH; lcid--) + ue_contextP->ue_context.ue_rrc_inactivity_timer = 1; } } @@ -1227,85 +1029,31 @@ schedule_ue_spec(module_id_t module_idP, } // there is at least one SDU or TA command - // if (num_sdus > 0 ){ if (ta_len + sdu_length_total + header_length_total > 0) { // Now compute number of required RBs for total sdu length // Assume RAH format 2 - mcs = eNB_UE_stats->dlsch_mcs1; - - if (mcs == 0) { - nb_rb = 4; // don't let the TBS get too small - } else { - nb_rb = min_rb_unit; - } - - TBS = get_TBS_DL(mcs, nb_rb); - - while (TBS < sdu_length_total + header_length_total + ta_len) { - nb_rb += min_rb_unit; // - - if (nb_rb > nb_available_rb) { // if we've gone beyond the maximum number of RBs - // (can happen if N_RB_DL is odd) - TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, - nb_available_rb); - nb_rb = nb_available_rb; - break; - } - - TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, - nb_rb); - } - - if (nb_rb == ue_sched_ctrl->pre_nb_available_rbs[CC_id]) { - for (j = 0; j < N_RBG; ++j) { // for indicating the rballoc for each sub-band - ue_template->rballoc_subband[harq_pid][j] = ue_sched_ctrl->rballoc_sub_UE[CC_id][j]; - } - } else { - nb_rb_temp = nb_rb; - j = 0; - - while ((nb_rb_temp > 0) && (j < N_RBG)) { - if (ue_sched_ctrl->rballoc_sub_UE[CC_id][j] == 1) { - ue_template->rballoc_subband[harq_pid][j] = ue_sched_ctrl->rballoc_sub_UE[CC_id][j]; - - if ((j == N_RBG - 1) && ((N_RB_DL == 25) || (N_RB_DL == 50))) { - nb_rb_temp = nb_rb_temp - min_rb_unit + 1; - } else { - nb_rb_temp = nb_rb_temp - min_rb_unit; - } - } - - j++; - } - } + int mcs = eNB_UE_stats->dlsch_mcs1; + const int nb_rb = ue_sched_ctrl->pre_nb_available_rbs[CC_id]; + /* TODO make special function */ // decrease mcs until TBS falls below required length while ((TBS > sdu_length_total + header_length_total + ta_len) && (mcs > 0)) { mcs--; - TBS = get_TBS_DL(mcs, - nb_rb); + TBS = get_TBS_DL(mcs, nb_rb); } // if we have decreased too much or we don't have enough RBs, increase MCS - while (TBS < sdu_length_total + header_length_total + ta_len && - ((ue_sched_ctrl->dl_pow_off[CC_id] > 0 && mcs < 28) || (ue_sched_ctrl->dl_pow_off[CC_id] == 0 && mcs <= 15))) { + while (TBS < sdu_length_total + header_length_total + ta_len && mcs < 28) { + // the second part of this condition is useless since dl_pow_off is + // always 2? + //&& ((ue_sched_ctrl->dl_pow_off[CC_id] > 0 && mcs < 28) || (ue_sched_ctrl->dl_pow_off[CC_id] == 0 && mcs <= 15))) { mcs++; TBS = get_TBS_DL(mcs, nb_rb); } - LOG_D(MAC, "dlsch_mcs before and after the rate matching = (%d, %d)\n", - eNB_UE_stats->dlsch_mcs1, - mcs); -#ifdef DEBUG_eNB_SCHEDULER - LOG_D(MAC, "[eNB %d] CC_id %d Generated DLSCH header (mcs %d, TBS %d, nb_rb %d)\n", - module_idP, - CC_id, - mcs, TBS, - nb_rb); - // msg("[MAC][eNB ] Reminder of DLSCH with random data %d %d %d %d \n", - // TBS, sdu_length_total, offset, TBS-sdu_length_total-offset); -#endif + LOG_D(MAC, "dlsch_mcs before and after the rate matching = (%d, %d), TBS %d, nb_rb %d\n", + eNB_UE_stats->dlsch_mcs1, mcs, TBS, nb_rb); if (TBS - header_length_total - sdu_length_total - ta_len <= 2) { padding = TBS - header_length_total - sdu_length_total - ta_len; @@ -1315,15 +1063,15 @@ schedule_ue_spec(module_id_t module_idP, post_padding = 1; } - offset = generate_dlsch_header((unsigned char *) UE_info->DLSCH_pdu[CC_id][0][UE_id].payload[0], - num_sdus, //num_sdus - sdu_lengths, // - sdu_lcids, - 255, // no drx - ta_update, // timing advance - NULL, // contention res id - padding, - post_padding); + const int offset = generate_dlsch_header((unsigned char *) UE_info->DLSCH_pdu[CC_id][0][UE_id].payload[0], + num_sdus, //num_sdus + sdu_lengths, // + sdu_lcids, + 255, // no drx + ta_update, // timing advance + NULL, // contention res id + padding, + post_padding); //#ifdef DEBUG_eNB_SCHEDULER if (ta_update != 31) { @@ -1360,10 +1108,7 @@ schedule_ue_spec(module_id_t module_idP, #endif // cycle through SDUs and place in dlsch_buffer dlsch_pdu = &UE_info->DLSCH_pdu[CC_id][0][UE_id]; - memcpy(&dlsch_pdu->payload[0][offset], - dlsch_buffer, - sdu_length_total); - // memcpy(RC.mac[0].DLSCH_pdu[0][0].payload[0][offset],dcch_buffer,sdu_lengths[0]); + memcpy(&dlsch_pdu->payload[0][offset], dlsch_buffer, sdu_length_total); // fill remainder of DLSCH with 0 for (j = 0; j < (TBS - sdu_length_total - offset); j++) { @@ -1592,10 +1337,10 @@ schedule_ue_spec(module_id_t module_idP, UE_id, rnti); } - } else { // There is no data from RLC or MAC header, so don't schedule } } + /* TODO this seems to not be necessary, we already do this above */ if (cc[CC_id].tdd_Config != NULL) { // TDD set_ul_DAI(module_idP, UE_id, @@ -1606,6 +1351,7 @@ schedule_ue_spec(module_id_t module_idP, } // UE_id loop fill_DLSCH_dci(module_idP, + CC_id, frameP, subframeP); stop_meas(&eNB->schedule_dlsch); @@ -2297,92 +2043,56 @@ schedule_ue_spec_br(module_id_t module_idP, //------------------------------------------------------------------------------ void fill_DLSCH_dci(module_id_t module_idP, + int CC_id, frame_t frameP, sub_frame_t subframeP) //------------------------------------------------------------------------------ { - // loop over all allocated UEs and compute frequency allocations for PDSCH - int UE_id = -1; - uint8_t /* first_rb, */ nb_rb = 3; - rnti_t rnti; - //unsigned char *vrb_map; - uint8_t rballoc_sub[25]; - //uint8_t number_of_subbands=13; - //unsigned char round; - unsigned char harq_pid; - int i; - int CC_id; eNB_MAC_INST *eNB = RC.mac[module_idP]; - UE_info_t *UE_info = &eNB->UE_info; - int N_RBG; - int N_RB_DL; - COMMON_channels_t *cc; - eNB_DLSCH_INFO *dlsch_info; - UE_TEMPLATE *ue_template; + const UE_info_t *UE_info = &eNB->UE_info; + const int N_RBG = to_rbg(eNB->common_channels[CC_id].mib->message.dl_Bandwidth); + const int N_RB_DL = to_prb(eNB->common_channels[CC_id].mib->message.dl_Bandwidth); + start_meas(&eNB->fill_DLSCH_dci); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_FILL_DLSCH_DCI, - VCD_FUNCTION_IN); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_FILL_DLSCH_DCI, VCD_FUNCTION_IN); - for (CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; CC_id++) { - LOG_D(MAC, "Doing fill DCI for CC_id %d\n", - CC_id); + // UE specific DCIs + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + eNB_DLSCH_INFO *dlsch_info = &eNB_dlsch_info[module_idP][CC_id][UE_id]; + LOG_T(MAC, "CC_id %d, UE_id: %d => status %d\n", CC_id, UE_id, dlsch_info->status); - cc = &eNB->common_channels[CC_id]; - N_RBG = to_rbg(cc->mib->message.dl_Bandwidth); - N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth); + if (dlsch_info->status != S_DL_SCHEDULED) + continue; - // UE specific DCIs - for (UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { - dlsch_info = &eNB_dlsch_info[module_idP][CC_id][UE_id]; - LOG_T(MAC, "CC_id %d, UE_id: %d => status %d\n", - CC_id, - UE_id, - dlsch_info->status); + // clear scheduling flag + dlsch_info->status = S_DL_WAITING; + const rnti_t rnti = UE_info->UE_template[CC_id][UE_id].rnti; + const UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + const int nb_rb = ue_sched_ctrl->pre_nb_available_rbs[CC_id]; - if (dlsch_info->status == S_DL_SCHEDULED) { - // clear scheduling flag - dlsch_info->status = S_DL_WAITING; - rnti = UE_RNTI(module_idP, UE_id); - harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP, - subframeP); - ue_template = &UE_info->UE_template[CC_id][UE_id]; - nb_rb = ue_template->nb_rb[harq_pid]; + nfapi_dl_config_request_body_t *dl_config_request_body = &RC.mac[module_idP]->DL_req[CC_id].dl_config_request_body; + nfapi_dl_config_request_pdu_t *dl_config_pdu; - /// Synchronizing rballoc with rballoc_sub - for (i = 0; i < N_RBG; i++) { - rballoc_sub[i] = ue_template->rballoc_subband[harq_pid][i]; - } + for (int i = 0; i < dl_config_request_body->number_pdu; i++) { + dl_config_pdu = &dl_config_request_body->dl_config_pdu_list[i]; - nfapi_dl_config_request_body_t *dl_config_request_body = &RC.mac[module_idP]->DL_req[CC_id].dl_config_request_body; - nfapi_dl_config_request_pdu_t *dl_config_pdu; - - for (i = 0; i < dl_config_request_body->number_pdu; i++) { - dl_config_pdu = &dl_config_request_body->dl_config_pdu_list[i]; - - if (dl_config_pdu->pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE && - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti == rnti && - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format != 1) { - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = allocate_prbs_sub(nb_rb, - N_RB_DL, - N_RBG, - rballoc_sub); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_allocation_type = 0; - } else if (dl_config_pdu->pdu_type == NFAPI_DL_CONFIG_DLSCH_PDU_TYPE && - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti == rnti && - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type == 0) { - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = allocate_prbs_sub(nb_rb, - N_RB_DL, - N_RBG, - rballoc_sub); - } - } + if (dl_config_pdu->pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE + && dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti == rnti + && dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format != 1) { + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = + allocate_prbs_sub(nb_rb, N_RB_DL, N_RBG, ue_sched_ctrl->rballoc_sub_UE[CC_id]); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_allocation_type = 0; + } else if (dl_config_pdu->pdu_type == NFAPI_DL_CONFIG_DLSCH_PDU_TYPE + && dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti == rnti + && dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type == 0) { + dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = + allocate_prbs_sub(nb_rb, N_RB_DL, N_RBG, ue_sched_ctrl->rballoc_sub_UE[CC_id]); } } } stop_meas(&eNB->fill_DLSCH_dci); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_FILL_DLSCH_DCI, - VCD_FUNCTION_OUT); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_FILL_DLSCH_DCI, VCD_FUNCTION_OUT); } //------------------------------------------------------------------------------ diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index 858be832fc..bb0b0604d3 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -2653,7 +2653,7 @@ uint32_t allocate_prbs_sub(int nb_rb, int N_RB_DL, int N_RBG, - uint8_t *rballoc) + const uint8_t *rballoc) //------------------------------------------------------------------------------ { int check = 0; //check1=0,check2=0; diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index a79c4a1f2a..a785bfb6e9 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -140,10 +140,11 @@ void schedule_ulsch_rnti_emtc(module_id_t module_idP, /** \brief Second stage of DLSCH scheduling, after schedule_SI, schedule_RA and schedule_dlsch have been called. This routine first allocates random frequency assignments for SI and RA SDUs using distributed VRB allocations and adds the corresponding DCI SDU to the DCI buffer for PHY. It then loops over the UE specific DCIs previously allocated and fills in the remaining DCI fields related to frequency allocation. It assumes localized allocation of type 0 (DCI.rah=0). The allocation is done for tranmission modes 1,2,4. @param Mod_id Instance of eNB +@param CC_id the component carrier @param frame Frame index @param subframe Index of subframe */ -void fill_DLSCH_dci(module_id_t module_idP,frame_t frameP,sub_frame_t subframe); +void fill_DLSCH_dci(module_id_t module_idP, int CC_id, frame_t frameP,sub_frame_t subframe); /** \brief UE specific DLSCH scheduling. Retrieves next ue to be schduled from round-robin scheduler and gets the appropriate harq_pid for the subframe from PHY. If the process is active and requires a retransmission, it schedules the retransmission with the same PRB count and MCS as the first transmission. Otherwise it consults RLC for DCCH/DTCH SDUs (status with maximum number of available PRBS), builds the MAC header (timing advance sent by default) and copies @param Mod_id Instance ID of eNB @@ -874,8 +875,7 @@ void add_common_dci(DCI_PDU *DCI_pdu, uint8_t ra_flag); */ -uint32_t allocate_prbs_sub(int nb_rb, int N_RB_DL, int N_RBG, - uint8_t *rballoc); +uint32_t allocate_prbs_sub(int nb_rb, int N_RB_DL, int N_RBG, const uint8_t *rballoc); void update_ul_dci(module_id_t module_idP, uint8_t CC_id, rnti_t rnti, uint8_t dai, sub_frame_t subframe); From 1670b4521e3d77a3f646dead7dd24fcf3f2d8896 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 23 Jan 2020 17:57:54 +0100 Subject: [PATCH 122/240] Reimplement the DLSCH preprocessor This refactors the preprocessor. The new preprocessor implements the same scheduling strategy (Modified Round-Robin: give resources according to round-robin, then group) but should be fairer by changing every time the RR start UE (i.e., 1st TTI UE 0 starts, 2nd TTI UE 1, etc) when the UE number is not a divisor/multiple of the RBG size (and the last RBG is often smaller). This also removes all unneeded code of the preprocessor such as allocate(), positioning(), etc. --- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 3 + openair2/LAYER2/MAC/mac_proto.h | 25 -- openair2/LAYER2/MAC/pre_processor.c | 471 +++++++++++----------- 3 files changed, 234 insertions(+), 265 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index a6a723d58a..9d68d42ed3 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -921,6 +921,9 @@ schedule_ue_spec(module_id_t module_idP, // add the length for all the control elements (timing adv, drx, etc) : header + payload + if (ue_sched_ctrl->ta_timer) + ue_sched_ctrl->ta_timer--; + if (ue_sched_ctrl->ta_timer == 0) { ta_update = ue_sched_ctrl->ta_update; diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index a785bfb6e9..b8834007e0 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -237,30 +237,6 @@ void dlsch_scheduler_pre_processor(module_id_t module_idP, frame_t frameP, sub_frame_t subframe); -void dlsch_scheduler_pre_processor_reset(module_id_t module_idP, - int CC_id, - uint8_t rballoc_sub[N_RBG_MAX]); - -void dlsch_scheduler_pre_processor_accounting(module_id_t Mod_id, - int CC_id, - frame_t frameP, - sub_frame_t subframeP, - uint16_t nb_rbs_required[MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_accounted[MAX_MOBILES_PER_ENB]); - -void dlsch_scheduler_pre_processor_positioning(module_id_t Mod_id, - int CC_id, - uint16_t nb_rbs_required[MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_accounted[MAX_MOBILES_PER_ENB], - uint8_t rballoc_sub[N_RBG_MAX]); - -void dlsch_scheduler_pre_processor_allocate(module_id_t Mod_id, - int UE_id, - uint8_t CC_id, - uint16_t nb_rbs_required, - uint16_t *nb_rbs_remaining, - uint8_t rballoc_sub[N_RBG_MAX]); - /* \brief Function to trigger the eNB scheduling procedure. It is called by PHY at the beginning of each subframe, \f$n$\f and generates all DLSCH allocations for subframe \f$n\f$ and ULSCH allocations for subframe \f$n+k$\f. @param Mod_id Instance ID of eNB @@ -684,7 +660,6 @@ int add_new_ue(module_id_t Mod_id, int CC_id, rnti_t rnti, int harq_pid, uint8_t int rrc_mac_remove_ue(module_id_t Mod_id, rnti_t rntiP); void store_dlsch_buffer(module_id_t Mod_id, int CC_id, frame_t frameP, sub_frame_t subframeP); -void assign_rbs_required(module_id_t Mod_id, int CC_id, uint16_t nb_rbs_required[MAX_MOBILES_PER_ENB]); int prev(UE_list_t *listP, int nodeP); void add_ue_list(UE_list_t *listP, int UE_id); diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index fed69a82b1..6c810fea0d 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -50,9 +50,152 @@ extern RAN_CONTEXT_t RC; -#define DEBUG_eNB_SCHEDULER 1 +#define DEBUG_eNB_SCHEDULER #define DEBUG_HEADER_PARSING 1 +int next_ue_list_looped(UE_list_t* list, int UE_id) { + if (UE_id < 0) + return list->head; + return list->next[UE_id] < 0 ? list->head : list->next[UE_id]; +} + +int g_start_ue_dl = -1; +int round_robin_dl(module_id_t Mod_id, + int CC_id, + int frame, + int subframe, + UE_list_t *UE_list, + int max_num_ue, + int n_rbg_sched, + uint8_t *rbgalloc_mask) { + DevAssert(UE_list->head >= 0); + DevAssert(n_rbg_sched > 0); + const int RBGsize = get_min_rb_unit(Mod_id, CC_id); + int num_ue_req = 0; + UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; + + int rb_required[MAX_MOBILES_PER_ENB]; // how much UEs request + memset(rb_required, 0, sizeof(rb_required)); + + int rbg = 0; + for (; !rbgalloc_mask[rbg]; rbg++) + ; /* fast-forward to first allowed RBG */ + + // Calculate the amount of RBs every UE wants to send. + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + // check whether there are HARQ retransmissions + const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id]; + const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, frame, subframe); + UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + const uint8_t round = ue_ctrl->round[CC_id][harq_pid]; + if (round != 8) { // retransmission: allocate + int nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid]; + if (nb_rb % RBGsize != 0) { + nb_rb += nb_rb % RBGsize; // should now divide evenly + } + int nb_rbg = nb_rb / RBGsize; + if (nb_rbg > n_rbg_sched) // needs more RBGs than we can allocate + continue; + // retransmissions: directly allocate + n_rbg_sched -= nb_rbg; + ue_ctrl->pre_nb_available_rbs[CC_id] += nb_rb; + for (; nb_rbg > 0; rbg++) { + if (!rbgalloc_mask[rbg]) + continue; + ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1; + nb_rbg--; + } + LOG_D(MAC, + "%4d.%d n_rbg_sched %d after retransmission reservation for UE %d " + "round %d retx nb_rb %d pre_nb_available_rbs %d\n", + frame, subframe, n_rbg_sched, UE_id, round, + UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid], + ue_ctrl->pre_nb_available_rbs[CC_id]); + /* if there are no more RBG to give, return */ + if (n_rbg_sched <= 0) + return 0; + max_num_ue--; + /* if there are no UEs that can be allocated anymore, return */ + if (max_num_ue == 0) + return n_rbg_sched; + for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; + } else { + const int dlsch_mcs1 = cqi_to_mcs[UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]]; + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = dlsch_mcs1; + rb_required[UE_id] = + find_nb_rb_DL(dlsch_mcs1, + UE_info->UE_template[CC_id][UE_id].dl_buffer_total, + n_rbg_sched * RBGsize, + RBGsize); + if (rb_required[UE_id] > 0) + num_ue_req++; + LOG_D(MAC, + "%d/%d UE_id %d rb_required %d n_rbg_sched %d\n", + frame, + subframe, + UE_id, + rb_required[UE_id], + n_rbg_sched); + } + } + + if (num_ue_req == 0) + return n_rbg_sched; // no UE has a transmission + + // after allocating retransmissions: build list of UE to allocate. + // if start_UE does not exist anymore (detach etc), start at first UE + if (g_start_ue_dl == -1) + g_start_ue_dl = UE_list->head; + int UE_id = g_start_ue_dl; + UE_list_t UE_sched; + int rb_required_total = 0; + int num_ue_sched = 0; + max_num_ue = min(min(max_num_ue, num_ue_req), n_rbg_sched); + int *cur_UE = &UE_sched.head; + while (num_ue_sched < max_num_ue) { + while (rb_required[UE_id] == 0) + UE_id = next_ue_list_looped(UE_list, UE_id); + /* TODO: check that CCE allocation is feasible. If it is not, reduce + * num_ue_req anyway because this would have been one opportunity */ + *cur_UE = UE_id; + cur_UE = &UE_sched.next[UE_id]; + rb_required_total += rb_required[UE_id]; + num_ue_sched++; + UE_id = next_ue_list_looped(UE_list, UE_id); // next candidate + } + *cur_UE = -1; + + /* for one UE after the next: allocate resources */ + for (int UE_id = UE_sched.head; UE_id >= 0; + UE_id = next_ue_list_looped(&UE_sched, UE_id)) { + if (rb_required[UE_id] <= 0) + continue; + UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1; + ue_ctrl->pre_nb_available_rbs[CC_id] += RBGsize; + rb_required[UE_id] -= RBGsize; + rb_required_total -= RBGsize; + if (rb_required_total <= 0) + break; + n_rbg_sched--; + if (n_rbg_sched <= 0) + break; + for (rbg++; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; + } + + /* if not all UEs could be allocated in this round */ + if (num_ue_req > max_num_ue) { + /* go to the first one we missed */ + for (int i = 0; i < max_num_ue; ++i) + g_start_ue_dl = next_ue_list_looped(UE_list, g_start_ue_dl); + } else { + /* else, just start with the next UE next time */ + g_start_ue_dl = next_ue_list_looped(UE_list, g_start_ue_dl); + } + + return n_rbg_sched; +} + void sort_ue_ul(module_id_t module_idP, int slice_idx, @@ -129,41 +272,6 @@ store_dlsch_buffer(module_id_t Mod_id, } } -// This function returns the estimated number of RBs required to send the full -// buffer -int get_rbs_required(module_id_t Mod_id, - int CC_id, - int UE_id) { - const UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; - - if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total == 0) - return 0; - - const int dlsch_mcs1 = cqi_to_mcs[UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]]; - const int min_rb_unit = get_min_rb_unit(Mod_id, CC_id); - int nb_rbs_required = min_rb_unit; - /* calculating required number of RBs for each UE */ - int TBS = get_TBS_DL(dlsch_mcs1, nb_rbs_required); - while (TBS < UE_info->UE_template[CC_id][UE_id].dl_buffer_total) { - nb_rbs_required += min_rb_unit; - TBS = get_TBS_DL(dlsch_mcs1, nb_rbs_required); - } - return nb_rbs_required; -} - -void -assign_rbs_required(module_id_t Mod_id, - int CC_id, - uint16_t nb_rbs_required[MAX_MOBILES_PER_ENB]) { - UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; - for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { - nb_rbs_required[UE_id] = get_rbs_required(Mod_id, CC_id, UE_id); - // TODO: the following should not be here - UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = cqi_to_mcs[UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]]; - } -} - - int maxround_ul(module_id_t Mod_id, uint16_t rnti, int sched_frame, sub_frame_t sched_subframe) { @@ -190,241 +298,124 @@ maxround_ul(module_id_t Mod_id, uint16_t rnti, int sched_frame, return round_max; } -void dlsch_scheduler_pre_processor_accounting(module_id_t Mod_id, - int CC_id, - frame_t frameP, - sub_frame_t subframeP, - uint16_t nb_rbs_required[MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_accounted[MAX_MOBILES_PER_ENB]) { - uint16_t available_rbs = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); - uint8_t rbs_retx = 0; - uint16_t average_rbs_per_user = 0; - int ue_count_newtx = 0; - int ue_count_retx = 0; - - UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; - - // Find total UE count, and account the RBs required for retransmissions - for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { - const rnti_t rnti = UE_RNTI(Mod_id, UE_id); - if (rnti == NOT_A_RNTI) continue; - if (UE_info->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; - - const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id]; - const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP,subframeP); - const uint8_t round = UE_info->UE_sched_ctrl[UE_id].round[CC_id][harq_pid]; - - // retransmission - if (round != 8) { - nb_rbs_required[UE_id] = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid]; - rbs_retx += nb_rbs_required[UE_id]; - ue_count_retx++; - } else { - ue_count_newtx++; - } - } - - available_rbs = available_rbs - rbs_retx; - const int min_rb_unit = get_min_rb_unit(Mod_id, CC_id); - - if (ue_count_newtx == 0) { - average_rbs_per_user = 0; - } else if (min_rb_unit*ue_count_newtx <= available_rbs) { - average_rbs_per_user = (uint16_t)floor(available_rbs/ue_count_newtx); - } else { - // consider the total number of use that can be scheduled UE - average_rbs_per_user = (uint16_t)min_rb_unit; - } - - for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { - const rnti_t rnti = UE_RNTI(Mod_id, UE_id); - if (rnti == NOT_A_RNTI) continue; - if (UE_info->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; - - const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id]; - const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,frameP,subframeP); - const uint8_t round = UE_info->UE_sched_ctrl[UE_id].round[CC_id][harq_pid]; - - /* TODO the first seems unnecessary, remove it */ - if (mac_eNB_get_rrc_status(Mod_id, rnti) < RRC_RECONFIGURED || round != 8) - nb_rbs_accounted[UE_id] = nb_rbs_required[UE_id]; - else - nb_rbs_accounted[UE_id] = cmin(average_rbs_per_user, nb_rbs_required[UE_id]); - } -} - -void dlsch_scheduler_pre_processor_positioning(module_id_t Mod_id, - int CC_id, - uint16_t nb_rbs_required[MAX_MOBILES_PER_ENB], - uint16_t nb_rbs_accounted[MAX_MOBILES_PER_ENB], - uint8_t rballoc_sub[N_RBG_MAX]) { - UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; - - for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { - if (UE_RNTI(Mod_id, UE_id) == NOT_A_RNTI) continue; - if (UE_info->UE_sched_ctrl[UE_id].ul_out_of_sync == 1) continue; - - dlsch_scheduler_pre_processor_allocate(Mod_id, - UE_id, - CC_id, - nb_rbs_required[UE_id], - &nb_rbs_accounted[UE_id], - rballoc_sub); - - } -} - // This function assigns pre-available RBS to each UE in specified sub-bands before scheduling is done void dlsch_scheduler_pre_processor(module_id_t Mod_id, int CC_id, frame_t frameP, sub_frame_t subframeP) { - uint8_t rballoc_sub[N_RBG_MAX]; - memset(rballoc_sub, 0, sizeof(rballoc_sub)); + UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; + const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); + const int RBGsize = get_min_rb_unit(Mod_id, CC_id); - // Initialize scheduling information for all active UEs - dlsch_scheduler_pre_processor_reset(Mod_id, - CC_id, - rballoc_sub); - - /* update all buffers. TODO move before CC scheduling */ store_dlsch_buffer(Mod_id, CC_id, frameP, subframeP); - // Calculate the number of RBs required by each UE on the basis of logical channel's buffer - uint16_t nb_rbs_required[MAX_MOBILES_PER_ENB]; - memset(nb_rbs_required, 0, sizeof(nb_rbs_required)); - assign_rbs_required(Mod_id, - CC_id, - nb_rbs_required); + UE_list_t UE_to_sched; + UE_to_sched.head = -1; + for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) + UE_to_sched.next[i] = -1; + int first = 1; + int last_UE_id = -1; + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; - // Decide the number of RBs to allocate - uint16_t nb_rbs_accounted[MAX_MOBILES_PER_ENB]; - memset(nb_rbs_accounted, 0, sizeof(nb_rbs_accounted)); - dlsch_scheduler_pre_processor_accounting(Mod_id, - CC_id, - frameP, - subframeP, - nb_rbs_required, - nb_rbs_accounted); + /* initialize per-UE scheduling information */ + ue_sched_ctrl->pre_nb_available_rbs[CC_id] = 0; + ue_sched_ctrl->dl_pow_off[CC_id] = 2; + memset(ue_sched_ctrl->rballoc_sub_UE[CC_id], 0, sizeof(ue_sched_ctrl->rballoc_sub_UE[CC_id])); - // POSITIONING - // This procedure does the main allocation of the RBs - dlsch_scheduler_pre_processor_positioning(Mod_id, - CC_id, - nb_rbs_required, - nb_rbs_accounted, - rballoc_sub); + const rnti_t rnti = UE_RNTI(Mod_id, UE_id); + if (rnti == NOT_A_RNTI) { + LOG_E(MAC, "UE %d has RNTI NOT_A_RNTI!\n", UE_id); + continue; + } + if (UE_info->active[UE_id] != TRUE) { + LOG_E(MAC, "UE %d RNTI %x is NOT active!\n", UE_id, rnti); + continue; + } - const UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; - const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id]; - const int N_RBG = to_rbg(cc->mib->message.dl_Bandwidth); + /* define UEs to schedule */ + if (first) { + first = 0; + UE_to_sched.head = UE_id; + } else { + UE_to_sched.next[last_UE_id] = UE_id; + } + UE_to_sched.next[UE_id] = -1; + last_UE_id = UE_id; + } + + if (UE_to_sched.head < 0) + return; + + uint8_t *vrb_map = RC.mac[Mod_id]->common_channels[CC_id].vrb_map; + uint8_t rbgalloc_mask[N_RBG_MAX]; + int n_rbg_sched = 0; + for (int i = 0; i < N_RBG; i++) { + // calculate mask: init to one + "AND" with vrb_map: + // if any RB in vrb_map is blocked (1), the current RBG will be 0 + rbgalloc_mask[i] = 1; + for (int j = 0; j < RBGsize; j++) + rbgalloc_mask[i] &= !vrb_map[RBGsize * i + j]; + n_rbg_sched += rbgalloc_mask[i]; + } + + round_robin_dl(Mod_id, + CC_id, + frameP, + subframeP, + &UE_to_sched, + 3, // max_num_ue + n_rbg_sched, + rbgalloc_mask); + + // the following block is meant for validation of the pre-processor to check + // whether all UE allocations are non-overlapping and is not necessary for + // scheduling functionality +#ifdef DEBUG_eNB_SCHEDULER + char t[26] = "_________________________"; + t[N_RBG] = 0; + for (int i = 0; i < N_RBG; i++) + for (int j = 0; j < RBGsize; j++) + if (vrb_map[RBGsize*i+j] != 0) + t[i] = 'x'; + int print = 0; for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { const UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; if (ue_sched_ctrl->pre_nb_available_rbs[CC_id] == 0) continue; - char s[101]; - for (int i = 0; i < N_RBG; i++) - sprintf(&s[i*2], " %d", ue_sched_ctrl->rballoc_sub_UE[CC_id][i]); - LOG_D(MAC, - "%d/%d allocation UE %d RNTI %x:%s, total %d, MCS %d\n", + "%4d.%d UE%d %d RBs allocated, pre MCS %d\n", frameP, subframeP, UE_id, - UE_info->UE_template[CC_id][UE_id].rnti, - s, ue_sched_ctrl->pre_nb_available_rbs[CC_id], UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1); - } -} -void -dlsch_scheduler_pre_processor_reset(module_id_t module_idP, - int CC_id, - uint8_t rballoc_sub[N_RBG_MAX]) { - UE_info_t *UE_info = &RC.mac[module_idP]->UE_info; + print = 1; - for (int UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; ++UE_id) { - UE_sched_ctrl_t *ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; - const rnti_t rnti = UE_RNTI(module_idP, UE_id); - - if (rnti == NOT_A_RNTI) - continue; - - if (UE_info->active[UE_id] != TRUE) - continue; - - // initialize harq_pid and round - if (ue_sched_ctl->ta_timer) - ue_sched_ctl->ta_timer--; - - ue_sched_ctl->pre_nb_available_rbs[CC_id] = 0; - ue_sched_ctl->dl_pow_off[CC_id] = 2; - - for (int i = 0; i < sizeof(ue_sched_ctl->rballoc_sub_UE[CC_id])/sizeof(unsigned char); i++) { - ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 0; + for (int i = 0; i < N_RBG; i++) { + if (!ue_sched_ctrl->rballoc_sub_UE[CC_id][i]) + continue; + for (int j = 0; j < RBGsize; j++) { + if (vrb_map[RBGsize*i+j] != 0) { + LOG_I(MAC, "%4d.%d DL scheduler allocation list: %s\n", frameP, subframeP, t); + LOG_E(MAC, "%4d.%d: UE %d allocated at locked RB %d/RBG %d\n", frameP, + subframeP, UE_id, RBGsize * i + j, i); + } + vrb_map[RBGsize*i+j] = 1; + } + t[i] = '0' + UE_id; } } - - const int N_RB_DL = to_prb(RC.mac[module_idP]->common_channels[CC_id].mib->message.dl_Bandwidth); - const int RBGsize = get_min_rb_unit(module_idP, CC_id); - const uint8_t *vrb_map = RC.mac[module_idP]->common_channels[CC_id].vrb_map; - - // Check for SI-RNTI, RA-RNTI or P-RNTI allocations in VRB map and - // initialize subbands accordly - for (int i = 0; i < N_RB_DL; i++) { - if (vrb_map[i] != 0) - rballoc_sub[i/RBGsize] = 1; - } + if (print) + LOG_I(MAC, "%4d.%d DL scheduler allocation list: %s\n", frameP, subframeP, t); +#endif } - -void -dlsch_scheduler_pre_processor_allocate(module_id_t Mod_id, - int UE_id, - uint8_t CC_id, - uint16_t nb_rbs_required, - uint16_t *nb_rbs_remaining, - uint8_t rballoc_sub[N_RBG_MAX]) { - UE_sched_ctrl_t *ue_sched_ctl = &RC.mac[Mod_id]->UE_info.UE_sched_ctrl[UE_id]; - const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); - const int N_RB_DL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); - const int min_rb_unit = get_min_rb_unit(Mod_id, CC_id); - - for (int i = 0; i < N_RBG; i++) { - if (rballoc_sub[i] != 0) continue; - if (ue_sched_ctl->rballoc_sub_UE[CC_id][i] != 0) continue; - if (*nb_rbs_remaining <= 0) continue; - if (ue_sched_ctl->pre_nb_available_rbs[CC_id] >= nb_rbs_required) continue; - if (ue_sched_ctl->dl_pow_off[CC_id] == 0) continue; - - if ((i == N_RBG - 1) && ((N_RB_DL == 25) || (N_RB_DL == 50))) { - // Allocating last, smaller RBG - if (*nb_rbs_remaining >= min_rb_unit - 1) { - rballoc_sub[i] = 1; - ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1; - - *nb_rbs_remaining -= min_rb_unit + 1; - ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit - 1; - } - } else { - // Allocating a standard-sized RBG - if (*nb_rbs_remaining >= min_rb_unit) { - rballoc_sub[i] = 1; - ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1; - - *nb_rbs_remaining -= min_rb_unit; - ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit; - } - } - } -} - - /// ULSCH PRE_PROCESSOR void ulsch_scheduler_pre_processor(module_id_t module_idP, From 4250f8eaec8630ebd924175604743b8575c44e95 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 4 Feb 2020 17:45:18 +0200 Subject: [PATCH 123/240] ULSCH: remove CC loop, remove variables or limit scope --- openair2/LAYER2/MAC/eNB_scheduler_ulsch.c | 1047 ++++++++++----------- openair2/LAYER2/MAC/mac_proto.h | 8 +- openair2/LAYER2/MAC/pre_processor.c | 11 +- 3 files changed, 532 insertions(+), 534 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index d7b12aef22..d34fa28fa5 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -1101,13 +1101,11 @@ schedule_ulsch(module_id_t module_idP, { uint16_t first_rb[NFAPI_CC_MAX]; eNB_MAC_INST *mac = NULL; - slice_info_t *sli = NULL; COMMON_channels_t *cc = NULL; int sched_subframe; int sched_frame; /* Init */ mac = RC.mac[module_idP]; - sli = &(mac->slice_info); memset(first_rb, 0, NFAPI_CC_MAX * sizeof(uint16_t)); start_meas(&(mac->schedule_ulsch)); sched_subframe = (subframeP + 4) % 10; @@ -1263,12 +1261,8 @@ schedule_ulsch(module_id_t module_idP, // break; } } - } - /* Run each enabled slice-specific schedulers one by one */ - for (int i = 0; i < sli->n_ul; i++) { - /* By default the scheduler is schedule_ulsch_rnti (see below) */ - sli->ul[i].sched_cb(module_idP, i, frameP, subframeP, sched_subframe, first_rb); + schedule_ulsch_rnti(module_idP, CC_id, frameP, subframeP, sched_subframe, first_rb); } stop_meas(&mac->schedule_ulsch); @@ -1280,44 +1274,23 @@ schedule_ulsch(module_id_t module_idP, */ void schedule_ulsch_rnti(module_id_t module_idP, - int slice_idx, + int CC_id, frame_t frameP, sub_frame_t subframeP, unsigned char sched_subframeP, - uint16_t *first_rb) -//----------------------------------------------------------------------------- -{ - rnti_t rnti = -1; - uint8_t aggregation = 2; - uint8_t round_index = 0; - uint8_t harq_pid = 0; - uint8_t status = 0; - uint8_t rb_table_index = -1; - uint8_t dlsch_flag = 0; - uint16_t ul_req_index = 0; - uint32_t cqi_req = 0; - uint32_t cshift = 0; - uint32_t ndi = 0; - uint32_t tpc = 0; - int32_t snr = 0; - int32_t target_snr = 0; - int32_t framex10psubframe = 0; + uint16_t *first_rb) { + const uint8_t aggregation = 2; + /* TODO: does this need to be static? */ static int32_t tpc_accumulated = 0; - int sched_frame = 0; - int CC_id = 0; + /* values from 0 to 7 can be used for mapping the cyclic shift + * (36.211 , Table 5.5.2.1.1-1) */ + const uint32_t cshift = 0; eNB_MAC_INST *mac = RC.mac[module_idP]; COMMON_channels_t *cc = mac->common_channels; UE_info_t *UE_info = &mac->UE_info; - slice_info_t *sli = &mac->slice_info; - UE_TEMPLATE *UE_template_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]; - /* Init */ - memset(first_rb_slice, 0, NFAPI_CC_MAX * sizeof(int)); - memset(n_rb_ul_tab, 0, NFAPI_CC_MAX * sizeof(int)); - sched_frame = frameP; + const int rvidx_tab[4] = {0, 2, 3, 1}; + + int sched_frame = frameP; if (sched_subframeP < subframeP) { sched_frame++; @@ -1333,63 +1306,53 @@ schedule_ulsch_rnti(module_id_t module_idP, nfapi_ul_config_ulsch_harq_information *ulsch_harq_information; hi_dci0_req->sfn_sf = (frameP << 4) + subframeP; - /* Note: RC.nb_mac_CC[module_idP] should be lower than or equal to NFAPI_CC_MAX */ - for (CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; CC_id++) { - n_rb_ul_tab[CC_id] = to_prb(cc[CC_id].ul_Bandwidth); // return total number of PRB + int n_rb_ul_tab = to_prb(cc[CC_id].ul_Bandwidth); + /* HACK: let's remove the PUCCH from available RBs + * we suppose PUCCH size is: + * - for 25 RBs: 1 RB (top and bottom of ressource grid) + * - for 50: 2 RBs + * - for 100: 3 RBs + * This is totally arbitrary and might even be wrong. + * We suppose 'first_rb[]' has been correctly populated by the caller, + * so we only remove the top part of the resource grid. + */ + switch (n_rb_ul_tab) { + case 25: + n_rb_ul_tab -= 1; + break; - /* HACK: let's remove the PUCCH from available RBs - * we suppose PUCCH size is: - * - for 25 RBs: 1 RB (top and bottom of ressource grid) - * - for 50: 2 RBs - * - for 100: 3 RBs - * This is totally arbitrary and might even be wrong. - * We suppose 'first_rb[]' has been correctly populated by the caller, - * so we only remove the top part of the resource grid. - */ - switch (n_rb_ul_tab[CC_id]) { - case 25: - n_rb_ul_tab[CC_id] -= 1; - break; + case 50: + n_rb_ul_tab -= 2; + break; - case 50: - n_rb_ul_tab[CC_id] -= 2; - break; + case 100: + n_rb_ul_tab -= 3; + break; - case 100: - n_rb_ul_tab[CC_id] -= 3; - break; - - default: - LOG_E(MAC, "RBs setting not handled. Todo.\n"); - exit(1); - } - - UE_info->first_rb_offset[CC_id][slice_idx] = cmin(n_rb_ul_tab[CC_id], sli->ul[slice_idx].first_rb); + default: + LOG_E(MAC, "RBs setting not handled. Todo.\n"); + exit(1); } + UE_info->first_rb_offset[CC_id][0] = n_rb_ul_tab; + /* * ULSCH preprocessor: set UE_template-> * pre_allocated_nb_rb_ul[slice_idx] * pre_assigned_mcs_ul * pre_allocated_rb_table_index_ul */ - ulsch_scheduler_pre_processor(module_idP, slice_idx, frameP, subframeP, sched_frame, sched_subframeP, first_rb); + ulsch_scheduler_pre_processor(module_idP, CC_id, frameP, subframeP, sched_frame, sched_subframeP, first_rb); - for (CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; CC_id++) { - first_rb_slice[CC_id] = first_rb[CC_id] + UE_info->first_rb_offset[CC_id][slice_idx]; - } - - // loop over all active UEs until end of function for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { - if (!ue_ul_slice_membership(module_idP, UE_id, slice_idx)) { + if (UE_info->UE_template[CC_id][UE_id].rach_resource_type > 0) continue; - } - - if (UE_info->UE_template[UE_PCCID(module_idP, UE_id)][UE_id].rach_resource_type > 0) continue; // don't schedule if Msg5 is not received yet - if (UE_info->UE_template[UE_PCCID(module_idP, UE_id)][UE_id].configured == FALSE) { - LOG_D(MAC, "[eNB %d] frame %d, subframe %d, UE %d: not configured, skipping UE scheduling \n", + if (UE_info->UE_template[CC_id][UE_id].configured == FALSE) { + LOG_D(MAC, + "[eNB %d] frame %d, subframe %d, UE %d: not configured, skipping " + "UE scheduling \n", module_idP, frameP, subframeP, @@ -1397,10 +1360,11 @@ schedule_ulsch_rnti(module_id_t module_idP, continue; } - rnti = UE_RNTI(module_idP, UE_id); + const rnti_t rnti = UE_RNTI(module_idP, UE_id); if (rnti == NOT_A_RNTI) { - LOG_W(MAC, "[eNB %d] frame %d, subframe %d, UE %d: no RNTI \n", + LOG_W(MAC, + "[eNB %d] frame %d, subframe %d, UE %d: no RNTI \n", module_idP, frameP, subframeP, @@ -1408,485 +1372,518 @@ schedule_ulsch_rnti(module_id_t module_idP, continue; } - // loop over all active UL CC_ids for this UE until end of function - for (int n = 0; n < UE_info->numactiveULCCs[UE_id]; n++) { - /* This is the actual CC_id in the list */ - CC_id = UE_info->ordered_ULCCids[n][UE_id]; - UE_template_ptr = &UE_info->UE_template[CC_id][UE_id]; - UE_sched_ctrl_ptr = &UE_info->UE_sched_ctrl[UE_id]; - harq_pid = subframe2harqpid(&cc[CC_id], sched_frame, sched_subframeP); - round_index = UE_sched_ctrl_ptr->round_UL[CC_id][harq_pid]; - AssertFatal(round_index < 8, "round %d > 7 for UE %d/%x\n", - round_index, - UE_id, - rnti); - LOG_D(MAC, "[eNB %d] frame %d subframe %d (sched_frame %d, sched_subframe %d), Checking PUSCH %d for UE %d/%x CC %d : aggregation level %d, N_RB_UL %d\n", - module_idP, - frameP, - subframeP, - sched_frame, - sched_subframeP, - harq_pid, - UE_id, - rnti, - CC_id, - aggregation, - n_rb_ul_tab[CC_id]); - /* Seems unused, only for debug */ - RC.eNB[module_idP][CC_id]->pusch_stats_BO[UE_id][(frameP * 10) + subframeP] = UE_template_ptr->estimated_ul_buffer; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_BO, UE_template_ptr->estimated_ul_buffer); + UE_TEMPLATE *UE_template_ptr = &UE_info->UE_template[CC_id][UE_id]; + UE_sched_ctrl_t *UE_sched_ctrl_ptr = &UE_info->UE_sched_ctrl[UE_id]; + const uint8_t harq_pid = subframe2harqpid(&cc[CC_id], sched_frame, sched_subframeP); + uint8_t round_index = UE_sched_ctrl_ptr->round_UL[CC_id][harq_pid]; + AssertFatal(round_index < 8, + "round %d > 7 for UE %d/%x\n", + round_index, + UE_id, + rnti); + LOG_D(MAC, + "[eNB %d] %d.%d (sched_frame %d, sched_subframe %d), " + "Checking PUSCH %d for UE %d/%x CC %d : aggregation level %d, " + "N_RB_UL %d\n", + module_idP, + frameP, + subframeP, + sched_frame, + sched_subframeP, + harq_pid, + UE_id, + rnti, + CC_id, + aggregation, + n_rb_ul_tab); + /* Seems unused, only for debug */ + RC.eNB[module_idP][CC_id]->pusch_stats_BO[UE_id][(frameP * 10) + subframeP] = + UE_template_ptr->estimated_ul_buffer; + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_BO, + UE_template_ptr->estimated_ul_buffer); - /* - * If there is information on BSR of DCCH, DTCH or if there is UL_SR, - * or if there is a packet to retransmit, or we want to schedule a periodic feedback - */ - if (UE_is_to_be_scheduled(module_idP, CC_id, UE_id) > 0 || round_index > 0) { - LOG_D(MAC, "[eNB %d][PUSCH %d] Frame %d subframe %d Scheduling UE %d/%x in round %d(SR %d,UL_inactivity timer %d,UL_failure timer %d,cqi_req_timer %d)\n", + /* + * If there is information on BSR of DCCH, DTCH or if there is UL_SR, + * or if there is a packet to retransmit, or we want to schedule a periodic + * feedback + * TODO: this should be decided in the preprocessor + */ + if (UE_is_to_be_scheduled(module_idP, CC_id, UE_id) == 0 && round_index == 0) + continue; + + LOG_D(MAC, + "[eNB %d][PUSCH %d] %d.%d Scheduling UE %d/%x in " + "round %d (SR %d, UL_inactivity timer %d, UL_failure timer " + "%d, cqi_req_timer %d)\n", + module_idP, + harq_pid, + frameP, + subframeP, + UE_id, + rnti, + round_index, + UE_template_ptr->ul_SR, + UE_sched_ctrl_ptr->ul_inactivity_timer, + UE_sched_ctrl_ptr->ul_failure_timer, + UE_sched_ctrl_ptr->cqi_req_timer); + + /* Reset the scheduling request */ + UE_template_ptr->ul_SR = 0; + const uint8_t status = mac_eNB_get_rrc_status(module_idP, rnti); + + /* New transmission */ + if (round_index == 0) { + /* Should format_flag be 2 in CCE_allocation_infeasible??? */ + /* This test seems to be way too long, can we provide an optimization? */ + if (CCE_allocation_infeasible(module_idP, CC_id, 1, subframeP, aggregation, rnti)) { + LOG_W(MAC, + "[eNB %d] %d.%d, UE %d/%x CC %d: not enough CCE\n", module_idP, - harq_pid, frameP, subframeP, UE_id, rnti, - round_index, - UE_template_ptr->ul_SR, - UE_sched_ctrl_ptr->ul_inactivity_timer, - UE_sched_ctrl_ptr->ul_failure_timer, - UE_sched_ctrl_ptr->cqi_req_timer); - /* Reset the scheduling request */ - UE_template_ptr->ul_SR = 0; - status = mac_eNB_get_rrc_status(module_idP, rnti); + CC_id); + continue; + } - /* New transmission */ - if (round_index == 0) { - /* Be sure that there are some free RBs */ - if (first_rb_slice[CC_id] >= n_rb_ul_tab[CC_id]) { - LOG_W(MAC, "[eNB %d] frame %d, subframe %d, UE %d/%x CC %d: dropping, not enough RBs\n", - module_idP, - frameP, - subframeP, - UE_id, - rnti, - CC_id); - continue; - } + /* Handle the aperiodic CQI report */ + uint32_t cqi_req = 0; + LOG_D(MAC, + "RRC Connection status %d, cqi_timer %d\n", + status, + UE_sched_ctrl_ptr->cqi_req_timer); - /* Should format_flag be 2 in CCE_allocation_infeasible??? */ - /* This test seems to be way too long, can we provide an optimization? */ - if (CCE_allocation_infeasible(module_idP, CC_id, 1, subframeP, aggregation, rnti)) { - LOG_W(MAC, "[eNB %d] frame %d, subframe %d, UE %d/%x CC %d: not enough CCE\n", - module_idP, - frameP, - subframeP, - UE_id, - rnti, - CC_id); - continue; - } + if (status >= RRC_CONNECTED && UE_sched_ctrl_ptr->cqi_req_timer > 30) { + if (UE_sched_ctrl_ptr->cqi_received == 0) { + cqi_req = 1; + LOG_D(MAC, + "Setting CQI_REQ (timer %d)\n", + UE_sched_ctrl_ptr->cqi_req_timer); - /* Handle the aperiodic CQI report */ - cqi_req = 0; - LOG_D(MAC,"RRC Conenction status %d, cqi_timer %d\n",status,UE_sched_ctrl_ptr->cqi_req_timer); + /* TDD: to be safe, do not ask CQI in special + * Subframes:36.213/7.2.3 CQI definition */ + if (cc[CC_id].tdd_Config) { + switch (cc[CC_id].tdd_Config->subframeAssignment) { + case 1: + if (subframeP == 1 || subframeP == 6) + cqi_req = 0; + break; - if (status >= RRC_CONNECTED && UE_sched_ctrl_ptr->cqi_req_timer > 30) { - if (UE_sched_ctrl_ptr->cqi_received == 0) { - cqi_req = 1; - LOG_D(MAC, - "Setting CQI_REQ (timer %d)\n", - UE_sched_ctrl_ptr->cqi_req_timer); + case 3: + if (subframeP == 1) + cqi_req = 0; + break; - /* TDD: to be safe, do not ask CQI in special - * Subframes:36.213/7.2.3 CQI definition */ - if (cc[CC_id].tdd_Config) { - switch (cc[CC_id].tdd_Config->subframeAssignment) { - case 1: - if (subframeP == 1 || subframeP == 6) - cqi_req = 0; - break; - - case 3: - if (subframeP == 1) - cqi_req = 0; - break; - - default: - LOG_E(MAC, " TDD config not supported\n"); - break; - } - } - - if (cqi_req == 1) { - UE_sched_ctrl_ptr->cqi_req_flag |= 1 << sched_subframeP; - } - } else { - LOG_D(MAC,"Clearing CQI request timer\n"); - UE_sched_ctrl_ptr->cqi_req_flag = 0; - UE_sched_ctrl_ptr->cqi_received = 0; - UE_sched_ctrl_ptr->cqi_req_timer = 0; + default: + LOG_E(MAC, " TDD config not supported\n"); + break; } } - /* Power control */ - /* - * Compute the expected ULSCH RX snr (for the stats) - * This is the normalized RX snr and this should be constant (regardless of mcs) - * Is not in dBm, unit from nfapi, converting to dBm - */ - snr = (5 * UE_sched_ctrl_ptr->pusch_snr[CC_id] - 640) / 10; - target_snr = mac->puSch10xSnr / 10; - /* - * This assumes accumulated tpc - * Make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out - */ - framex10psubframe = (UE_template_ptr->pusch_tpc_tx_frame * 10) + UE_template_ptr->pusch_tpc_tx_subframe; + if (cqi_req == 1) + UE_sched_ctrl_ptr->cqi_req_flag |= 1 << sched_subframeP; + } else { + LOG_D(MAC, "Clearing CQI request timer\n"); + UE_sched_ctrl_ptr->cqi_req_flag = 0; + UE_sched_ctrl_ptr->cqi_received = 0; + UE_sched_ctrl_ptr->cqi_req_timer = 0; + } + } - if (((framex10psubframe + 10) <= (frameP * 10 + subframeP)) || // normal case - ((framex10psubframe > (frameP * 10 + subframeP)) && (((10240 - framex10psubframe + frameP * 10 + subframeP) >= 10)))) { //frame wrap-around - UE_template_ptr->pusch_tpc_tx_frame = frameP; - UE_template_ptr->pusch_tpc_tx_subframe = subframeP; + /* Power control */ + /* + * Compute the expected ULSCH RX snr (for the stats) + * This is the normalized RX snr and this should be constant (regardless + * of mcs) Is not in dBm, unit from nfapi, converting to dBm + */ + const int32_t snr = (5 * UE_sched_ctrl_ptr->pusch_snr[CC_id] - 640) / 10; + const int32_t target_snr = mac->puSch10xSnr / 10; + /* + * This assumes accumulated tpc + * Make sure that we are only sending a tpc update once a frame, otherwise + * the control loop will freak out + */ + const int32_t fx10psf = (UE_template_ptr->pusch_tpc_tx_frame * 10) + + UE_template_ptr->pusch_tpc_tx_subframe; + uint32_t tpc = 0; - if (snr > target_snr + 4) { - tpc = 0; // -1 - tpc_accumulated--; - } else if (snr < target_snr - 4) { - tpc = 2; // +1 - tpc_accumulated++; - } else { - tpc = 1; // 0 - } - } else { - tpc = 1; // 0 - } + if (((fx10psf + 10) <= (frameP * 10 + subframeP)) // normal case + || ((fx10psf > (frameP * 10 + subframeP)) + && (((10240 - fx10psf + frameP * 10 + subframeP) >= 10)))) { // frame wrap-around + UE_template_ptr->pusch_tpc_tx_frame = frameP; + UE_template_ptr->pusch_tpc_tx_subframe = subframeP; - if (tpc != 1) { - LOG_D(MAC, "[eNB %d] ULSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, snr/target snr %d/%d\n", - module_idP, - frameP, - subframeP, - harq_pid, - tpc, - tpc_accumulated, - snr, - target_snr); - } + if (snr > target_snr + 4) { + tpc = 0; // -1 + tpc_accumulated--; + } else if (snr < target_snr - 4) { + tpc = 2; // +1 + tpc_accumulated++; + } else { + tpc = 1; // 0 + } + } else { + tpc = 1; // 0 + } - ndi = 1 - UE_template_ptr->oldNDI_UL[harq_pid]; // NDI: new data indicator - UE_template_ptr->oldNDI_UL[harq_pid] = ndi; - UE_info->eNB_UE_stats[CC_id][UE_id].snr = snr; - UE_info->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr; - UE_template_ptr->mcs_UL[harq_pid] = cmin(UE_template_ptr->pre_assigned_mcs_ul, sli->ul[slice_idx].maxmcs); - UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1= UE_template_ptr->mcs_UL[harq_pid]; + if (tpc != 1) { + LOG_D(MAC, + "[eNB %d] ULSCH scheduler: frame %d, subframe %d, harq_pid %d, " + "tpc %d, accumulated %d, snr/target snr %d/%d\n", + module_idP, + frameP, + subframeP, + harq_pid, + tpc, + tpc_accumulated, + snr, + target_snr); + } - /* CDRX */ - if (UE_sched_ctrl_ptr->cdrx_configured) { - UE_sched_ctrl_ptr->drx_inactivity_timer = 1; // reset drx inactivity timer when new transmission - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_INACTIVITY, (unsigned long) UE_sched_ctrl_ptr->drx_inactivity_timer); - UE_sched_ctrl_ptr->dci0_ongoing_timer = 1; // when set the UE_template_ptr->ul_SR cannot be set to 1, - // see definition for more information - } + const uint8_t ndi = 1 - UE_template_ptr->oldNDI_UL[harq_pid]; // NDI: new data indicator + UE_template_ptr->oldNDI_UL[harq_pid] = ndi; + UE_info->eNB_UE_stats[CC_id][UE_id].snr = snr; + UE_info->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr; + UE_template_ptr->mcs_UL[harq_pid] = UE_template_ptr->pre_assigned_mcs_ul; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1 = UE_template_ptr->mcs_UL[harq_pid]; - if (UE_template_ptr->pre_allocated_rb_table_index_ul >= 0) { - rb_table_index = UE_template_ptr->pre_allocated_rb_table_index_ul; - } else { - UE_template_ptr->mcs_UL[harq_pid] = 10; - rb_table_index = 5; // for PHR - } + /* CDRX */ + if (UE_sched_ctrl_ptr->cdrx_configured) { + // reset drx inactivity timer when new transmission + UE_sched_ctrl_ptr->drx_inactivity_timer = 1; + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( + VCD_SIGNAL_DUMPER_VARIABLES_DRX_INACTIVITY, + (unsigned long)UE_sched_ctrl_ptr->drx_inactivity_timer); + // when set the UE_template_ptr->ul_SR cannot be set to 1, + // see definition for more information + UE_sched_ctrl_ptr->dci0_ongoing_timer = 1; + } - UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2 = UE_template_ptr->mcs_UL[harq_pid]; + uint8_t rb_table_index = -1; + if (UE_template_ptr->pre_allocated_rb_table_index_ul >= 0) { + rb_table_index = UE_template_ptr->pre_allocated_rb_table_index_ul; + } else { + UE_template_ptr->mcs_UL[harq_pid] = 10; + rb_table_index = 5; // for PHR + } - while (((rb_table[rb_table_index] > (n_rb_ul_tab[CC_id] - first_rb_slice[CC_id])) || - (rb_table[rb_table_index] > 45)) && (rb_table_index > 0)) { - rb_table_index--; - } + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2 = UE_template_ptr->mcs_UL[harq_pid]; - UE_template_ptr->TBS_UL[harq_pid] = get_TBS_UL(UE_template_ptr->mcs_UL[harq_pid], rb_table[rb_table_index]); - UE_info->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx += rb_table[rb_table_index]; - UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_TBS = UE_template_ptr->TBS_UL[harq_pid]; - UE_info->eNB_UE_stats[CC_id][UE_id].total_ulsch_TBS += UE_template_ptr->TBS_UL[harq_pid]; - T(T_ENB_MAC_UE_UL_SCHEDULE, - T_INT(module_idP), - T_INT(CC_id), - T_INT(rnti), - T_INT(frameP), - T_INT(subframeP), - T_INT(harq_pid), - T_INT(UE_template_ptr->mcs_UL[harq_pid]), - T_INT(first_rb_slice[CC_id]), - T_INT(rb_table[rb_table_index]), - T_INT(UE_template_ptr->TBS_UL[harq_pid]), - T_INT(ndi)); - /* Store information for possible retransmission */ - UE_template_ptr->nb_rb_ul[harq_pid] = rb_table[rb_table_index]; - UE_template_ptr->first_rb_ul[harq_pid] = first_rb_slice[CC_id]; - UE_template_ptr->cqi_req[harq_pid] = cqi_req; - UE_sched_ctrl_ptr->ul_scheduled |= (1 << harq_pid); + while (((rb_table[rb_table_index] > (n_rb_ul_tab - first_rb[CC_id])) + || (rb_table[rb_table_index] > 45)) + && (rb_table_index > 0)) { + rb_table_index--; + } - if (UE_id == UE_info->list.head) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_SCHEDULED, UE_sched_ctrl_ptr->ul_scheduled); - } + UE_template_ptr->TBS_UL[harq_pid] = get_TBS_UL(UE_template_ptr->mcs_UL[harq_pid], rb_table[rb_table_index]); + UE_info->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx += rb_table[rb_table_index]; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_TBS = UE_template_ptr->TBS_UL[harq_pid]; + UE_info->eNB_UE_stats[CC_id][UE_id].total_ulsch_TBS += UE_template_ptr->TBS_UL[harq_pid]; + T(T_ENB_MAC_UE_UL_SCHEDULE, + T_INT(module_idP), + T_INT(CC_id), + T_INT(rnti), + T_INT(frameP), + T_INT(subframeP), + T_INT(harq_pid), + T_INT(UE_template_ptr->mcs_UL[harq_pid]), + T_INT(first_rb[CC_id]), + T_INT(rb_table[rb_table_index]), + T_INT(UE_template_ptr->TBS_UL[harq_pid]), + T_INT(ndi)); + /* Store information for possible retransmission */ + UE_template_ptr->nb_rb_ul[harq_pid] = rb_table[rb_table_index]; + UE_template_ptr->first_rb_ul[harq_pid] = first_rb[CC_id]; + UE_template_ptr->cqi_req[harq_pid] = cqi_req; + UE_sched_ctrl_ptr->ul_scheduled |= (1 << harq_pid); - /* Adjust scheduled UL bytes by TBS, wait for UL sdus to do final update */ - LOG_D(MAC, "[eNB %d] CC_id %d UE %d/%x : adjusting scheduled_ul_bytes, old %d, TBS %d\n", - module_idP, - CC_id, - UE_id, + if (UE_id == UE_info->list.head) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( + VCD_SIGNAL_DUMPER_VARIABLES_UE0_SCHEDULED, + UE_sched_ctrl_ptr->ul_scheduled); + } + + /* Adjust scheduled UL bytes by TBS, wait for UL sdus to do final update */ + LOG_D(MAC, + "[eNB %d] CC_id %d UE %d/%x : adjusting scheduled_ul_bytes, old " + "%d, TBS %d\n", + module_idP, + CC_id, + UE_id, + rnti, + UE_template_ptr->scheduled_ul_bytes, + UE_template_ptr->TBS_UL[harq_pid]); + UE_template_ptr->scheduled_ul_bytes += UE_template_ptr->TBS_UL[harq_pid]; + LOG_D(MAC, + "scheduled_ul_bytes, new %d\n", + UE_template_ptr->scheduled_ul_bytes); + /* Cyclic shift for DM-RS */ + /* Save it for a potential retransmission */ + UE_template_ptr->cshift[harq_pid] = cshift; + /* Setting DCI0 NFAPI struct */ + hi_dci0_pdu = &hi_dci0_req_body->hi_dci0_pdu_list[hi_dci0_req_body->number_of_dci + hi_dci0_req_body->number_of_hi]; + memset((void *)hi_dci0_pdu, 0, sizeof(nfapi_hi_dci0_request_pdu_t)); + hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_DCI_PDU_TYPE; + hi_dci0_pdu->pdu_size = 2 + sizeof(nfapi_hi_dci0_dci_pdu); + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.tl.tag = + NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dci_format = NFAPI_UL_DCI_FORMAT_0; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.transmission_power = 6000; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.resource_block_start = first_rb[CC_id]; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.number_of_resource_block = + rb_table[rb_table_index]; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.mcs_1 = + UE_template_ptr->mcs_UL[harq_pid]; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cyclic_shift_2_for_drms = cshift; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.frequency_hopping_enabled_flag = 0; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.new_data_indication_1 = ndi; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.tpc = tpc; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cqi_csi_request = cqi_req; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dl_assignment_index = + UE_template_ptr->DAI_ul[sched_subframeP]; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.harq_pid = harq_pid; + hi_dci0_req_body->number_of_dci++; + hi_dci0_req_body->sfnsf = + sfnsf_add_subframe(sched_frame, sched_subframeP, 0); + hi_dci0_req_body->tl.tag = NFAPI_HI_DCI0_REQUEST_BODY_TAG; + hi_dci0_req->sfn_sf = frameP << 4 | subframeP; + hi_dci0_req->header.message_id = NFAPI_HI_DCI0_REQUEST; + LOG_D(MAC, + "[PUSCH %d] Frame %d, Subframe %d: Adding UL CONFIG.Request for UE " + "%d/%x, ulsch_frame %d, ulsch_subframe %d\n", + harq_pid, + frameP, + subframeP, + UE_id, + rnti, + sched_frame, + sched_subframeP); + uint16_t ul_req_index = 0; + uint8_t dlsch_flag = 0; + + for (ul_req_index = 0; ul_req_index < ul_req_tmp_body->number_of_pdus; ul_req_index++) { + if (ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE && + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].uci_harq_pdu.ue_information.ue_information_rel8.rnti == rnti) { + dlsch_flag = 1; + LOG_D(MAC, + "Frame %d, Subframe %d:rnti %x ul_req_index %d Switched UCI " + "HARQ to ULSCH HARQ(first)\n", + frameP, + subframeP, rnti, - UE_template_ptr->scheduled_ul_bytes, - UE_template_ptr->TBS_UL[harq_pid]); - UE_template_ptr->scheduled_ul_bytes += UE_template_ptr->TBS_UL[harq_pid]; - LOG_D(MAC, "scheduled_ul_bytes, new %d\n", - UE_template_ptr->scheduled_ul_bytes); - /* Cyclic shift for DM-RS */ - cshift = 0; // values from 0 to 7 can be used for mapping the cyclic shift (36.211 , Table 5.5.2.1.1-1) - /* Save it for a potential retransmission */ - UE_template_ptr->cshift[harq_pid] = cshift; - /* Setting DCI0 NFAPI struct */ - hi_dci0_pdu = &hi_dci0_req_body->hi_dci0_pdu_list[hi_dci0_req_body->number_of_dci + hi_dci0_req_body->number_of_hi]; - memset((void *) hi_dci0_pdu, 0,sizeof(nfapi_hi_dci0_request_pdu_t)); - hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_DCI_PDU_TYPE; - hi_dci0_pdu->pdu_size = 2 + sizeof(nfapi_hi_dci0_dci_pdu); - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.tl.tag = NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dci_format = NFAPI_UL_DCI_FORMAT_0; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.transmission_power = 6000; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.resource_block_start = first_rb_slice[CC_id]; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.number_of_resource_block = rb_table[rb_table_index]; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.mcs_1 = UE_template_ptr->mcs_UL[harq_pid]; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cyclic_shift_2_for_drms = cshift; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.frequency_hopping_enabled_flag = 0; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.new_data_indication_1 = ndi; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.tpc = tpc; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cqi_csi_request = cqi_req; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dl_assignment_index = UE_template_ptr->DAI_ul[sched_subframeP]; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.harq_pid = harq_pid; - hi_dci0_req_body->number_of_dci++; - hi_dci0_req_body->sfnsf = sfnsf_add_subframe(sched_frame, sched_subframeP, 0); - hi_dci0_req_body->tl.tag = NFAPI_HI_DCI0_REQUEST_BODY_TAG; - hi_dci0_req->sfn_sf = frameP << 4 | subframeP; - hi_dci0_req->header.message_id = NFAPI_HI_DCI0_REQUEST; - LOG_D(MAC, "[PUSCH %d] Frame %d, Subframe %d: Adding UL CONFIG.Request for UE %d/%x, ulsch_frame %d, ulsch_subframe %d\n", - harq_pid, + ul_req_index); + break; + } + } + + /* Add UL_config PDUs */ + fill_nfapi_ulsch_config_request_rel8( + &ul_req_tmp_body->ul_config_pdu_list[ul_req_index], + cqi_req, + cc, + UE_template_ptr->physicalConfigDedicated, + get_tmode(module_idP, CC_id, UE_id), + mac->ul_handle, + rnti, + first_rb[CC_id], // resource_block_start + rb_table[rb_table_index], // number_of_resource_blocks + UE_template_ptr->mcs_UL[harq_pid], + cshift, // cyclic_shift_2_for_drms + 0, // frequency_hopping_enabled_flag + 0, // frequency_hopping_bits + ndi, // new_data_indication + 0, // redundancy_version + harq_pid, // harq_process_number + 0, // ul_tx_mode + 0, // current_tx_nb + 0, // n_srs + get_TBS_UL(UE_template_ptr->mcs_UL[harq_pid], + rb_table[rb_table_index])); + + /* This is a BL/CE UE allocation */ + if (UE_template_ptr->rach_resource_type > 0) { + fill_nfapi_ulsch_config_request_emtc( + &ul_req_tmp_body->ul_config_pdu_list[ul_req_index], + UE_template_ptr->rach_resource_type > 2 ? 2 : 1, + 1, // total_number_of_repetitions + 1, // repetition_number + (frameP * 10) + subframeP); + } + + if (dlsch_flag == 1) { + if (cqi_req == 1) { + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type = NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE; + ulsch_harq_information = &ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.harq_information; + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG; + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.n_srs_initial = 0; // last symbol not punctured + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.initial_number_of_resource_blocks = rb_table[rb_table_index]; + } else { + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type = NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE; + ulsch_harq_information = &ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.harq_information; + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG; + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.n_srs_initial = 0; // last symbol not punctured + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.initial_number_of_resource_blocks = rb_table[rb_table_index]; + } + + fill_nfapi_ulsch_harq_information(module_idP, CC_id, rnti, ulsch_harq_information, subframeP); + } else { + ul_req_tmp_body->number_of_pdus++; + } + + ul_req_tmp->header.message_id = NFAPI_UL_CONFIG_REQUEST; + ul_req_tmp_body->tl.tag = NFAPI_UL_CONFIG_REQUEST_BODY_TAG; + mac->ul_handle++; + ul_req_tmp->sfn_sf = sched_frame << 4 | sched_subframeP; + add_ue_ulsch_info(module_idP, CC_id, UE_id, subframeP, S_UL_SCHEDULED); + LOG_D(MAC, + "[eNB %d] CC_id %d Frame %d, subframeP %d: Generated ULSCH DCI for " + "next UE_id %d, format 0\n", + module_idP, + CC_id, + frameP, + subframeP, + UE_id); + LOG_D( + MAC, + "[PUSCH %d] SFN/SF:%04d%d UL_CFG:SFN/SF:%04d%d CQI:%d for UE %d/%x\n", + harq_pid, + frameP, + subframeP, + sched_frame, + sched_subframeP, + cqi_req, + UE_id, + rnti); + /* Increment first rb for next UE allocation */ + first_rb[CC_id] += rb_table[rb_table_index]; + } else { // round_index > 0 => retransmission + T(T_ENB_MAC_UE_UL_SCHEDULE_RETRANSMISSION, + T_INT(module_idP), + T_INT(CC_id), + T_INT(rnti), + T_INT(frameP), + T_INT(subframeP), + T_INT(harq_pid), + T_INT(UE_template_ptr->mcs_UL[harq_pid]), + T_INT(UE_template_ptr->first_rb_ul[harq_pid]), + T_INT(UE_template_ptr->nb_rb_ul[harq_pid]), + T_INT(round_index)); + /* Add UL_config PDUs */ + LOG_D(MAC, + "[PUSCH %d] Frame %d, Subframe %d: Adding UL CONFIG.Request for UE " + "%d/%x, ulsch_frame %d, ulsch_subframe %d\n", + harq_pid, + frameP, + subframeP, + UE_id, + rnti, + sched_frame, + sched_subframeP); + uint16_t ul_req_index = 0; + uint8_t dlsch_flag = 0; + uint32_t cqi_req = UE_template_ptr->cqi_req[harq_pid]; + + for (ul_req_index = 0; ul_req_index < ul_req_tmp_body->number_of_pdus; ul_req_index++) { + if (ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE && + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].uci_harq_pdu.ue_information.ue_information_rel8.rnti == rnti) { + dlsch_flag = 1; + LOG_D(MAC, + "Frame %d, Subframe %d:rnti %x ul_req_index %d Switched UCI " + "HARQ to ULSCH HARQ(first)\n", frameP, subframeP, - UE_id, rnti, - sched_frame, - sched_subframeP); - ul_req_index = 0; - dlsch_flag = 0; + ul_req_index); + break; + } + } - for(ul_req_index = 0; ul_req_index < ul_req_tmp_body->number_of_pdus; ul_req_index++) { - if(ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE && - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].uci_harq_pdu.ue_information.ue_information_rel8.rnti == rnti) { - dlsch_flag = 1; - LOG_D(MAC, "Frame %d, Subframe %d:rnti %x ul_req_index %d Switched UCI HARQ to ULSCH HARQ(first)\n", - frameP, - subframeP, - rnti, - ul_req_index); - break; - } - } + fill_nfapi_ulsch_config_request_rel8( + &ul_req_tmp_body->ul_config_pdu_list[ul_req_index], + cqi_req, + cc, + UE_template_ptr->physicalConfigDedicated, + get_tmode(module_idP, CC_id, UE_id), + mac->ul_handle, + rnti, + UE_template_ptr->first_rb_ul[harq_pid], // resource_block_start + UE_template_ptr->nb_rb_ul[harq_pid], // number_of_resource_blocks + UE_template_ptr->mcs_UL[harq_pid], + cshift, // cyclic_shift_2_for_drms + 0, // frequency_hopping_enabled_flag + 0, // frequency_hopping_bits + UE_template_ptr->oldNDI_UL[harq_pid], // new_data_indication + rvidx_tab[round_index & 3], // redundancy_version + harq_pid, // harq_process_number + 0, // ul_tx_mode + 0, // current_tx_nb + 0, // n_srs + UE_template_ptr->TBS_UL[harq_pid]); - /* Add UL_config PDUs */ - fill_nfapi_ulsch_config_request_rel8(&ul_req_tmp_body->ul_config_pdu_list[ul_req_index], - cqi_req, - cc, - UE_template_ptr->physicalConfigDedicated, - get_tmode(module_idP, CC_id, UE_id), - mac->ul_handle, - rnti, - first_rb_slice[CC_id], // resource_block_start - rb_table[rb_table_index], // number_of_resource_blocks - UE_template_ptr->mcs_UL[harq_pid], - cshift, // cyclic_shift_2_for_drms - 0, // frequency_hopping_enabled_flag - 0, // frequency_hopping_bits - ndi, // new_data_indication - 0, // redundancy_version - harq_pid, // harq_process_number - 0, // ul_tx_mode - 0, // current_tx_nb - 0, // n_srs - get_TBS_UL(UE_template_ptr->mcs_UL[harq_pid], rb_table[rb_table_index])); + /* This is a BL/CE UE allocation */ + if (UE_template_ptr->rach_resource_type > 0) { + fill_nfapi_ulsch_config_request_emtc( + &ul_req_tmp_body->ul_config_pdu_list[ul_req_index], + UE_template_ptr->rach_resource_type > 2 ? 2 : 1, + 1, // total_number_of_repetitions + 1, // repetition_number + (frameP * 10) + subframeP); + } - /* This is a BL/CE UE allocation */ - if (UE_template_ptr->rach_resource_type > 0) { - fill_nfapi_ulsch_config_request_emtc(&ul_req_tmp_body->ul_config_pdu_list[ul_req_index], - UE_template_ptr->rach_resource_type > 2 ? 2 : 1, - 1, // total_number_of_repetitions - 1, // repetition_number - (frameP * 10) + subframeP); - } + if (dlsch_flag == 1) { + if (cqi_req == 1) { + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type = NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE; + ulsch_harq_information = &ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.harq_information; + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG; + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.n_srs_initial = 0; // last symbol not punctured + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.initial_number_of_resource_blocks = UE_template_ptr->nb_rb_ul[harq_pid]; + } else { + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type = NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE; + ulsch_harq_information = &ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.harq_information; + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG; + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.n_srs_initial = 0; // last symbol not punctured + ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.initial_number_of_resource_blocks = UE_template_ptr->nb_rb_ul[harq_pid]; + } - if (dlsch_flag == 1) { - if (cqi_req == 1) { - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type = NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE; - ulsch_harq_information = &ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.harq_information; - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.tl.tag = - NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG; - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.n_srs_initial = 0; // last symbol not punctured - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.initial_number_of_resource_blocks = - rb_table[rb_table_index]; - } else { - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type = NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE; - ulsch_harq_information = &ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.harq_information; - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.tl.tag = - NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG; - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.n_srs_initial = 0; // last symbol not punctured - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.initial_number_of_resource_blocks = rb_table[rb_table_index]; - } + fill_nfapi_ulsch_harq_information(module_idP, CC_id, rnti, ulsch_harq_information, subframeP); + } else { + ul_req_tmp_body->number_of_pdus++; + } - fill_nfapi_ulsch_harq_information(module_idP, CC_id,rnti, ulsch_harq_information,subframeP); - } else { - ul_req_tmp_body->number_of_pdus++; - } + mac->ul_handle++; + ul_req_tmp_body->tl.tag = NFAPI_UL_CONFIG_REQUEST_BODY_TAG; + ul_req_tmp->sfn_sf = sched_frame << 4 | sched_subframeP; + ul_req_tmp->header.message_id = NFAPI_UL_CONFIG_REQUEST; + LOG_D(MAC, + "[PUSCH %d] Frame %d, Subframe %d: Adding UL CONFIG.Request for UE " + "%d/%x, ulsch_frame %d, ulsch_subframe %d cqi_req %d\n", + harq_pid, + frameP, + subframeP, + UE_id, + rnti, + sched_frame, + sched_subframeP, + cqi_req); - ul_req_tmp->header.message_id = NFAPI_UL_CONFIG_REQUEST; - ul_req_tmp_body->tl.tag = NFAPI_UL_CONFIG_REQUEST_BODY_TAG; - mac->ul_handle++; - ul_req_tmp->sfn_sf = sched_frame << 4 | sched_subframeP; - add_ue_ulsch_info(module_idP, CC_id, UE_id, subframeP, S_UL_SCHEDULED); - LOG_D(MAC, "[eNB %d] CC_id %d Frame %d, subframeP %d: Generated ULSCH DCI for next UE_id %d, format 0\n", - module_idP, - CC_id, - frameP, - subframeP, - UE_id); - LOG_D(MAC, "[PUSCH %d] SFN/SF:%04d%d UL_CFG:SFN/SF:%04d%d CQI:%d for UE %d/%x\n", - harq_pid, - frameP, - subframeP, - sched_frame, - sched_subframeP, - cqi_req, - UE_id, - rnti); - /* Increment first rb for next UE allocation */ - first_rb_slice[CC_id] += rb_table[rb_table_index]; - } else { // round_index > 0 => retransmission - T(T_ENB_MAC_UE_UL_SCHEDULE_RETRANSMISSION, - T_INT(module_idP), - T_INT(CC_id), - T_INT(rnti), - T_INT(frameP), - T_INT(subframeP), - T_INT(harq_pid), - T_INT(UE_template_ptr->mcs_UL[harq_pid]), - T_INT(UE_template_ptr->first_rb_ul[harq_pid]), - T_INT(UE_template_ptr->nb_rb_ul[harq_pid]), - T_INT(round_index)); - /* Add UL_config PDUs */ - LOG_D(MAC, "[PUSCH %d] Frame %d, Subframe %d: Adding UL CONFIG.Request for UE %d/%x, ulsch_frame %d, ulsch_subframe %d\n", - harq_pid, - frameP, - subframeP, - UE_id, - rnti, - sched_frame, - sched_subframeP); - ul_req_index = 0; - dlsch_flag = 0; - cqi_req = UE_template_ptr->cqi_req[harq_pid]; - - for(ul_req_index = 0; ul_req_index < ul_req_tmp_body->number_of_pdus; ul_req_index++) { - if(ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE && - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].uci_harq_pdu.ue_information.ue_information_rel8.rnti == rnti) { - dlsch_flag = 1; - LOG_D(MAC, "Frame %d, Subframe %d:rnti %x ul_req_index %d Switched UCI HARQ to ULSCH HARQ(first)\n", - frameP, - subframeP, - rnti, - ul_req_index); - break; - } - } - - fill_nfapi_ulsch_config_request_rel8(&ul_req_tmp_body->ul_config_pdu_list[ul_req_index], - cqi_req, - cc, - UE_template_ptr->physicalConfigDedicated, - get_tmode(module_idP, CC_id, UE_id), - mac->ul_handle, - rnti, - UE_template_ptr->first_rb_ul[harq_pid], // resource_block_start - UE_template_ptr->nb_rb_ul[harq_pid], // number_of_resource_blocks - UE_template_ptr->mcs_UL[harq_pid], - cshift, // cyclic_shift_2_for_drms - 0, // frequency_hopping_enabled_flag - 0, // frequency_hopping_bits - UE_template_ptr->oldNDI_UL[harq_pid], // new_data_indication - rvidx_tab[round_index & 3], // redundancy_version - harq_pid, // harq_process_number - 0, // ul_tx_mode - 0, // current_tx_nb - 0, // n_srs - UE_template_ptr->TBS_UL[harq_pid]); - - /* This is a BL/CE UE allocation */ - if (UE_template_ptr->rach_resource_type > 0) { - fill_nfapi_ulsch_config_request_emtc(&ul_req_tmp_body->ul_config_pdu_list[ul_req_index], - UE_template_ptr->rach_resource_type > 2 ? 2 : 1, - 1, // total_number_of_repetitions - 1, // repetition_number - (frameP * 10) + subframeP); - } - - if(dlsch_flag == 1) { - if(cqi_req == 1) { - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type = NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE; - ulsch_harq_information = &ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.harq_information; - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.tl.tag= - NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG; - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.n_srs_initial = 0; // last symbol not punctured - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.initial_number_of_resource_blocks = - UE_template_ptr->nb_rb_ul[harq_pid]; - } else { - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type = NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE; - ulsch_harq_information = &ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.harq_information; - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.tl.tag = - NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG; - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.n_srs_initial = 0; // last symbol not punctured - ul_req_tmp_body->ul_config_pdu_list[ul_req_index].ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.initial_number_of_resource_blocks = - UE_template_ptr->nb_rb_ul[harq_pid]; - } - - fill_nfapi_ulsch_harq_information(module_idP, CC_id,rnti, ulsch_harq_information, subframeP); - } else { - ul_req_tmp_body->number_of_pdus++; - } - - mac->ul_handle++; - ul_req_tmp_body->tl.tag = NFAPI_UL_CONFIG_REQUEST_BODY_TAG; - ul_req_tmp->sfn_sf = sched_frame<<4|sched_subframeP; - ul_req_tmp->header.message_id = NFAPI_UL_CONFIG_REQUEST; - LOG_D(MAC, "[PUSCH %d] Frame %d, Subframe %d: Adding UL CONFIG.Request for UE %d/%x, ulsch_frame %d, ulsch_subframe %d cqi_req %d\n", - harq_pid, - frameP, - subframeP, - UE_id, - rnti, - sched_frame, - sched_subframeP, - cqi_req); - - /* HACK: RBs used by retransmission have to be reserved. - * The current mechanism uses the notion of 'first_rb', so - * we skip all RBs below the ones retransmitted. This is - * not correct. Imagine only RB 23 is retransmitted, then all - * RBs < 23 will be marked unusable for new transmissions (case where round == 0). - * Note also that this code works only if the preprocessor orders - * UEs with retransmission with higher priority than UEs with new - * transmission. - * All this should be cleaned up properly. - */ - if (first_rb_slice[CC_id] < UE_template_ptr->first_rb_ul[harq_pid] + UE_template_ptr->nb_rb_ul[harq_pid]) - first_rb_slice[CC_id] = UE_template_ptr->first_rb_ul[harq_pid] + UE_template_ptr->nb_rb_ul[harq_pid]; - } // end of round > 0 - } // UE_is_to_be_scheduled - } // loop over all active CC_ids - } // loop over UE_ids + /* HACK: RBs used by retransmission have to be reserved. + * The current mechanism uses the notion of 'first_rb', so + * we skip all RBs below the ones retransmitted. This is + * not correct. Imagine only RB 23 is retransmitted, then all + * RBs < 23 will be marked unusable for new transmissions (case where + * round == 0). Note also that this code works only if the preprocessor + * orders UEs with retransmission with higher priority than UEs with new + * transmission. + * All this should be cleaned up properly. + */ + if (first_rb[CC_id] < UE_template_ptr->first_rb_ul[harq_pid] + UE_template_ptr->nb_rb_ul[harq_pid]) + first_rb[CC_id] = UE_template_ptr->first_rb_ul[harq_pid] + + UE_template_ptr->nb_rb_ul[harq_pid]; + } // end of round > 0 + } // loop over UE_ids } diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index b8834007e0..ef2f0fd5f7 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -122,12 +122,12 @@ void schedule_ulsch(module_id_t module_idP, frame_t frameP, /** \brief ULSCH Scheduling per RNTI @param Mod_id Instance ID of eNB -@param slice_idx Slice instance index for this eNB +@param CC_id The component carrier to schedule @param frame Frame index @param subframe Subframe number on which to act @param sched_subframe Subframe number where PUSCH is transmitted (for DAI lookup) */ -void schedule_ulsch_rnti(module_id_t module_idP, int slice_idx, frame_t frameP, +void schedule_ulsch_rnti(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t subframe, unsigned char sched_subframe, uint16_t *first_rb); @@ -677,7 +677,9 @@ void set_ul_DAI(int module_idP, int frameP, int subframeP); -void ulsch_scheduler_pre_processor(module_id_t module_idP, int slice_idx, int frameP, +void ulsch_scheduler_pre_processor(module_id_t module_idP, + int CC_id, + int frameP, sub_frame_t subframeP, int sched_frameP, unsigned char sched_subframeP, diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 6c810fea0d..4b9925968d 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -419,7 +419,7 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, /// ULSCH PRE_PROCESSOR void ulsch_scheduler_pre_processor(module_id_t module_idP, - int slice_idx, + int CC_id, int frameP, sub_frame_t subframeP, int sched_frameP, @@ -427,7 +427,7 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, uint16_t *first_rb) { int UE_id; uint16_t n; - uint8_t CC_id, harq_pid; + uint8_t harq_pid; uint16_t nb_allocated_rbs[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]; uint16_t total_allocated_rbs[NFAPI_CC_MAX]; uint16_t average_rbs_per_user[NFAPI_CC_MAX]; @@ -436,6 +436,7 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, eNB_MAC_INST *eNB = RC.mac[module_idP]; UE_info_t *UE_info = &eNB->UE_info; slice_info_t *sli = &eNB->slice_info; + const int slice_idx = 0; UE_TEMPLATE *UE_template = 0; UE_sched_ctrl_t *ue_sched_ctl; int N_RB_UL = 0; @@ -498,8 +499,7 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, ue_sched_ctl->max_rbs_allowed_slice_uplink[CC_id][slice_idx] = nb_rbs_allowed_slice(sli->ul[slice_idx].pct, N_RB_UL); first_rb_offset = UE_info->first_rb_offset[CC_id][slice_idx]; - available_rbs = - cmin(ue_sched_ctl->max_rbs_allowed_slice_uplink[CC_id][slice_idx], N_RB_UL - first_rb[CC_id] - first_rb_offset); + available_rbs = N_RB_UL - 2 * first_rb[CC_id]; // factor 2: top&bottom if (available_rbs < 0) available_rbs = 0; @@ -668,8 +668,7 @@ assign_max_mcs_min_rb(module_id_t module_idP, } first_rb_offset = UE_info->first_rb_offset[CC_id][slice_idx]; - available_rbs = - cmin(ue_sched_ctl->max_rbs_allowed_slice_uplink[CC_id][slice_idx], N_RB_UL - first_rb[CC_id] - first_rb_offset); + available_rbs = N_RB_UL - 2 * first_rb[CC_id]; while (tbs < bits_to_schedule && rb_table[rb_table_index] < available_rbs && From 9b4725ad0bf07428504080f6704678c1a577cdcc Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 5 Feb 2020 15:49:33 +0200 Subject: [PATCH 124/240] Shortened UL-PP, remove CC and slicing --- openair2/ENB_APP/flexran_agent_ran_api.c | 14 +- openair2/LAYER2/MAC/eNB_scheduler_fairRR.c | 10 +- .../LAYER2/MAC/eNB_scheduler_primitives.c | 21 - openair2/LAYER2/MAC/eNB_scheduler_ulsch.c | 2 +- openair2/LAYER2/MAC/mac.h | 7 +- openair2/LAYER2/MAC/mac_proto.h | 7 +- openair2/LAYER2/MAC/main.c | 1 - openair2/LAYER2/MAC/pre_processor.c | 360 ++++++------------ 8 files changed, 144 insertions(+), 278 deletions(-) diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index 4a29a4ba5a..32cb8c74e1 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -3037,7 +3037,7 @@ void flexran_set_ue_dl_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx) { int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return -1; - int slice_idx = RC.mac[mod_id]->UE_info.assoc_ul_slice_idx[ue_id]; + int slice_idx = 0; //RC.mac[mod_id]->UE_info.assoc_ul_slice_idx[ue_id]; if (slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_ul) return RC.mac[mod_id]->slice_info.ul[slice_idx].id; @@ -3052,7 +3052,7 @@ void flexran_set_ue_ul_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx) { if (!flexran_ul_slice_exists(mod_id, slice_idx)) return; - RC.mac[mod_id]->UE_info.assoc_ul_slice_idx[ue_id] = slice_idx; + //RC.mac[mod_id]->UE_info.assoc_ul_slice_idx[ue_id] = slice_idx; } int flexran_dl_slice_exists(mid_t mod_id, int slice_idx) { @@ -3397,12 +3397,12 @@ int flexran_remove_ul_slice(mid_t mod_id, int slice_idx) { memset(&sli->ul[sli->n_ul], 0, sizeof(sli->ul[sli->n_ul])); /* all UEs that have been in the old slice are put into slice index 0 */ - int *assoc_list = RC.mac[mod_id]->UE_info.assoc_ul_slice_idx; + //int *assoc_list = RC.mac[mod_id]->UE_info.assoc_ul_slice_idx; - for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) { - if (assoc_list[i] == slice_idx) - assoc_list[i] = 0; - } + //for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) { + // if (assoc_list[i] == slice_idx) + // assoc_list[i] = 0; + //} return sli->n_ul; } diff --git a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c index 96eededc1a..d486c59ff5 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c @@ -2695,7 +2695,7 @@ void ulsch_scheduler_pre_processor_fairRR(module_id_t module_idP, if ( rb_table[rb_table_index] <= average_rbs ) { // assigne RBS( nb_rb) first_rb[CC_id] = first_rb[CC_id] + rb_table[rb_table_index]; - UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[0] = rb_table[rb_table_index]; + UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul = rb_table[rb_table_index]; UE_info->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = rb_table_index; UE_info->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = mcs; } @@ -2711,7 +2711,7 @@ void ulsch_scheduler_pre_processor_fairRR(module_id_t module_idP, } first_rb[CC_id] = first_rb[CC_id] + rb_table[rb_table_index]; - UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[0] = rb_table[rb_table_index]; + UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul = rb_table[rb_table_index]; UE_info->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = rb_table_index; UE_info->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = mcs; } @@ -2719,13 +2719,13 @@ void ulsch_scheduler_pre_processor_fairRR(module_id_t module_idP, if (mac_eNB_get_rrc_status(module_idP,UE_RNTI(module_idP, UE_id)) < RRC_CONNECTED) { // assigne RBS( 6 RBs) first_rb[CC_id] = first_rb[CC_id] + 6; - UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[0] = 6; + UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul = 6; UE_info->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = 5; UE_info->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = 10; } else { // assigne RBS( 3 RBs) first_rb[CC_id] = first_rb[CC_id] + 3; - UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[0] = 3; + UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul = 3; UE_info->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = 2; UE_info->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = 10; } @@ -2733,7 +2733,7 @@ void ulsch_scheduler_pre_processor_fairRR(module_id_t module_idP, } else if ( ulsch_ue_select[CC_id].list[ulsch_ue_num].ue_priority == SCH_UL_INACTIVE ) { // assigne RBS( 3 RBs) first_rb[CC_id] = first_rb[CC_id] + 3; - UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[0] = 3; + UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul = 3; UE_info->UE_template[CC_id][UE_id].pre_allocated_rb_table_index_ul = 2; UE_info->UE_template[CC_id][UE_id].pre_assigned_mcs_ul = 10; } diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index bb0b0604d3..fdd4459c45 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -2209,8 +2209,6 @@ add_new_ue(module_id_t mod_idP, 0, sizeof(eNB_UE_STATS)); UE_info->UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 0; - /* default slice in case there was something different */ - UE_info->assoc_ul_slice_idx[UE_id] = 0; UE_info->UE_sched_ctrl[UE_id].ta_update = 31; for (j = 0; j < 8; j++) { @@ -5055,22 +5053,3 @@ nb_rbs_allowed_slice(float rb_percentage, { return (uint16_t) floor(rb_percentage * total_rbs); } - -//------------------------------------------------------------------------------ -int -ue_ul_slice_membership(module_id_t mod_id, - int UE_id, - int slice_idx) -//------------------------------------------------------------------------------ -{ - eNB_MAC_INST *eNB = RC.mac[mod_id]; - - if (slice_idx < 0 || slice_idx >= eNB->slice_info.n_ul) { - LOG_W(MAC, "out of range slice index %d (slice ID %d)\n", - slice_idx, - eNB->slice_info.dl[slice_idx].id); - return 0; - } - - return eNB->UE_info.active[UE_id] == TRUE && eNB->UE_info.assoc_ul_slice_idx[UE_id] == slice_idx; -} diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index d34fa28fa5..a6083fbf1c 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -1334,7 +1334,7 @@ schedule_ulsch_rnti(module_id_t module_idP, exit(1); } - UE_info->first_rb_offset[CC_id][0] = n_rb_ul_tab; + UE_info->first_rb_offset[CC_id] = n_rb_ul_tab; /* * ULSCH preprocessor: set UE_template-> diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h index 6f445eabb7..0a7e616d91 100644 --- a/openair2/LAYER2/MAC/mac.h +++ b/openair2/LAYER2/MAC/mac.h @@ -824,7 +824,7 @@ typedef struct { uint16_t cshift[8]; // num_max_harq /// Number of Allocated RBs by the ulsch preprocessor - uint8_t pre_allocated_nb_rb_ul[MAX_NUM_SLICES]; + uint8_t pre_allocated_nb_rb_ul; /// index of Allocated RBs by the ulsch preprocessor int8_t pre_allocated_rb_table_index_ul; @@ -920,8 +920,6 @@ typedef struct { /// number of bytes to schedule for each LC uint32_t dl_lc_bytes[MAX_NUM_LCID]; - uint16_t max_rbs_allowed_slice_uplink[NFAPI_CC_MAX][MAX_NUM_SLICES]; - // resource scheduling information /// Current DL harq round per harq_pid on each CC @@ -1149,8 +1147,7 @@ typedef struct { /// Sorting criteria for the UE list in the MAC preprocessor uint16_t sorting_criteria[MAX_NUM_SLICES][CR_NUM]; - uint16_t first_rb_offset[NFAPI_CC_MAX][MAX_NUM_SLICES]; - int assoc_ul_slice_idx[MAX_MOBILES_PER_ENB]; + uint16_t first_rb_offset[NFAPI_CC_MAX]; } UE_info_t; /*! \brief deleting control information*/ diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index ef2f0fd5f7..0804dcd8c3 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -686,8 +686,11 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, uint16_t *first_rb); void store_ulsch_buffer(module_id_t module_idP, int frameP, sub_frame_t subframeP); -void assign_max_mcs_min_rb(module_id_t module_idP, int slice_idx, int frameP, - sub_frame_t subframeP, uint16_t *first_rb); +void assign_max_mcs_min_rb(module_id_t module_idP, + int CC_id, + int frameP, + sub_frame_t subframeP, + uint16_t *first_rb); void adjust_bsr_info(int buffer_occupancy, uint16_t TBS, UE_TEMPLATE *UE_template); diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index ae1e7aee37..1a88623a1f 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -55,7 +55,6 @@ void init_UE_info(UE_info_t *UE_info) memset(UE_info->eNB_UE_stats, 0, sizeof(UE_info->eNB_UE_stats)); memset(UE_info->UE_sched_ctrl, 0, sizeof(UE_info->UE_sched_ctrl)); memset(UE_info->active, 0, sizeof(UE_info->active)); - memset(UE_info->assoc_ul_slice_idx, 0, sizeof(UE_info->assoc_ul_slice_idx)); } void init_slice_info(slice_info_t *sli) diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 4b9925968d..a1cd64a7d5 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -198,7 +198,6 @@ int round_robin_dl(module_id_t Mod_id, void sort_ue_ul(module_id_t module_idP, - int slice_idx, int sched_frameP, sub_frame_t sched_subframeP, rnti_t *rntiTable); @@ -425,190 +424,98 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, int sched_frameP, unsigned char sched_subframeP, uint16_t *first_rb) { - int UE_id; - uint16_t n; - uint8_t harq_pid; - uint16_t nb_allocated_rbs[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]; - uint16_t total_allocated_rbs[NFAPI_CC_MAX]; - uint16_t average_rbs_per_user[NFAPI_CC_MAX]; - int16_t total_remaining_rbs[NFAPI_CC_MAX]; - uint16_t total_ue_count[NFAPI_CC_MAX]; + uint16_t nb_allocated_rbs[MAX_MOBILES_PER_ENB]; + uint16_t total_allocated_rbs = 0; + uint16_t average_rbs_per_user = 0; + int16_t total_remaining_rbs = 0; + uint16_t total_ue_count = 0; eNB_MAC_INST *eNB = RC.mac[module_idP]; UE_info_t *UE_info = &eNB->UE_info; - slice_info_t *sli = &eNB->slice_info; - const int slice_idx = 0; - UE_TEMPLATE *UE_template = 0; - UE_sched_ctrl_t *ue_sched_ctl; - int N_RB_UL = 0; - uint16_t available_rbs, first_rb_offset; + const int N_RB_UL = to_prb(eNB->common_channels[CC_id].ul_Bandwidth); + uint16_t available_rbs = N_RB_UL - 2 * first_rb[CC_id]; // top and bottom // - UE_info->first_rb_offset[CC_id]; rnti_t rntiTable[MAX_MOBILES_PER_ENB]; + // sort ues LOG_D(MAC, "In ulsch_preprocessor: sort ue \n"); - sort_ue_ul(module_idP, slice_idx, sched_frameP, sched_subframeP, rntiTable); + sort_ue_ul(module_idP, sched_frameP, sched_subframeP, rntiTable); // maximize MCS and then allocate required RB according to the buffer occupancy with the limit of max available UL RB LOG_D(MAC, "In ulsch_preprocessor: assign max mcs min rb\n"); - assign_max_mcs_min_rb(module_idP, slice_idx, frameP, subframeP, first_rb); - // we need to distribute RBs among UEs - // step1: reset the vars - uint8_t CC_nb = (uint8_t) RC.nb_mac_CC[module_idP]; + assign_max_mcs_min_rb(module_idP, CC_id, frameP, subframeP, first_rb); - for (CC_id = 0; CC_id < CC_nb; CC_id++) { - total_allocated_rbs[CC_id] = 0; - total_remaining_rbs[CC_id] = 0; - average_rbs_per_user[CC_id] = 0; - total_ue_count[CC_id] = 0; - } - - // Step 1.5: Calculate total_ue_count - for (UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { - // This is not the actual CC_id in the list - for (n = 0; n < UE_info->numactiveULCCs[UE_id]; n++) { - CC_id = UE_info->ordered_ULCCids[n][UE_id]; - UE_template = &UE_info->UE_template[CC_id][UE_id]; - - if (UE_template->pre_allocated_nb_rb_ul[slice_idx] > 0) { - total_ue_count[CC_id]++; - } + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + if (UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul > 0) { + total_ue_count++; } } - // step 2: calculate the average rb per UE - LOG_D(MAC, "In ulsch_preprocessor: step2 \n"); + if (total_ue_count == 0) + average_rbs_per_user = 0; + else if (total_ue_count == 1) + average_rbs_per_user = available_rbs + 1; + else if (total_ue_count <= available_rbs) + average_rbs_per_user = (uint16_t) floor(available_rbs / total_ue_count); + else + average_rbs_per_user = 1; - for (UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { - if (UE_info->UE_template[CC_id][UE_id].rach_resource_type > 0) continue; + if (total_ue_count > 0) + LOG_D(MAC, "[eNB %d] Frame %d subframe %d: total ue to be scheduled %d\n", + module_idP, + frameP, + subframeP, + total_ue_count); - LOG_D(MAC, "In ulsch_preprocessor: handling UE %d/%x\n", + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + uint8_t harq_pid = subframe2harqpid(&RC.mac[module_idP]->common_channels[CC_id], + sched_frameP, sched_subframeP); + + if (UE_info->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid] > 0) + nb_allocated_rbs[UE_id] = UE_info->UE_template[CC_id][UE_id].nb_rb_ul[harq_pid]; + else + nb_allocated_rbs[UE_id] = cmin(UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul, average_rbs_per_user); + + total_allocated_rbs += nb_allocated_rbs[UE_id]; + LOG_D(MAC, "In ulsch_preprocessor: assigning %d RBs for UE %d/%x CCid %d, harq_pid %d\n", + nb_allocated_rbs[UE_id], UE_id, - rntiTable[UE_id]); - - for (n = 0; n < UE_info->numactiveULCCs[UE_id]; n++) { - // This is the actual CC_id in the list - CC_id = UE_info->ordered_ULCCids[n][UE_id]; - LOG_D(MAC, "In ulsch_preprocessor: handling UE %d/%x CCid %d\n", - UE_id, - rntiTable[UE_id], - CC_id); - /* - if((mac_xface->get_nCCE_max(module_idP,CC_id,3,subframeP) - nCCE_to_be_used[CC_id]) > (1<common_channels[CC_id].ul_Bandwidth); - ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; - ue_sched_ctl->max_rbs_allowed_slice_uplink[CC_id][slice_idx] = - nb_rbs_allowed_slice(sli->ul[slice_idx].pct, N_RB_UL); - first_rb_offset = UE_info->first_rb_offset[CC_id][slice_idx]; - available_rbs = N_RB_UL - 2 * first_rb[CC_id]; // factor 2: top&bottom - - if (available_rbs < 0) - available_rbs = 0; - - if (total_ue_count[CC_id] == 0) { - average_rbs_per_user[CC_id] = 0; - } else if (total_ue_count[CC_id] == 1) { // increase the available RBs, special case, - average_rbs_per_user[CC_id] = (uint16_t) (available_rbs + 1); - } else if (total_ue_count[CC_id] <= available_rbs) { - average_rbs_per_user[CC_id] = (uint16_t) floor(available_rbs / total_ue_count[CC_id]); - } else { - average_rbs_per_user[CC_id] = 1; - LOG_W(MAC, "[eNB %d] frame %d subframe %d: UE %d CC %d: can't get average rb per user (should not be here)\n", - module_idP, - frameP, - subframeP, - UE_id, - CC_id); - } - - if (total_ue_count[CC_id] > 0) { - LOG_D(MAC, "[eNB %d] Frame %d subframe %d: total ue to be scheduled %d\n", - module_idP, - frameP, - subframeP, - total_ue_count[CC_id]); - } - } + rntiTable[UE_id], + CC_id, + harq_pid); } - // step 3: assigne RBS - for (UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { - // if (continueTable[UE_id]) continue; - for (n = 0; n < UE_info->numactiveULCCs[UE_id]; n++) { - // This is the actual CC_id in the list - CC_id = UE_info->ordered_ULCCids[n][UE_id]; - UE_template = &UE_info->UE_template[CC_id][UE_id]; - harq_pid = subframe2harqpid(&RC.mac[module_idP]->common_channels[CC_id], - sched_frameP, sched_subframeP); + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + UE_TEMPLATE *UE_template = &UE_info->UE_template[CC_id][UE_id]; + total_remaining_rbs = available_rbs - total_allocated_rbs; - // mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,openair_harq_UL); + /* TODO this has already been accounted for - do we need it again? */ + //if (total_ue_count == 1) + // total_remaining_rbs++; - if (UE_info->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid] > 0) { - nb_allocated_rbs[CC_id][UE_id] = UE_info->UE_template[CC_id][UE_id].nb_rb_ul[harq_pid]; - } else { - nb_allocated_rbs[CC_id][UE_id] = - cmin(UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[slice_idx], average_rbs_per_user[CC_id]); - } - - total_allocated_rbs[CC_id] += nb_allocated_rbs[CC_id][UE_id]; - LOG_D(MAC, "In ulsch_preprocessor: assigning %d RBs for UE %d/%x CCid %d, harq_pid %d\n", - nb_allocated_rbs[CC_id][UE_id], - UE_id, - rntiTable[UE_id], - CC_id, - harq_pid); + while (UE_template->pre_allocated_nb_rb_ul > 0 && + nb_allocated_rbs[UE_id] < UE_template->pre_allocated_nb_rb_ul && + total_remaining_rbs > 0) { + nb_allocated_rbs[UE_id] = cmin(nb_allocated_rbs[UE_id] + 1, UE_template->pre_allocated_nb_rb_ul); + total_remaining_rbs--; + total_allocated_rbs++; } + + UE_template->pre_allocated_nb_rb_ul = nb_allocated_rbs[UE_id]; + LOG_D(MAC, "******************UL Scheduling Information for UE%d CC_id %d ************************\n", + UE_id, + CC_id); + LOG_D(MAC, "[eNB %d] total RB allocated for UE%d CC_id %d = %d\n", + module_idP, + UE_id, + CC_id, + UE_template->pre_allocated_nb_rb_ul); } - - // step 4: assigne the remaining RBs and set the pre_allocated rbs accordingly - for (UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { - // if (continueTable[UE_id]) continue; - ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; - - for (n = 0; n < UE_info->numactiveULCCs[UE_id]; n++) { - // This is the actual CC_id in the list - CC_id = UE_info->ordered_ULCCids[n][UE_id]; - UE_template = &UE_info->UE_template[CC_id][UE_id]; - N_RB_UL = to_prb(eNB->common_channels[CC_id].ul_Bandwidth); - first_rb_offset = UE_info->first_rb_offset[CC_id][slice_idx]; - available_rbs = cmin(ue_sched_ctl->max_rbs_allowed_slice_uplink[CC_id][slice_idx], N_RB_UL - first_rb[CC_id] - first_rb_offset); - total_remaining_rbs[CC_id] = available_rbs - total_allocated_rbs[CC_id]; - - if (total_ue_count[CC_id] == 1) { - total_remaining_rbs[CC_id]++; - } - - while (UE_template->pre_allocated_nb_rb_ul[slice_idx] > 0 && - nb_allocated_rbs[CC_id][UE_id] < UE_template->pre_allocated_nb_rb_ul[slice_idx] && - total_remaining_rbs[CC_id] > 0) { - nb_allocated_rbs[CC_id][UE_id] = cmin(nb_allocated_rbs[CC_id][UE_id] + 1, UE_template->pre_allocated_nb_rb_ul[slice_idx]); - total_remaining_rbs[CC_id]--; - total_allocated_rbs[CC_id]++; - } - - UE_template->pre_allocated_nb_rb_ul[slice_idx] = nb_allocated_rbs[CC_id][UE_id]; - LOG_D(MAC, "******************UL Scheduling Information for UE%d CC_id %d ************************\n", - UE_id, - CC_id); - LOG_D(MAC, "[eNB %d] total RB allocated for UE%d CC_id %d = %d\n", - module_idP, - UE_id, - CC_id, - UE_template->pre_allocated_nb_rb_ul[slice_idx]); - } - } - - return; } void assign_max_mcs_min_rb(module_id_t module_idP, - int slice_idx, + int CC_id, int frameP, sub_frame_t subframeP, uint16_t *first_rb) { - int i; - uint16_t n, UE_id; - uint8_t CC_id; int mcs; int rb_table_index = 0, tbs, tx_power; eNB_MAC_INST *eNB = RC.mac[module_idP]; @@ -620,77 +527,61 @@ assign_max_mcs_min_rb(module_id_t module_idP, int N_RB_UL; int first_rb_offset, available_rbs; - for (i = UE_info->list.head; i >= 0; i = UE_info->list.next[i]) { - if (UE_info->UE_sched_ctrl[i].phr_received == 1) { - /* if we've received the power headroom information the UE, we can go to - * maximum mcs */ - mcs = cmin(20, sli->ul[slice_idx].maxmcs); - } else { - /* otherwise, limit to QPSK PUSCH */ - mcs = cmin(10, sli->ul[slice_idx].maxmcs); - } + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + /* if we've received the power headroom information the UE, we can go to + * maximum mcs */ + mcs = UE_info->UE_sched_ctrl[UE_id].phr_received == 1 ? 20 : 10; - UE_id = i; + UE_template = &UE_info->UE_template[CC_id][UE_id]; + UE_template->pre_assigned_mcs_ul = mcs; + ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; + Ncp = eNB->common_channels[CC_id].Ncp; + N_RB_UL = to_prb(eNB->common_channels[CC_id].ul_Bandwidth); + int bytes_to_schedule = UE_template->estimated_ul_buffer - UE_template->scheduled_ul_bytes; - for (n = 0; n < UE_info->numactiveULCCs[UE_id]; n++) { - // This is the actual CC_id in the list - CC_id = UE_info->ordered_ULCCids[n][UE_id]; - AssertFatal(CC_id < RC.nb_mac_CC[module_idP], "CC_id %u should be < %u, loop n=%u < numactiveULCCs[%u]=%u", - CC_id, - NFAPI_CC_MAX, - n, - UE_id, - UE_info->numactiveULCCs[UE_id]); - UE_template = &UE_info->UE_template[CC_id][UE_id]; - UE_template->pre_assigned_mcs_ul = mcs; - ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; - Ncp = eNB->common_channels[CC_id].Ncp; - N_RB_UL = to_prb(eNB->common_channels[CC_id].ul_Bandwidth); - ue_sched_ctl->max_rbs_allowed_slice_uplink[CC_id][slice_idx] = nb_rbs_allowed_slice(sli->ul[slice_idx].pct, N_RB_UL); - int bytes_to_schedule = UE_template->estimated_ul_buffer - UE_template->scheduled_ul_bytes; + if (bytes_to_schedule < 0) bytes_to_schedule = 0; - if (bytes_to_schedule < 0) bytes_to_schedule = 0; + int bits_to_schedule = bytes_to_schedule * 8; - int bits_to_schedule = bytes_to_schedule * 8; + // if this UE has UL traffic + if (bits_to_schedule > 0) { + tbs = get_TBS_UL(UE_template->pre_assigned_mcs_ul, 3) << 3; // 1 or 2 PRB with cqi enabled does not work well! + rb_table_index = 2; + // fixme: set use_srs flag + tx_power = estimate_ue_tx_power(tbs, rb_table[rb_table_index], 0, Ncp, 0); - // if this UE has UL traffic - if (bits_to_schedule > 0) { - tbs = get_TBS_UL(UE_template->pre_assigned_mcs_ul, 3) << 3; // 1 or 2 PRB with cqi enabled does not work well! - rb_table_index = 2; - // fixme: set use_srs flag + while ((UE_template->phr_info - tx_power < 0 || tbs > bits_to_schedule) && UE_template->pre_assigned_mcs_ul > 3) { + // LOG_I(MAC,"UE_template->phr_info %d tx_power %d mcs %d\n", UE_template->phr_info,tx_power, mcs); + UE_template->pre_assigned_mcs_ul--; + tbs = get_TBS_UL(UE_template->pre_assigned_mcs_ul, rb_table[rb_table_index]) << 3; + tx_power = estimate_ue_tx_power(tbs, rb_table[rb_table_index], 0, Ncp, 0); // fixme: set use_srs + } + + first_rb_offset = UE_info->first_rb_offset[CC_id]; + available_rbs = N_RB_UL - 2 * first_rb[CC_id]; + + while (tbs < bits_to_schedule && + rb_table[rb_table_index] < available_rbs && + UE_template->phr_info - tx_power > 0 && + rb_table_index < 32) { + rb_table_index++; + tbs = get_TBS_UL(UE_template->pre_assigned_mcs_ul, rb_table[rb_table_index]) << 3; tx_power = estimate_ue_tx_power(tbs, rb_table[rb_table_index], 0, Ncp, 0); + } - while ((UE_template->phr_info - tx_power < 0 || tbs > bits_to_schedule) && UE_template->pre_assigned_mcs_ul > 3) { - // LOG_I(MAC,"UE_template->phr_info %d tx_power %d mcs %d\n", UE_template->phr_info,tx_power, mcs); - UE_template->pre_assigned_mcs_ul--; - tbs = get_TBS_UL(UE_template->pre_assigned_mcs_ul, rb_table[rb_table_index]) << 3; - tx_power = estimate_ue_tx_power(tbs, rb_table[rb_table_index], 0, Ncp, 0); // fixme: set use_srs - } + if (rb_table[rb_table_index] > (available_rbs - 1)) { + rb_table_index--; + } - first_rb_offset = UE_info->first_rb_offset[CC_id][slice_idx]; - available_rbs = N_RB_UL - 2 * first_rb[CC_id]; + // 1 or 2 PRB with cqi enabled does not work well + if (rb_table[rb_table_index] < 3) { + rb_table_index = 2; //3PRB + } - while (tbs < bits_to_schedule && - rb_table[rb_table_index] < available_rbs && - UE_template->phr_info - tx_power > 0 && - rb_table_index < 32) { - rb_table_index++; - tbs = get_TBS_UL(UE_template->pre_assigned_mcs_ul, rb_table[rb_table_index]) << 3; - tx_power = estimate_ue_tx_power(tbs, rb_table[rb_table_index], 0, Ncp, 0); - } - - if (rb_table[rb_table_index] > (available_rbs - 1)) { - rb_table_index--; - } - - // 1 or 2 PRB with cqi enabled does not work well - if (rb_table[rb_table_index] < 3) { - rb_table_index = 2; //3PRB - } - - UE_template->pre_allocated_rb_table_index_ul = rb_table_index; - UE_template->pre_allocated_nb_rb_ul[slice_idx] = rb_table[rb_table_index]; - LOG_D(MAC, "[eNB %d] frame %d subframe %d: for UE %d CC %d: pre-assigned mcs %d, pre-allocated rb_table[%d]=%d RBs (phr %d, tx power %d)\n", + UE_template->pre_allocated_rb_table_index_ul = rb_table_index; + UE_template->pre_allocated_nb_rb_ul = rb_table[rb_table_index]; + if (UE_template->pre_allocated_nb_rb_ul > 0) + LOG_W(MAC, "[eNB %d] frame %d subframe %d: for UE %d CC %d: pre-assigned mcs %d, pre-allocated rb_table[%d]=%d RBs (phr %d, tx power %d)\n", module_idP, frameP, subframeP, @@ -698,21 +589,20 @@ assign_max_mcs_min_rb(module_id_t module_idP, CC_id, UE_template->pre_assigned_mcs_ul, UE_template->pre_allocated_rb_table_index_ul, - UE_template->pre_allocated_nb_rb_ul[slice_idx], + UE_template->pre_allocated_nb_rb_ul, UE_template->phr_info, tx_power); + } else { + /* if UE has pending scheduling request then pre-allocate 3 RBs */ + //if (UE_template->ul_active == 1 && UE_template->ul_SR == 1) { + if (UE_is_to_be_scheduled(module_idP, CC_id, UE_id)) { + /* use QPSK mcs */ + UE_template->pre_assigned_mcs_ul = 10; + UE_template->pre_allocated_rb_table_index_ul = 2; + UE_template->pre_allocated_nb_rb_ul = 3; } else { - /* if UE has pending scheduling request then pre-allocate 3 RBs */ - //if (UE_template->ul_active == 1 && UE_template->ul_SR == 1) { - if (UE_is_to_be_scheduled(module_idP, CC_id, i)) { - /* use QPSK mcs */ - UE_template->pre_assigned_mcs_ul = 10; - UE_template->pre_allocated_rb_table_index_ul = 2; - UE_template->pre_allocated_nb_rb_ul[slice_idx] = 3; - } else { - UE_template->pre_assigned_mcs_ul = 0; - UE_template->pre_allocated_rb_table_index_ul = -1; - UE_template->pre_allocated_nb_rb_ul[slice_idx] = 0; - } + UE_template->pre_assigned_mcs_ul = 0; + UE_template->pre_allocated_rb_table_index_ul = -1; + UE_template->pre_allocated_nb_rb_ul = 0; } } } @@ -790,7 +680,6 @@ static int ue_ul_compare(const void *_a, const void *_b, void *_params) { * This function sorts the UEs in order, depending on their ulsch buffer and CQI */ void sort_ue_ul(module_id_t module_idP, - int slice_idx, int sched_frameP, sub_frame_t sched_subframeP, rnti_t *rntiTable) @@ -817,8 +706,7 @@ void sort_ue_ul(module_id_t module_idP, // Valid element and is not the actual CC_id in the list if (UE_info->active[i] == TRUE && rntiTable[i] != NOT_A_RNTI && - UE_info->UE_sched_ctrl[i].ul_out_of_sync != 1 && - ue_ul_slice_membership(module_idP, i, slice_idx)) { + UE_info->UE_sched_ctrl[i].ul_out_of_sync != 1) { list[list_size++] = i; // Add to list } } From 10bd164ad486c46e617ec1351b8bea892c5a51c4 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 7 Feb 2020 17:38:28 +0100 Subject: [PATCH 125/240] UL PP: Remove UE sorting and slicing --- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 59 ------- .../LAYER2/MAC/eNB_scheduler_primitives.c | 10 -- openair2/LAYER2/MAC/mac_proto.h | 12 -- openair2/LAYER2/MAC/pre_processor.c | 155 +----------------- 4 files changed, 1 insertion(+), 235 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 9d68d42ed3..6e0942c92d 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -86,31 +86,6 @@ add_ue_dlsch_info(module_id_t module_idP, return; } -//------------------------------------------------------------------------------ -int -schedule_next_dlue(module_id_t module_idP, - int CC_id, - sub_frame_t subframeP) -//------------------------------------------------------------------------------ -{ - int next_ue; - UE_list_t *UE_list = &RC.mac[module_idP]->UE_info.list; - - for (next_ue = UE_list->head; next_ue >= 0; next_ue = UE_list->next[next_ue]) { - if (eNB_dlsch_info[module_idP][CC_id][next_ue].status == S_DL_WAITING) { - return next_ue; - } - } - - for (next_ue = UE_list->head; next_ue >= 0; next_ue = UE_list->next[next_ue]) { - if (eNB_dlsch_info[module_idP][CC_id][next_ue].status == S_DL_BUFFERED) { - eNB_dlsch_info[module_idP][CC_id][next_ue].status = S_DL_WAITING; - } - } - - return (-1); //next_ue; -} - //------------------------------------------------------------------------------ int generate_dlsch_header(unsigned char *mac_header, @@ -2631,37 +2606,3 @@ schedule_PCH(module_id_t module_idP, stop_meas(&eNB->schedule_pch); return; } - -static int -slice_priority_compare(const void *_a, - const void *_b, - void *_c) { - const int slice_id1 = *(const int *) _a; - const int slice_id2 = *(const int *) _b; - const module_id_t Mod_id = *(int *) _c; - const slice_info_t *sli = &RC.mac[Mod_id]->slice_info; - - if (sli->dl[slice_id1].prio > sli->dl[slice_id2].prio) { - return -1; - } - - return 1; -} - -void -slice_priority_sort(module_id_t Mod_id, - int slice_list[MAX_NUM_SLICES]) { - int i; - int n_dl = RC.mac[Mod_id]->slice_info.n_dl; - - for (i = 0; i < n_dl; i++) { - slice_list[i] = i; - } - - qsort_r(slice_list, - n_dl, - sizeof(int), - slice_priority_compare, - &Mod_id); - return; -} diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index fdd4459c45..9072a3c872 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -5043,13 +5043,3 @@ harq_indication(module_id_t mod_idP, return; } - -// Flexran Slicing functions -//------------------------------------------------------------------------------ -uint16_t -nb_rbs_allowed_slice(float rb_percentage, - int total_rbs) -//------------------------------------------------------------------------------ -{ - return (uint16_t) floor(rb_percentage * total_rbs); -} diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index 0804dcd8c3..f9deeeae4f 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -448,14 +448,6 @@ uint8_t UE_is_to_be_scheduled(module_id_t module_idP, int CC_id, module_id_t schedule_next_ulue(module_id_t module_idP, int UE_id, sub_frame_t subframe); -/** \brief Round-robin scheduler for DLSCH traffic. -@param Mod_id Instance ID for eNB -@param subframe Subframe number on which to act -@returns UE index that is to be scheduled if needed/room -*/ -int schedule_next_dlue(module_id_t module_idP, int CC_id, - sub_frame_t subframe); - /* \brief Allocates a set of PRBS for a particular UE. This is a simple function for the moment, later it should process frequency-domain CQI information and/or PMI information. Currently it just returns the first PRBS that are available in the subframe based on the number requested. @param UE_id Index of UE on which to act @param nb_rb Number of PRBs allocated to UE by scheduler @@ -1218,10 +1210,6 @@ void pre_scd_nb_rbs_required( module_id_t module_idP, uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX]); #endif -/* Slice related functions */ -uint16_t nb_rbs_allowed_slice(float rb_percentage, int total_rbs); -int ue_ul_slice_membership(module_id_t mod_id, int UE_id, int slice_idx); - /* DRX Configuration */ /* Configure local DRX timers and thresholds in UE context, following the drx_configuration input */ void eNB_Config_Local_DRX(instance_t Mod_id, rrc_mac_drx_config_req_t *rrc_mac_drx_config_req); diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index a1cd64a7d5..d2b2f695e9 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -196,12 +196,6 @@ int round_robin_dl(module_id_t Mod_id, return n_rbg_sched; } -void -sort_ue_ul(module_id_t module_idP, - int sched_frameP, - sub_frame_t sched_subframeP, - rnti_t *rntiTable); - // This function stores the downlink buffer for all the logical channels void store_dlsch_buffer(module_id_t Mod_id, @@ -271,31 +265,6 @@ store_dlsch_buffer(module_id_t Mod_id, } } -int -maxround_ul(module_id_t Mod_id, uint16_t rnti, int sched_frame, - sub_frame_t sched_subframe) { - uint8_t round, round_max = 0, UE_id; - int CC_id, harq_pid; - UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; - COMMON_channels_t *cc; - - for (CC_id = 0; CC_id < RC.nb_mac_CC[Mod_id]; CC_id++) { - cc = &RC.mac[Mod_id]->common_channels[CC_id]; - UE_id = find_UE_id(Mod_id, rnti); - - if(UE_id == -1) - continue; - - harq_pid = subframe2harqpid(cc, sched_frame, sched_subframe); - round = UE_info->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid]; - - if (round > round_max) { - round_max = round; - } - } - - return round_max; -} // This function assigns pre-available RBS to each UE in specified sub-bands before scheduling is done void @@ -433,11 +402,7 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, UE_info_t *UE_info = &eNB->UE_info; const int N_RB_UL = to_prb(eNB->common_channels[CC_id].ul_Bandwidth); uint16_t available_rbs = N_RB_UL - 2 * first_rb[CC_id]; // top and bottom // - UE_info->first_rb_offset[CC_id]; - rnti_t rntiTable[MAX_MOBILES_PER_ENB]; - // sort ues - LOG_D(MAC, "In ulsch_preprocessor: sort ue \n"); - sort_ue_ul(module_idP, sched_frameP, sched_subframeP, rntiTable); // maximize MCS and then allocate required RB according to the buffer occupancy with the limit of max available UL RB LOG_D(MAC, "In ulsch_preprocessor: assign max mcs min rb\n"); assign_max_mcs_min_rb(module_idP, CC_id, frameP, subframeP, first_rb); @@ -474,10 +439,9 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, nb_allocated_rbs[UE_id] = cmin(UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul, average_rbs_per_user); total_allocated_rbs += nb_allocated_rbs[UE_id]; - LOG_D(MAC, "In ulsch_preprocessor: assigning %d RBs for UE %d/%x CCid %d, harq_pid %d\n", + LOG_D(MAC, "In ulsch_preprocessor: assigning %d RBs for UE %d CCid %d, harq_pid %d\n", nb_allocated_rbs[UE_id], UE_id, - rntiTable[UE_id], CC_id, harq_pid); } @@ -607,120 +571,3 @@ assign_max_mcs_min_rb(module_id_t module_idP, } } } - -struct sort_ue_ul_params { - int module_idP; - int sched_frameP; - int sched_subframeP; -}; - -static int ue_ul_compare(const void *_a, const void *_b, void *_params) { - struct sort_ue_ul_params *params = _params; - UE_info_t *UE_info = &RC.mac[params->module_idP]->UE_info; - int UE_id1 = *(const int *) _a; - int UE_id2 = *(const int *) _b; - int rnti1 = UE_RNTI(params->module_idP, UE_id1); - int pCCid1 = UE_PCCID(params->module_idP, UE_id1); - int round1 = maxround_ul(params->module_idP, rnti1, params->sched_frameP, - params->sched_subframeP); - int rnti2 = UE_RNTI(params->module_idP, UE_id2); - int pCCid2 = UE_PCCID(params->module_idP, UE_id2); - int round2 = maxround_ul(params->module_idP, rnti2, params->sched_frameP, - params->sched_subframeP); - - if (round1 > round2) - return -1; - - if (round1 < round2) - return 1; - - if (UE_info->UE_template[pCCid1][UE_id1].ul_buffer_info[LCGID0] > - UE_info->UE_template[pCCid2][UE_id2].ul_buffer_info[LCGID0]) - return -1; - - if (UE_info->UE_template[pCCid1][UE_id1].ul_buffer_info[LCGID0] < - UE_info->UE_template[pCCid2][UE_id2].ul_buffer_info[LCGID0]) - return 1; - - int bytes_to_schedule1 = UE_info->UE_template[pCCid1][UE_id1].estimated_ul_buffer - UE_info->UE_template[pCCid1][UE_id1].scheduled_ul_bytes; - - if (bytes_to_schedule1 < 0) bytes_to_schedule1 = 0; - - int bytes_to_schedule2 = UE_info->UE_template[pCCid2][UE_id2].estimated_ul_buffer - UE_info->UE_template[pCCid2][UE_id2].scheduled_ul_bytes; - - if (bytes_to_schedule2 < 0) bytes_to_schedule2 = 0; - - if (bytes_to_schedule1 > bytes_to_schedule2) - return -1; - - if (bytes_to_schedule1 < bytes_to_schedule2) - return 1; - - if (UE_info->UE_template[pCCid1][UE_id1].pre_assigned_mcs_ul > - UE_info->UE_template[pCCid2][UE_id2].pre_assigned_mcs_ul) - return -1; - - if (UE_info->UE_template[pCCid1][UE_id1].pre_assigned_mcs_ul < - UE_info->UE_template[pCCid2][UE_id2].pre_assigned_mcs_ul) - return 1; - - if (UE_info->UE_sched_ctrl[UE_id1].cqi_req_timer > - UE_info->UE_sched_ctrl[UE_id2].cqi_req_timer) - return -1; - - if (UE_info->UE_sched_ctrl[UE_id1].cqi_req_timer < - UE_info->UE_sched_ctrl[UE_id2].cqi_req_timer) - return 1; - - return 0; -} - -//----------------------------------------------------------------------------- -/* - * This function sorts the UEs in order, depending on their ulsch buffer and CQI - */ -void sort_ue_ul(module_id_t module_idP, - int sched_frameP, - sub_frame_t sched_subframeP, - rnti_t *rntiTable) -//----------------------------------------------------------------------------- -{ - int list[MAX_MOBILES_PER_ENB]; - int list_size = 0; - struct sort_ue_ul_params params = { module_idP, sched_frameP, sched_subframeP }; - UE_info_t *UE_info = &RC.mac[module_idP]->UE_info; - UE_sched_ctrl_t *UE_scheduling_control = NULL; - - for (int i = 0; i < MAX_MOBILES_PER_ENB; i++) { - UE_scheduling_control = &(UE_info->UE_sched_ctrl[i]); - - /* Check CDRX configuration and if UE is in active time for this subframe */ - if (UE_scheduling_control->cdrx_configured == TRUE) { - if (UE_scheduling_control->in_active_time == FALSE) { - continue; - } - } - - rntiTable[i] = UE_RNTI(module_idP, i); - - // Valid element and is not the actual CC_id in the list - if (UE_info->active[i] == TRUE && - rntiTable[i] != NOT_A_RNTI && - UE_info->UE_sched_ctrl[i].ul_out_of_sync != 1) { - list[list_size++] = i; // Add to list - } - } - - qsort_r(list, list_size, sizeof(int), ue_ul_compare, ¶ms); - - if (list_size) { // At mimimum one list element - for (int i = 0; i < list_size - 1; i++) { - UE_info->list.next[list[i]] = list[i + 1]; - } - - UE_info->list.next[list[list_size - 1]] = -1; - UE_info->list.head = list[0]; - } else { // No element - UE_info->list.head = -1; - } -} From 8a84e2d92e1b2131052feeaa109ab4b0a33842a8 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 7 Feb 2020 16:06:33 +0100 Subject: [PATCH 126/240] Rewrite assign_max_mcs_min_rb() more concisely --- openair2/LAYER2/MAC/pre_processor.c | 171 ++++++++++++++-------------- 1 file changed, 88 insertions(+), 83 deletions(-) diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index d2b2f695e9..9f5d029955 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -474,100 +474,105 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, } } +void calculate_max_mcs_min_rb(module_id_t mod_id, + int CC_id, + int bytes, + int phr, + int max_mcs, + int *mcs, + int max_rbs, + int *rb_index, + int *tx_power) { + const int Ncp = RC.mac[mod_id]->common_channels[CC_id].Ncp; + /* TODO shouldn't we consider the SRS or other quality indicators? */ + *mcs = max_mcs; + *rb_index = 2; + int tbs = get_TBS_UL(*mcs, rb_table[*rb_index]); + + // fixme: set use_srs flag + *tx_power = estimate_ue_tx_power(tbs * 8, rb_table[*rb_index], 0, Ncp, 0); + + /* find maximum MCS */ + while ((phr - *tx_power < 0 || tbs > bytes) && *mcs > 3) { + mcs--; + tbs = get_TBS_UL(*mcs, rb_table[*rb_index]); + *tx_power = estimate_ue_tx_power(tbs * 8, rb_table[*rb_index], 0, Ncp, 0); + } + + /* find minimum necessary RBs */ + while (tbs < bytes + && *rb_index < 32 + && rb_table[*rb_index] < max_rbs + && phr - *tx_power > 0) { + (*rb_index)++; + tbs = get_TBS_UL(*mcs, rb_table[*rb_index]); + *tx_power = estimate_ue_tx_power(tbs * 8, rb_table[*rb_index], 0, Ncp, 0); + } + + /* Decrease if we went to far in last iteration */ + if (rb_table[*rb_index] > max_rbs) + (*rb_index)--; + + // 1 or 2 PRB with cqi enabled does not work well + if (rb_table[*rb_index] < 3) { + *rb_index = 2; //3PRB + } +} + void assign_max_mcs_min_rb(module_id_t module_idP, int CC_id, int frameP, sub_frame_t subframeP, uint16_t *first_rb) { - int mcs; - int rb_table_index = 0, tbs, tx_power; - eNB_MAC_INST *eNB = RC.mac[module_idP]; - UE_info_t *UE_info = &eNB->UE_info; - slice_info_t *sli = &eNB->slice_info; - UE_TEMPLATE *UE_template; - UE_sched_ctrl_t *ue_sched_ctl; - int Ncp; - int N_RB_UL; - int first_rb_offset, available_rbs; + const int N_RB_UL = to_prb(RC.mac[module_idP]->common_channels[CC_id].ul_Bandwidth); + const int available_rbs = N_RB_UL - 2 * first_rb[CC_id]; // top and bottom - UE_info->first_rb_offset[CC_id]; + const int Ncp = RC.mac[module_idP]->common_channels[CC_id].Ncp; + UE_info_t *UE_info = &RC.mac[module_idP]->UE_info; for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { - /* if we've received the power headroom information the UE, we can go to - * maximum mcs */ - mcs = UE_info->UE_sched_ctrl[UE_id].phr_received == 1 ? 20 : 10; + UE_TEMPLATE *UE_template = &UE_info->UE_template[CC_id][UE_id]; - UE_template = &UE_info->UE_template[CC_id][UE_id]; - UE_template->pre_assigned_mcs_ul = mcs; - ue_sched_ctl = &UE_info->UE_sched_ctrl[UE_id]; - Ncp = eNB->common_channels[CC_id].Ncp; - N_RB_UL = to_prb(eNB->common_channels[CC_id].ul_Bandwidth); - int bytes_to_schedule = UE_template->estimated_ul_buffer - UE_template->scheduled_ul_bytes; + const int B = cmax(UE_template->estimated_ul_buffer - UE_template->scheduled_ul_bytes, 0); - if (bytes_to_schedule < 0) bytes_to_schedule = 0; + const int UE_to_be_scheduled = UE_is_to_be_scheduled(module_idP, CC_id, UE_id); + if (B == 0 && !UE_to_be_scheduled) + continue; - int bits_to_schedule = bytes_to_schedule * 8; - - // if this UE has UL traffic - if (bits_to_schedule > 0) { - tbs = get_TBS_UL(UE_template->pre_assigned_mcs_ul, 3) << 3; // 1 or 2 PRB with cqi enabled does not work well! - rb_table_index = 2; - // fixme: set use_srs flag - tx_power = estimate_ue_tx_power(tbs, rb_table[rb_table_index], 0, Ncp, 0); - - while ((UE_template->phr_info - tx_power < 0 || tbs > bits_to_schedule) && UE_template->pre_assigned_mcs_ul > 3) { - // LOG_I(MAC,"UE_template->phr_info %d tx_power %d mcs %d\n", UE_template->phr_info,tx_power, mcs); - UE_template->pre_assigned_mcs_ul--; - tbs = get_TBS_UL(UE_template->pre_assigned_mcs_ul, rb_table[rb_table_index]) << 3; - tx_power = estimate_ue_tx_power(tbs, rb_table[rb_table_index], 0, Ncp, 0); // fixme: set use_srs - } - - first_rb_offset = UE_info->first_rb_offset[CC_id]; - available_rbs = N_RB_UL - 2 * first_rb[CC_id]; - - while (tbs < bits_to_schedule && - rb_table[rb_table_index] < available_rbs && - UE_template->phr_info - tx_power > 0 && - rb_table_index < 32) { - rb_table_index++; - tbs = get_TBS_UL(UE_template->pre_assigned_mcs_ul, rb_table[rb_table_index]) << 3; - tx_power = estimate_ue_tx_power(tbs, rb_table[rb_table_index], 0, Ncp, 0); - } - - if (rb_table[rb_table_index] > (available_rbs - 1)) { - rb_table_index--; - } - - // 1 or 2 PRB with cqi enabled does not work well - if (rb_table[rb_table_index] < 3) { - rb_table_index = 2; //3PRB - } - - UE_template->pre_allocated_rb_table_index_ul = rb_table_index; - UE_template->pre_allocated_nb_rb_ul = rb_table[rb_table_index]; - if (UE_template->pre_allocated_nb_rb_ul > 0) - LOG_W(MAC, "[eNB %d] frame %d subframe %d: for UE %d CC %d: pre-assigned mcs %d, pre-allocated rb_table[%d]=%d RBs (phr %d, tx power %d)\n", - module_idP, - frameP, - subframeP, - UE_id, - CC_id, - UE_template->pre_assigned_mcs_ul, - UE_template->pre_allocated_rb_table_index_ul, - UE_template->pre_allocated_nb_rb_ul, - UE_template->phr_info, tx_power); - } else { - /* if UE has pending scheduling request then pre-allocate 3 RBs */ - //if (UE_template->ul_active == 1 && UE_template->ul_SR == 1) { - if (UE_is_to_be_scheduled(module_idP, CC_id, UE_id)) { - /* use QPSK mcs */ - UE_template->pre_assigned_mcs_ul = 10; - UE_template->pre_allocated_rb_table_index_ul = 2; - UE_template->pre_allocated_nb_rb_ul = 3; - } else { - UE_template->pre_assigned_mcs_ul = 0; - UE_template->pre_allocated_rb_table_index_ul = -1; - UE_template->pre_allocated_nb_rb_ul = 0; - } + /* if UE has pending scheduling request then pre-allocate 3 RBs */ + if (B == 0 && UE_to_be_scheduled) { + UE_template->pre_assigned_mcs_ul = 10; /* use QPSK mcs only */ + UE_template->pre_allocated_rb_table_index_ul = 2; + UE_template->pre_allocated_nb_rb_ul = 3; + continue; } + + int mcs; + int rb_table_index; + int tx_power; + calculate_max_mcs_min_rb( + module_idP, + CC_id, + B, + UE_template->phr_info, + UE_info->UE_sched_ctrl[UE_id].phr_received == 1 ? 20 : 10, + &mcs, + available_rbs, + &rb_table_index, + &tx_power); + + UE_template->pre_assigned_mcs_ul = mcs; + UE_template->pre_allocated_rb_table_index_ul = rb_table_index; + UE_template->pre_allocated_nb_rb_ul = rb_table[rb_table_index]; + LOG_D(MAC, "[eNB %d] frame %d subframe %d: for UE %d CC %d: pre-assigned mcs %d, pre-allocated rb_table[%d]=%d RBs (phr %d, tx power %d)\n", + module_idP, + frameP, + subframeP, + UE_id, + CC_id, + UE_template->pre_assigned_mcs_ul, + UE_template->pre_allocated_rb_table_index_ul, + UE_template->pre_allocated_nb_rb_ul, + UE_template->phr_info, tx_power); } } From 8bf7a13ffaeffd85a7aab210673c95d35cc9a6e1 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 26 Feb 2020 16:41:10 +0100 Subject: [PATCH 127/240] Remove first_rb from ULSCH scheduler --- openair2/LAYER2/MAC/eNB_scheduler_ulsch.c | 131 ++++++++-------------- openair2/LAYER2/MAC/mac.h | 3 +- openair2/LAYER2/MAC/mac_proto.h | 8 +- openair2/LAYER2/MAC/pre_processor.c | 31 +++-- 4 files changed, 72 insertions(+), 101 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index a6083fbf1c..16127ad603 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -1099,14 +1099,12 @@ schedule_ulsch(module_id_t module_idP, sub_frame_t subframeP) //----------------------------------------------------------------------------- { - uint16_t first_rb[NFAPI_CC_MAX]; eNB_MAC_INST *mac = NULL; COMMON_channels_t *cc = NULL; int sched_subframe; int sched_frame; /* Init */ mac = RC.mac[module_idP]; - memset(first_rb, 0, NFAPI_CC_MAX * sizeof(uint16_t)); start_meas(&(mac->schedule_ulsch)); sched_subframe = (subframeP + 4) % 10; sched_frame = frameP; @@ -1213,9 +1211,6 @@ schedule_ulsch(module_id_t module_idP, /* Note: RC.nb_mac_CC[module_idP] should be lower than or equal to NFAPI_CC_MAX */ for (int CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; CC_id++, cc++) { - first_rb[CC_id] = (emtc_active[CC_id] == 1) ? 7 : 1; - RA_t *ra_ptr = cc->ra; - /* From Louis-Adrien to François: * The comment bloc below is to configure with a command line. * I took it from the equivalent part in the fairRR scheduler (around line 2578 in eNB_scheduler_fairRR.c). @@ -1226,6 +1221,7 @@ schedule_ulsch(module_id_t module_idP, * I think it should be sched_frame instead. This parameter has only impacts in case TDD and preamble format 4. * To confirm. */ + /* TODO: update vrb_map_UL here? */ /* int start_rb = 0; int nb_rb = 6; @@ -1242,27 +1238,41 @@ schedule_ulsch(module_id_t module_idP, } */ - /* - * Check if RA (Msg3) is active in this subframeP, if so skip the PRB used for Msg3 - * Msg3 is using 1 PRB so we need to increase first_rb accordingly - * Not sure about the break (can there be more than 1 active RA procedure per CC_id and per subframe?) + /* HACK: let's remove the PUCCH from available RBs + * we suppose PUCCH size is: + * - for 25 RBs: 1 RB (top and bottom of ressource grid) + * - for 50: 2 RBs + * - for 100: 3 RBs + * This is totally arbitrary and might even be wrong. */ - for (int ra_index = 0; ra_index < NB_RA_PROC_MAX; ra_index++, ra_ptr++) { - if ((ra_ptr->state == WAITMSG3) && (ra_ptr->Msg3_subframe == sched_subframe)) { - if (first_rb[CC_id] < ra_ptr->msg3_first_rb + ra_ptr->msg3_nb_rb) { - first_rb[CC_id] = ra_ptr->msg3_first_rb + ra_ptr->msg3_nb_rb; - } + switch (to_prb(cc[CC_id].ul_Bandwidth)) { + case 25: + cc[CC_id].vrb_map_UL[0] = 1; + cc[CC_id].vrb_map_UL[24] = 1; + break; - /* Louis-Adrien: I couldn't find an interdiction of multiple Msg3 scheduling - * on the same time resources. Also the performance improvement of breaking is low, - * since we will loop until the end, most of the time. - * I'm letting the break as a reminder, in case of misunderstanding the spec. - */ - // break; - } + case 50: + cc[CC_id].vrb_map_UL[0] = 1; + cc[CC_id].vrb_map_UL[1] = 1; + cc[CC_id].vrb_map_UL[48] = 1; + cc[CC_id].vrb_map_UL[49] = 1; + break; + + case 100: + cc[CC_id].vrb_map_UL[0] = 1; + cc[CC_id].vrb_map_UL[1] = 1; + cc[CC_id].vrb_map_UL[2] = 1; + cc[CC_id].vrb_map_UL[97] = 1; + cc[CC_id].vrb_map_UL[98] = 1; + cc[CC_id].vrb_map_UL[99] = 1; + break; + + default: + LOG_E(MAC, "RBs setting not handled. Todo.\n"); + exit(1); } - schedule_ulsch_rnti(module_idP, CC_id, frameP, subframeP, sched_subframe, first_rb); + schedule_ulsch_rnti(module_idP, CC_id, frameP, subframeP, sched_subframe); } stop_meas(&mac->schedule_ulsch); @@ -1277,8 +1287,7 @@ schedule_ulsch_rnti(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t subframeP, - unsigned char sched_subframeP, - uint16_t *first_rb) { + unsigned char sched_subframeP) { const uint8_t aggregation = 2; /* TODO: does this need to be static? */ static int32_t tpc_accumulated = 0; @@ -1306,43 +1315,13 @@ schedule_ulsch_rnti(module_id_t module_idP, nfapi_ul_config_ulsch_harq_information *ulsch_harq_information; hi_dci0_req->sfn_sf = (frameP << 4) + subframeP; - int n_rb_ul_tab = to_prb(cc[CC_id].ul_Bandwidth); - /* HACK: let's remove the PUCCH from available RBs - * we suppose PUCCH size is: - * - for 25 RBs: 1 RB (top and bottom of ressource grid) - * - for 50: 2 RBs - * - for 100: 3 RBs - * This is totally arbitrary and might even be wrong. - * We suppose 'first_rb[]' has been correctly populated by the caller, - * so we only remove the top part of the resource grid. - */ - switch (n_rb_ul_tab) { - case 25: - n_rb_ul_tab -= 1; - break; - - case 50: - n_rb_ul_tab -= 2; - break; - - case 100: - n_rb_ul_tab -= 3; - break; - - default: - LOG_E(MAC, "RBs setting not handled. Todo.\n"); - exit(1); - } - - UE_info->first_rb_offset[CC_id] = n_rb_ul_tab; - /* * ULSCH preprocessor: set UE_template-> * pre_allocated_nb_rb_ul[slice_idx] * pre_assigned_mcs_ul * pre_allocated_rb_table_index_ul */ - ulsch_scheduler_pre_processor(module_idP, CC_id, frameP, subframeP, sched_frame, sched_subframeP, first_rb); + ulsch_scheduler_pre_processor(module_idP, CC_id, frameP, subframeP, sched_frame, sched_subframeP); for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { if (UE_info->UE_template[CC_id][UE_id].rach_resource_type > 0) @@ -1382,9 +1361,8 @@ schedule_ulsch_rnti(module_id_t module_idP, UE_id, rnti); LOG_D(MAC, - "[eNB %d] %d.%d (sched_frame %d, sched_subframe %d), " - "Checking PUSCH %d for UE %d/%x CC %d : aggregation level %d, " - "N_RB_UL %d\n", + "[eNB %d] %d.%d (sched %d.%d), " + "Checking PUSCH %d for UE %d/%x CC %d : aggregation level %d\n", module_idP, frameP, subframeP, @@ -1394,8 +1372,7 @@ schedule_ulsch_rnti(module_id_t module_idP, UE_id, rnti, CC_id, - aggregation, - n_rb_ul_tab); + aggregation); /* Seems unused, only for debug */ RC.eNB[module_idP][CC_id]->pusch_stats_BO[UE_id][(frameP * 10) + subframeP] = UE_template_ptr->estimated_ul_buffer; @@ -1570,11 +1547,8 @@ schedule_ulsch_rnti(module_id_t module_idP, UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2 = UE_template_ptr->mcs_UL[harq_pid]; - while (((rb_table[rb_table_index] > (n_rb_ul_tab - first_rb[CC_id])) - || (rb_table[rb_table_index] > 45)) - && (rb_table_index > 0)) { + while (rb_table[rb_table_index] > 45 && rb_table_index > 0) rb_table_index--; - } UE_template_ptr->TBS_UL[harq_pid] = get_TBS_UL(UE_template_ptr->mcs_UL[harq_pid], rb_table[rb_table_index]); UE_info->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx += rb_table[rb_table_index]; @@ -1588,13 +1562,12 @@ schedule_ulsch_rnti(module_id_t module_idP, T_INT(subframeP), T_INT(harq_pid), T_INT(UE_template_ptr->mcs_UL[harq_pid]), - T_INT(first_rb[CC_id]), T_INT(rb_table[rb_table_index]), T_INT(UE_template_ptr->TBS_UL[harq_pid]), T_INT(ndi)); /* Store information for possible retransmission */ UE_template_ptr->nb_rb_ul[harq_pid] = rb_table[rb_table_index]; - UE_template_ptr->first_rb_ul[harq_pid] = first_rb[CC_id]; + UE_template_ptr->first_rb_ul[harq_pid] = UE_template_ptr->pre_first_nb_rb_ul; UE_template_ptr->cqi_req[harq_pid] = cqi_req; UE_sched_ctrl_ptr->ul_scheduled |= (1 << harq_pid); @@ -1632,7 +1605,7 @@ schedule_ulsch_rnti(module_id_t module_idP, hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation; hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti; hi_dci0_pdu->dci_pdu.dci_pdu_rel8.transmission_power = 6000; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.resource_block_start = first_rb[CC_id]; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.resource_block_start = UE_template_ptr->pre_first_nb_rb_ul; hi_dci0_pdu->dci_pdu.dci_pdu_rel8.number_of_resource_block = rb_table[rb_table_index]; hi_dci0_pdu->dci_pdu.dci_pdu_rel8.mcs_1 = @@ -1688,7 +1661,7 @@ schedule_ulsch_rnti(module_id_t module_idP, get_tmode(module_idP, CC_id, UE_id), mac->ul_handle, rnti, - first_rb[CC_id], // resource_block_start + UE_template_ptr->pre_first_nb_rb_ul, // resource_block_start rb_table[rb_table_index], // number_of_resource_blocks UE_template_ptr->mcs_UL[harq_pid], cshift, // cyclic_shift_2_for_drms @@ -1757,8 +1730,6 @@ schedule_ulsch_rnti(module_id_t module_idP, cqi_req, UE_id, rnti); - /* Increment first rb for next UE allocation */ - first_rb[CC_id] += rb_table[rb_table_index]; } else { // round_index > 0 => retransmission T(T_ENB_MAC_UE_UL_SCHEDULE_RETRANSMISSION, T_INT(module_idP), @@ -1868,20 +1839,6 @@ schedule_ulsch_rnti(module_id_t module_idP, sched_frame, sched_subframeP, cqi_req); - - /* HACK: RBs used by retransmission have to be reserved. - * The current mechanism uses the notion of 'first_rb', so - * we skip all RBs below the ones retransmitted. This is - * not correct. Imagine only RB 23 is retransmitted, then all - * RBs < 23 will be marked unusable for new transmissions (case where - * round == 0). Note also that this code works only if the preprocessor - * orders UEs with retransmission with higher priority than UEs with new - * transmission. - * All this should be cleaned up properly. - */ - if (first_rb[CC_id] < UE_template_ptr->first_rb_ul[harq_pid] + UE_template_ptr->nb_rb_ul[harq_pid]) - first_rb[CC_id] = UE_template_ptr->first_rb_ul[harq_pid] - + UE_template_ptr->nb_rb_ul[harq_pid]; } // end of round > 0 } // loop over UE_ids } @@ -2018,6 +1975,12 @@ void schedule_ulsch_rnti_emtc(module_id_t module_idP, UE_sched_ctrl->cqi_req_timer); /* Reset the scheduling request */ emtc_active[CC_id] = 1; + cc[CC_id].vrb_map_UL[1] = 1; + cc[CC_id].vrb_map_UL[2] = 1; + cc[CC_id].vrb_map_UL[3] = 1; + cc[CC_id].vrb_map_UL[4] = 1; + cc[CC_id].vrb_map_UL[5] = 1; + cc[CC_id].vrb_map_UL[6] = 1; UE_template->ul_SR = 0; status = mac_eNB_get_rrc_status(module_idP,rnti); cqi_req = 0; diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h index 0a7e616d91..16a1d8ec17 100644 --- a/openair2/LAYER2/MAC/mac.h +++ b/openair2/LAYER2/MAC/mac.h @@ -825,6 +825,8 @@ typedef struct { /// Number of Allocated RBs by the ulsch preprocessor uint8_t pre_allocated_nb_rb_ul; + /// Start of Allocated RBs by the USLCH preprocessor + uint8_t pre_first_nb_rb_ul; /// index of Allocated RBs by the ulsch preprocessor int8_t pre_allocated_rb_table_index_ul; @@ -1147,7 +1149,6 @@ typedef struct { /// Sorting criteria for the UE list in the MAC preprocessor uint16_t sorting_criteria[MAX_NUM_SLICES][CR_NUM]; - uint16_t first_rb_offset[NFAPI_CC_MAX]; } UE_info_t; /*! \brief deleting control information*/ diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index f9deeeae4f..ed4c2be024 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -129,8 +129,7 @@ void schedule_ulsch(module_id_t module_idP, frame_t frameP, */ void schedule_ulsch_rnti(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t subframe, - unsigned char sched_subframe, - uint16_t *first_rb); + unsigned char sched_subframe); void schedule_ulsch_rnti_emtc(module_id_t module_idP, frame_t frameP, @@ -674,15 +673,14 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, int frameP, sub_frame_t subframeP, int sched_frameP, - unsigned char sched_subframeP, - uint16_t *first_rb); + unsigned char sched_subframeP); void store_ulsch_buffer(module_id_t module_idP, int frameP, sub_frame_t subframeP); void assign_max_mcs_min_rb(module_id_t module_idP, int CC_id, int frameP, sub_frame_t subframeP, - uint16_t *first_rb); + int available_rbs); void adjust_bsr_info(int buffer_occupancy, uint16_t TBS, UE_TEMPLATE *UE_template); diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 9f5d029955..8563120856 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -391,21 +391,30 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, int frameP, sub_frame_t subframeP, int sched_frameP, - unsigned char sched_subframeP, - uint16_t *first_rb) { + unsigned char sched_subframeP) { uint16_t nb_allocated_rbs[MAX_MOBILES_PER_ENB]; uint16_t total_allocated_rbs = 0; uint16_t average_rbs_per_user = 0; int16_t total_remaining_rbs = 0; uint16_t total_ue_count = 0; - eNB_MAC_INST *eNB = RC.mac[module_idP]; - UE_info_t *UE_info = &eNB->UE_info; - const int N_RB_UL = to_prb(eNB->common_channels[CC_id].ul_Bandwidth); - uint16_t available_rbs = N_RB_UL - 2 * first_rb[CC_id]; // top and bottom // - UE_info->first_rb_offset[CC_id]; - // maximize MCS and then allocate required RB according to the buffer occupancy with the limit of max available UL RB + UE_info_t *UE_info = &RC.mac[module_idP]->UE_info; + const int N_RB_UL = to_prb(RC.mac[module_idP]->common_channels[CC_id].ul_Bandwidth); + const COMMON_channels_t *cc = &RC.mac[module_idP]->common_channels[CC_id]; + int available_rbs = 0; + int first_rb = -1; + for (int i = 0; i < N_RB_UL; ++i) { + if (cc->vrb_map_UL[i] == 0) { + available_rbs++; + if (first_rb < 0) + first_rb = i; + } + } + + // maximize MCS and then allocate required RB according to the buffer + // occupancy with the limit of max available UL RB LOG_D(MAC, "In ulsch_preprocessor: assign max mcs min rb\n"); - assign_max_mcs_min_rb(module_idP, CC_id, frameP, subframeP, first_rb); + assign_max_mcs_min_rb(module_idP, CC_id, frameP, subframeP, available_rbs); for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { if (UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul > 0) { @@ -462,7 +471,9 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, total_allocated_rbs++; } + UE_template->pre_first_nb_rb_ul = first_rb; UE_template->pre_allocated_nb_rb_ul = nb_allocated_rbs[UE_id]; + first_rb += nb_allocated_rbs[UE_id]; LOG_D(MAC, "******************UL Scheduling Information for UE%d CC_id %d ************************\n", UE_id, CC_id); @@ -524,9 +535,7 @@ assign_max_mcs_min_rb(module_id_t module_idP, int CC_id, int frameP, sub_frame_t subframeP, - uint16_t *first_rb) { - const int N_RB_UL = to_prb(RC.mac[module_idP]->common_channels[CC_id].ul_Bandwidth); - const int available_rbs = N_RB_UL - 2 * first_rb[CC_id]; // top and bottom - UE_info->first_rb_offset[CC_id]; + int available_rbs) { const int Ncp = RC.mac[module_idP]->common_channels[CC_id].Ncp; UE_info_t *UE_info = &RC.mac[module_idP]->UE_info; From abc65b1d868432ee1c9a7597b51f247c87836ba9 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 27 Feb 2020 16:47:11 +0100 Subject: [PATCH 128/240] Reimplement UL PP --- openair2/LAYER2/MAC/mac.h | 8 + openair2/LAYER2/MAC/mac_proto.h | 9 - openair2/LAYER2/MAC/pre_processor.c | 467 ++++++++++++++++++++-------- 3 files changed, 352 insertions(+), 132 deletions(-) diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h index 16a1d8ec17..feba483147 100644 --- a/openair2/LAYER2/MAC/mac.h +++ b/openair2/LAYER2/MAC/mac.h @@ -1262,6 +1262,14 @@ typedef struct { uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]; } slice_info_t; +/** + * describes contiguous RBs + */ +typedef struct { + int start; + int length; +} contig_rbs_t; + /*! \brief eNB common channels */ typedef struct { int physCellId; diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index ed4c2be024..650d5999e1 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -674,15 +674,6 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, sub_frame_t subframeP, int sched_frameP, unsigned char sched_subframeP); -void store_ulsch_buffer(module_id_t module_idP, int frameP, - sub_frame_t subframeP); -void assign_max_mcs_min_rb(module_id_t module_idP, - int CC_id, - int frameP, - sub_frame_t subframeP, - int available_rbs); -void adjust_bsr_info(int buffer_occupancy, uint16_t TBS, - UE_TEMPLATE *UE_template); int phy_stats_exist(module_id_t Mod_id, int rnti); diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 8563120856..613edf9127 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -380,111 +380,12 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, } } if (print) - LOG_I(MAC, "%4d.%d DL scheduler allocation list: %s\n", frameP, subframeP, t); + LOG_D(MAC, "%4d.%d DL scheduler allocation list: %s\n", frameP, subframeP, t); #endif } /// ULSCH PRE_PROCESSOR -void ulsch_scheduler_pre_processor(module_id_t module_idP, - int CC_id, - int frameP, - sub_frame_t subframeP, - int sched_frameP, - unsigned char sched_subframeP) { - uint16_t nb_allocated_rbs[MAX_MOBILES_PER_ENB]; - uint16_t total_allocated_rbs = 0; - uint16_t average_rbs_per_user = 0; - int16_t total_remaining_rbs = 0; - uint16_t total_ue_count = 0; - - UE_info_t *UE_info = &RC.mac[module_idP]->UE_info; - const int N_RB_UL = to_prb(RC.mac[module_idP]->common_channels[CC_id].ul_Bandwidth); - const COMMON_channels_t *cc = &RC.mac[module_idP]->common_channels[CC_id]; - int available_rbs = 0; - int first_rb = -1; - for (int i = 0; i < N_RB_UL; ++i) { - if (cc->vrb_map_UL[i] == 0) { - available_rbs++; - if (first_rb < 0) - first_rb = i; - } - } - - // maximize MCS and then allocate required RB according to the buffer - // occupancy with the limit of max available UL RB - LOG_D(MAC, "In ulsch_preprocessor: assign max mcs min rb\n"); - assign_max_mcs_min_rb(module_idP, CC_id, frameP, subframeP, available_rbs); - - for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { - if (UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul > 0) { - total_ue_count++; - } - } - - if (total_ue_count == 0) - average_rbs_per_user = 0; - else if (total_ue_count == 1) - average_rbs_per_user = available_rbs + 1; - else if (total_ue_count <= available_rbs) - average_rbs_per_user = (uint16_t) floor(available_rbs / total_ue_count); - else - average_rbs_per_user = 1; - - if (total_ue_count > 0) - LOG_D(MAC, "[eNB %d] Frame %d subframe %d: total ue to be scheduled %d\n", - module_idP, - frameP, - subframeP, - total_ue_count); - - for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { - uint8_t harq_pid = subframe2harqpid(&RC.mac[module_idP]->common_channels[CC_id], - sched_frameP, sched_subframeP); - - if (UE_info->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid] > 0) - nb_allocated_rbs[UE_id] = UE_info->UE_template[CC_id][UE_id].nb_rb_ul[harq_pid]; - else - nb_allocated_rbs[UE_id] = cmin(UE_info->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul, average_rbs_per_user); - - total_allocated_rbs += nb_allocated_rbs[UE_id]; - LOG_D(MAC, "In ulsch_preprocessor: assigning %d RBs for UE %d CCid %d, harq_pid %d\n", - nb_allocated_rbs[UE_id], - UE_id, - CC_id, - harq_pid); - } - - for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { - UE_TEMPLATE *UE_template = &UE_info->UE_template[CC_id][UE_id]; - total_remaining_rbs = available_rbs - total_allocated_rbs; - - /* TODO this has already been accounted for - do we need it again? */ - //if (total_ue_count == 1) - // total_remaining_rbs++; - - while (UE_template->pre_allocated_nb_rb_ul > 0 && - nb_allocated_rbs[UE_id] < UE_template->pre_allocated_nb_rb_ul && - total_remaining_rbs > 0) { - nb_allocated_rbs[UE_id] = cmin(nb_allocated_rbs[UE_id] + 1, UE_template->pre_allocated_nb_rb_ul); - total_remaining_rbs--; - total_allocated_rbs++; - } - - UE_template->pre_first_nb_rb_ul = first_rb; - UE_template->pre_allocated_nb_rb_ul = nb_allocated_rbs[UE_id]; - first_rb += nb_allocated_rbs[UE_id]; - LOG_D(MAC, "******************UL Scheduling Information for UE%d CC_id %d ************************\n", - UE_id, - CC_id); - LOG_D(MAC, "[eNB %d] total RB allocated for UE%d CC_id %d = %d\n", - module_idP, - UE_id, - CC_id, - UE_template->pre_allocated_nb_rb_ul); - } -} - void calculate_max_mcs_min_rb(module_id_t mod_id, int CC_id, int bytes, @@ -530,29 +431,106 @@ void calculate_max_mcs_min_rb(module_id_t mod_id, } } -void -assign_max_mcs_min_rb(module_id_t module_idP, - int CC_id, - int frameP, - sub_frame_t subframeP, - int available_rbs) { - const int Ncp = RC.mac[module_idP]->common_channels[CC_id].Ncp; - UE_info_t *UE_info = &RC.mac[module_idP]->UE_info; +int pp_find_rb_table_index(int approximate) { + int lo = 2; + if (approximate <= rb_table[lo]) + return lo; + int hi = sizeof(rb_table) - 1; + if (approximate >= rb_table[hi]) + return hi; + int p = (hi + lo) / 2; + for (; lo + 1 != hi; p = (hi + lo) / 2) { + if (approximate <= rb_table[p]) + hi = p; + else + lo = p; + } + return p + 1; +} - for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { +int g_start_ue_ul = -1; +int round_robin_ul(module_id_t Mod_id, + int CC_id, + int frame, + int subframe, + int sched_frame, + int sched_subframe, + UE_list_t *UE_list, + int max_num_ue, + int num_contig_rb, + contig_rbs_t *rbs) { + AssertFatal(num_contig_rb <= 2, "cannot handle more than two contiguous RB regions\n"); + UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; + const int max_rb = num_contig_rb > 1 ? MAX(rbs[0].length, rbs[1].length) : rbs[0].length; + + /* for every UE: check whether we have to handle a retransmission (and + * allocate, if so). If not, compute how much RBs this UE would need */ + int rb_idx_required[MAX_MOBILES_PER_ENB]; + memset(rb_idx_required, 0, sizeof(rb_idx_required)); + int num_ue_req = 0; + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { UE_TEMPLATE *UE_template = &UE_info->UE_template[CC_id][UE_id]; + uint8_t harq_pid = subframe2harqpid(&RC.mac[Mod_id]->common_channels[CC_id], + sched_frame, sched_subframe); + if (UE_info->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid] > 0) { + /* this UE has a retransmission, allocate it right away */ + const int nb_rb = UE_template->nb_rb_ul[harq_pid]; + if (nb_rb == 0) { + LOG_E(MAC, + "%4d.%d UE %d retransmission of 0 RBs in round %d, ignoring\n", + sched_frame, sched_subframe, UE_id, + UE_info->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid]); + continue; + } + if (rbs[0].length >= nb_rb) { // fits in first contiguous region + UE_template->pre_first_nb_rb_ul = rbs[0].start; + rbs[0].length -= nb_rb; + rbs[0].start += nb_rb; + } else if (num_contig_rb == 2 && rbs[1].length >= nb_rb) { // in second + UE_template->pre_first_nb_rb_ul = rbs[1].start; + rbs[1].length -= nb_rb; + rbs[1].start += nb_rb; + } else if (num_contig_rb == 2 + && rbs[1].start + rbs[1].length - rbs[0].start >= nb_rb) { // overlapping the middle + UE_template->pre_first_nb_rb_ul = rbs[0].start; + rbs[0].length = 0; + int ol = nb_rb - (rbs[1].start - rbs[0].start); // how much overlap in second region + if (ol > 0) { + rbs[1].length -= ol; + rbs[1].start += ol; + } + } else { + LOG_W(MAC, + "cannot allocate UL retransmission for UE %d (nb_rb %d)\n", + UE_id, + nb_rb); + continue; + } + LOG_D(MAC, "%4d.%d UE %d retx %d RBs at start %d\n", + sched_frame, + sched_subframe, + UE_id, + UE_template->pre_allocated_nb_rb_ul, + UE_template->pre_first_nb_rb_ul); + UE_template->pre_allocated_nb_rb_ul = nb_rb; + max_num_ue--; + if (max_num_ue == 0) /* in this case, cannot allocate any other UE anymore */ + return rbs[0].length + (num_contig_rb > 1 ? rbs[1].length : 0); + continue; + } const int B = cmax(UE_template->estimated_ul_buffer - UE_template->scheduled_ul_bytes, 0); - - const int UE_to_be_scheduled = UE_is_to_be_scheduled(module_idP, CC_id, UE_id); + const int UE_to_be_scheduled = UE_is_to_be_scheduled(Mod_id, CC_id, UE_id); if (B == 0 && !UE_to_be_scheduled) continue; + num_ue_req++; + /* if UE has pending scheduling request then pre-allocate 3 RBs */ if (B == 0 && UE_to_be_scheduled) { UE_template->pre_assigned_mcs_ul = 10; /* use QPSK mcs only */ - UE_template->pre_allocated_rb_table_index_ul = 2; - UE_template->pre_allocated_nb_rb_ul = 3; + rb_idx_required[UE_id] = 2; + //UE_template->pre_allocated_nb_rb_ul = 3; continue; } @@ -560,28 +538,271 @@ assign_max_mcs_min_rb(module_id_t module_idP, int rb_table_index; int tx_power; calculate_max_mcs_min_rb( - module_idP, + Mod_id, CC_id, B, UE_template->phr_info, UE_info->UE_sched_ctrl[UE_id].phr_received == 1 ? 20 : 10, &mcs, - available_rbs, + max_rb, &rb_table_index, &tx_power); UE_template->pre_assigned_mcs_ul = mcs; - UE_template->pre_allocated_rb_table_index_ul = rb_table_index; - UE_template->pre_allocated_nb_rb_ul = rb_table[rb_table_index]; - LOG_D(MAC, "[eNB %d] frame %d subframe %d: for UE %d CC %d: pre-assigned mcs %d, pre-allocated rb_table[%d]=%d RBs (phr %d, tx power %d)\n", - module_idP, + rb_idx_required[UE_id] = rb_table_index; + //UE_template->pre_allocated_nb_rb_ul = rb_table[rb_table_index]; + /* only print log when PHR changed */ + static int phr = 0; + if (phr != UE_template->phr_info) { + phr = UE_template->phr_info; + LOG_D(MAC, "%d.%d UE %d CC %d: pre mcs %d, pre rb_table[%d]=%d RBs (phr %d, tx power %d, bytes %d)\n", + frame, + subframe, + UE_id, + CC_id, + UE_template->pre_assigned_mcs_ul, + UE_template->pre_allocated_rb_table_index_ul, + UE_template->pre_allocated_nb_rb_ul, + UE_template->phr_info, + tx_power, + B); + } + } + + if (num_ue_req == 0) + return rbs[0].length + (num_contig_rb > 1 ? rbs[1].length : 0); + + // calculate how many users should be in both regions, and to maximize usage, + // go from the larger to the smaller one which at least will handle a single + // full load case better. + const int n = min(num_ue_req, max_num_ue); + int nr[2] = {n, 0}; + int step = 1; // the order if we have two regions + int start = 0; + int end = 1; + if (num_contig_rb > 1) { + // proportionally divide between both regions + int la = rbs[0].length > 0 ? rbs[0].length : 1; + int lb = rbs[1].length > 0 ? rbs[1].length : 1; + nr[1] = min(max(n/(la/lb + 1), 1), n - 1); + nr[0] = n - nr[1]; + step = la > lb ? 1 : -1; // 1: from 0 to 1, -1: from 1 to 0 + start = la > lb ? 0 : 1; + end = la > lb ? 2 : -1; + } + + if (g_start_ue_ul == -1) + g_start_ue_ul = UE_list->head; + int sUE_id = g_start_ue_ul; + int rb_idx_given[MAX_MOBILES_PER_ENB]; + memset(rb_idx_given, 0, sizeof(rb_idx_given)); + + for (int r = start; r != end; r += step) { + // don't allocate if we have too little RBs + if (rbs[r].length < 3) + continue; + if (nr[r] <= 0) + continue; + + UE_list_t UE_sched; + // average RB index: just below the index that fits all UEs + int start_idx = pp_find_rb_table_index(rbs[r].length / nr[r]) - 1; + int num_ue_sched = 0; + int rb_required_add = 0; + int *cur_UE = &UE_sched.head; + while (num_ue_sched < nr[r]) { + while (rb_idx_required[sUE_id] == 0) + sUE_id = next_ue_list_looped(UE_list, sUE_id); + /* TODO: check that CCE allocated is feasible. If it is not, reduce + * nr[r] by one as this would been one opportunity */ + *cur_UE = sUE_id; + cur_UE = &UE_sched.next[sUE_id]; + rb_idx_given[sUE_id] = min(start_idx, rb_idx_required[sUE_id]); + rb_required_add += rb_table[rb_idx_required[sUE_id]] - rb_table[rb_idx_given[sUE_id]]; + rbs[r].length -= rb_table[rb_idx_given[sUE_id]]; + num_ue_sched++; + sUE_id = next_ue_list_looped(UE_list, sUE_id); + } + *cur_UE = -1; + + /* give remaining RBs in RR fashion. Since we don't know in advance the + * amount of RBs we can give (the "step size" in rb_table is non-linear), go + * through all UEs and try to give a bit more. Continue until no UE can be + * given a higher index because the remaining RBs do not suffice to increase */ + int UE_id = UE_sched.head; + int rb_required_add_old; + do { + rb_required_add_old = rb_required_add; + for (int UE_id = UE_sched.head; UE_id >= 0; UE_id = UE_sched.next[UE_id]) { + if (rb_idx_given[UE_id] >= rb_idx_required[UE_id]) + continue; // this UE does not need more + const int new_idx = rb_idx_given[UE_id] + 1; + const int rb_inc = rb_table[new_idx] - rb_table[rb_idx_given[UE_id]]; + if (rbs[r].length < rb_inc) + continue; + rb_idx_given[UE_id] = new_idx; + rbs[r].length -= rb_inc; + rb_required_add -= rb_inc; + } + } while (rb_required_add != rb_required_add_old); + + for (UE_id = UE_sched.head; UE_id >= 0; UE_id = UE_sched.next[UE_id]) { + UE_TEMPLATE *UE_template = &UE_info->UE_template[CC_id][UE_id]; + + /* MCS has been allocated previously */ + UE_template->pre_first_nb_rb_ul = rbs[r].start; + UE_template->pre_allocated_rb_table_index_ul = rb_idx_given[UE_id]; + UE_template->pre_allocated_nb_rb_ul = rb_table[rb_idx_given[UE_id]]; + rbs[r].start += rb_table[rb_idx_given[UE_id]]; + LOG_D(MAC, "%4d.%d UE %d allocated %d RBs start %d new start %d\n", + sched_frame, + sched_subframe, + UE_id, + UE_template->pre_allocated_nb_rb_ul, + UE_template->pre_first_nb_rb_ul, + rbs[r].start); + } + } + + /* if not all UEs could be allocated in this round */ + if (num_ue_req > max_num_ue) { + /* go to the first one we missed */ + for (int i = 0; i < max_num_ue; ++i) + g_start_ue_ul = next_ue_list_looped(UE_list, g_start_ue_ul); + } else { + /* else, just start with the next UE next time */ + g_start_ue_ul = next_ue_list_looped(UE_list, g_start_ue_ul); + } + + return rbs[0].length + (num_contig_rb > 1 ? rbs[1].length : 0); +} + +void ulsch_scheduler_pre_processor(module_id_t Mod_id, + int CC_id, + int frameP, + sub_frame_t subframeP, + int sched_frameP, + unsigned char sched_subframeP) { + UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; + const int N_RB_UL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].ul_Bandwidth); + COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id]; + + UE_list_t UE_to_sched; + UE_to_sched.head = -1; + for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) + UE_to_sched.next[i] = -1; + + int last_UE_id = -1; + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + UE_TEMPLATE *UE_template = &UE_info->UE_template[CC_id][UE_id]; + UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + + /* initialize per-UE scheduling information */ + UE_template->pre_assigned_mcs_ul = 0; + UE_template->pre_allocated_nb_rb_ul = 0; + UE_template->pre_allocated_rb_table_index_ul = -1; + UE_template->pre_first_nb_rb_ul = 0; + + const rnti_t rnti = UE_RNTI(Mod_id, UE_id); + if (rnti == NOT_A_RNTI) { + LOG_E(MAC, "UE %d has RNTI NOT_A_RNTI!\n", UE_id); + continue; + } + if (ue_sched_ctrl->cdrx_configured && !ue_sched_ctrl->in_active_time) + continue; + if (UE_info->UE_template[CC_id][UE_id].rach_resource_type > 0) + continue; + + /* define UEs to schedule */ + if (UE_to_sched.head < 0) + UE_to_sched.head = UE_id; + else + UE_to_sched.next[last_UE_id] = UE_id; + UE_to_sched.next[UE_id] = -1; + last_UE_id = UE_id; + } + + if (UE_to_sched.head < 0) + return; + + int last_rb_blocked = 1; + int n_contig = 0; + contig_rbs_t rbs[2]; // up to two contig RBs for PRACH in between + for (int i = 0; i < N_RB_UL; ++i) { + if (cc->vrb_map_UL[i] == 0 && last_rb_blocked == 1) { + last_rb_blocked = 0; + n_contig++; + AssertFatal(n_contig <= 2, "cannot handle more than two contiguous RB regions\n"); + rbs[n_contig - 1].start = i; + } + if (cc->vrb_map_UL[i] == 1 && last_rb_blocked == 0) { + last_rb_blocked = 1; + rbs[n_contig - 1].length = i - rbs[n_contig - 1].start; + } + } + + round_robin_ul(Mod_id, + CC_id, + frameP, + subframeP, + sched_frameP, + sched_subframeP, + &UE_to_sched, + 3, // max_num_ue + n_contig, + rbs); + + // the following block is meant for validation of the pre-processor to check + // whether all UE allocations are non-overlapping and is not necessary for + // scheduling functionality +#ifdef DEBUG_eNB_SCHEDULER + char t[101] = "__________________________________________________" + "__________________________________________________"; + t[N_RB_UL] = 0; + for (int j = 0; j < N_RB_UL; j++) + if (cc->vrb_map_UL[j] != 0) + t[j] = 'x'; + int print = 0; + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + UE_TEMPLATE *UE_template = &UE_info->UE_template[CC_id][UE_id]; + if (UE_template->pre_allocated_nb_rb_ul == 0) + continue; + + print = 1; + uint8_t harq_pid = subframe2harqpid(&RC.mac[Mod_id]->common_channels[CC_id], + sched_frameP, sched_subframeP); + LOG_D(MAC, "%4d.%d UE%d %d RBs (index %d) at start %d, pre MCS %d %s\n", frameP, subframeP, UE_id, - CC_id, - UE_template->pre_assigned_mcs_ul, - UE_template->pre_allocated_rb_table_index_ul, UE_template->pre_allocated_nb_rb_ul, - UE_template->phr_info, tx_power); + UE_template->pre_allocated_rb_table_index_ul, + UE_template->pre_first_nb_rb_ul, + UE_template->pre_assigned_mcs_ul, + UE_info->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid] > 0 ? "(retx)" : ""); + + for (int i = 0; i < UE_template->pre_allocated_nb_rb_ul; ++i) { + /* only check if this is not a retransmission */ + if (UE_info->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid] == 0 + && cc->vrb_map_UL[UE_template->pre_first_nb_rb_ul + i] == 1) { + + LOG_I(MAC, "%4d.%d UL scheduler allocation list: %s\n", frameP, subframeP, t); + LOG_E(MAC, + "%4d.%d: UE %d allocated at locked RB %d (is: allocated start " + "%d/length %d)\n", + frameP, subframeP, UE_id, UE_template->pre_first_nb_rb_ul + i, + UE_template->pre_first_nb_rb_ul, + UE_template->pre_allocated_nb_rb_ul); + } + cc->vrb_map_UL[UE_template->pre_first_nb_rb_ul + i] = 1; + t[UE_template->pre_first_nb_rb_ul + i] = UE_id + '0'; + } } + if (print) + LOG_D(MAC, + "%4d.%d UL scheduler allocation list: %s\n", + sched_frameP, + sched_subframeP, + t); +#endif } From a3bbbd0630f70697c27007d1a618385790a3b49d Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 26 Mar 2020 19:13:14 +0100 Subject: [PATCH 129/240] Lock PRACH region through vrb_map_UL --- openair2/LAYER2/MAC/eNB_scheduler_ulsch.c | 35 +++++++---------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index 16127ad603..ac7ab0cbfd 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -1211,32 +1211,17 @@ schedule_ulsch(module_id_t module_idP, /* Note: RC.nb_mac_CC[module_idP] should be lower than or equal to NFAPI_CC_MAX */ for (int CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; CC_id++, cc++) { - /* From Louis-Adrien to François: - * The comment bloc below is to configure with a command line. - * I took it from the equivalent part in the fairRR scheduler (around line 2578 in eNB_scheduler_fairRR.c). - * As said in the meeting, it seems to work only for small TBS. - * The cause of false RA still present with this fix is to investigate. - * - * Note: in the get_prach_prb_offset() function below, the last argument is frameP in eNB_scheduler_fairRR.c - * I think it should be sched_frame instead. This parameter has only impacts in case TDD and preamble format 4. - * To confirm. - */ - /* TODO: update vrb_map_UL here? */ - /* - int start_rb = 0; - int nb_rb = 6; - LTE_DL_FRAME_PARMS *frame_parms = &(RC.eNB[module_idP][CC_id]->frame_parms); - - if (is_prach_subframe(frame_parms, sched_frame, sched_subframe) == 1) { - start_rb = get_prach_prb_offset(frame_parms, - frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex, - frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset, - 0, // tdd_mapindex - sched_frame); // Nf - - first_rb[CC_id] = start_rb + nb_rb; + LTE_DL_FRAME_PARMS *frame_parms = &RC.eNB[module_idP][CC_id]->frame_parms; + if (is_prach_subframe(frame_parms, sched_frame, sched_subframe)) { + int start_rb = get_prach_prb_offset( + frame_parms, + frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex, + frame_parms->prach_config_common.prach_ConfigInfo.prach_FreqOffset, + 0, // tdd_mapindex + sched_frame); // Nf + for (int i = 0; i < 6; i++) + cc[CC_id].vrb_map_UL[start_rb + i] = 1; } - */ /* HACK: let's remove the PUCCH from available RBs * we suppose PUCCH size is: From 2f32448707fdf2ce25397188a87a1dfb8108ef38 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 28 Mar 2020 12:19:10 +0100 Subject: [PATCH 130/240] Correctly handle 2ms Sched. Reqs --- openair2/LAYER2/MAC/eNB_scheduler.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c index 42eca36dcb..8d4b1ee5d6 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler.c +++ b/openair2/LAYER2/MAC/eNB_scheduler.c @@ -336,6 +336,8 @@ schedule_SR (module_id_t module_idP, if ((10 * (frameP & 3) + subframeP) != (SRconfig->choice.setup.sr_ConfigIndex - 35)) continue; } else if (SRconfig->choice.setup.sr_ConfigIndex <= 154) { // 80 ms SR period if ((10 * (frameP & 7) + subframeP) != (SRconfig->choice.setup.sr_ConfigIndex - 75)) continue; + } else if (SRconfig->choice.setup.sr_ConfigIndex <= 156) { // 2ms SR period + if ((subframeP % 2) != (SRconfig->choice.setup.sr_ConfigIndex - 155)) continue; } } // SRconfig->present == SchedulingRequestConfig_PR_setup) } // SRconfig = UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->schedulingRequestConfig)!=NULL) From fd2e5fee960ed94464cb3f622793045162cbfe40 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 1 Apr 2020 17:09:16 +0200 Subject: [PATCH 131/240] Clean up schedule_dlsch() --- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 376 ++++++------------ .../LAYER2/MAC/eNB_scheduler_primitives.c | 2 +- openair2/LAYER2/MAC/mac_proto.h | 10 +- openair2/LAYER2/MAC/pre_processor.c | 12 + 4 files changed, 142 insertions(+), 258 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 6e0942c92d..b520d71558 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -462,10 +462,59 @@ void check_ra_rnti_mui(module_id_t mod_id, int CC_id, frame_t f, sub_frame_t sf, //------------------------------------------------------------------------------ void schedule_dlsch(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP, int *mbsfn_flag) { - for (int CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; CC_id++) { - if (mbsfn_flag[CC_id] == 0) - schedule_ue_spec(module_idP, CC_id, frameP, subframeP); + if (is_pmch_subframe(frameP, subframeP, &RC.eNB[module_idP][0]->frame_parms)) + return; + for (int CC_id = 0; CC_id < RC.nb_mac_CC[module_idP]; CC_id++) { + // for TDD: check that we have to act here, otherwise skip + COMMON_channels_t *cc = &RC.mac[module_idP]->common_channels[CC_id]; + if (cc->tdd_Config) { + int tdd_sfa = cc->tdd_Config->subframeAssignment; + + switch (subframeP) { + case 0: + // always continue + break; + + case 1: + case 2: + continue; + + case 3: + if (tdd_sfa != 2 && tdd_sfa != 5) + continue; + break; + + case 4: + if (tdd_sfa != 1 && tdd_sfa != 2 && tdd_sfa != 4 && tdd_sfa != 5) + continue; + break; + + case 5: + break; + + case 6: + case 7: + if (tdd_sfa != 3 && tdd_sfa != 4 && tdd_sfa != 5) + continue; + break; + + case 8: + if (tdd_sfa != 2 && tdd_sfa != 3 && tdd_sfa != 4 && tdd_sfa != 5) + continue; + break; + + case 9: + if (tdd_sfa == 0) + continue; + break; + } + } + + if (mbsfn_flag[CC_id] != 0) + continue; + + schedule_ue_spec(module_idP, CC_id, frameP, subframeP); } } @@ -494,84 +543,23 @@ schedule_ue_spec(module_id_t module_idP, sub_frame_t subframeP) //------------------------------------------------------------------------------ { - int aggregation = 2; int ta_len = 0; - unsigned char sdu_lcids[NB_RB_MAX]; - int TBS, j, padding = 0, post_padding = 0; unsigned char dlsch_buffer[MAX_DLSCH_PAYLOAD_BYTES]; - DLSCH_PDU *dlsch_pdu = NULL; eNB_MAC_INST *eNB = RC.mac[module_idP]; COMMON_channels_t *cc = eNB->common_channels; UE_info_t *UE_info = &eNB->UE_info; - int continue_flag = 0; - int32_t snr, target_snr; int tpc = 1; const int dl_Bandwidth = cc[CC_id].mib->message.dl_Bandwidth; const int N_RB_DL = to_prb(dl_Bandwidth); + const int N_RBG = to_rbg(eNB->common_channels[CC_id].mib->message.dl_Bandwidth); int total_nb_available_rb = N_RB_DL; - nfapi_dl_config_request_body_t *dl_req; - nfapi_dl_config_request_pdu_t *dl_config_pdu; - int tdd_sfa; + nfapi_dl_config_request_body_t *dl_req = &eNB->DL_req[CC_id].dl_config_request_body; int ta_update; - if(is_pmch_subframe(frameP,subframeP,&RC.eNB[module_idP][0]->frame_parms)){ - //LOG_E(MAC,"Frame[%d] SF:%d This SF should not be allocated\n",frameP,subframeP); - return ; - } - start_meas(&eNB->schedule_dlsch); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH, VCD_FUNCTION_IN); - // for TDD: check that we have to act here, otherwise return - if (cc[CC_id].tdd_Config) { - tdd_sfa = cc[CC_id].tdd_Config->subframeAssignment; - - switch (subframeP) { - case 0: - // always continue - break; - - case 1: - case 2: - return; - - case 3: - if (tdd_sfa != 2 && tdd_sfa != 5) - return; - - break; - - case 4: - if (tdd_sfa != 1 && tdd_sfa != 2 && tdd_sfa != 4 && tdd_sfa != 5) - return; - - break; - - case 5: - break; - - case 6: - case 7: - if (tdd_sfa != 3 && tdd_sfa != 4 && tdd_sfa != 5) - return; - - break; - - case 8: - if (tdd_sfa != 2 && tdd_sfa != 3 && tdd_sfa != 4 && tdd_sfa != 5) - return; - - break; - - case 9: - if (tdd_sfa == 0) - return; - - break; - } - } - for (int i = 0; i < N_RB_DL; i++) if (cc[CC_id].vrb_map[i] != 0) total_nb_available_rb--; @@ -596,79 +584,15 @@ schedule_ue_spec(module_id_t module_idP, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR, VCD_FUNCTION_OUT); - LOG_D(MAC, "doing schedule_ue_spec for CC_id %d\n", - CC_id); - dl_req = &eNB->DL_req[CC_id].dl_config_request_body; - for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { LOG_D(MAC, "doing schedule_ue_spec for CC_id %d UE %d\n", CC_id, UE_id); - continue_flag = 0; // reset the flag to allow allocation for the remaining UEs UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; UE_TEMPLATE *ue_template = &UE_info->UE_template[CC_id][UE_id]; eNB_UE_STATS *eNB_UE_stats = &UE_info->eNB_UE_stats[CC_id][UE_id]; const rnti_t rnti = ue_template->rnti; - - ue_rrc_release(rnti); - check_ra_rnti_mui(module_idP, CC_id, frameP, subframeP, rnti); - - if (ue_template->rach_resource_type > 0) { - continue_flag = 1; - } - - if (continue_flag != 1) { - switch (get_tmode(module_idP, - CC_id, - UE_id)) { - case 1: - case 2: - case 7: - aggregation = get_aggregation(get_bw_index(module_idP, - CC_id), - ue_sched_ctrl->dl_cqi[CC_id], - format1); - break; - - case 3: - aggregation = get_aggregation(get_bw_index(module_idP, - CC_id), - ue_sched_ctrl->dl_cqi[CC_id], - format2A); - break; - - default: - AssertFatal(1==0,"Unsupported transmission mode %d\n", get_tmode(module_idP, CC_id, UE_id)); - aggregation = 2; - break; - } - } - - /* if (continue_flag != 1 */ - if (ue_sched_ctrl->pre_nb_available_rbs[CC_id] == 0) { // no RBs allocated - LOG_D(MAC, "%d.%d: no RBs allocated for UE %d on CC_id %d\n", - frameP, - subframeP, - UE_id, - CC_id); - continue_flag = 1; - } - - if (CCE_allocation_infeasible(module_idP, - CC_id, - 1, - subframeP, - aggregation, - rnti)) { - LOG_W(MAC, "%d.%d: Dropping Allocation for RNTI 0x%04x/UE %d\n", - frameP, - subframeP, - rnti, - UE_id); - continue_flag = 1; //to next user (there might be rbs availiable for other UEs in TM5 - } - // If TDD if (cc[CC_id].tdd_Config != NULL) { //TDD set_ue_dai(subframeP, @@ -684,13 +608,55 @@ schedule_ue_spec(module_id_t module_idP, subframeP); } - if (continue_flag == 1) { - add_ue_dlsch_info(module_idP, - CC_id, - UE_id, - subframeP, - S_DL_NONE, - rnti); + ue_rrc_release(rnti); + check_ra_rnti_mui(module_idP, CC_id, frameP, subframeP, rnti); + + if (ue_sched_ctrl->pre_nb_available_rbs[CC_id] == 0) { // no RBs allocated + LOG_D(MAC, "%d.%d: no RBs allocated for UE %d on CC_id %d\n", + frameP, + subframeP, + UE_id, + CC_id); + continue; + } + + int aggregation = 2; + switch (get_tmode(module_idP, + CC_id, + UE_id)) { + case 1: + case 2: + case 7: + aggregation = get_aggregation(get_bw_index(module_idP, + CC_id), + ue_sched_ctrl->dl_cqi[CC_id], + format1); + break; + + case 3: + aggregation = get_aggregation(get_bw_index(module_idP, + CC_id), + ue_sched_ctrl->dl_cqi[CC_id], + format2A); + break; + + default: + AssertFatal(1==0,"Unsupported transmission mode %d\n", get_tmode(module_idP, CC_id, UE_id)); + aggregation = 2; + break; + } + + if (CCE_allocation_infeasible(module_idP, + CC_id, + 1, + subframeP, + aggregation, + rnti)) { + LOG_W(MAC, "%d.%d: Dropping Allocation for RNTI 0x%04x/UE %d\n", + frameP, + subframeP, + rnti, + UE_id); continue; } @@ -707,18 +673,6 @@ schedule_ue_spec(module_id_t module_idP, ue_sched_ctrl->uplane_inactivity_timer = 0; } - if (eNB_UE_stats->rrc_status < RRC_CONNECTED) { - LOG_D(MAC, "UE %d is not in RRC_CONNECTED\n", UE_id); - continue; - } - - //if (NFAPI_MODE != NFAPI_MONOLITHIC) { - // eNB_UE_stats->dlsch_mcs1 = cqi_to_mcs[ue_sched_ctrl->dl_cqi[CC_id]]; - //} else { // this operation is also done in the preprocessor - // eNB_UE_stats->dlsch_mcs1 = cmin(eNB_UE_stats->dlsch_mcs1, - // eNB->slice_info.dl[0/*slice_idxP*/].maxmcs); // cmin(eNB_UE_stats->dlsch_mcs1, openair_daq_vars.target_ue_dl_mcs); - //} - LOG_D(MAC, "[eNB %d] Frame %d: Scheduling UE %d on CC_id %d (rnti %x, harq_pid %d, round %d, rb %d, cqi %d, mcs %d, rrc %d)\n", module_idP, frameP, @@ -736,8 +690,9 @@ schedule_ue_spec(module_id_t module_idP, if (round_DL != 8) { // get freq_allocation const int nb_rb = ue_template->nb_rb[harq_pid]; - TBS = get_TBS_DL(ue_template->oldmcs1[harq_pid], - nb_rb); + int TBS = get_TBS_DL(ue_template->oldmcs1[harq_pid], nb_rb); + const uint32_t rbc = allocate_prbs_sub( + nb_rb, N_RB_DL, N_RBG, ue_sched_ctrl->rballoc_sub_UE[CC_id]); if (nb_rb <= ue_sched_ctrl->pre_nb_available_rbs[CC_id]) { /* CDRX */ @@ -768,6 +723,8 @@ schedule_ue_spec(module_id_t module_idP, ue_template->DAI); } + nfapi_dl_config_request_pdu_t *dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + memset(dl_config_pdu, 0, sizeof(nfapi_dl_config_request_pdu_t)); switch (get_tmode(module_idP, CC_id, UE_id)) { case 1: case 2: @@ -775,10 +732,6 @@ schedule_ue_spec(module_id_t module_idP, default: LOG_D(MAC, "retransmission DL_REQ: rnti:%x\n", rnti); - dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; - memset((void *) dl_config_pdu, - 0, - sizeof(nfapi_dl_config_request_pdu_t)); dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu)); dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG; @@ -796,6 +749,8 @@ schedule_ue_spec(module_id_t module_idP, dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = ue_template->oldNDI[harq_pid]; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = ue_template->oldmcs1[harq_pid]; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = round_DL & 3; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = rbc; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_allocation_type = 0; // TDD if (cc[CC_id].tdd_Config != NULL) { @@ -834,7 +789,7 @@ schedule_ue_spec(module_id_t module_idP, rnti, 0, // type 0 allocation from 7.1.6 in 36.213 0, // virtual_resource_block_assignment_flag, unused here - 0, // resource_block_coding, to be filled in later + rbc, // resource_block_coding getQm(ue_template->oldmcs1[harq_pid]), round_DL & 3, // redundancy version 1, // transport blocks @@ -870,11 +825,6 @@ schedule_ue_spec(module_id_t module_idP, } } - add_ue_dlsch_info(module_idP, - CC_id, UE_id, - subframeP, - S_DL_SCHEDULED, - rnti); //eNB_UE_stats->dlsch_trials[round]++; eNB_UE_stats->num_retransmission += 1; eNB_UE_stats->rbs_used_retx = nb_rb; @@ -891,8 +841,9 @@ schedule_ue_spec(module_id_t module_idP, } else { // Now check RLC information to compute number of required RBs // get maximum TBS size for RLC request - /* TODO this assumes that UE is allocated continuously, can we do better? */ - TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, ue_sched_ctrl->pre_nb_available_rbs[CC_id]); + const int nb_rb = ue_sched_ctrl->pre_nb_available_rbs[CC_id]; + int TBS = get_TBS_DL(eNB_UE_stats->dlsch_mcs1, nb_rb); + const uint32_t rbc = allocate_prbs_sub(nb_rb, N_RB_DL, N_RBG, ue_sched_ctrl->rballoc_sub_UE[CC_id]); // add the length for all the control elements (timing adv, drx, etc) : header + payload @@ -921,6 +872,7 @@ schedule_ue_spec(module_id_t module_idP, int sdu_length_total = 0; int header_length_total = 0; int header_length_last = 0; + unsigned char sdu_lcids[NB_RB_MAX]; for (int i = 0; i < ue_sched_ctrl->dl_lc_num; ++i) { const int lcid = ue_sched_ctrl->dl_lc_ids[i]; // will match DCCH, DCCH1, DTCH @@ -957,8 +909,8 @@ schedule_ue_spec(module_id_t module_idP, lcid, CC_id, sdu_lengths[num_sdus]); - for (j = 0; j < sdu_lengths[num_sdus]; ++j) - LOG_T(MAC, "%x ", dlsch_buffer[sdu_length_total+j]); + for (int j = 0; j < sdu_lengths[num_sdus]; ++j) + LOG_T(MAC, "%x ", dlsch_buffer[sdu_length_total + j]); LOG_T(MAC, "\n"); #endif @@ -1011,7 +963,6 @@ schedule_ue_spec(module_id_t module_idP, // Now compute number of required RBs for total sdu length // Assume RAH format 2 int mcs = eNB_UE_stats->dlsch_mcs1; - const int nb_rb = ue_sched_ctrl->pre_nb_available_rbs[CC_id]; /* TODO make special function */ // decrease mcs until TBS falls below required length @@ -1033,13 +984,8 @@ schedule_ue_spec(module_id_t module_idP, LOG_D(MAC, "dlsch_mcs before and after the rate matching = (%d, %d), TBS %d, nb_rb %d\n", eNB_UE_stats->dlsch_mcs1, mcs, TBS, nb_rb); - if (TBS - header_length_total - sdu_length_total - ta_len <= 2) { - padding = TBS - header_length_total - sdu_length_total - ta_len; - post_padding = 0; - } else { - padding = 0; - post_padding = 1; - } + int post_padding = TBS - header_length_total - sdu_length_total - ta_len > 2; + int padding = post_padding ? 0 : TBS - header_length_total - sdu_length_total - ta_len; const int offset = generate_dlsch_header((unsigned char *) UE_info->DLSCH_pdu[CC_id][0][UE_id].payload[0], num_sdus, //num_sdus @@ -1085,11 +1031,11 @@ schedule_ue_spec(module_id_t module_idP, LOG_T(MAC, "\n"); #endif // cycle through SDUs and place in dlsch_buffer - dlsch_pdu = &UE_info->DLSCH_pdu[CC_id][0][UE_id]; + DLSCH_PDU *dlsch_pdu = &UE_info->DLSCH_pdu[CC_id][0][UE_id]; memcpy(&dlsch_pdu->payload[0][offset], dlsch_buffer, sdu_length_total); // fill remainder of DLSCH with 0 - for (j = 0; j < (TBS - sdu_length_total - offset); j++) { + for (int j = 0; j < TBS - sdu_length_total - offset; j++) { dlsch_pdu->payload[0][offset + sdu_length_total + j] = 0; } @@ -1114,12 +1060,6 @@ schedule_ue_spec(module_id_t module_idP, T_BUFFER(dlsch_pdu->payload[0], TBS)); ue_template->nb_rb[harq_pid] = nb_rb; - add_ue_dlsch_info(module_idP, - CC_id, - UE_id, - subframeP, - S_DL_SCHEDULED, - rnti); // store stats eNB->eNB_stats[CC_id].dlsch_bytes_tx += sdu_length_total; eNB->eNB_stats[CC_id].dlsch_pdus_tx += 1; @@ -1146,8 +1086,8 @@ schedule_ue_spec(module_id_t module_idP, // this is the snr // unit is not dBm, it's special from nfapi // converting to dBm - snr = (5 * ue_sched_ctrl->pucch1_snr[CC_id] - 640) / 10; - target_snr = eNB->puCch10xSnr / 10; + int snr = (5 * ue_sched_ctrl->pucch1_snr[CC_id] - 640) / 10; + int target_snr = eNB->puCch10xSnr / 10; // this assumes accumulated tpc // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out int32_t framex10psubframe = ue_template->pucch_tpc_tx_frame * 10 + ue_template->pucch_tpc_tx_subframe; @@ -1183,10 +1123,8 @@ schedule_ue_spec(module_id_t module_idP, tpc = 1; //0 } - dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; - memset((void *) dl_config_pdu, - 0, - sizeof(nfapi_dl_config_request_pdu_t)); + nfapi_dl_config_request_pdu_t *dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; + memset(dl_config_pdu, 0, sizeof(nfapi_dl_config_request_pdu_t)); dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu)); dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1; @@ -1207,6 +1145,8 @@ schedule_ue_spec(module_id_t module_idP, //deactivate second codeword dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_2 = 0; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_2 = 1; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = rbc; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_allocation_type = 0; if (cc[CC_id].tdd_Config != NULL) { //TDD dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.downlink_assignment_index = (ue_template->DAI - 1) & 3; @@ -1277,7 +1217,7 @@ schedule_ue_spec(module_id_t module_idP, rnti, 0, // type 0 allocation from 7.1.6 in 36.213 0, // virtual_resource_block_assignment_flag, unused here - 0, // resource_block_coding, to be filled in later + rbc,// resource_block_coding getQm(mcs), 0, // redundancy version 1, // transport blocks @@ -1327,11 +1267,6 @@ schedule_ue_spec(module_id_t module_idP, subframeP); } } // UE_id loop - - fill_DLSCH_dci(module_idP, - CC_id, - frameP, - subframeP); stop_meas(&eNB->schedule_dlsch); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH, VCD_FUNCTION_OUT); @@ -2018,61 +1953,6 @@ schedule_ue_spec_br(module_id_t module_idP, } // end loop on UE_id } -//------------------------------------------------------------------------------ -void -fill_DLSCH_dci(module_id_t module_idP, - int CC_id, - frame_t frameP, - sub_frame_t subframeP) -//------------------------------------------------------------------------------ -{ - eNB_MAC_INST *eNB = RC.mac[module_idP]; - const UE_info_t *UE_info = &eNB->UE_info; - const int N_RBG = to_rbg(eNB->common_channels[CC_id].mib->message.dl_Bandwidth); - const int N_RB_DL = to_prb(eNB->common_channels[CC_id].mib->message.dl_Bandwidth); - - start_meas(&eNB->fill_DLSCH_dci); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_FILL_DLSCH_DCI, VCD_FUNCTION_IN); - - // UE specific DCIs - for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { - eNB_DLSCH_INFO *dlsch_info = &eNB_dlsch_info[module_idP][CC_id][UE_id]; - LOG_T(MAC, "CC_id %d, UE_id: %d => status %d\n", CC_id, UE_id, dlsch_info->status); - - if (dlsch_info->status != S_DL_SCHEDULED) - continue; - - // clear scheduling flag - dlsch_info->status = S_DL_WAITING; - const rnti_t rnti = UE_info->UE_template[CC_id][UE_id].rnti; - const UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; - const int nb_rb = ue_sched_ctrl->pre_nb_available_rbs[CC_id]; - - nfapi_dl_config_request_body_t *dl_config_request_body = &RC.mac[module_idP]->DL_req[CC_id].dl_config_request_body; - nfapi_dl_config_request_pdu_t *dl_config_pdu; - - for (int i = 0; i < dl_config_request_body->number_pdu; i++) { - dl_config_pdu = &dl_config_request_body->dl_config_pdu_list[i]; - - if (dl_config_pdu->pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE - && dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti == rnti - && dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format != 1) { - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = - allocate_prbs_sub(nb_rb, N_RB_DL, N_RBG, ue_sched_ctrl->rballoc_sub_UE[CC_id]); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_allocation_type = 0; - } else if (dl_config_pdu->pdu_type == NFAPI_DL_CONFIG_DLSCH_PDU_TYPE - && dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti == rnti - && dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type == 0) { - dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding = - allocate_prbs_sub(nb_rb, N_RB_DL, N_RBG, ue_sched_ctrl->rballoc_sub_UE[CC_id]); - } - } - } - - stop_meas(&eNB->fill_DLSCH_dci); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_FILL_DLSCH_DCI, VCD_FUNCTION_OUT); -} - //------------------------------------------------------------------------------ unsigned char *get_dlsch_sdu(module_id_t module_idP, int CC_id, diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index 9072a3c872..6e9875e0a6 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -1627,7 +1627,7 @@ fill_nfapi_dlsch_config(eNB_MAC_INST *eNB, uint8_t resource_allocation_type, uint8_t virtual_resource_block_assignment_flag, - uint16_t resource_block_coding, + uint32_t resource_block_coding, uint8_t modulation, uint8_t redundancy_version, uint8_t transport_blocks, diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index 650d5999e1..8861675735 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -137,14 +137,6 @@ void schedule_ulsch_rnti_emtc(module_id_t module_idP, unsigned char sched_subframeP, int *emtc_active); -/** \brief Second stage of DLSCH scheduling, after schedule_SI, schedule_RA and schedule_dlsch have been called. This routine first allocates random frequency assignments for SI and RA SDUs using distributed VRB allocations and adds the corresponding DCI SDU to the DCI buffer for PHY. It then loops over the UE specific DCIs previously allocated and fills in the remaining DCI fields related to frequency allocation. It assumes localized allocation of type 0 (DCI.rah=0). The allocation is done for tranmission modes 1,2,4. -@param Mod_id Instance of eNB -@param CC_id the component carrier -@param frame Frame index -@param subframe Index of subframe -*/ -void fill_DLSCH_dci(module_id_t module_idP, int CC_id, frame_t frameP,sub_frame_t subframe); - /** \brief UE specific DLSCH scheduling. Retrieves next ue to be schduled from round-robin scheduler and gets the appropriate harq_pid for the subframe from PHY. If the process is active and requires a retransmission, it schedules the retransmission with the same PRB count and MCS as the first transmission. Otherwise it consults RLC for DCCH/DTCH SDUs (status with maximum number of available PRBS), builds the MAC header (timing advance sent by default) and copies @param Mod_id Instance ID of eNB @param frame Frame index @@ -1105,7 +1097,7 @@ void fill_nfapi_dlsch_config(eNB_MAC_INST *eNB, uint8_t resource_allocation_type, uint8_t virtual_resource_block_assignment_flag, - uint16_t resource_block_coding, + uint32_t resource_block_coding, uint8_t modulation, uint8_t redundancy_version, uint8_t transport_blocks, diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 613edf9127..aeb432f64e 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -287,6 +287,7 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, int last_UE_id = -1; for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + const UE_TEMPLATE *ue_template = &UE_info->UE_template[CC_id][UE_id]; /* initialize per-UE scheduling information */ ue_sched_ctrl->pre_nb_available_rbs[CC_id] = 0; @@ -302,6 +303,17 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, LOG_E(MAC, "UE %d RNTI %x is NOT active!\n", UE_id, rnti); continue; } + if (ue_template->rach_resource_type > 0) { + LOG_D(MAC, + "UE %d is RACH resource type %d\n", + UE_id, + ue_template->rach_resource_type); + continue; + } + if (mac_eNB_get_rrc_status(Mod_id, rnti) < RRC_CONNECTED) { + LOG_D(MAC, "UE %d is not in RRC_CONNECTED\n", UE_id); + continue; + } /* define UEs to schedule */ if (first) { From c9a921504cf083d9915a1b2a624d44ddbb208e11 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 1 Apr 2020 18:43:25 +0200 Subject: [PATCH 132/240] TEST: TPC + TA cleaned up in DLSCH --- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index b520d71558..cd56f07eaf 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -543,18 +543,15 @@ schedule_ue_spec(module_id_t module_idP, sub_frame_t subframeP) //------------------------------------------------------------------------------ { - int ta_len = 0; unsigned char dlsch_buffer[MAX_DLSCH_PAYLOAD_BYTES]; eNB_MAC_INST *eNB = RC.mac[module_idP]; COMMON_channels_t *cc = eNB->common_channels; UE_info_t *UE_info = &eNB->UE_info; - int tpc = 1; const int dl_Bandwidth = cc[CC_id].mib->message.dl_Bandwidth; const int N_RB_DL = to_prb(dl_Bandwidth); const int N_RBG = to_rbg(eNB->common_channels[CC_id].mib->message.dl_Bandwidth); int total_nb_available_rb = N_RB_DL; nfapi_dl_config_request_body_t *dl_req = &eNB->DL_req[CC_id].dl_config_request_body; - int ta_update; start_meas(&eNB->schedule_dlsch); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH, @@ -850,6 +847,7 @@ schedule_ue_spec(module_id_t module_idP, if (ue_sched_ctrl->ta_timer) ue_sched_ctrl->ta_timer--; + int ta_update = 31; if (ue_sched_ctrl->ta_timer == 0) { ta_update = ue_sched_ctrl->ta_update; @@ -860,11 +858,9 @@ schedule_ue_spec(module_id_t module_idP, /* reset ta_update */ ue_sched_ctrl->ta_update = 31; - } else { - ta_update = 31; } - ta_len = (ta_update != 31) ? 2 : 0; + int ta_len = (ta_update != 31) ? 2 : 0; int num_sdus = 0; @@ -1092,8 +1088,9 @@ schedule_ue_spec(module_id_t module_idP, // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out int32_t framex10psubframe = ue_template->pucch_tpc_tx_frame * 10 + ue_template->pucch_tpc_tx_subframe; + int tpc = 1; if (framex10psubframe + 10 <= (frameP * 10) + subframeP || //normal case - (framex10psubframe > (frameP * 10) + subframeP && 10240 - framex10psubframe + (frameP * 10) + subframeP >= 10)) //frame wrap-around + (framex10psubframe > (frameP * 10) + subframeP && 10240 - framex10psubframe + (frameP * 10) + subframeP >= 10)) { //frame wrap-around if (ue_sched_ctrl->pucch1_cqi_update[CC_id] == 1) { ue_sched_ctrl->pucch1_cqi_update[CC_id] = 0; ue_template->pucch_tpc_tx_frame = frameP; @@ -1116,11 +1113,6 @@ schedule_ue_spec(module_id_t module_idP, snr, target_snr); } // Po_PUCCH has been updated - else { - tpc = 1; //0 - } // time to do TPC update - else { - tpc = 1; //0 } nfapi_dl_config_request_pdu_t *dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; From 9256a9e81329197a9e2a860b960676779708f77e Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 2 Apr 2020 17:55:34 +0200 Subject: [PATCH 133/240] Clean up schedule_ulsch_rnti() --- openair2/LAYER2/MAC/eNB_scheduler_ulsch.c | 35 +++++++---------------- 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index ac7ab0cbfd..8c84c82a00 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -1364,13 +1364,7 @@ schedule_ulsch_rnti(module_id_t module_idP, VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_BO, UE_template_ptr->estimated_ul_buffer); - /* - * If there is information on BSR of DCCH, DTCH or if there is UL_SR, - * or if there is a packet to retransmit, or we want to schedule a periodic - * feedback - * TODO: this should be decided in the preprocessor - */ - if (UE_is_to_be_scheduled(module_idP, CC_id, UE_id) == 0 && round_index == 0) + if (UE_template_ptr->pre_allocated_nb_rb_ul < 1) continue; LOG_D(MAC, @@ -1504,11 +1498,12 @@ schedule_ulsch_rnti(module_id_t module_idP, } const uint8_t ndi = 1 - UE_template_ptr->oldNDI_UL[harq_pid]; // NDI: new data indicator + const uint8_t mcs = UE_template_ptr->pre_assigned_mcs_ul; UE_template_ptr->oldNDI_UL[harq_pid] = ndi; UE_info->eNB_UE_stats[CC_id][UE_id].snr = snr; UE_info->eNB_UE_stats[CC_id][UE_id].target_snr = target_snr; - UE_template_ptr->mcs_UL[harq_pid] = UE_template_ptr->pre_assigned_mcs_ul; - UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1 = UE_template_ptr->mcs_UL[harq_pid]; + UE_template_ptr->mcs_UL[harq_pid] = mcs; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs1 = mcs; /* CDRX */ if (UE_sched_ctrl_ptr->cdrx_configured) { @@ -1522,20 +1517,14 @@ schedule_ulsch_rnti(module_id_t module_idP, UE_sched_ctrl_ptr->dci0_ongoing_timer = 1; } - uint8_t rb_table_index = -1; - if (UE_template_ptr->pre_allocated_rb_table_index_ul >= 0) { - rb_table_index = UE_template_ptr->pre_allocated_rb_table_index_ul; - } else { - UE_template_ptr->mcs_UL[harq_pid] = 10; - rb_table_index = 5; // for PHR - } + uint8_t rb_table_index = UE_template_ptr->pre_allocated_rb_table_index_ul; - UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2 = UE_template_ptr->mcs_UL[harq_pid]; + UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2 = mcs; while (rb_table[rb_table_index] > 45 && rb_table_index > 0) rb_table_index--; - UE_template_ptr->TBS_UL[harq_pid] = get_TBS_UL(UE_template_ptr->mcs_UL[harq_pid], rb_table[rb_table_index]); + UE_template_ptr->TBS_UL[harq_pid] = get_TBS_UL(mcs, rb_table[rb_table_index]); UE_info->eNB_UE_stats[CC_id][UE_id].total_rbs_used_rx += rb_table[rb_table_index]; UE_info->eNB_UE_stats[CC_id][UE_id].ulsch_TBS = UE_template_ptr->TBS_UL[harq_pid]; UE_info->eNB_UE_stats[CC_id][UE_id].total_ulsch_TBS += UE_template_ptr->TBS_UL[harq_pid]; @@ -1546,7 +1535,7 @@ schedule_ulsch_rnti(module_id_t module_idP, T_INT(frameP), T_INT(subframeP), T_INT(harq_pid), - T_INT(UE_template_ptr->mcs_UL[harq_pid]), + T_INT(mcs), T_INT(rb_table[rb_table_index]), T_INT(UE_template_ptr->TBS_UL[harq_pid]), T_INT(ndi)); @@ -1593,8 +1582,7 @@ schedule_ulsch_rnti(module_id_t module_idP, hi_dci0_pdu->dci_pdu.dci_pdu_rel8.resource_block_start = UE_template_ptr->pre_first_nb_rb_ul; hi_dci0_pdu->dci_pdu.dci_pdu_rel8.number_of_resource_block = rb_table[rb_table_index]; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.mcs_1 = - UE_template_ptr->mcs_UL[harq_pid]; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.mcs_1 = mcs; hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cyclic_shift_2_for_drms = cshift; hi_dci0_pdu->dci_pdu.dci_pdu_rel8.frequency_hopping_enabled_flag = 0; hi_dci0_pdu->dci_pdu.dci_pdu_rel8.new_data_indication_1 = ndi; @@ -1648,7 +1636,7 @@ schedule_ulsch_rnti(module_id_t module_idP, rnti, UE_template_ptr->pre_first_nb_rb_ul, // resource_block_start rb_table[rb_table_index], // number_of_resource_blocks - UE_template_ptr->mcs_UL[harq_pid], + mcs, cshift, // cyclic_shift_2_for_drms 0, // frequency_hopping_enabled_flag 0, // frequency_hopping_bits @@ -1658,8 +1646,7 @@ schedule_ulsch_rnti(module_id_t module_idP, 0, // ul_tx_mode 0, // current_tx_nb 0, // n_srs - get_TBS_UL(UE_template_ptr->mcs_UL[harq_pid], - rb_table[rb_table_index])); + get_TBS_UL(mcs, rb_table[rb_table_index])); /* This is a BL/CE UE allocation */ if (UE_template_ptr->rach_resource_type > 0) { From 24fb5e9c80ea9f6559d3af7253a04d4aeafb0347 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 5 Apr 2020 22:25:51 +0200 Subject: [PATCH 134/240] add adaptive HARQ UL --- openair2/LAYER2/MAC/eNB_scheduler_ulsch.c | 162 +++++++++++++--------- 1 file changed, 93 insertions(+), 69 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index 8c84c82a00..e4e0a363ec 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -1282,7 +1282,6 @@ schedule_ulsch_rnti(module_id_t module_idP, eNB_MAC_INST *mac = RC.mac[module_idP]; COMMON_channels_t *cc = mac->common_channels; UE_info_t *UE_info = &mac->UE_info; - const int rvidx_tab[4] = {0, 2, 3, 1}; int sched_frame = frameP; @@ -1367,6 +1366,18 @@ schedule_ulsch_rnti(module_id_t module_idP, if (UE_template_ptr->pre_allocated_nb_rb_ul < 1) continue; + if (CCE_allocation_infeasible(module_idP, CC_id, 2, subframeP, aggregation, rnti)) { + LOG_W(MAC, + "[eNB %d] %d.%d, UE %d/%x CC %d: not enough CCE\n", + module_idP, + frameP, + subframeP, + UE_id, + rnti, + CC_id); + continue; + } + LOG_D(MAC, "[eNB %d][PUSCH %d] %d.%d Scheduling UE %d/%x in " "round %d (SR %d, UL_inactivity timer %d, UL_failure timer " @@ -1387,22 +1398,54 @@ schedule_ulsch_rnti(module_id_t module_idP, UE_template_ptr->ul_SR = 0; const uint8_t status = mac_eNB_get_rrc_status(module_idP, rnti); + /* Power control */ + /* + * Compute the expected ULSCH RX snr (for the stats) + * This is the normalized RX snr and this should be constant (regardless + * of mcs) Is not in dBm, unit from nfapi, converting to dBm + */ + const int32_t snr = (5 * UE_sched_ctrl_ptr->pusch_snr[CC_id] - 640) / 10; + const int32_t target_snr = mac->puSch10xSnr / 10; + + /* + * This assumes accumulated tpc + * Make sure that we are only sending a tpc update once a frame, otherwise + * the control loop will freak out + */ + const int32_t fx10psf = (UE_template_ptr->pusch_tpc_tx_frame * 10) + + UE_template_ptr->pusch_tpc_tx_subframe; + uint32_t tpc = 1; + if (((fx10psf + 10) <= (frameP * 10 + subframeP)) // normal case + || ((fx10psf > (frameP * 10 + subframeP)) + && (((10240 - fx10psf + frameP * 10 + subframeP) >= 10)))) { // frame wrap-around + UE_template_ptr->pusch_tpc_tx_frame = frameP; + UE_template_ptr->pusch_tpc_tx_subframe = subframeP; + + if (snr > target_snr + 4) { + tpc = 0; // -1 + tpc_accumulated--; + } else if (snr < target_snr - 4) { + tpc = 2; // +1 + tpc_accumulated++; + } + } + + if (tpc != 1) { + LOG_D(MAC, + "[eNB %d] ULSCH scheduler: frame %d, subframe %d, harq_pid %d, " + "tpc %d, accumulated %d, snr/target snr %d/%d\n", + module_idP, + frameP, + subframeP, + harq_pid, + tpc, + tpc_accumulated, + snr, + target_snr); + } + /* New transmission */ if (round_index == 0) { - /* Should format_flag be 2 in CCE_allocation_infeasible??? */ - /* This test seems to be way too long, can we provide an optimization? */ - if (CCE_allocation_infeasible(module_idP, CC_id, 1, subframeP, aggregation, rnti)) { - LOG_W(MAC, - "[eNB %d] %d.%d, UE %d/%x CC %d: not enough CCE\n", - module_idP, - frameP, - subframeP, - UE_id, - rnti, - CC_id); - continue; - } - /* Handle the aperiodic CQI report */ uint32_t cqi_req = 0; LOG_D(MAC, @@ -1447,56 +1490,6 @@ schedule_ulsch_rnti(module_id_t module_idP, } } - /* Power control */ - /* - * Compute the expected ULSCH RX snr (for the stats) - * This is the normalized RX snr and this should be constant (regardless - * of mcs) Is not in dBm, unit from nfapi, converting to dBm - */ - const int32_t snr = (5 * UE_sched_ctrl_ptr->pusch_snr[CC_id] - 640) / 10; - const int32_t target_snr = mac->puSch10xSnr / 10; - /* - * This assumes accumulated tpc - * Make sure that we are only sending a tpc update once a frame, otherwise - * the control loop will freak out - */ - const int32_t fx10psf = (UE_template_ptr->pusch_tpc_tx_frame * 10) - + UE_template_ptr->pusch_tpc_tx_subframe; - uint32_t tpc = 0; - - if (((fx10psf + 10) <= (frameP * 10 + subframeP)) // normal case - || ((fx10psf > (frameP * 10 + subframeP)) - && (((10240 - fx10psf + frameP * 10 + subframeP) >= 10)))) { // frame wrap-around - UE_template_ptr->pusch_tpc_tx_frame = frameP; - UE_template_ptr->pusch_tpc_tx_subframe = subframeP; - - if (snr > target_snr + 4) { - tpc = 0; // -1 - tpc_accumulated--; - } else if (snr < target_snr - 4) { - tpc = 2; // +1 - tpc_accumulated++; - } else { - tpc = 1; // 0 - } - } else { - tpc = 1; // 0 - } - - if (tpc != 1) { - LOG_D(MAC, - "[eNB %d] ULSCH scheduler: frame %d, subframe %d, harq_pid %d, " - "tpc %d, accumulated %d, snr/target snr %d/%d\n", - module_idP, - frameP, - subframeP, - harq_pid, - tpc, - tpc_accumulated, - snr, - target_snr); - } - const uint8_t ndi = 1 - UE_template_ptr->oldNDI_UL[harq_pid]; // NDI: new data indicator const uint8_t mcs = UE_template_ptr->pre_assigned_mcs_ul; UE_template_ptr->oldNDI_UL[harq_pid] = ndi; @@ -1703,6 +1696,16 @@ schedule_ulsch_rnti(module_id_t module_idP, UE_id, rnti); } else { // round_index > 0 => retransmission + uint8_t mcs_rv = 0; + const int rvidx_tab[4] = {0, 2, 3, 1}; + uint8_t round_UL = UE_sched_ctrl_ptr->round_UL[CC_id][harq_pid]; + if (rvidx_tab[round_UL & 3] == 1) { + mcs_rv = 29; + } else if (rvidx_tab[round_UL & 3] == 2) { + mcs_rv = 30; + } else if (rvidx_tab[round_UL & 3] == 3) { + mcs_rv = 31; + } T(T_ENB_MAC_UE_UL_SCHEDULE_RETRANSMISSION, T_INT(module_idP), T_INT(CC_id), @@ -1710,13 +1713,13 @@ schedule_ulsch_rnti(module_id_t module_idP, T_INT(frameP), T_INT(subframeP), T_INT(harq_pid), - T_INT(UE_template_ptr->mcs_UL[harq_pid]), + T_INT(mcs_rv), T_INT(UE_template_ptr->first_rb_ul[harq_pid]), T_INT(UE_template_ptr->nb_rb_ul[harq_pid]), T_INT(round_index)); /* Add UL_config PDUs */ LOG_D(MAC, - "[PUSCH %d] Frame %d, Subframe %d: Adding UL CONFIG.Request for UE " + "[PUSCH %d] %4d.%d: Adding UL CONFIG.Request for UE " "%d/%x, ulsch_frame %d, ulsch_subframe %d\n", harq_pid, frameP, @@ -1725,10 +1728,31 @@ schedule_ulsch_rnti(module_id_t module_idP, rnti, sched_frame, sched_subframeP); + + hi_dci0_pdu = &hi_dci0_req_body->hi_dci0_pdu_list[hi_dci0_req_body->number_of_dci + hi_dci0_req_body->number_of_hi]; + memset((void *)hi_dci0_pdu, 0, sizeof(nfapi_hi_dci0_request_pdu_t)); + hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_DCI_PDU_TYPE; + hi_dci0_pdu->pdu_size = 2 + sizeof(nfapi_hi_dci0_dci_pdu); + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.tl.tag = NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dci_format = NFAPI_UL_DCI_FORMAT_0; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.transmission_power = 6000; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.resource_block_start = UE_template_ptr->first_rb_ul[harq_pid]; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.number_of_resource_block = UE_template_ptr->nb_rb_ul[harq_pid]; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.mcs_1 = mcs_rv; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cyclic_shift_2_for_drms = cshift; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.frequency_hopping_enabled_flag = 0; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.new_data_indication_1 = UE_template_ptr->oldNDI_UL[harq_pid]; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.tpc = tpc; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cqi_csi_request = UE_template_ptr->cqi_req[harq_pid]; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dl_assignment_index = UE_template_ptr->DAI_ul[sched_subframeP]; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.harq_pid = harq_pid; + hi_dci0_req_body->number_of_dci++; + uint16_t ul_req_index = 0; uint8_t dlsch_flag = 0; uint32_t cqi_req = UE_template_ptr->cqi_req[harq_pid]; - for (ul_req_index = 0; ul_req_index < ul_req_tmp_body->number_of_pdus; ul_req_index++) { if (ul_req_tmp_body->ul_config_pdu_list[ul_req_index].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE && ul_req_tmp_body->ul_config_pdu_list[ul_req_index].uci_harq_pdu.ue_information.ue_information_rel8.rnti == rnti) { @@ -1754,7 +1778,7 @@ schedule_ulsch_rnti(module_id_t module_idP, rnti, UE_template_ptr->first_rb_ul[harq_pid], // resource_block_start UE_template_ptr->nb_rb_ul[harq_pid], // number_of_resource_blocks - UE_template_ptr->mcs_UL[harq_pid], + mcs_rv, cshift, // cyclic_shift_2_for_drms 0, // frequency_hopping_enabled_flag 0, // frequency_hopping_bits From 0f46f17c1c917aeedf300d72f6f214c8de407c80 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 3 Apr 2020 10:47:14 +0200 Subject: [PATCH 135/240] UL PP can change retx freq allocation --- openair2/LAYER2/MAC/eNB_scheduler_ulsch.c | 29 ++++++++++++++++++----- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index e4e0a363ec..88c5e20c27 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -1706,6 +1706,23 @@ schedule_ulsch_rnti(module_id_t module_idP, } else if (rvidx_tab[round_UL & 3] == 3) { mcs_rv = 31; } + + const uint16_t first_rb = UE_template_ptr->pre_first_nb_rb_ul; + const uint8_t nb_rb = UE_template_ptr->pre_allocated_nb_rb_ul; + if (first_rb != UE_template_ptr->first_rb_ul[harq_pid] + || nb_rb != UE_template_ptr->nb_rb_ul[harq_pid]) + LOG_D(MAC, + "%4d.%d UE %4x retx: change freq allocation to %d RBs start %d (from %d RBs start %d)\n", + frameP, + subframeP, + rnti, + nb_rb, + first_rb, + UE_template_ptr->nb_rb_ul[harq_pid], + UE_template_ptr->first_rb_ul[harq_pid]); + UE_template_ptr->first_rb_ul[harq_pid] = first_rb; + UE_template_ptr->nb_rb_ul[harq_pid] = nb_rb; + T(T_ENB_MAC_UE_UL_SCHEDULE_RETRANSMISSION, T_INT(module_idP), T_INT(CC_id), @@ -1714,8 +1731,8 @@ schedule_ulsch_rnti(module_id_t module_idP, T_INT(subframeP), T_INT(harq_pid), T_INT(mcs_rv), - T_INT(UE_template_ptr->first_rb_ul[harq_pid]), - T_INT(UE_template_ptr->nb_rb_ul[harq_pid]), + T_INT(first_rb), + T_INT(nb_rb), T_INT(round_index)); /* Add UL_config PDUs */ LOG_D(MAC, @@ -1738,8 +1755,8 @@ schedule_ulsch_rnti(module_id_t module_idP, hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation; hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti; hi_dci0_pdu->dci_pdu.dci_pdu_rel8.transmission_power = 6000; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.resource_block_start = UE_template_ptr->first_rb_ul[harq_pid]; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.number_of_resource_block = UE_template_ptr->nb_rb_ul[harq_pid]; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.resource_block_start = first_rb; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.number_of_resource_block = nb_rb; hi_dci0_pdu->dci_pdu.dci_pdu_rel8.mcs_1 = mcs_rv; hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cyclic_shift_2_for_drms = cshift; hi_dci0_pdu->dci_pdu.dci_pdu_rel8.frequency_hopping_enabled_flag = 0; @@ -1776,8 +1793,8 @@ schedule_ulsch_rnti(module_id_t module_idP, get_tmode(module_idP, CC_id, UE_id), mac->ul_handle, rnti, - UE_template_ptr->first_rb_ul[harq_pid], // resource_block_start - UE_template_ptr->nb_rb_ul[harq_pid], // number_of_resource_blocks + first_rb, // resource_block_start + nb_rb, // number_of_resource_blocks mcs_rv, cshift, // cyclic_shift_2_for_drms 0, // frequency_hopping_enabled_flag From 5443c7a792e2103eac068e23834c51d17bdd4d3f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 3 Apr 2020 22:47:36 +0200 Subject: [PATCH 136/240] fill_nfapi_dlsch_config() takes index for filling --- openair2/LAYER2/MAC/eNB_scheduler_RA.c | 11 +++++++++-- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 8 ++++---- openair2/LAYER2/MAC/eNB_scheduler_fairRR.c | 8 ++++++-- openair2/LAYER2/MAC/eNB_scheduler_phytest.c | 4 ++-- openair2/LAYER2/MAC/eNB_scheduler_primitives.c | 5 +---- openair2/LAYER2/MAC/mac_proto.h | 3 +-- 6 files changed, 23 insertions(+), 16 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_RA.c b/openair2/LAYER2/MAC/eNB_scheduler_RA.c index 2e8f06586b..d1365b9ac3 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_RA.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_RA.c @@ -1030,7 +1030,11 @@ generate_Msg4(module_id_t module_idP, memcpy((void *) &mac->UE_info.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0][(unsigned char)offset], &cc[CC_idP].CCCH_pdu.payload[0], rrc_sdu_length); // DLSCH Config - fill_nfapi_dlsch_config(mac, dl_req_body, ra->msg4_TBsize, mac->pdu_index[CC_idP], ra->rnti, 2, // resource_allocation_type : format 1A/1B/1D + fill_nfapi_dlsch_config(&dl_req_body->dl_config_pdu_list[dl_req_body->number_pdu], + ra->msg4_TBsize, + mac->pdu_index[CC_idP], + ra->rnti, + 2, // resource_allocation_type : format 1A/1B/1D 0, // virtual_resource_block_assignment_flag : localized getRIV(N_RB_DL, first_rb, 4), // resource_block_coding : RIV, 4 PRB 2, // modulation: QPSK @@ -1049,6 +1053,7 @@ generate_Msg4(module_id_t module_idP, (cc->p_eNB == 1) ? 1 : 2, // transmission mode 1, // num_bf_prb_per_subband 1); // num_bf_vector + dl_req_body->number_pdu++; LOG_D(MAC, "Filled DLSCH config, pdu number %d, non-dci pdu_index %d\n", dl_req_body->number_pdu, mac->pdu_index[CC_idP]); @@ -1173,7 +1178,8 @@ check_Msg4_retransmission(module_id_t module_idP, int CC_idP, // DLSCH Config //DJP - fix this pdu_index = -1 LOG_D(MAC, "check_Msg4_retransmission() before fill_nfapi_dlsch_config() with pdu_index = -1 \n"); - fill_nfapi_dlsch_config(mac, dl_req_body, ra->msg4_TBsize, + fill_nfapi_dlsch_config(&dl_req_body->dl_config_pdu_list[dl_req_body->number_pdu], + ra->msg4_TBsize, -1 /* retransmission, no pdu_index */ , ra->rnti, 2, // resource_allocation_type : format 1A/1B/1D @@ -1195,6 +1201,7 @@ check_Msg4_retransmission(module_id_t module_idP, int CC_idP, (cc->p_eNB == 1) ? 1 : 2, // transmission mode 1, // num_bf_prb_per_subband 1); // num_bf_vector + dl_req_body->number_pdu++; if(RC.mac[module_idP]->scheduler_mode == SCHED_MODE_FAIR_RR) { set_dl_ue_select_msg4(CC_idP, 4, UE_id, ra->rnti); diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index cd56f07eaf..1f6f2d9e3d 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -779,8 +779,7 @@ schedule_ue_spec(module_id_t module_idP, dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG; eNB->DL_req[CC_id].sfn_sf = frameP<<4 | subframeP; eNB->DL_req[CC_id].header.message_id = NFAPI_DL_CONFIG_REQUEST; - fill_nfapi_dlsch_config(eNB, - dl_req, + fill_nfapi_dlsch_config(&dl_req->dl_config_pdu_list[dl_req->number_pdu], TBS, -1, // retransmission, no pdu_index rnti, @@ -803,6 +802,7 @@ schedule_ue_spec(module_id_t module_idP, cc[CC_id].p_eNB == 1 ? 1 : 2, // transmission mode 0, //number of PRBs treated as one subband, not used here 0); // number of beamforming vectors, not used here + dl_req->number_pdu++; LOG_D(MAC, "Filled NFAPI configuration for DCI/DLSCH %d, retransmission round %d\n", eNB->pdu_index[CC_id], round_DL); @@ -1202,8 +1202,7 @@ schedule_ue_spec(module_id_t module_idP, AssertFatal(ue_template->physicalConfigDedicated != NULL, "physicalConfigDedicated is NULL\n"); AssertFatal(ue_template->physicalConfigDedicated->pdsch_ConfigDedicated != NULL, "physicalConfigDedicated->pdsch_ConfigDedicated is NULL\n"); - fill_nfapi_dlsch_config(eNB, - dl_req, + fill_nfapi_dlsch_config(&dl_req->dl_config_pdu_list[dl_req->number_pdu], TBS, eNB->pdu_index[CC_id], rnti, @@ -1226,6 +1225,7 @@ schedule_ue_spec(module_id_t module_idP, cc[CC_id].p_eNB == 1 ? 1 : 2, // transmission mode 0, //number of PRBs treated as one subband, not used here 0); // number of beamforming vectors, not used here + dl_req->number_pdu++; eNB->TX_req[CC_id].sfn_sf = fill_nfapi_tx_req(&eNB->TX_req[CC_id].tx_request_body, (frameP * 10) + subframeP, TBS, diff --git a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c index d486c59ff5..a42922c300 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c @@ -1493,7 +1493,9 @@ schedule_ue_spec_fairRR(module_id_t module_idP, dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG; eNB->DL_req[CC_id].sfn_sf = frameP<<4 | subframeP; eNB->DL_req[CC_id].header.message_id = NFAPI_DL_CONFIG_REQUEST; - fill_nfapi_dlsch_config(eNB, dl_req, TBS, -1 + fill_nfapi_dlsch_config(&dl_req->dl_config_pdu_list[dl_req->number_pdu], + TBS, + -1 /* retransmission, no pdu_index */ , rnti, 0, // type 0 allocation from 7.1.6 in 36.213 0, // virtual_resource_block_assignment_flag, unused here @@ -1513,6 +1515,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, 0, //number of PRBs treated as one subband, not used here 0 // number of beamforming vectors, not used here ); + dl_req->number_pdu++; LOG_D(MAC, "Filled NFAPI configuration for DCI/DLSCH %d, retransmission round %d\n", eNB->pdu_index[CC_id], round); @@ -2077,7 +2080,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, UE_info->UE_template[CC_id][UE_id].oldmcs2[harq_pid] = 0; AssertFatal(UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated!=NULL,"physicalConfigDedicated is NULL\n"); AssertFatal(UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated!=NULL,"physicalConfigDedicated->pdsch_ConfigDedicated is NULL\n"); - fill_nfapi_dlsch_config(eNB,dl_req, + fill_nfapi_dlsch_config(&dl_req->dl_config_pdu_list[dl_req->number_pdu], TBS, eNB->pdu_index[CC_id], rnti, @@ -2101,6 +2104,7 @@ schedule_ue_spec_fairRR(module_id_t module_idP, 0, //number of PRBs treated as one subband, not used here 0 // number of beamforming vectors, not used here ); + dl_req->number_pdu++; eNB->TX_req[CC_id].sfn_sf = fill_nfapi_tx_req(&eNB->TX_req[CC_id].tx_request_body, (frameP*10)+subframeP, TBS, diff --git a/openair2/LAYER2/MAC/eNB_scheduler_phytest.c b/openair2/LAYER2/MAC/eNB_scheduler_phytest.c index 776f2994cf..689db8e208 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_phytest.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_phytest.c @@ -141,8 +141,7 @@ schedule_ue_spec_phy_test( AssertFatal(UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated!=NULL,"physicalConfigDedicated is NULL\n"); AssertFatal(UE_info->UE_template[CC_id][UE_id].physicalConfigDedicated->pdsch_ConfigDedicated!=NULL,"physicalConfigDedicated->pdsch_ConfigDedicated is NULL\n"); */ - fill_nfapi_dlsch_config(eNB, - dl_req, + fill_nfapi_dlsch_config(&dl_req->dl_config_pdu_list[dl_req->number_pdu], TBS, eNB->pdu_index[CC_id], rnti, @@ -166,6 +165,7 @@ schedule_ue_spec_phy_test( 0, //number of PRBs treated as one subband, not used here 0 // number of beamforming vectors, not used here ); + dl_req->number_pdu++; eNB->TX_req[CC_id].sfn_sf = fill_nfapi_tx_req(&eNB->TX_req[CC_id].tx_request_body, (frameP*10)+subframeP, TBS, diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index 6e9875e0a6..0cd4993b30 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -1619,8 +1619,7 @@ fill_nfapi_mch_config(nfapi_dl_config_request_body_t *dl_req, //------------------------------------------------------------------------------ void -fill_nfapi_dlsch_config(eNB_MAC_INST *eNB, - nfapi_dl_config_request_body_t *dl_req, +fill_nfapi_dlsch_config(nfapi_dl_config_request_pdu_t *dl_config_pdu, uint16_t length, int16_t pdu_index, uint16_t rnti, @@ -1646,7 +1645,6 @@ fill_nfapi_dlsch_config(eNB_MAC_INST *eNB, uint8_t num_bf_vector) //------------------------------------------------------------------------------ { - nfapi_dl_config_request_pdu_t *dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; memset((void *) dl_config_pdu, 0, sizeof(nfapi_dl_config_request_pdu_t)); dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dlsch_pdu)); @@ -1673,7 +1671,6 @@ fill_nfapi_dlsch_config(eNB_MAC_INST *eNB, dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode = transmission_mode; dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband = num_bf_prb_per_subband; dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector = num_bf_vector; - dl_req->number_pdu++; return; } diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index 8861675735..289973cd30 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -1090,8 +1090,7 @@ void program_dlsch_acknak(module_id_t module_idP, int CC_idP, int UE_idP, frame_t frameP, sub_frame_t subframeP, uint8_t cce_idx); -void fill_nfapi_dlsch_config(eNB_MAC_INST *eNB, - nfapi_dl_config_request_body_t *dl_req, +void fill_nfapi_dlsch_config(nfapi_dl_config_request_pdu_t *dl_config_pdu, uint16_t length, int16_t pdu_index, uint16_t rnti, uint8_t resource_allocation_type, From 88d156478fcf148900cc89ba9c20ea1a40741c1b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 4 Apr 2020 11:15:55 +0200 Subject: [PATCH 137/240] CCE_allocation_infeasible(): log only debug --- openair2/LAYER2/MAC/eNB_scheduler_primitives.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index 0cd4993b30..07ae5e3079 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -3321,7 +3321,7 @@ try_again: if (fCCE == -1) { if (DL_req->number_pdcch_ofdm_symbols == max_symbol) { - LOG_I(MAC, "subframe %d: Dropping Allocation for RNTI %x\n", + LOG_D(MAC, "subframe %d: Dropping Allocation for RNTI %x\n", subframeP, dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.rnti); From 6b3b0b0b8bf4ca922bd673347eba28fc9d6130d8 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 5 Apr 2020 11:39:22 +0200 Subject: [PATCH 138/240] Final CCE allocation check: print message on fail --- openair2/LAYER2/MAC/eNB_scheduler.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c index 8d4b1ee5d6..c46005ee2d 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler.c +++ b/openair2/LAYER2/MAC/eNB_scheduler.c @@ -982,7 +982,9 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, /* Allocate CCEs for good after scheduling is done */ for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { if (cc[CC_id].tdd_Config == NULL || !(is_UL_sf(&cc[CC_id],subframeP))) { - allocate_CCEs(module_idP, CC_id, frameP, subframeP, 2); + int rc = allocate_CCEs(module_idP, CC_id, frameP, subframeP, 2); + if (rc < 0) + LOG_E(MAC, "%s() %4d.%d ERROR ALLOCATING CCEs\n", __func__, frameP, subframeP); } } From ed6e5ce8326cca545852e1ec556936729663d657 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 3 Apr 2020 23:07:24 +0200 Subject: [PATCH 139/240] Use CCE_try_allocate_dlsch() --- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 480 ++++++++---------- .../LAYER2/MAC/eNB_scheduler_primitives.c | 61 +++ openair2/LAYER2/MAC/mac.h | 1 + openair2/LAYER2/MAC/mac_proto.h | 6 + openair2/LAYER2/MAC/pre_processor.c | 1 + 5 files changed, 274 insertions(+), 275 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 1f6f2d9e3d..7621994ab2 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -617,43 +617,31 @@ schedule_ue_spec(module_id_t module_idP, continue; } - int aggregation = 2; - switch (get_tmode(module_idP, - CC_id, - UE_id)) { - case 1: - case 2: - case 7: - aggregation = get_aggregation(get_bw_index(module_idP, - CC_id), - ue_sched_ctrl->dl_cqi[CC_id], - format1); - break; - - case 3: - aggregation = get_aggregation(get_bw_index(module_idP, - CC_id), - ue_sched_ctrl->dl_cqi[CC_id], - format2A); - break; - - default: - AssertFatal(1==0,"Unsupported transmission mode %d\n", get_tmode(module_idP, CC_id, UE_id)); - aggregation = 2; - break; + int dci_dl_pdu_idx = ue_sched_ctrl->pre_dci_dl_pdu_idx; + if (dci_dl_pdu_idx < 0) { + dci_dl_pdu_idx = CCE_try_allocate_dlsch( + module_idP, CC_id, subframeP, UE_id, ue_sched_ctrl->dl_cqi[CC_id]); + if (dci_dl_pdu_idx < 0) { + LOG_W(MAC, "%d.%d: Dropping Allocation for RNTI 0x%04x/UE %d\n", + frameP, + subframeP, + rnti, + UE_id); + continue; + } } - if (CCE_allocation_infeasible(module_idP, - CC_id, - 1, - subframeP, - aggregation, - rnti)) { - LOG_W(MAC, "%d.%d: Dropping Allocation for RNTI 0x%04x/UE %d\n", - frameP, - subframeP, - rnti, - UE_id); + /* verify it is the right UE */ + nfapi_dl_config_request_pdu_t *dci = &dl_req->dl_config_pdu_list[dci_dl_pdu_idx]; + nfapi_dl_config_request_pdu_t *dlsch = &dl_req->dl_config_pdu_list[dci_dl_pdu_idx + 1]; + if (dci->pdu_type != NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE + || dci->dci_dl_pdu.dci_dl_pdu_rel8.rnti != rnti + || dlsch->pdu_type != NFAPI_DL_CONFIG_DLSCH_PDU_TYPE + || dlsch->dlsch_pdu.dlsch_pdu_rel8.rnti != rnti) { + LOG_E(MAC, "illegal dl_config_pdu_list index %d for UE %d/RNTI %04x\n", + dci_dl_pdu_idx, + UE_id, + rnti); continue; } @@ -691,150 +679,126 @@ schedule_ue_spec(module_id_t module_idP, const uint32_t rbc = allocate_prbs_sub( nb_rb, N_RB_DL, N_RBG, ue_sched_ctrl->rballoc_sub_UE[CC_id]); - if (nb_rb <= ue_sched_ctrl->pre_nb_available_rbs[CC_id]) { - /* CDRX */ - ue_sched_ctrl->harq_rtt_timer[CC_id][harq_pid] = 1; // restart HARQ RTT timer - - if (ue_sched_ctrl->cdrx_configured) { - ue_sched_ctrl->drx_retransmission_timer[harq_pid] = 0; // stop drx retransmission - - /* - * Note: contrary to the spec drx_retransmission_timer[harq_pid] is reset not stop. - */ - if (harq_pid == 0) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_RETRANSMISSION_HARQ0, (unsigned long) ue_sched_ctrl->drx_retransmission_timer[0]); - } - } - - if (cc[CC_id].tdd_Config != NULL) { - ue_template->DAI++; - update_ul_dci(module_idP, - CC_id, - rnti, - ue_template->DAI, - subframeP); - LOG_D(MAC, "DAI update: CC_id %d subframeP %d: UE %d, DAI %d\n", - CC_id, - subframeP, - UE_id, - ue_template->DAI); - } - - nfapi_dl_config_request_pdu_t *dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; - memset(dl_config_pdu, 0, sizeof(nfapi_dl_config_request_pdu_t)); - switch (get_tmode(module_idP, CC_id, UE_id)) { - case 1: - case 2: - case 7: - default: - LOG_D(MAC, "retransmission DL_REQ: rnti:%x\n", - rnti); - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; - dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu)); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = - get_aggregation(get_bw_index(module_idP, - CC_id), - ue_sched_ctrl->dl_cqi[CC_id], - format1); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // CRNTI: see Table 4-10 from SCF082 - nFAPI specifications - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = harq_pid; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // Don't adjust power when retransmitting - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = ue_template->oldNDI[harq_pid]; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = ue_template->oldmcs1[harq_pid]; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = round_DL & 3; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = rbc; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_allocation_type = 0; - - // TDD - if (cc[CC_id].tdd_Config != NULL) { - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.downlink_assignment_index = (ue_template->DAI - 1) & 3; - LOG_D(MAC, "[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, dai %d, mcs %d\n", - module_idP, - CC_id, - harq_pid, - round_DL, - ue_template->DAI - 1, - ue_template->oldmcs1[harq_pid]); - } else { - LOG_D(MAC, "[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, mcs %d\n", - module_idP, - CC_id, - harq_pid, - round_DL, - ue_template->oldmcs1[harq_pid]); - } - - if (!CCE_allocation_infeasible(module_idP, - CC_id, - 1, - subframeP, - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, - rnti)) { - dl_req->number_dci++; - dl_req->number_pdu++; - dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG; - eNB->DL_req[CC_id].sfn_sf = frameP<<4 | subframeP; - eNB->DL_req[CC_id].header.message_id = NFAPI_DL_CONFIG_REQUEST; - fill_nfapi_dlsch_config(&dl_req->dl_config_pdu_list[dl_req->number_pdu], - TBS, - -1, // retransmission, no pdu_index - rnti, - 0, // type 0 allocation from 7.1.6 in 36.213 - 0, // virtual_resource_block_assignment_flag, unused here - rbc, // resource_block_coding - getQm(ue_template->oldmcs1[harq_pid]), - round_DL & 3, // redundancy version - 1, // transport blocks - 0, // transport block to codeword swap flag - cc[CC_id].p_eNB == 1 ? 0 : 1, // transmission_scheme - 1, // number of layers - 1, // number of subbands - // uint8_t codebook_index, - 4, // UE category capacity - ue_template->physicalConfigDedicated->pdsch_ConfigDedicated->p_a, - 0, // delta_power_offset for TM5 - 0, // ngap - 0, // nprb - cc[CC_id].p_eNB == 1 ? 1 : 2, // transmission mode - 0, //number of PRBs treated as one subband, not used here - 0); // number of beamforming vectors, not used here - dl_req->number_pdu++; - LOG_D(MAC, "Filled NFAPI configuration for DCI/DLSCH %d, retransmission round %d\n", - eNB->pdu_index[CC_id], - round_DL); - program_dlsch_acknak(module_idP, - CC_id, - UE_id, - frameP, - subframeP, - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx); - // No TX request for retransmission (check if null request for FAPI) - } else { - LOG_W(MAC, "Frame %d, Subframe %d: Dropping DLSCH allocation for UE %d\%x, infeasible CCE allocation\n", - frameP, - subframeP, - UE_id, - rnti); - } - } - - //eNB_UE_stats->dlsch_trials[round]++; - eNB_UE_stats->num_retransmission += 1; - eNB_UE_stats->rbs_used_retx = nb_rb; - eNB_UE_stats->total_rbs_used_retx += nb_rb; - eNB_UE_stats->dlsch_mcs2 = eNB_UE_stats->dlsch_mcs1; - } else { + if (nb_rb > ue_sched_ctrl->pre_nb_available_rbs[CC_id]) { LOG_D(MAC, "[eNB %d] Frame %d CC_id %d : don't schedule UE %d, its retransmission takes more resources than we have\n", module_idP, frameP, CC_id, UE_id); + continue; } + + /* CDRX */ + ue_sched_ctrl->harq_rtt_timer[CC_id][harq_pid] = 1; // restart HARQ RTT timer + + if (ue_sched_ctrl->cdrx_configured) { + ue_sched_ctrl->drx_retransmission_timer[harq_pid] = 0; // stop drx retransmission + + /* + * Note: contrary to the spec drx_retransmission_timer[harq_pid] is reset not stop. + */ + if (harq_pid == 0) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_RETRANSMISSION_HARQ0, (unsigned long) ue_sched_ctrl->drx_retransmission_timer[0]); + } + } + + if (cc[CC_id].tdd_Config != NULL) { + ue_template->DAI++; + update_ul_dci(module_idP, + CC_id, + rnti, + ue_template->DAI, + subframeP); + LOG_D(MAC, "DAI update: CC_id %d subframeP %d: UE %d, DAI %d\n", + CC_id, + subframeP, + UE_id, + ue_template->DAI); + } + + nfapi_dl_config_request_pdu_t *dl_config_pdu = &dl_req->dl_config_pdu_list[dci_dl_pdu_idx]; + switch (get_tmode(module_idP, CC_id, UE_id)) { + case 1: + case 2: + case 7: + default: + LOG_D(MAC, "retransmission DL_REQ: rnti:%x\n", + rnti); + dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu)); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // CRNTI: see Table 4-10 from SCF082 - nFAPI specifications + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = harq_pid; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc = 1; // Don't adjust power when retransmitting + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1 = ue_template->oldNDI[harq_pid]; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1 = ue_template->oldmcs1[harq_pid]; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1 = round_DL & 3; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding = rbc; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_allocation_type = 0; + + // TDD + if (cc[CC_id].tdd_Config != NULL) { + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.downlink_assignment_index = (ue_template->DAI - 1) & 3; + LOG_D(MAC, "[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, dai %d, mcs %d\n", + module_idP, + CC_id, + harq_pid, + round_DL, + ue_template->DAI - 1, + ue_template->oldmcs1[harq_pid]); + } else { + LOG_D(MAC, "[eNB %d] Retransmission CC_id %d : harq_pid %d, round %d, mcs %d\n", + module_idP, + CC_id, + harq_pid, + round_DL, + ue_template->oldmcs1[harq_pid]); + } + + dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG; + eNB->DL_req[CC_id].sfn_sf = frameP<<4 | subframeP; + eNB->DL_req[CC_id].header.message_id = NFAPI_DL_CONFIG_REQUEST; + fill_nfapi_dlsch_config(&dl_req->dl_config_pdu_list[dci_dl_pdu_idx + 1], + TBS, + -1, // retransmission, no pdu_index + rnti, + 0, // type 0 allocation from 7.1.6 in 36.213 + 0, // virtual_resource_block_assignment_flag, unused here + rbc, // resource_block_coding + getQm(ue_template->oldmcs1[harq_pid]), + round_DL & 3, // redundancy version + 1, // transport blocks + 0, // transport block to codeword swap flag + cc[CC_id].p_eNB == 1 ? 0 : 1, // transmission_scheme + 1, // number of layers + 1, // number of subbands + // uint8_t codebook_index, + 4, // UE category capacity + ue_template->physicalConfigDedicated->pdsch_ConfigDedicated->p_a, + 0, // delta_power_offset for TM5 + 0, // ngap + 0, // nprb + cc[CC_id].p_eNB == 1 ? 1 : 2, // transmission mode + 0, //number of PRBs treated as one subband, not used here + 0); // number of beamforming vectors, not used here + LOG_D(MAC, "Filled NFAPI configuration for DCI/DLSCH %d, retransmission round %d\n", + eNB->pdu_index[CC_id], + round_DL); + program_dlsch_acknak(module_idP, + CC_id, + UE_id, + frameP, + subframeP, + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx); + // No TX request for retransmission (check if null request for FAPI) + } + + //eNB_UE_stats->dlsch_trials[round]++; + eNB_UE_stats->num_retransmission += 1; + eNB_UE_stats->rbs_used_retx = nb_rb; + eNB_UE_stats->total_rbs_used_retx += nb_rb; + eNB_UE_stats->dlsch_mcs2 = eNB_UE_stats->dlsch_mcs1; } else { // Now check RLC information to compute number of required RBs // get maximum TBS size for RLC request @@ -1115,18 +1079,9 @@ schedule_ue_spec(module_id_t module_idP, } // Po_PUCCH has been updated } - nfapi_dl_config_request_pdu_t *dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; - memset(dl_config_pdu, 0, sizeof(nfapi_dl_config_request_pdu_t)); - dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; + nfapi_dl_config_request_pdu_t *dl_config_pdu = &dl_req->dl_config_pdu_list[dci_dl_pdu_idx]; dl_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu)); dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format = NFAPI_DL_DCI_FORMAT_1; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = - get_aggregation(get_bw_index(module_idP, - CC_id), - ue_sched_ctrl->dl_cqi[CC_id], - format1); - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG; - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; // CRNTI : see Table 4-10 from SCF082 - nFAPI specifications dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power = 6000; // equal to RS power dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process = harq_pid; @@ -1159,104 +1114,79 @@ schedule_ue_spec(module_id_t module_idP, LOG_D(MAC, "Checking feasibility pdu %d (new sdu)\n", dl_req->number_pdu); - if (!CCE_allocation_infeasible(module_idP, - CC_id, - 1, - subframeP, - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level, - rnti)) { - ue_sched_ctrl->round[CC_id][harq_pid] = 0; - dl_req->number_dci++; - dl_req->number_pdu++; - dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG; - eNB->DL_req[CC_id].sfn_sf = frameP << 4 | subframeP; - eNB->DL_req[CC_id].header.message_id = NFAPI_DL_CONFIG_REQUEST; - /* CDRX */ - ue_sched_ctrl->harq_rtt_timer[CC_id][harq_pid] = 1; // restart HARQ RTT timer + ue_sched_ctrl->round[CC_id][harq_pid] = 0; + dl_req->tl.tag = NFAPI_DL_CONFIG_REQUEST_BODY_TAG; + eNB->DL_req[CC_id].sfn_sf = frameP << 4 | subframeP; + eNB->DL_req[CC_id].header.message_id = NFAPI_DL_CONFIG_REQUEST; + /* CDRX */ + ue_sched_ctrl->harq_rtt_timer[CC_id][harq_pid] = 1; // restart HARQ RTT timer - if (ue_sched_ctrl->cdrx_configured) { - ue_sched_ctrl->drx_inactivity_timer = 1; // restart drx inactivity timer when new transmission - ue_sched_ctrl->drx_retransmission_timer[harq_pid] = 0; // stop drx retransmission - /* - * Note: contrary to the spec drx_retransmission_timer[harq_pid] is reset not stop. - */ - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_INACTIVITY, (unsigned long) ue_sched_ctrl->drx_inactivity_timer); + if (ue_sched_ctrl->cdrx_configured) { + ue_sched_ctrl->drx_inactivity_timer = 1; // restart drx inactivity timer when new transmission + ue_sched_ctrl->drx_retransmission_timer[harq_pid] = 0; // stop drx retransmission + /* + * Note: contrary to the spec drx_retransmission_timer[harq_pid] is reset not stop. + */ + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_INACTIVITY, (unsigned long) ue_sched_ctrl->drx_inactivity_timer); - if (harq_pid == 0) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_RETRANSMISSION_HARQ0, (unsigned long) ue_sched_ctrl->drx_retransmission_timer[0]); - } + if (harq_pid == 0) { + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DRX_RETRANSMISSION_HARQ0, (unsigned long) ue_sched_ctrl->drx_retransmission_timer[0]); } - - // Toggle NDI for next time - LOG_D(MAC, "CC_id %d Frame %d, subframeP %d: Toggling Format1 NDI for UE %d (rnti %x/%d) oldNDI %d\n", - CC_id, - frameP, - subframeP, - UE_id, - rnti, - harq_pid, - ue_template->oldNDI[harq_pid]); - ue_template->oldNDI[harq_pid] = 1 - ue_template->oldNDI[harq_pid]; - ue_template->oldmcs1[harq_pid] = mcs; - ue_template->oldmcs2[harq_pid] = 0; - AssertFatal(ue_template->physicalConfigDedicated != NULL, "physicalConfigDedicated is NULL\n"); - AssertFatal(ue_template->physicalConfigDedicated->pdsch_ConfigDedicated != NULL, - "physicalConfigDedicated->pdsch_ConfigDedicated is NULL\n"); - fill_nfapi_dlsch_config(&dl_req->dl_config_pdu_list[dl_req->number_pdu], - TBS, - eNB->pdu_index[CC_id], - rnti, - 0, // type 0 allocation from 7.1.6 in 36.213 - 0, // virtual_resource_block_assignment_flag, unused here - rbc,// resource_block_coding - getQm(mcs), - 0, // redundancy version - 1, // transport blocks - 0, // transport block to codeword swap flag - cc[CC_id].p_eNB == 1 ? 0 : 1, // transmission_scheme - 1, // number of layers - 1, // number of subbands - // uint8_t codebook_index, - 4, // UE category capacity - ue_template->physicalConfigDedicated->pdsch_ConfigDedicated->p_a, - 0, // delta_power_offset for TM5 - 0, // ngap - 0, // nprb - cc[CC_id].p_eNB == 1 ? 1 : 2, // transmission mode - 0, //number of PRBs treated as one subband, not used here - 0); // number of beamforming vectors, not used here - dl_req->number_pdu++; - eNB->TX_req[CC_id].sfn_sf = fill_nfapi_tx_req(&eNB->TX_req[CC_id].tx_request_body, - (frameP * 10) + subframeP, - TBS, - eNB->pdu_index[CC_id], - dlsch_pdu->payload[0]); - LOG_D(MAC, "Filled NFAPI configuration for DCI/DLSCH/TXREQ %d, new SDU\n", - eNB->pdu_index[CC_id]); - eNB->pdu_index[CC_id]++; - program_dlsch_acknak(module_idP, - CC_id, - UE_id, - frameP, - subframeP, - dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx); - } else { - LOG_W(MAC, "Frame %d, Subframe %d: Dropping DLSCH allocation for UE %d/%x, infeasible CCE allocations\n", - frameP, - subframeP, - UE_id, - rnti); } - } - } - /* TODO this seems to not be necessary, we already do this above */ - if (cc[CC_id].tdd_Config != NULL) { // TDD - set_ul_DAI(module_idP, - UE_id, - CC_id, - frameP, - subframeP); + // Toggle NDI for next time + LOG_D(MAC, "CC_id %d Frame %d, subframeP %d: Toggling Format1 NDI for UE %d (rnti %x/%d) oldNDI %d\n", + CC_id, + frameP, + subframeP, + UE_id, + rnti, + harq_pid, + ue_template->oldNDI[harq_pid]); + ue_template->oldNDI[harq_pid] = 1 - ue_template->oldNDI[harq_pid]; + ue_template->oldmcs1[harq_pid] = mcs; + ue_template->oldmcs2[harq_pid] = 0; + AssertFatal(ue_template->physicalConfigDedicated != NULL, "physicalConfigDedicated is NULL\n"); + AssertFatal(ue_template->physicalConfigDedicated->pdsch_ConfigDedicated != NULL, + "physicalConfigDedicated->pdsch_ConfigDedicated is NULL\n"); + fill_nfapi_dlsch_config(&dl_req->dl_config_pdu_list[dci_dl_pdu_idx + 1], + TBS, + eNB->pdu_index[CC_id], + rnti, + 0, // type 0 allocation from 7.1.6 in 36.213 + 0, // virtual_resource_block_assignment_flag, unused here + rbc,// resource_block_coding + getQm(mcs), + 0, // redundancy version + 1, // transport blocks + 0, // transport block to codeword swap flag + cc[CC_id].p_eNB == 1 ? 0 : 1, // transmission_scheme + 1, // number of layers + 1, // number of subbands + // uint8_t codebook_index, + 4, // UE category capacity + ue_template->physicalConfigDedicated->pdsch_ConfigDedicated->p_a, + 0, // delta_power_offset for TM5 + 0, // ngap + 0, // nprb + cc[CC_id].p_eNB == 1 ? 1 : 2, // transmission mode + 0, //number of PRBs treated as one subband, not used here + 0); // number of beamforming vectors, not used here + eNB->TX_req[CC_id].sfn_sf = fill_nfapi_tx_req(&eNB->TX_req[CC_id].tx_request_body, + (frameP * 10) + subframeP, + TBS, + eNB->pdu_index[CC_id], + dlsch_pdu->payload[0]); + LOG_D(MAC, "Filled NFAPI configuration for DCI/DLSCH/TXREQ %d, new SDU\n", + eNB->pdu_index[CC_id]); + eNB->pdu_index[CC_id]++; + program_dlsch_acknak(module_idP, + CC_id, + UE_id, + frameP, + subframeP, + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx); + } } } // UE_id loop stop_meas(&eNB->schedule_dlsch); diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index 07ae5e3079..692619ccfe 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -3510,6 +3510,67 @@ CCE_allocation_infeasible(int module_idP, return res; } +int CCE_try_allocate_dlsch(int module_id, + int CC_id, + int subframe, + int UE_id, + uint8_t dl_cqi) { + const rnti_t rnti = RC.mac[module_id]->UE_info.UE_template[CC_id][UE_id].rnti; + nfapi_dl_config_request_body_t *DL_req = &RC.mac[module_id]->DL_req[CC_id].dl_config_request_body; + + if (DL_req->number_pdu >= MAX_NUM_DL_PDU) { + LOG_W(MAC, "Subframe %d: FAPI DL structure is full, skip scheduling UE %d\n", subframe, rnti); + return -1; + } + + int aggregation = 2; + const uint8_t tm = get_tmode(module_id, CC_id, UE_id); + switch (tm) { + case 1: + case 2: + case 7: + aggregation = get_aggregation(get_bw_index(module_id, CC_id), + dl_cqi, + format1); + break; + + case 3: + aggregation = get_aggregation(get_bw_index(module_id, CC_id), + dl_cqi, + format2A); + break; + + default: + AssertFatal(0, "Unsupported transmission mode %d\n", tm); + break; + } + + nfapi_dl_config_request_pdu_t *dl_config_pdu = &DL_req->dl_config_pdu_list[DL_req->number_pdu]; + memset(dl_config_pdu, 0, sizeof(nfapi_dl_config_request_pdu_t)); + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG; + dl_config_pdu->pdu_type = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti = rnti; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type = 1; + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = aggregation; + DL_req->number_pdu++; + LOG_D(MAC, "Subframe %d: Checking CCE feasibility format 1: (%x,%d) \n", + subframe, rnti, aggregation); + + if (allocate_CCEs(module_id, CC_id, 0, subframe, 0) < 0) { + DL_req->number_pdu--; + return -1; + } + + DL_req->number_dci++; + nfapi_dl_config_request_pdu_t *dl_dlsch_pdu = &DL_req->dl_config_pdu_list[DL_req->number_pdu]; + dl_dlsch_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; + dl_dlsch_pdu->dlsch_pdu.dlsch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG; + dl_dlsch_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = rnti; + DL_req->number_pdu++; + + return DL_req->number_pdu - 2; +} + //------------------------------------------------------------------------------ void get_retransmission_timing(LTE_TDD_Config_t *tdd_Config, diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h index feba483147..91cd447d09 100644 --- a/openair2/LAYER2/MAC/mac.h +++ b/openair2/LAYER2/MAC/mac.h @@ -933,6 +933,7 @@ typedef struct { uint8_t dl_pow_off[NFAPI_CC_MAX]; uint16_t pre_nb_available_rbs[NFAPI_CC_MAX]; unsigned char rballoc_sub_UE[NFAPI_CC_MAX][N_RBG_MAX]; + int pre_dci_dl_pdu_idx; uint16_t ta_timer; int16_t ta_update; uint16_t ul_consecutive_errors; diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index 289973cd30..f321494568 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -413,6 +413,12 @@ boolean_t CCE_allocation_infeasible(int module_idP, int common_flag, int subframe, int aggregation, int rnti); +/* tries to allocate a CCE. If it succeeds, reserves NFAPI DCI and DLSCH config */ +int CCE_try_allocate_dlsch(int module_id, + int CC_id, + int subframe, + int UE_id, + uint8_t dl_cqi); void set_ue_dai(sub_frame_t subframeP, int UE_id, diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index aeb432f64e..478c9effe0 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -293,6 +293,7 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, ue_sched_ctrl->pre_nb_available_rbs[CC_id] = 0; ue_sched_ctrl->dl_pow_off[CC_id] = 2; memset(ue_sched_ctrl->rballoc_sub_UE[CC_id], 0, sizeof(ue_sched_ctrl->rballoc_sub_UE[CC_id])); + ue_sched_ctrl->pre_dci_dl_pdu_idx = -1; const rnti_t rnti = UE_RNTI(Mod_id, UE_id); if (rnti == NOT_A_RNTI) { From c76af0a142e8679c9646ef1ed1900987bc693c36 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 4 Apr 2020 14:53:06 +0200 Subject: [PATCH 140/240] Check for CCE allocation in DL PP --- openair2/LAYER2/MAC/pre_processor.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 478c9effe0..5e1e6c2fcd 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -90,12 +90,18 @@ int round_robin_dl(module_id_t Mod_id, const uint8_t round = ue_ctrl->round[CC_id][harq_pid]; if (round != 8) { // retransmission: allocate int nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid]; - if (nb_rb % RBGsize != 0) { + if (nb_rb == 0) + continue; + if (nb_rb % RBGsize != 0) nb_rb += nb_rb % RBGsize; // should now divide evenly - } int nb_rbg = nb_rb / RBGsize; if (nb_rbg > n_rbg_sched) // needs more RBGs than we can allocate continue; + const uint8_t cqi = ue_ctrl->dl_cqi[CC_id]; + const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi); + if (idx < 0) + continue; // cannot allocate CCE + ue_ctrl->pre_dci_dl_pdu_idx = idx; // retransmissions: directly allocate n_rbg_sched -= nb_rbg; ue_ctrl->pre_nb_available_rbs[CC_id] += nb_rb; @@ -155,8 +161,16 @@ int round_robin_dl(module_id_t Mod_id, while (num_ue_sched < max_num_ue) { while (rb_required[UE_id] == 0) UE_id = next_ue_list_looped(UE_list, UE_id); - /* TODO: check that CCE allocation is feasible. If it is not, reduce - * num_ue_req anyway because this would have been one opportunity */ + const uint8_t cqi = UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]; + const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi); + if (idx < 0) { + LOG_D(MAC, "cannot allocate CCE for UE %d, skipping\n", UE_id); + num_ue_req--; + max_num_ue = min(min(max_num_ue, num_ue_req), n_rbg_sched); + UE_id = next_ue_list_looped(UE_list, UE_id); // next candidate + continue; + } + UE_info->UE_sched_ctrl[UE_id].pre_dci_dl_pdu_idx = idx; *cur_UE = UE_id; cur_UE = &UE_sched.next[UE_id]; rb_required_total += rb_required[UE_id]; @@ -347,7 +361,7 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, frameP, subframeP, &UE_to_sched, - 3, // max_num_ue + 4, // max_num_ue n_rbg_sched, rbgalloc_mask); From 36ebfe04f6ee1f5a86f56fac18a808fee736b3b9 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 5 Apr 2020 11:39:47 +0200 Subject: [PATCH 141/240] Use CCE_try_allocate_ulsch() in ULSCH --- .../LAYER2/MAC/eNB_scheduler_primitives.c | 54 +++++++++++++++++ openair2/LAYER2/MAC/eNB_scheduler_ulsch.c | 59 +++++++------------ openair2/LAYER2/MAC/mac_proto.h | 7 +++ 3 files changed, 82 insertions(+), 38 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index 692619ccfe..78d6f6a3d7 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -3571,6 +3571,60 @@ int CCE_try_allocate_dlsch(int module_id, return DL_req->number_pdu - 2; } +int CCE_try_allocate_ulsch(int module_id, + int CC_id, + int subframe, + int UE_id, + uint8_t dl_cqi) { + const rnti_t rnti = RC.mac[module_id]->UE_info.UE_template[CC_id][UE_id].rnti; + nfapi_hi_dci0_request_body_t *HI_DCI0_req = &RC.mac[module_id]->HI_DCI0_req[CC_id][subframe].hi_dci0_request_body; + + if (HI_DCI0_req->number_of_dci + HI_DCI0_req->number_of_hi >= MAX_NUM_HI_DCI0_PDU) { + LOG_W(MAC, "Subframe %d: FAPI UL structure is full, skip scheduling UE %d\n", subframe, rnti); + return -1; + } + + int aggregation = 2; + const uint8_t tm = get_tmode(module_id, CC_id, UE_id); + switch (tm) { + case 1: + case 2: + case 7: + aggregation = get_aggregation(get_bw_index(module_id, CC_id), + dl_cqi, + format1); + break; + + case 3: + aggregation = get_aggregation(get_bw_index(module_id, CC_id), + dl_cqi, + format2A); + break; + + default: + AssertFatal(0, "Unsupported transmission mode %d\n", tm); + break; + } + + const int idx = HI_DCI0_req->number_of_dci + HI_DCI0_req->number_of_hi; + nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[idx]; + memset(hi_dci0_pdu, 0, sizeof(nfapi_hi_dci0_request_pdu_t)); + hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_DCI_PDU_TYPE; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.tl.tag = NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti; + hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation; + HI_DCI0_req->number_of_dci++; + LOG_D(MAC, "%s() sf %d: Checking CCE feasibility format 2: RNTI %04x, agg %d\n", + __func__, subframe, rnti, aggregation); + + if (allocate_CCEs(module_id, CC_id, 0, subframe, 0) < 0) { + HI_DCI0_req->number_of_dci--; + return -1; + } + + return idx; +} + //------------------------------------------------------------------------------ void get_retransmission_timing(LTE_TDD_Config_t *tdd_Config, diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index 88c5e20c27..52c930113f 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -1273,7 +1273,6 @@ schedule_ulsch_rnti(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP, unsigned char sched_subframeP) { - const uint8_t aggregation = 2; /* TODO: does this need to be static? */ static int32_t tpc_accumulated = 0; /* values from 0 to 7 can be used for mapping the cyclic shift @@ -1344,19 +1343,7 @@ schedule_ulsch_rnti(module_id_t module_idP, round_index, UE_id, rnti); - LOG_D(MAC, - "[eNB %d] %d.%d (sched %d.%d), " - "Checking PUSCH %d for UE %d/%x CC %d : aggregation level %d\n", - module_idP, - frameP, - subframeP, - sched_frame, - sched_subframeP, - harq_pid, - UE_id, - rnti, - CC_id, - aggregation); + /* Seems unused, only for debug */ RC.eNB[module_idP][CC_id]->pusch_stats_BO[UE_id][(frameP * 10) + subframeP] = UE_template_ptr->estimated_ul_buffer; @@ -1366,15 +1353,25 @@ schedule_ulsch_rnti(module_id_t module_idP, if (UE_template_ptr->pre_allocated_nb_rb_ul < 1) continue; - if (CCE_allocation_infeasible(module_idP, CC_id, 2, subframeP, aggregation, rnti)) { - LOG_W(MAC, - "[eNB %d] %d.%d, UE %d/%x CC %d: not enough CCE\n", - module_idP, - frameP, - subframeP, + int dci_ul_pdu_idx = -1; + if (dci_ul_pdu_idx < 0) { + dci_ul_pdu_idx = CCE_try_allocate_ulsch( + module_idP, CC_id, subframeP, UE_id, UE_sched_ctrl_ptr->dl_cqi[CC_id]); + if (dci_ul_pdu_idx < 0) { + LOG_W(MAC ,"%4d.%d: Dropping UL Allocation for RNTI 0x%04x/UE %d\n", + frameP, subframeP, rnti, UE_id); + continue; + } + } + + /* verify it is the right UE */ + hi_dci0_pdu = &hi_dci0_req_body->hi_dci0_pdu_list[dci_ul_pdu_idx]; + if (hi_dci0_pdu->pdu_type != NFAPI_HI_DCI0_DCI_PDU_TYPE + || hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti != rnti) { + LOG_E(MAC, "illegal hi_dci0_pdu_list index %d for UE %d/RNTI %04x\n", + dci_ul_pdu_idx, UE_id, - rnti, - CC_id); + rnti); continue; } @@ -1429,7 +1426,6 @@ schedule_ulsch_rnti(module_id_t module_idP, tpc_accumulated++; } } - if (tpc != 1) { LOG_D(MAC, "[eNB %d] ULSCH scheduler: frame %d, subframe %d, harq_pid %d, " @@ -1562,15 +1558,9 @@ schedule_ulsch_rnti(module_id_t module_idP, /* Save it for a potential retransmission */ UE_template_ptr->cshift[harq_pid] = cshift; /* Setting DCI0 NFAPI struct */ - hi_dci0_pdu = &hi_dci0_req_body->hi_dci0_pdu_list[hi_dci0_req_body->number_of_dci + hi_dci0_req_body->number_of_hi]; - memset((void *)hi_dci0_pdu, 0, sizeof(nfapi_hi_dci0_request_pdu_t)); - hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_DCI_PDU_TYPE; + hi_dci0_pdu = &hi_dci0_req_body->hi_dci0_pdu_list[dci_ul_pdu_idx]; hi_dci0_pdu->pdu_size = 2 + sizeof(nfapi_hi_dci0_dci_pdu); - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.tl.tag = - NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG; hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dci_format = NFAPI_UL_DCI_FORMAT_0; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti; hi_dci0_pdu->dci_pdu.dci_pdu_rel8.transmission_power = 6000; hi_dci0_pdu->dci_pdu.dci_pdu_rel8.resource_block_start = UE_template_ptr->pre_first_nb_rb_ul; hi_dci0_pdu->dci_pdu.dci_pdu_rel8.number_of_resource_block = @@ -1584,7 +1574,6 @@ schedule_ulsch_rnti(module_id_t module_idP, hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dl_assignment_index = UE_template_ptr->DAI_ul[sched_subframeP]; hi_dci0_pdu->dci_pdu.dci_pdu_rel8.harq_pid = harq_pid; - hi_dci0_req_body->number_of_dci++; hi_dci0_req_body->sfnsf = sfnsf_add_subframe(sched_frame, sched_subframeP, 0); hi_dci0_req_body->tl.tag = NFAPI_HI_DCI0_REQUEST_BODY_TAG; @@ -1746,14 +1735,9 @@ schedule_ulsch_rnti(module_id_t module_idP, sched_frame, sched_subframeP); - hi_dci0_pdu = &hi_dci0_req_body->hi_dci0_pdu_list[hi_dci0_req_body->number_of_dci + hi_dci0_req_body->number_of_hi]; - memset((void *)hi_dci0_pdu, 0, sizeof(nfapi_hi_dci0_request_pdu_t)); - hi_dci0_pdu->pdu_type = NFAPI_HI_DCI0_DCI_PDU_TYPE; + hi_dci0_pdu = &hi_dci0_req_body->hi_dci0_pdu_list[dci_ul_pdu_idx]; hi_dci0_pdu->pdu_size = 2 + sizeof(nfapi_hi_dci0_dci_pdu); - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.tl.tag = NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG; hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dci_format = NFAPI_UL_DCI_FORMAT_0; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation; - hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti = rnti; hi_dci0_pdu->dci_pdu.dci_pdu_rel8.transmission_power = 6000; hi_dci0_pdu->dci_pdu.dci_pdu_rel8.resource_block_start = first_rb; hi_dci0_pdu->dci_pdu.dci_pdu_rel8.number_of_resource_block = nb_rb; @@ -1765,7 +1749,6 @@ schedule_ulsch_rnti(module_id_t module_idP, hi_dci0_pdu->dci_pdu.dci_pdu_rel8.cqi_csi_request = UE_template_ptr->cqi_req[harq_pid]; hi_dci0_pdu->dci_pdu.dci_pdu_rel8.dl_assignment_index = UE_template_ptr->DAI_ul[sched_subframeP]; hi_dci0_pdu->dci_pdu.dci_pdu_rel8.harq_pid = harq_pid; - hi_dci0_req_body->number_of_dci++; uint16_t ul_req_index = 0; uint8_t dlsch_flag = 0; diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index f321494568..2cb86c25af 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -420,6 +420,13 @@ int CCE_try_allocate_dlsch(int module_id, int UE_id, uint8_t dl_cqi); +/* tries to allocate a CCE for UL. If it succeeds, reserves the NFAPI DCI */ +int CCE_try_allocate_ulsch(int module_id, + int CC_id, + int subframe, + int UE_id, + uint8_t dl_cqi); + void set_ue_dai(sub_frame_t subframeP, int UE_id, uint8_t CC_id, uint8_t tdd_config, UE_info_t *UE_info); From 1372e0220683b8bafc723c4e5d33dedd13619dd6 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 5 Apr 2020 15:59:14 +0200 Subject: [PATCH 142/240] Check for CCE allocation in UL PP --- openair2/LAYER2/MAC/eNB_scheduler_ulsch.c | 2 +- openair2/LAYER2/MAC/mac.h | 3 +++ openair2/LAYER2/MAC/pre_processor.c | 21 ++++++++++++++++++--- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index 52c930113f..656dd885df 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -1353,7 +1353,7 @@ schedule_ulsch_rnti(module_id_t module_idP, if (UE_template_ptr->pre_allocated_nb_rb_ul < 1) continue; - int dci_ul_pdu_idx = -1; + int dci_ul_pdu_idx = UE_template_ptr->pre_dci_ul_pdu_idx; if (dci_ul_pdu_idx < 0) { dci_ul_pdu_idx = CCE_try_allocate_ulsch( module_idP, CC_id, subframeP, UE_id, UE_sched_ctrl_ptr->dl_cqi[CC_id]); diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h index 91cd447d09..329e262c82 100644 --- a/openair2/LAYER2/MAC/mac.h +++ b/openair2/LAYER2/MAC/mac.h @@ -831,6 +831,9 @@ typedef struct { /// index of Allocated RBs by the ulsch preprocessor int8_t pre_allocated_rb_table_index_ul; + /// index of allocated HI_DCI0 + int pre_dci_ul_pdu_idx; + /// total allocated RBs int8_t total_allocated_rbs; diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 5e1e6c2fcd..d649832090 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -509,6 +509,11 @@ int round_robin_ul(module_id_t Mod_id, UE_info->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid]); continue; } + const uint8_t cqi = UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]; + const int idx = CCE_try_allocate_ulsch(Mod_id, CC_id, subframe, UE_id, cqi); + if (idx < 0) + continue; // cannot allocate CCE + UE_template->pre_dci_ul_pdu_idx = idx; if (rbs[0].length >= nb_rb) { // fits in first contiguous region UE_template->pre_first_nb_rb_ul = rbs[0].start; rbs[0].length -= nb_rb; @@ -531,6 +536,8 @@ int round_robin_ul(module_id_t Mod_id, "cannot allocate UL retransmission for UE %d (nb_rb %d)\n", UE_id, nb_rb); + UE_template->pre_dci_ul_pdu_idx = -1; // do not need CCE + RC.mac[Mod_id]->HI_DCI0_req[CC_id][subframe].hi_dci0_request_body.number_of_dci--; continue; } LOG_D(MAC, "%4d.%d UE %d retx %d RBs at start %d\n", @@ -640,8 +647,15 @@ int round_robin_ul(module_id_t Mod_id, while (num_ue_sched < nr[r]) { while (rb_idx_required[sUE_id] == 0) sUE_id = next_ue_list_looped(UE_list, sUE_id); - /* TODO: check that CCE allocated is feasible. If it is not, reduce - * nr[r] by one as this would been one opportunity */ + const int cqi = UE_info->UE_sched_ctrl[sUE_id].dl_cqi[CC_id]; + const int idx = CCE_try_allocate_ulsch(Mod_id, CC_id, subframe, sUE_id, cqi); + if (idx < 0) { + LOG_D(MAC, "cannot allocate CCE for UE %d, skipping\n", sUE_id); + nr[r]--; + sUE_id = next_ue_list_looped(UE_list, sUE_id); // next candidate + continue; + } + UE_info->UE_template[CC_id][sUE_id].pre_dci_ul_pdu_idx = idx; *cur_UE = sUE_id; cur_UE = &UE_sched.next[sUE_id]; rb_idx_given[sUE_id] = min(start_idx, rb_idx_required[sUE_id]); @@ -729,6 +743,7 @@ void ulsch_scheduler_pre_processor(module_id_t Mod_id, UE_template->pre_allocated_nb_rb_ul = 0; UE_template->pre_allocated_rb_table_index_ul = -1; UE_template->pre_first_nb_rb_ul = 0; + UE_template->pre_dci_ul_pdu_idx = -1; const rnti_t rnti = UE_RNTI(Mod_id, UE_id); if (rnti == NOT_A_RNTI) { @@ -775,7 +790,7 @@ void ulsch_scheduler_pre_processor(module_id_t Mod_id, sched_frameP, sched_subframeP, &UE_to_sched, - 3, // max_num_ue + 4, // max_num_ue n_contig, rbs); From eff978af5d67e34f4e3527f4fbaf0ce38f82039b Mon Sep 17 00:00:00 2001 From: Gabriele Perrone Date: Mon, 6 Apr 2020 14:54:13 +0200 Subject: [PATCH 143/240] debugging --- ci-scripts/main.py | 8 +++++++- ci-scripts/sshconnection.py | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 94a7a52dc6..5d143eece6 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -750,8 +750,12 @@ class OaiCiTest(): SSH.command('stdbuf -o0 adb -s ' + device_id + ' shell "dumpsys telephony.registry" | grep -m 1 mDataConnectionState', '\$', 15) else: SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\' | grep -m 1 mDataConnectionState', '\$', 60) - print('#GP: in SSH.getBefore() K=0 (it was K=2 in main.py)') result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', SSH.getBefore()) + print("\n") + print(SSH.getBefore()) + print("\n") + print(result) + print("\n") if result is None: logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m') lock.acquire() @@ -761,6 +765,8 @@ class OaiCiTest(): lock.release() break mDataConnectionState = int(result.group('state')) + print(mDataConnectionState) + print("\n") if mDataConnectionState == 2: logging.debug('\u001B[1mUE (' + device_id + ') Attach Completed\u001B[0m') lock.acquire() diff --git a/ci-scripts/sshconnection.py b/ci-scripts/sshconnection.py index ecaf8f4116..6fad5065e2 100644 --- a/ci-scripts/sshconnection.py +++ b/ci-scripts/sshconnection.py @@ -87,7 +87,7 @@ class SSHConnection(): if connect_status: pass else: - sys.exit('CiTestObj.Connection Failed') + sys.exit('SSH Connection Failed') def command(self, commandline, expectedline, timeout): From 564db9c398c1ca0ea93ce5d4ecbb894c1bb33d3b Mon Sep 17 00:00:00 2001 From: Gabriele Perrone Date: Mon, 6 Apr 2020 15:20:02 +0200 Subject: [PATCH 144/240] debugging --- ci-scripts/main.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 5d143eece6..0501cd263e 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -751,11 +751,7 @@ class OaiCiTest(): else: SSH.command('ssh ' + self.UEDevicesRemoteUser[idx] + '@' + self.UEDevicesRemoteServer[idx] + ' \'adb -s ' + device_id + ' shell "dumpsys telephony.registry"\' | grep -m 1 mDataConnectionState', '\$', 60) result = re.search('mDataConnectionState.*=(?P[0-9\-]+)', SSH.getBefore()) - print("\n") - print(SSH.getBefore()) - print("\n") - print(result) - print("\n") + print(SSH.getBefore()) #GP debugging if result is None: logging.debug('\u001B[1;37;41m mDataConnectionState Not Found! \u001B[0m') lock.acquire() @@ -765,8 +761,6 @@ class OaiCiTest(): lock.release() break mDataConnectionState = int(result.group('state')) - print(mDataConnectionState) - print("\n") if mDataConnectionState == 2: logging.debug('\u001B[1mUE (' + device_id + ') Attach Completed\u001B[0m') lock.acquire() From 9a136695523d7525bf01c02404d9a790a6870145 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Mon, 6 Apr 2020 16:33:40 +0200 Subject: [PATCH 145/240] CI: adding a few checks before loading images in R2LAB Signed-off-by: Raphael Defosseux --- ci-scripts/Jenkinsfile-inria-r2lab | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ci-scripts/Jenkinsfile-inria-r2lab b/ci-scripts/Jenkinsfile-inria-r2lab index 3c4dddae8b..7e797fdf14 100644 --- a/ci-scripts/Jenkinsfile-inria-r2lab +++ b/ci-scripts/Jenkinsfile-inria-r2lab @@ -142,6 +142,12 @@ pipeline { stage ("Load Images") { steps { script { + // Adding a tempo after booking leases + sh "sleep 10" + sh "ssh -t inria_oaici@faraday.inria.fr 'rleases --check'" + sh "ssh -t inria_oaici@faraday.inria.fr 'all-off'" + sh "sleep 10" + echo '\u2705 \u001B[32mLoad Image for Python Executor\u001B[0m' sh "ssh -t inria_oaici@faraday.inria.fr 'rload -i oai-ci-cd-u18-lowlatency-enb-ue ${r2labPythonExeIdx} > /dev/null 2>&1'" sh "ssh -t inria_oaici@faraday.inria.fr 'rwait --silent ${r2labPythonExeIdx}'" From 8bef0d1d612b19591296420858a4895b4f5fad02 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Tue, 7 Apr 2020 12:24:08 +0200 Subject: [PATCH 146/240] CI: adding some try/catches and more debug to see what is going on --> failure to load images since 2 weeks Signed-off-by: Raphael Defosseux --- ci-scripts/Jenkinsfile-inria-r2lab | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/ci-scripts/Jenkinsfile-inria-r2lab b/ci-scripts/Jenkinsfile-inria-r2lab index 7e797fdf14..ca6893dc4f 100644 --- a/ci-scripts/Jenkinsfile-inria-r2lab +++ b/ci-scripts/Jenkinsfile-inria-r2lab @@ -149,12 +149,32 @@ pipeline { sh "sleep 10" echo '\u2705 \u001B[32mLoad Image for Python Executor\u001B[0m' - sh "ssh -t inria_oaici@faraday.inria.fr 'rload -i oai-ci-cd-u18-lowlatency-enb-ue ${r2labPythonExeIdx} > /dev/null 2>&1'" - sh "ssh -t inria_oaici@faraday.inria.fr 'rwait --silent ${r2labPythonExeIdx}'" + try { + //sh "ssh -t inria_oaici@faraday.inria.fr 'rload -i oai-ci-cd-u18-lowlatency-enb-ue ${r2labPythonExeIdx} > /dev/null 2>&1'" + sh "ssh -t inria_oaici@faraday.inria.fr 'rload -i oai-ci-cd-u18-lowlatency-enb-ue ${r2labPythonExeIdx}'" + } catch (Exception e) { + echo "Why is it wrong?" + } + try { + //sh "ssh -t inria_oaici@faraday.inria.fr 'rwait --silent ${r2labPythonExeIdx}'" + sh "ssh -t inria_oaici@faraday.inria.fr 'rwait ${r2labPythonExeIdx}'" + } catch (Exception e) { + echo "Why is it wrong?" + } echo '\u2705 \u001B[32mLoad Image for two (2) eNBs\u001B[0m' - sh "ssh -t inria_oaici@faraday.inria.fr 'rload -i oai-ci-cd-u18-lowlatency-enb-ue ${r2labENB0Idx},${r2labENB1Idx} > /dev/null 2>&1'" - sh "ssh -t inria_oaici@faraday.inria.fr 'rwait --silent ${r2labENB0Idx},${r2labENB1Idx}'" + try { + //sh "ssh -t inria_oaici@faraday.inria.fr 'rload -i oai-ci-cd-u18-lowlatency-enb-ue ${r2labENB0Idx},${r2labENB1Idx} > /dev/null 2>&1'" + sh "ssh -t inria_oaici@faraday.inria.fr 'rload -i oai-ci-cd-u18-lowlatency-enb-ue ${r2labENB0Idx},${r2labENB1Idx}" + } catch (Exception e) { + echo "Why is it wrong?" + } + try { + //sh "ssh -t inria_oaici@faraday.inria.fr 'rwait --silent ${r2labENB0Idx},${r2labENB1Idx}'" + sh "ssh -t inria_oaici@faraday.inria.fr 'rwait ${r2labENB0Idx},${r2labENB1Idx}'" + } catch (Exception e) { + echo "Why is it wrong?" + } sh "ssh -t inria_oaici@faraday.inria.fr 'uon ${r2labENB0Idx},${r2labENB1Idx}'" sh "sleep 5" sh "ssh -t inria_oaici@faraday.inria.fr 'uon ${r2labENB0Idx},${r2labENB1Idx}'" From be9d4e1b55c64a3a600576ddf17877c574821e0e Mon Sep 17 00:00:00 2001 From: Gabriele Perrone Date: Tue, 7 Apr 2020 16:10:58 +0200 Subject: [PATCH 147/240] after full run of enb_usrp210_band7_test_05mhz_tm1.xml commit the latest changes; then I will create an integration branch to run CI --- ci-scripts/main.py | 1 - ci-scripts/xml_files/enb_usrp210_band7_test_05mhz_tm1.xml | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 0501cd263e..11686601b4 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -1235,7 +1235,6 @@ class OaiCiTest(): SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) idx = 0 for device_id in self.UEDevices: - print('UE status attched'+CONST.UE_STATUS_ATTACHED) if self.UEDevicesStatus[idx] != CONST.UE_STATUS_ATTACHED: idx += 1 continue 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 6bc60b113a..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 @@ -108,7 +108,7 @@ Initialize_eNB Initialize eNB (FDD/Band7/5MHz) - -O ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf --eNBs.[0].plmn_list.[0].mnc 93 + -O ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf From d15d86cf0c62a729c091bf3d5bd21ebb3d81e71c Mon Sep 17 00:00:00 2001 From: Gabriele Perrone Date: Tue, 7 Apr 2020 19:20:30 +0200 Subject: [PATCH 148/240] Update README.md --- targets/ARCH/rfsimulator/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/targets/ARCH/rfsimulator/README.md b/targets/ARCH/rfsimulator/README.md index 421cc662bb..f841c324c0 100644 --- a/targets/ARCH/rfsimulator/README.md +++ b/targets/ARCH/rfsimulator/README.md @@ -1,3 +1,10 @@ +# :construction: **WORK IN PROGRESS** :exclamation: + +# **PLEASE IGNORE THE FOLLOWING PAGE** :exclamation: + + + + # General This is an RF simulator that allows to test OAI without an RF board. It replaces an actual RF board driver. From b568d5b01af488908a200c9d1c45d58278f6faba Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 9 Apr 2020 22:25:02 +0200 Subject: [PATCH 149/240] removed faulty entries in ci unitary simulators and SNR starting point for nr_ulsim tests --- cmake_targets/autotests/test_case_list.xml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 7908772bb6..085e5fb07b 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1104,8 +1104,7 @@ -n100 -R217 -a80 -s5 -n100 -R217 -a110 -s5 -b100 -n100 -e27 -s30 - -n100 -e16 -s10 - + -n100 -e16 -s10 nr_dlsim.test1 nr_dlsim.test2 nr_dlsim.test3 nr_dlsim.test4 nr_dlsim.test5 nr_dlsim.test6 nr_dlsim.test7 nr_dlsim.test8 nr_dlsim.test9 nr_dlsim.test10 PDSCH test OK segmentation fault|assertion|exiting|fatal @@ -1245,11 +1244,11 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/targets/bin/nr_ulsim.Rel15 - -n100 -m9 -r106 -s0 + -n100 -m9 -r106 -s5 -n100 -m16 -s10 -n100 -m28 -s20 - -n100 -m9 -R217 -r217 -s0 - -n100 -m9 -R273 -r273 -s0 + -n100 -m9 -R217 -r217 -s5 + -n100 -m9 -R273 -r273 -s5 nr_ulsim.test1 nr_ulsim.test2 nr_ulsim.test3 nr_ulsim.test4 nr_ulsim.test5 PUSCH test OK segmentation fault|assertion|exiting|fatal From 8f450f0e516955b33ab2decedd684a13ffb1679e Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 9 Apr 2020 16:49:46 +0200 Subject: [PATCH 150/240] DL PP: consider the last RBG might be smaller --- openair2/LAYER2/MAC/pre_processor.c | 40 +++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index d649832090..c4dd6b8419 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -59,6 +59,15 @@ int next_ue_list_looped(UE_list_t* list, int UE_id) { return list->next[UE_id] < 0 ? list->head : list->next[UE_id]; } +int get_rbg_size_last(module_id_t Mod_id, int CC_id) { + const int RBGsize = get_min_rb_unit(Mod_id, CC_id); + const int N_RB_DL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); + if (N_RB_DL == 15 || N_RB_DL == 25 || N_RB_DL == 50 || N_RB_DL == 75) + return RBGsize - 1; + else + return RBGsize; +} + int g_start_ue_dl = -1; int round_robin_dl(module_id_t Mod_id, int CC_id, @@ -70,7 +79,9 @@ int round_robin_dl(module_id_t Mod_id, uint8_t *rbgalloc_mask) { DevAssert(UE_list->head >= 0); DevAssert(n_rbg_sched > 0); + const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); const int RBGsize = get_min_rb_unit(Mod_id, CC_id); + const int RBGlastsize = get_rbg_size_last(Mod_id, CC_id); int num_ue_req = 0; UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; @@ -89,14 +100,26 @@ int round_robin_dl(module_id_t Mod_id, UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id]; const uint8_t round = ue_ctrl->round[CC_id][harq_pid]; if (round != 8) { // retransmission: allocate - int nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid]; + const int nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid]; if (nb_rb == 0) continue; - if (nb_rb % RBGsize != 0) - nb_rb += nb_rb % RBGsize; // should now divide evenly - int nb_rbg = nb_rb / RBGsize; - if (nb_rbg > n_rbg_sched) // needs more RBGs than we can allocate + int nb_rbg = (nb_rb + (nb_rb % RBGsize)) / RBGsize; + // needs more RBGs than we can allocate + if (nb_rbg > n_rbg_sched) { + LOG_D(MAC, + "retransmission of UE %d needs more RBGs (%d) than we have (%d)\n", + UE_id, nb_rbg, n_rbg_sched); continue; + } + // ensure that the number of RBs can be contained by the RBGs (!), i.e. + // if we allocate the last RBG this one should have the full RBGsize + if ((nb_rb % RBGsize) == 0 && nb_rbg == n_rbg_sched + && rbgalloc_mask[N_RBG - 1] && RBGlastsize != RBGsize) { + LOG_D(MAC, + "retransmission of UE %d needs %d RBs, but the last RBG %d is too small (%d, normal %d)\n", + UE_id, nb_rb, N_RBG - 1, RBGlastsize, RBGsize); + continue; + } const uint8_t cqi = ue_ctrl->dl_cqi[CC_id]; const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi); if (idx < 0) @@ -186,9 +209,10 @@ int round_robin_dl(module_id_t Mod_id, continue; UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id]; ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1; - ue_ctrl->pre_nb_available_rbs[CC_id] += RBGsize; - rb_required[UE_id] -= RBGsize; - rb_required_total -= RBGsize; + const int sRBG = rbg == N_RBG - 1 ? RBGlastsize : RBGsize; + ue_ctrl->pre_nb_available_rbs[CC_id] += sRBG; + rb_required[UE_id] -= sRBG; + rb_required_total -= sRBG; if (rb_required_total <= 0) break; n_rbg_sched--; From 382b815fa453333513d6a09fb588f4f839598eb8 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 9 Apr 2020 22:06:25 +0200 Subject: [PATCH 151/240] Remove AssertFatal from UCI handlers --- openair1/SCHED/fapi_l1.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/openair1/SCHED/fapi_l1.c b/openair1/SCHED/fapi_l1.c index 4ce89775c7..16fcc75a79 100644 --- a/openair1/SCHED/fapi_l1.c +++ b/openair1/SCHED/fapi_l1.c @@ -597,7 +597,6 @@ void handle_uci_sr_pdu(PHY_VARS_eNB *eNB, uci->subframe = subframe; uci->rnti = ul_config_pdu->uci_sr_pdu.ue_information.ue_information_rel8.rnti; uci->ue_id = find_ulsch(ul_config_pdu->uci_sr_pdu.ue_information.ue_information_rel8.rnti,eNB,SEARCH_EXIST_OR_FREE); - AssertFatal(uci->ue_id < MAX_MOBILES_PER_ENB, "illegal UE_id %d\n", uci->ue_id); uci->type = SR; uci->pucch_fmt = pucch_format1; uci->num_antenna_ports = 1; @@ -624,7 +623,6 @@ void handle_uci_sr_harq_pdu(PHY_VARS_eNB *eNB,int UE_id,nfapi_ul_config_request_ uci->subframe = subframe; uci->rnti = ul_config_pdu->uci_sr_harq_pdu.ue_information.ue_information_rel8.rnti; uci->ue_id = find_ulsch(ul_config_pdu->uci_sr_harq_pdu.ue_information.ue_information_rel8.rnti,eNB,SEARCH_EXIST_OR_FREE); - AssertFatal(uci->ue_id < MAX_MOBILES_PER_ENB, "illegal UE_id %d\n", uci->ue_id); uci->type = HARQ_SR; uci->num_antenna_ports = 1; uci->num_pucch_resources = 1; @@ -647,7 +645,6 @@ void handle_uci_harq_pdu(PHY_VARS_eNB *eNB,int UE_id,nfapi_ul_config_request_pdu uci->subframe = subframe; uci->rnti = ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.rnti; uci->ue_id = find_ulsch(ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.rnti,eNB,SEARCH_EXIST_OR_FREE); - AssertFatal(uci->ue_id < MAX_MOBILES_PER_ENB, "illegal UE_id %d\n", uci->ue_id); uci->type = HARQ; uci->srs_active = srs_active; uci->num_antenna_ports = ul_config_pdu->uci_harq_pdu.harq_information.harq_information_rel11.num_ant_ports; From 0bef57e2d4a843c3c15d0a13d994880f5f836f27 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Mar 2020 09:31:59 +0100 Subject: [PATCH 152/240] L2 sim: fix PDU_index test --- openair2/PHY_INTERFACE/phy_stub_UE.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/PHY_INTERFACE/phy_stub_UE.c b/openair2/PHY_INTERFACE/phy_stub_UE.c index bf2bbf7429..4d3b579f84 100644 --- a/openair2/PHY_INTERFACE/phy_stub_UE.c +++ b/openair2/PHY_INTERFACE/phy_stub_UE.c @@ -740,7 +740,7 @@ int dl_config_req_UE_MAC(nfapi_dl_config_request_t* req, module_id_t Mod_id) { continue; } const int pdu_index = dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index; - if (pdu_index < 0 && pdu_index >= tx_req_num_elems) { + if (pdu_index < 0 || pdu_index >= tx_req_num_elems) { LOG_E(MAC, "dl_config_req_UE_MAC 2: Problem with receiving data: " "sfn/sf:%d PDU[%d] size:%d, TX_PDU index: %d\n", From 4df3157a7ac681058bc5a6cef39d3c90e1ba08f1 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 19 Mar 2020 09:33:18 +0100 Subject: [PATCH 153/240] L2: do not overwrite FAPI message, correct check --- openair2/PHY_INTERFACE/phy_stub_UE.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/openair2/PHY_INTERFACE/phy_stub_UE.c b/openair2/PHY_INTERFACE/phy_stub_UE.c index 4d3b579f84..8a238fa5b5 100644 --- a/openair2/PHY_INTERFACE/phy_stub_UE.c +++ b/openair2/PHY_INTERFACE/phy_stub_UE.c @@ -791,7 +791,11 @@ int dl_config_req_UE_MAC(nfapi_dl_config_request_t* req, module_id_t Mod_id) { tx_request_pdu_list[pdu_index].segments[0].segment_data, tx_request_pdu_list[pdu_index].segments[0].segment_length); } else if (rnti == 0x0002) { /* RA-RNTI */ - LOG_E(MAC, "%s(): Received RAR?\n", __func__); + if (UE_mac_inst[Mod_id].UE_mode[0] != RA_RESPONSE) { + LOG_D(MAC, "UE %d not awaiting RAR, is in mode %d\n", + Mod_id, UE_mac_inst[Mod_id].UE_mode[0]); + continue; + } // RNTI parameter not actually used. Provided only to comply with // existing function definition. Not sure about parameters to fill // the preamble index. @@ -806,7 +810,7 @@ int dl_config_req_UE_MAC(nfapi_dl_config_request_t* req, module_id_t Mod_id) { ue_process_rar(Mod_id, 0, sfn, ra_rnti, //RA-RNTI tx_request_pdu_list[pdu_index].segments[0].segment_data, - &dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.rnti, //t-crnti + &UE_mac_inst[Mod_id].crnti, //t-crnti UE_mac_inst[Mod_id].RA_prach_resources.ra_PreambleIndex, tx_request_pdu_list[pdu_index].segments[0].segment_data); UE_mac_inst[Mod_id].UE_mode[0] = RA_RESPONSE; From a56be93e80a87da621b2d1e89215871246c1b184 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 8 Apr 2020 11:05:48 +0200 Subject: [PATCH 154/240] Reduce CPU load in PHY stub UE (L2 sim) Instead of looping over UEs and all DL config Req/HI DCI0, loop first over all DL config Req/HI DCI0, and for each, match UE. Lowers CPU traffic for high traffic situations. --- openair2/PHY_INTERFACE/phy_stub_UE.c | 291 +++++++++++---------------- openair2/PHY_INTERFACE/phy_stub_UE.h | 16 +- targets/RT/USER/lte-ue.c | 54 ++++- 3 files changed, 173 insertions(+), 188 deletions(-) diff --git a/openair2/PHY_INTERFACE/phy_stub_UE.c b/openair2/PHY_INTERFACE/phy_stub_UE.c index 8a238fa5b5..be7c578267 100644 --- a/openair2/PHY_INTERFACE/phy_stub_UE.c +++ b/openair2/PHY_INTERFACE/phy_stub_UE.c @@ -708,199 +708,142 @@ int tx_req_UE_MAC(nfapi_tx_request_t *req) { return 0; } -int dl_config_req_UE_MAC(nfapi_dl_config_request_t* req, module_id_t Mod_id) { - int sfn = NFAPI_SFNSF2SFN(req->sfn_sf); - int sf = NFAPI_SFNSF2SF(req->sfn_sf); +void dl_config_req_UE_MAC_dci(int sfn, + int sf, + nfapi_dl_config_request_pdu_t *dci, + nfapi_dl_config_request_pdu_t *dlsch, + int num_ue) { + DevAssert(dci->pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE); + DevAssert(dlsch->pdu_type == NFAPI_DL_CONFIG_DLSCH_PDU_TYPE); - nfapi_dl_config_request_pdu_t* dl_config_pdu_list = req->dl_config_request_body.dl_config_pdu_list; + const rnti_t rnti = dci->dci_dl_pdu.dci_dl_pdu_rel8.rnti; + const int rnti_type = dci->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type; + if (rnti != dlsch->dlsch_pdu.dlsch_pdu_rel8.rnti) { + LOG_E(MAC, + "%s(): sfn/sf %d.%d DLSCH PDU RNTI %x does not match DCI RNTI %x\n", + __func__, sfn, sf, rnti, dlsch->dlsch_pdu.dlsch_pdu_rel8.rnti); + return; + } - for (int i = 0; i < req->dl_config_request_body.number_pdu; i++) { - if (dl_config_pdu_list[i].pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE) { - const rnti_t rnti = dl_config_pdu_list[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti; - const int rnti_type = dl_config_pdu_list[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti_type; - /* We assume the DCI DL PDU is followed by the DLSCH (the standard is - * more free), so advance by one more and directly process the - * following DLSCH PDU */ - i++; - AssertFatal(i < req->dl_config_request_body.number_pdu, - "Need PDU following DCI at index %d, but not found\n", - i); - nfapi_dl_config_request_pdu_t *dl_config_pdu_tmp = &dl_config_pdu_list[i]; - if (dl_config_pdu_tmp->pdu_type != NFAPI_DL_CONFIG_DLSCH_PDU_TYPE) { - LOG_E(MAC, "expected DLSCH PDU at index %d\n", i); - continue; - } - if (rnti != dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.rnti) { - LOG_I(MAC, - "%s(): sfn/sf %d DLSCH PDU RNTI %x does not match DCI RNTI %x\n", - __func__, - NFAPI_SFNSF2DEC(req->sfn_sf), - rnti, - dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.rnti); - continue; - } - const int pdu_index = dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index; - if (pdu_index < 0 || pdu_index >= tx_req_num_elems) { - LOG_E(MAC, - "dl_config_req_UE_MAC 2: Problem with receiving data: " - "sfn/sf:%d PDU[%d] size:%d, TX_PDU index: %d\n", - NFAPI_SFNSF2DEC(req->sfn_sf), - i, - dl_config_pdu_list[i].pdu_size, - dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index); - continue; - } - if (rnti_type == 1) { - // C-RNTI (Normal DLSCH case) - if (UE_mac_inst[Mod_id].crnti != rnti) { - LOG_D(MAC, - "sfn/sf %d/%d DCI not for UE %d/RNTI %x but for RNTI %x, " - "skipping\n", - sfn, sf, Mod_id, UE_mac_inst[Mod_id].crnti, rnti); - continue; - } + const int pdu_index = dlsch->dlsch_pdu.dlsch_pdu_rel8.pdu_index; + if (pdu_index < 0 || pdu_index >= tx_req_num_elems) { + LOG_E(MAC, + "%s(): Problem with receiving data: " + "sfn/sf:%d.%d PDU size:%d, TX_PDU index: %d\n", + __func__, + sfn, sf, dci->pdu_size, dlsch->dlsch_pdu.dlsch_pdu_rel8.pdu_index); + return; + } + if (rnti_type == 1) { // C-RNTI (Normal DLSCH case) + for (int ue_id = 0; ue_id < num_ue; ue_id++) { + if (UE_mac_inst[ue_id].crnti == rnti) { LOG_D(MAC, - "%s() Received data: sfn/sf:%d PDU[%d] " + "%s() Received data: sfn/sf:%d.%d " "size:%d, TX_PDU index: %d, tx_req_num_elems: %d \n", __func__, - NFAPI_SFNSF2DEC(req->sfn_sf), - i, - dl_config_pdu_list[i].pdu_size, - dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.pdu_index, + sfn, sf, dci->pdu_size, + dlsch->dlsch_pdu.dlsch_pdu_rel8.pdu_index, tx_req_num_elems); - ue_send_sdu(Mod_id, 0, sfn, sf, + ue_send_sdu(ue_id, 0, sfn, sf, tx_request_pdu_list[pdu_index].segments[0].segment_data, tx_request_pdu_list[pdu_index].segments[0].segment_length, 0); - } else if (rnti_type == 2) { - if (rnti == 0xFFFF) { /* SI-RNTI */ - if (UE_mac_inst[Mod_id].UE_mode[0] == NOT_SYNCHED) { - /* this check is in the code before refactoring, but I don't know - * why. Leave it in here for the moment */ - continue; - } - - ue_decode_si(Mod_id, 0, sfn, 0, - tx_request_pdu_list[pdu_index].segments[0].segment_data, - tx_request_pdu_list[pdu_index].segments[0].segment_length); - } else if (rnti == 0xFFFE) { /* PI-RNTI */ - LOG_I(MAC, "%s() Received paging message: sfn/sf:%d PDU[%d]\n", - __func__, NFAPI_SFNSF2DEC(req->sfn_sf), i); - ue_decode_p(Mod_id, 0, sfn, 0, - tx_request_pdu_list[pdu_index].segments[0].segment_data, - tx_request_pdu_list[pdu_index].segments[0].segment_length); - } else if (rnti == 0x0002) { /* RA-RNTI */ - if (UE_mac_inst[Mod_id].UE_mode[0] != RA_RESPONSE) { - LOG_D(MAC, "UE %d not awaiting RAR, is in mode %d\n", - Mod_id, UE_mac_inst[Mod_id].UE_mode[0]); - continue; - } - // RNTI parameter not actually used. Provided only to comply with - // existing function definition. Not sure about parameters to fill - // the preamble index. - const rnti_t ra_rnti = UE_mac_inst[Mod_id].RA_prach_resources.ra_RNTI; - DevAssert(ra_rnti == 0x0002); - if (UE_mac_inst[Mod_id].UE_mode[0] != PUSCH - && UE_mac_inst[Mod_id].RA_prach_resources.Msg3 != NULL - && ra_rnti == dl_config_pdu_tmp->dlsch_pdu.dlsch_pdu_rel8.rnti) { - LOG_E(MAC, - "dl_config_req_UE_MAC 5 Received RAR, PreambleIndex: %d \n", - UE_mac_inst[Mod_id].RA_prach_resources.ra_PreambleIndex); - ue_process_rar(Mod_id, 0, sfn, - ra_rnti, //RA-RNTI - tx_request_pdu_list[pdu_index].segments[0].segment_data, - &UE_mac_inst[Mod_id].crnti, //t-crnti - UE_mac_inst[Mod_id].RA_prach_resources.ra_PreambleIndex, - tx_request_pdu_list[pdu_index].segments[0].segment_data); - UE_mac_inst[Mod_id].UE_mode[0] = RA_RESPONSE; - // Expecting an UL_CONFIG_ULSCH_PDU to enable Msg3 Txon (first - // ULSCH Txon for the UE) - UE_mac_inst[Mod_id].first_ULSCH_Tx = 1; - } - } else { - LOG_W(MAC, "can not handle special RNTI %x\n", rnti); - } - } - } else if (dl_config_pdu_list[i].pdu_type == NFAPI_DL_CONFIG_BCH_PDU_TYPE) { - // BCH case: Last parameter is 1 if first time synchronization and zero - // otherwise. Not sure which value to put for our case. - if (UE_mac_inst[Mod_id].UE_mode[0] == NOT_SYNCHED){ - dl_phy_sync_success(Mod_id, sfn, 0, 1); - LOG_E(MAC, - "%s(): Received MIB: UE_mode: %d, sfn/sf: %d.%d\n", - __func__, - UE_mac_inst[Mod_id].UE_mode[0], - sfn, - sf); - UE_mac_inst[Mod_id].UE_mode[0] = PRACH; - } else { - dl_phy_sync_success(Mod_id, sfn, 0, 0); + return; } } + } else if (rnti_type == 2) { + if (rnti == 0xFFFF) { /* SI-RNTI */ + for (int ue_id = 0; ue_id < num_ue; ue_id++) { + if (UE_mac_inst[ue_id].UE_mode[0] == NOT_SYNCHED) + continue; + + ue_decode_si(ue_id, 0, sfn, 0, + tx_request_pdu_list[pdu_index].segments[0].segment_data, + tx_request_pdu_list[pdu_index].segments[0].segment_length); + } + } else if (rnti == 0xFFFE) { /* PI-RNTI */ + for (int ue_id = 0; ue_id < num_ue; ue_id++) { + LOG_I(MAC, "%s() Received paging message: sfn/sf:%d.%d\n", + __func__, sfn, sf); + ue_decode_p(ue_id, 0, sfn, 0, + tx_request_pdu_list[pdu_index].segments[0].segment_data, + tx_request_pdu_list[pdu_index].segments[0].segment_length); + } + } else if (rnti == 0x0002) { /* RA-RNTI */ + for (int ue_id = 0; ue_id < num_ue; ue_id++) { + if (UE_mac_inst[ue_id].UE_mode[0] != RA_RESPONSE) { + LOG_D(MAC, "UE %d not awaiting RAR, is in mode %d\n", + ue_id, UE_mac_inst[ue_id].UE_mode[0]); + continue; + } + // RNTI parameter not actually used. Provided only to comply with + // existing function definition. Not sure about parameters to fill + // the preamble index. + const rnti_t ra_rnti = UE_mac_inst[ue_id].RA_prach_resources.ra_RNTI; + DevAssert(ra_rnti == 0x0002); + if (UE_mac_inst[ue_id].UE_mode[0] != PUSCH + && UE_mac_inst[ue_id].RA_prach_resources.Msg3 != NULL + && ra_rnti == dlsch->dlsch_pdu.dlsch_pdu_rel8.rnti) { + LOG_E(MAC, + "%s(): Received RAR, PreambleIndex: %d\n", + __func__, UE_mac_inst[ue_id].RA_prach_resources.ra_PreambleIndex); + ue_process_rar(ue_id, 0, sfn, + ra_rnti, //RA-RNTI + tx_request_pdu_list[pdu_index].segments[0].segment_data, + &UE_mac_inst[ue_id].crnti, //t-crnti + UE_mac_inst[ue_id].RA_prach_resources.ra_PreambleIndex, + tx_request_pdu_list[pdu_index].segments[0].segment_data); + UE_mac_inst[ue_id].UE_mode[0] = RA_RESPONSE; + // Expecting an UL_CONFIG_ULSCH_PDU to enable Msg3 Txon (first + // ULSCH Txon for the UE) + UE_mac_inst[ue_id].first_ULSCH_Tx = 1; + } + } + } else { + LOG_W(MAC, "can not handle special RNTI %x\n", rnti); + } } - return 0; } -int hi_dci0_req_UE_MAC(nfapi_hi_dci0_request_t *req, module_id_t Mod_id) { - if (req != NULL && req->hi_dci0_request_body.hi_dci0_pdu_list != NULL) { - LOG_D(PHY, - "[UE-PHY_STUB] hi dci0 request sfn_sf:%d number_of_dci:%d " - "number_of_hi:%d\n", - NFAPI_SFNSF2DEC(req->sfn_sf), - req->hi_dci0_request_body.number_of_dci, - req->hi_dci0_request_body.number_of_hi); +void dl_config_req_UE_MAC_bch(int sfn, + int sf, + nfapi_dl_config_request_pdu_t *bch, + int num_ue) { + DevAssert(bch->pdu_type == NFAPI_DL_CONFIG_BCH_PDU_TYPE); - for (int i = 0; i < req->hi_dci0_request_body.number_of_dci - + req->hi_dci0_request_body.number_of_hi; - i++) { - LOG_D(PHY, - "[UE-PHY_STUB] HI_DCI0_REQ sfn_sf:%d PDU[%d]\n", - NFAPI_SFNSF2DEC(req->sfn_sf), - i); - - if (req->hi_dci0_request_body.hi_dci0_pdu_list[i].pdu_type - == NFAPI_HI_DCI0_DCI_PDU_TYPE) { - LOG_D(PHY, - "[UE-PHY_STUB] HI_DCI0_REQ sfn_sf:%d PDU[%d] - " - "NFAPI_HI_DCI0_DCI_PDU_TYPE\n", - NFAPI_SFNSF2DEC(req->sfn_sf), - i); - const nfapi_hi_dci0_dci_pdu_rel8_t *dci = - &req->hi_dci0_request_body.hi_dci0_pdu_list[i].dci_pdu.dci_pdu_rel8; - if (dci->rnti != UE_mac_inst[Mod_id].crnti) - continue; - const int sfn = NFAPI_SFNSF2SFN(req->sfn_sf); - const int sf = NFAPI_SFNSF2SF(req->sfn_sf); - if (dci->cqi_csi_request) - fill_ulsch_cqi_indication_UE_MAC(Mod_id, sfn, sf, UL_INFO, dci->rnti); - } else if (req->hi_dci0_request_body.hi_dci0_pdu_list[i].pdu_type - == NFAPI_HI_DCI0_HI_PDU_TYPE) { - nfapi_hi_dci0_request_pdu_t *hi_dci0_req_pdu = - &req->hi_dci0_request_body.hi_dci0_pdu_list[i]; - - // This is meaningful only after ACKnowledging the first ULSCH Txon - // (i.e. Msg3) - if (hi_dci0_req_pdu->hi_pdu.hi_pdu_rel8.hi_value == 1 - && UE_mac_inst[Mod_id].first_ULSCH_Tx == 1) { - // LOG_I(MAC,"[UE-PHY_STUB] HI_DCI0_REQ 2 sfn_sf:%d PDU[%d] - - // NFAPI_HI_DCI0_HI_PDU_TYPE\n", NFAPI_SFNSF2DEC(req->sfn_sf), i); - // UE_mac_inst[Mod_id].UE_mode[0] = PUSCH; - // UE_mac_inst[Mod_id].first_ULSCH_Tx = 0; - } - - } else { - LOG_E(PHY, - "[UE-PHY_STUB] HI_DCI0_REQ sfn_sf:%d PDU[%d] - unknown pdu " - "type:%d\n", - NFAPI_SFNSF2DEC(req->sfn_sf), - i, - req->hi_dci0_request_body.hi_dci0_pdu_list[i].pdu_type); - } + for (int ue_id = 0; ue_id < num_ue; ue_id++) { + if (UE_mac_inst[ue_id].UE_mode[0] == NOT_SYNCHED){ + dl_phy_sync_success(ue_id, sfn, 0, 1); + LOG_E(MAC, + "%s(): Received MIB: UE_mode: %d, sfn/sf: %d.%d\n", + __func__, + UE_mac_inst[ue_id].UE_mode[0], + sfn, + sf); + UE_mac_inst[ue_id].UE_mode[0] = PRACH; + } else { + dl_phy_sync_success(ue_id, sfn, 0, 0); } } +} - return 0; +void hi_dci0_req_UE_MAC(int sfn, + int sf, + nfapi_hi_dci0_request_pdu_t* hi_dci0, + int num_ue) { + if (hi_dci0->pdu_type != NFAPI_HI_DCI0_DCI_PDU_TYPE) + return; + + const nfapi_hi_dci0_dci_pdu_rel8_t *dci = &hi_dci0->dci_pdu.dci_pdu_rel8; + if (!dci->cqi_csi_request) + return; + for (int ue_id = 0; ue_id < num_ue; ue_id++) { + if (dci->rnti == UE_mac_inst[ue_id].crnti) { + fill_ulsch_cqi_indication_UE_MAC(ue_id, sfn, sf, UL_INFO, dci->rnti); + return; + } + } } // The following set of memcpy functions should be getting called as callback diff --git a/openair2/PHY_INTERFACE/phy_stub_UE.h b/openair2/PHY_INTERFACE/phy_stub_UE.h index 21fb8518fa..034da51d6f 100644 --- a/openair2/PHY_INTERFACE/phy_stub_UE.h +++ b/openair2/PHY_INTERFACE/phy_stub_UE.h @@ -93,13 +93,23 @@ void handle_nfapi_ul_pdu_UE_MAC(module_id_t Mod_id, nfapi_ul_config_request_pdu_t *ul_config_pdu, uint16_t frame,uint8_t subframe,uint8_t srs_present, int index); -//int dl_config_req_UE_MAC(nfapi_dl_config_request_t* req, nfapi_tx_request_pdu_t* tx_request_pdu_list); -int dl_config_req_UE_MAC(nfapi_dl_config_request_t* req, module_id_t Mod_id); +void dl_config_req_UE_MAC_dci(int sfn, + int sf, + nfapi_dl_config_request_pdu_t *dci, + nfapi_dl_config_request_pdu_t *dlsch, + int num_ue); +void dl_config_req_UE_MAC_bch(int sfn, + int sf, + nfapi_dl_config_request_pdu_t *bch, + int num_ue); int tx_req_UE_MAC(nfapi_tx_request_t* req); -int hi_dci0_req_UE_MAC(nfapi_hi_dci0_request_t* req, module_id_t Mod_id); +void hi_dci0_req_UE_MAC(int sfn, + int sf, + nfapi_hi_dci0_request_pdu_t* bch, + int num_ue); // The following set of memcpy functions should be getting called as callback functions from // pnf_p7_subframe_ind. diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c index 75ed018434..8355108bdf 100644 --- a/targets/RT/USER/lte-ue.c +++ b/targets/RT/USER/lte-ue.c @@ -1108,6 +1108,45 @@ static void *UE_phy_stub_single_thread_rxn_txnp4(void *arg) } } + if (dl_config_req && tx_request_pdu_list) { + nfapi_dl_config_request_body_t* dl_config_req_body = &dl_config_req->dl_config_request_body; + for (int i = 0; i < dl_config_req_body->number_pdu; ++i) { + nfapi_dl_config_request_pdu_t* pdu = &dl_config_req_body->dl_config_pdu_list[i]; + if (pdu->pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE) { + i += 1; + AssertFatal(i < dl_config_req->dl_config_request_body.number_pdu, + "Need PDU following DCI at index %d, but not found\n", + i); + nfapi_dl_config_request_pdu_t *dlsch = &dl_config_req_body->dl_config_pdu_list[i]; + if (dlsch->pdu_type != NFAPI_DL_CONFIG_DLSCH_PDU_TYPE) { + LOG_E(MAC, "expected DLSCH PDU at index %d\n", i); + continue; + } + dl_config_req_UE_MAC_dci(NFAPI_SFNSF2SFN(dl_config_req->sfn_sf), + NFAPI_SFNSF2SF(dl_config_req->sfn_sf), + pdu, + dlsch, + ue_num); + } else if (pdu->pdu_type == NFAPI_DL_CONFIG_BCH_PDU_TYPE) { + dl_config_req_UE_MAC_bch(NFAPI_SFNSF2SFN(dl_config_req->sfn_sf), + NFAPI_SFNSF2SF(dl_config_req->sfn_sf), + pdu, + ue_num); + } + } + } + + if (hi_dci0_req) { + nfapi_hi_dci0_request_body_t *hi_dci0_body = &hi_dci0_req->hi_dci0_request_body; + for (int i = 0; i < hi_dci0_body->number_of_dci + hi_dci0_body->number_of_hi; i++) { + nfapi_hi_dci0_request_pdu_t* pdu = &hi_dci0_body->hi_dci0_pdu_list[i]; + hi_dci0_req_UE_MAC(NFAPI_SFNSF2SFN(hi_dci0_req->sfn_sf), + NFAPI_SFNSF2SF(hi_dci0_req->sfn_sf), + pdu, + ue_num); + } + } + //for (Mod_id=0; Mod_idhi_dci0_request_body.hi_dci0_pdu_list!=NULL) { - hi_dci0_req_UE_MAC(hi_dci0_req, ue_Mod_id); - } - if(NFAPI_MODE!=NFAPI_UE_STUB_PNF) phy_procedures_UE_SL_TX(UE,proc); } @@ -1413,12 +1443,14 @@ static void *UE_phy_stub_thread_rxn_txnp4(void *arg) oai_subframe_ind(timer_frame, timer_subframe); if(dl_config_req!= NULL) { - dl_config_req_UE_MAC(dl_config_req, Mod_id); + AssertFatal(0, "dl_config_req_UE_MAC() not handled\n"); + //dl_config_req_UE_MAC(dl_config_req, Mod_id); } //if(UE_mac_inst[Mod_id].hi_dci0_req!= NULL){ if (hi_dci0_req!=NULL && hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list!=NULL) { - hi_dci0_req_UE_MAC(hi_dci0_req, Mod_id); + AssertFatal(0, "hi_dci0_req_UE_MAC() not handled\n"); + //hi_dci0_req_UE_MAC(hi_dci0_req, Mod_id); //if(UE_mac_inst[Mod_id].hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list!=NULL){ free(hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list); hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list = NULL; From 23fb00a248e7954bc771d710555fc0fd38c7ca7e Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 9 Apr 2020 14:46:40 +0200 Subject: [PATCH 155/240] Fix: telnet use right variable names --- .../utils/telnetsrv/telnetsrv_enb_measurements.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/common/utils/telnetsrv/telnetsrv_enb_measurements.c b/common/utils/telnetsrv/telnetsrv_enb_measurements.c index 9c5c5b675b..8830173e6d 100644 --- a/common/utils/telnetsrv/telnetsrv_enb_measurements.c +++ b/common/utils/telnetsrv/telnetsrv_enb_measurements.c @@ -110,13 +110,13 @@ void measurcmd_display_pdcpcpu(telnet_printfunc_t prnt) { void measurcmd_display_macstats_ue(telnet_printfunc_t prnt) { - UE_list_t *UE_list = &(RC.mac[eNB_id]->UE_list); + UE_info_t *UE_info = &(RC.mac[eNB_id]->UE_info); - for (int UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) { - for (int i=0; inumactiveCCs[UE_id]; i++) { - int CC_id = UE_list->ordered_CCids[i][UE_id]; + for (int UE_id=UE_info->list.head; UE_id>=0; UE_id=UE_info->list.next[UE_id]) { + for (int i=0; inumactiveCCs[UE_id]; i++) { + int CC_id = UE_info->ordered_CCids[i][UE_id]; prnt("%s UE %i Id %i CCid %i %s\n",HDR,i,UE_id,CC_id,HDR); - eNB_UE_STATS *macuestatptr = &(UE_list->eNB_UE_stats[CC_id][UE_id]); + eNB_UE_STATS *macuestatptr = &(UE_info->eNB_UE_stats[CC_id][UE_id]); telnet_ltemeasurdef_t statsptr[]=LTEMAC_UEMEASURE; measurcmd_display_measures(prnt, statsptr, sizeof(statsptr)/sizeof(telnet_ltemeasurdef_t)); } @@ -155,7 +155,7 @@ void measurcmd_display_one_rlcstat(telnet_printfunc_t prnt, int UE_id, telnet_lt void measurcmd_display_rlcstats(telnet_printfunc_t prnt) { protocol_ctxt_t ctxt; - UE_list_t *UE_list = &(RC.mac[eNB_id]->UE_list); + UE_info_t *UE_info = &(RC.mac[eNB_id]->UE_info); telnet_ltemeasurdef_t statsptr[]=LTE_RLCMEASURE; int num_rlcmeasure = sizeof(statsptr)/sizeof(telnet_ltemeasurdef_t ); unsigned int *rlcstats = malloc(num_rlcmeasure*sizeof(unsigned int)); @@ -165,9 +165,9 @@ void measurcmd_display_rlcstats(telnet_printfunc_t prnt) { statsptr[i].vptr = rlcstats + i; } - for (int UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) { + for (int UE_id=UE_info->list.head; UE_id>=0; UE_id=UE_info->list.next[UE_id]) { #define NB_eNB_INST 1 - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt,eNB_id, ENB_FLAG_YES,UE_list->eNB_UE_stats[0][UE_id].crnti, + PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt,eNB_id, ENB_FLAG_YES,UE_info->eNB_UE_stats[0][UE_id].crnti, eNB->frame,eNB->subframe,eNB_id); measurcmd_display_one_rlcstat(prnt, UE_id, statsptr, num_rlcmeasure, rlcstats, "DCCH", &ctxt, SRB_FLAG_YES, DCCH); measurcmd_display_one_rlcstat(prnt, UE_id, statsptr, num_rlcmeasure, rlcstats, "DTCH", &ctxt, SRB_FLAG_NO, DTCH-2); From 0e4ff0ecb45b23a3bc6b48c6180c95327750beb9 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 9 Apr 2020 23:42:44 +0200 Subject: [PATCH 156/240] L2 sim: space RA in time --- targets/RT/USER/lte-ue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c index 8355108bdf..3ad3a44c97 100644 --- a/targets/RT/USER/lte-ue.c +++ b/targets/RT/USER/lte-ue.c @@ -1213,7 +1213,7 @@ static void *UE_phy_stub_single_thread_rxn_txnp4(void *arg) if (UE_mac_inst[ue_Mod_id].UE_mode[0] == PRACH && ue_Mod_id == next_Mod_id) { next_ra_frame++; - if(next_ra_frame > 200) { + if(next_ra_frame > 500) { // check if we have PRACH opportunity if (is_prach_subframe(&UE->frame_parms,proc->frame_tx, proc->subframe_tx) && UE_mac_inst[ue_Mod_id].SI_Decoded == 1) { // The one working strangely... From e197824e20491a1fcd2fcacf3f7b10866b42bb70 Mon Sep 17 00:00:00 2001 From: Florian Kaltenberger Date: Fri, 10 Apr 2020 14:16:15 +0200 Subject: [PATCH 157/240] updating targets/ARCH/rfsimulator/README.md --- targets/ARCH/rfsimulator/README.md | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/targets/ARCH/rfsimulator/README.md b/targets/ARCH/rfsimulator/README.md index f841c324c0..014f5f7505 100644 --- a/targets/ARCH/rfsimulator/README.md +++ b/targets/ARCH/rfsimulator/README.md @@ -1,21 +1,8 @@ -# :construction: **WORK IN PROGRESS** :exclamation: - -# **PLEASE IGNORE THE FOLLOWING PAGE** :exclamation: - - - - # General This is an RF simulator that allows to test OAI without an RF board. It replaces an actual RF board driver. As much as possible, it works like an RF board, but not in real-time: It can run faster than real-time if there is enough CPU, or slower (it is CPU-bound instead of real-time RF sampling-bound). -It can be run either in: - -- "noS1" mode: the generated IP traffic is sent and received between gNB and UE IP tunnel interfaces ("oaitun") by applications like ping and iperf -- "phy-test" mode: random UL and DL traffic is generated at every scheduling opportunity - - # build ## From [build_oai](../../../doc/BUILD.md) script From 58e973409aaf2b31bbea6fcafabd02099a71a5e0 Mon Sep 17 00:00:00 2001 From: laurent Date: Tue, 14 Apr 2020 11:25:59 +0200 Subject: [PATCH 158/240] small compilation details --- openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c | 4 ++-- openair1/SIMULATION/LTE_PHY/ulsim.c | 2 +- openair2/RRC/NR/nr_rrc_extern.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c index 36a3cd9a5c..90492b9999 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c @@ -314,7 +314,7 @@ int ulsch_decoding_data(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc, unsigned int Kr_bytes = Kr>>3; #ifdef DEBUG_ULSCH_DECODING - printf("Rate Matching Segment %u (coded bits (G) %d,unpunctured/repeated bits %u, Q_m %d, Nl %d, r_offset %d)...\n", + printf("Rate Matching Segment %d (coded bits (G) %d,unpunctured/repeated bits %u, Q_m %d, Nl %d, r_offset %u)...\n", r, G, Kr*3, ulsch_harq->Qm, @@ -572,7 +572,7 @@ unsigned int ulsch_decoding(PHY_VARS_eNB *eNB, G = G - Q_RI - Q_CQI; ulsch_harq->G = G; AssertFatal((int)G > 0, - "FATAL: ulsch_decoding.c G < 0 (%d) : Q_RI %d, Q_CQI %d\n",G,Q_RI,Q_CQI); + "FATAL: ulsch_decoding.c G < 0 (%u) : Q_RI %u, Q_CQI %u\n",G,Q_RI,Q_CQI); H = G + Q_CQI; Hprime = H/Q_m; // Demultiplexing/Deinterleaving of PUSCH/ACK/RI/CQI diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c index 064066801d..c950d6f4da 100644 --- a/openair1/SIMULATION/LTE_PHY/ulsim.c +++ b/openair1/SIMULATION/LTE_PHY/ulsim.c @@ -1286,7 +1286,7 @@ int main(int argc, char **argv) { LOG_UDUMPMSG(SIM,dataArray(table_rx),table_rx->size,LOG_DUMP_DOUBLE,"The receiver raw data: \n"); } - printf("\n**********rb: %d ***mcs : %d *********SNR = %f dB (%f): TX %u dB (gain %f dB), N0W %f dB, I0 %d dB, delta_IF %d [ (%d,%d) dB / (%d,%d) dB ]**************************\n", + printf("\n**********rb: %d ***mcs : %d *********SNR = %f dB (%f): TX %u dB (gain %f dB), N0W %f dB, I0 %u dB, delta_IF %d [ (%d,%d) dB / (%u,%u) dB ]**************************\n", nb_rb,mcs,SNR,SNR2, tx_lev_dB, 20*log10(tx_gain), diff --git a/openair2/RRC/NR/nr_rrc_extern.h b/openair2/RRC/NR/nr_rrc_extern.h index cb6adc8012..04e0392236 100644 --- a/openair2/RRC/NR/nr_rrc_extern.h +++ b/openair2/RRC/NR/nr_rrc_extern.h @@ -73,7 +73,7 @@ extern UE_PF_PO_t UE_PF_PO[NFAPI_CC_MAX][MAX_MOBILES_PER_ENB]; extern pthread_mutex_t ue_pf_po_mutex; -extern uint16_t reestablish_rnti_map[NUMBER_OF_UE_MAX][2]; +extern uint16_t reestablish_rnti_map[MAX_MOBILES_PER_ENB][2]; char openair_rrc_gNB_configuration(const module_id_t gnb_mod_idP, gNB_RrcConfigurationReq *configuration); #endif From 8a58359a1be513c6ac8f68f1dac38704fc79abd1 Mon Sep 17 00:00:00 2001 From: laurent Date: Tue, 14 Apr 2020 19:51:00 +0200 Subject: [PATCH 159/240] rereremerge --- openair1/SCHED/fapi_l1.c | 1 - openair2/LAYER2/MAC/pre_processor.c | 319 +-------------------------- openair2/PHY_INTERFACE/phy_stub_UE.c | 2 - openair2/X2AP/x2ap_eNB_handler.c | 4 +- targets/RT/USER/lte-ue.c | 5 +- targets/RT/USER/lte-uesoftmodem.c | 1 - 6 files changed, 12 insertions(+), 320 deletions(-) diff --git a/openair1/SCHED/fapi_l1.c b/openair1/SCHED/fapi_l1.c index b55ad99386..96a073fbb8 100644 --- a/openair1/SCHED/fapi_l1.c +++ b/openair1/SCHED/fapi_l1.c @@ -381,7 +381,6 @@ void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB,int frame,int subframe,L1_rxtx_pro dlsch0_harq->TBS, dlsch0_harq->Qm, dlsch0_harq->codeword, dlsch0_harq->rb_alloc[0], rel8->length ); - dlsch0->active = 1; harq_pid = dlsch0->harq_ids[frame%2][proc->subframe_tx]; dlsch0->harq_mask |= (1<pre_first_nb_rb_ul + i] = UE_id + '0'; } } - - // step 3: assigne RBS - for (UE_id = UE_list->head_ul; UE_id >= 0; UE_id = UE_list->next_ul[UE_id]) { - // if (continueTable[UE_id]) continue; - for (n = 0; n < UE_list->numactiveULCCs[UE_id]; n++) { - // This is the actual CC_id in the list - CC_id = UE_list->ordered_ULCCids[n][UE_id]; - UE_template = &UE_list->UE_template[CC_id][UE_id]; - harq_pid = subframe2harqpid(&RC.mac[module_idP]->common_channels[CC_id], - sched_frameP, sched_subframeP); - - // mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,openair_harq_UL); - - if (UE_list->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid] > 0) { - nb_allocated_rbs[CC_id][UE_id] = UE_list->UE_template[CC_id][UE_id].nb_rb_ul[harq_pid]; - } else { - nb_allocated_rbs[CC_id][UE_id] = - cmin(UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[slice_idx], average_rbs_per_user[CC_id]); - } - - total_allocated_rbs[CC_id] += nb_allocated_rbs[CC_id][UE_id]; - LOG_D(MAC, "In ulsch_preprocessor: assigning %d RBs for UE %d/%x CCid %d, harq_pid %d, nb_rb_ul %d, %d ,%d, slice %d, round ul %d\n", - nb_allocated_rbs[CC_id][UE_id], - UE_id, - rntiTable[UE_id], - CC_id, - harq_pid, - UE_list->UE_template[CC_id][UE_id].nb_rb_ul[harq_pid], - UE_list->UE_template[CC_id][UE_id].pre_allocated_nb_rb_ul[slice_idx], - average_rbs_per_user[CC_id], - slice_idx, - UE_list->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid]); - } - } - - // step 4: assigne the remaining RBs and set the pre_allocated rbs accordingly - for (UE_id = UE_list->head_ul; UE_id >= 0; UE_id = UE_list->next_ul[UE_id]) { - // if (continueTable[UE_id]) continue; - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - - for (n = 0; n < UE_list->numactiveULCCs[UE_id]; n++) { - // This is the actual CC_id in the list - CC_id = UE_list->ordered_ULCCids[n][UE_id]; - UE_template = &UE_list->UE_template[CC_id][UE_id]; - N_RB_UL = to_prb(eNB->common_channels[CC_id].ul_Bandwidth); - first_rb_offset = UE_list->first_rb_offset[CC_id][slice_idx]; - available_rbs = cmin(ue_sched_ctl->max_rbs_allowed_slice_uplink[CC_id][slice_idx], N_RB_UL - first_rb[CC_id] - first_rb_offset); - total_remaining_rbs[CC_id] = available_rbs - total_allocated_rbs[CC_id]; - - if (total_ue_count[CC_id] == 1) { - total_remaining_rbs[CC_id]++; - } - - while (UE_template->pre_allocated_nb_rb_ul[slice_idx] > 0 && - nb_allocated_rbs[CC_id][UE_id] < UE_template->pre_allocated_nb_rb_ul[slice_idx] && - total_remaining_rbs[CC_id] > 0) { - nb_allocated_rbs[CC_id][UE_id] = cmin(nb_allocated_rbs[CC_id][UE_id] + 1, UE_template->pre_allocated_nb_rb_ul[slice_idx]); - total_remaining_rbs[CC_id]--; - total_allocated_rbs[CC_id]++; - } - - UE_template->pre_allocated_nb_rb_ul[slice_idx] = nb_allocated_rbs[CC_id][UE_id]; - LOG_D(MAC, "******************UL Scheduling Information for UE%d CC_id %d ************************\n", - UE_id, - CC_id); - LOG_D(MAC, "[eNB %d] total RB allocated for UE%d CC_id %d = %d\n", - module_idP, - UE_id, - CC_id, - UE_template->pre_allocated_nb_rb_ul[slice_idx]); - } - } - - return; -} - -void -assign_max_mcs_min_rb(module_id_t module_idP, - int slice_idx, - int frameP, - sub_frame_t subframeP, - uint16_t *first_rb) { - int i; - uint16_t n, UE_id; - uint8_t CC_id; - int mcs; - int rb_table_index = 0, tbs, tx_power; - eNB_MAC_INST *eNB = RC.mac[module_idP]; - UE_list_t *UE_list = &eNB->UE_list; - slice_info_t *sli = &eNB->slice_info; - UE_TEMPLATE *UE_template; - UE_sched_ctrl_t *ue_sched_ctl; - int Ncp; - int N_RB_UL; - int first_rb_offset, available_rbs; - - for (i = UE_list->head_ul; i >= 0; i = UE_list->next_ul[i]) { - if (UE_list->UE_sched_ctrl[i].phr_received == 1) { - /* if we've received the power headroom information the UE, we can go to - * maximum mcs */ - mcs = cmin(20, sli->ul[slice_idx].maxmcs); - } else { - /* otherwise, limit to QPSK PUSCH */ - mcs = cmin(10, sli->ul[slice_idx].maxmcs); - } - - UE_id = i; - - for (n = 0; n < UE_list->numactiveULCCs[UE_id]; n++) { - // This is the actual CC_id in the list - CC_id = UE_list->ordered_ULCCids[n][UE_id]; - AssertFatal(CC_id < RC.nb_mac_CC[module_idP], "CC_id %u should be < %u, loop n=%u < numactiveULCCs[%u]=%u", - CC_id, - NFAPI_CC_MAX, - n, - UE_id, - UE_list->numactiveULCCs[UE_id]); - UE_template = &UE_list->UE_template[CC_id][UE_id]; - UE_template->pre_assigned_mcs_ul = mcs; - ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; - Ncp = eNB->common_channels[CC_id].Ncp; - N_RB_UL = to_prb(eNB->common_channels[CC_id].ul_Bandwidth); - ue_sched_ctl->max_rbs_allowed_slice_uplink[CC_id][slice_idx] = nb_rbs_allowed_slice(sli->ul[slice_idx].pct, N_RB_UL); - int bytes_to_schedule = UE_template->estimated_ul_buffer - UE_template->scheduled_ul_bytes; - - if (bytes_to_schedule < 0) bytes_to_schedule = 0; - - int bits_to_schedule = bytes_to_schedule * 8; - - // if this UE has UL traffic - if (bits_to_schedule > 0) { - tbs = get_TBS_UL(UE_template->pre_assigned_mcs_ul, 3) << 3; // 1 or 2 PRB with cqi enabled does not work well! - rb_table_index = 2; - // fixme: set use_srs flag - tx_power = estimate_ue_tx_power(tbs, rb_table[rb_table_index], 0, Ncp, 0); - - while ((UE_template->phr_info - tx_power < 0 || tbs > bits_to_schedule) && UE_template->pre_assigned_mcs_ul > 3) { - // LOG_I(MAC,"UE_template->phr_info %d tx_power %d mcs %d\n", UE_template->phr_info,tx_power, mcs); - UE_template->pre_assigned_mcs_ul--; - tbs = get_TBS_UL(UE_template->pre_assigned_mcs_ul, rb_table[rb_table_index]) << 3; - tx_power = estimate_ue_tx_power(tbs, rb_table[rb_table_index], 0, Ncp, 0); // fixme: set use_srs - } - - first_rb_offset = UE_list->first_rb_offset[CC_id][slice_idx]; - available_rbs = - cmin(ue_sched_ctl->max_rbs_allowed_slice_uplink[CC_id][slice_idx], N_RB_UL - first_rb[CC_id] - first_rb_offset); - - while (tbs < bits_to_schedule && - rb_table[rb_table_index] < available_rbs && - UE_template->phr_info - tx_power > 0 && - rb_table_index < 32) { - rb_table_index++; - tbs = get_TBS_UL(UE_template->pre_assigned_mcs_ul, rb_table[rb_table_index]) << 3; - tx_power = estimate_ue_tx_power(tbs, rb_table[rb_table_index], 0, Ncp, 0); - } - - if (rb_table[rb_table_index] > (available_rbs - 1)) { - rb_table_index--; - } - - // 1 or 2 PRB with cqi enabled does not work well - if (rb_table[rb_table_index] < 3) { - rb_table_index = 2; //3PRB - } - - UE_template->pre_allocated_rb_table_index_ul = rb_table_index; - UE_template->pre_allocated_nb_rb_ul[slice_idx] = rb_table[rb_table_index]; - LOG_D(MAC, "[eNB %d] frame %d subframe %d: for UE %d CC %d: pre-assigned mcs %d, pre-allocated rb_table[%d]=%d RBs (phr %d, tx power %d)\n", - module_idP, - frameP, - subframeP, - UE_id, - CC_id, - UE_template->pre_assigned_mcs_ul, - UE_template->pre_allocated_rb_table_index_ul, - UE_template->pre_allocated_nb_rb_ul[slice_idx], - UE_template->phr_info, tx_power); - } else { - /* if UE has pending scheduling request then pre-allocate 3 RBs */ - //if (UE_template->ul_active == 1 && UE_template->ul_SR == 1) { - if (UE_is_to_be_scheduled(module_idP, CC_id, i)) { - /* use QPSK mcs */ - UE_template->pre_assigned_mcs_ul = 10; - UE_template->pre_allocated_rb_table_index_ul = 2; - UE_template->pre_allocated_nb_rb_ul[slice_idx] = 3; - } else { - UE_template->pre_assigned_mcs_ul = 0; - UE_template->pre_allocated_rb_table_index_ul = -1; - UE_template->pre_allocated_nb_rb_ul[slice_idx] = 0; - } - } - } - } -} - -struct sort_ue_ul_params { - int module_idP; - int sched_frameP; - int sched_subframeP; -}; - -static int ue_ul_compare(const void *_a, const void *_b, void *_params) { - struct sort_ue_ul_params *params = _params; - UE_list_t *UE_list = &RC.mac[params->module_idP]->UE_list; - int UE_id1 = *(const int *) _a; - int UE_id2 = *(const int *) _b; - int rnti1 = UE_RNTI(params->module_idP, UE_id1); - int pCCid1 = UE_PCCID(params->module_idP, UE_id1); - int round1 = maxround_ul(params->module_idP, rnti1, params->sched_frameP, - params->sched_subframeP); - int rnti2 = UE_RNTI(params->module_idP, UE_id2); - int pCCid2 = UE_PCCID(params->module_idP, UE_id2); - int round2 = maxround_ul(params->module_idP, rnti2, params->sched_frameP, - params->sched_subframeP); - - if (round1 > round2) - return -1; - - if (round1 < round2) - return 1; - - if (UE_list->UE_template[pCCid1][UE_id1].ul_buffer_info[LCGID0] > - UE_list->UE_template[pCCid2][UE_id2].ul_buffer_info[LCGID0]) - return -1; - - if (UE_list->UE_template[pCCid1][UE_id1].ul_buffer_info[LCGID0] < - UE_list->UE_template[pCCid2][UE_id2].ul_buffer_info[LCGID0]) - return 1; - - int bytes_to_schedule1 = UE_list->UE_template[pCCid1][UE_id1].estimated_ul_buffer - UE_list->UE_template[pCCid1][UE_id1].scheduled_ul_bytes; - - if (bytes_to_schedule1 < 0) bytes_to_schedule1 = 0; - - int bytes_to_schedule2 = UE_list->UE_template[pCCid2][UE_id2].estimated_ul_buffer - UE_list->UE_template[pCCid2][UE_id2].scheduled_ul_bytes; - - if (bytes_to_schedule2 < 0) bytes_to_schedule2 = 0; - - if (bytes_to_schedule1 > bytes_to_schedule2) - return -1; - - if (bytes_to_schedule1 < bytes_to_schedule2) - return 1; - - if (UE_list->UE_template[pCCid1][UE_id1].pre_assigned_mcs_ul > - UE_list->UE_template[pCCid2][UE_id2].pre_assigned_mcs_ul) - return -1; - - if (UE_list->UE_template[pCCid1][UE_id1].pre_assigned_mcs_ul < - UE_list->UE_template[pCCid2][UE_id2].pre_assigned_mcs_ul) - return 1; - - if (UE_list->UE_sched_ctrl[UE_id1].cqi_req_timer > - UE_list->UE_sched_ctrl[UE_id2].cqi_req_timer) - return -1; - - if (UE_list->UE_sched_ctrl[UE_id1].cqi_req_timer < - UE_list->UE_sched_ctrl[UE_id2].cqi_req_timer) - return 1; - - return 0; -} - -//----------------------------------------------------------------------------- -/* - * This function sorts the UEs in order, depending on their ulsch buffer and CQI - */ -void sort_ue_ul(module_id_t module_idP, - int slice_idx, - int sched_frameP, - sub_frame_t sched_subframeP, - rnti_t *rntiTable) -//----------------------------------------------------------------------------- -{ - int list[MAX_MOBILES_PER_ENB]; - 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_t *UE_scheduling_control = NULL; - - for (int i = 0; i < MAX_MOBILES_PER_ENB; i++) { - UE_scheduling_control = &(UE_list->UE_sched_ctrl[i]); - - /* Check CDRX configuration and if UE is in active time for this subframe */ - if (UE_scheduling_control->cdrx_configured == TRUE) { - if (UE_scheduling_control->in_active_time == FALSE) { - continue; - } - } - - rntiTable[i] = UE_RNTI(module_idP, i); - - // Valid element and is not the actual CC_id in the list - if (UE_list->active[i] == TRUE && - rntiTable[i] != NOT_A_RNTI && - UE_list->UE_sched_ctrl[i].ul_out_of_sync != 1 && - ue_ul_slice_membership(module_idP, i, slice_idx)) { - list[list_size++] = i; // Add to list - } - } - - qsort_r(list, list_size, sizeof(int), ue_ul_compare, ¶ms); - - if (list_size) { // At mimimum one list element - for (int i = 0; i < list_size - 1; i++) { - UE_list->next_ul[list[i]] = list[i + 1]; - } - - UE_list->next_ul[list[list_size - 1]] = -1; - UE_list->head_ul = list[0]; - } else { // No element - UE_list->head_ul = -1; - } + if (print) + LOG_D(MAC, + "%4d.%d UL scheduler allocation list: %s\n", + sched_frameP, + sched_subframeP, + t); +#endif } diff --git a/openair2/PHY_INTERFACE/phy_stub_UE.c b/openair2/PHY_INTERFACE/phy_stub_UE.c index 8bd172f79f..5c9b4b996e 100644 --- a/openair2/PHY_INTERFACE/phy_stub_UE.c +++ b/openair2/PHY_INTERFACE/phy_stub_UE.c @@ -863,7 +863,6 @@ int memcpy_dl_config_req(L1_rxtx_proc_t *proc, dl_config_req->dl_config_request_body.number_pdsch_rnti = req->dl_config_request_body.number_pdsch_rnti; dl_config_req->dl_config_request_body.number_pdu = req->dl_config_request_body.number_pdu; - dl_config_req->dl_config_request_body.tl.tag = req->dl_config_request_body.tl.tag; dl_config_req->dl_config_request_body.tl.length = req->dl_config_request_body.tl.length; @@ -1045,7 +1044,6 @@ void handle_nfapi_bch_pdu(PHY_VARS_eNB *eNB, uint8_t *sdu) { } - void handle_nfapi_dlsch_pdu(PHY_VARS_eNB *eNB, int frame, int subframe, diff --git a/openair2/X2AP/x2ap_eNB_handler.c b/openair2/X2AP/x2ap_eNB_handler.c index df68746201..afaae1756d 100644 --- a/openair2/X2AP/x2ap_eNB_handler.c +++ b/openair2/X2AP/x2ap_eNB_handler.c @@ -1771,9 +1771,9 @@ int x2ap_gNB_handle_ENDC_sGNB_addition_request (instance_t instance, X2AP_FIND_PROTOCOLIE_BY_ID(X2AP_SgNBAdditionRequest_IEs_t, ie, x2SgNBAdditionRequest, X2AP_ProtocolIE_ID_id_MeNBtoSgNBContainer, true); + X2AP_MeNBtoSgNBContainer_t *container = &ie->value.choice.MeNBtoSgNBContainer; //X2AP_MeNBtoSgNBContainer_t *container = &ie->value.choice.MeNBtoSgNBContainer; - - if (ie->value.choice.MeNBtoSgNBContainer.size > 8192 ) // TODO: this is the size of rrc_buffer in struct x2ap_handover_req_s + if (container->size > 8192 ) // TODO: this is the size of rrc_buffer in struct x2ap_handover_req_s { printf("%s:%d: fatal: buffer too big\n", __FILE__, __LINE__); abort(); } memcpy(X2AP_ENDC_SGNB_ADDITION_REQ(msg).rrc_buffer, ie->value.choice.MeNBtoSgNBContainer.buf, ie->value.choice.MeNBtoSgNBContainer.size); diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c index d9465db425..006394eb78 100644 --- a/targets/RT/USER/lte-ue.c +++ b/targets/RT/USER/lte-ue.c @@ -1617,14 +1617,14 @@ void *UE_thread(void *arg) if (is_synchronized == 0) { if (instance_cnt_synch < 0) { // we can invoke the synch // grab 10 ms of signal and wakeup synch thread + if (UE->mode != loop_through_memory) { if (IS_SOFTMODEM_RFSIM ) { for(int sf=0; sf<10; sf++) { for (int i=0; iframe_parms.nb_antennas_rx; i++) rxp[i] = (void *)&UE->common_vars.rxdata[i][UE->frame_parms.samples_per_tti*sf]; - AssertFatal( UE->frame_parms.samples_per_tti == - UE->rfdevice.trx_read_func(&UE->rfdevice, + AssertFatal(UE->frame_parms.samples_per_tti == UE->rfdevice.trx_read_func(&UE->rfdevice, ×tamp, rxp, UE->frame_parms.samples_per_tti, @@ -1643,6 +1643,7 @@ void *UE_thread(void *arg) UE->frame_parms.nb_antennas_rx), ""); } } + AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), ""); instance_cnt_synch = ++UE->proc.instance_cnt_synch; diff --git a/targets/RT/USER/lte-uesoftmodem.c b/targets/RT/USER/lte-uesoftmodem.c index 8afbbe5358..395e73bb66 100644 --- a/targets/RT/USER/lte-uesoftmodem.c +++ b/targets/RT/USER/lte-uesoftmodem.c @@ -605,7 +605,6 @@ int main( int argc, char **argv ) { pthread_mutex_init(&sync_mutex, NULL); printf("ITTI init\n"); -#define UE itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info); // initialize mscgen log after ITTI From e1b968db8be52ba48d0c2bf0b64fe5cbb5f9cb76 Mon Sep 17 00:00:00 2001 From: matzakos Date: Wed, 15 Apr 2020 10:17:12 +0200 Subject: [PATCH 160/240] Small Fix for NR Downlink IP traffic issue after last updates in develop branch --- openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index 20311ef967..608c0bc2e2 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -123,10 +123,7 @@ tbs_size_t mac_rlc_data_req( rb->set_time(rb, nr_rlc_current_time); /* UE does not seem to use saved_status_ind_tb_size */ is_enb = nr_rlc_manager_get_enb_flag(nr_rlc_ue_manager); - if (is_enb) - maxsize = ue->saved_status_ind_tb_size[channel_idP - 1]; - else - maxsize = tb_sizeP; + maxsize = tb_sizeP; ret = rb->generate_pdu(rb, buffer_pP, maxsize); } else { LOG_E(RLC, "%s:%d:%s: fatal: data req for unknown RB\n", __FILE__, __LINE__, __FUNCTION__); From e9b8c72b7cabbd93559e039a6326ca84f4b3cab4 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Wed, 15 Apr 2020 15:55:47 +0200 Subject: [PATCH 161/240] CI: adding ping operations to 5G-RF sim; try loop on failures Signed-off-by: Raphael Defosseux --- ci-scripts/runTestOnVM.sh | 176 ++++++++++++++++++++------------------ 1 file changed, 93 insertions(+), 83 deletions(-) diff --git a/ci-scripts/runTestOnVM.sh b/ci-scripts/runTestOnVM.sh index 502c1a5d47..64af11c8ba 100755 --- a/ci-scripts/runTestOnVM.sh +++ b/ci-scripts/runTestOnVM.sh @@ -342,34 +342,8 @@ function check_iperf { local FILE_COMPLETE=`egrep -c "Server Report" ${LOC_BASE_LOG}_client.txt` if [ $FILE_COMPLETE -eq 0 ] then - # This part will become obsolete once we have UL - if [[ $LOC_IS_RF_SIM -eq 1 ]] && [[ $LOC_IS_NR -eq 1 ]] - then - echo "no UL integration right now --> normal to have no server report" - if [ -f ${LOC_BASE_LOG}_server.txt ] - then - local EFFECTIVE_BANDWIDTH=`tail -n1 ${LOC_BASE_LOG}_server.txt | sed -e "s#^.*MBytes *##" -e "s#^.*KBytes *##" -e "s#sec.*#sec#"` - if [[ $2 =~ .*K.* ]] - then - local BW_PREFIX="K" - else - local BW_PREFIX="M" - fi - if [[ $EFFECTIVE_BANDWIDTH =~ .*${LOC_REQ_BW}.*${BW_PREFIX}bits.* ]] || [[ $EFFECTIVE_BANDWIDTH =~ .*${LOC_REQ_BW_MINUS_ONE}.*${BW_PREFIX}bits.* ]] - then - echo "got requested DL bandwidth: $EFFECTIVE_BANDWIDTH" - else - echo "got LESS than requested DL bandwidth: $EFFECTIVE_BANDWIDTH" - IPERF_STATUS=-1 - fi - else - IPERF_STATUS=-1 - echo "Server File Report not found" - fi - else - IPERF_STATUS=-1 - echo "File Report not found" - fi + IPERF_STATUS=-1 + echo "File Report not found" else if [ `egrep -c "Mbits/sec" ${LOC_BASE_LOG}_client.txt` -ne 0 ] then @@ -2044,81 +2018,117 @@ function run_test_on_vm { if [[ "$RUN_OPTIONS" == "complex" ]] && [[ $VM_NAME =~ .*-rf-sim.* ]] then - NR_STATUS=0 - PING_STATUS=0 - IPERF_STATUS=0 - CN_CONFIG="noS1" CONF_FILE=gnb.band78.tm1.106PRB.usrpn300.conf S1_NOS1_CFG=0 PRB=106 FREQUENCY=3510 + local try_cnt="0" + NR_STATUS=0 + ######### start of loop + while [ $try_cnt -lt 5 ] + do + SYNC_STATUS=0 + PING_STATUS=0 + IPERF_STATUS=0 - echo "############################################################" - echo "${CN_CONFIG} : Starting the gNB" - echo "############################################################" - CURRENT_GNB_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_gnb.log - start_rf_sim_gnb $GNB_VM_CMDS "$GNB_VM_IP_ADDR" $CURRENT_GNB_LOG_FILE $PRB $CONF_FILE $S1_NOS1_CFG + echo "############################################################" + echo "${CN_CONFIG} : Starting the gNB" + echo "############################################################" + CURRENT_GNB_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_gnb.log + start_rf_sim_gnb $GNB_VM_CMDS "$GNB_VM_IP_ADDR" $CURRENT_GNB_LOG_FILE $PRB $CONF_FILE $S1_NOS1_CFG - echo "############################################################" - echo "${CN_CONFIG} : Starting the NR-UE" - echo "############################################################" - CURRENT_NR_UE_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ue.log - start_rf_sim_nr_ue $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $GNB_VM_IP_ADDR $CURRENT_NR_UE_LOG_FILE $PRB $FREQUENCY $S1_NOS1_CFG - if [ $NR_UE_SYNC -eq 0 ] - then - echo "Problem w/ gNB and NR-UE not syncing" + echo "############################################################" + echo "${CN_CONFIG} : Starting the NR-UE" + echo "############################################################" + CURRENT_NR_UE_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ue.log + start_rf_sim_nr_ue $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $GNB_VM_IP_ADDR $CURRENT_NR_UE_LOG_FILE $PRB $FREQUENCY $S1_NOS1_CFG + if [ $NR_UE_SYNC -eq 0 ] + then + echo "Problem w/ gNB and NR-UE not syncing" + terminate_enb_ue_basic_sim $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 2 + terminate_enb_ue_basic_sim $GNB_VM_CMDS $GNB_VM_IP_ADDR 1 + SYNC_STATUS=-1 + try_cnt=$[$try_cnt+1] + continue + fi + + echo "############################################################" + echo "${CN_CONFIG} : Pinging the gNB from NR-UE" + echo "############################################################" + get_enb_noS1_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR + PING_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ping_gnb_from_nrue.log + ping_epc_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $ENB_IP_ADDR $PING_LOG_FILE 1 0 + scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/$PING_LOG_FILE $ARCHIVES_LOC + check_ping_result $ARCHIVES_LOC/$PING_LOG_FILE 20 + + echo "############################################################" + echo "${CN_CONFIG} : Pinging the NR-UE from gNB" + echo "############################################################" + get_ue_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 1 + PING_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ping_from_gnb_nrue.log + ping_enb_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR $UE_IP_ADDR $PING_LOG_FILE 0 + scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/$PING_LOG_FILE $ARCHIVES_LOC + check_ping_result $ARCHIVES_LOC/$PING_LOG_FILE 20 + + echo "############################################################" + echo "${CN_CONFIG} : iperf DL -- NR-UE is server and gNB is client" + echo "############################################################" + THROUGHPUT="30K" + CURR_IPERF_LOG_BASE=tdd_${PRB}prb_${CN_CONFIG}_iperf_dl + get_enb_noS1_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR + get_ue_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 1 + generic_iperf $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $UE_IP_ADDR $GNB_VM_CMDS $GNB_VM_IP_ADDR $ENB_IP_ADDR $THROUGHPUT $CURR_IPERF_LOG_BASE 1 0 + scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/${CURR_IPERF_LOG_BASE}_client.txt $ARCHIVES_LOC + scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/${CURR_IPERF_LOG_BASE}_server.txt $ARCHIVES_LOC + check_iperf $ARCHIVES_LOC/$CURR_IPERF_LOG_BASE $THROUGHPUT + if [ $IPERF_STATUS -ne 0 ] + then + echo "DL test not OK" + terminate_enb_ue_basic_sim $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 2 + terminate_enb_ue_basic_sim $GNB_VM_CMDS $GNB_VM_IP_ADDR 1 + try_cnt=$[$try_cnt+1] + continue + fi + + echo "############################################################" + echo "${CN_CONFIG} : iperf UL -- gNB is server and NR-UE is client" + echo "############################################################" + THROUGHPUT="30K" + CURR_IPERF_LOG_BASE=tdd_${PRB}prb_${CN_CONFIG}_iperf_ul + get_enb_noS1_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR + get_ue_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 1 + generic_iperf $GNB_VM_CMDS $GNB_VM_IP_ADDR $ENB_IP_ADDR $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $UE_IP_ADDR $THROUGHPUT $CURR_IPERF_LOG_BASE 1 0 + scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/${CURR_IPERF_LOG_BASE}_server.txt $ARCHIVES_LOC + scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/${CURR_IPERF_LOG_BASE}_client.txt $ARCHIVES_LOC + check_iperf $ARCHIVES_LOC/$CURR_IPERF_LOG_BASE $THROUGHPUT + + echo "############################################################" + echo "${CN_CONFIG} : Terminate gNB/NR-UE simulators" + echo "############################################################" terminate_enb_ue_basic_sim $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 2 terminate_enb_ue_basic_sim $GNB_VM_CMDS $GNB_VM_IP_ADDR 1 scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_NR_UE_LOG_FILE $ARCHIVES_LOC - echo "5G-NR RFSIM seems to FAIL" - echo "5G-NR: TEST_KO" >> $ARCHIVES_LOC/test_final_status.log - STATUS=-1 - return - fi - - echo "############################################################" - echo "${CN_CONFIG} : iperf DL -- NR-UE is server and gNB is client" - echo "############################################################" - THROUGHPUT="30K" - CURR_IPERF_LOG_BASE=tdd_${PRB}prb_${CN_CONFIG}_iperf_dl - get_enb_noS1_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR - get_ue_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 1 - generic_iperf $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $UE_IP_ADDR $GNB_VM_CMDS $GNB_VM_IP_ADDR $ENB_IP_ADDR $THROUGHPUT $CURR_IPERF_LOG_BASE 1 0 - scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/${CURR_IPERF_LOG_BASE}_client.txt $ARCHIVES_LOC - scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/${CURR_IPERF_LOG_BASE}_server.txt $ARCHIVES_LOC - check_iperf $ARCHIVES_LOC/$CURR_IPERF_LOG_BASE $THROUGHPUT - - echo "############################################################" - echo "${CN_CONFIG} : iperf UL -- gNB is server and NR-UE is client" - echo "############################################################" - THROUGHPUT="30K" - CURR_IPERF_LOG_BASE=tdd_${PRB}prb_${CN_CONFIG}_iperf_ul - get_enb_noS1_ip_addr $GNB_VM_CMDS $GNB_VM_IP_ADDR - get_ue_ip_addr $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 1 - generic_iperf $GNB_VM_CMDS $GNB_VM_IP_ADDR $ENB_IP_ADDR $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $UE_IP_ADDR $THROUGHPUT $CURR_IPERF_LOG_BASE 1 0 - scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/${CURR_IPERF_LOG_BASE}_server.txt $ARCHIVES_LOC - scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/${CURR_IPERF_LOG_BASE}_client.txt $ARCHIVES_LOC - check_iperf $ARCHIVES_LOC/$CURR_IPERF_LOG_BASE $THROUGHPUT - - echo "############################################################" - echo "${CN_CONFIG} : Terminate gNB/NR-UE simulators" - echo "############################################################" - terminate_enb_ue_basic_sim $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 2 - terminate_enb_ue_basic_sim $GNB_VM_CMDS $GNB_VM_IP_ADDR 1 - scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC - scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_NR_UE_LOG_FILE $ARCHIVES_LOC - + if [ $IPERF_STATUS -ne 0 ] + then + echo "UL test not OK" + try_cnt=$[$try_cnt+1] + else + try_cnt=$[$try_cnt+10] + fi + done ######### end of loop full_l2_sim_destroy + echo "############################################################" echo "Checking run status" echo "############################################################" + if [ $SYNC_STATUS -ne 0 ]; then NR_STATUS=-1; fi if [ $PING_STATUS -ne 0 ]; then NR_STATUS=-1; fi if [ $IPERF_STATUS -ne 0 ]; then NR_STATUS=-1; fi if [ $NR_STATUS -eq 0 ] From 71cbb7e894750504c2f9ad9b53c927d1847946c2 Mon Sep 17 00:00:00 2001 From: laurent Date: Thu, 16 Apr 2020 10:40:33 +0200 Subject: [PATCH 162/240] dirty workaround if4p5 bug --- cmake_targets/CMakeLists.txt | 10 +++++----- openair2/MCE_APP/mce_app.c | 4 +++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 05d32b74df..6382bbea51 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -185,7 +185,7 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath -Wl,${CMAKE_CU # set a flag for changes in the source code # these changes are related to hardcoded path to include .h files set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -g3 -DMALLOC_CHECK_=3") -set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS} -g3 -DMALLOC_CHECK_=3 -Og") +set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS} -g3 -DMALLOC_CHECK_=3 -O2") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -O3") set(GIT_BRANCH "UNKNOWN") @@ -2519,7 +2519,7 @@ target_link_libraries (lte-softmodem ${LIB_LMS_LIBRARIES}) target_link_libraries (lte-softmodem ${T_LIB}) -add_executable(ocp-softmodem +add_executable(ocp-enb ${OPENAIR_DIR}/executables/main-ocp.c ${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c ${OPENAIR_DIR}/executables/softmodem-common.c @@ -2545,15 +2545,15 @@ add_executable(ocp-softmodem ${CONFIG_SOURCES} ${SHLIB_LOADER_SOURCES} ) -add_dependencies(ocp-softmodem rrc_flag s1ap_flag x2_flag oai_iqplayer) +add_dependencies(ocp-enb rrc_flag s1ap_flag x2_flag oai_iqplayer) -target_link_libraries (ocp-softmodem +target_link_libraries (ocp-enb -Wl,--start-group RRC_LIB NR_RRC_LIB S1AP_LIB S1AP_ENB F1AP_LIB F1AP M2AP_LIB M2AP_ENB X2AP_LIB X2AP_ENB M3AP_LIB M3AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT MME_APP UDP SCHED_LIB SCHED_RU_LIB PHY_COMMON PHY PHY_RU LFDS L2 L2_LTE NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB LFDS7 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} ${FSPT_MSG_LIB} ${PROTO_AGENT_LIB} -Wl,--end-group z dl) -target_link_libraries (ocp-softmodem ${LIBXML2_LIBRARIES} pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES} ${LIB_LMS_LIBRARIES} ${T_LIB}) +target_link_libraries (ocp-enb ${LIBXML2_LIBRARIES} pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${PROTOBUF_LIB} ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES} ${LIB_LMS_LIBRARIES} ${T_LIB}) add_executable(cu_test ${OPENAIR2_DIR}/LAYER2/PROTO_AGENT/cu_test.c diff --git a/openair2/MCE_APP/mce_app.c b/openair2/MCE_APP/mce_app.c index 32dfa5cc42..6f7454c321 100644 --- a/openair2/MCE_APP/mce_app.c +++ b/openair2/MCE_APP/mce_app.c @@ -343,7 +343,9 @@ void *MCE_app_task(void *args_p) { /* Try to register each MCE */ // This assumes that node_type of all RRC instances is the same - if (EPC_MODE_ENABLED) { + if ( EPC_MODE_ENABLED && RC.rrc == NULL ) + LOG_E(RRC, "inconsistent global variables\n"); + if (EPC_MODE_ENABLED && RC.rrc ) { register_mce_pending = MCE_app_register(RC.rrc[0]->node_type, mce_id_start, mce_id_end); } From 3310f5c6b04f30720c783abe3b05e58113cfd170 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Thu, 25 Apr 2019 10:54:58 +0200 Subject: [PATCH 163/240] alternative RLC implementation This commit introduces an alternative RLC implementation based on 36.322 version 8. AM and UM done, TM not done. See openair2/LAYER2/rlc_v2/TODO for missing parts. --- cmake_targets/CMakeLists.txt | 21 +- common/utils/T/tracer/hacks/pilot_timeplot.sh | 15 + common/utils/T/tracer/hacks/time_meas.c | 10 +- common/utils/T/tracer/hacks/timeplot.c | 18 +- openair2/COMMON/rrc_messages_def.h | 3 + openair2/COMMON/rrc_messages_types.h | 10 + openair2/LAYER2/rlc_v2/TODO | 18 + openair2/LAYER2/rlc_v2/asn1_utils.c | 129 ++ openair2/LAYER2/rlc_v2/asn1_utils.h | 33 + openair2/LAYER2/rlc_v2/rlc_entity.c | 144 ++ openair2/LAYER2/rlc_v2/rlc_entity.h | 97 + openair2/LAYER2/rlc_v2/rlc_entity_am.c | 1694 +++++++++++++++++ openair2/LAYER2/rlc_v2/rlc_entity_am.h | 285 +++ openair2/LAYER2/rlc_v2/rlc_entity_um.c | 703 +++++++ openair2/LAYER2/rlc_v2/rlc_entity_um.h | 90 + openair2/LAYER2/rlc_v2/rlc_oai_api.c | 821 ++++++++ openair2/LAYER2/rlc_v2/rlc_pdu.c | 266 +++ openair2/LAYER2/rlc_v2/rlc_pdu.h | 109 ++ openair2/LAYER2/rlc_v2/rlc_sdu.c | 68 + openair2/LAYER2/rlc_v2/rlc_sdu.h | 39 + openair2/LAYER2/rlc_v2/rlc_ue_manager.c | 182 ++ openair2/LAYER2/rlc_v2/rlc_ue_manager.h | 58 + openair2/LAYER2/rlc_v2/tests/LOG/log.h | 10 + openair2/LAYER2/rlc_v2/tests/Makefile | 32 + openair2/LAYER2/rlc_v2/tests/README | 38 + openair2/LAYER2/rlc_v2/tests/make_pdu.c | 29 + openair2/LAYER2/rlc_v2/tests/run_tests.sh | 12 + openair2/LAYER2/rlc_v2/tests/test.c | 433 +++++ openair2/LAYER2/rlc_v2/tests/test1.h | 14 + openair2/LAYER2/rlc_v2/tests/test1.txt.gz | Bin 0 -> 238 bytes openair2/LAYER2/rlc_v2/tests/test10.h | 23 + openair2/LAYER2/rlc_v2/tests/test10.txt.gz | Bin 0 -> 361 bytes openair2/LAYER2/rlc_v2/tests/test11.h | 37 + openair2/LAYER2/rlc_v2/tests/test11.txt.gz | Bin 0 -> 430 bytes openair2/LAYER2/rlc_v2/tests/test12.h | 34 + openair2/LAYER2/rlc_v2/tests/test12.txt.gz | Bin 0 -> 415 bytes openair2/LAYER2/rlc_v2/tests/test13.h | 30 + openair2/LAYER2/rlc_v2/tests/test13.txt.gz | Bin 0 -> 351 bytes openair2/LAYER2/rlc_v2/tests/test14.h | 12 + openair2/LAYER2/rlc_v2/tests/test14.txt.gz | Bin 0 -> 180 bytes openair2/LAYER2/rlc_v2/tests/test15.h | 42 + openair2/LAYER2/rlc_v2/tests/test15.txt.gz | Bin 0 -> 360 bytes openair2/LAYER2/rlc_v2/tests/test16.h | 48 + openair2/LAYER2/rlc_v2/tests/test16.txt.gz | Bin 0 -> 353 bytes openair2/LAYER2/rlc_v2/tests/test17.h | 30 + openair2/LAYER2/rlc_v2/tests/test17.txt.gz | Bin 0 -> 298 bytes openair2/LAYER2/rlc_v2/tests/test18.h | 10 + openair2/LAYER2/rlc_v2/tests/test18.txt.gz | Bin 0 -> 207 bytes openair2/LAYER2/rlc_v2/tests/test19.h | 54 + openair2/LAYER2/rlc_v2/tests/test19.txt.gz | Bin 0 -> 101 bytes openair2/LAYER2/rlc_v2/tests/test2.h | 10 + openair2/LAYER2/rlc_v2/tests/test2.txt.gz | Bin 0 -> 1616 bytes openair2/LAYER2/rlc_v2/tests/test20.h | 28 + openair2/LAYER2/rlc_v2/tests/test20.txt.gz | Bin 0 -> 3931 bytes openair2/LAYER2/rlc_v2/tests/test21.h | 18 + openair2/LAYER2/rlc_v2/tests/test21.txt.gz | Bin 0 -> 970 bytes openair2/LAYER2/rlc_v2/tests/test22.h | 25 + openair2/LAYER2/rlc_v2/tests/test22.txt.gz | Bin 0 -> 392 bytes openair2/LAYER2/rlc_v2/tests/test23.h | 9 + openair2/LAYER2/rlc_v2/tests/test23.txt.gz | Bin 0 -> 266 bytes openair2/LAYER2/rlc_v2/tests/test24.h | 9 + openair2/LAYER2/rlc_v2/tests/test24.txt.gz | Bin 0 -> 324 bytes openair2/LAYER2/rlc_v2/tests/test25.h | 8 + openair2/LAYER2/rlc_v2/tests/test25.txt.gz | Bin 0 -> 161 bytes openair2/LAYER2/rlc_v2/tests/test26.h | 25 + openair2/LAYER2/rlc_v2/tests/test26.txt.gz | Bin 0 -> 374 bytes openair2/LAYER2/rlc_v2/tests/test27.h | 17 + openair2/LAYER2/rlc_v2/tests/test27.txt.gz | Bin 0 -> 243 bytes openair2/LAYER2/rlc_v2/tests/test28.h | 18 + openair2/LAYER2/rlc_v2/tests/test28.txt.gz | Bin 0 -> 282 bytes openair2/LAYER2/rlc_v2/tests/test29.h | 21 + openair2/LAYER2/rlc_v2/tests/test29.txt.gz | Bin 0 -> 349 bytes openair2/LAYER2/rlc_v2/tests/test3.h | 11 + openair2/LAYER2/rlc_v2/tests/test3.txt.gz | Bin 0 -> 757 bytes openair2/LAYER2/rlc_v2/tests/test30.h | 16 + openair2/LAYER2/rlc_v2/tests/test30.txt.gz | Bin 0 -> 395 bytes openair2/LAYER2/rlc_v2/tests/test31.h | 10 + openair2/LAYER2/rlc_v2/tests/test31.txt.gz | Bin 0 -> 267 bytes openair2/LAYER2/rlc_v2/tests/test32.h | 10 + openair2/LAYER2/rlc_v2/tests/test32.txt.gz | Bin 0 -> 268 bytes openair2/LAYER2/rlc_v2/tests/test33.h | 18 + openair2/LAYER2/rlc_v2/tests/test33.txt.gz | Bin 0 -> 421 bytes openair2/LAYER2/rlc_v2/tests/test34.h | 15 + openair2/LAYER2/rlc_v2/tests/test34.txt.gz | Bin 0 -> 434 bytes openair2/LAYER2/rlc_v2/tests/test35.h | 9 + openair2/LAYER2/rlc_v2/tests/test35.txt.gz | Bin 0 -> 170 bytes openair2/LAYER2/rlc_v2/tests/test36.h | 14 + openair2/LAYER2/rlc_v2/tests/test36.txt.gz | Bin 0 -> 379 bytes openair2/LAYER2/rlc_v2/tests/test37.h | 37 + openair2/LAYER2/rlc_v2/tests/test37.txt.gz | Bin 0 -> 92 bytes openair2/LAYER2/rlc_v2/tests/test38.h | 22 + openair2/LAYER2/rlc_v2/tests/test38.txt.gz | Bin 0 -> 1048 bytes openair2/LAYER2/rlc_v2/tests/test39.h | 9 + openair2/LAYER2/rlc_v2/tests/test39.txt.gz | Bin 0 -> 758 bytes openair2/LAYER2/rlc_v2/tests/test4.h | 13 + openair2/LAYER2/rlc_v2/tests/test4.txt.gz | Bin 0 -> 166 bytes openair2/LAYER2/rlc_v2/tests/test40.h | 9 + openair2/LAYER2/rlc_v2/tests/test40.txt.gz | Bin 0 -> 148 bytes openair2/LAYER2/rlc_v2/tests/test41.h | 45 + openair2/LAYER2/rlc_v2/tests/test41.txt.gz | Bin 0 -> 875 bytes openair2/LAYER2/rlc_v2/tests/test42.h | 39 + openair2/LAYER2/rlc_v2/tests/test42.txt.gz | Bin 0 -> 496 bytes openair2/LAYER2/rlc_v2/tests/test43.h | 39 + openair2/LAYER2/rlc_v2/tests/test43.txt.gz | Bin 0 -> 416 bytes openair2/LAYER2/rlc_v2/tests/test44.h | 20 + openair2/LAYER2/rlc_v2/tests/test44.txt.gz | Bin 0 -> 278 bytes openair2/LAYER2/rlc_v2/tests/test45.h | 30 + openair2/LAYER2/rlc_v2/tests/test45.txt.gz | Bin 0 -> 358 bytes openair2/LAYER2/rlc_v2/tests/test5.h | 13 + openair2/LAYER2/rlc_v2/tests/test5.txt.gz | Bin 0 -> 167 bytes openair2/LAYER2/rlc_v2/tests/test6.h | 27 + openair2/LAYER2/rlc_v2/tests/test6.txt.gz | Bin 0 -> 777 bytes openair2/LAYER2/rlc_v2/tests/test7.h | 26 + openair2/LAYER2/rlc_v2/tests/test7.txt.gz | Bin 0 -> 796 bytes openair2/LAYER2/rlc_v2/tests/test8.h | 19 + openair2/LAYER2/rlc_v2/tests/test8.txt.gz | Bin 0 -> 461 bytes openair2/LAYER2/rlc_v2/tests/test9.h | 34 + openair2/LAYER2/rlc_v2/tests/test9.txt.gz | Bin 0 -> 327 bytes openair2/RRC/LTE/rrc_eNB.c | 228 ++- 119 files changed, 6579 insertions(+), 23 deletions(-) create mode 100755 common/utils/T/tracer/hacks/pilot_timeplot.sh create mode 100644 openair2/LAYER2/rlc_v2/TODO create mode 100644 openair2/LAYER2/rlc_v2/asn1_utils.c create mode 100644 openair2/LAYER2/rlc_v2/asn1_utils.h create mode 100644 openair2/LAYER2/rlc_v2/rlc_entity.c create mode 100644 openair2/LAYER2/rlc_v2/rlc_entity.h create mode 100644 openair2/LAYER2/rlc_v2/rlc_entity_am.c create mode 100644 openair2/LAYER2/rlc_v2/rlc_entity_am.h create mode 100644 openair2/LAYER2/rlc_v2/rlc_entity_um.c create mode 100644 openair2/LAYER2/rlc_v2/rlc_entity_um.h create mode 100644 openair2/LAYER2/rlc_v2/rlc_oai_api.c create mode 100644 openair2/LAYER2/rlc_v2/rlc_pdu.c create mode 100644 openair2/LAYER2/rlc_v2/rlc_pdu.h create mode 100644 openair2/LAYER2/rlc_v2/rlc_sdu.c create mode 100644 openair2/LAYER2/rlc_v2/rlc_sdu.h create mode 100644 openair2/LAYER2/rlc_v2/rlc_ue_manager.c create mode 100644 openair2/LAYER2/rlc_v2/rlc_ue_manager.h create mode 100644 openair2/LAYER2/rlc_v2/tests/LOG/log.h create mode 100644 openair2/LAYER2/rlc_v2/tests/Makefile create mode 100644 openair2/LAYER2/rlc_v2/tests/README create mode 100644 openair2/LAYER2/rlc_v2/tests/make_pdu.c create mode 100755 openair2/LAYER2/rlc_v2/tests/run_tests.sh create mode 100644 openair2/LAYER2/rlc_v2/tests/test.c create mode 100644 openair2/LAYER2/rlc_v2/tests/test1.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test1.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test10.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test10.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test11.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test11.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test12.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test12.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test13.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test13.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test14.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test14.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test15.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test15.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test16.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test16.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test17.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test17.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test18.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test18.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test19.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test19.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test2.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test2.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test20.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test20.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test21.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test21.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test22.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test22.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test23.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test23.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test24.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test24.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test25.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test25.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test26.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test26.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test27.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test27.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test28.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test28.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test29.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test29.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test3.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test3.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test30.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test30.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test31.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test31.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test32.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test32.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test33.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test33.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test34.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test34.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test35.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test35.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test36.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test36.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test37.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test37.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test38.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test38.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test39.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test39.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test4.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test4.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test40.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test40.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test41.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test41.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test42.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test42.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test43.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test43.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test44.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test44.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test45.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test45.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test5.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test5.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test6.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test6.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test7.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test7.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test8.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test8.txt.gz create mode 100644 openair2/LAYER2/rlc_v2/tests/test9.h create mode 100644 openair2/LAYER2/rlc_v2/tests/test9.txt.gz diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index f155d3061d..68849c0191 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -727,7 +727,6 @@ Message("CPU_Affinity flag is ${CPU_AFFINITY}") ############################################################## add_boolean_option(NO_RRM True "DO WE HAVE A RADIO RESSOURCE MANAGER: NO") -add_boolean_option(RRC_DEFAULT_RAB_IS_AM False "set the RLC mode to AM for the default bearer") add_boolean_option(OAI_NW_DRIVER_TYPE_ETHERNET False "????") add_boolean_option(DEADLINE_SCHEDULER True "Use the Linux scheduler SCHED_DEADLINE: kernel >= 3.14") @@ -828,7 +827,7 @@ add_boolean_option(TRACE_RLC_UM_TX_STATUS False "TRACE for RLC UM, TO BE CHANGE ########################## # RRC LAYER OPTIONS ########################## -add_boolean_option(RRC_DEFAULT_RAB_IS_AM False "Otherwise it is UM, configure params are actually set in rrc_eNB.c:rrc_eNB_generate_defaultRRCConnectionReconfiguration(...)") +add_boolean_option(RRC_DEFAULT_RAB_IS_AM True "set the RLC mode to AM for the default bearer, otherwise it is UM.") ########################## @@ -1640,7 +1639,7 @@ set(NR_RRC_DIR ${OPENAIR2_DIR}/RRC/NR) set(NR_UE_RRC_DIR ${OPENAIR2_DIR}/RRC/NR_UE) set(PDCP_DIR ${OPENAIR2_DIR}/LAYER2/PDCP_v10.1.0) -set(LTE_RLC_SRC +set(RLC_ENB_V1 ${RLC_AM_DIR}/rlc_am.c ${RLC_AM_DIR}/rlc_am_init.c ${RLC_AM_DIR}/rlc_am_timer_poll_retransmit.c @@ -1670,6 +1669,17 @@ set(LTE_RLC_SRC ${RLC_DIR}/rlc_mpls.c ) +set(RLC_ENB_V2 + ${OPENAIR2_DIR}/LAYER2/rlc_v2/rlc_oai_api.c + ${OPENAIR2_DIR}/LAYER2/rlc_v2/asn1_utils.c + ${OPENAIR2_DIR}/LAYER2/rlc_v2/rlc_ue_manager.c + ${OPENAIR2_DIR}/LAYER2/rlc_v2/rlc_entity.c + ${OPENAIR2_DIR}/LAYER2/rlc_v2/rlc_entity_am.c + ${OPENAIR2_DIR}/LAYER2/rlc_v2/rlc_entity_um.c + ${OPENAIR2_DIR}/LAYER2/rlc_v2/rlc_pdu.c + ${OPENAIR2_DIR}/LAYER2/rlc_v2/rlc_sdu.c + ) + set(NR_RLC_SRC ${OPENAIR2_DIR}/LAYER2/nr_rlc/asn1_utils.c ${OPENAIR2_DIR}/LAYER2/nr_rlc/nr_rlc_entity.c @@ -1691,6 +1701,7 @@ set(L2_SRC ${PDCP_DIR}/pdcp_util.c ${PDCP_DIR}/pdcp_security.c ${PDCP_DIR}/pdcp_netlink.c + ${RLC_ENB_V2} # ${RRC_DIR}/rrc_UE.c ${RRC_DIR}/rrc_eNB.c ${RRC_DIR}/rrc_eNB_endc.c @@ -1704,7 +1715,7 @@ set(L2_SRC ) set(L2_LTE_SRC - ${LTE_RLC_SRC} + ${RLC_ENB_V1} ) set(L2_NR_SRC @@ -1741,7 +1752,7 @@ set(LTE_NR_L2_SRC_UE ${PDCP_DIR}/pdcp_util.c ${PDCP_DIR}/pdcp_security.c ${PDCP_DIR}/pdcp_netlink.c - ${LTE_RLC_SRC} + ${RLC_ENB_V1} ) set(NR_L2_SRC_UE diff --git a/common/utils/T/tracer/hacks/pilot_timeplot.sh b/common/utils/T/tracer/hacks/pilot_timeplot.sh new file mode 100755 index 0000000000..0d9c4694a6 --- /dev/null +++ b/common/utils/T/tracer/hacks/pilot_timeplot.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +# use UP and DOWN arrow keys to scroll the view displayed by timeplot + +while read -n 1 key +do + case "$key" in + 'B' ) + kill -SIGUSR1 `ps aux|grep timeplot|grep -v grep|grep -v sh|tr -s ' ' :|cut -f 2 -d :` + ;; + 'A' ) + kill -SIGUSR2 `ps aux|grep timeplot|grep -v grep|grep -v sh|tr -s ' ' :|cut -f 2 -d :` + ;; + esac +done diff --git a/common/utils/T/tracer/hacks/time_meas.c b/common/utils/T/tracer/hacks/time_meas.c index 6bd2950301..408189cd80 100644 --- a/common/utils/T/tracer/hacks/time_meas.c +++ b/common/utils/T/tracer/hacks/time_meas.c @@ -13,7 +13,8 @@ void usage(void) "options:\n" " -d this option is mandatory\n" " -ip connect to given IP address (default %s)\n" -" -p connect to given port (default %d)\n", +" -p connect to given port (default %d)\n" +" -e event to trace (default VCD_FUNCTION_ENB_DLSCH_ULSCH_SCHEDULER)\n", DEFAULT_REMOTE_IP, DEFAULT_REMOTE_PORT ); @@ -47,6 +48,7 @@ int main(int n, char **v) int ev_fun; int start_valid = 0; struct timespec start_time, stop_time, delta_time; + char *name = "VCD_FUNCTION_ENB_DLSCH_ULSCH_SCHEDULER"; for (i = 1; i < n; i++) { if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage(); @@ -55,6 +57,7 @@ int main(int n, char **v) if (!strcmp(v[i], "-ip")) { if (i > n-2) usage(); ip = v[++i]; continue; } if (!strcmp(v[i], "-p")) { if (i > n-2) usage(); port = atoi(v[++i]); continue; } + if (!strcmp(v[i], "-e")) { if (i > n-2) usage(); name = v[++i]; continue; } usage(); } @@ -71,10 +74,9 @@ int main(int n, char **v) is_on = calloc(number_of_events, sizeof(int)); if (is_on == NULL) abort(); - on_off(database, "VCD_FUNCTION_ENB_DLSCH_ULSCH_SCHEDULER", is_on, 1); + on_off(database, name, is_on, 1); - ev_fun = event_id_from_name(database, - "VCD_FUNCTION_ENB_DLSCH_ULSCH_SCHEDULER"); + ev_fun = event_id_from_name(database, name); socket = connect_to(ip, port); diff --git a/common/utils/T/tracer/hacks/timeplot.c b/common/utils/T/tracer/hacks/timeplot.c index 79905d16f9..a1ddb2a1c9 100644 --- a/common/utils/T/tracer/hacks/timeplot.c +++ b/common/utils/T/tracer/hacks/timeplot.c @@ -28,6 +28,7 @@ int bins[50]; #define N 1000 int data[N]; +long start = 100; void plot(void) { @@ -45,7 +46,8 @@ void plot(void) if (data[i] < vmin) vmin = data[i]; if (data[i] > vmax) vmax = data[i]; vavg += data[i]; - int ms2 = data[i]/binsize_ns; + int ms2 = (data[i] - start * 1000)/binsize_ns; + if (ms2 < 0) ms2 = 0; if (ms2 > 49) ms2 = 49; bins[ms2]++; if (bins[ms2] > max) max = bins[ms2]; @@ -55,7 +57,7 @@ void plot(void) GOTO(1,1); for (i = 0; i < 50; i++) { - double binend = (i+1) * binsize_ns / 1000.; + double binend = (i+1) * binsize_ns / 1000. + start; int k; int width = bins[i] * 70 / max; /* force at least width of 1 if some point is there */ @@ -68,11 +70,23 @@ void plot(void) printf("min %d ns max %d ns avg %ld ns\n", vmin, vmax, vavg); } +void up(int x) +{ + start += 5; +} + +void down(int x) +{ + start -= 5; +} + int main(void) { int i; int pos = 0; signal(SIGINT, sig); + signal(SIGUSR1, up); + signal(SIGUSR2, down); RESET(); HIDE_CURSOR(); while (!feof(stdin)) { diff --git a/openair2/COMMON/rrc_messages_def.h b/openair2/COMMON/rrc_messages_def.h index 1d0c2dfdb8..cde2497880 100644 --- a/openair2/COMMON/rrc_messages_def.h +++ b/openair2/COMMON/rrc_messages_def.h @@ -76,3 +76,6 @@ MESSAGE_DEF(NAS_DOWNLINK_DATA_IND, MESSAGE_PRIORITY_MED, NasDlDataInd // eNB: realtime -> RRC messages MESSAGE_DEF(RRC_SUBFRAME_PROCESS, MESSAGE_PRIORITY_MED, RrcSubframeProcess, rrc_subframe_process) + +// eNB: RLC -> RRC messages +MESSAGE_DEF(RLC_SDU_INDICATION, MESSAGE_PRIORITY_MED, RlcSduIndication, rlc_sdu_indication) diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index 68e1753448..7582de65ba 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -87,6 +87,8 @@ #define RRC_SUBFRAME_PROCESS(mSGpTR) (mSGpTR)->ittiMsg.rrc_subframe_process +#define RLC_SDU_INDICATION(mSGpTR) (mSGpTR)->ittiMsg.rlc_sdu_indication + //-------------------------------------------------------------------------------------------// typedef struct RrcStateInd_s { Rrc_State_t state; @@ -429,4 +431,12 @@ typedef struct rrc_subframe_process_s { int CC_id; } RrcSubframeProcess; +// eNB: RLC -> RRC messages +typedef struct rlc_sdu_indication_s { + int rnti; + int is_successful; + int srb_id; + int message_id; +} RlcSduIndication; + #endif /* RRC_MESSAGES_TYPES_H_ */ diff --git a/openair2/LAYER2/rlc_v2/TODO b/openair2/LAYER2/rlc_v2/TODO new file mode 100644 index 0000000000..0778d4320b --- /dev/null +++ b/openair2/LAYER2/rlc_v2/TODO @@ -0,0 +1,18 @@ +RLC AM +====== + +- 36.322 5.4 Re-establishment procedure + when possible, reassemble RLC SDUs from any byte segments of AMD PDUs + with SN < VR(MR) in the receiving side, remove RLC headers when doing + so and deliver all reassembled RLC SDUs to upper layer in ascending order + of the RLC SN, if not delivered before; + +- 36.322 5.2.3 Status reporting + delay triggering the STATUS report until x < VR(MS) or x >= VR(MR) + +- 36.322 5.1.3.2.3 Actions when a RLC data PDU is placed in the reception + buffer + [...] and in-sequence byte segments of the AMD PDU with SN = VR(R) [...] + +- use SOstart/SOend in NACK reporting, do not NACK full PDU if + parts of it have been received diff --git a/openair2/LAYER2/rlc_v2/asn1_utils.c b/openair2/LAYER2/rlc_v2/asn1_utils.c new file mode 100644 index 0000000000..46f7d90da5 --- /dev/null +++ b/openair2/LAYER2/rlc_v2/asn1_utils.c @@ -0,0 +1,129 @@ +/* + * 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 "rlc.h" + +int decode_t_reordering(int v) +{ + static int tab[32] = { + 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, + 90, 95, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 1600 + }; + + if (v < 0 || v > 31) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + return tab[v]; +} + +int decode_t_status_prohibit(int v) +{ + static int tab[62] = { + 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, + 95, 100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 165, + 170, 175, 180, 185, 190, 195, 200, 205, 210, 215, 220, 225, 230, 235, 240, + 245, 250, 300, 350, 400, 450, 500, 800, 1000, 1200, 1600, 2000, 2400 + }; + + if (v < 0 || v > 61) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + return tab[v]; +} + +int decode_t_poll_retransmit(int v) +{ + static int tab[59] = { + 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, + 100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 165, 170, + 175, 180, 185, 190, 195, 200, 205, 210, 215, 220, 225, 230, 235, 240, 245, + 250, 300, 350, 400, 450, 500, 800, 1000, 2000, 4000 + }; + + if (v < 0 || v > 58) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + return tab[v]; +} + +int decode_poll_pdu(int v) +{ + static int tab[8] = { + 4, 8, 16, 32, 64, 128, 256, -1 /* -1 means infinity */ + }; + + if (v < 0 || v > 7) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + return tab[v]; +} + +int decode_poll_byte(int v) +{ + static int tab[15] = { + 25, 50, 75, 100, 125, 250, 375, 500, 750, 1000, 1250, 1500, 2000, 3000, + -1 /* -1 means infinity */ + }; + + if (v < 0 || v > 14) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + if (tab[v] == -1) return -1; + return tab[v] * 1024; +} + +int decode_max_retx_threshold(int v) +{ + static int tab[8] = { + 1, 2, 3, 4, 6, 8, 16, 32 + }; + + if (v < 0 || v > 7) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + return tab[v]; +} + +int decode_sn_field_length(int v) +{ + static int tab[2] = { + 5, 10 + }; + + if (v < 0 || v > 1) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + return tab[v]; +} diff --git a/openair2/LAYER2/rlc_v2/asn1_utils.h b/openair2/LAYER2/rlc_v2/asn1_utils.h new file mode 100644 index 0000000000..61394c9c69 --- /dev/null +++ b/openair2/LAYER2/rlc_v2/asn1_utils.h @@ -0,0 +1,33 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef _ASN1_UTILS_H_ +#define _ASN1_UTILS_H_ + +int decode_t_reordering(int v); +int decode_t_status_prohibit(int v); +int decode_t_poll_retransmit(int v); +int decode_poll_pdu(int v); +int decode_poll_byte(int v); +int decode_max_retx_threshold(int v); +int decode_sn_field_length(int v); + +#endif /* _ASN1_UTILS_H_ */ diff --git a/openair2/LAYER2/rlc_v2/rlc_entity.c b/openair2/LAYER2/rlc_v2/rlc_entity.c new file mode 100644 index 0000000000..d774e2b7e1 --- /dev/null +++ b/openair2/LAYER2/rlc_v2/rlc_entity.c @@ -0,0 +1,144 @@ +/* + * 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 "rlc_entity.h" + +#include + +#include "rlc_entity_am.h" +#include "rlc_entity_um.h" + +#include "LOG/log.h" + +rlc_entity_t *new_rlc_entity_am( + int rx_maxsize, + int tx_maxsize, + void (*deliver_sdu)(void *deliver_sdu_data, struct rlc_entity_t *entity, + char *buf, int size), + void *deliver_sdu_data, + void (*sdu_successful_delivery)(void *sdu_successful_delivery_data, + struct rlc_entity_t *entity, + int sdu_id), + void *sdu_successful_delivery_data, + void (*max_retx_reached)(void *max_retx_reached_data, + struct rlc_entity_t *entity), + void *max_retx_reached_data, + int t_reordering, + int t_status_prohibit, + int t_poll_retransmit, + int poll_pdu, + int poll_byte, + int max_retx_threshold) +{ + rlc_entity_am_t *ret; + + ret = calloc(1, sizeof(rlc_entity_am_t)); + if (ret == NULL) { + LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + ret->common.recv_pdu = rlc_entity_am_recv_pdu; + ret->common.buffer_status = rlc_entity_am_buffer_status; + ret->common.generate_pdu = rlc_entity_am_generate_pdu; + + ret->common.recv_sdu = rlc_entity_am_recv_sdu; + + ret->common.set_time = rlc_entity_am_set_time; + + ret->common.discard_sdu = rlc_entity_am_discard_sdu; + + ret->common.reestablishment = rlc_entity_am_reestablishment; + + ret->common.delete = rlc_entity_am_delete; + + ret->common.deliver_sdu = deliver_sdu; + ret->common.deliver_sdu_data = deliver_sdu_data; + + ret->common.sdu_successful_delivery = sdu_successful_delivery; + ret->common.sdu_successful_delivery_data = sdu_successful_delivery_data; + + ret->common.max_retx_reached = max_retx_reached; + ret->common.max_retx_reached_data = max_retx_reached_data; + + ret->rx_maxsize = rx_maxsize; + ret->tx_maxsize = tx_maxsize; + ret->t_reordering = t_reordering; + ret->t_status_prohibit = t_status_prohibit; + ret->t_poll_retransmit = t_poll_retransmit; + ret->poll_pdu = poll_pdu; + ret->poll_byte = poll_byte; + ret->max_retx_threshold = max_retx_threshold; + + return (rlc_entity_t *)ret; +} + +rlc_entity_t *new_rlc_entity_um( + int rx_maxsize, + int tx_maxsize, + void (*deliver_sdu)(void *deliver_sdu_data, struct rlc_entity_t *entity, + char *buf, int size), + void *deliver_sdu_data, + int t_reordering, + int sn_field_length) +{ + rlc_entity_um_t *ret; + + ret = calloc(1, sizeof(rlc_entity_um_t)); + if (ret == NULL) { + LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + ret->common.recv_pdu = rlc_entity_um_recv_pdu; + ret->common.buffer_status = rlc_entity_um_buffer_status; + ret->common.generate_pdu = rlc_entity_um_generate_pdu; + + ret->common.recv_sdu = rlc_entity_um_recv_sdu; + + ret->common.set_time = rlc_entity_um_set_time; + + ret->common.discard_sdu = rlc_entity_um_discard_sdu; + + ret->common.reestablishment = rlc_entity_um_reestablishment; + + ret->common.delete = rlc_entity_um_delete; + + ret->common.deliver_sdu = deliver_sdu; + ret->common.deliver_sdu_data = deliver_sdu_data; + + ret->sn_field_length = sn_field_length; + ret->rx_maxsize = rx_maxsize; + ret->tx_maxsize = tx_maxsize; + ret->t_reordering = t_reordering; + + if (sn_field_length == 5) + ret->sn_modulus = 32; + else if (sn_field_length == 10) + ret->sn_modulus = 1024; + else { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + ret->window_size = ret->sn_modulus / 2; + + return (rlc_entity_t *)ret; +} diff --git a/openair2/LAYER2/rlc_v2/rlc_entity.h b/openair2/LAYER2/rlc_v2/rlc_entity.h new file mode 100644 index 0000000000..c9b35204f0 --- /dev/null +++ b/openair2/LAYER2/rlc_v2/rlc_entity.h @@ -0,0 +1,97 @@ +/* + * 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 _RLC_ENTITY_H_ +#define _RLC_ENTITY_H_ + +#include + +#define SDU_MAX 16000 /* maximum PDCP SDU size is 8188, let's take more */ + +typedef struct { + int status_size; + int tx_size; + int retx_size; +} rlc_entity_buffer_status_t; + +typedef struct rlc_entity_t { + /* functions provided by the RLC module */ + void (*recv_pdu)(struct rlc_entity_t *entity, char *buffer, int size); + rlc_entity_buffer_status_t (*buffer_status)( + struct rlc_entity_t *entity, int maxsize); + int (*generate_pdu)(struct rlc_entity_t *entity, char *buffer, int size); + + void (*recv_sdu)(struct rlc_entity_t *entity, char *buffer, int size, + int sdu_id); + + void (*set_time)(struct rlc_entity_t *entity, uint64_t now); + + void (*discard_sdu)(struct rlc_entity_t *entity, int sdu_id); + + void (*reestablishment)(struct rlc_entity_t *entity); + + void (*delete)(struct rlc_entity_t *entity); + + /* callbacks provided to the RLC module */ + void (*deliver_sdu)(void *deliver_sdu_data, struct rlc_entity_t *entity, + char *buf, int size); + void *deliver_sdu_data; + + void (*sdu_successful_delivery)(void *sdu_successful_delivery_data, + struct rlc_entity_t *entity, + int sdu_id); + void *sdu_successful_delivery_data; + + void (*max_retx_reached)(void *max_retx_reached_data, + struct rlc_entity_t *entity); + void *max_retx_reached_data; +} rlc_entity_t; + +rlc_entity_t *new_rlc_entity_am( + int rx_maxsize, + int tx_maxsize, + void (*deliver_sdu)(void *deliver_sdu_data, struct rlc_entity_t *entity, + char *buf, int size), + void *deliver_sdu_data, + void (*sdu_successful_delivery)(void *sdu_successful_delivery_data, + struct rlc_entity_t *entity, + int sdu_id), + void *sdu_successful_delivery_data, + void (*max_retx_reached)(void *max_retx_reached_data, + struct rlc_entity_t *entity), + void *max_retx_reached_data, + int t_reordering, + int t_status_prohibit, + int t_poll_retransmit, + int poll_pdu, + int poll_byte, + int max_retx_threshold); + +rlc_entity_t *new_rlc_entity_um( + int rx_maxsize, + int tx_maxsize, + void (*deliver_sdu)(void *deliver_sdu_data, struct rlc_entity_t *entity, + char *buf, int size), + void *deliver_sdu_data, + int t_reordering, + int sn_field_length); + +#endif /* _RLC_ENTITY_H_ */ diff --git a/openair2/LAYER2/rlc_v2/rlc_entity_am.c b/openair2/LAYER2/rlc_v2/rlc_entity_am.c new file mode 100644 index 0000000000..5b3df3ec75 --- /dev/null +++ b/openair2/LAYER2/rlc_v2/rlc_entity_am.c @@ -0,0 +1,1694 @@ +/* + * 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 "rlc_entity_am.h" +#include "rlc_pdu.h" + +#include +#include + +#include "LOG/log.h" + +/*************************************************************************/ +/* PDU RX functions */ +/*************************************************************************/ + +static int modulus_rx(rlc_entity_am_t *entity, int a) +{ + /* as per 36.322 7.1, modulus base is vr(r) and modulus is 1024 for rx */ + int r = a - entity->vr_r; + if (r < 0) r += 1024; + return r; +} + +/* used in both RX and TX processing */ +static int modulus_tx(rlc_entity_am_t *entity, int a) +{ + /* as per 36.322 7.1, modulus base is vt(a) and modulus is 1024 for tx */ + int r = a - entity->vt_a; + if (r < 0) r += 1024; + return r; +} + +static int sn_in_recv_window(void *_entity, int sn) +{ + rlc_entity_am_t *entity = _entity; + int mod_sn = modulus_rx(entity, sn); + /* we simplify vr(r)<=snrx_list; + + while (l != NULL) { + if (l->sn == sn && l->so <= so && + l->so + l->size - l->data_offset >= so + data_size) + return 1; + l = l->next; + } + + return 0; +} + +static int rlc_am_segment_full(rlc_entity_am_t *entity, int sn) +{ + rlc_rx_pdu_segment_t *l = entity->rx_list; + int last_byte; + int new_last_byte; + + last_byte = -1; + while (l != NULL) { + if (l->sn == sn) + break; + l = l->next; + } + while (l != NULL && l->sn == sn) { + if (l->so > last_byte + 1) + return 0; + if (l->is_last) + return 1; + new_last_byte = l->so + l->size - l->data_offset - 1; + if (new_last_byte > last_byte) + last_byte = new_last_byte; + l = l->next; + } + return 0; +} + +/* return 1 if the new segment has some data to consume, 0 if not */ +static int rlc_am_reassemble_next_segment(rlc_am_reassemble_t *r) +{ + int rf; + int sn; + + r->sdu_offset = r->start->data_offset; + + rlc_pdu_decoder_init(&r->dec, r->start->data, r->start->size); + + rlc_pdu_decoder_get_bits(&r->dec, 1); /* dc */ + rf = rlc_pdu_decoder_get_bits(&r->dec, 1); + rlc_pdu_decoder_get_bits(&r->dec, 1); /* p */ + r->fi = rlc_pdu_decoder_get_bits(&r->dec, 2); + r->e = rlc_pdu_decoder_get_bits(&r->dec, 1); + sn = rlc_pdu_decoder_get_bits(&r->dec, 10); + if (rf) { + rlc_pdu_decoder_get_bits(&r->dec, 1); /* lsf */ + r->so = rlc_pdu_decoder_get_bits(&r->dec, 15); + } else { + r->so = 0; + } + + if (r->e) { + r->e = rlc_pdu_decoder_get_bits(&r->dec, 1); + r->sdu_len = rlc_pdu_decoder_get_bits(&r->dec, 11); + } else + r->sdu_len = r->start->size - r->sdu_offset; + + /* new sn: read starts from PDU byte 0 */ + if (sn != r->sn) { + r->pdu_byte = 0; + r->sn = sn; + } + + r->data_pos = r->start->data_offset + r->pdu_byte - r->so; + + /* TODO: remove this check, it is useless, data has been validated before */ + if (r->pdu_byte < r->so) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + /* if pdu_byte is not in [so .. so+len-1] then all bytes from this segment + * have already been consumed + */ + if (r->pdu_byte >= r->so + r->start->size - r->start->data_offset) + return 0; + + /* go to correct SDU */ + while (r->pdu_byte >= r->so + (r->sdu_offset - r->start->data_offset) + r->sdu_len) { + r->sdu_offset += r->sdu_len; + if (r->e) { + r->e = rlc_pdu_decoder_get_bits(&r->dec, 1); + r->sdu_len = rlc_pdu_decoder_get_bits(&r->dec, 11); + } else { + r->sdu_len = r->start->size - r->sdu_offset; + } + } + + return 1; +} + +static void rlc_am_reassemble(rlc_entity_am_t *entity) +{ + rlc_am_reassemble_t *r = &entity->reassemble; + + while (r->start != NULL) { + if (r->sdu_pos >= SDU_MAX) { + /* TODO: proper error handling (discard PDUs with current sn from + * reassembly queue? something else?) + */ + LOG_E(RLC, "%s:%d:%s: bad RLC PDU\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + r->sdu[r->sdu_pos] = r->start->data[r->data_pos]; + r->sdu_pos++; + r->data_pos++; + r->pdu_byte++; + if (r->data_pos == r->sdu_offset + r->sdu_len) { + /* all bytes of SDU are consumed, check if SDU is fully there. + * It is if the data pointer is not at the end of the PDU segment + * or if 'fi' & 1 == 0 + */ + if (r->data_pos != r->start->size || + (r->fi & 1) == 0) { + /* SDU is full - deliver to higher layer */ + entity->common.deliver_sdu(entity->common.deliver_sdu_data, + (rlc_entity_t *)entity, + r->sdu, r->sdu_pos); + r->sdu_pos = 0; + } + if (r->data_pos != r->start->size) { + /* not at the end, process next SDU */ + r->sdu_offset += r->sdu_len; + if (r->e) { + r->e = rlc_pdu_decoder_get_bits(&r->dec, 1); + r->sdu_len = rlc_pdu_decoder_get_bits(&r->dec, 11); + } else + r->sdu_len = r->start->size - r->sdu_offset; + } else { + /* all bytes are consumend, go to next segment not already fully + * processed, if any + */ + do { + rlc_rx_pdu_segment_t *e = r->start; + entity->rx_size -= e->size; + r->start = r->start->next; + rlc_rx_free_pdu_segment(e); + } while (r->start != NULL && !rlc_am_reassemble_next_segment(r)); + } + } + } +} + +static void rlc_am_reception_actions(rlc_entity_am_t *entity, + rlc_rx_pdu_segment_t *pdu_segment) +{ + int x = pdu_segment->sn; + int vr_ms; + int vr_r; + + if (modulus_rx(entity, x) >= modulus_rx(entity, entity->vr_h)) + entity->vr_h = (x + 1) % 1024; + + vr_ms = entity->vr_ms; + while (rlc_am_segment_full(entity, vr_ms)) + vr_ms = (vr_ms + 1) % 1024; + entity->vr_ms = vr_ms; + + if (x == entity->vr_r) { + vr_r = entity->vr_r; + while (rlc_am_segment_full(entity, vr_r)) { + /* move segments with sn=vr(r) from rx list to end of reassembly list */ + while (entity->rx_list != NULL && entity->rx_list->sn == vr_r) { + rlc_rx_pdu_segment_t *e = entity->rx_list; + entity->rx_list = e->next; + e->next = NULL; + if (entity->reassemble.start == NULL) { + entity->reassemble.start = e; + /* the list was empty, we need to init decoder */ + entity->reassemble.sn = -1; + if (!rlc_am_reassemble_next_segment(&entity->reassemble)) { + /* TODO: proper error recovery (or remove the test, it should not happen) */ + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + } else { + entity->reassemble.end->next = e; + } + entity->reassemble.end = e; + } + + /* update vr_r */ + vr_r = (vr_r + 1) % 1024; + } + entity->vr_r = vr_r; + } + + rlc_am_reassemble(entity); + + if (entity->t_reordering_start) { + int vr_x = entity->vr_x; + if (vr_x < entity->vr_r) vr_x += 1024; + if (vr_x == entity->vr_r || vr_x > entity->vr_r + 512) + entity->t_reordering_start = 0; + } + + if (entity->t_reordering_start == 0) { + if (sn_compare_rx(entity, entity->vr_h, entity->vr_r) > 0) { + entity->t_reordering_start = entity->t_current; + entity->vr_x = entity->vr_h; + } + } +} + +static void process_received_ack(rlc_entity_am_t *entity, int sn) +{ + rlc_tx_pdu_segment_t head; + rlc_tx_pdu_segment_t *cur; + rlc_tx_pdu_segment_t *prev; + + /* put all PDUs from wait and retransmit lists with SN < 'sn' to ack_list */ + + /* process wait list */ + head.next = entity->wait_list; + prev = &head; + cur = entity->wait_list; + while (cur != NULL) { + if (sn_compare_tx(entity, cur->sn, sn) < 0) { + /* remove from wait list */ + prev->next = cur->next; + /* put the PDU in the ack list */ + entity->ack_list = rlc_tx_pdu_list_add(sn_compare_tx, entity, + entity->ack_list, cur); + cur = prev->next; + } else { + prev = cur; + cur = cur->next; + } + } + entity->wait_list = head.next; + + /* process retransmit list */ + head.next = entity->retransmit_list; + prev = &head; + cur = entity->retransmit_list; + while (cur != NULL) { + if (sn_compare_tx(entity, cur->sn, sn) < 0) { + /* dec. retx_count in case we put this segment back in retransmit list + * in 'process_received_nack' + */ + cur->retx_count--; + /* remove from retransmit list */ + prev->next = cur->next; + /* put the PDU in the ack list */ + entity->ack_list = rlc_tx_pdu_list_add(sn_compare_tx, entity, + entity->ack_list, cur); + cur = prev->next; + } else { + prev = cur; + cur = cur->next; + } + } + entity->retransmit_list = head.next; + +} + +static void consider_retransmission(rlc_entity_am_t *entity, + rlc_tx_pdu_segment_t *cur) +{ + cur->retx_count++; + + /* let's report max RETX reached for all retx_count >= max_retx_threshold + * (specs say to report if retx_count == max_retx_threshold). + * Upper layers should react (radio link failure), so no big deal actually. + */ + if (cur->retx_count >= entity->max_retx_threshold) { + entity->common.max_retx_reached(entity->common.max_retx_reached_data, + (rlc_entity_t *)entity); + } + + /* let's put in retransmit list even if we are over max_retx_threshold. + * upper layers should deal with this condition, internally it's better + * for the RLC code to keep going with this segment (we only remove + * a segment that was ACKed) + */ + entity->retransmit_list = rlc_tx_pdu_list_add(sn_compare_tx, entity, + entity->retransmit_list, cur); +} + +static int so_overlap(int s1, int e1, int s2, int e2) +{ + if (s1 < s2) { + if (e1 == -1 || e1 >= s2) + return 1; + return 0; + } + if (e2 == -1 || s1 <= e2) + return 1; + return 0; +} + +static void process_received_nack(rlc_entity_am_t *entity, int sn, + int so_start, int so_end) +{ + /* put all PDU segments with SN == 'sn' and with an overlapping so start/end + * to the retransmit list + * source lists are ack list and wait list. + * Not sure if we should consider wait list, isn't the other end supposed + * to only NACK SNs lower than the ACK SN sent in the status PDU, in which + * case all potential PDU segments should all be in ack list when calling + * the current function? in doubt let's accept anything and thus process + * also wait list. + */ + rlc_tx_pdu_segment_t head; + rlc_tx_pdu_segment_t *cur; + rlc_tx_pdu_segment_t *prev; + + /* check that VT(A) <= sn < VT(S) */ + if (!(sn_compare_tx(entity, entity->vt_a, sn) <= 0 && + sn_compare_tx(entity, sn, entity->vt_s) < 0)) + return; + + /* process wait list */ + head.next = entity->wait_list; + prev = &head; + cur = entity->wait_list; + while (cur != NULL) { + if (cur->sn == sn && + so_overlap(so_start, so_end, cur->so, cur->so + cur->data_size - 1)) { + /* remove from wait list */ + prev->next = cur->next; + /* consider the PDU segment for retransmission */ + consider_retransmission(entity, cur); + cur = prev->next; + } else { + prev = cur; + cur = cur->next; + } + } + entity->wait_list = head.next; + + /* process ack list */ + head.next = entity->ack_list; + prev = &head; + cur = entity->ack_list; + while (cur != NULL) { + if (cur->sn == sn && + so_overlap(so_start, so_end, cur->so, cur->so + cur->data_size - 1)) { + /* remove from ack list */ + prev->next = cur->next; + /* consider the PDU segment for retransmission */ + consider_retransmission(entity, cur); + cur = prev->next; + } else { + prev = cur; + cur = cur->next; + } + } + entity->ack_list = head.next; +} + +int tx_pdu_in_ack_list_full(rlc_tx_pdu_segment_t *pdu) +{ + int sn = pdu->sn; + int last_byte = -1; + int new_last_byte; + int is_last_seen = 0; + + while (pdu != NULL && pdu->sn == sn) { + if (pdu->so > last_byte + 1) return 0; + if (pdu->is_last) + is_last_seen = 1; + new_last_byte = pdu->so + pdu->data_size - 1; + if (new_last_byte > last_byte) + last_byte = new_last_byte; + pdu = pdu->next; + } + + return is_last_seen == 1; +} + +int tx_pdu_in_ack_list_size(rlc_tx_pdu_segment_t *pdu) +{ + int sn = pdu->sn; + int ret = 0; + + while (pdu != NULL && pdu->sn == sn) { + ret += pdu->data_size; + pdu = pdu->next; + } + + return ret; +} + +void ack_sdu_bytes(rlc_sdu_t *start, int start_byte, int sdu_size) +{ + rlc_sdu_t *cur = start; + int remaining_size = sdu_size; + + while (remaining_size) { + int cursize = cur->size - start_byte; + if (cursize > remaining_size) + cursize = remaining_size; + cur->acked_bytes += cursize; + remaining_size -= cursize; + /* start_byte is only meaningful for the 1st SDU, then it is 0 */ + start_byte = 0; + cur = cur->next; + } +} + +rlc_tx_pdu_segment_t *tx_list_remove_sn(rlc_tx_pdu_segment_t *list, int sn) +{ + rlc_tx_pdu_segment_t head; + rlc_tx_pdu_segment_t *cur; + rlc_tx_pdu_segment_t *prev; + + head.next = list; + cur = list; + prev = &head; + + while (cur != NULL) { + if (cur->sn == sn) { + prev->next = cur->next; + rlc_tx_free_pdu(cur); + cur = prev->next; + } else { + prev = cur; + cur = cur->next; + } + } + + return head.next; +} + +void cleanup_sdu_list(rlc_entity_am_t *entity) +{ + rlc_sdu_t head; + rlc_sdu_t *cur; + rlc_sdu_t *prev; + + /* remove fully acked SDUs, indicate successful delivery to upper layer */ + head.next = entity->tx_list; + cur = entity->tx_list; + prev = &head; + + while (cur != NULL) { + if (cur->acked_bytes == cur->size) { + prev->next = cur->next; + entity->tx_size -= cur->size; + entity->common.sdu_successful_delivery( + entity->common.sdu_successful_delivery_data, + (rlc_entity_t *)entity, cur->upper_layer_id); + rlc_free_sdu(cur); + entity->tx_end = prev; + cur = prev->next; + } else { + entity->tx_end = cur; + cur = cur->next; + } + } + + entity->tx_list = head.next; + + /* if tx_end == head then it means that the list is now empty */ + if (entity->tx_end == &head) + entity->tx_end = NULL; +} + +static void finalize_ack_nack_processing(rlc_entity_am_t *entity) +{ + int sn; + rlc_tx_pdu_segment_t *cur = entity->ack_list; + int pdu_size; + + if (cur == NULL) + return; + + /* Remove full PDUs and ack the SDU bytes they cover. Start from SN == VT(A) + * and process increasing SNs until end of list or missing ACK or PDU not + * fully ACKed. + */ + while (cur != NULL && cur->sn == entity->vt_a && + tx_pdu_in_ack_list_full(cur)) { + sn = cur->sn; + entity->vt_a = (entity->vt_a + 1) % 1024; + pdu_size = tx_pdu_in_ack_list_size(cur); + ack_sdu_bytes(cur->start_sdu, cur->sdu_start_byte, pdu_size); + while (cur != NULL && cur->sn == sn) + cur = cur->next; + entity->ack_list = tx_list_remove_sn(entity->ack_list, sn); + } + + cleanup_sdu_list(entity); +} + +void rlc_entity_am_recv_pdu(rlc_entity_t *_entity, char *buffer, int size) +{ +#define R(d) do { if (rlc_pdu_decoder_in_error(&d)) goto err; } while (0) + rlc_entity_am_t *entity = (rlc_entity_am_t *)_entity; + rlc_pdu_decoder_t decoder; + rlc_pdu_decoder_t data_decoder; + rlc_pdu_decoder_t control_decoder; + + int dc; + int rf; + int p = 0; + int fi; + int e; + int sn; + int lsf; + int so; + + int cpt; + int e1; + int e2; + int ack_sn; + int nack_sn; + int so_start; + int so_end; + int control_e1; + int control_e2; + + int data_e; + int data_li; + + int packet_count; + int data_size; + int data_start; + int indicated_data_size; + + rlc_rx_pdu_segment_t *pdu_segment; + + rlc_pdu_decoder_init(&decoder, buffer, size); + dc = rlc_pdu_decoder_get_bits(&decoder, 1); R(decoder); + if (dc == 0) goto control; + + /* data PDU */ + rf = rlc_pdu_decoder_get_bits(&decoder, 1); R(decoder); + p = rlc_pdu_decoder_get_bits(&decoder, 1); R(decoder); + fi = rlc_pdu_decoder_get_bits(&decoder, 2); R(decoder); + e = rlc_pdu_decoder_get_bits(&decoder, 1); R(decoder); + sn = rlc_pdu_decoder_get_bits(&decoder, 10); R(decoder); + + /* dicard PDU if rx buffer is full */ + if (entity->rx_size + size > entity->rx_maxsize) { + LOG_D(RLC, "%s:%d:%s: warning: discard PDU, RX buffer full\n", + __FILE__, __LINE__, __FUNCTION__); + goto discard; + } + + if (!sn_in_recv_window(entity, sn)) { + LOG_D(RLC, "%s:%d:%s: warning: discard PDU, sn out of window (sn %d vr_r %d)\n", + __FILE__, __LINE__, __FUNCTION__, + sn, entity->vr_r); + goto discard; + } + + if (rf) { + lsf = rlc_pdu_decoder_get_bits(&decoder, 1); R(decoder); + so = rlc_pdu_decoder_get_bits(&decoder, 15); R(decoder); + } else { + lsf = 1; + so = 0; + } + + packet_count = 1; + + /* go to start of data */ + indicated_data_size = 0; + data_decoder = decoder; + data_e = e; + while (data_e) { + data_e = rlc_pdu_decoder_get_bits(&data_decoder, 1); R(data_decoder); + data_li = rlc_pdu_decoder_get_bits(&data_decoder, 11); R(data_decoder); + if (data_li == 0) { + LOG_D(RLC, "%s:%d:%s: warning: discard PDU, li == 0\n", + __FILE__, __LINE__, __FUNCTION__); + goto discard; + } + indicated_data_size += data_li; + packet_count++; + } + rlc_pdu_decoder_align(&data_decoder); + + data_start = data_decoder.byte; + data_size = size - data_start; + + if (data_size <= 0) { + LOG_D(RLC, "%s:%d:%s: warning: discard PDU, wrong data size (sum of LI %d data size %d)\n", + __FILE__, __LINE__, __FUNCTION__, + indicated_data_size, data_size); + goto discard; + } + if (indicated_data_size >= data_size) { + LOG_D(RLC, "%s:%d:%s: warning: discard PDU, bad LIs (sum of LI %d data size %d)\n", + __FILE__, __LINE__, __FUNCTION__, + indicated_data_size, data_size); + goto discard; + } + + /* discard segment if all the bytes of the segment are already there */ + if (segment_already_received(entity, sn, so, data_size)) { + LOG_D(RLC, "%s:%d:%s: warning: discard PDU, already received\n", + __FILE__, __LINE__, __FUNCTION__); + goto discard; + } + + char *fi_str[] = { + "first byte: YES last byte: YES", + "first byte: YES last byte: NO", + "first byte: NO last byte: YES", + "first byte: NO last byte: NO", + }; + + LOG_D(RLC, "found %d packets, data size %d data start %d [fi %d %s] (sn %d) (p %d)\n", + packet_count, data_size, data_decoder.byte, fi, fi_str[fi], sn, p); + + /* put in pdu reception list */ + entity->rx_size += size; + pdu_segment = rlc_rx_new_pdu_segment(sn, so, size, lsf, buffer, data_start); + entity->rx_list = rlc_rx_pdu_segment_list_add(sn_compare_rx, entity, + entity->rx_list, pdu_segment); + + /* do reception actions (36.322 5.1.3.2.3) */ + rlc_am_reception_actions(entity, pdu_segment); + + if (p) { + /* 36.322 5.2.3 says status triggering should be delayed + * until x < VR(MS) or x >= VR(MR). This is not clear (what + * is x then? we keep the same?). So let's trigger no matter what. + */ + int vr_mr = (entity->vr_r + 512) % 1024; + entity->status_triggered = 1; + if (!(sn_compare_rx(entity, sn, entity->vr_ms) < 0 || + sn_compare_rx(entity, sn, vr_mr) >= 0)) { + LOG_D(RLC, "%s:%d:%s: warning: STATUS trigger should be delayed, according to specs\n", + __FILE__, __LINE__, __FUNCTION__); + } + } + + return; + +control: + cpt = rlc_pdu_decoder_get_bits(&decoder, 3); R(decoder); + if (cpt != 0) { + LOG_D(RLC, "%s:%d:%s: warning: discard PDU, CPT not 0 (%d)\n", + __FILE__, __LINE__, __FUNCTION__, cpt); + goto discard; + } + ack_sn = rlc_pdu_decoder_get_bits(&decoder, 10); R(decoder); + e1 = rlc_pdu_decoder_get_bits(&decoder, 1); R(decoder); + + /* let's try to parse the control PDU once to check consistency */ + control_decoder = decoder; + control_e1 = e1; + while (control_e1) { + rlc_pdu_decoder_get_bits(&control_decoder, 10); R(control_decoder); /* NACK_SN */ + control_e1 = rlc_pdu_decoder_get_bits(&control_decoder, 1); R(control_decoder); + control_e2 = rlc_pdu_decoder_get_bits(&control_decoder, 1); R(control_decoder); + if (control_e2) { + rlc_pdu_decoder_get_bits(&control_decoder, 15); R(control_decoder); /* SOstart */ + rlc_pdu_decoder_get_bits(&control_decoder, 15); R(control_decoder); /* SOend */ + } + } + + /* 36.322 5.2.2.2 says to stop t_poll_retransmit if a ACK or NACK is + * received for the SN 'poll_sn' + */ + if (sn_compare_tx(entity, entity->poll_sn, ack_sn) < 0) + entity->t_poll_retransmit_start = 0; + + /* at this point, accept the PDU even if the actual values + * may be incorrect (eg. if so_start > so_end) + */ + process_received_ack(entity, ack_sn); + + while (e1) { + nack_sn = rlc_pdu_decoder_get_bits(&decoder, 10); R(decoder); + e1 = rlc_pdu_decoder_get_bits(&decoder, 1); R(decoder); + e2 = rlc_pdu_decoder_get_bits(&decoder, 1); R(decoder); + if (e2) { + so_start = rlc_pdu_decoder_get_bits(&decoder, 15); R(decoder); + so_end = rlc_pdu_decoder_get_bits(&decoder, 15); R(decoder); + if (so_end < so_start) { + LOG_W(RLC, "%s:%d:%s: warning, bad so start/end, NACK the whole PDU (sn %d)\n", + __FILE__, __LINE__, __FUNCTION__, nack_sn); + so_start = 0; + so_end = -1; + } + /* special value 0x7fff indicates 'all bytes to the end' */ + if (so_end == 0x7fff) + so_end = -1; + } else { + so_start = 0; + so_end = -1; + } + process_received_nack(entity, nack_sn, so_start, so_end); + + /* 36.322 5.2.2.2 says to stop t_poll_retransmit if a ACK or NACK is + * received for the SN 'poll_sn' + */ + if (entity->poll_sn == nack_sn) + entity->t_poll_retransmit_start = 0; + } + + finalize_ack_nack_processing(entity); + + return; + +err: + LOG_W(RLC, "%s:%d:%s: error decoding PDU, discarding\n", __FILE__, __LINE__, __FUNCTION__); + goto discard; + +discard: + if (p) + entity->status_triggered = 1; + +#undef R +} + +/*************************************************************************/ +/* TX functions */ +/*************************************************************************/ + +static int pdu_size(rlc_entity_am_t *entity, rlc_tx_pdu_segment_t *pdu) +{ + int header_size; + int sdu_count; + int data_size; + int li_bits; + rlc_sdu_t *sdu; + + header_size = 2; + if (pdu->is_segment) + header_size += 2; + + data_size = pdu->data_size; + + sdu = pdu->start_sdu; + + sdu_count = 1; + data_size -= sdu->size - pdu->sdu_start_byte; + sdu = sdu->next; + + while (data_size > 0) { + sdu_count++; + data_size -= sdu->size; + sdu = sdu->next; + } + + li_bits = 12 * (sdu_count - 1); + header_size += (li_bits + 7) / 8; + + return header_size + pdu->data_size; +} + +static int header_size(int sdu_count) +{ + int bits = 16 + 12 * (sdu_count - 1); + /* padding if we have to */ + return (bits + 7) / 8; +} + +typedef struct { + int sdu_count; + int data_size; + int header_size; +} tx_pdu_size_t; + +static tx_pdu_size_t compute_new_pdu_size(rlc_entity_am_t *entity, int maxsize) +{ + tx_pdu_size_t ret; + int sdu_count; + int sdu_size; + int pdu_data_size; + rlc_sdu_t *sdu; + + int vt_ms = (entity->vt_a + 512) % 1024; + + ret.sdu_count = 0; + ret.data_size = 0; + ret.header_size = 0; + + /* sn out of window? nothing to do */ + if (!(sn_compare_tx(entity, entity->vt_s, entity->vt_a) >= 0 && + sn_compare_tx(entity, entity->vt_s, vt_ms) < 0)) + return ret; + + /* TX PDU - let's make the biggest PDU we can with the SDUs we have */ + sdu_count = 0; + pdu_data_size = 0; + sdu = entity->tx_list; + while (sdu != NULL) { + /* include SDU only if it has not been fully included in PDUs already */ + if (sdu->next_byte != sdu->size) { + int new_header_size = header_size(sdu_count + 1); + /* if we cannot put new header + at least 1 byte of data then over */ + if (new_header_size + pdu_data_size + 1 > maxsize) + break; + sdu_count++; + /* only include the bytes of this SDU not included in PDUs already */ + sdu_size = sdu->size - sdu->next_byte; + /* don't feed more than 'maxsize' bytes */ + if (new_header_size + pdu_data_size + sdu_size > maxsize) + sdu_size = maxsize - new_header_size - pdu_data_size; + pdu_data_size += sdu_size; + /* if we put more than 2^11-1 bytes then the LI field cannot be used, + * so this is the last SDU we can put + */ + if (sdu_size > 2047) + break; + } + sdu = sdu->next; + } + + if (sdu_count) { + ret.sdu_count = sdu_count; + ret.data_size = pdu_data_size; + ret.header_size = header_size(sdu_count); + } + + return ret; +} + +static int status_size(rlc_entity_am_t *entity, int maxsize) +{ + /* let's count bits */ + int bits = 15; /* minimum size is 15 (header+ack_sn+e1) */ + int sn; + + maxsize *= 8; + + if (bits > maxsize) { + LOG_W(RLC, "%s:%d:%s: warning: cannot generate status PDU, not enough room\n", + __FILE__, __LINE__, __FUNCTION__); + return 0; + } + + /* each NACK adds 12 bits */ + sn = entity->vr_r; + while (bits + 12 <= maxsize && sn_compare_rx(entity, sn, entity->vr_ms) < 0) { + if (!(rlc_am_segment_full(entity, sn))) + bits += 12; + sn = (sn + 1) % 1024; + } + + return (bits + 7) / 8; +} + +static int generate_status(rlc_entity_am_t *entity, char *buffer, int size) +{ + /* let's count bits */ + int bits = 15; /* minimum size is 15 (header+ack_sn+e1) */ + int sn; + rlc_pdu_encoder_t encoder; + int has_nack = 0; + int ack; + + rlc_pdu_encoder_init(&encoder, buffer, size); + + size *= 8; + + if (bits > size) { + LOG_W(RLC, "%s:%d:%s: warning: cannot generate status PDU, not enough room\n", + __FILE__, __LINE__, __FUNCTION__); + return 0; + } + + /* header */ + rlc_pdu_encoder_put_bits(&encoder, 0, 1); /* D/C */ + rlc_pdu_encoder_put_bits(&encoder, 0, 3); /* CPT */ + + /* reserve room for ACK (it will be set after putting the NACKs) */ + rlc_pdu_encoder_put_bits(&encoder, 0, 10); + + /* at this point, ACK is VR(R) */ + ack = entity->vr_r; + + /* each NACK adds 12 bits */ + sn = entity->vr_r; + while (bits + 12 <= size && sn_compare_rx(entity, sn, entity->vr_ms) < 0) { + if (!(rlc_am_segment_full(entity, sn))) { + /* put previous e1 (is 1) */ + rlc_pdu_encoder_put_bits(&encoder, 1, 1); + /* if previous was NACK, put previous e2 (0, we don't do 'so' thing) */ + if (has_nack) + rlc_pdu_encoder_put_bits(&encoder, 0, 1); + /* put NACKed sn */ + rlc_pdu_encoder_put_bits(&encoder, sn, 10); + has_nack = 1; + bits += 12; + } else { + /* this sn is full and we put all NACKs before it, use it for ACK */ + ack = (sn + 1) % 1024; + } + sn = (sn + 1) % 1024; + } + + /* go to highest full sn+1 for ACK, VR(MS) is the limit */ + while (sn_compare_rx(entity, sn, entity->vr_ms) < 0 && + rlc_am_segment_full(entity, sn)) { + ack = (sn + 1) % 1024; + sn = (sn + 1) % 1024; + } + + /* at this point, if last put was NACK then put 2 bits else put 1 bit */ + if (has_nack) + rlc_pdu_encoder_put_bits(&encoder, 0, 2); + else + rlc_pdu_encoder_put_bits(&encoder, 0, 1); + + rlc_pdu_encoder_align(&encoder); + + /* let's put the ACK */ + buffer[0] |= ack >> 6; + buffer[1] |= (ack & 0x3f) << 2; + + /* reset the trigger */ + entity->status_triggered = 0; + + /* start t_status_prohibit */ + entity->t_status_prohibit_start = entity->t_current; + + return encoder.byte; +} + +int transmission_buffer_empty(rlc_entity_am_t *entity) +{ + rlc_sdu_t *sdu; + + /* is transmission buffer empty? */ + sdu = entity->tx_list; + while (sdu != NULL) { + if (sdu->next_byte != sdu->size) + return 0; + sdu = sdu->next; + } + return 1; +} + +int check_poll_after_pdu_assembly(rlc_entity_am_t *entity) +{ + int retransmission_buffer_empty; + int window_stalling; + int vt_ms; + + /* is retransmission buffer empty? */ + if (entity->retransmit_list == NULL) + retransmission_buffer_empty = 1; + else + retransmission_buffer_empty = 0; + + /* is window stalling? */ + vt_ms = (entity->vt_a + 512) % 1024; + if (!(sn_compare_tx(entity, entity->vt_s, entity->vt_a) >= 0 && + sn_compare_tx(entity, entity->vt_s, vt_ms) < 0)) + window_stalling = 1; + else + window_stalling = 0; + + return (transmission_buffer_empty(entity) && retransmission_buffer_empty) || + window_stalling; +} + +void include_poll(rlc_entity_am_t *entity, char *buffer) +{ + /* set the P bit to 1 */ + buffer[0] |= 0x20; + + entity->pdu_without_poll = 0; + entity->byte_without_poll = 0; + + /* set POLL_SN to VT(S) - 1 */ + entity->poll_sn = (entity->vt_s + 1023) % 1024; + + /* start t_poll_retransmit */ + entity->t_poll_retransmit_start = entity->t_current; +} + +static int serialize_pdu(rlc_entity_am_t *entity, char *buffer, int bufsize, + rlc_tx_pdu_segment_t *pdu, int p) +{ + int first_sdu_full; + int last_sdu_full; + int sdu_next_byte; + rlc_sdu_t *sdu; + int i; + int cursize; + rlc_pdu_encoder_t encoder; + int fi; + int e; + int li; + char *out; + int outpos; + int sdu_count; + int header_size; + int sdu_start_byte; + + first_sdu_full = pdu->sdu_start_byte == 0; + + /* is last SDU full? (and also compute sdu_count) */ + last_sdu_full = 1; + sdu = pdu->start_sdu; + sdu_next_byte = pdu->sdu_start_byte; + cursize = 0; + sdu_count = 0; + while (cursize != pdu->data_size) { + int sdu_size = sdu->size - sdu_next_byte; + sdu_count++; + if (cursize + sdu_size > pdu->data_size) { + last_sdu_full = 0; + break; + } + cursize += sdu_size; + sdu = sdu->next; + sdu_next_byte = 0; + } + + /* generate header */ + rlc_pdu_encoder_init(&encoder, buffer, bufsize); + + rlc_pdu_encoder_put_bits(&encoder, 1, 1); /* D/C: 1 = data */ + rlc_pdu_encoder_put_bits(&encoder, pdu->is_segment, 1); /* RF */ + rlc_pdu_encoder_put_bits(&encoder, 0, 1); /* P: reserve, set later */ + + fi = 0; + if (!first_sdu_full) + fi |= 0x02; + if (!last_sdu_full) + fi |= 0x01; + rlc_pdu_encoder_put_bits(&encoder, fi, 2); /* FI */ + + /* to understand the logic for Es and LIs: + * If we have: + * 1 SDU: E=0 + * + * 2 SDUs: E=1 + * then: E=0 LI(sdu[0]) + * + * 3 SDUs: E=1 + * then: E=1 LI(sdu[0]) + * then: E=0 LI(sdu[1]) + * + * 4 SDUs: E=1 + * then: E=1 LI(sdu[0]) + * then: E=1 LI(sdu[1]) + * then: E=0 LI(sdu[2]) + */ + if (sdu_count >= 2) + e = 1; + else + e = 0; + rlc_pdu_encoder_put_bits(&encoder, e, 1); /* E */ + + rlc_pdu_encoder_put_bits(&encoder, pdu->sn, 10); /* SN */ + + if (pdu->is_segment) { + rlc_pdu_encoder_put_bits(&encoder, pdu->is_last, 1); /* LSF */ + rlc_pdu_encoder_put_bits(&encoder, pdu->so, 15); /* SO */ + } + + /* put LIs */ + sdu = pdu->start_sdu; + /* first SDU */ + li = sdu->size - pdu->sdu_start_byte; + /* put E+LI only if at least 2 SDUs */ + if (sdu_count >= 2) { + /* E is 1 if at least 3 SDUs */ + if (sdu_count >= 3) + e = 1; + else + e = 0; + rlc_pdu_encoder_put_bits(&encoder, e, 1); /* E */ + rlc_pdu_encoder_put_bits(&encoder, li, 11); /* LI */ + } + /* next SDUs, but not the last (no LI for the last) */ + sdu = sdu->next; + for (i = 2; i < sdu_count; i++, sdu = sdu->next) { + if (i != sdu_count - 1) + e = 1; + else + e = 0; + li = sdu->size; + rlc_pdu_encoder_put_bits(&encoder, e, 1); /* E */ + rlc_pdu_encoder_put_bits(&encoder, li, 11); /* LI */ + } + + rlc_pdu_encoder_align(&encoder); + + header_size = encoder.byte; + + /* generate data */ + out = buffer + header_size; + sdu = pdu->start_sdu; + sdu_start_byte = pdu->sdu_start_byte; + outpos = 0; + for (i = 0; i < sdu_count; i++, sdu = sdu->next) { + li = sdu->size - sdu_start_byte; + if (outpos + li >= pdu->data_size) + li = pdu->data_size - outpos; + memcpy(out+outpos, sdu->data + sdu_start_byte, li); + outpos += li; + sdu_start_byte = 0; + } + + if (p) + include_poll(entity, buffer); + + return header_size + pdu->data_size; +} + +static int generate_tx_pdu(rlc_entity_am_t *entity, char *buffer, int bufsize) +{ + int vt_ms; + tx_pdu_size_t pdu_size; + rlc_sdu_t *sdu; + int i; + int cursize; + int p; + rlc_tx_pdu_segment_t *pdu; + + /* sn out of window? do nothing */ + vt_ms = (entity->vt_a + 512) % 1024; + if (!(sn_compare_tx(entity, entity->vt_s, entity->vt_a) >= 0 && + sn_compare_tx(entity, entity->vt_s, vt_ms) < 0)) + return 0; + + pdu_size = compute_new_pdu_size(entity, bufsize); + if (pdu_size.sdu_count == 0) + return 0; + + pdu = rlc_tx_new_pdu(); + + pdu->sn = entity->vt_s; + entity->vt_s = (entity->vt_s + 1) % 1024; + + /* go to first SDU (skip those already fully processed) */ + sdu = entity->tx_list; + while (sdu->next_byte == sdu->size) + sdu = sdu->next; + + pdu->start_sdu = sdu; + + pdu->sdu_start_byte = sdu->next_byte; + + pdu->so = 0; + pdu->is_segment = 0; + pdu->is_last = 1; + /* to conform to specs' logic, put -1 (specs say "for 1st retransmission + * put 0 otherwise increase", let's put -1 and always increase when the + * segment goes to retransmit list) + */ + pdu->retx_count = -1; + + /* reserve SDU bytes */ + cursize = 0; + for (i = 0; i < pdu_size.sdu_count; i++, sdu = sdu->next) { + int sdu_size = sdu->size - sdu->next_byte; + if (cursize + sdu_size > pdu_size.data_size) + sdu_size = pdu_size.data_size - cursize; + sdu->next_byte += sdu_size; + cursize += sdu_size; + } + + pdu->data_size = cursize; + + /* put PDU at the end of the wait list */ + entity->wait_list = rlc_tx_pdu_list_append(entity->wait_list, pdu); + + /* polling actions for a new PDU */ + entity->pdu_without_poll++; + entity->byte_without_poll += pdu_size.data_size; + if ((entity->poll_pdu != -1 && + entity->pdu_without_poll >= entity->poll_pdu) || + (entity->poll_byte != -1 && + entity->byte_without_poll >= entity->poll_byte)) + p = 1; + else + p = check_poll_after_pdu_assembly(entity); + + if (entity->force_poll) { + p = 1; + entity->force_poll = 0; + } + + return serialize_pdu(entity, buffer, bufsize, pdu, p); +} + +static void resegment(rlc_tx_pdu_segment_t *pdu, int size) +{ + rlc_tx_pdu_segment_t *new_pdu; + rlc_sdu_t *sdu; + int sdu_count; + int pdu_header_size; + int pdu_data_size; + int sdu_pos; + int sdu_bytes_to_take; + + /* PDU segment too big, cut in two parts so that first part fits into + * size bytes (including header) + */ + sdu = pdu->start_sdu; + pdu_data_size = 0; + sdu_pos = pdu->sdu_start_byte; + sdu_count = 0; + while (1) { + /* can we put a new header and at least one byte of data? */ + /* header has 2 more bytes for SO */ + pdu_header_size = 2 + header_size(sdu_count + 1); + if (pdu_header_size + pdu_data_size + 1 > size) { + /* no we can't, stop here */ + break; + } + /* yes we can, go ahead */ + sdu_count++; + sdu_bytes_to_take = sdu->size - sdu_pos; + if (pdu_header_size + pdu_data_size + sdu_bytes_to_take > size) { + sdu_bytes_to_take = size - (pdu_header_size + pdu_data_size); + } + sdu_pos += sdu_bytes_to_take; + if (sdu_pos == sdu->size) { + sdu = sdu->next; + sdu_pos = 0; + } + pdu_data_size += sdu_bytes_to_take; + } + + new_pdu = rlc_tx_new_pdu(); + pdu->is_segment = 1; + *new_pdu = *pdu; + + new_pdu->so = pdu->so + pdu_data_size; + new_pdu->data_size = pdu->data_size - pdu_data_size; + new_pdu->start_sdu = sdu; + new_pdu->sdu_start_byte = sdu_pos; + + pdu->is_last = 0; + pdu->data_size = pdu_data_size; + pdu->next = new_pdu; +} + +static int generate_retx_pdu(rlc_entity_am_t *entity, char *buffer, int size) +{ + rlc_tx_pdu_segment_t *pdu; + int orig_size; + int p; + + pdu = entity->retransmit_list; + orig_size = pdu_size(entity, pdu); + + if (orig_size > size) { + /* we can't resegment if size is less than 5 + * (4 bytes for header, 1 byte for data) + */ + if (size < 5) + return 0; + resegment(pdu, size); + } + + /* remove from retransmit list and put in wait list */ + entity->retransmit_list = pdu->next; + entity->wait_list = rlc_tx_pdu_list_add(sn_compare_tx, entity, + entity->wait_list, pdu); + + p = check_poll_after_pdu_assembly(entity); + + if (entity->force_poll) { + p = 1; + entity->force_poll = 0; + } + + return serialize_pdu(entity, buffer, orig_size, pdu, p); +} + +static int status_to_report(rlc_entity_am_t *entity) +{ + return entity->status_triggered && + (entity->t_status_prohibit_start == 0 || + entity->t_current - entity->t_status_prohibit_start > + entity->t_status_prohibit); +} + +static int retx_pdu_size(rlc_entity_am_t *entity, int maxsize) +{ + int size; + + if (entity->retransmit_list == NULL) + return 0; + + size = pdu_size(entity, entity->retransmit_list); + if (size <= maxsize) + return size; + + /* we can segment head of retransmist list if maxsize is large enough + * to hold a PDU segment with at least 1 data byte (so 5 bytes: 4 bytes + * header + 1 byte data) + */ + if (maxsize < 5) + return 0; + + /* a later segmentation of the head of retransmit list will generate a pdu + * of maximum size 'maxsize' (can be less) + */ + return maxsize; +} + +rlc_entity_buffer_status_t rlc_entity_am_buffer_status( + rlc_entity_t *_entity, int maxsize) +{ + rlc_entity_am_t *entity = (rlc_entity_am_t *)_entity; + rlc_entity_buffer_status_t ret; + tx_pdu_size_t tx_size; + + /* status PDU, if we have to */ + if (status_to_report(entity)) + ret.status_size = status_size(entity, maxsize); + else + ret.status_size = 0; + + /* TX PDU */ + tx_size = compute_new_pdu_size(entity, maxsize); + ret.tx_size = tx_size.data_size + tx_size.header_size; + + /* reTX PDU */ + ret.retx_size = retx_pdu_size(entity, maxsize); + + return ret; +} + +int rlc_entity_am_generate_pdu(rlc_entity_t *_entity, char *buffer, int size) +{ + rlc_entity_am_t *entity = (rlc_entity_am_t *)_entity; + int ret; + + if (status_to_report(entity)) { + ret = generate_status(entity, buffer, size); + if (ret != 0) + return ret; + } + + if (entity->retransmit_list != NULL) { + ret = generate_retx_pdu(entity, buffer, size); + if (ret != 0) + return ret; + } + + return generate_tx_pdu(entity, buffer, size); +} + +/*************************************************************************/ +/* SDU RX functions */ +/*************************************************************************/ + +void rlc_entity_am_recv_sdu(rlc_entity_t *_entity, char *buffer, int size, + int sdu_id) +{ + rlc_entity_am_t *entity = (rlc_entity_am_t *)_entity; + rlc_sdu_t *sdu; + + if (size > SDU_MAX) { + LOG_E(RLC, "%s:%d:%s: fatal: SDU size too big (%d bytes)\n", + __FILE__, __LINE__, __FUNCTION__, size); + exit(1); + } + + if (entity->tx_size + size > entity->tx_maxsize) { + LOG_D(RLC, "%s:%d:%s: warning: SDU rejected, SDU buffer full\n", + __FILE__, __LINE__, __FUNCTION__); + return; + } + + entity->tx_size += size; + + sdu = rlc_new_sdu(buffer, size, sdu_id); + rlc_sdu_list_add(&entity->tx_list, &entity->tx_end, sdu); +} + +/*************************************************************************/ +/* time/timers */ +/*************************************************************************/ + +static void check_t_poll_retransmit(rlc_entity_am_t *entity) +{ + rlc_tx_pdu_segment_t head; + rlc_tx_pdu_segment_t *cur; + rlc_tx_pdu_segment_t *prev; + int sn; + + /* 36.322 5.2.2.3 */ + /* did t_poll_retransmit expire? */ + if (entity->t_poll_retransmit_start == 0 || + entity->t_current <= entity->t_poll_retransmit_start + + entity->t_poll_retransmit) + return; + + /* stop timer */ + entity->t_poll_retransmit_start = 0; + + /* 36.322 5.2.2.3 says: + * + * - include a poll in a RLC data PDU as described in section 5.2.2.1 + * + * That does not seem to be conditional. So we forcefully will send + * a poll as soon as we generate a PDU. + * Hopefully this interpretation is correct. In the worst case we generate + * more polling than necessary, but it's not a big deal. When + * 't_poll_retransmit' expires it means we didn't receive a status report, + * meaning a bad radio link, so things are quite bad at this point and + * asking again for a poll won't hurt much more. + */ + entity->force_poll = 1; + + LOG_D(RLC, "%s:%d:%s: warning: t_poll_retransmit expired\n", + __FILE__, __LINE__, __FUNCTION__); + + /* do we meet conditions of 36.322 5.2.2.3? */ + if (!check_poll_after_pdu_assembly(entity)) + return; + + /* search wait list for PDU with SN = VT(S)-1 */ + sn = (entity->vt_s + 1023) % 1024; + + head.next = entity->wait_list; + cur = entity->wait_list; + prev = &head; + + while (cur != NULL) { + if (cur->sn == sn) + break; + prev = cur; + cur = cur->next; + } + + /* PDU with SN = VT(S)-1 not found?, take the head of wait list */ + if (cur == NULL) { + cur = entity->wait_list; + prev = &head; + sn = cur->sn; + } + + /* 36.322 says "PDU", not "PDU segment", so let's retransmit all + * PDU segments with this SN + */ + while (cur != NULL && cur->sn == sn) { + prev->next = cur->next; + entity->wait_list = head.next; + /* put in retransmit list */ + consider_retransmission(entity, cur); + cur = prev->next; + } +} + +static void check_t_reordering(rlc_entity_am_t *entity) +{ + int sn; + + /* is t_reordering running and if yes has it expired? */ + if (entity->t_reordering_start == 0 || + entity->t_current <= entity->t_reordering_start + entity->t_reordering) + return; + + /* stop timer */ + entity->t_reordering_start = 0; + + LOG_D(RLC, "%s:%d:%s: t_reordering expired\n", __FILE__, __LINE__, __FUNCTION__); + + /* update VR(MS) to first SN >= VR(X) for which not all PDU segments + * have been received + */ + sn = entity->vr_x; + while (rlc_am_segment_full(entity, sn)) + sn = (sn + 1) % 1024; + entity->vr_ms = sn; + + if (sn_compare_rx(entity, entity->vr_h, entity->vr_ms) > 0) { + entity->t_reordering_start = entity->t_current; + entity->vr_x = entity->vr_h; + } + + /* trigger STATUS report */ + entity->status_triggered = 1; +} + +void rlc_entity_am_set_time(rlc_entity_t *_entity, uint64_t now) +{ + rlc_entity_am_t *entity = (rlc_entity_am_t *)_entity; + + entity->t_current = now; + + check_t_poll_retransmit(entity); + + check_t_reordering(entity); + + /* t_status_prohibit is handled by generate_status */ +} + +/*************************************************************************/ +/* discard/re-establishment/delete */ +/*************************************************************************/ + +void rlc_entity_am_discard_sdu(rlc_entity_t *_entity, int sdu_id) +{ + /* implements 36.322 5.3 */ + rlc_entity_am_t *entity = (rlc_entity_am_t *)_entity; + rlc_sdu_t head; + rlc_sdu_t *cur; + rlc_sdu_t *prev; + + head.next = entity->tx_list; + cur = entity->tx_list; + prev = &head; + + while (cur != NULL && cur->upper_layer_id != sdu_id) { + prev = cur; + cur = cur->next; + } + + /* if sdu_id not found or some bytes have already been 'PDU-ized' + * then do nothing + */ + if (cur == NULL || cur->next_byte != 0) + return; + + /* remove SDU from tx_list */ + prev->next = cur->next; + entity->tx_list = head.next; + if (entity->tx_end == cur) { + if (prev != &head) + entity->tx_end = prev; + else + entity->tx_end = NULL; + } + + rlc_free_sdu(cur); +} + +static void free_pdu_segment_list(rlc_tx_pdu_segment_t *l) +{ + rlc_tx_pdu_segment_t *cur; + + while (l != NULL) { + cur = l; + l = l->next; + rlc_tx_free_pdu(cur); + } +} + +static void clear_entity(rlc_entity_am_t *entity) +{ + rlc_rx_pdu_segment_t *cur_rx; + rlc_sdu_t *cur_tx; + + entity->vr_r = 0; + entity->vr_x = 0; + entity->vr_ms = 0; + entity->vr_h = 0; + + entity->status_triggered = 0; + + entity->vt_a = 0; + entity->vt_s = 0; + entity->poll_sn = 0; + entity->pdu_without_poll = 0; + entity->byte_without_poll = 0; + entity->force_poll = 0; + + entity->t_current = 0; + + entity->t_reordering_start = 0; + entity->t_status_prohibit_start = 0; + entity->t_poll_retransmit_start = 0; + + cur_rx = entity->rx_list; + while (cur_rx != NULL) { + rlc_rx_pdu_segment_t *p = cur_rx; + cur_rx = cur_rx->next; + rlc_rx_free_pdu_segment(p); + } + entity->rx_list = NULL; + entity->rx_size = 0; + + memset(&entity->reassemble, 0, sizeof(rlc_am_reassemble_t)); + + cur_tx = entity->tx_list; + while (cur_tx != NULL) { + rlc_sdu_t *p = cur_tx; + cur_tx = cur_tx->next; + rlc_free_sdu(p); + } + entity->tx_list = NULL; + entity->tx_end = NULL; + entity->tx_size = 0; + + free_pdu_segment_list(entity->wait_list); + free_pdu_segment_list(entity->retransmit_list); + free_pdu_segment_list(entity->ack_list); + entity->wait_list = NULL; + entity->retransmit_list = NULL; + entity->ack_list = NULL; +} + +void rlc_entity_am_reestablishment(rlc_entity_t *_entity) +{ + rlc_entity_am_t *entity = (rlc_entity_am_t *)_entity; + + /* 36.322 5.4 says to deliver SDUs if possible. + * Let's not do that, it makes the code simpler. + * TODO: change this behavior if wanted/needed. + */ + + clear_entity(entity); +} + +void rlc_entity_am_delete(rlc_entity_t *_entity) +{ + rlc_entity_am_t *entity = (rlc_entity_am_t *)_entity; + clear_entity(entity); + free(entity); +} diff --git a/openair2/LAYER2/rlc_v2/rlc_entity_am.h b/openair2/LAYER2/rlc_v2/rlc_entity_am.h new file mode 100644 index 0000000000..0437f17ad8 --- /dev/null +++ b/openair2/LAYER2/rlc_v2/rlc_entity_am.h @@ -0,0 +1,285 @@ +/* + * 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 _RLC_ENTITY_AM_H_ +#define _RLC_ENTITY_AM_H_ + +#include + +#include "rlc_entity.h" +#include "rlc_pdu.h" +#include "rlc_sdu.h" + +/* + * Here comes some documentation to understand the reassembly + * logic in the code and the fields in the structure rlc_am_reassemble_t. + * + * Inside RLC, we deal with SDUs, PDUs and PDU segments. + * SDUs are packets coming from upper layer. + * A PDU is made of a header and a payload. + * In the payload there are SDUs. + * First SDU and last SDU in a PDU may be incomplete. + * PDU segments exist in case of retransmissions when the MAC + * layer asks for less data than previously, in which case + * only part of the previous PDU is sent. + * + * This is PDU data (just bytes): + * --------------------------------------------------------- + * | PDU data | + * --------------------------------------------------------- + * It contains SDUs, like: + * --------------------------------------------------------- + * | SDU 1 | SDU 2 | [...] | SDU n | + * --------------------------------------------------------- + * SDU 1 may be only the end of an SDU from which previous bytes were + * transmitted in previous PDUs. + * SDU n may be only the start of an SDU, that is more bytes from + * this SDU may be sent in successive PDUs. + * + * At front of the PDU data, we have a header: + * --------------- --------------------------------------------------------- + * | PDU header | | SDU 1 | SDU 2 | [...] | SDU n | + * --------------- --------------------------------------------------------- + * PDU header describes PDU data (most notably lengths). + * + * A PDU segment is a part of a PDU. For example, from this PDU data: + * --------------------------------------------------------- + * | SDU 1 | SDU 2 | [...] | SDU n | + * --------------------------------------------------------- + * We can extract the following PDU segment (data part only): + * ---------------------- + * | PDU segment data | + * ---------------------- + * This PDU segment would contain the end of SDU 2 above and some SDUs up to, + * let's say SDU x (x is 5 below). + * + * In front of a transmitted PDU segment, we have a header, + * containing the important variable 'so' (segment offset) that gives + * the index of the first byte of the segment in the original PDU. + * -------------- ---------------------- + * | seg. header| | PDU segment data | + * -------------- ---------------------- + * + * Let's now explain the data structure rlc_am_reassemble_t. + * + * In the structure rlc_am_reassemble_t, the fields fi, e, sn and so + * are coming from the PDU segment header and the semantics is the + * one of the RLC specs. + * + * The currently processed PDU segment is stored in 'start'. + * We have 'start->s->data_offset' and 'start->s->size'. + * start->s->data_offset is the index of the start of the data in the + * PDU segment. That is if the header is of length 3 bytes + * then start->s->data_offset is 3. + * start->s->size is the total length of the PDU segment, + * including header. + * The size of actual data bytes in the PDU segment is thus + * start->s->size - start->s->data_offset. + * + * The field sdu_len is the length of the current SDU being + * processed. + * + * The field sdu_offset is the starting point of the + * current SDU being processed (starting from beginning + * of PDU segment, including header). + * + * The field data_pos is the current read pointer. 0 points to + * the beginning of the PDU segment (including header). + * + * The field pdu_byte points to the current byte in the original + * PDU (not the PDU segment). It starts at 0 when we start + * processing a new PDU (when a new 'sn' is seen) and always + * increases after each byte processed. This is tha variable + * that is used to know if the next PDU segment will be used + * or not and if yes, starting from which data byte (see + * function rlc_am_reassemble_next_segment). + * + * 'so' is important and points to the byte in the original PDU + * that is the first byte of the PDU segment. + * + * For example, let's take this PDU segment data from above: + * ---------------------- + * | PDU segment data | + * ---------------------- + * Let's say it is decomposed as: + * ---------------------- + * |222|33|4444|55555555| + * ---------------------- + * It contains SDUs 2, 3, 4, and 5. + * SDU 2 is 3 bytes, SDU 3 is 2 bytes, SDU 4 is 4 bytes, SDU 5 is 8 bytes. + * + * Let's suppose that the original PDU starts with: + * ---------------- + * |1111111|222222| + * ---------------- + * + * (In this example, in the PDU segment, SDU 2 is not full, + * we only have its end.) + * + * Then 'so' is 13 (SDU 1 is 7 bytes, head of SDU 2 is 6 bytes). + * + * Let's continue with our PDU segment data. + * Let's say we are current processing SDU 4. + * Let's say the read pointer (variable 'data_pos') is there: + * ---------------------- + * |222|33|4444|55555555| + * ---------------------- + * ^ + * read pointer (data_pos) + * + * Then: + * - sdu_len is 4 + * - sdu_offset is 5 + [PDU segment header length] + * (it points to the beginning of SDU 4, starting + * from the head of the PDU segment, that is + * 3 bytes for SDU 2, 2 bytes for SDU 3, and the + * PDU segment header length) + * - start->s->data_offset is [PDU segment header length] + * - pdu_byte is 20 + * (13 bytes from beginning of original PDU, + * 3 bytes for SDU 2, 2 bytes for SDU 3, then 2 bytes for SDU 4) + * - data_pos = read pointer = 7 + [PDU segment header length] + * + * To finish this description, in the code, a PDU is simply + * seen as a PDU segment with 'so' = 0 (and is_last == 1 (lsf in the specs), + * but this variable is not used by the reassembly logic). + * + * And for [PDU segment header length] we use start->s->data_offset. + * + * To recap, here is an illustration of the various variables + * and what starting point they use. In the figures, the start + * of the variable name is aligned to the byte it refers to. + * + is used to show the starting point. + * + * Let's put the PDU segment back into the original PDU. + * And let's show the values for when the read pointer + * is on the second byte of SDU 4 (as above). + * + * +++++++++++++++ so + * +++++++++++++++++++++++ pdu_byte + * --------------------------------------------------------- + * | SDU 1| SDU 2..222|33|4444|55555555| [...] | SDU n | + * --------------------------------------------------------- + * + * And now the PDU segment with header. + * + * + * ++++ sdu_len + * ++++++++++++++++++++++ sdu_offset + * +++++++++++++++++++++++ data_pos + * +++++++++++++++ start->s->data_offset + * +++++++++++++++++++++++++++++++++++++ start->s->size + * -------------- ---------------------- + * | seg. header| |222|33|4444|55555555| + * -------------- ---------------------- + * + * We see three case for the starting point: + * - start of original PDU (without any header) + * - start of header of current PDU segment + * - start of current SDU (for sdu_len) + */ + +typedef struct { + rlc_rx_pdu_segment_t *start; /* start of list */ + rlc_rx_pdu_segment_t *end; /* end of list (last element) */ + int pos; /* byte to get from current buffer */ + char sdu[SDU_MAX]; /* sdu is reassembled here */ + int sdu_pos; /* next byte to put in sdu */ + + /* decoder of current PDU */ + rlc_pdu_decoder_t dec; + int fi; + int e; + int sn; + int so; + int sdu_len; + int sdu_offset; + int data_pos; + int pdu_byte; +} rlc_am_reassemble_t; + +typedef struct { + rlc_entity_t common; + + /* configuration */ + int t_reordering; + int t_status_prohibit; + int t_poll_retransmit; + int poll_pdu; /* -1 means infinity */ + int poll_byte; /* -1 means infinity */ + int max_retx_threshold; + + /* runtime rx */ + int vr_r; + int vr_x; + int vr_ms; + int vr_h; + + int status_triggered; + + /* runtime tx */ + int vt_a; + int vt_s; + int poll_sn; + int pdu_without_poll; + int byte_without_poll; + int force_poll; + + /* set to the latest know time by the user of the module. Unit: ms */ + uint64_t t_current; + + /* timers (stores the TTI of activation, 0 means not active) */ + uint64_t t_reordering_start; + uint64_t t_status_prohibit_start; + uint64_t t_poll_retransmit_start; + + /* rx management */ + rlc_rx_pdu_segment_t *rx_list; + int rx_size; + int rx_maxsize; + + /* reassembly management */ + rlc_am_reassemble_t reassemble; + + /* tx management */ + rlc_sdu_t *tx_list; + rlc_sdu_t *tx_end; + int tx_size; + int tx_maxsize; + + rlc_tx_pdu_segment_t *wait_list; + rlc_tx_pdu_segment_t *retransmit_list; + + rlc_tx_pdu_segment_t *ack_list; +} rlc_entity_am_t; + +void rlc_entity_am_recv_sdu(rlc_entity_t *entity, char *buffer, int size, + int sdu_id); +void rlc_entity_am_recv_pdu(rlc_entity_t *entity, char *buffer, int size); +rlc_entity_buffer_status_t rlc_entity_am_buffer_status( + rlc_entity_t *entity, int maxsize); +int rlc_entity_am_generate_pdu(rlc_entity_t *entity, char *buffer, int size); +void rlc_entity_am_set_time(rlc_entity_t *entity, uint64_t now); +void rlc_entity_am_discard_sdu(rlc_entity_t *entity, int sdu_id); +void rlc_entity_am_reestablishment(rlc_entity_t *entity); +void rlc_entity_am_delete(rlc_entity_t *entity); + +#endif /* _RLC_ENTITY_AM_H_ */ diff --git a/openair2/LAYER2/rlc_v2/rlc_entity_um.c b/openair2/LAYER2/rlc_v2/rlc_entity_um.c new file mode 100644 index 0000000000..75692851cd --- /dev/null +++ b/openair2/LAYER2/rlc_v2/rlc_entity_um.c @@ -0,0 +1,703 @@ +/* + * 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 "rlc_entity_um.h" +#include "rlc_pdu.h" + +#include +#include + +#include "LOG/log.h" + +/*************************************************************************/ +/* PDU RX functions */ +/*************************************************************************/ + +static int modulus_rx(rlc_entity_um_t *entity, int a) +{ + /* as per 36.322 7.1, modulus base is vr(uh)-window_size and modulus is + * 2^sn_field_length (which is 'sn_modulus' in rlc_entity_um_t) + */ + int r = a - (entity->vr_uh - entity->window_size); + if (r < 0) r += entity->sn_modulus; + return r % entity->sn_modulus; +} + +static int sn_compare_rx(void *_entity, int a, int b) +{ + rlc_entity_um_t *entity = _entity; + return modulus_rx(entity, a) - modulus_rx(entity, b); +} + +static int sn_in_recv_window(void *_entity, int sn) +{ + rlc_entity_um_t *entity = _entity; + int mod_sn = modulus_rx(entity, sn); + /* we simplify (VR(UH) - UM_Window_Size) <= SN < VR(UH), base is + * (VR(UH) - UM_Window_Size) and VR(UH) = base + window_size + */ + return mod_sn < entity->window_size; +} + +/* return 1 if a PDU with SN == 'sn' is in the rx list, 0 otherwise */ +static int rlc_um_pdu_received(rlc_entity_um_t *entity, int sn) +{ + rlc_rx_pdu_segment_t *cur = entity->rx_list; + while (cur != NULL) { + if (cur->sn == sn) + return 1; + cur = cur->next; + } + return 0; +} + +static int less_than_vr_ur(rlc_entity_um_t *entity, int sn) +{ + return sn_compare_rx(entity, sn, entity->vr_ur) < 0; +} + +static int outside_of_reordering_window(rlc_entity_um_t *entity, int sn) +{ + return !sn_in_recv_window(entity, sn); +} + +static int less_than_vr_uh(rlc_entity_um_t *entity, int sn) +{ + return sn_compare_rx(entity, sn, entity->vr_uh) < 0; +} + +static void rlc_um_reassemble_pdu(rlc_entity_um_t *entity, + rlc_rx_pdu_segment_t *pdu) +{ + rlc_um_reassemble_t *r = &entity->reassemble; + + int fi; + int e; + int sn; + int data_pos; + int sdu_len; + int sdu_offset; + + sdu_offset = pdu->data_offset; + + rlc_pdu_decoder_init(&r->dec, pdu->data, pdu->size); + + if (entity->sn_field_length == 10) + rlc_pdu_decoder_get_bits(&r->dec, 3); + + fi = rlc_pdu_decoder_get_bits(&r->dec, 2); + e = rlc_pdu_decoder_get_bits(&r->dec, 1); + sn = rlc_pdu_decoder_get_bits(&r->dec, entity->sn_field_length); + + if (e) { + e = rlc_pdu_decoder_get_bits(&r->dec, 1); + sdu_len = rlc_pdu_decoder_get_bits(&r->dec, 11); + } else + sdu_len = pdu->size - sdu_offset; + + /* discard current SDU being reassembled if bad SN or bad FI */ + if (sn != (r->sn + 1) % entity->sn_modulus || + !(fi & 0x02)) { + if (r->sdu_pos) + LOG_D(RLC, "%s:%d:%s: warning: discard partially reassembled SDU\n", + __FILE__, __LINE__, __FUNCTION__); + r->sdu_pos = 0; + } + + /* if the head of the SDU is missing, still process the PDU + * but remember to discard the reassembled SDU later on (the + * head has not been received). + * The head is missing if sdu_pos == 0 and fi says the PDU does not + * start an SDU. + */ + if (r->sdu_pos == 0 && (fi & 0x02)) + r->sdu_head_missing = 1; + + r->sn = sn; + data_pos = pdu->data_offset; + + while (1) { + if (r->sdu_pos >= SDU_MAX) { + /* TODO: proper error handling (discard PDUs with current sn from + * reassembly queue? something else?) + */ + LOG_E(RLC, "%s:%d:%s: bad RLC PDU\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + r->sdu[r->sdu_pos] = pdu->data[data_pos]; + r->sdu_pos++; + data_pos++; + if (data_pos == sdu_offset + sdu_len) { + /* all bytes of SDU are consumed, check if SDU is fully there. + * It is if the data pointer is not at the end of the PDU segment + * or if 'fi' & 1 == 0 + */ + if (data_pos != pdu->size || (fi & 1) == 0) { + /* time to discard the SDU if we didn't receive the head */ + if (r->sdu_head_missing) { + LOG_D(RLC, "%s:%d:%s: warning: discard SDU, head not received\n", + __FILE__, __LINE__, __FUNCTION__); + r->sdu_head_missing = 0; + } else { + /* SDU is full - deliver to higher layer */ + entity->common.deliver_sdu(entity->common.deliver_sdu_data, + (rlc_entity_t *)entity, + r->sdu, r->sdu_pos); + } + r->sdu_pos = 0; + } + /* done with PDU? */ + if (data_pos == pdu->size) + break; + /* not at the end of PDU, process next SDU */ + sdu_offset += sdu_len; + if (e) { + e = rlc_pdu_decoder_get_bits(&r->dec, 1); + sdu_len = rlc_pdu_decoder_get_bits(&r->dec, 11); + } else + sdu_len = pdu->size - sdu_offset; + } + } +} + +static void rlc_um_reassemble(rlc_entity_um_t *entity, + int (*check_sn)(rlc_entity_um_t *entity, int sn)) +{ + rlc_rx_pdu_segment_t *cur; + + /* process all PDUs from head of rx list until all is processed or + * the SN is not valid anymore with respect to 'check_sn' + */ + while (entity->rx_list != NULL && check_sn(entity, entity->rx_list->sn)) { + cur = entity->rx_list; + rlc_um_reassemble_pdu(entity, cur); + entity->rx_size -= cur->size; + entity->rx_list = cur->next; + rlc_rx_free_pdu_segment(cur); + } +} + +static void rlc_um_reception_actions(rlc_entity_um_t *entity, + rlc_rx_pdu_segment_t *pdu_segment) +{ + if (!sn_in_recv_window(entity, pdu_segment->sn)) { + entity->vr_uh = (pdu_segment->sn + 1) % entity->sn_modulus; + rlc_um_reassemble(entity, outside_of_reordering_window); + if (!sn_in_recv_window(entity, entity->vr_ur)) + entity->vr_ur = (entity->vr_uh - entity->window_size + + entity->sn_modulus) % entity->sn_modulus; + } + + if (rlc_um_pdu_received(entity, entity->vr_ur)) { + do { + entity->vr_ur = (entity->vr_ur + 1) % entity->sn_modulus; + } while (rlc_um_pdu_received(entity, entity->vr_ur)); + rlc_um_reassemble(entity, less_than_vr_ur); + } + + if (entity->t_reordering_start) { + if (sn_compare_rx(entity, entity->vr_ux, entity->vr_ur) <= 0 || + (!sn_in_recv_window(entity, entity->vr_ux) && + entity->vr_ux != entity->vr_uh)) + entity->t_reordering_start = 0; + } + + if (entity->t_reordering_start == 0) { + if (sn_compare_rx(entity, entity->vr_uh, entity->vr_ur) > 0) { + entity->t_reordering_start = entity->t_current; + entity->vr_ux = entity->vr_uh; + } + } +} + +void rlc_entity_um_recv_pdu(rlc_entity_t *_entity, char *buffer, int size) +{ +#define R(d) do { if (rlc_pdu_decoder_in_error(&d)) goto err; } while (0) + rlc_entity_um_t *entity = (rlc_entity_um_t *)_entity; + rlc_pdu_decoder_t decoder; + rlc_pdu_decoder_t data_decoder; + + int e; + int sn; + + int data_e; + int data_li; + + int packet_count; + int data_size; + int data_start; + int indicated_data_size; + + rlc_rx_pdu_segment_t *pdu_segment; + + rlc_pdu_decoder_init(&decoder, buffer, size); + + if (entity->sn_field_length == 10) { + rlc_pdu_decoder_get_bits(&decoder, 3); R(decoder); /* R1 */ + } + + rlc_pdu_decoder_get_bits(&decoder, 2); R(decoder); /* FI */ + e = rlc_pdu_decoder_get_bits(&decoder, 1); R(decoder); + sn = rlc_pdu_decoder_get_bits(&decoder, entity->sn_field_length); R(decoder); + + /* dicard PDU if rx buffer is full */ + if (entity->rx_size + size > entity->rx_maxsize) { + LOG_D(RLC, "%s:%d:%s: warning: discard PDU, RX buffer full\n", + __FILE__, __LINE__, __FUNCTION__); + return; + } + + /* discard according to 36.322 5.1.2.2.2 */ + if ((sn_compare_rx(entity, entity->vr_ur, sn) < 0 && + sn_compare_rx(entity, sn, entity->vr_uh) < 0 && + rlc_um_pdu_received(entity, sn)) || + (sn_compare_rx(entity, entity->vr_uh - entity->window_size, sn) <= 0 && + sn_compare_rx(entity, sn, entity->vr_ur) < 0)) { + LOG_D(RLC, "%s:%d:%s: warning: discard PDU (sn %d vr(ur) %d vr(uh) %d)\n", + __FILE__, __LINE__, __FUNCTION__, + sn, entity->vr_ur, entity->vr_uh); + return; + } + + packet_count = 1; + + /* go to start of data */ + indicated_data_size = 0; + data_decoder = decoder; + data_e = e; + while (data_e) { + data_e = rlc_pdu_decoder_get_bits(&data_decoder, 1); R(data_decoder); + data_li = rlc_pdu_decoder_get_bits(&data_decoder, 11); R(data_decoder); + if (data_li == 0) { + LOG_D(RLC, "%s:%d:%s: warning: discard PDU, li == 0\n", + __FILE__, __LINE__, __FUNCTION__); + return; + } + indicated_data_size += data_li; + packet_count++; + } + rlc_pdu_decoder_align(&data_decoder); + + data_start = data_decoder.byte; + data_size = size - data_start; + + if (data_size <= 0) { + LOG_D(RLC, "%s:%d:%s: warning: discard PDU, wrong data size (sum of LI %d data size %d)\n", + __FILE__, __LINE__, __FUNCTION__, + indicated_data_size, data_size); + return; + } + if (indicated_data_size >= data_size) { + LOG_D(RLC, "%s:%d:%s: warning: discard PDU, bad LIs (sum of LI %d data size %d)\n", + __FILE__, __LINE__, __FUNCTION__, + indicated_data_size, data_size); + return; + } + + /* put in pdu reception list */ + entity->rx_size += size; + pdu_segment = rlc_rx_new_pdu_segment(sn, 0, size, 1, buffer, data_start); + entity->rx_list = rlc_rx_pdu_segment_list_add(sn_compare_rx, entity, + entity->rx_list, pdu_segment); + + /* do reception actions (36.322 5.1.2.2.3) */ + rlc_um_reception_actions(entity, pdu_segment); + + return; + +err: + LOG_D(RLC, "%s:%d:%s: error decoding PDU, discarding\n", __FILE__, __LINE__, __FUNCTION__); + +#undef R +} + +/*************************************************************************/ +/* TX functions */ +/*************************************************************************/ + +typedef struct { + int sdu_count; + int data_size; + int header_size; + int last_sdu_is_full; + int first_sdu_length; +} tx_pdu_size_t; + +static int header_size(int sn_field_length, int sdu_count) +{ + int bits = 8 + 8 * (sn_field_length == 10) + 12 * (sdu_count - 1); + /* padding if we have to */ + return (bits + 7) / 8; +} + +static tx_pdu_size_t tx_pdu_size(rlc_entity_um_t *entity, int maxsize) +{ + tx_pdu_size_t ret; + int sdu_count; + int sdu_size; + int pdu_data_size; + rlc_sdu_t *sdu; + + ret.sdu_count = 0; + ret.data_size = 0; + ret.header_size = 0; + ret.last_sdu_is_full = 1; + + /* TX PDU - let's make the biggest PDU we can with the SDUs we have */ + sdu_count = 0; + pdu_data_size = 0; + sdu = entity->tx_list; + while (sdu != NULL) { + int new_header_size = header_size(entity->sn_field_length, sdu_count+1); + /* if we cannot put new header + at least 1 byte of data then over */ + if (new_header_size + pdu_data_size >= maxsize) + break; + sdu_count++; + /* only include the bytes of this SDU not included in PDUs already */ + sdu_size = sdu->size - sdu->next_byte; + /* don't feed more than 'maxsize' bytes */ + if (new_header_size + pdu_data_size + sdu_size > maxsize) { + sdu_size = maxsize - new_header_size - pdu_data_size; + ret.last_sdu_is_full = 0; + } + if (sdu_count == 1) + ret.first_sdu_length = sdu_size; + pdu_data_size += sdu_size; + /* if we put more than 2^11-1 bytes then the LI field cannot be used, + * so this is the last SDU we can put + */ + if (sdu_size > 2047) + break; + sdu = sdu->next; + } + + if (sdu_count) { + ret.sdu_count = sdu_count; + ret.data_size = pdu_data_size; + ret.header_size = header_size(entity->sn_field_length, sdu_count); + } + + return ret; +} + +rlc_entity_buffer_status_t rlc_entity_um_buffer_status( + rlc_entity_t *_entity, int maxsize) +{ + rlc_entity_um_t *entity = (rlc_entity_um_t *)_entity; + rlc_entity_buffer_status_t ret; + tx_pdu_size_t tx_size; + + ret.status_size = 0; + + tx_size = tx_pdu_size(entity, maxsize); + ret.tx_size = tx_size.data_size + tx_size.header_size; + + ret.retx_size = 0; + + return ret; +} + +int rlc_entity_um_generate_pdu(rlc_entity_t *_entity, char *buffer, int size) +{ + rlc_entity_um_t *entity = (rlc_entity_um_t *)_entity; + tx_pdu_size_t pdu_size; + rlc_sdu_t *sdu; + int i; + int cursize; + int first_sdu_full; + int last_sdu_full; + rlc_pdu_encoder_t encoder; + int fi; + int e; + int li; + char *out; + int outpos; + int first_sdu_start_byte; + int sdu_start_byte; + + pdu_size = tx_pdu_size(entity, size); + if (pdu_size.sdu_count == 0) + return 0; + + sdu = entity->tx_list; + + first_sdu_start_byte = sdu->next_byte; + + /* reserve SDU bytes */ + cursize = 0; + for (i = 0; i < pdu_size.sdu_count; i++, sdu = sdu->next) { + int sdu_size = sdu->size - sdu->next_byte; + if (cursize + sdu_size > pdu_size.data_size) + sdu_size = pdu_size.data_size - cursize; + sdu->next_byte += sdu_size; + cursize += sdu_size; + } + + first_sdu_full = first_sdu_start_byte == 0; + last_sdu_full = pdu_size.last_sdu_is_full; + + /* generate header */ + rlc_pdu_encoder_init(&encoder, buffer, size); + + if (entity->sn_field_length == 10) + rlc_pdu_encoder_put_bits(&encoder, 0, 3); /* R1 */ + + fi = 0; + if (!first_sdu_full) + fi |= 0x02; + if (!last_sdu_full) + fi |= 0x01; + rlc_pdu_encoder_put_bits(&encoder, fi, 2); /* FI */ + + /* see the AM code to understand the logic for Es and LIs */ + if (pdu_size.sdu_count >= 2) + e = 1; + else + e = 0; + rlc_pdu_encoder_put_bits(&encoder, e, 1); /* E */ + + if (entity->sn_field_length == 10) + rlc_pdu_encoder_put_bits(&encoder, entity->vt_us, 10); /* SN */ + else + rlc_pdu_encoder_put_bits(&encoder, entity->vt_us, 5); /* SN */ + + /* put LIs */ + sdu = entity->tx_list; + /* first SDU */ + li = pdu_size.first_sdu_length; + /* put E+LI only if at least 2 SDUs */ + if (pdu_size.sdu_count >= 2) { + /* E is 1 if at least 3 SDUs */ + if (pdu_size.sdu_count >= 3) + e = 1; + else + e = 0; + rlc_pdu_encoder_put_bits(&encoder, e, 1); /* E */ + rlc_pdu_encoder_put_bits(&encoder, li, 11); /* LI */ + } + /* next SDUs, but not the last (no LI for the last) */ + sdu = sdu->next; + for (i = 2; i < pdu_size.sdu_count; i++, sdu = sdu->next) { + if (i != pdu_size.sdu_count - 1) + e = 1; + else + e = 0; + li = sdu->size; + rlc_pdu_encoder_put_bits(&encoder, e, 1); /* E */ + rlc_pdu_encoder_put_bits(&encoder, li, 11); /* LI */ + } + + rlc_pdu_encoder_align(&encoder); + + /* generate data */ + out = buffer + pdu_size.header_size; + sdu = entity->tx_list; + sdu_start_byte = first_sdu_start_byte; + outpos = 0; + for (i = 0; i < pdu_size.sdu_count; i++, sdu = sdu->next) { + li = sdu->size - sdu_start_byte; + if (outpos + li >= pdu_size.data_size) + li = pdu_size.data_size - outpos; + memcpy(out+outpos, sdu->data + sdu_start_byte, li); + outpos += li; + sdu_start_byte = 0; + } + + /* cleanup sdu list */ + while (entity->tx_list != NULL && + entity->tx_list->size == entity->tx_list->next_byte) { + rlc_sdu_t *c = entity->tx_list; + /* release SDU bytes */ + entity->tx_size -= c->size; + entity->tx_list = c->next; + rlc_free_sdu(c); + } + if (entity->tx_list == NULL) + entity->tx_end = NULL; + + /* update VT(US) */ + entity->vt_us = (entity->vt_us + 1) % entity->sn_modulus; + + return pdu_size.header_size + pdu_size.data_size; +} + +/*************************************************************************/ +/* SDU RX functions */ +/*************************************************************************/ + +void rlc_entity_um_recv_sdu(rlc_entity_t *_entity, char *buffer, int size, + int sdu_id) +{ + rlc_entity_um_t *entity = (rlc_entity_um_t *)_entity; + rlc_sdu_t *sdu; + + if (size > SDU_MAX) { + LOG_E(RLC, "%s:%d:%s: fatal: SDU size too big (%d bytes)\n", + __FILE__, __LINE__, __FUNCTION__, size); + exit(1); + } + + if (entity->tx_size + size > entity->tx_maxsize) { + LOG_D(RLC, "%s:%d:%s: warning: SDU rejected, SDU buffer full\n", + __FILE__, __LINE__, __FUNCTION__); + return; + } + + entity->tx_size += size; + + sdu = rlc_new_sdu(buffer, size, sdu_id); + rlc_sdu_list_add(&entity->tx_list, &entity->tx_end, sdu); +} + +/*************************************************************************/ +/* time/timers */ +/*************************************************************************/ + +static void check_t_reordering(rlc_entity_um_t *entity) +{ + int sn; + + /* is t_reordering running and if yes has it expired? */ + if (entity->t_reordering_start == 0 || + entity->t_current <= entity->t_reordering_start + entity->t_reordering) + return; + + /* stop timer */ + entity->t_reordering_start = 0; + + LOG_D(RLC, "%s:%d:%s: t_reordering expired\n", __FILE__, __LINE__, __FUNCTION__); + + /* update VR(UR) to first SN >= VR(UX) of PDU not received + */ + sn = entity->vr_ux; + while (rlc_um_pdu_received(entity, sn)) + sn = (sn + 1) % entity->sn_modulus; + entity->vr_ur = sn; + + rlc_um_reassemble(entity, less_than_vr_ur); + + if (sn_compare_rx(entity, entity->vr_uh, entity->vr_ur) > 0) { + entity->t_reordering_start = entity->t_current; + entity->vr_ux = entity->vr_uh; + } +} + +void rlc_entity_um_set_time(rlc_entity_t *_entity, uint64_t now) +{ + rlc_entity_um_t *entity = (rlc_entity_um_t *)_entity; + + entity->t_current = now; + + check_t_reordering(entity); +} + +/*************************************************************************/ +/* discard/re-establishment/delete */ +/*************************************************************************/ + +void rlc_entity_um_discard_sdu(rlc_entity_t *_entity, int sdu_id) +{ + /* implements 36.322 5.3 */ + rlc_entity_um_t *entity = (rlc_entity_um_t *)_entity; + rlc_sdu_t head; + rlc_sdu_t *cur; + rlc_sdu_t *prev; + + head.next = entity->tx_list; + cur = entity->tx_list; + prev = &head; + + while (cur != NULL && cur->upper_layer_id != sdu_id) { + prev = cur; + cur = cur->next; + } + + /* if sdu_id not found or some bytes have already been 'PDU-ized' + * then do nothing + */ + if (cur == NULL || cur->next_byte != 0) + return; + + /* remove SDU from tx_list */ + prev->next = cur->next; + entity->tx_list = head.next; + if (entity->tx_end == cur) { + if (prev != &head) + entity->tx_end = prev; + else + entity->tx_end = NULL; + } + + rlc_free_sdu(cur); +} + +static void clear_entity(rlc_entity_um_t *entity) +{ + rlc_rx_pdu_segment_t *cur_rx; + rlc_sdu_t *cur_tx; + + entity->vr_ur = 0; + entity->vr_ux = 0; + entity->vr_uh = 0; + + entity->vt_us = 0; + + entity->t_current = 0; + + entity->t_reordering_start = 0; + + cur_rx = entity->rx_list; + while (cur_rx != NULL) { + rlc_rx_pdu_segment_t *p = cur_rx; + cur_rx = cur_rx->next; + rlc_rx_free_pdu_segment(p); + } + entity->rx_list = NULL; + entity->rx_size = 0; + + memset(&entity->reassemble, 0, sizeof(rlc_um_reassemble_t)); + + cur_tx = entity->tx_list; + while (cur_tx != NULL) { + rlc_sdu_t *p = cur_tx; + cur_tx = cur_tx->next; + rlc_free_sdu(p); + } + entity->tx_list = NULL; + entity->tx_end = NULL; + entity->tx_size = 0; +} + +void rlc_entity_um_reestablishment(rlc_entity_t *_entity) +{ + rlc_entity_um_t *entity = (rlc_entity_um_t *)_entity; + + rlc_um_reassemble(entity, less_than_vr_uh); + + clear_entity(entity); +} + +void rlc_entity_um_delete(rlc_entity_t *_entity) +{ + rlc_entity_um_t *entity = (rlc_entity_um_t *)_entity; + clear_entity(entity); + free(entity); +} diff --git a/openair2/LAYER2/rlc_v2/rlc_entity_um.h b/openair2/LAYER2/rlc_v2/rlc_entity_um.h new file mode 100644 index 0000000000..02c5141a7a --- /dev/null +++ b/openair2/LAYER2/rlc_v2/rlc_entity_um.h @@ -0,0 +1,90 @@ +/* + * 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 _RLC_ENTITY_UM_H_ +#define _RLC_ENTITY_UM_H_ + +#include "rlc_entity.h" +#include "rlc_pdu.h" +#include "rlc_sdu.h" + +typedef struct { + char sdu[SDU_MAX]; /* sdu is reassembled here */ + int sdu_pos; /* next byte to put in sdu */ + + /* decoder of current PDU */ + rlc_pdu_decoder_t dec; + int sn; + + int sdu_head_missing; +} rlc_um_reassemble_t; + +typedef struct { + rlc_entity_t common; + + /* configuration */ + int t_reordering; + int sn_field_length; + + int sn_modulus; /* 1024 for sn_field_length == 10, 32 for 5 */ + int window_size; /* 512 for sn_field_length == 10, 16 for 5 */ + + /* runtime rx */ + int vr_ur; + int vr_ux; + int vr_uh; + + /* runtime tx */ + int vt_us; + + /* set to the latest know time by the user of the module. Unit: ms */ + uint64_t t_current; + + /* timers (stores the TTI of activation, 0 means not active) */ + uint64_t t_reordering_start; + + /* rx management */ + rlc_rx_pdu_segment_t *rx_list; + int rx_size; + int rx_maxsize; + + /* reassembly management */ + rlc_um_reassemble_t reassemble; + + /* tx management */ + rlc_sdu_t *tx_list; + rlc_sdu_t *tx_end; + int tx_size; + int tx_maxsize; +} rlc_entity_um_t; + +void rlc_entity_um_recv_sdu(rlc_entity_t *_entity, char *buffer, int size, + int sdu_id); +void rlc_entity_um_recv_pdu(rlc_entity_t *entity, char *buffer, int size); +rlc_entity_buffer_status_t rlc_entity_um_buffer_status( + rlc_entity_t *entity, int maxsize); +int rlc_entity_um_generate_pdu(rlc_entity_t *_entity, char *buffer, int size); +void rlc_entity_um_set_time(rlc_entity_t *entity, uint64_t now); +void rlc_entity_um_discard_sdu(rlc_entity_t *entity, int sdu_id); +void rlc_entity_um_reestablishment(rlc_entity_t *entity); +void rlc_entity_um_delete(rlc_entity_t *entity); + +#endif /* _RLC_ENTITY_UM_H_ */ diff --git a/openair2/LAYER2/rlc_v2/rlc_oai_api.c b/openair2/LAYER2/rlc_v2/rlc_oai_api.c new file mode 100644 index 0000000000..1be9c90a31 --- /dev/null +++ b/openair2/LAYER2/rlc_v2/rlc_oai_api.c @@ -0,0 +1,821 @@ +/* + * 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 + */ + +/* from openair */ +#include "rlc.h" +#include "pdcp.h" + +/* from new rlc module */ +#include "asn1_utils.h" +#include "rlc_ue_manager.h" +#include "rlc_entity.h" + +#include + +static rlc_ue_manager_t *rlc_ue_manager; + +/* TODO: handle time a bit more properly */ +static uint64_t rlc_current_time; +static int rlc_current_time_last_frame; +static int rlc_current_time_last_subframe; + +void mac_rlc_data_ind ( + const module_id_t module_idP, + const rnti_t rntiP, + const eNB_index_t eNB_index, + const frame_t frameP, + const eNB_flag_t enb_flagP, + const MBMS_flag_t MBMS_flagP, + const logical_chan_id_t channel_idP, + char *buffer_pP, + const tb_size_t tb_sizeP, + num_tb_t num_tbP, + crc_t *crcs_pP) +{ + rlc_ue_t *ue; + rlc_entity_t *rb; + + if (module_idP != 0 || eNB_index != 0 || enb_flagP != 1 || MBMS_flagP != 0) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + if (enb_flagP) + T(T_ENB_RLC_MAC_UL, T_INT(module_idP), T_INT(rntiP), + T_INT(channel_idP), T_INT(tb_sizeP)); + + rlc_manager_lock(rlc_ue_manager); + ue = rlc_manager_get_ue(rlc_ue_manager, rntiP); + + switch (channel_idP) { + case 1 ... 2: rb = ue->srb[channel_idP - 1]; break; + case 3 ... 7: rb = ue->drb[channel_idP - 3]; break; + default: rb = NULL; break; + } + + if (rb != NULL) { + rb->set_time(rb, rlc_current_time); + rb->recv_pdu(rb, buffer_pP, tb_sizeP); + } else { + LOG_E(RLC, "%s:%d:%s: fatal: no RB found (channel ID %d)\n", + __FILE__, __LINE__, __FUNCTION__, channel_idP); + exit(1); + } + + rlc_manager_unlock(rlc_ue_manager); +} + +tbs_size_t mac_rlc_data_req( + const module_id_t module_idP, + const rnti_t rntiP, + const eNB_index_t eNB_index, + const frame_t frameP, + const eNB_flag_t enb_flagP, + const MBMS_flag_t MBMS_flagP, + const logical_chan_id_t channel_idP, + const tb_size_t tb_sizeP, + char *buffer_pP +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + ,const uint32_t sourceL2Id + ,const uint32_t destinationL2Id +#endif + ) +{ + int ret; + rlc_ue_t *ue; + rlc_entity_t *rb; + + rlc_manager_lock(rlc_ue_manager); + ue = rlc_manager_get_ue(rlc_ue_manager, rntiP); + + switch (channel_idP) { + case 1 ... 2: rb = ue->srb[channel_idP - 1]; break; + case 3 ... 7: rb = ue->drb[channel_idP - 3]; break; + default: rb = NULL; break; + } + + if (rb != NULL) { + rb->set_time(rb, rlc_current_time); + ret = rb->generate_pdu(rb, buffer_pP, ue->saved_status_ind_tb_size[channel_idP - 1]); + } else { + LOG_E(RLC, "%s:%d:%s: fatal: data req for unknown RB\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + ret = 0; + } + + rlc_manager_unlock(rlc_ue_manager); + + if (enb_flagP) + T(T_ENB_RLC_MAC_DL, T_INT(module_idP), T_INT(rntiP), + T_INT(channel_idP), T_INT(ret)); + + return ret; +} + +mac_rlc_status_resp_t mac_rlc_status_ind( + const module_id_t module_idP, + const rnti_t rntiP, + const eNB_index_t eNB_index, + const frame_t frameP, + const sub_frame_t subframeP, + const eNB_flag_t enb_flagP, + const MBMS_flag_t MBMS_flagP, + const logical_chan_id_t channel_idP, + const tb_size_t tb_sizeP +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + ,const uint32_t sourceL2Id + ,const uint32_t destinationL2Id +#endif + ) +{ + rlc_ue_t *ue; + mac_rlc_status_resp_t ret; + rlc_entity_t *rb; + + /* TODO: handle time a bit more properly */ + if (rlc_current_time_last_frame != frameP || + rlc_current_time_last_subframe != subframeP) { + rlc_current_time++; + rlc_current_time_last_frame = frameP; + rlc_current_time_last_subframe = subframeP; + } + + rlc_manager_lock(rlc_ue_manager); + ue = rlc_manager_get_ue(rlc_ue_manager, rntiP); + + switch (channel_idP) { + case 1 ... 2: rb = ue->srb[channel_idP - 1]; break; + case 3 ... 7: rb = ue->drb[channel_idP - 3]; break; + default: rb = NULL; break; + } + + if (rb != NULL) { + rlc_entity_buffer_status_t buf_stat; + rb->set_time(rb, rlc_current_time); + buf_stat = rb->buffer_status(rb, tb_sizeP ? tb_sizeP : 1000000); + if (buf_stat.status_size) + ret.bytes_in_buffer = buf_stat.status_size; + else if (buf_stat.retx_size) + ret.bytes_in_buffer = buf_stat.retx_size; + else + ret.bytes_in_buffer = buf_stat.tx_size; + ue->saved_status_ind_tb_size[channel_idP - 1] = tb_sizeP; + } else { + ret.bytes_in_buffer = 0; + } + + rlc_manager_unlock(rlc_ue_manager); + + ret.pdus_in_buffer = 0; + /* TODO: creation time may be important (unit: frame, as it seems) */ + ret.head_sdu_creation_time = 0; + ret.head_sdu_remaining_size_to_send = 0; + ret.head_sdu_is_segmented = 0; + return ret; +} + +int oai_emulation; + +rlc_op_status_t rlc_data_req (const protocol_ctxt_t *const ctxt_pP, + const srb_flag_t srb_flagP, + const MBMS_flag_t MBMS_flagP, + const rb_id_t rb_idP, + const mui_t muiP, + confirm_t confirmP, + sdu_size_t sdu_sizeP, + mem_block_t *sdu_pP +#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) + ,const uint32_t *const sourceL2Id + ,const uint32_t *const destinationL2Id +#endif + ) +{ + int rnti = ctxt_pP->rnti; + rlc_ue_t *ue; + rlc_entity_t *rb; + + LOG_D(RLC, "%s rnti %d srb_flag %d rb_id %d mui %d confirm %d sdu_size %d MBMS_flag %d\n", + __FUNCTION__, rnti, srb_flagP, rb_idP, muiP, confirmP, sdu_sizeP, + MBMS_flagP); + + if (ctxt_pP->enb_flag) + T(T_ENB_RLC_DL, T_INT(ctxt_pP->module_id), + T_INT(ctxt_pP->rnti), T_INT(rb_idP), T_INT(sdu_sizeP)); + + rlc_manager_lock(rlc_ue_manager); + ue = rlc_manager_get_ue(rlc_ue_manager, rnti); + + rb = NULL; + + if (srb_flagP) { + if (rb_idP >= 1 && rb_idP <= 2) + rb = ue->srb[rb_idP - 1]; + } else { + if (rb_idP >= 1 && rb_idP <= 5) + rb = ue->drb[rb_idP - 1]; + } + + if (rb != NULL) { + rb->set_time(rb, rlc_current_time); + rb->recv_sdu(rb, (char *)sdu_pP->data, sdu_sizeP, muiP); + } else { + LOG_E(RLC, "%s:%d:%s: fatal: SDU sent to unknown RB\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + rlc_manager_unlock(rlc_ue_manager); + + free_mem_block(sdu_pP, __func__); + + return RLC_OP_STATUS_OK; +} + +int rlc_module_init(void) +{ + static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + static int inited = 0; + + if (pthread_mutex_lock(&lock)) abort(); + + if (inited) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + inited = 1; + + rlc_ue_manager = new_rlc_ue_manager(); + + if (pthread_mutex_unlock(&lock)) abort(); + + return 0; +} + +void rlc_util_print_hex_octets(comp_name_t componentP, unsigned char *dataP, const signed long sizeP) +{ +} + +static void deliver_sdu(void *_ue, rlc_entity_t *entity, char *buf, int size) +{ + rlc_ue_t *ue = _ue; + int is_srb; + int rb_id; + protocol_ctxt_t ctx; + mem_block_t *memblock; + int i; + + /* is it SRB? */ + for (i = 0; i < 2; i++) { + if (entity == ue->srb[i]) { + is_srb = 1; + rb_id = i+1; + goto rb_found; + } + } + + /* maybe DRB? */ + for (i = 0; i < 5; i++) { + if (entity == ue->drb[i]) { + is_srb = 0; + rb_id = i+1; + goto rb_found; + } + } + + LOG_E(RLC, "%s:%d:%s: fatal, no RB found for ue %d\n", + __FILE__, __LINE__, __FUNCTION__, ue->rnti); + exit(1); + +rb_found: + LOG_D(RLC, "%s:%d:%s: delivering SDU (rnti %d is_srb %d rb_id %d) size %d", + __FILE__, __LINE__, __FUNCTION__, ue->rnti, is_srb, rb_id, size); + + memblock = get_free_mem_block(size, __func__); + if (memblock == NULL) { + LOG_E(RLC, "%s:%d:%s: ERROR: get_free_mem_block failed\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + memcpy(memblock->data, buf, size); + + /* unused fields? */ + ctx.instance = 0; + ctx.frame = 0; + ctx.subframe = 0; + ctx.eNB_index = 0; + ctx.configured = 1; + ctx.brOption = 0; + + /* used fields? */ + ctx.module_id = 0; + ctx.rnti = ue->rnti; + ctx.enb_flag = 1; + + T(T_ENB_RLC_UL, + T_INT(0 /*ctxt_pP->module_id*/), + T_INT(ue->rnti), T_INT(rb_id), T_INT(size)); + + if (!pdcp_data_ind(&ctx, is_srb, 0, rb_id, size, memblock)) { + LOG_E(RLC, "%s:%d:%s: ERROR: pdcp_data_ind failed\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +static void successful_delivery(void *_ue, rlc_entity_t *entity, int sdu_id) +{ + rlc_ue_t *ue = _ue; + int i; + int is_srb; + int rb_id; + MessageDef *msg; + + /* is it SRB? */ + for (i = 0; i < 2; i++) { + if (entity == ue->srb[i]) { + is_srb = 1; + rb_id = i+1; + goto rb_found; + } + } + + /* maybe DRB? */ + for (i = 0; i < 5; i++) { + if (entity == ue->drb[i]) { + is_srb = 0; + rb_id = i+1; + goto rb_found; + } + } + + LOG_E(RLC, "%s:%d:%s: fatal, no RB found for ue %d\n", + __FILE__, __LINE__, __FUNCTION__, ue->rnti); + exit(1); + +rb_found: + LOG_D(RLC, "sdu %d was successfully delivered on %s %d\n", + sdu_id, + is_srb ? "SRB" : "DRB", + rb_id); + + /* TODO: do something for DRBs? */ + if (is_srb == 0) + return; + + msg = itti_alloc_new_message(TASK_RLC_ENB, RLC_SDU_INDICATION); + RLC_SDU_INDICATION(msg).rnti = ue->rnti; + RLC_SDU_INDICATION(msg).is_successful = 1; + RLC_SDU_INDICATION(msg).srb_id = rb_id; + RLC_SDU_INDICATION(msg).message_id = sdu_id; + /* TODO: accept more than 1 instance? here we send to instance id 0 */ + itti_send_msg_to_task(TASK_RRC_ENB, 0, msg); +} + +static void max_retx_reached(void *_ue, rlc_entity_t *entity) +{ + rlc_ue_t *ue = _ue; + int i; + int is_srb; + int rb_id; + MessageDef *msg; + + /* is it SRB? */ + for (i = 0; i < 2; i++) { + if (entity == ue->srb[i]) { + is_srb = 1; + rb_id = i+1; + goto rb_found; + } + } + + /* maybe DRB? */ + for (i = 0; i < 5; i++) { + if (entity == ue->drb[i]) { + is_srb = 0; + rb_id = i+1; + goto rb_found; + } + } + + LOG_E(RLC, "%s:%d:%s: fatal, no RB found for ue %d\n", + __FILE__, __LINE__, __FUNCTION__, ue->rnti); + exit(1); + +rb_found: + LOG_D(RLC, "max RETX reached on %s %d\n", + is_srb ? "SRB" : "DRB", + rb_id); + + /* TODO: do something for DRBs? */ + if (is_srb == 0) + return; + + msg = itti_alloc_new_message(TASK_RLC_ENB, RLC_SDU_INDICATION); + RLC_SDU_INDICATION(msg).rnti = ue->rnti; + RLC_SDU_INDICATION(msg).is_successful = 0; + RLC_SDU_INDICATION(msg).srb_id = rb_id; + RLC_SDU_INDICATION(msg).message_id = -1; + /* TODO: accept more than 1 instance? here we send to instance id 0 */ + itti_send_msg_to_task(TASK_RRC_ENB, 0, msg); +} + +static void add_srb(int rnti, struct LTE_SRB_ToAddMod *s) +{ + rlc_entity_t *rlc_am; + rlc_ue_t *ue; + + struct LTE_SRB_ToAddMod__rlc_Config *r = s->rlc_Config; + struct LTE_SRB_ToAddMod__logicalChannelConfig *l = s->logicalChannelConfig; + int srb_id = s->srb_Identity; + int logical_channel_group; + + int t_reordering; + int t_status_prohibit; + int t_poll_retransmit; + int poll_pdu; + int poll_byte; + int max_retx_threshold; + + if (srb_id != 1 && srb_id != 2) { + LOG_E(RLC, "%s:%d:%s: fatal, bad srb id %d\n", + __FILE__, __LINE__, __FUNCTION__, srb_id); + exit(1); + } + + switch (l->present) { + case LTE_SRB_ToAddMod__logicalChannelConfig_PR_explicitValue: + logical_channel_group = *l->choice.explicitValue.ul_SpecificParameters->logicalChannelGroup; + break; + case LTE_SRB_ToAddMod__logicalChannelConfig_PR_defaultValue: + /* default value from 36.331 9.2.1 */ + logical_channel_group = 0; + break; + default: + LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + /* TODO: accept other values? */ + if (logical_channel_group != 0) { + LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + switch (r->present) { + case LTE_SRB_ToAddMod__rlc_Config_PR_explicitValue: { + struct LTE_RLC_Config__am *am; + if (r->choice.explicitValue.present != LTE_RLC_Config_PR_am) { + LOG_E(RLC, "%s:%d:%s: fatal error, must be RLC AM\n", + __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + am = &r->choice.explicitValue.choice.am; + t_reordering = decode_t_reordering(am->dl_AM_RLC.t_Reordering); + t_status_prohibit = decode_t_status_prohibit(am->dl_AM_RLC.t_StatusProhibit); + t_poll_retransmit = decode_t_poll_retransmit(am->ul_AM_RLC.t_PollRetransmit); + poll_pdu = decode_poll_pdu(am->ul_AM_RLC.pollPDU); + poll_byte = decode_poll_byte(am->ul_AM_RLC.pollByte); + max_retx_threshold = decode_max_retx_threshold(am->ul_AM_RLC.maxRetxThreshold); + break; + } + case LTE_SRB_ToAddMod__rlc_Config_PR_defaultValue: + /* default values from 36.331 9.2.1 */ + t_reordering = 35; + t_status_prohibit = 0; + t_poll_retransmit = 45; + poll_pdu = -1; + poll_byte = -1; + max_retx_threshold = 4; + break; + default: + LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + rlc_manager_lock(rlc_ue_manager); + ue = rlc_manager_get_ue(rlc_ue_manager, rnti); + if (ue->srb[srb_id-1] != NULL) { + LOG_D(RLC, "%s:%d:%s: warning SRB %d already exist for ue %d, do nothing\n", + __FILE__, __LINE__, __FUNCTION__, srb_id, rnti); + } else { + rlc_am = new_rlc_entity_am(100000, + 100000, + deliver_sdu, ue, + successful_delivery, ue, + max_retx_reached, ue, + t_reordering, t_status_prohibit, + t_poll_retransmit, + poll_pdu, poll_byte, max_retx_threshold); + rlc_ue_add_srb_rlc_entity(ue, srb_id, rlc_am); + + LOG_D(RLC, "%s:%d:%s: added srb %d to ue %d\n", + __FILE__, __LINE__, __FUNCTION__, srb_id, rnti); + } + rlc_manager_unlock(rlc_ue_manager); +} + +static void add_drb_am(int rnti, struct LTE_DRB_ToAddMod *s) +{ + rlc_entity_t *rlc_am; + rlc_ue_t *ue; + + struct LTE_RLC_Config *r = s->rlc_Config; + struct LTE_LogicalChannelConfig *l = s->logicalChannelConfig; + int drb_id = s->drb_Identity; + int channel_id = *s->logicalChannelIdentity; + int logical_channel_group; + + int t_reordering; + int t_status_prohibit; + int t_poll_retransmit; + int poll_pdu; + int poll_byte; + int max_retx_threshold; + + if (!(drb_id >= 1 && drb_id <= 5)) { + LOG_E(RLC, "%s:%d:%s: fatal, bad srb id %d\n", + __FILE__, __LINE__, __FUNCTION__, drb_id); + exit(1); + } + + if (channel_id != drb_id + 2) { + LOG_E(RLC, "%s:%d:%s: todo, remove this limitation\n", + __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + logical_channel_group = *l->ul_SpecificParameters->logicalChannelGroup; + + /* TODO: accept other values? */ + if (logical_channel_group != 1) { + LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + switch (r->present) { + case LTE_RLC_Config_PR_am: { + struct LTE_RLC_Config__am *am; + am = &r->choice.am; + t_reordering = decode_t_reordering(am->dl_AM_RLC.t_Reordering); + t_status_prohibit = decode_t_status_prohibit(am->dl_AM_RLC.t_StatusProhibit); + t_poll_retransmit = decode_t_poll_retransmit(am->ul_AM_RLC.t_PollRetransmit); + poll_pdu = decode_poll_pdu(am->ul_AM_RLC.pollPDU); + poll_byte = decode_poll_byte(am->ul_AM_RLC.pollByte); + max_retx_threshold = decode_max_retx_threshold(am->ul_AM_RLC.maxRetxThreshold); + break; + } + default: + LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + rlc_manager_lock(rlc_ue_manager); + ue = rlc_manager_get_ue(rlc_ue_manager, rnti); + if (ue->drb[drb_id-1] != NULL) { + LOG_D(RLC, "%s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n", + __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); + } else { + rlc_am = new_rlc_entity_am(1000000, + 1000000, + deliver_sdu, ue, + successful_delivery, ue, + max_retx_reached, ue, + t_reordering, t_status_prohibit, + t_poll_retransmit, + poll_pdu, poll_byte, max_retx_threshold); + rlc_ue_add_drb_rlc_entity(ue, drb_id, rlc_am); + + LOG_D(RLC, "%s:%d:%s: added drb %d to ue %d\n", + __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); + } + rlc_manager_unlock(rlc_ue_manager); +} + +static void add_drb_um(int rnti, struct LTE_DRB_ToAddMod *s) +{ + rlc_entity_t *rlc_um; + rlc_ue_t *ue; + + struct LTE_RLC_Config *r = s->rlc_Config; + struct LTE_LogicalChannelConfig *l = s->logicalChannelConfig; + int drb_id = s->drb_Identity; + int channel_id = *s->logicalChannelIdentity; + int logical_channel_group; + + int t_reordering; + int sn_field_length; + + if (!(drb_id >= 1 && drb_id <= 5)) { + LOG_E(RLC, "%s:%d:%s: fatal, bad srb id %d\n", + __FILE__, __LINE__, __FUNCTION__, drb_id); + exit(1); + } + + if (channel_id != drb_id + 2) { + LOG_E(RLC, "%s:%d:%s: todo, remove this limitation\n", + __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + logical_channel_group = *l->ul_SpecificParameters->logicalChannelGroup; + + /* TODO: accept other values? */ + if (logical_channel_group != 1) { + LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + switch (r->present) { + case LTE_RLC_Config_PR_um_Bi_Directional: { + struct LTE_RLC_Config__um_Bi_Directional *um; + um = &r->choice.um_Bi_Directional; + t_reordering = decode_t_reordering(um->dl_UM_RLC.t_Reordering); + if (um->dl_UM_RLC.sn_FieldLength != um->ul_UM_RLC.sn_FieldLength) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + sn_field_length = decode_sn_field_length(um->dl_UM_RLC.sn_FieldLength); + break; + } + default: + LOG_E(RLC, "%s:%d:%s: fatal error\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + rlc_manager_lock(rlc_ue_manager); + ue = rlc_manager_get_ue(rlc_ue_manager, rnti); + if (ue->drb[drb_id-1] != NULL) { + LOG_D(RLC, "%s:%d:%s: warning DRB %d already exist for ue %d, do nothing\n", + __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); + } else { + rlc_um = new_rlc_entity_um(1000000, + 1000000, + deliver_sdu, ue, + t_reordering, + sn_field_length); + rlc_ue_add_drb_rlc_entity(ue, drb_id, rlc_um); + + LOG_D(RLC, "%s:%d:%s: added drb %d to ue %d\n", + __FILE__, __LINE__, __FUNCTION__, drb_id, rnti); + } + rlc_manager_unlock(rlc_ue_manager); +} + +static void add_drb(int rnti, struct LTE_DRB_ToAddMod *s) +{ + switch (s->rlc_Config->present) { + case LTE_RLC_Config_PR_am: + add_drb_am(rnti, s); + break; + case LTE_RLC_Config_PR_um_Bi_Directional: + add_drb_um(rnti, s); + break; + default: + LOG_E(RLC, "%s:%d:%s: fatal: unhandled DRB type\n", + __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP, + const LTE_SRB_ToAddModList_t * const srb2add_listP, + const LTE_DRB_ToAddModList_t * const drb2add_listP, + const LTE_DRB_ToReleaseList_t * const drb2release_listP +#if (LTE_RRC_VERSION >= MAKE_VERSION(9, 0, 0)) + ,const LTE_PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP + ,const uint32_t sourceL2Id + ,const uint32_t destinationL2Id +#endif + ) +{ + int rnti = ctxt_pP->rnti; + int i; + + if (ctxt_pP->enb_flag != 1 || ctxt_pP->module_id != 0 /*|| + ctxt_pP->instance != 0 || ctxt_pP->eNB_index != 0 || + ctxt_pP->configured != 1 || ctxt_pP->brOption != 0 */) { + LOG_E(RLC, "%s: ctxt_pP not handled (%d %d %d %d %d %d)\n", __FUNCTION__, + ctxt_pP->enb_flag , ctxt_pP->module_id, ctxt_pP->instance, + ctxt_pP->eNB_index, ctxt_pP->configured, ctxt_pP->brOption); + exit(1); + } + + if (pmch_InfoList_r9_pP != NULL) { + LOG_E(RLC, "%s: pmch_InfoList_r9_pP not handled\n", __FUNCTION__); + exit(1); + } + + if (drb2release_listP != NULL) { + LOG_E(RLC, "%s:%d:%s: TODO\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + if (srb2add_listP != NULL) { + for (i = 0; i < srb2add_listP->list.count; i++) { + add_srb(rnti, srb2add_listP->list.array[i]); + } + } + + if (drb2add_listP != NULL) { + for (i = 0; i < drb2add_listP->list.count; i++) { + add_drb(rnti, drb2add_listP->list.array[i]); + } + } + + return RLC_OP_STATUS_OK; +} + +rlc_op_status_t rrc_rlc_config_req ( + const protocol_ctxt_t* const ctxt_pP, + const srb_flag_t srb_flagP, + const MBMS_flag_t mbms_flagP, + const config_action_t actionP, + const rb_id_t rb_idP, + const rlc_info_t rlc_infoP) +{ + rlc_ue_t *ue; + int i; + + if (mbms_flagP) { + LOG_E(RLC, "%s:%d:%s: todo (mbms not supported)\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + if (!ctxt_pP->enb_flag) { + LOG_E(RLC, "%s:%d:%s: todo (only eNB supported, not UE)\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + if (actionP != CONFIG_ACTION_REMOVE) { + LOG_E(RLC, "%s:%d:%s: todo (only CONFIG_ACTION_REMOVE supported)\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + if (ctxt_pP->module_id) { + LOG_E(RLC, "%s:%d:%s: todo (only module_id 0 supported)\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + if ((srb_flagP && !(rb_idP >= 1 && rb_idP <= 2)) || + (!srb_flagP && !(rb_idP >= 1 && rb_idP <= 5))) { + LOG_E(RLC, "%s:%d:%s: bad rb_id (%d) (is_srb %d)\n", __FILE__, __LINE__, __FUNCTION__, rb_idP, srb_flagP); + exit(1); + } + rlc_manager_lock(rlc_ue_manager); + LOG_D(RLC, "%s:%d:%s: remove rb %d (is_srb %d) for UE %d\n", __FILE__, __LINE__, __FUNCTION__, rb_idP, srb_flagP, ctxt_pP->rnti); + ue = rlc_manager_get_ue(rlc_ue_manager, ctxt_pP->rnti); + if (srb_flagP) { + if (ue->srb[rb_idP-1] != NULL) { + ue->srb[rb_idP-1]->delete(ue->srb[rb_idP-1]); + ue->srb[rb_idP-1] = NULL; + } else + LOG_W(RLC, "removing non allocated SRB %d, do nothing\n", rb_idP); + } else { + if (ue->drb[rb_idP-1] != NULL) { + ue->drb[rb_idP-1]->delete(ue->drb[rb_idP-1]); + ue->drb[rb_idP-1] = NULL; + } else + LOG_W(RLC, "removing non allocated DRB %d, do nothing\n", rb_idP); + } + /* remove UE if it has no more RB configured */ + for (i = 0; i < 2; i++) + if (ue->srb[i] != NULL) + break; + if (i == 2) { + for (i = 0; i < 5; i++) + if (ue->drb[i] != NULL) + break; + if (i == 5) + rlc_manager_remove_ue(rlc_ue_manager, ctxt_pP->rnti); + } + rlc_manager_unlock(rlc_ue_manager); + return RLC_OP_STATUS_OK; +} + +void rrc_rlc_register_rrc (rrc_data_ind_cb_t rrc_data_indP, rrc_data_conf_cb_t rrc_data_confP) +{ + /* nothing to do */ +} + +rlc_op_status_t rrc_rlc_remove_ue (const protocol_ctxt_t* const x) +{ + LOG_D(RLC, "%s:%d:%s: remove UE %d\n", __FILE__, __LINE__, __FUNCTION__, x->rnti); + rlc_manager_lock(rlc_ue_manager); + rlc_manager_remove_ue(rlc_ue_manager, x->rnti); + rlc_manager_unlock(rlc_ue_manager); + + return RLC_OP_STATUS_OK; +} + diff --git a/openair2/LAYER2/rlc_v2/rlc_pdu.c b/openair2/LAYER2/rlc_v2/rlc_pdu.c new file mode 100644 index 0000000000..c55e2d9c3c --- /dev/null +++ b/openair2/LAYER2/rlc_v2/rlc_pdu.c @@ -0,0 +1,266 @@ +/* + * 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 "rlc_pdu.h" + +#include +#include + +#include "LOG/log.h" + +/**************************************************************************/ +/* RX PDU segment and segment list */ +/**************************************************************************/ + +rlc_rx_pdu_segment_t *rlc_rx_new_pdu_segment(int sn, int so, int size, + int is_last, char *data, int data_offset) +{ + rlc_rx_pdu_segment_t *ret = malloc(sizeof(rlc_rx_pdu_segment_t)); + if (ret == NULL) { + LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + ret->sn = sn; + ret->so = so; + ret->size = size; + ret->is_last = is_last; + ret->next = NULL; + + ret->data = malloc(size); + if (ret->data == NULL) { + LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + memcpy(ret->data, data, size); + + ret->data_offset = data_offset; + + return ret; +} + +void rlc_rx_free_pdu_segment(rlc_rx_pdu_segment_t *pdu_segment) +{ + free(pdu_segment->data); + free(pdu_segment); +} + +rlc_rx_pdu_segment_t *rlc_rx_pdu_segment_list_add( + int (*sn_compare)(void *, int, int), void *sn_compare_data, + rlc_rx_pdu_segment_t *list, rlc_rx_pdu_segment_t *pdu_segment) +{ + rlc_rx_pdu_segment_t head; + rlc_rx_pdu_segment_t *cur; + rlc_rx_pdu_segment_t *prev; + + head.next = list; + cur = list; + prev = &head; + + /* order is by 'sn', if 'sn' is the same then order is by 'so' */ + while (cur != NULL) { + /* check if 'pdu_segment' is before 'cur' in the list */ + if (sn_compare(sn_compare_data, cur->sn, pdu_segment->sn) > 0 || + (cur->sn == pdu_segment->sn && cur->so > pdu_segment->so)) { + break; + } + prev = cur; + cur = cur->next; + } + prev->next = pdu_segment; + pdu_segment->next = cur; + return head.next; +} + +/**************************************************************************/ +/* TX PDU management */ +/**************************************************************************/ + +rlc_tx_pdu_segment_t *rlc_tx_new_pdu(void) +{ + rlc_tx_pdu_segment_t *ret = calloc(1, sizeof(rlc_tx_pdu_segment_t)); + if (ret == NULL) { + LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + ret->retx_count = -1; + return ret; +} + +void rlc_tx_free_pdu(rlc_tx_pdu_segment_t *pdu) +{ + free(pdu); +} + +rlc_tx_pdu_segment_t *rlc_tx_pdu_list_append(rlc_tx_pdu_segment_t *list, + rlc_tx_pdu_segment_t *pdu) +{ + rlc_tx_pdu_segment_t head; + rlc_tx_pdu_segment_t *cur; + + head.next = list; + + cur = &head; + while (cur->next != NULL) { + cur = cur->next; + } + cur->next = pdu; + + return head.next; +} + +rlc_tx_pdu_segment_t *rlc_tx_pdu_list_add( + int (*sn_compare)(void *, int, int), void *sn_compare_data, + rlc_tx_pdu_segment_t *list, rlc_tx_pdu_segment_t *pdu_segment) +{ + rlc_tx_pdu_segment_t head; + rlc_tx_pdu_segment_t *cur; + rlc_tx_pdu_segment_t *prev; + + head.next = list; + cur = list; + prev = &head; + + /* order is by 'sn', if 'sn' is the same then order is by 'so' */ + while (cur != NULL) { + /* check if 'pdu_segment' is before 'cur' in the list */ + if (sn_compare(sn_compare_data, cur->sn, pdu_segment->sn) > 0 || + (cur->sn == pdu_segment->sn && cur->so > pdu_segment->so)) { + break; + } + prev = cur; + cur = cur->next; + } + prev->next = pdu_segment; + pdu_segment->next = cur; + return head.next; +} + +/**************************************************************************/ +/* PDU decoder */ +/**************************************************************************/ + +void rlc_pdu_decoder_init(rlc_pdu_decoder_t *decoder, char *buffer, int size) +{ + decoder->error = 0; + decoder->byte = 0; + decoder->bit = 0; + decoder->buffer = buffer; + decoder->size = size; +} + +static int get_bit(rlc_pdu_decoder_t *decoder) +{ + int ret; + + if (decoder->byte >= decoder->size) { + decoder->error = 1; + return 0; + } + + ret = (decoder->buffer[decoder->byte] >> (7 - decoder->bit)) & 1; + + decoder->bit++; + if (decoder->bit == 8) { + decoder->bit = 0; + decoder->byte++; + } + + return ret; +} + +int rlc_pdu_decoder_get_bits(rlc_pdu_decoder_t *decoder, int count) +{ + int ret = 0; + int i; + + if (count > 31) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + for (i = 0; i < count; i++) { + ret <<= 1; + ret |= get_bit(decoder); + if (decoder->error) return -1; + } + + return ret; +} + +void rlc_pdu_decoder_align(rlc_pdu_decoder_t *decoder) +{ + if (decoder->bit) { + decoder->bit = 0; + decoder->byte++; + } +} + +/**************************************************************************/ +/* PDU encoder */ +/**************************************************************************/ + +void rlc_pdu_encoder_init(rlc_pdu_encoder_t *encoder, char *buffer, int size) +{ + encoder->byte = 0; + encoder->bit = 0; + encoder->buffer = buffer; + encoder->size = size; +} + +static void put_bit(rlc_pdu_encoder_t *encoder, int bit) +{ + if (encoder->byte == encoder->size) { + LOG_E(RLC, "%s:%d:%s: fatal, buffer full\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + encoder->buffer[encoder->byte] <<= 1; + if (bit) + encoder->buffer[encoder->byte] |= 1; + + encoder->bit++; + if (encoder->bit == 8) { + encoder->bit = 0; + encoder->byte++; + } +} + +void rlc_pdu_encoder_put_bits(rlc_pdu_encoder_t *encoder, int value, int count) +{ + int i; + int x; + + if (count > 31) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + x = 1 << (count - 1); + for (i = 0; i < count; i++, x >>= 1) + put_bit(encoder, value & x); +} + +void rlc_pdu_encoder_align(rlc_pdu_encoder_t *encoder) +{ + while (encoder->bit) + put_bit(encoder, 0); +} diff --git a/openair2/LAYER2/rlc_v2/rlc_pdu.h b/openair2/LAYER2/rlc_v2/rlc_pdu.h new file mode 100644 index 0000000000..dbffe9f3cb --- /dev/null +++ b/openair2/LAYER2/rlc_v2/rlc_pdu.h @@ -0,0 +1,109 @@ +/* + * 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 _RLC_PDU_H_ +#define _RLC_PDU_H_ + +/**************************************************************************/ +/* RX PDU segment and segment list */ +/**************************************************************************/ + +typedef struct rlc_rx_pdu_segment_t { + int sn; + int so; + int size; + int is_last; + char *data; + int data_offset; + struct rlc_rx_pdu_segment_t *next; +} rlc_rx_pdu_segment_t; + +rlc_rx_pdu_segment_t *rlc_rx_new_pdu_segment(int sn, int so, int size, + int is_last, char *data, int data_offset); + +void rlc_rx_free_pdu_segment(rlc_rx_pdu_segment_t *pdu_segment); + +rlc_rx_pdu_segment_t *rlc_rx_pdu_segment_list_add( + int (*sn_compare)(void *, int, int), void *sn_compare_data, + rlc_rx_pdu_segment_t *list, rlc_rx_pdu_segment_t *pdu_segment); + +/**************************************************************************/ +/* TX PDU management */ +/**************************************************************************/ + +typedef struct rlc_tx_pdu_segment_t { + int sn; + void *start_sdu; /* real type is rlc_sdu_t * */ + int sdu_start_byte; /* starting byte in 'start_sdu' */ + int so; /* starting byte of the segment in full PDU */ + int data_size; /* number of data bytes (exclude header) */ + int is_segment; + int is_last; + int retx_count; + struct rlc_tx_pdu_segment_t *next; +} rlc_tx_pdu_segment_t; + +rlc_tx_pdu_segment_t *rlc_tx_new_pdu(void); +void rlc_tx_free_pdu(rlc_tx_pdu_segment_t *pdu); +rlc_tx_pdu_segment_t *rlc_tx_pdu_list_append(rlc_tx_pdu_segment_t *list, + rlc_tx_pdu_segment_t *pdu); +rlc_tx_pdu_segment_t *rlc_tx_pdu_list_add( + int (*sn_compare)(void *, int, int), void *sn_compare_data, + rlc_tx_pdu_segment_t *list, rlc_tx_pdu_segment_t *pdu_segment); + +/**************************************************************************/ +/* PDU decoder */ +/**************************************************************************/ + +typedef struct { + int error; + int byte; /* next byte to decode */ + int bit; /* next bit in next byte to decode */ + char *buffer; + int size; +} rlc_pdu_decoder_t; + +void rlc_pdu_decoder_init(rlc_pdu_decoder_t *decoder, char *buffer, int size); + +#define rlc_pdu_decoder_in_error(d) ((d)->error == 1) + +int rlc_pdu_decoder_get_bits(rlc_pdu_decoder_t *decoder, int count); + +void rlc_pdu_decoder_align(rlc_pdu_decoder_t *decoder); + +/**************************************************************************/ +/* PDU encoder */ +/**************************************************************************/ + +typedef struct { + int byte; /* next byte to encode */ + int bit; /* next bit in next byte to encode */ + char *buffer; + int size; +} rlc_pdu_encoder_t; + +void rlc_pdu_encoder_init(rlc_pdu_encoder_t *encoder, char *buffer, int size); + +void rlc_pdu_encoder_put_bits(rlc_pdu_encoder_t *encoder, int value, int count); + +void rlc_pdu_encoder_align(rlc_pdu_encoder_t *encoder); + +#endif /* _RLC_PDU_H_ */ diff --git a/openair2/LAYER2/rlc_v2/rlc_sdu.c b/openair2/LAYER2/rlc_v2/rlc_sdu.c new file mode 100644 index 0000000000..16465a9ff1 --- /dev/null +++ b/openair2/LAYER2/rlc_v2/rlc_sdu.c @@ -0,0 +1,68 @@ +/* + * 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 "rlc_sdu.h" + +#include +#include + +#include "LOG/log.h" + +rlc_sdu_t *rlc_new_sdu(char *buffer, int size, int upper_layer_id) +{ + rlc_sdu_t *ret = calloc(1, sizeof(rlc_sdu_t)); + if (ret == NULL) + goto oom; + + ret->upper_layer_id = upper_layer_id; + + ret->data = malloc(size); + if (ret->data == NULL) + goto oom; + + memcpy(ret->data, buffer, size); + + ret->size = size; + + return ret; + +oom: + LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); +} + +void rlc_free_sdu(rlc_sdu_t *sdu) +{ + free(sdu->data); + free(sdu); +} + +void rlc_sdu_list_add(rlc_sdu_t **list, rlc_sdu_t **end, rlc_sdu_t *sdu) +{ + if (*list == NULL) { + *list = sdu; + *end = sdu; + return; + } + + (*end)->next = sdu; + *end = sdu; +} diff --git a/openair2/LAYER2/rlc_v2/rlc_sdu.h b/openair2/LAYER2/rlc_v2/rlc_sdu.h new file mode 100644 index 0000000000..2c678956ee --- /dev/null +++ b/openair2/LAYER2/rlc_v2/rlc_sdu.h @@ -0,0 +1,39 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef _RLC_SDU_H_ +#define _RLC_SDU_H_ + +typedef struct rlc_sdu_t { + int upper_layer_id; + char *data; + int size; + /* next_byte indicates the starting byte to use to construct a new PDU */ + int next_byte; + int acked_bytes; + struct rlc_sdu_t *next; +} rlc_sdu_t; + +rlc_sdu_t *rlc_new_sdu(char *buffer, int size, int upper_layer_id); +void rlc_free_sdu(rlc_sdu_t *sdu); +void rlc_sdu_list_add(rlc_sdu_t **list, rlc_sdu_t **end, rlc_sdu_t *sdu); + +#endif /* _RLC_SDU_H_ */ diff --git a/openair2/LAYER2/rlc_v2/rlc_ue_manager.c b/openair2/LAYER2/rlc_v2/rlc_ue_manager.c new file mode 100644 index 0000000000..1d0884bb9c --- /dev/null +++ b/openair2/LAYER2/rlc_v2/rlc_ue_manager.c @@ -0,0 +1,182 @@ +/* + * 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 "rlc_ue_manager.h" + +#include +#include +#include + +#include "LOG/log.h" + +typedef struct { + pthread_mutex_t lock; + rlc_ue_t **ue_list; + int ue_count; +} rlc_ue_manager_internal_t; + +rlc_ue_manager_t *new_rlc_ue_manager(void) +{ + rlc_ue_manager_internal_t *ret; + + ret = calloc(1, sizeof(rlc_ue_manager_internal_t)); + if (ret == NULL) { + LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + if (pthread_mutex_init(&ret->lock, NULL)) abort(); + + return ret; +} + +void rlc_manager_lock(rlc_ue_manager_t *_m) +{ + rlc_ue_manager_internal_t *m = _m; + if (pthread_mutex_lock(&m->lock)) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +void rlc_manager_unlock(rlc_ue_manager_t *_m) +{ + rlc_ue_manager_internal_t *m = _m; + if (pthread_mutex_unlock(&m->lock)) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +/* must be called with lock acquired */ +rlc_ue_t *rlc_manager_get_ue(rlc_ue_manager_t *_m, int rnti) +{ + /* TODO: optimze */ + rlc_ue_manager_internal_t *m = _m; + int i; + + for (i = 0; i < m->ue_count; i++) + if (m->ue_list[i]->rnti == rnti) + return m->ue_list[i]; + + LOG_D(RLC, "%s:%d:%s: new UE %d\n", __FILE__, __LINE__, __FUNCTION__, rnti); + + m->ue_count++; + m->ue_list = realloc(m->ue_list, sizeof(rlc_ue_t *) * m->ue_count); + if (m->ue_list == NULL) { + LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + m->ue_list[m->ue_count-1] = calloc(1, sizeof(rlc_ue_t)); + if (m->ue_list[m->ue_count-1] == NULL) { + LOG_E(RLC, "%s:%d:%s: out of memory\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + m->ue_list[m->ue_count-1]->rnti = rnti; + + return m->ue_list[m->ue_count-1]; +} + +/* must be called with lock acquired */ +void rlc_manager_remove_ue(rlc_ue_manager_t *_m, int rnti) +{ + rlc_ue_manager_internal_t *m = _m; + rlc_ue_t *ue; + int i; + int j; + + for (i = 0; i < m->ue_count; i++) + if (m->ue_list[i]->rnti == rnti) + break; + + if (i == m->ue_count) { + LOG_D(RLC, "%s:%d:%s: warning: ue %d not found\n", + __FILE__, __LINE__, __FUNCTION__, + rnti); + return; + } + + ue = m->ue_list[i]; + + for (j = 0; j < 2; j++) + if (ue->srb[j] != NULL) + ue->srb[j]->delete(ue->srb[j]); + + for (j = 0; j < 5; j++) + if (ue->drb[j] != NULL) + ue->drb[j]->delete(ue->drb[j]); + + free(ue); + + m->ue_count--; + if (m->ue_count == 0) { + free(m->ue_list); + m->ue_list = NULL; + return; + } + + memmove(&m->ue_list[i], &m->ue_list[i+1], + (m->ue_count - i) * sizeof(rlc_ue_t *)); + m->ue_list = realloc(m->ue_list, m->ue_count * sizeof(rlc_ue_t *)); + if (m->ue_list == NULL) { + LOG_E(RLC, "%s:%d:%s: fatal\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } +} + +/* must be called with lock acquired */ +void rlc_ue_add_srb_rlc_entity(rlc_ue_t *ue, int srb_id, rlc_entity_t *entity) +{ + if (srb_id < 1 || srb_id > 2) { + LOG_E(RLC, "%s:%d:%s: fatal, bad srb id\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + srb_id--; + + if (ue->srb[srb_id] != NULL) { + LOG_E(RLC, "%s:%d:%s: fatal, srb already present\n", + __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + ue->srb[srb_id] = entity; +} + +/* must be called with lock acquired */ +void rlc_ue_add_drb_rlc_entity(rlc_ue_t *ue, int drb_id, rlc_entity_t *entity) +{ + if (drb_id < 1 || drb_id > 5) { + LOG_E(RLC, "%s:%d:%s: fatal, bad drb id\n", __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + drb_id--; + + if (ue->drb[drb_id] != NULL) { + LOG_E(RLC, "%s:%d:%s: fatal, drb already present\n", + __FILE__, __LINE__, __FUNCTION__); + exit(1); + } + + ue->drb[drb_id] = entity; +} diff --git a/openair2/LAYER2/rlc_v2/rlc_ue_manager.h b/openair2/LAYER2/rlc_v2/rlc_ue_manager.h new file mode 100644 index 0000000000..7d5ef18b1e --- /dev/null +++ b/openair2/LAYER2/rlc_v2/rlc_ue_manager.h @@ -0,0 +1,58 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef _RLC_UE_MANAGER_H_ +#define _RLC_UE_MANAGER_H_ + +#include "rlc_entity.h" + +typedef void rlc_ue_manager_t; + +typedef struct rlc_ue_t { + int rnti; + /* due to openair calling status_ind/data_req, we need to keep this. + * To be considered 'hackish'. + */ + int saved_status_ind_tb_size[2+5]; + rlc_entity_t *srb[2]; + rlc_entity_t *drb[5]; +} rlc_ue_t; + +/***********************************************************************/ +/* manager functions */ +/***********************************************************************/ + +rlc_ue_manager_t *new_rlc_ue_manager(void); + +void rlc_manager_lock(rlc_ue_manager_t *m); +void rlc_manager_unlock(rlc_ue_manager_t *m); + +rlc_ue_t *rlc_manager_get_ue(rlc_ue_manager_t *m, int rnti); +void rlc_manager_remove_ue(rlc_ue_manager_t *m, int rnti); + +/***********************************************************************/ +/* ue functions */ +/***********************************************************************/ + +void rlc_ue_add_srb_rlc_entity(rlc_ue_t *ue, int srb_id, rlc_entity_t *entity); +void rlc_ue_add_drb_rlc_entity(rlc_ue_t *ue, int drb_id, rlc_entity_t *entity); + +#endif /* _RLC_UE_MANAGER_H_ */ diff --git a/openair2/LAYER2/rlc_v2/tests/LOG/log.h b/openair2/LAYER2/rlc_v2/tests/LOG/log.h new file mode 100644 index 0000000000..5c9fcd643c --- /dev/null +++ b/openair2/LAYER2/rlc_v2/tests/LOG/log.h @@ -0,0 +1,10 @@ +#ifndef _LOG_H_ +#define _LOG_H_ + +#include + +#define LOG_E(x, ...) printf(__VA_ARGS__) +#define LOG_D(x, ...) printf(__VA_ARGS__) +#define LOG_W(x, ...) printf(__VA_ARGS__) + +#endif /* _LOG_H_ */ diff --git a/openair2/LAYER2/rlc_v2/tests/Makefile b/openair2/LAYER2/rlc_v2/tests/Makefile new file mode 100644 index 0000000000..14bb186d4c --- /dev/null +++ b/openair2/LAYER2/rlc_v2/tests/Makefile @@ -0,0 +1,32 @@ +CC=gcc +CFLAGS=-Wall -g --coverage -I. + +LIB=rlc_entity.o rlc_entity_am.o rlc_entity_um.o rlc_pdu.o rlc_sdu.o + +tests: + @./run_tests.sh + +all: clean_run $(TEST).run + +%.run: $(TEST).bin + #valgrind ./$(TEST).bin > $(TEST).run_pre 2> $(TEST).valgrind + ./$(TEST).bin > $(TEST).run_pre + grep ^TEST $(TEST).run_pre > $(TEST).run + gunzip -c $(TEST).txt.gz > $(TEST).txt + diff -q $(TEST).txt $(TEST).run + +$(TEST).bin: $(TEST).o $(LIB) + $(CC) $(CFLAGS) -o $@ $^ + +%.o: ../%.c + $(CC) $(CFLAGS) -I.. -c -o $@ $< + +$(TEST).o: test.c + $(CC) $(CFLAGS) -c -o $@ $< -DTEST='"$(TEST).h"' + +clean_run: + rm -f $(TEST).run $(TEST).bin $(TEST).o + +clean: + rm -f *.o *.bin *.run *.run_pre *.gcov *.gcda *.gcno test*.txt a.out \ + *.valgrind diff --git a/openair2/LAYER2/rlc_v2/tests/README b/openair2/LAYER2/rlc_v2/tests/README new file mode 100644 index 0000000000..db69cd4fa7 --- /dev/null +++ b/openair2/LAYER2/rlc_v2/tests/README @@ -0,0 +1,38 @@ +To run tests, simply type: make + +Each test is made of: + testXX.h definition of the test + testXX.txt.gz compressed expected output of the test + +At runtime, we generate: + testXX.run actual output of the test + +test.c is the test driving program. + +Only the output lines of the test program starting with "TEST" are +stored into testXX.txt and testXX.run. + +A test is considered a success if testXX.txt and testXX.run are equal. + +Only failed tests are reported. + +How to define a new test? + +1 - get the ID + + Look in the file run_tests.sh, the variable test_count gives you + the number of existing tests. The ID of your test has to be + test_count + 1. + +2 - create files + + Create the file test.h containing the test, then generate test.run + by running 'make all TEST=test' and copy test.run to test.txt. + Then compress this file (gzip -9 test.txt). Be sure that the output + is correct, of course. + + For the file names, replace by the actual number of the test. + For example, if your test ID is 47, then name the files test47.h and + test47.txt. And run 'make all TEST=test47' to generate test47.run. + +The available instructions for a test are described at the top of test.c. diff --git a/openair2/LAYER2/rlc_v2/tests/make_pdu.c b/openair2/LAYER2/rlc_v2/tests/make_pdu.c new file mode 100644 index 0000000000..057cc3e36d --- /dev/null +++ b/openair2/LAYER2/rlc_v2/tests/make_pdu.c @@ -0,0 +1,29 @@ +/* gcc -Wall make_pdu.c -I.. ../rlc_pdu.c */ + +#include "rlc_pdu.h" +#include + +int main(void) +{ + char out[100]; + rlc_pdu_encoder_t e; + int i; + + rlc_pdu_encoder_init(&e, out, 100); + + rlc_pdu_encoder_put_bits(&e, 0, 1); // D/C + rlc_pdu_encoder_put_bits(&e, 0, 3); // CPT + rlc_pdu_encoder_put_bits(&e, 0, 10); // ack_sn + rlc_pdu_encoder_put_bits(&e, 1, 1); // e1 + rlc_pdu_encoder_put_bits(&e, 10, 10); // nack_sn + rlc_pdu_encoder_put_bits(&e, 0, 1); // e1 + rlc_pdu_encoder_put_bits(&e, 0, 1); // e2 + + rlc_pdu_encoder_align(&e); + + for (i = 0; i < e.byte; i++) printf(" %2.2x", (unsigned char)e.buffer[i]); + + printf("\n"); + + return 0; +} diff --git a/openair2/LAYER2/rlc_v2/tests/run_tests.sh b/openair2/LAYER2/rlc_v2/tests/run_tests.sh new file mode 100755 index 0000000000..72feff0036 --- /dev/null +++ b/openair2/LAYER2/rlc_v2/tests/run_tests.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +test_count=45 + +for i in `seq $test_count` +do + make all TEST=test$i >/dev/null 2>/dev/null + if [ $? != 0 ] + then + echo TEST $i FAILURE + fi +done diff --git a/openair2/LAYER2/rlc_v2/tests/test.c b/openair2/LAYER2/rlc_v2/tests/test.c new file mode 100644 index 0000000000..734e85f1f5 --- /dev/null +++ b/openair2/LAYER2/rlc_v2/tests/test.c @@ -0,0 +1,433 @@ +#include "../rlc_entity.h" +#include "../rlc_entity_am.h" +#include "../rlc_entity_um.h" + +#include +#include +#include +#include +#include +#include + +/* + * ENB_AM + * + * create the eNB RLC AM entity with given parameters + * + * UE_AM + * + * create the UE RLC AM entity with given parameters + * + * ENB_UM + * create the eNB RLC UM entity with given parameters + * + * UE_UM + * create the UE RLC UM entity with given parameters + * + * TIME
\n') self.htmlFile.write('

\n') self.htmlFile.write(' \n') - # GP machines = [ 'eNB', 'UE' ] - # GP for machine in machines: - #GP This needs to move back to main and be called before CreateHtmlFooter - - res = self.reseNB - if res != -1: + machines = [ 'eNB', 'UE' ] + for machine in machines: + if machine == 'eNB': + idx = 0 + else: + idx = 1 + if self.OsVersion[idx] == '': + continue + self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') - self.htmlFile.write(' \n') + self.htmlFile.write(' \n') self.htmlFile.write(' \n') - self.htmlFile.write(' \n') + self.htmlFile.write(' \n') self.htmlFile.write(' \n') - self.htmlFile.write(' \n') + self.htmlFile.write(' \n') self.htmlFile.write(' \n') - self.htmlFile.write(' \n') + self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') - self.htmlFile.write(' \n') + self.htmlFile.write(' \n') self.htmlFile.write(' \n') - self.htmlFile.write(' \n') + self.htmlFile.write(' \n') self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - - - res = self.resUE - if res != -1: - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') - self.htmlFile.write(' \n') + self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') self.htmlFile.write(' \n') diff --git a/ci-scripts/main.py b/ci-scripts/main.py index e7601f556d..595a984bbe 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -94,13 +94,6 @@ class OaiCiTest(): self.x2ENBConnectedUEs = [] self.repeatCounts = [] self.finalStatus = False - self.OsVersion = '' - self.KernelVersion = '' - self.UhdVersion = '' - self.UsrpBoard = '' - self.CpuNb = '' - self.CpuModel = '' - self.CpuMHz = '' self.UEIPAddress = '' self.UEUserName = '' self.UEPassword = '' @@ -2747,26 +2740,26 @@ class OaiCiTest(): def AutoTerminateUEandeNB(self): if (self.ADBIPAddress != 'none'): self.testCase_id = 'AUTO-KILL-UE' - RAN.SettestCase_id(self.testCase_id) + HTML.SettestCase_id(self.testCase_id) self.desc = 'Automatic Termination of UE' self.ShowTestID() self.TerminateUE() if (self.Initialize_OAI_UE_args != ''): self.testCase_id = 'AUTO-KILL-UE' - RAN.SettestCase_id(self.testCase_id) + HTML.SettestCase_id(self.testCase_id) self.desc = 'Automatic Termination of UE' self.ShowTestID() self.TerminateOAIUE() if (RAN.GetInitialize_eNB_args() != ''): self.testCase_id = 'AUTO-KILL-eNB' - RAN.SettestCase_id(self.testCase_id) + HTML.SettestCase_id(self.testCase_id) self.desc = 'Automatic Termination of eNB' self.ShowTestID() RAN.SeteNB_instance('0') RAN.TerminateeNB() if RAN.GetflexranCtrlInstalled() and RAN.GetflexranCtrlStarted(): self.testCase_id = 'AUTO-KILL-flexran-ctl' - RAN.SettestCase_id(self.testCase_id) + HTML.SettestCase_id(self.testCase_id) self.desc = 'Automatic Termination of FlexRan CTL' self.ShowTestID() self.TerminateFlexranCtrl() @@ -2934,19 +2927,20 @@ class OaiCiTest(): def RetrieveSystemVersion(self, machine): if RAN.GeteNBIPAddress() == 'none' or self.UEIPAddress == 'none': - self.OsVersion = 'Ubuntu 16.04.5 LTS' - self.KernelVersion = '4.15.0-45-generic' - self.UhdVersion = '3.13.0.1-0' - self.UsrpBoard = 'B210' - self.CpuNb = '4' - self.CpuModel = 'Intel(R) Core(TM) i5-6200U' - self.CpuMHz = '2399.996 MHz' + HTML.SetOsVersion('Ubuntu 16.04.5 LTS', 0) + HTML.SetKernelVersion('4.15.0-45-generic', 0) + HTML.SetUhdVersion('3.13.0.1-0', 0) + HTML.SetUsrpBoard('B210', 0) + HTML.SetCpuNb('4', 0) + HTML.SetCpuModel('Intel(R) Core(TM) i5-6200U', 0) + HTML.SetCpuMHz('2399.996 MHz', 0) return 0 if machine == 'eNB': if RAN.GeteNBIPAddress() != '' and RAN.GeteNBUserName() != '' and RAN.GeteNBPassword() != '': IPAddress = RAN.GeteNBIPAddress() UserName = RAN.GeteNBUserName() Password = RAN.GeteNBPassword() + idx = 0 else: return -1 if machine == 'UE': @@ -2954,6 +2948,7 @@ class OaiCiTest(): IPAddress = self.UEIPAddress UserName = self.UEUserName Password = self.UEPassword + idx = 1 else: return -1 @@ -2961,55 +2956,64 @@ class OaiCiTest(): SSH.command('lsb_release -a', '\$', 5) result = re.search('Description:\\\\t(?P[a-zA-Z0-9\-\_\.\ ]+)', SSH.getBefore()) if result is not None: - self.OsVersion = result.group('os_type') - logging.debug('OS is: ' + self.OsVersion) + OsVersion = result.group('os_type') + logging.debug('OS is: ' + OsVersion) + HTML.SetOsVersion(OsVersion, idx) else: SSH.command('hostnamectl', '\$', 5) result = re.search('Operating System: (?P[a-zA-Z0-9\-\_\.\ ]+)', SSH.getBefore()) if result is not None: - self.OsVersion = result.group('os_type') - if self.OsVersion == 'CentOS Linux 7 ': + OsVersion = result.group('os_type') + if OsVersion == 'CentOS Linux 7 ': SSH.command('cat /etc/redhat-release', '\$', 5) result = re.search('CentOS Linux release (?P[0-9\.]+)', SSH.getBefore()) if result is not None: - self.OsVersion = self.OsVersion.replace('7 ', result.group('os_version')) - logging.debug('OS is: ' + self.OsVersion) + OsVersion = OsVersion.replace('7 ', result.group('os_version')) + logging.debug('OS is: ' + OsVersion) + HTML.SetOsVersion(OsVersion, idx) SSH.command('uname -r', '\$', 5) result = re.search('uname -r\\\\r\\\\n(?P[a-zA-Z0-9\-\_\.]+)', SSH.getBefore()) if result is not None: - self.KernelVersion = result.group('kernel_version') - logging.debug('Kernel Version is: ' + self.KernelVersion) + KernelVersion = result.group('kernel_version') + logging.debug('Kernel Version is: ' + KernelVersion) + HTML.SetKernelVersion(KernelVersion, idx) SSH.command('dpkg --list | egrep --color=never libuhd003', '\$', 5) result = re.search('libuhd003:amd64 *(?P[0-9\.]+)', SSH.getBefore()) if result is not None: - self.UhdVersion = result.group('uhd_version') - logging.debug('UHD Version is: ' + self.UhdVersion) + UhdVersion = result.group('uhd_version') + logging.debug('UHD Version is: ' + UhdVersion) + HTML.SetUhdVersion(UhdVersion, idx) else: SSH.command('uhd_config_info --version', '\$', 5) result = re.search('UHD (?P[a-zA-Z0-9\.\-]+)', SSH.getBefore()) if result is not None: - self.UhdVersion = result.group('uhd_version') - logging.debug('UHD Version is: ' + self.UhdVersion) + UhdVersion = result.group('uhd_version') + logging.debug('UHD Version is: ' + UhdVersion) + HTML.SetUhdVersion(UhdVersion, idx) SSH.command('echo ' + Password + ' | sudo -S uhd_find_devices', '\$', 60) usrp_boards = re.findall('product: ([0-9A-Za-z]+)\\\\r\\\\n', SSH.getBefore()) count = 0 for board in usrp_boards: if count == 0: - self.UsrpBoard = board + UsrpBoard = board else: - self.UsrpBoard += ',' + board + UsrpBoard += ',' + board count += 1 if count > 0: - logging.debug('USRP Board(s) : ' + self.UsrpBoard) + logging.debug('USRP Board(s) : ' + UsrpBoard) + HTML.SetUsrpBoard(UsrpBoard, idx) SSH.command('lscpu', '\$', 5) result = re.search('CPU\(s\): *(?P[0-9]+).*Model name: *(?P[a-zA-Z0-9\-\_\.\ \(\)]+).*CPU MHz: *(?P[0-9\.]+)', SSH.getBefore()) if result is not None: - self.CpuNb = result.group('nb_cpus') - logging.debug('nb_cpus: ' + self.CpuNb) - self.CpuModel = result.group('model') - logging.debug('model: ' + self.CpuModel) - self.CpuMHz = result.group('cpu_mhz') + ' MHz' - logging.debug('cpu_mhz: ' + self.CpuMHz) + CpuNb = result.group('nb_cpus') + logging.debug('nb_cpus: ' + CpuNb) + HTML.SetCpuNb(CpuNb, idx) + CpuModel = result.group('model') + logging.debug('model: ' + CpuModel) + HTML.SetCpuModel(CpuModel, idx) + CpuMHz = result.group('cpu_mhz') + ' MHz' + logging.debug('cpu_mhz: ' + CpuMHz) + HTML.SetCpuMHz(CpuMHz, idx) SSH.close() #----------------------------------------------------------- @@ -3199,6 +3203,8 @@ RAN = ran.RANManagement() HTML = html.HTMLManagement() EPC.SetHtmlObj(HTML) +RAN.SetHtmlObj(HTML) +RAN.SetEpcObj(EPC) argvs = sys.argv argc = len(argvs) @@ -3293,19 +3299,15 @@ while len(argvs) > 1: elif re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCIPAddress=(.+)$', myArgv, re.IGNORECASE) EPC.SetIPAddress(matchReg.group(1)) - RAN.SetIPAddress(matchReg.group(1)) elif re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCUserName=(.+)$', myArgv, re.IGNORECASE) EPC.SetUserName(matchReg.group(1)) - RAN.SetUserName(matchReg.group(1)) elif re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCPassword=(.+)$', myArgv, re.IGNORECASE) EPC.SetPassword(matchReg.group(1)) - RAN.SetPassword(matchReg.group(1)) elif re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCSourceCodePath=(.+)$', myArgv, re.IGNORECASE) EPC.SetSourceCodePath(matchReg.group(1)) - RAN.SetSourceCodePath(matchReg.group(1)) elif re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-EPCType=(.+)$', myArgv, re.IGNORECASE) if re.match('OAI', matchReg.group(1), re.IGNORECASE) or re.match('ltebox', matchReg.group(1), re.IGNORECASE) or re.match('OAI-Rel14-CUPS', matchReg.group(1), re.IGNORECASE): @@ -3466,8 +3468,12 @@ elif re.match('^InitiateHtml$', mode, re.IGNORECASE): HTML.SethtmlNb_CATM_Modules(len(CiTestObj.CatMDevices)) HTML.CreateHtmlHeader(CiTestObj.ADBIPAddress) elif re.match('^FinalizeHtml$', mode, re.IGNORECASE): - HTML.SetreseNB(RetrieveSystemVersion('eNB')) - HTML.SetresUE(RetrieveSystemVersion('UE')) + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + logging.debug('\u001B[1m Creating HTML footer \u001B[0m') + logging.debug('\u001B[1m----------------------------------------\u001B[0m') + + CiTestObj.RetrieveSystemVersion('eNB') + CiTestObj.RetrieveSystemVersion('UE') HTML.CreateHtmlFooter(CiTestObj.finalStatus) elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re.IGNORECASE): if re.match('^TesteNB$', mode, re.IGNORECASE): @@ -3575,7 +3581,6 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re if test_case_id != id: continue CiTestObj.testCase_id = id - RAN.SettestCase_id(CiTestObj.testCase_id) HTML.SettestCase_id(CiTestObj.testCase_id) CiTestObj.desc = test.findtext('desc') HTML.Setdesc(CiTestObj.desc) diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py index e390b6aecb..f03cb6413c 100644 --- a/ci-scripts/ran.py +++ b/ci-scripts/ran.py @@ -46,10 +46,7 @@ import sshconnection as SSH import epc import helpreadme as HELP import constants as CONST -import html as HTML - -EPC = epc.EPCManagement() - +import html #----------------------------------------------------------- # Class Declaration @@ -90,23 +87,19 @@ class RANManagement(): self.eNBstatuses = [-1, -1, -1] self.flexranCtrlInstalled = False self.flexranCtrlStarted = False + self.epcPcapFile = '' + self.htmlObj = None + self.epcObj = None #----------------------------------------------------------- -# Setters and Getters +# Setters and Getters on Public members #----------------------------------------------------------- - def SetIPAddress(self, ipaddress): - self.EPCIPAddress = ipaddress - def SetUserName(self, username): - self.EPCUserName = username - def SetPassword(self, password): - self.EPCPassword = password - def SetSourceCodePath(self, sourcecodepath): - self.EPCSourceCodePath = sourcecodepath + def SetHtmlObj(self, obj): + self.htmlObj = obj + def SetEpcObj(self, obj): + self.epcObj = obj - - def SettestCase_id(self,tcid): - self.testCase_id = tcid def SetflexranCtrlInstalled(self,fxrctin): self.flexranCtrlInstalled = fxrctin def GetflexranCtrlInstalled(self): @@ -242,7 +235,6 @@ class RANManagement(): def BuildeNB(self): - myHTML = HTML.HTMLManagement() if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': GenericHelp(Version) sys.exit('Insufficient Parameter') @@ -315,7 +307,8 @@ class RANManagement(): mismatch = True if not mismatch: mySSH.close() - myHTML.CreateHtmlTestRow(self.Build_eNB_args, 'OK', CONST.ALL_PROCESSES_OK) + if self.htmlObj is not None: + self.htmlObj.CreateHtmlTestRow(self.Build_eNB_args, 'OK', CONST.ALL_PROCESSES_OK) return mySSH.command('echo ' + lPassWord + ' | sudo -S git clean -x -d -ff', '\$', 30) @@ -341,12 +334,17 @@ class RANManagement(): mySSH.command('chmod 775 ./my-lte-softmodem-build.sh', '\$', 5) mySSH.command('echo ' + lPassWord + ' | sudo -S -E daemon --inherit --unsafe --name=build_enb_daemon --chdir=' + lSourcePath + '/cmake_targets -o ' + lSourcePath + '/cmake_targets/compile_oai_enb.log ./my-lte-softmodem-build.sh', '\$', 5) mySSH.close() - myHTML.CreateHtmlTestRow(self.Build_eNB_args, 'OK', CONST.ALL_PROCESSES_OK) - self.backgroundBuildTestId[int(self.eNB_instance)] = self.testCase_id + if self.htmlObj is not None: + self.htmlObj.CreateHtmlTestRow(self.Build_eNB_args, 'OK', CONST.ALL_PROCESSES_OK) + self.backgroundBuildTestId[int(self.eNB_instance)] = self.htmlObj.GettestCase_id() return mySSH.command('stdbuf -o0 ./build_oai ' + self.Build_eNB_args + ' 2>&1 | stdbuf -o0 tee compile_oai_enb.log', 'Bypassing the Tests|build have failed', 1500) mySSH.close() - self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.testCase_id) + if self.htmlObj is not None: + tId = self.htmlObj.GettestCase_id() + else: + tId = '0000' + self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, tId) @@ -385,8 +383,8 @@ class RANManagement(): self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.backgroundBuildTestId[int(self.eNB_instance)]) def checkBuildeNB(self, lIpAddr, lUserName, lPassWord, lSourcePath, testcaseId): - myHTML = HTML.HTMLManagement() - myHTML.SettestCase_id(testcaseId) + if self.htmlObj is not None: + self.htmlObj.SettestCase_id(testcaseId) mySSH = SSH.SSHConnection() mySSH.open(lIpAddr, lUserName, lPassWord) mySSH.command('cd ' + lSourcePath + '/cmake_targets', '\$', 3) @@ -436,16 +434,17 @@ class RANManagement(): if buildStatus: logging.info('\u001B[1m Building OAI ' + nodeB_prefix + 'NB Pass\u001B[0m') - myHTML.CreateHtmlTestRow(self.Build_eNB_args, 'OK', CONST.ALL_PROCESSES_OK) + if self.htmlObj is not None: + self.htmlObj.CreateHtmlTestRow(self.Build_eNB_args, 'OK', CONST.ALL_PROCESSES_OK) else: logging.error('\u001B[1m Building OAI ' + nodeB_prefix + 'NB Failed\u001B[0m') - myHTML.CreateHtmlTestRow(self.Build_eNB_args, 'KO', CONST.ALL_PROCESSES_OK) - myHTML.CreateHtmlTabFooter(False) + if self.htmlObj is not None: + self.htmlObj.CreateHtmlTestRow(self.Build_eNB_args, 'KO', CONST.ALL_PROCESSES_OK) + self.htmlObj.CreateHtmlTabFooter(False) sys.exit(1) def InitializeeNB(self): - myHTML = HTML.HTMLManagement() if self.eNB_serverId == '0': lIpAddr = self.eNBIPAddress lUserName = self.eNBUserName @@ -467,21 +466,25 @@ class RANManagement(): mySSH = SSH.SSHConnection() if (self.pStatus < 0): - myHTML.CreateHtmlTestRow(self.Initialize_eNB_args, 'KO', self.pStatus) - myHTML.CreateHtmlTabFooter(False) + if self.htmlObj is not None: + self.htmlObj.CreateHtmlTestRow(self.Initialize_eNB_args, 'KO', self.pStatus) + self.htmlObj.CreateHtmlTabFooter(False) sys.exit(1) # If tracer options is on, running tshark on EPC side and capture traffic b/ EPC and eNB result = re.search('T_stdout', str(self.Initialize_eNB_args)) - if result is not None: - mySSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + if (result is not None) and (self.epcObj is not None): + localEpcIpAddr = self.epcObj.GetIPAddress() + localEpcUserName = self.epcObj.GetUserName() + localEpcPassword = self.epcObj.GetPassword() + mySSH.open(localEpcIpAddr, localEpcUserName, localEpcPassword) mySSH.command('ip addr show | awk -f /tmp/active_net_interfaces.awk | egrep -v "lo|tun"', '\$', 5) result = re.search('interfaceToUse=(?P[a-zA-Z0-9\-\_]+)done', mySSH.getBefore()) if result is not None: eth_interface = result.group('eth_interface') logging.debug('\u001B[1m Launching tshark on interface ' + eth_interface + '\u001B[0m') - EPC.Set_PcapFileName('enb_' + self.testCase_id + '_s1log.pcap') - mySSH.command('echo ' + self.EPCPassword + ' | sudo -S rm -f /tmp/' + EPC.Get_PcapFileName() , '\$', 5) - mySSH.command('echo $USER; nohup sudo tshark -f "host ' + lIpAddr +'" -i ' + eth_interface + ' -w /tmp/' + EPC.Get_PcapFileName() + ' > /tmp/tshark.log 2>&1 &', self.EPCUserName, 5) + self.epcPcapFile = 'enb_' + self.testCase_id + '_s1log.pcap' + mySSH.command('echo ' + localEpcPassword + ' | sudo -S rm -f /tmp/' + self.epcPcapFile , '\$', 5) + mySSH.command('echo $USER; nohup sudo tshark -f "host ' + lIpAddr +'" -i ' + eth_interface + ' -w /tmp/' + self.epcPcapFile + ' > /tmp/tshark.log 2>&1 &', localEpcUserName, 5) mySSH.close() mySSH.open(lIpAddr, lUserName, lPassWord) mySSH.command('cd ' + lSourcePath, '\$', 5) @@ -520,7 +523,9 @@ class RANManagement(): mySSH.command('echo ' + lPassWord + ' | sudo -S uhd_find_devices', '\$', 60) # Make a copy and adapt to EPC / eNB IP addresses mySSH.command('cp ' + full_config_file + ' ' + ci_full_config_file, '\$', 5) - mySSH.command('sed -i -e \'s/CI_MME_IP_ADDR/' + self.EPCIPAddress + '/\' ' + ci_full_config_file, '\$', 2); + if self.epcObj is not None: + localEpcIpAddr = self.epcObj.GetIPAddress() + mySSH.command('sed -i -e \'s/CI_MME_IP_ADDR/' + localEpcIpAddr + '/\' ' + ci_full_config_file, '\$', 2); mySSH.command('sed -i -e \'s/CI_ENB_IP_ADDR/' + lIpAddr + '/\' ' + ci_full_config_file, '\$', 2); mySSH.command('sed -i -e \'s/CI_RCC_IP_ADDR/' + self.eNBIPAddress + '/\' ' + ci_full_config_file, '\$', 2); mySSH.command('sed -i -e \'s/CI_RRU1_IP_ADDR/' + self.eNB1IPAddress + '/\' ' + ci_full_config_file, '\$', 2); @@ -569,22 +574,26 @@ class RANManagement(): mySSH.close() doLoop = False logging.error('\u001B[1;37;41m eNB logging system did not show got sync! \u001B[0m') - myHTML.CreateHtmlTestRow('-O ' + config_file + extra_options, 'KO', CONST.ALL_PROCESSES_OK) + if self.htmlObj is not None: + self.htmlObj.CreateHtmlTestRow('-O ' + config_file + extra_options, 'KO', CONST.ALL_PROCESSES_OK) # In case of T tracer recording, we need to kill tshark on EPC side result = re.search('T_stdout', str(self.Initialize_eNB_args)) - if result is not None: - mySSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + if (result is not None) and (self.epcObj is not None): + localEpcIpAddr = self.epcObj.GetIPAddress() + localEpcUserName = self.epcObj.GetUserName() + localEpcPassword = self.epcObj.GetPassword() + mySSH.open(localEpcIpAddr, localEpcUserName, localEpcPassword) logging.debug('\u001B[1m Stopping tshark \u001B[0m') - mySSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) - if EPC.Get_PcapFileName() != '': + mySSH.command('echo ' + localEpcPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) + if self.epcPcapFile != '': time.sleep(0.5) - mySSH.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 /tmp/' + EPC.Get_PcapFileName() , '\$', 5) + mySSH.command('echo ' + localEpcPassword + ' | sudo -S chmod 666 /tmp/' + self.epcPcapFile, '\$', 5) mySSH.close() time.sleep(1) - if EPC.Get_PcapFileName() != '': - copyin_res = mySSH.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + EPC.Get_PcapFileName() , '.') + if self.epcPcapFile != '': + copyin_res = mySSH.copyin(localEpcIpAddr, localEpcUserName, localEpcPassword, '/tmp/' + self.epcPcapFile, '.') if (copyin_res == 0): - mySSH.copyout(lIpAddr, lUserName, lPassWord, EPC.Get_PcapFileName() , lSourcePath + '/cmake_targets/.') + mySSH.copyout(lIpAddr, lUserName, lPassWord, self.epcPcapFile, lSourcePath + '/cmake_targets/.') self.prematureExit = True return else: @@ -619,7 +628,8 @@ class RANManagement(): self.eNBstatuses[int(self.eNB_instance)] = int(self.eNB_serverId) mySSH.close() - myHTML.CreateHtmlTestRow('-O ' + config_file + extra_options, 'OK', CONST.ALL_PROCESSES_OK) + if self.htmlObj is not None: + self.htmlObj.CreateHtmlTestRow('-O ' + config_file + extra_options, 'OK', CONST.ALL_PROCESSES_OK) logging.debug('\u001B[1m Initialize eNB Completed\u001B[0m') @@ -659,7 +669,6 @@ class RANManagement(): def TerminateeNB(self): - myHTML = HTML.HTMLManagement() if self.eNB_serverId == '0': lIpAddr = self.eNBIPAddress lUserName = self.eNBUserName @@ -700,15 +709,18 @@ class RANManagement(): mySSH.close() # If tracer options is on, stopping tshark on EPC side result = re.search('T_stdout', str(self.Initialize_eNB_args)) - if result is not None: - mySSH.open(self.EPCIPAddress, self.EPCUserName, self.EPCPassword) + if (result is not None) and (self.epcObj is not None): + localEpcIpAddr = self.epcObj.GetIPAddress() + localEpcUserName = self.epcObj.GetUserName() + localEpcPassword = self.epcObj.GetPassword() + mySSH.open(localEpcIpAddr, localEpcUserName, localEpcPassword) logging.debug('\u001B[1m Stopping tshark \u001B[0m') - mySSH.command('echo ' + self.EPCPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) + mySSH.command('echo ' + localEpcPassword + ' | sudo -S killall --signal SIGKILL tshark', '\$', 5) time.sleep(1) - if EPC.Get_PcapFileName() != '': - mySSH.command('echo ' + self.EPCPassword + ' | sudo -S chmod 666 /tmp/' + EPC.Get_PcapFileName() , '\$', 5) - mySSH.copyin(self.EPCIPAddress, self.EPCUserName, self.EPCPassword, '/tmp/' + EPC.Get_PcapFileName() , '.') - mySSH.copyout(lIpAddr, lUserName, lPassWord, EPC.Get_PcapFileName() , lSourcePath + '/cmake_targets/.') + if self.epcPcapFile != '': + mySSH.command('echo ' + localEpcPassword + ' | sudo -S chmod 666 /tmp/' + self.epcPcapFile, '\$', 5) + mySSH.copyin(localEpcIpAddr, localEpcUserName, localEpcPassword, '/tmp/' + self.epcPcapFile, '.') + mySSH.copyout(lIpAddr, lUserName, lPassWord, self.epcPcapFile, lSourcePath + '/cmake_targets/.') mySSH.close() logging.debug('\u001B[1m Replaying RAW record file\u001B[0m') mySSH.open(lIpAddr, lUserName, lPassWord) @@ -725,7 +737,8 @@ class RANManagement(): mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + extracted_log_file, '.') logging.debug('\u001B[1m Analyzing eNB replay logfile \u001B[0m') logStatus = self.AnalyzeLogFile_eNB(extracted_log_file) - myHTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + if self.htmlObj is not None: + self.htmlObj.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) self.eNBLogFiles[int(self.eNB_instance)] = '' else: analyzeFile = False @@ -738,7 +751,8 @@ class RANManagement(): if (copyin_res == -1): logging.debug('\u001B[1;37;41m Could not copy ' + nodeB_prefix + 'NB logfile to analyze it! \u001B[0m') self.htmleNBFailureMsg = 'Could not copy ' + nodeB_prefix + 'NB logfile to analyze it!' - myHTML.CreateHtmlTestRow('N/A', 'KO', CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE) + if self.htmlObj is not None: + self.htmlObj.CreateHtmlTestRow('N/A', 'KO', CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE) self.eNBmbmsEnables[int(self.eNB_instance)] = False return if self.eNB_serverId != '0': @@ -746,14 +760,17 @@ class RANManagement(): logging.debug('\u001B[1m Analyzing ' + nodeB_prefix + 'NB logfile \u001B[0m ' + fileToAnalyze) logStatus = self.AnalyzeLogFile_eNB(fileToAnalyze) if (logStatus < 0): - myHTML.CreateHtmlTestRow('N/A', 'KO', logStatus) + if self.htmlObj is not None: + self.htmlObj.CreateHtmlTestRow('N/A', 'KO', logStatus) self.preamtureExit = True self.eNBmbmsEnables[int(self.eNB_instance)] = False return else: - myHTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + if self.htmlObj is not None: + self.htmlObj.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) else: - myHTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) + if self.htmlObj is not None: + self.htmlObj.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) self.eNBmbmsEnables[int(self.eNB_instance)] = False self.eNBstatuses[int(self.eNB_instance)] = -1 From ea376b1eb259c8a43aad3674239fcbc330c92f0b Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Tue, 21 Apr 2020 16:36:43 +0200 Subject: [PATCH 182/240] CI: fix eNB log analysis Signed-off-by: Raphael Defosseux --- ci-scripts/html.py | 2 ++ ci-scripts/ran.py | 81 +++++++++++++++++++++++++++------------------- 2 files changed, 49 insertions(+), 34 deletions(-) diff --git a/ci-scripts/html.py b/ci-scripts/html.py index 9d78ced991..6daf36a314 100644 --- a/ci-scripts/html.py +++ b/ci-scripts/html.py @@ -84,6 +84,8 @@ class HTMLManagement(): self.htmlUEFailureMsg = huefa def GethtmlUEFailureMsg(self): return self.htmlUEFailureMsg + def SetHmleNBFailureMsg(self, msg): + self.htmleNBFailureMsg = msg def SetreseNB(self,rsenb): self.reseNB = rsenb diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py index f03cb6413c..7efe96dc2e 100644 --- a/ci-scripts/ran.py +++ b/ci-scripts/ran.py @@ -87,6 +87,7 @@ class RANManagement(): self.eNBstatuses = [-1, -1, -1] self.flexranCtrlInstalled = False self.flexranCtrlStarted = False + self.testCase_id = '' self.epcPcapFile = '' self.htmlObj = None self.epcObj = None @@ -267,6 +268,10 @@ class RANManagement(): # Worakround for some servers, we need to erase completely the workspace if self.Build_eNB_forced_workspace_cleanup: mySSH.command('echo ' + lPassWord + ' | sudo -S rm -Rf ' + lSourcePath, '\$', 15) + if self.htmlObj is not None: + self.testCase_id = self.htmlObj.GettestCase_id() + else: + self.testCase_id = '000000' # on RedHat/CentOS .git extension is mandatory result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository) if result is not None: @@ -336,15 +341,11 @@ class RANManagement(): mySSH.close() if self.htmlObj is not None: self.htmlObj.CreateHtmlTestRow(self.Build_eNB_args, 'OK', CONST.ALL_PROCESSES_OK) - self.backgroundBuildTestId[int(self.eNB_instance)] = self.htmlObj.GettestCase_id() + self.backgroundBuildTestId[int(self.eNB_instance)] = self.testCase_id return mySSH.command('stdbuf -o0 ./build_oai ' + self.Build_eNB_args + ' 2>&1 | stdbuf -o0 tee compile_oai_enb.log', 'Bypassing the Tests|build have failed', 1500) mySSH.close() - if self.htmlObj is not None: - tId = self.htmlObj.GettestCase_id() - else: - tId = '0000' - self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, tId) + self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.testCase_id) @@ -463,6 +464,11 @@ class RANManagement(): if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': GenericHelp(Version) sys.exit('Insufficient Parameter') + + if self.htmlObj is not None: + self.testCase_id = self.htmlObj.GettestCase_id() + else: + self.testCase_id = '000000' mySSH = SSH.SSHConnection() if (self.pStatus < 0): @@ -750,8 +756,8 @@ class RANManagement(): copyin_res = mySSH.copyin(lIpAddr, lUserName, lPassWord, lSourcePath + '/cmake_targets/' + fileToAnalyze, '.') if (copyin_res == -1): logging.debug('\u001B[1;37;41m Could not copy ' + nodeB_prefix + 'NB logfile to analyze it! \u001B[0m') - self.htmleNBFailureMsg = 'Could not copy ' + nodeB_prefix + 'NB logfile to analyze it!' if self.htmlObj is not None: + self.htmlObj.SetHmleNBFailureMsg('Could not copy ' + nodeB_prefix + 'NB logfile to analyze it!') self.htmlObj.CreateHtmlTestRow('N/A', 'KO', CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE) self.eNBmbmsEnables[int(self.eNB_instance)] = False return @@ -811,7 +817,7 @@ class RANManagement(): cdrxActivationMessageCount = 0 dropNotEnoughRBs = 0 mbmsRequestMsg = 0 - self.htmleNBFailureMsg = '' + htmleNBFailureMsg = '' isRRU = False isSlave = False slaveReceivesFrameResyncCmd = False @@ -852,9 +858,9 @@ class RANManagement(): requested_option = int(res1.group('requested_option')) applied_option = int(res2.group('applied_option')) if requested_option == applied_option: - self.htmleNBFailureMsg += ' Command line option(s) correctly applied ' + self.eNBOptions[int(self.eNB_instance)] + '\n\n' + htmleNBFailureMsg += ' Command line option(s) correctly applied ' + self.eNBOptions[int(self.eNB_instance)] + '\n\n' else: - self.htmleNBFailureMsg += ' Command line option(s) NOT applied ' + self.eNBOptions[int(self.eNB_instance)] + '\n\n' + htmleNBFailureMsg += ' Command line option(s) NOT applied ' + self.eNBOptions[int(self.eNB_instance)] + '\n\n' result = re.search('Exiting OAI softmodem', str(line)) if result is not None: exitSignalReceived = True @@ -935,7 +941,6 @@ class RANManagement(): mbmsRequestMsg += 1 enb_log_file.close() logging.debug(' File analysis completed') - self.htmleNBFailureMsg = '' if self.air_interface == 'lte': nodeB_prefix = 'e' else: @@ -943,101 +948,109 @@ class RANManagement(): if uciStatMsgCount > 0: statMsg = nodeB_prefix + 'NB showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmleNBFailureMsg += statMsg + '\n' + htmleNBFailureMsg += statMsg + '\n' if pdcpFailure > 0: statMsg = nodeB_prefix + 'NB showed ' + str(pdcpFailure) + ' "PDCP Out of Resources" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmleNBFailureMsg += statMsg + '\n' + htmleNBFailureMsg += statMsg + '\n' if ulschFailure > 0: statMsg = nodeB_prefix + 'NB showed ' + str(ulschFailure) + ' "ULSCH in error in round" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') - self.htmleNBFailureMsg += statMsg + '\n' + 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' + htmleNBFailureMsg += statMsg + '\n' if rrcSetupComplete > 0: rrcMsg = nodeB_prefix + 'NB completed ' + str(rrcSetupComplete) + ' RRC Connection Setup(s)' logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' + htmleNBFailureMsg += rrcMsg + '\n' rrcMsg = ' -- ' + str(rrcSetupComplete) + ' were completed' logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' + htmleNBFailureMsg += rrcMsg + '\n' if rrcReleaseRequest > 0: rrcMsg = nodeB_prefix + 'NB requested ' + str(rrcReleaseRequest) + ' RRC Connection Release(s)' logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' + htmleNBFailureMsg += rrcMsg + '\n' if rrcReconfigRequest > 0 or rrcReconfigComplete > 0: rrcMsg = nodeB_prefix + 'NB requested ' + str(rrcReconfigRequest) + ' RRC Connection Reconfiguration(s)' logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' + htmleNBFailureMsg += rrcMsg + '\n' rrcMsg = ' -- ' + str(rrcReconfigComplete) + ' were completed' logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' + htmleNBFailureMsg += rrcMsg + '\n' if rrcReestablishRequest > 0 or rrcReestablishComplete > 0 or rrcReestablishReject > 0: rrcMsg = nodeB_prefix + 'NB requested ' + str(rrcReestablishRequest) + ' RRC Connection Reestablishment(s)' logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' + htmleNBFailureMsg += rrcMsg + '\n' rrcMsg = ' -- ' + str(rrcReestablishComplete) + ' were completed' logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' + htmleNBFailureMsg += rrcMsg + '\n' rrcMsg = ' -- ' + str(rrcReestablishReject) + ' were rejected' logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' + htmleNBFailureMsg += rrcMsg + '\n' if self.eNBmbmsEnables[int(self.eNB_instance)]: if mbmsRequestMsg > 0: rrcMsg = 'eNB requested ' + str(mbmsRequestMsg) + ' times the RLC for MBMS USER-PLANE' logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' + htmleNBFailureMsg += rrcMsg + '\n' if X2HO_inNbProcedures > 0: rrcMsg = 'eNB completed ' + str(X2HO_inNbProcedures) + ' X2 Handover Connection procedure(s)' logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' + htmleNBFailureMsg += rrcMsg + '\n' if X2HO_outNbProcedures > 0: rrcMsg = 'eNB completed ' + str(X2HO_outNbProcedures) + ' X2 Handover Release procedure(s)' logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' + htmleNBFailureMsg += rrcMsg + '\n' if self.eNBOptions[int(self.eNB_instance)] != '': res1 = re.search('drx_Config_present prSetup', self.eNBOptions[int(self.eNB_instance)]) if res1 is not None: if cdrxActivationMessageCount > 0: rrcMsg = 'eNB activated the CDRX Configuration for ' + str(cdrxActivationMessageCount) + ' time(s)' logging.debug('\u001B[1;30;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' + htmleNBFailureMsg += rrcMsg + '\n' else: rrcMsg = 'eNB did NOT ACTIVATE the CDRX Configuration' logging.debug('\u001B[1;37;43m ' + rrcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rrcMsg + '\n' + htmleNBFailureMsg += rrcMsg + '\n' if rachCanceledProcedure > 0: rachMsg = nodeB_prefix + 'NB cancelled ' + str(rachCanceledProcedure) + ' RA procedure(s)' logging.debug('\u001B[1;30;43m ' + rachMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rachMsg + '\n' + htmleNBFailureMsg += rachMsg + '\n' if isRRU: if isSlave: if slaveReceivesFrameResyncCmd: rruMsg = 'Slave RRU received the RRU_frame_resynch command from RAU' logging.debug('\u001B[1;30;43m ' + rruMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rruMsg + '\n' + htmleNBFailureMsg += rruMsg + '\n' else: rruMsg = 'Slave RRU DID NOT receive the RRU_frame_resynch command from RAU' logging.debug('\u001B[1;37;41m ' + rruMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rruMsg + '\n' + htmleNBFailureMsg += rruMsg + '\n' self.prematureExit(True) return CONST.ENB_PROCESS_SLAVE_RRU_NOT_SYNCED if foundSegFault: logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB ended with a Segmentation Fault! \u001B[0m') + if self.htmlObj is not None: + self.htmlObj.SetHmleNBFailureMsg(htmleNBFailureMsg) return CONST.ENB_PROCESS_SEG_FAULT if foundAssertion: logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB ended with an assertion! \u001B[0m') - self.htmleNBFailureMsg += msgAssertion + htmleNBFailureMsg += msgAssertion + if self.htmlObj is not None: + self.htmlObj.SetHmleNBFailureMsg(htmleNBFailureMsg) return CONST.ENB_PROCESS_ASSERTION if foundRealTimeIssue: logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB faced real time issues! \u001B[0m') - self.htmleNBFailureMsg += nodeB_prefix + 'NB faced real time issues!\n' + htmleNBFailureMsg += nodeB_prefix + 'NB faced real time issues!\n' #return ENB_PROCESS_REALTIME_ISSUE if rlcDiscardBuffer > 0: rlcMsg = nodeB_prefix + 'NB RLC discarded ' + str(rlcDiscardBuffer) + ' buffer(s)' logging.debug('\u001B[1;37;41m ' + rlcMsg + ' \u001B[0m') - self.htmleNBFailureMsg += rlcMsg + '\n' + htmleNBFailureMsg += rlcMsg + '\n' + if self.htmlObj is not None: + self.htmlObj.SetHmleNBFailureMsg(htmleNBFailureMsg) return CONST.ENB_PROCESS_REALTIME_ISSUE + if self.htmlObj is not None: + self.htmlObj.SetHmleNBFailureMsg(htmleNBFailureMsg) return 0 From 9758abf9b9666185dfbcf2d5ecbe69eaa1ce8f71 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Tue, 21 Apr 2020 16:47:44 +0200 Subject: [PATCH 183/240] CI: cleanup Signed-off-by: Raphael Defosseux --- ci-scripts/main.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 595a984bbe..5a9836f474 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -3451,9 +3451,6 @@ elif re.match('^InitiateHtml$', mode, re.IGNORECASE): HTML.SethtmlTabRefs(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count))) HTML.SethtmlTabNames(xmlRoot.findtext('htmlTabName',default='test-tab-' + str(count))) HTML.SethtmlTabIcons(xmlRoot.findtext('htmlTabIcon',default='info-sign')) - #CiTestObj.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-' + str(count))) - #CiTestObj.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-' + str(count))) - #CiTestObj.htmlTabIcons.append(xmlRoot.findtext('htmlTabIcon',default='info-sign')) foundCount += 1 count += 1 if foundCount != HTML.GetnbTestXMLfiles(): @@ -3510,8 +3507,6 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re if (HTML.GetnbTestXMLfiles() == 1): HTML.SethtmlTabRefs(xmlRoot.findtext('htmlTabRef',default='test-tab-0')) HTML.SethtmlTabNames(xmlRoot.findtext('htmlTabName',default='Test-0')) - #CiTestObj.htmlTabRefs.append(xmlRoot.findtext('htmlTabRef',default='test-tab-0')) - #CiTestObj.htmlTabNames.append(xmlRoot.findtext('htmlTabName',default='Test-0')) repeatCount = xmlRoot.findtext('repeatCount',default='1') CiTestObj.repeatCounts.append(int(repeatCount)) all_tests=xmlRoot.findall('testCase') From 39a5ddf5518e35af0906054b9ba8fbd279bdb48d Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Tue, 21 Apr 2020 20:15:57 +0200 Subject: [PATCH 184/240] CI: cleanup Signed-off-by: Raphael Defosseux --- ci-scripts/constants.py | 2 +- ci-scripts/epc.py | 7 ++---- ci-scripts/helpreadme.py | 2 +- ci-scripts/html.py | 50 +++++++++++-------------------------- ci-scripts/main.py | 7 +----- ci-scripts/ran.py | 16 ++---------- ci-scripts/sshconnection.py | 5 ++-- 7 files changed, 24 insertions(+), 65 deletions(-) diff --git a/ci-scripts/constants.py b/ci-scripts/constants.py index 65fca7193b..ca3cde446d 100644 --- a/ci-scripts/constants.py +++ b/ci-scripts/constants.py @@ -1,4 +1,4 @@ - +#/* # * 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. diff --git a/ci-scripts/epc.py b/ci-scripts/epc.py index 07462bf762..e67de43b09 100644 --- a/ci-scripts/epc.py +++ b/ci-scripts/epc.py @@ -1,3 +1,4 @@ +#/* # * 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. @@ -27,7 +28,6 @@ # pexpect #--------------------------------------------------------------------- - #----------------------------------------------------------- # Import #----------------------------------------------------------- @@ -124,7 +124,7 @@ class EPCManagement(): mySSH.command('if [ -d ' + self.SourceCodePath + '/scripts ]; then echo ' + self.Password + ' | sudo -S rm -Rf ' + self.SourceCodePath + '/scripts ; fi', '\$', 5) mySSH.command('mkdir -p ' + self.SourceCodePath + '/scripts', '\$', 5) mySSH.command('cd /opt/hss_sim0609', '\$', 5) - mySSH.command('echo ' + self.Password + ' | sudo -S rm -f hss.log daemon.log', '\$', 5) + mySSH.command('echo ' + self.Password + ' | sudo -S rm -f hss.log', '\$', 5) mySSH.command('echo ' + self.Password + ' | sudo -S echo "Starting sudo session" && sudo su -c "screen -dm -S simulated_hss ./starthss"', '\$', 5) else: logging.error('This option should not occur!') @@ -198,7 +198,6 @@ class EPCManagement(): if self.htmlObj is not None: self.htmlObj.CreateHtmlTestRow(self.Type, 'OK', CONST.ALL_PROCESSES_OK) - def CheckHSSProcess(self, status_queue): try: mySSH = SSH.SSHConnection() @@ -267,7 +266,6 @@ class EPCManagement(): except: os.kill(os.getppid(),signal.SIGUSR1) - def TerminateHSS(self): mySSH = SSH.SSHConnection() mySSH.open(self.IPAddress, self.UserName, self.Password) @@ -349,7 +347,6 @@ class EPCManagement(): if self.htmlObj is not None: self.htmlObj.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) - def LogCollectHSS(self): mySSH = SSH.SSHConnection() mySSH.open(self.IPAddress, self.UserName, self.Password) diff --git a/ci-scripts/helpreadme.py b/ci-scripts/helpreadme.py index 307ab4ff31..4b58c77510 100644 --- a/ci-scripts/helpreadme.py +++ b/ci-scripts/helpreadme.py @@ -1,3 +1,4 @@ +#/* # * 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. @@ -27,7 +28,6 @@ # pexpect #--------------------------------------------------------------------- - #----------------------------------------------------------- # Functions Declaration #----------------------------------------------------------- diff --git a/ci-scripts/html.py b/ci-scripts/html.py index 6daf36a314..ac2362477a 100644 --- a/ci-scripts/html.py +++ b/ci-scripts/html.py @@ -1,3 +1,4 @@ +#/* # * 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. @@ -27,7 +28,6 @@ # pexpect #--------------------------------------------------------------------- - #----------------------------------------------------------- # Import #----------------------------------------------------------- @@ -39,6 +39,8 @@ import time import subprocess from multiprocessing import Process, Lock, SimpleQueue +import constants as CONST + #----------------------------------------------------------- # Class Declaration #----------------------------------------------------------- @@ -87,11 +89,6 @@ class HTMLManagement(): def SetHmleNBFailureMsg(self, msg): self.htmleNBFailureMsg = msg - def SetreseNB(self,rsenb): - self.reseNB = rsenb - def SetresUE(self,rsue): - self.resUE = rsue - def Setdesc(self, dsc): self.desc = dsc @@ -105,35 +102,19 @@ class HTMLManagement(): def SetranRepository(self, repository): self.ranRepository = repository - def GetranRepository(self): - return self.ranRepository - def SetranAllowMerge(self, merge): self.ranAllowMerge = merge - def GetranAllowMerge(self): - return self.ranAllowMerge - def SetranBranch(self, branch): self.ranBranch = branch - def GetranBranch(self): - return self.ranBranch - def SetranCommitID(self, commitid): self.ranCommitID = commitid - def GetranCommitID(self): - return self.ranCommitID - def SetranTargetBranch(self, tbranch): self.ranTargetBranch = tbranch - def GetranTargetBranch(self): - return self.ranTargetBranch def SethtmlUEConnected(self, nbUEs): self.htmlUEConnected = nbUEs - def SethtmlNb_Smartphones(self, nbUEs): self.htmlNb_Smartphones = nbUEs - def SethtmlNb_CATM_Modules(self, nbUEs): self.htmlNb_CATM_Modules = nbUEs @@ -400,29 +381,29 @@ class HTMLManagement(): elif (str(status) == 'KO'): if (processesStatus == 0): self.htmlFile.write(' \n') - elif (processesStatus == ENB_PROCESS_FAILED): + elif (processesStatus == CONST.ENB_PROCESS_FAILED): self.htmlFile.write(' \n') - elif (processesStatus == OAI_UE_PROCESS_FAILED): + elif (processesStatus == CONST.OAI_UE_PROCESS_FAILED): self.htmlFile.write(' \n') - elif (processesStatus == ENB_PROCESS_SEG_FAULT) or (processesStatus == OAI_UE_PROCESS_SEG_FAULT): + elif (processesStatus == CONST.ENB_PROCESS_SEG_FAULT) or (processesStatus == CONST.OAI_UE_PROCESS_SEG_FAULT): self.htmlFile.write(' \n') - elif (processesStatus == ENB_PROCESS_ASSERTION) or (processesStatus == OAI_UE_PROCESS_ASSERTION): + elif (processesStatus == CONST.ENB_PROCESS_ASSERTION) or (processesStatus == CONST.OAI_UE_PROCESS_ASSERTION): self.htmlFile.write(' \n') - elif (processesStatus == ENB_PROCESS_REALTIME_ISSUE): + elif (processesStatus == CONST.ENB_PROCESS_REALTIME_ISSUE): self.htmlFile.write(' \n') - elif (processesStatus == ENB_PROCESS_NOLOGFILE_TO_ANALYZE) or (processesStatus == OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE): + elif (processesStatus == CONST.ENB_PROCESS_NOLOGFILE_TO_ANALYZE) or (processesStatus == CONST.OAI_UE_PROCESS_NOLOGFILE_TO_ANALYZE): self.htmlFile.write(' \n') - elif (processesStatus == ENB_PROCESS_SLAVE_RRU_NOT_SYNCED): + elif (processesStatus == CONST.ENB_PROCESS_SLAVE_RRU_NOT_SYNCED): self.htmlFile.write(' \n') - elif (processesStatus == OAI_UE_PROCESS_COULD_NOT_SYNC): + elif (processesStatus == CONST.OAI_UE_PROCESS_COULD_NOT_SYNC): self.htmlFile.write(' \n') - elif (processesStatus == HSS_PROCESS_FAILED): + elif (processesStatus == CONST.HSS_PROCESS_FAILED): self.htmlFile.write(' \n') - elif (processesStatus == MME_PROCESS_FAILED): + elif (processesStatus == CONST.MME_PROCESS_FAILED): self.htmlFile.write(' \n') - elif (processesStatus == SPGW_PROCESS_FAILED): + elif (processesStatus == CONST.SPGW_PROCESS_FAILED): self.htmlFile.write(' \n') - elif (processesStatus == UE_IP_ADDRESS_ISSUE): + elif (processesStatus == CONST.UE_IP_ADDRESS_ISSUE): self.htmlFile.write(' \n') else: self.htmlFile.write(' \n') @@ -491,4 +472,3 @@ class HTMLManagement(): self.htmlFile.write(' \n') self.htmlFile.close() - diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 5a9836f474..6aeefdef54 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -104,8 +104,6 @@ class OaiCiTest(): self.Initialize_OAI_UE_args = '' self.clean_repository = True self.expectedNbOfConnectedUEs = 0 - self.startTime = 0 - def BuildOAIUE(self): if self.UEIPAddress == '' or RAN.GetranRepository() == '' or RAN.GetranBranch() == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': @@ -1901,7 +1899,6 @@ class OaiCiTest(): def Iperf_common(self, lock, UE_IPAddress, device_id, idx, ue_num, statusQueue): try: - logging.debug('entring Iperf_common') # Single-UE profile -- iperf only on one UE if self.iperf_profile == 'single-ue' and idx != 0: return @@ -2239,7 +2236,6 @@ class OaiCiTest(): ue_num = len(self.UEIPAddresses) lock = Lock() status_queue = SimpleQueue() - logging.debug('ue_num = ' + str(ue_num)) for UE_IPAddress in self.UEIPAddresses: device_id = self.UEDevices[i] p = Process(target = self.Iperf_common, args = (lock,UE_IPAddress,device_id,i,ue_num,status_queue,)) @@ -3559,8 +3555,7 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re CiTestObj.FailReportCnt = 0 RAN.SetprematureExit(True) - CiTestObj.startTime = int(round(time.time() * 1000)) - HTML.SetstartTime(CiTestObj.startTime) + HTML.SetstartTime(int(round(time.time() * 1000)) while CiTestObj.FailReportCnt < CiTestObj.repeatCounts[0] and RAN.GetprematureExit(): RAN.SetprematureExit(False) # At every iteratin of the retry loop, a separator will be added diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py index 7efe96dc2e..917410b8ae 100644 --- a/ci-scripts/ran.py +++ b/ci-scripts/ran.py @@ -1,4 +1,4 @@ - +#/* # * 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. @@ -28,7 +28,6 @@ # pexpect #--------------------------------------------------------------------- - #----------------------------------------------------------- # Import #----------------------------------------------------------- @@ -233,8 +232,6 @@ class RANManagement(): # RAN management functions #----------------------------------------------------------- - - def BuildeNB(self): if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': GenericHelp(Version) @@ -347,8 +344,6 @@ class RANManagement(): mySSH.close() self.checkBuildeNB(lIpAddr, lUserName, lPassWord, lSourcePath, self.testCase_id) - - def WaitBuildeNBisFinished(self): if self.eNB_serverId == '0': lIpAddr = self.eNBIPAddress @@ -444,7 +439,6 @@ class RANManagement(): self.htmlObj.CreateHtmlTabFooter(False) sys.exit(1) - def InitializeeNB(self): if self.eNB_serverId == '0': lIpAddr = self.eNBIPAddress @@ -638,8 +632,6 @@ class RANManagement(): self.htmlObj.CreateHtmlTestRow('-O ' + config_file + extra_options, 'OK', CONST.ALL_PROCESSES_OK) logging.debug('\u001B[1m Initialize eNB Completed\u001B[0m') - - def CheckeNBProcess(self, status_queue): try: # At least the instance 0 SHALL be on! @@ -672,8 +664,6 @@ class RANManagement(): except: os.kill(os.getppid(),signal.SIGUSR1) - - def TerminateeNB(self): if self.eNB_serverId == '0': lIpAddr = self.eNBIPAddress @@ -780,7 +770,6 @@ class RANManagement(): self.eNBmbmsEnables[int(self.eNB_instance)] = False self.eNBstatuses[int(self.eNB_instance)] = -1 - def LogCollecteNB(self): mySSH = SSH.SSHConnection() mySSH.open(self.eNBIPAddress, self.eNBUserName, self.eNBPassword) @@ -791,7 +780,6 @@ class RANManagement(): mySSH.command('echo ' + self.eNBPassword + ' | sudo -S rm enb*.log core* enb_*record.raw enb_*.pcap enb_*txt', '\$', 5) mySSH.close() - def AnalyzeLogFile_eNB(self, eNBlogFile): if (not os.path.isfile('./' + eNBlogFile)): return -1 @@ -1043,7 +1031,7 @@ class RANManagement(): if foundRealTimeIssue: logging.debug('\u001B[1;37;41m ' + nodeB_prefix + 'NB faced real time issues! \u001B[0m') htmleNBFailureMsg += nodeB_prefix + 'NB faced real time issues!\n' - #return ENB_PROCESS_REALTIME_ISSUE + #return CONST.ENB_PROCESS_REALTIME_ISSUE if rlcDiscardBuffer > 0: rlcMsg = nodeB_prefix + 'NB RLC discarded ' + str(rlcDiscardBuffer) + ' buffer(s)' logging.debug('\u001B[1;37;41m ' + rlcMsg + ' \u001B[0m') diff --git a/ci-scripts/sshconnection.py b/ci-scripts/sshconnection.py index 6fad5065e2..cdd062f846 100644 --- a/ci-scripts/sshconnection.py +++ b/ci-scripts/sshconnection.py @@ -1,4 +1,4 @@ - +#/* # * 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. @@ -28,7 +28,6 @@ # pexpect #--------------------------------------------------------------------- - #----------------------------------------------------------- # Import #----------------------------------------------------------- @@ -36,6 +35,7 @@ import pexpect # pexpect import logging import time # sleep import re + #----------------------------------------------------------- # Class Declaration #----------------------------------------------------------- @@ -89,7 +89,6 @@ class SSHConnection(): else: sys.exit('SSH Connection Failed') - def command(self, commandline, expectedline, timeout): logging.debug(commandline) self.ssh.timeout = timeout From 6eb5d8c9c7169499fee869ea2331dc62f86ceeff Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Tue, 21 Apr 2020 22:25:16 +0200 Subject: [PATCH 185/240] CI: fix a few more things Signed-off-by: Raphael Defosseux --- ci-scripts/html.py | 2 ++ ci-scripts/main.py | 32 +++++++++++++++++--------------- ci-scripts/ran.py | 23 +++++++++++++++-------- 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/ci-scripts/html.py b/ci-scripts/html.py index ac2362477a..67deaa75ce 100644 --- a/ci-scripts/html.py +++ b/ci-scripts/html.py @@ -369,6 +369,8 @@ class HTMLManagement(): self.htmlFile.close() def CreateHtmlTestRow(self, options, status, processesStatus, machine='eNB'): + if (self.htmlFooterCreated or (not self.htmlHeaderCreated)): + return self.htmlFile = open('test_results.html', 'a') currentTime = int(round(time.time() * 1000)) - self.startTime self.htmlFile.write(' \n') diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 6aeefdef54..1b65fe0f19 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -353,7 +353,7 @@ class OaiCiTest(): SSH.command('sed -e "s#93#92#" -e "s#8baf473f2f8fd09487cccbd7097c6862#fec86ba6eb707ed08905757b1bb44b8f#" -e "s#e734f8734007d6c5ce7a0508809e7e9c#C42449363BBAD02B66D16BC975D77CC1#" ../../../openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf > ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf', '\$', 5) SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf .u*', '\$', 5) SSH.command('echo ' + self.UEPassword + ' | sudo -S ../../../targets/bin/conf2uedata -c ../../../openair3/NAS/TOOLS/ci-ue_eurecom_test_sfr.conf -o .', '\$', 5) - SSH.command('echo "ulimit -c unlimited && ./'+ RAN.Getair_interface() +'-uesoftmodem ' + self.Initialize_OAI_UE_args + '" > ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) + SSH.command('echo "ulimit -c unlimited && ./'+ RAN.Getair_interface() +'-uesoftmodem ' + modifiedUeOptions + '" > ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) SSH.command('chmod 775 ./my-lte-uesoftmodem-run' + str(self.UE_instance) + '.sh', '\$', 5) SSH.command('echo ' + self.UEPassword + ' | sudo -S rm -Rf ' + self.UESourceCodePath + '/cmake_targets/ue_' + self.testCase_id + '.log', '\$', 5) self.UELogFile = 'ue_' + self.testCase_id + '.log' @@ -451,7 +451,7 @@ class OaiCiTest(): logging.debug(SSH.getBefore()) logging.error('\u001B[1m oaitun_ue1 interface is either NOT mounted or NOT configured\u001B[0m') tunnelInterfaceStatus = False - if RAN.GeteNBmbmsEnables[0]: + if RAN.GeteNBmbmsEnable(0): self.command('ifconfig oaitun_uem1', '\$', 4) result = re.search('inet addr', SSH.getBefore()) if result is not None: @@ -476,7 +476,7 @@ class OaiCiTest(): self.UEDevicesStatus.append(CONST.UE_STATUS_DETACHED) else: if RAN.Getair_interface() == 'lte': - if RAN.GeteNBmbmsEnables[0]: + if RAN.GeteNBmbmsEnable(0): HTML.SethtmlUEFailureMsg('oaitun_ue1/oaitun_uem1 interfaces are either NOT mounted or NOT configured') else: HTML.SethtmlUEFailureMsg('oaitun_ue1 interface is either NOT mounted or NOT configured') @@ -2316,13 +2316,13 @@ class OaiCiTest(): if (status < 0): result = status if result == CONST.ENB_PROCESS_FAILED: - fileCheck = re.search('enb_', str(RAN.GeteNBLogFiles[0])) + fileCheck = re.search('enb_', str(RAN.GeteNBLogFile(0))) if fileCheck is not None: - SSH.copyin(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath() + '/cmake_targets/' + RAN.GeteNBLogFiles[0], '.') - logStatus = self.AnalyzeLogFile_eNB(RAN.GeteNBLogFiles[0]) + SSH.copyin(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath() + '/cmake_targets/' + RAN.GeteNBLogFile(0), '.') + logStatus = RAN.AnalyzeLogFile_eNB(RAN.GeteNBLogFile[0]) if logStatus < 0: result = logStatus - RAN.SeteNBLogFiles[0] = '' + RAN.SeteNBLogFile('', 0) if RAN.GetflexranCtrlInstalled() and RAN.GetflexranCtrlStarted(): self.TerminateFlexranCtrl() return result @@ -2457,7 +2457,7 @@ class OaiCiTest(): result = re.search('No cell synchronization found, abandoning', str(line)) if result is not None: no_cell_sync_found = True - if RAN.GeteNBmbmsEnables[0]: + if RAN.GeteNBmbmsEnable(0): result = re.search('TRIED TO PUSH MBMS DATA', str(line)) if result is not None: mbms_messages += 1 @@ -2583,7 +2583,7 @@ class OaiCiTest(): statMsg = 'UE showed ' + str(fatalErrorCount) + ' "MAC BSR Triggered ReTxBSR Timer expiry" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') HTML.SethtmlUEFailureMsg(HTML.GethtmlUEFailureMsg() + statMsg + '\n') - if RAN.GeteNBmbmsEnables[0]: + if RAN.GeteNBmbmsEnable(0): if mbms_messages > 0: statMsg = 'UE showed ' + str(mbms_messages) + ' "TRIED TO PUSH MBMS DATA" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') @@ -3075,6 +3075,7 @@ def GetParametersFromXML(action): CiTestObj.air_interface = 'lte' else: CiTestObj.air_interface = CiTestObj.air_interface.lower() + RAN.Setair_interface(CiTestObj.air_interface) if action == 'Terminate_eNB': RAN.SeteNB_instance(test.findtext('eNB_instance')) @@ -3088,6 +3089,7 @@ def GetParametersFromXML(action): CiTestObj.air_interface = 'lte' else: CiTestObj.air_interface = CiTestObj.air_interface.lower() + RAN.Setair_interface(CiTestObj.air_interface) if action == 'Attach_UE': nbMaxUEtoAttach = test.findtext('nbMaxUEtoAttach') @@ -3120,7 +3122,7 @@ def GetParametersFromXML(action): if (CiTestObj.air_interface is None): CiTestObj.air_interface = 'lte' else: - CiTestObj.air_interface = SSH.air_interface.lower() + CiTestObj.air_interface = CiTestObj.air_interface.lower() if action == 'Terminate_OAI_UE': RAN.SeteNB_instance(test.findtext('UE_instance')) @@ -3378,17 +3380,17 @@ elif re.match('^TerminateHSS$', mode, re.IGNORECASE): if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': GenericHelp(Version) sys.exit('Insufficient Parameter') - CiTestObj.TerminateHSS() + EPC.TerminateHSS() elif re.match('^TerminateMME$', mode, re.IGNORECASE): if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': GenericHelp(Version) sys.exit('Insufficient Parameter') - CiTestObj.TerminateMME() + EPC.TerminateMME() elif re.match('^TerminateSPGW$', mode, re.IGNORECASE): if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': GenericHelp(Version) sys.exit('Insufficient Parameter') - CiTestObj.TerminateSPGW() + EPC.TerminateSPGW() elif re.match('^LogCollectBuild$', mode, re.IGNORECASE): if (RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '') and (CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == ''): GenericHelp(Version) @@ -3398,7 +3400,7 @@ elif re.match('^LogCollecteNB$', mode, re.IGNORECASE): if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '': GenericHelp(Version) sys.exit('Insufficient Parameter') - CiTestObj.LogCollecteNB() + RAN.LogCollecteNB() elif re.match('^LogCollectHSS$', mode, re.IGNORECASE): if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': GenericHelp(Version) @@ -3555,7 +3557,7 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re CiTestObj.FailReportCnt = 0 RAN.SetprematureExit(True) - HTML.SetstartTime(int(round(time.time() * 1000)) + HTML.SetstartTime(int(round(time.time() * 1000))) while CiTestObj.FailReportCnt < CiTestObj.repeatCounts[0] and RAN.GetprematureExit(): RAN.SetprematureExit(False) # At every iteratin of the retry loop, a separator will be added diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py index 917410b8ae..c65c21c252 100644 --- a/ci-scripts/ran.py +++ b/ci-scripts/ran.py @@ -179,15 +179,13 @@ class RANManagement(): def GeteNB_instance(self): return self.eNB_instance - def SeteNBLogFiles(self, enblogs): - self.eNBLogFiles = enblogs - def GeteNBLogFiles(self): - return self.eNBLogFiles + def SeteNBLogFile(self, enblog, idx): + self.eNBLogFiles[idx] = enblog + def GeteNBLogFile(self, idx): + return self.eNBLogFiles[idx] - def SeteNBmbmsEnables(self, enbmbms): - self.eNBmbmsEnables = enbmbms - def GeteNBmbmsEnables(self): - return self.eNBmbmsEnables + def GeteNBmbmsEnable(self, idx): + return self.eNBmbmsEnables[idx] def SeteNB1IPAddress(self,enb1ip): self.eNB1IPAddress = enb1ip @@ -802,6 +800,7 @@ class RANManagement(): uciStatMsgCount = 0 pdcpFailure = 0 ulschFailure = 0 + ulschReceiveOK = 0 cdrxActivationMessageCount = 0 dropNotEnoughRBs = 0 mbmsRequestMsg = 0 @@ -914,6 +913,9 @@ class RANManagement(): result = re.search('ULSCH in error in round', str(line)) if result is not None: ulschFailure += 1 + result = re.search('ULSCH received ok', str(line)) + if result is not None: + ulschReceiveOK += 1 result = re.search('BAD all_segments_received', str(line)) if result is not None: rlcDiscardBuffer += 1 @@ -933,6 +935,11 @@ class RANManagement(): nodeB_prefix = 'e' else: nodeB_prefix = 'g' + if self.air_interface == 'nr': + if ulschReceiveOK > 0: + statMsg = nodeB_prefix + 'NB showed ' + str(ulschReceiveOK) + ' "ULSCH received ok" message(s)' + logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') + htmleNBFailureMsg += statMsg + '\n' if uciStatMsgCount > 0: statMsg = nodeB_prefix + 'NB showed ' + str(uciStatMsgCount) + ' "uci->stat" message(s)' logging.debug('\u001B[1;30;43m ' + statMsg + ' \u001B[0m') From 93ba34b027ed78dbf626ddede7f79455c23948fb Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Tue, 21 Apr 2020 23:44:06 +0200 Subject: [PATCH 186/240] testing for pucch format 2, 3-11 bits. Configuration works for 2 PRBs, 1 symbol only. Assertion in gNB RX otherwise. --- cmake_targets/CMakeLists.txt | 1 + openair1/PHY/INIT/nr_init.c | 3 +- openair1/PHY/NR_REFSIG/nr_refsig.h | 8 +- openair1/PHY/NR_TRANSPORT/pucch_rx.c | 530 +++++++++++++++++++++++- openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c | 14 +- openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h | 4 +- openair1/SIMULATION/NR_PHY/pucchsim.c | 73 +++- 7 files changed, 607 insertions(+), 26 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index f6fcabf82e..d07694725d 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -1495,6 +1495,7 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_dmrs_rx.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gold.c + ${OPENAIR1_DIR}/PHY/NR_REFSIG/scrambling_luts.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/dmrs_nr.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/ptrs_nr.c ${OPENAIR1_DIR}/PHY/NR_UE_ESTIMATION/filt16a_32.c diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index 1c0d5a6aca..46fd9fb5fd 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -96,7 +96,6 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, while(gNB->configured == 0) usleep(10000); - init_dfts(); /* LOG_I(PHY,"[gNB %"PRIu8"] Initializing DL_FRAME_PARMS : N_RB_DL %"PRIu8", PHICH Resource %d, PHICH Duration %d nb_antennas_tx:%u nb_antennas_rx:%u PRACH[rootSequenceIndex:%u prach_Config_enabled:%u configIndex:%u highSpeed:%u zeroCorrelationZoneConfig:%u freqOffset:%u]\n", gNB->Mod_id, @@ -113,6 +112,8 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, LOG_D(PHY,"[MSC_NEW][FRAME 00000][PHY_gNB][MOD %02"PRIu8"][]\n", gNB->Mod_id); crcTableInit(); init_dfts(); + init_scrambling_luts(); + init_pucch2_luts(); load_nrLDPClib(); // PBCH DMRS gold sequences generation nr_init_pbch_dmrs(gNB); diff --git a/openair1/PHY/NR_REFSIG/nr_refsig.h b/openair1/PHY/NR_REFSIG/nr_refsig.h index 5af0e88099..d18f6405d7 100644 --- a/openair1/PHY/NR_REFSIG/nr_refsig.h +++ b/openair1/PHY/NR_REFSIG/nr_refsig.h @@ -26,7 +26,7 @@ #include "PHY/defs_gNB.h" #include "PHY/LTE_REFSIG/lte_refsig.h" - +#include "PHY/sse_intrin.h" /*!\brief This function generates the NR Gold sequence (38-211, Sec 5.2.1) for the PBCH DMRS. @param PHY_VARS_gNB* gNB structure provides configuration, frame parameters and the pointers to the 32 bits sequence storage tables @@ -49,4 +49,10 @@ int nr_pusch_dmrs_rx(PHY_VARS_gNB *gNB, unsigned char lp, unsigned short nb_pusch_rb, uint8_t dmrs_type); + +void init_scrambling_luts(void); + +extern __m64 byte2m64_re[256]; +extern __m64 byte2m64_im[256]; + #endif diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index ee3e247cb0..62ced5af9d 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -1,3 +1,34 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file PHY/NR_TRANSPORT/pucch_rx.c +* \brief Top-level routines for decoding the PUCCH physical channel +* \author A. Mico Pereperez, Padarthi Naga Prasanth, Francesco Mani, Raymond Knopp +* \date 2020 +* \version 0.2 +* \company Eurecom +* \email: +* \note +* \warning +*/ #include #include #include @@ -8,10 +39,12 @@ #include "PHY/impl_defs_nr.h" #include "PHY/defs_nr_common.h" -#include "PHY/defs_nr_UE.h" +#include "PHY/defs_gNB.h" +#include "PHY/sse_intrin.h" #include "PHY/NR_UE_TRANSPORT/pucch_nr.h" #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h" #include "PHY/NR_TRANSPORT/nr_transport.h" +#include "PHY/NR_REFSIG/nr_refsig.h" #include "common/utils/LOG/log.h" #include "common/utils/LOG/vcd_signal_dumper.h" @@ -188,7 +221,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, for (l=0; lnr_of_symbols; l++) { l2 = l+pucch_pdu->start_symbol_index; - re_offset = (12*pucch_pdu->prb_start) + frame_parms->first_carrier_offset; + re_offset = (12*pucch_pdu->prb_start) + (12*pucch_pdu->bwp_start) + frame_parms->first_carrier_offset; if (re_offset>= frame_parms->ofdm_symbol_size) re_offset-=frame_parms->ofdm_symbol_size; @@ -818,3 +851,496 @@ void nr_decode_pucch1( int32_t **rxdataF, } } +__m256i pucch2_3bit[8*2]; +__m256i pucch2_4bit[16*2]; +__m256i pucch2_5bit[32*2]; +__m256i pucch2_6bit[64*2]; +__m256i pucch2_7bit[128*2]; +__m256i pucch2_8bit[256*2]; +__m256i pucch2_9bit[512*2]; +__m256i pucch2_10bit[1024*2]; +__m256i pucch2_11bit[2048*2]; + +__m256i *pucch2_lut[9]={pucch2_3bit, + pucch2_4bit, + pucch2_5bit, + pucch2_6bit, + pucch2_7bit, + pucch2_8bit, + pucch2_9bit, + pucch2_10bit, + pucch2_11bit}; + +void init_pucch2_luts() { + + uint32_t out; + int8_t bit; + + for (int b=3;b<12;b++) { + for (uint16_t i=0;i<(1< 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,0); + bit = (out&0x2) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,0); + bit = (out&0x4) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,1); + bit = (out&0x8) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,1); + bit = (out&0x10) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,2); + bit = (out&0x20) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,2); + bit = (out&0x40) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,3); + bit = (out&0x80) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,3); + bit = (out&0x100) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,4); + bit = (out&0x200) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,4); + bit = (out&0x400) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,5); + bit = (out&0x800) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,5); + bit = (out&0x1000) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,6); + bit = (out&0x2000) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,6); + bit = (out&0x4000) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,7); + bit = (out&0x8000) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,7); + bit = (out&0x10000) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,8); + bit = (out&0x20000) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,8); + bit = (out&0x40000) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,9); + bit = (out&0x80000) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,9); + bit = (out&0x100000) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,10); + bit = (out&0x200000) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,10); + bit = (out&0x400000) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,11); + bit = (out&0x800000) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,11); + bit = (out&0x1000000) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,12); + bit = (out&0x2000000) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,12); + bit = (out&0x4000000) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,13); + bit = (out&0x8000000) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,13); + bit = (out&0x10000000) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,14); + bit = (out&0x20000000) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,14); + bit = (out&0x40000000) > 0 ? -1 : 1; + *lut_i = _mm256_insert_epi16(*lut_i,bit,15); + bit = (out&0x80000000) > 0 ? -1 : 1; + *lut_ip1 = _mm256_insert_epi16(*lut_ip1,bit,15); + } + } +} + + +void nr_decode_pucch2(PHY_VARS_gNB *gNB, + int slot, + nfapi_nr_uci_pucch_pdu_format_2_3_4_t* uci_pdu, + nfapi_nr_pucch_pdu_t* pucch_pdu) { + + int32_t **rxdataF = gNB->common_vars.rxdataF; + NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; + pucch_GroupHopping_t pucch_GroupHopping = pucch_pdu->group_hop_flag + (pucch_pdu->sequence_hop_flag<<1); + + AssertFatal(pucch_pdu->nr_of_symbols==1 || pucch_pdu->nr_of_symbols==2, + "Illegal number of symbols for PUCCH 2 %d\n",pucch_pdu->nr_of_symbols); + + + //extract pucch and dmrs first + + int l2; + int re_offset = (12*pucch_pdu->prb_start) + (12*pucch_pdu->bwp_start) + frame_parms->first_carrier_offset; + if (re_offset>= frame_parms->ofdm_symbol_size) + re_offset-=frame_parms->ofdm_symbol_size; + + AssertFatal(pucch_pdu->prb_size*pucch_pdu->nr_of_symbols > 1,"number of PRB*SYMB (%d,%d)< 2", + pucch_pdu->prb_size,pucch_pdu->nr_of_symbols); + + int Prx = gNB->gNB_config.carrier_config.num_rx_ant.value; + int Prx2 = (Prx==1)?2:Prx; + // use 2 for Nb antennas in case of single antenna to allow the following allocations + int16_t r_re_ext[Prx2][8*pucch_pdu->nr_of_symbols*pucch_pdu->prb_size] __attribute__((aligned(32))); + int16_t r_im_ext[Prx2][8*pucch_pdu->nr_of_symbols*pucch_pdu->prb_size] __attribute__((aligned(32))); + int16_t r_re_ext2[Prx2][8*pucch_pdu->nr_of_symbols*pucch_pdu->prb_size] __attribute__((aligned(32))); + int16_t r_im_ext2[Prx2][8*pucch_pdu->nr_of_symbols*pucch_pdu->prb_size] __attribute__((aligned(32))); + int16_t rd_re_ext[Prx2][4*pucch_pdu->nr_of_symbols*pucch_pdu->prb_size] __attribute__((aligned(32))); + int16_t rd_im_ext[Prx2][4*pucch_pdu->nr_of_symbols*pucch_pdu->prb_size] __attribute__((aligned(32))); + + int16_t *rp[Prx2]; + __m64 dmrs_re,dmrs_im; + + for (int aa=0;aaofdm_symbol_size)+re_offset]); + +#ifdef DEBUG_NR_PUCCH_RX + printf("Decoding pucch2 for %d symbols, %d PRB\n",pucch_pdu->nr_of_symbols,pucch_pdu->prb_size); +#endif + + int nc_group_size=1; // 2 PRB + int ngroup = pucch_pdu->prb_size/nc_group_size/2; + int32_t corr32_re[ngroup][Prx2],corr32_im[ngroup][Prx2]; + for (int aa=0;aanr_of_symbols == 1) { + AssertFatal((pucch_pdu->prb_size&1) == 0,"prb_size %d is not a multiple of 2\n",pucch_pdu->prb_size); + // 24 PRBs contains 48x16-bit, so 6x8x16-bit + for (int prb=0;prbprb_size;prb+=2) { + for (int aa=0;aa (%d,%d)\n",aa,prb+(i>>2),i,rd_re_ext[aa][i],rd_im_ext[aa],i); +#endif + } // aa + } // prb + + + // first compute DMRS component + uint32_t x1, x2, s=0; + x2 = (((1<<17)*((14*slot) + (pucch_pdu->start_symbol_index) + 1)*((2*pucch_pdu->dmrs_scrambling_id) + 1)) + (2*pucch_pdu->dmrs_scrambling_id))%(1U<<31); // c_init calculation according to TS38.211 subclause +#ifdef DEBUG_NR_PUCCH_RX + printf("slot %d, start_symbol_index %d, dmrs_scrambling_id %d\n", + slot,pucch_pdu->start_symbol_index,pucch_pdu->dmrs_scrambling_id); +#endif + s = lte_gold_generic(&x1, &x2, 1); + + + for (int group=0;group>=5; + corr32_im[group][aa]>>=5; +#ifdef DEBUG_NR_PUCCH_RX + printf("Group %d: corr32 (%d,%d)\n",group,corr32_re[group][aa],corr32_im[group][aa]); +#endif + } //aa + + if ((group&3) == 3) s = lte_gold_generic(&x1, &x2, 0); + } // group + } + else { // 2 symbol case + AssertFatal(1==0, "Fill in 2 symbol PUCCH2 case\n"); + } + + uint32_t x1, x2, s=0; + // unscrambling + x2 = ((pucch_pdu->rnti)<<15)+pucch_pdu->data_scrambling_id; + s = lte_gold_generic(&x1, &x2, 1); +#ifdef DEBUG_NR_PUCCH_RX + printf("x2 %x, s %x\n",x2,s); +#endif + __m64 c_re0,c_im0,c_re1,c_im1,c_re2,c_im2,c_re3,c_im3; + re_offset=0; + for (int prb=0;prbprb_size;prb+=2,re_offset+=16) { + c_re0 = byte2m64_re[((uint8_t*)&s)[0]]; + c_im0 = byte2m64_im[((uint8_t*)&s)[0]]; + c_re1 = byte2m64_re[((uint8_t*)&s)[1]]; + c_im1 = byte2m64_im[((uint8_t*)&s)[1]]; + c_re2 = byte2m64_re[((uint8_t*)&s)[2]]; + c_im2 = byte2m64_im[((uint8_t*)&s)[2]]; + c_re3 = byte2m64_re[((uint8_t*)&s)[3]]; + c_im3 = byte2m64_im[((uint8_t*)&s)[3]]; + + for (int aa=0;aabit_len_csi_part1 + pucch_pdu->bit_len_csi_part2 == 0,"no csi for now\n"); + AssertFatal((pucch_pdu->bit_len_harq+pucch_pdu->sr_flag > 2 ) && (pucch_pdu->bit_len_harq+pucch_pdu->sr_flag < 12),"illegal length (%d,%d)\n",pucch_pdu->bit_len_harq,pucch_pdu->sr_flag); + int nb_bit = pucch_pdu->bit_len_harq+pucch_pdu->sr_flag; + __m256i *rp_re[Prx2]; + __m256i *rp2_re[Prx2]; + __m256i *rp_im[Prx2]; + __m256i *rp2_im[Prx2]; + for (int aa=0;aa>1], + ((int16_t*)&pucch2_lut[nb_bit-3][cw<<1])[1+(i>>1)]); + } + printf("\n"); +#endif + // do complex correlation + for (int aa=0;aa corr) { + corr = corr_tmp; + cw_ML=cw; + } + } + uint8_t corr_dB = dB_fixed64((uint64_t)corr); + LOG_D(PHY,"cw_ML %d, metric %d dB\n",cw_ML,corr_dB); + uci_pdu->harq.harq_bit_len = pucch_pdu->bit_len_harq; + + + int harq_bytes=pucch_pdu->bit_len_harq>>3; + if ((pucch_pdu->bit_len_harq&7) > 0) harq_bytes++; + uci_pdu->harq.harq_payload = (nfapi_nr_harq_t*)malloc(harq_bytes); + uci_pdu->harq.harq_crc = 2; + for (int i=0;iharq.harq_payload[i] = cw_ML & 255; + cw_ML>>=8; + } + + if (pucch_pdu->sr_flag == 1) { + uci_pdu->sr.sr_bit_len = 1; + uci_pdu->sr.sr_payload = malloc(1); + uci_pdu->sr.sr_payload[0] = cw_ML; + } +} + diff --git a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c index d63cef5085..2a08d54c5a 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.c @@ -42,6 +42,7 @@ #include "common/utils/LOG/vcd_signal_dumper.h" #include "T.h" +//#define NR_UNIT_TEST 1 #ifdef NR_UNIT_TEST #define DEBUG_PUCCH_TX #define DEBUG_NR_PUCCH_TX @@ -905,7 +906,9 @@ void nr_uci_encoding(uint64_t payload, if (A<=11) { // procedure in subclause 6.3.1.2.2 (UCI encoded by channel coding of small block lengths -> subclause 6.3.1.3.2) // CRC bits are not attached, and coding small block lengths (subclause 5.3.3) + b[0] = encodeSmallBlock((uint16_t*)&payload,A); } else if (A>=12) { + AssertFatal(1==0,"Polar encoding not supported yet for UCI\n"); // procedure in subclause 6.3.1.2.1 (UCI encoded by Polar code -> subclause 6.3.1.3.1) /*if ((A>=360 && E>=1088)||(A>=1013)) { I_seg = 1; @@ -924,10 +927,13 @@ void nr_uci_encoding(uint64_t payload, // code block segmentation and CRC attachment is performed according to subclause 5.2.1 // polar coding subclause 5.3.1 } + } //#if 0 void nr_generate_pucch2(PHY_VARS_NR_UE *ue, uint16_t crnti, + uint32_t dmrs_scrambling_id, + uint32_t data_scrambling_id, int32_t **txdataF, NR_DL_FRAME_PARMS *frame_parms, PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, @@ -961,14 +967,14 @@ void nr_generate_pucch2(PHY_VARS_NR_UE *ue, */ uint8_t *btilde = malloc(sizeof(int8_t)*M_bit); // rnti is given by the C-RNTI - uint16_t rnti=crnti, n_id=0; + uint16_t rnti=crnti; #ifdef DEBUG_NR_PUCCH_TX printf("\t [nr_generate_pucch2] rnti = %d ,\n",rnti); #endif /* * Implementing TS 38.211 Subclause 6.3.2.5.1 scrambling format 2 */ - nr_pucch2_3_4_scrambling(M_bit,rnti,n_id,b,btilde); + nr_pucch2_3_4_scrambling(M_bit,rnti,data_scrambling_id,b,btilde); /* * Implementing TS 38.211 Subclause 6.3.2.5.2 modulation format 2 * btilde shall be modulated as described in subclause 5.1 using QPSK @@ -1016,10 +1022,10 @@ void nr_generate_pucch2(PHY_VARS_NR_UE *ue, int m=0; for (int l=0; lN_RB_DL>>1)) && ((frame_parms->N_RB_DL & 1) == 0)) { // if number RBs in bandwidth is even and current PRB is lower band diff --git a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h index 4c4847d7de..510abb8373 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h +++ b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h @@ -20,7 +20,7 @@ */ /*! \file PHY/NR_UE_TRANSPORT/pucch_nr.c -* \brief Top-level routines for generating and decoding the PUCCH physical channel +* \brief Top-level routines for generating the PUCCH physical channel * \author A. Mico Pereperez * \date 2018 * \version 0.1 @@ -70,6 +70,8 @@ void nr_generate_pucch1(PHY_VARS_NR_UE *ue, uint8_t nr_bit); void nr_generate_pucch2(PHY_VARS_NR_UE *ue, uint16_t crnti, + uint32_t dmrs_scrambling_id, + uint32_t data_scrambling_id, int32_t **txdataF, NR_DL_FRAME_PARMS *frame_parms, PUCCH_CONFIG_DEDICATED *pucch_config_dedicated, diff --git a/openair1/SIMULATION/NR_PHY/pucchsim.c b/openair1/SIMULATION/NR_PHY/pucchsim.c index 3b7305bf9b..9e1609c3b4 100644 --- a/openair1/SIMULATION/NR_PHY/pucchsim.c +++ b/openair1/SIMULATION/NR_PHY/pucchsim.c @@ -93,11 +93,12 @@ int main(int argc, char **argv) uint8_t nrofSymbols=1; //number of OFDM symbols can be 1-2 for format 1 uint8_t startingSymbolIndex=0; // resource allocated see 9.2.1, 38.213 for more info.should be actually present in the resource set provided uint16_t startingPRB=0,startingPRB_intraSlotHopping=0; //PRB number not sure see 9.2.1, 38.213 for more info. Should be actually present in the resource set provided + uint16_t nrofPRB=2; uint8_t timeDomainOCC=0; SCM_t channel_model=AWGN;//Rayleigh1_anticorr; int N_RB_DL=273,mu=1; - float target_error_rate=0.01; + float target_error_rate=0.001; int frame_length_complex_samples; //int frame_length_complex_samples_no_prefix; NR_DL_FRAME_PARMS *frame_parms; @@ -112,9 +113,8 @@ int main(int argc, char **argv) randominit(0); logInit(); - set_glog(loglvl); - while ((c = getopt (argc, argv, "f:hA:f:g:i:I:P:B:b:T:m:n:r:o:s:S:x:y:z:N:F:GR:IL")) != -1) { + while ((c = getopt (argc, argv, "f:hA:f:g:i:I:P:B:b:T:m:n:r:o:s:S:x:y:z:N:F:GR:IL:q:")) != -1) { switch (c) { case 'f': //write_output_file=1; @@ -263,6 +263,9 @@ int main(int argc, char **argv) case 'r': startingPRB=atoi(optarg); break; + case 'q': + nrofPRB=atoi(optarg); + break; case 'P': format=atoi(optarg); break; @@ -305,7 +308,8 @@ int main(int argc, char **argv) printf("-F Input filename (.txt format) for RX conformance testing\n"); printf("-i Enter number of ofdm symbols for pucch\n"); printf("-I Starting symbol index for pucch\n"); - printf("-r PUCCCH starting PRB\n"); + printf("-r PUCCH starting PRB\n"); + printf("-q PUCCH number of PRB\n"); printf("-P Enter the format of PUCCH\n"); printf("-b number of HARQ bits (1-2)\n"); printf("-B payload to be transmitted on PUCCH\n"); @@ -316,18 +320,22 @@ int main(int argc, char **argv) } } + set_glog(loglvl); + if (snr1set==0) snr1 = snr0+10; printf("Initializing gNodeB for mu %d, N_RB_DL %d\n",mu,N_RB_DL); - if((format!=0) && (format!=1)){ + if((format!=0) && (format!=1) && (format!=2)){ printf("PUCCH format %d not supported\n",format); exit(0); } - AssertFatal((nr_bit<3)&&(actual_payload<4),"Only format 0 and 1 currently supported. 2 bits max supported"); + AssertFatal(((format < 2)&&(nr_bit<3)&&(actual_payload<4)) || + ((format == 2)&&(nr_bit>2)&&(nr_bit<12)),"illegal combination format %d, nr_bit %d\n", + format,nr_bit); - if (nr_bit==1) actual_payload = actual_payload&1; + actual_payload &= ((1<ofdm_symbol_size); - txdataF[i] = malloc(14*frame_parms->ofdm_symbol_size*sizeof(int)); + txdataF[i] = memalign(32,14*frame_parms->ofdm_symbol_size*sizeof(int)); bzero(txdataF[i],14*frame_parms->ofdm_symbol_size*sizeof(int)); - rxdataF[i] = malloc(14*frame_parms->ofdm_symbol_size*sizeof(int)); + rxdataF[i] = memalign(32,14*frame_parms->ofdm_symbol_size*sizeof(int)); bzero(rxdataF[i],14*frame_parms->ofdm_symbol_size*sizeof(int)); } @@ -443,8 +451,8 @@ int main(int argc, char **argv) uint8_t mcs=0; startingPRB_intraSlotHopping=N_RB_DL-1; pucch_GroupHopping_t PUCCH_GroupHopping=UE->pucch_config_common_nr->pucch_GroupHopping; - uint32_t n_id=UE->pucch_config_common_nr->hoppingId; - + uint32_t hopping_id=UE->pucch_config_common_nr->hoppingId; + uint32_t dmrs_scrambling_id = 0, data_scrambling_id=0; if(format==0){ // for now we are not considering SR just HARQ-ACK if(nr_bit==1) @@ -461,9 +469,12 @@ int main(int argc, char **argv) if(format==0){ nr_generate_pucch0(UE,txdataF,frame_parms,UE->pucch_config_dedicated,amp,nr_tti_tx,m0,mcs,nrofSymbols,startingSymbolIndex,startingPRB); } - else{ + else if (format == 1){ nr_generate_pucch1(UE,txdataF,frame_parms,UE->pucch_config_dedicated,actual_payload,amp,nr_tti_tx,m0,nrofSymbols,startingSymbolIndex,startingPRB,startingPRB_intraSlotHopping,0,nr_bit); } + else { + nr_generate_pucch2(UE,0x1234,dmrs_scrambling_id,data_scrambling_id,txdataF,frame_parms,UE->pucch_config_dedicated,actual_payload,amp,nr_tti_tx,nrofSymbols,startingSymbolIndex,nrofPRB,startingPRB,nr_bit); + } int txlev = signal_energy(&txdataF[aa][startingSymbolIndex*frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size); @@ -489,7 +500,7 @@ int main(int argc, char **argv) pucch_pdu.bit_len_harq = nr_bit; pucch_pdu.sr_flag = 0; pucch_pdu.nr_of_symbols = nrofSymbols; - pucch_pdu.hopping_id = n_id; + pucch_pdu.hopping_id = hopping_id; pucch_pdu.initial_cyclic_shift = 0; pucch_pdu.start_symbol_index = startingSymbolIndex; pucch_pdu.prb_start = startingPRB; @@ -497,21 +508,49 @@ int main(int argc, char **argv) if(nr_bit==1) ack_nack_errors+=(actual_payload^uci_pdu.harq->harq_list[0].harq_value); else - ack_nack_errors+=((actual_payload^uci_pdu.harq->harq_list[0].harq_value)+((actual_payload>>1)^uci_pdu.harq->harq_list[1].harq_value)); + ack_nack_errors+=(((actual_payload&1)^uci_pdu.harq->harq_list[0].harq_value)+((actual_payload>>1)^uci_pdu.harq->harq_list[1].harq_value)); free(uci_pdu.harq->harq_list); } - else{ + else if (format==1) { - nr_decode_pucch1(rxdataF,PUCCH_GroupHopping,n_id,&(payload_received),frame_parms,amp,nr_tti_tx,m0,nrofSymbols,startingSymbolIndex,startingPRB,startingPRB_intraSlotHopping,timeDomainOCC,nr_bit); + nr_decode_pucch1(rxdataF,PUCCH_GroupHopping,hopping_id,&(payload_received),frame_parms,amp,nr_tti_tx,m0,nrofSymbols,startingSymbolIndex,startingPRB,startingPRB_intraSlotHopping,timeDomainOCC,nr_bit); if(nr_bit==1) ack_nack_errors+=((actual_payload^payload_received)&1); else ack_nack_errors+=((actual_payload^payload_received)&1) + (((actual_payload^payload_received)&2)>>1); } + else if (format==2) { + nfapi_nr_uci_pucch_pdu_format_2_3_4_t uci_pdu; + nfapi_nr_pucch_pdu_t pucch_pdu; + pucch_pdu.rnti = 0x1234; + pucch_pdu.subcarrier_spacing = 1; + pucch_pdu.group_hop_flag = PUCCH_GroupHopping&1; + pucch_pdu.sequence_hop_flag = (PUCCH_GroupHopping>>1)&1; + pucch_pdu.bit_len_harq = nr_bit; + pucch_pdu.sr_flag = 0; + pucch_pdu.nr_of_symbols = nrofSymbols; + pucch_pdu.hopping_id = hopping_id; + pucch_pdu.initial_cyclic_shift = 0; + pucch_pdu.start_symbol_index = startingSymbolIndex; + pucch_pdu.prb_size = nrofPRB; + pucch_pdu.prb_start = startingPRB; + pucch_pdu.dmrs_scrambling_id = dmrs_scrambling_id; + pucch_pdu.data_scrambling_id = data_scrambling_id; + nr_decode_pucch2(gNB,nr_tti_tx,&uci_pdu,&pucch_pdu); + int harq_bytes=pucch_pdu.bit_len_harq>>3; + if ((pucch_pdu.bit_len_harq&7) > 0) harq_bytes++; + for (int i=0;i>1)+(((actual_payload^payload_received)&4)>>2)+n_errors; } printf("SNR=%f, n_trials=%d, n_bit_errors=%d\n",SNR,n_trials,ack_nack_errors); - if((float)ack_nack_errors/(float)(nr_bit*n_trials)<=target_error_rate){ + if((float)ack_nack_errors/(float)(n_trials)<=target_error_rate){ printf("PUCCH test OK\n"); break; } From 1e6e780a71679eeb3be35676726198b9c55834d3 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Wed, 22 Apr 2020 12:04:51 +0200 Subject: [PATCH 187/240] CI: final fixes for noS1 ping operations and LTE-M Signed-off-by: Raphael Defosseux --- ci-scripts/main.py | 25 ++++++++++++------------- ci-scripts/sshconnection.py | 7 +++++++ 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 1b65fe0f19..837c592bd7 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -86,7 +86,6 @@ class OaiCiTest(): self.CatMDevices = [] self.UEIPAddresses = [] self.htmlUEConnected = -1 - self.picocom_closure = False self.idle_sleep_time = 0 self.x2_ho_options = 'network' self.x2NbENBs = 0 @@ -452,7 +451,7 @@ class OaiCiTest(): logging.error('\u001B[1m oaitun_ue1 interface is either NOT mounted or NOT configured\u001B[0m') tunnelInterfaceStatus = False if RAN.GeteNBmbmsEnable(0): - self.command('ifconfig oaitun_uem1', '\$', 4) + SSH.command('ifconfig oaitun_uem1', '\$', 4) result = re.search('inet addr', SSH.getBefore()) if result is not None: logging.debug('\u001B[1m oaitun_uem1 interface is mounted and configured\u001B[0m') @@ -504,7 +503,7 @@ class OaiCiTest(): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': GenericHelp(Version) sys.exit('Insufficient Parameter') - self.picocom_closure = True + SSH.enablePicocomClosure() SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` SSH.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) @@ -514,10 +513,10 @@ class OaiCiTest(): SSH.command('AT', 'OK|ERROR', 5) SSH.command('AT', 'OK', 5) # Doing a power cycle - self.command('AT^RESET', 'SIMSTORE,READY', 15) - self.command('AT', 'OK|ERROR', 5) - self.command('AT', 'OK', 5) - self.command('ATE1', 'OK', 5) + SSH.command('AT^RESET', 'SIMSTORE,READY', 15) + SSH.command('AT', 'OK|ERROR', 5) + SSH.command('AT', 'OK', 5) + SSH.command('ATE1', 'OK', 5) # Disabling the Radio SSH.command('AT+CFUN=0', 'OK', 5) logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') @@ -535,7 +534,7 @@ class OaiCiTest(): logging.debug('\u001B[1;37;41m Could not check Auto-Attach! \u001B[0m') # Force closure of picocom but device might still be locked SSH.close() - self.picocom_closure = False + SSH.disablePicocomClosure() HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) self.checkDevTTYisUnlocked() @@ -543,7 +542,7 @@ class OaiCiTest(): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': GenericHelp(Version) sys.exit('Insufficient Parameter') - self.picocom_closure = True + SSH.enablePicocomClosure() SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` SSH.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) @@ -556,7 +555,7 @@ class OaiCiTest(): SSH.command('AT+CFUN=0', 'OK', 5) logging.debug('\u001B[1m Cellular Functionality disabled\u001B[0m') SSH.close() - self.picocom_closure = False + SSH.disablePicocomClosure() HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) self.checkDevTTYisUnlocked() @@ -564,7 +563,7 @@ class OaiCiTest(): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': GenericHelp(Version) sys.exit('Insufficient Parameter') - self.picocom_closure = True + SSH.enablePicocomClosure() SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) # dummy call to start a sudo session. The picocom command does NOT handle well the `sudo -S` SSH.command('echo ' + self.ADBPassword + ' | sudo -S ls', '\$', 10) @@ -615,7 +614,7 @@ class OaiCiTest(): logging.debug(' RSRQ = ' + str(-20+(nRSRQ/2)) + ' dB') logging.debug(' RSRP = ' + str(-140+nRSRP) + ' dBm') SSH.close() - self.picocom_closure = False + SSH.disablePicocomClosure() html_queue = SimpleQueue() self.checkDevTTYisUnlocked() if attach_status: @@ -1382,7 +1381,7 @@ class OaiCiTest(): sys.exit('Insufficient Parameter') try: if ping_from_eNB is not None: - SSH.open(RAN.GeteNBIPAddress, RAN.GeteNBUserName, RAN.GeteNBPassword) + SSH.open(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword()) SSH.command('cd ' + RAN.GeteNBSourceCodePath() + '/cmake_targets/', '\$', 5) else: SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) diff --git a/ci-scripts/sshconnection.py b/ci-scripts/sshconnection.py index cdd062f846..649ffef26c 100644 --- a/ci-scripts/sshconnection.py +++ b/ci-scripts/sshconnection.py @@ -42,6 +42,13 @@ import re class SSHConnection(): def __init__(self): self.ssh = '' + self.picocom_closure = False + + def disablePicocomClosure(self): + self.picocom_closure = False + + def enablePicocomClosure(self): + self.picocom_closure = True def open(self, ipaddress, username, password): count = 0 From 009609f1f31bdcef33770222ecdebbccdb7bbba8 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Wed, 22 Apr 2020 16:46:42 +0200 Subject: [PATCH 188/240] DOC: update L2 nFAPI simulator Signed-off-by: Raphael Defosseux --- doc/L2NFAPI.md | 19 +- doc/L2NFAPI_NOS1.md | 349 +++++++++++++++++++ doc/L2NFAPI_S1.md | 167 +++++---- doc/images/L2-sim-S1-3-host-deployment.png | Bin 0 -> 88726 bytes doc/images/L2-sim-noS1-2-host-deployment.png | Bin 0 -> 57368 bytes 5 files changed, 458 insertions(+), 77 deletions(-) create mode 100644 doc/L2NFAPI_NOS1.md create mode 100644 doc/images/L2-sim-S1-3-host-deployment.png create mode 100644 doc/images/L2-sim-noS1-2-host-deployment.png diff --git a/doc/L2NFAPI.md b/doc/L2NFAPI.md index 4dcaaef3bc..137e4847e4 100644 --- a/doc/L2NFAPI.md +++ b/doc/L2NFAPI.md @@ -14,19 +14,24 @@ This simulator allows to test L2 and above Layers using the nFAPI interface. +The UE executable is able to "simulate" multiple UEs in order to stimulate the scheduler in the eNB. + **This simulator is available starting the `v1.0.0` release on the `master` branch.** -Currently the only validated deployment by CI and developers is *with S1 interface and eNB / UEs are on the same machine*. - -Others deployments will be supported later after bug fixes and validation in the CI process. - -1. [With S1 -- eNB and UE on same machine](L2NFAPI_S1.md) - - +Currently the Continuous Integration process is validating this simulator the following way: +* the LTE modem executable is run on one host (in our CI deployment it is a **Xenial Virtual Machine**) +* the UE(s) modem executable is run on another host (in our CI deployment it is also a **Xenial Virtual Machine**) +* We are testing: + * in S1 mode (ie we are connected to a 3rd-party EPC) + * in noS1 mode (no need for an EPC) +Normally it should be fine to run both executables on the same host using the `loopback` interface to communicate. **But we are not guaranting it** +1. [With S1 -- eNB and UE on 2 hosts](L2NFAPI_S1.md) +2. [No S1 -- eNB and UE on 2 hosts](L2NFAPI_NOS1.md) +---- [oai wiki home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home) diff --git a/doc/L2NFAPI_NOS1.md b/doc/L2NFAPI_NOS1.md new file mode 100644 index 0000000000..bb4c32ec08 --- /dev/null +++ b/doc/L2NFAPI_NOS1.md @@ -0,0 +1,349 @@ +
' + str('eNB') + ' Server Characteristics
OS Version' + self.OsVersion + '' + self.OsVersion[idx] + 'Kernel Version' + self.KernelVersion + '' + self.KernelVersion[idx] + 'UHD Version' + self.UhdVersion + '' + self.UhdVersion[idx] + 'USRP Board' + self.UsrpBoard + '' + self.UsrpBoard[idx] + '
Nb CPUs' + self.CpuNb + '' + self.CpuNb[idx] + 'CPU Model Name' + self.CpuModel + '' + self.CpuModel[idx] + 'CPU Frequency' + self.CpuMHz + '
' + str('UE') + ' Server Characteristics
OS Version' + self.OsVersion + 'Kernel Version' + self.KernelVersion + 'UHD Version' + self.UhdVersion + 'USRP Board' + self.UsrpBoard + '
Nb CPUs' + self.CpuNb + 'CPU Model Name' + self.CpuModel + 'CPU Frequency' + self.CpuMHz + '' + self.CpuMHz[idx] + '
' + str(status) + 'KO - eNB process not foundKO - OAI UE process not foundKO - ' + machine + ' process ended in Segmentation FaultKO - ' + machine + ' process ended in AssertionKO - ' + machine + ' process faced Real Time issue(s)OK?KO - ' + machine + ' Slave RRU could not synchKO - UE could not syncKO - HSS process not foundKO - MME process not foundKO - SPGW process not foundKO - Could not retrieve UE IP address' + str(status) + '
+ + + + +
+ + + + + + L2 nFAPI Simulator (no S1 Mode / 2-host deployment) +
+ +## Table of Contents ## + +1. [Environment](#1-environment) +2. [Retrieve the OAI eNB-UE source code](#2-retrieve-the-oai-enb-ue-source-code) +3. [Setup of the USIM information in UE folder](#3-setup-of-the-usim-information-in-ue-folder) +4. [Setup of the Configuration files](#4-setup-of-the-configuration-files) + 1. [The eNB Configuration file](#41-the-enb-configuration-file) + 2. [The UE Configuration file](#42-the-ue-configuration-file) +5. [Build OAI UE and eNodeB](#5-build-oai-ue-and-enodeb) +6. [Start the eNB](#6-start-the-enb) +7. [Start the UE](#7-start-the-ue) +8. [Test with ping](#8-test-with-ping) +9. [Limitations](#9-limitations) + +# 1. Environment # + +You may not have access to an EPC or you don't want to hassle to deploy one. + +2 servers are used in this deployment. You can use Virtual Machines instead of each server; like it is done in the CI process. + +* Machine B contains the OAI eNB executable (`lte-softmodem`) +* Machine C contains the OAI UE(s) executable (`lte-uesoftmodem`) + +Example of L2 nFAPI Simulator testing environment: + + + +Note that the IP addresses are indicative and need to be adapted to your environment. + +# 2. Retrieve the OAI eNB-UE source code # + +At the time of writing, the tag used in the `develop` branch to do this documentation was `2020.w16`. + +The tutorial should be valid for the `master` branch tags such as `v1.2.0` or `v1.2.1`. But you may face issues that could be fixed in newer `develop` tags. + +Please try to use the same commit ID on both eNB/UE hosts. + +```bash +$ ssh sudousername@machineB +git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git enb_folder +cd enb_folder +git checkout develop +``` + +```bash +$ ssh sudousername@machineC +git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git ue_folder +cd ue_folder +git checkout develop +``` + +# 3. Setup of the USIM information in UE folder # + +```bash +$ ssh sudousername@machineC +cd ue_folder +# Edit openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf with your preferred editor +``` + +Edit the USIM information within this file in order to match the HSS database. They **HAVE TO** match: + +* PLMN+MSIN and IMSI of users table of HSS database **SHALL** be the same. +* OPC of this file and OPC of users table of HSS database **SHALL** be the same. +* USIM_API_K of this file and the key of users table of HSS database **SHALL** be the same. + +When testing multiple UEs, it is necessary to add other UEs information like described below for 2 Users. Only UE0 (first UE) information is written in the original file. + +``` +UE0: +{ + USER: { + IMEI="356113022094149"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; + + SIM: { + MSIN="0000000001"; // <-- Modify here + USIM_API_K="8baf473f2f8fd09487cccbd7097c6862"; + OPC="e734f8734007d6c5ce7a0508809e7e9c"; + MSISDN="33611123456"; + }; +... +}; +// Copy the UE0 and edit +UE1: // <- Edit here +{ + USER: { + IMEI="356113022094149"; + MANUFACTURER="EURECOM"; + MODEL="LTE Android PC"; + PIN="0000"; + }; + + SIM: { + MSIN="0000000002"; // <-- Modify here + USIM_API_K="8baf473f2f8fd09487cccbd7097c6862"; + OPC="e734f8734007d6c5ce7a0508809e7e9c"; + MSISDN="33611123456"; + }; +... +}; +``` + +You can repeat the operation for as many users you want to test with. + +# 4. Setup of the Configuration files # + +**CAUTION: both proposed configuration files resides in the ci-scripts realm. You can copy them but you CANNOT push any modification on these 2 files as part of an MR without informing the CI team.** + +## 4.1. The eNB Configuration file ## + +```bash +$ ssh sudousername@machineB +cd enb_folder +# Edit ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf with your preferred editor +``` + +First verify the nFAPI interface setup on the physical ethernet interface of machineB and put the proper IP addresses for both hosts. + +``` +MACRLCs = ( + { + num_cc = 1; + local_s_if_name = "ens3"; // <-- HERE + remote_s_address = "192.168.122.169"; // <-- HERE + local_s_address = "192.168.122.31"; // <-- HERE + local_s_portc = 50001; + remote_s_portc = 50000; + local_s_portd = 50011; + remote_s_portd = 50010; + tr_s_preference = "nfapi"; + tr_n_preference = "local_RRC"; + } +); +``` + +If you are testing more than 16 UEs, a proper setting on the RUs is necessary. **Note that this part is NOT present in the original configuration file**. + +``` +RUs = ( + { + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 20 + att_rx = 0; + bands = [38]; + max_pdschReferenceSignalPower = -23; + max_rxgain = 116; + eNB_instances = [0]; + } +); +``` + +Last, the S1 interface shall be properly set. + +``` + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; // replace with 192.168.122.195 + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "ens3"; // replace with the proper interface name + ENB_IPV4_ADDRESS_FOR_S1_MME = "CI_ENB_IP_ADDR"; // replace with 192.168.122.31 + ENB_INTERFACE_NAME_FOR_S1U = "ens3"; // replace with the proper interface name + ENB_IPV4_ADDRESS_FOR_S1U = "CI_ENB_IP_ADDR"; // replace with 192.168.122.31 + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + ENB_IPV4_ADDRESS_FOR_X2C = "CI_ENB_IP_ADDR"; // replace with 192.168.122.31 + ENB_PORT_FOR_X2C = 36422; # Spec 36422 + + }; +``` + +## 4.2. The UE Configuration file ## + +```bash +$ ssh sudousername@machineB +cd ue_folder +# Edit ci-scripts/conf_files/ue.nfapi.conf with your preferred editor +``` + +Verify the nFAPI interface setup on the loopback interface. + +``` +L1s = ( + { + num_cc = 1; + tr_n_preference = "nfapi"; + local_n_if_name = "ens3"; // <- HERE + remote_n_address = "192.168.122.31"; // <- HERE + local_n_address = "192.168.122.169"; // <- HERE + local_n_portc = 50000; + remote_n_portc = 50001; + local_n_portd = 50010; + remote_n_portd = 50011; + } +); +``` + +# 5. Build OAI UE and eNodeB # + +See [Build documentation](./BUILD.md). + +# 6. Start the eNB # + +In the first terminal (the one you used to build the eNB): + +```bash +$ ssh sudousername@machineB +cd enb_folder/cmake_targets +sudo -E ./ran_build/build/lte-softmodem -O ../ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf --noS1 > enb.log 2>&1 +sleep 10 +ifconfig +ens3 Link encap:Ethernet HWaddr XX:XX:XX:XX:XX:XX + inet addr:192.168.122.31 Bcast:192.168.122.255 Mask:255.255.255.0 +.... +oaitun_enb1 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 + inet addr:10.0.1.1 P-t-P:192.172.0.2 Mask:255.255.255.0 +.... +``` + +If you don't use redirection, you can test but many logs are printed on the console and this may affect performance of the L2-nFAPI simulator. + +We do recommend the redirection in steady mode once your setup is correct. + +# 7. Start the UE # + +In the second terminal (the one you used to build the UE): + +```bash +$ ssh sudousername@machineC +cd ue_folder/cmake_targets +# Test 64 UEs, 1 thread in FDD mode +sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/ue.nfapi.conf --noS1 --L2-emul 3 --num-ues 64 --nums_ue_thread 1 --nokrnmod 1 > ue.log 2>&1 +# Test 64 UEs, 1 thread in TDD mode +sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/ue.nfapi.conf --noS1 --L2-emul 3 --num-ues 64 --nums_ue_thread 1 --nokrnmod 1 -T 1 > ue.log 2>&1 +# The "-T 1" option means TDD config +``` + +- The number of UEs can set by using `--num-ues` option and the maximum UE number is 255 (with the `--mu*` options, otherwise 16). +- The number of threads can set with the `--nums-ue-thread`. This number **SHALL NOT** be greater than the number of UEs. + * At the time of writing, it seems to be enough to run on a single thread. +- The `--nokrnmod 1` option makes use of the preferred and supported tunnel interface. +- How many UE that can be tested depends on hardware (server , PC, etc) performance in your environment. + +For example, running with 4 UEs: + +```bash +$ ssh sudousername@machineC +cd ue_folder/cmake_targets +sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/ue.nfapi.conf --noS1 --L2-emul 3 --num-ues 64 --nums_ue_thread 1 --nokrnmod 1 > ue.log 2>&1 +sleep 10 +ifconfig +ens3 Link encap:Ethernet HWaddr XX:XX:XX:XX:XX:XX + inet addr:192.168.122.169 Bcast:192.168.122.255 Mask:255.255.255.0 +.... +oaitun_ue1 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 + inet addr:10.0.1.2 P-t-P:192.172.0.2 Mask:255.255.255.0 +.... +oaitun_ue2 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 + inet addr:10.0.1.3 P-t-P:192.172.0.3 Mask:255.255.255.0 +.... +oaitun_ue3 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 + inet addr:10.0.1.4 P-t-P:192.172.0.4 Mask:255.255.255.0 +.... +oaitun_ue4 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 + inet addr:10.0.1.5 P-t-P:192.172.0.5 Mask:255.255.255.0 +.... +oaitun_uem1 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 + inet addr:10.0.2.2 P-t-P:10.0.2.2 Mask:255.255.255.0 +.... +.... +``` + +Having the 4 oaitun_ue tunnel interfaces up and with an allocated address means the connection with EPC went alright. + +# 8. Test with ping # + +In a third terminal, after around 10 seconds, the UE(s) shall be connected to the eNB: Check with ifconfig + +```bash +$ ssh sudousername@machineB +# Ping UE1 IP address based on the EPC pool used: in this example: +ping -I oaitun_enb1 -c 20 10.0.1.2 +# Ping UE4 IP address based on the EPC pool used: in this example: +ping -I oaitun_enb1 -c 20 10.0.1.5 +``` + +Ping from the UE side: + +```bash +$ ssh sudousername@machineC +ping -I oaitun_ue1 -c 20 10.0.1.1 +ping -I oaitun_ue3 -c 20 10.0.1.1 +``` + +iperf operations can also be performed. + +DL traffic: + +```bash +$ ssh sudousername@machineC +iperf -B 10.0.1.2 -u -s -i 1 -fm -p 5002 +$ ssh sudousername@machineB +iperf -c 10.0.1.2 -u -t 30 -b 3M -i 1 -fm -B 10.0.1.1 -p 5002 +``` + +UL traffic: + +```bash +$ ssh sudousername@machineB +iperf -B 10.0.1.1 -u -s -i 1 -fm -p 5002 +$ ssh sudousername@machineC +iperf -c 10.0.1.1 -u -t 30 -b 2M -i 1 -fm -B 10.0.1.2 -p 5002 +``` + +# 9. Limitations # + + +---- + +[oai wiki home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home) + +[oai softmodem features](FEATURE_SET.md) + +[oai softmodem build procedure](BUILD.md) + +[L2 nfapi simulator](L2NFAPI.md) diff --git a/doc/L2NFAPI_S1.md b/doc/L2NFAPI_S1.md index b9156e9379..9fd6d51818 100644 --- a/doc/L2NFAPI_S1.md +++ b/doc/L2NFAPI_S1.md @@ -7,7 +7,7 @@ - L2 nFAPI Simulator (with S1 / same machine deployment) + L2 nFAPI Simulator (with S1 / 2-host deployment) @@ -21,25 +21,24 @@ 5. [Setup of the Configuration files](#5-setup-of-the-configuration-files) 1. [The eNB Configuration file](#51-the-enb-configuration-file) 2. [The UE Configuration file](#52-the-ue-configuration-file) -6. [Bring Up a second loopback interface](#6-bring-up-a-second-loopback-interface) -7. [Build the eNB](#7-build-the-enb) -8. [Build the UE](#8-build-the-ue) -9. [Initialize the NAS UE Layer](#9-initialize-the-nas-ue-layer) -10. [Start the eNB](#10-start-the-enb) -11. [Start the UE](#11-start-the-ue) -12. [Test with ping](#12-test-with-ping) -13. [Limitations](#13-limitations) +6. [Build OAI UE and eNodeB](#6-build-oai-ue-and-enodeb) +7. [Start EPC](#7-start-epc) +8. [Start the eNB](#8-start-the-enb) +9. [Start the UE](#9-start-the-ue) +10. [Test with ping](#10-test-with-ping) +11. [Limitations](#11-limitations) # 1. Environment # -2 servers are used in this deployment. You can use Virtual Machines instead of each server; like it is done in the CI process. +3 servers are used in this deployment. You can use Virtual Machines instead of each server; like it is done in the CI process. * Machine A contains the EPC. -* Machine B contains the OAI eNB and the OAI UE(s) +* Machine B contains the OAI eNB executable (`lte-softmodem`) +* Machine C contains the OAI UE(s) executable (`lte-uesoftmodem`) Example of L2 nFAPI Simulator testing environment: - + Note that the IP addresses are indicative and need to be adapted to your environment. @@ -47,26 +46,35 @@ Note that the IP addresses are indicative and need to be adapted to your environ Create the environment for the EPC and register all **USIM** information into the **HSS** database. -If you are using OAI-EPC ([see on GitHub](https://github.com/OPENAIRINTERFACE/openair-cn)), build **HSS/MME/SPGW** and create config files. +If you are using OAI-EPC ([see on GitHub](https://github.com/OPENAIRINTERFACE/openair-epc-fed)), build **HSS/MME/SPGW** and create config files. # 3. Retrieve the OAI eNB-UE source code # -The eNB and the UE executables will compiled into 2 separate folders on the same machine `B`. +At the time of writing, the tag used in the `develop` branch to do this documentation was `2020.w16`. + +The tutorial should be valid for the `master` branch tags such as `v1.2.0` or `v1.2.1`. But you may face issues that could be fixed in newer `develop` tags. + +Please try to use the same commit ID on both eNB/UE hosts. ```bash $ ssh sudousername@machineB -$ git clone https://gitlab.eurecom.fr/oai/openairinterface5g/ enb_folder -$ cd enb_folder -$ git checkout -f v1.0.0 -$ cd .. -$ cp -Rf enb_folder ue_folder +git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git enb_folder +cd enb_folder +git checkout develop +``` + +```bash +$ ssh sudousername@machineC +git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git ue_folder +cd ue_folder +git checkout develop ``` # 4. Setup of the USIM information in UE folder # ```bash -$ ssh sudousername@machineB -$ cd ue_folder +$ ssh sudousername@machineC +cd ue_folder # Edit openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf with your preferred editor ``` @@ -126,19 +134,19 @@ You can repeat the operation for as many users you want to test with. ```bash $ ssh sudousername@machineB -$ cd enb_folder +cd enb_folder # Edit ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf with your preferred editor ``` -First verify the nFAPI interface setup on the 2nd loopback interface. +First verify the nFAPI interface setup on the physical ethernet interface of machineB and put the proper IP addresses for both hosts. ``` MACRLCs = ( { num_cc = 1; - local_s_if_name = "lo:"; // <-- HERE - remote_s_address = "127.0.0.1"; // <-- HERE - local_s_address = "127.0.0.2"; // <-- HERE + local_s_if_name = "ens3"; // <-- HERE + remote_s_address = "192.168.122.169"; // <-- HERE + local_s_address = "192.168.122.31"; // <-- HERE local_s_portc = 50001; remote_s_portc = 50000; local_s_portd = 50011; @@ -171,7 +179,7 @@ Last, the S1 interface shall be properly set. ``` ////////// MME parameters: - mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; // replace with 192.168.10.20 + mme_ip_address = ( { ipv4 = "CI_MME_IP_ADDR"; // replace with 192.168.122.195 ipv6 = "192:168:30::17"; active = "yes"; preference = "ipv4"; @@ -181,11 +189,11 @@ Last, the S1 interface shall be properly set. NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "ens3"; // replace with the proper interface name - ENB_IPV4_ADDRESS_FOR_S1_MME = "CI_ENB_IP_ADDR"; // replace with 192.168.10.10 + ENB_IPV4_ADDRESS_FOR_S1_MME = "CI_ENB_IP_ADDR"; // replace with 192.168.122.31 ENB_INTERFACE_NAME_FOR_S1U = "ens3"; // replace with the proper interface name - ENB_IPV4_ADDRESS_FOR_S1U = "CI_ENB_IP_ADDR"; // replace with 192.168.10.10 + ENB_IPV4_ADDRESS_FOR_S1U = "CI_ENB_IP_ADDR"; // replace with 192.168.122.31 ENB_PORT_FOR_S1U = 2152; # Spec 2152 - ENB_IPV4_ADDRESS_FOR_X2C = "CI_ENB_IP_ADDR"; // replace with 192.168.10.10 + ENB_IPV4_ADDRESS_FOR_X2C = "CI_ENB_IP_ADDR"; // replace with 192.168.122.31 ENB_PORT_FOR_X2C = 36422; # Spec 36422 }; @@ -195,7 +203,7 @@ Last, the S1 interface shall be properly set. ```bash $ ssh sudousername@machineB -$ cd ue_folder +cd ue_folder # Edit ci-scripts/conf_files/ue.nfapi.conf with your preferred editor ``` @@ -206,9 +214,9 @@ L1s = ( { num_cc = 1; tr_n_preference = "nfapi"; - local_n_if_name = "lo"; // <- HERE - remote_n_address = "127.0.0.2"; // <- HERE - local_n_address = "127.0.0.1"; // <- HERE + local_n_if_name = "ens3"; // <- HERE + remote_n_address = "192.168.122.31"; // <- HERE + local_n_address = "192.168.122.169"; // <- HERE local_n_portc = 50000; remote_n_portc = 50001; local_n_portd = 50010; @@ -217,20 +225,11 @@ L1s = ( ); ``` -# 6. Bring Up a second loopback interface # +# 6. Build OAI UE and eNodeB # -A second loopback interface is used to connect the eNB and the UEs. +See [Build documentation](./BUILD.md). -```bash -$ ssh sudousername@machineB -$ sudo ifconfig lo: 127.0.0.2 netmask 255.0.0.0 up -``` - -# 7. [Build OAI UE and eNodeB](BUILD.md) # - - - -# 8. Initialize the NAS UE Layer # +# 7. Start EPC # Start the EPC on machine `A`. @@ -239,61 +238,89 @@ $ ssh sudousername@machineA # Start the EPC ``` -# 9. Start the eNB # +# 8. Start the eNB # In the first terminal (the one you used to build the eNB): ```bash $ ssh sudousername@machineB -$ cd enb_folder/cmake_targets -$ sudo -E ./ran_build/build/lte-softmodem -O ../ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf > enb.log 2>&1 +cd enb_folder/cmake_targets +sudo -E ./ran_build/build/lte-softmodem -O ../ci-scripts/conf_files/rcc.band7.tm1.nfapi.conf > enb.log 2>&1 ``` If you don't use redirection, you can test but many logs are printed on the console and this may affect performance of the L2-nFAPI simulator. We do recommend the redirection in steady mode once your setup is correct. -# 10. Start the UE # +# 9. Start the UE # In the second terminal (the one you used to build the UE): ```bash -$ ssh sudousername@machineB -$ cd ue_folder/cmake_targets -# Test 64 UEs, 64 threads in FDD mode -$ sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/ue.nfapi.conf --L2-emul 3 --num-ues 64 --nums-ue-thread 64 > ue.log 2>&1 -# Test 64 UEs, 64 threads in TDD mode -$ sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/ue.nfapi.conf --L2-emul 3 --num-ues 64 --nums-ue-thread 64 -T 1 > ue.log 2>&1 +$ ssh sudousername@machineC +cd ue_folder/cmake_targets +# Test 64 UEs, 1 thread in FDD mode +sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/ue.nfapi.conf --L2-emul 3 --num-ues 64 --nums_ue_thread 1 --nokrnmod 1 > ue.log 2>&1 +# Test 64 UEs, 1 thread in TDD mode +sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/ue.nfapi.conf --L2-emul 3 --num-ues 64 --nums_ue_thread 1 --nokrnmod 1 -T 1 > ue.log 2>&1 # The "-T 1" option means TDD config ``` - The number of UEs can set by using `--num-ues` option and the maximum UE number is 255 (with the `--mu*` options, otherwise 16). -- The umber of threads can set with the `--nums-ue-thread`. This number **SHALL NOT** be greater than the number of UEs. +- The number of threads can set with the `--nums-ue-thread`. This number **SHALL NOT** be greater than the number of UEs. + * At the time of writing, it seems to be enough to run on a single thread. +- The `--nokrnmod 1` option makes use of the preferred and supported tunnel interface. - How many UE that can be tested depends on hardware (server , PC, etc) performance in your environment. -# 11. Test with ping # +For example, running with 4 UEs: -In a third terminal, after around 10 seconds, the UE(s) shall be connected to the eNB: +```bash +$ ssh sudousername@machineC +cd ue_folder/cmake_targets +sudo -E ./ran_build/build/lte-uesoftmodem -O ../ci-scripts/conf_files/ue.nfapi.conf --L2-emul 3 --num-ues 64 --nums_ue_thread 1 --nokrnmod 1 > ue.log 2>&1 +sleep 10 +ifconfig +ens3 Link encap:Ethernet HWaddr XX:XX:XX:XX:XX:XX + inet addr:192.168.122.169 Bcast:192.168.122.255 Mask:255.255.255.0 +.... +oaitun_ue1 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 + inet addr:192.172.0.2 P-t-P:192.172.0.2 Mask:255.255.255.0 +.... +oaitun_ue2 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 + inet addr:192.172.0.3 P-t-P:192.172.0.3 Mask:255.255.255.0 +.... +oaitun_ue3 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 + inet addr:192.172.0.4 P-t-P:192.172.0.4 Mask:255.255.255.0 +.... +oaitun_ue4 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 + inet addr:192.172.0.5 P-t-P:192.172.0.5 Mask:255.255.255.0 +.... +oaitun_uem1 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 + inet addr:10.0.2.2 P-t-P:10.0.2.2 Mask:255.255.255.0 +.... +.... +``` + +Having the 4 oaitun_ue tunnel interfaces up and with an allocated address means the connection with EPC went alright. + +# 10. Test with ping # + +In a third terminal, after around 10 seconds, the UE(s) shall be connected to the eNB: Check with ifconfig ```bash $ ssh sudousername@machineA -# Ping UE0 IP address based on the EPC pool used: in this example: -$ ping -c 20 192.168.200.2 # Ping UE1 IP address based on the EPC pool used: in this example: -$ ping -c 20 192.168.200.4 +$ ping -c 20 192.172.0.2 +# Ping UE4 IP address based on the EPC pool used: in this example: +$ ping -c 20 192.172.0.5 ``` -# 12. Limitations # - -Testing on the CI process is currently limited at time of writing. Improvements will be made soon. - - - - - +iperf operations can also be performed. +# 11. Limitations # +---- [oai wiki home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home) diff --git a/doc/images/L2-sim-S1-3-host-deployment.png b/doc/images/L2-sim-S1-3-host-deployment.png new file mode 100644 index 0000000000000000000000000000000000000000..4049ebd7a8ace60df576a988f32442526af7f13e GIT binary patch literal 88726 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 literal 0 HcmV?d00001 diff --git a/doc/images/L2-sim-noS1-2-host-deployment.png b/doc/images/L2-sim-noS1-2-host-deployment.png new file mode 100644 index 0000000000000000000000000000000000000000..02d29b7b3cdfb05dc912548e001fb11aa1d96fc8 GIT binary patch literal 57368 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

7PsQt@ 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 literal 0 HcmV?d00001 From a0cf40774264ad2f9c4c0c69efdb391aa373be5a Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Wed, 22 Apr 2020 17:26:34 +0200 Subject: [PATCH 189/240] CI: final fixes on help functions Signed-off-by: Raphael Defosseux --- ci-scripts/constants.py | 2 +- ci-scripts/epc.py | 6 +- ci-scripts/html.py | 4 +- ci-scripts/main.py | 162 ++++++++++-------- ci-scripts/ran.py | 10 +- .../enb_usrp210_band40_test_05mhz_tm2.xml | 2 +- 6 files changed, 98 insertions(+), 88 deletions(-) diff --git a/ci-scripts/constants.py b/ci-scripts/constants.py index ca3cde446d..1e7e84fb32 100644 --- a/ci-scripts/constants.py +++ b/ci-scripts/constants.py @@ -31,7 +31,7 @@ #----------------------------------------------------------- # Version #----------------------------------------------------------- -Version = '0.1' +Version = '0.2' #----------------------------------------------------------- # Constants diff --git a/ci-scripts/epc.py b/ci-scripts/epc.py index e67de43b09..4926f2d6e8 100644 --- a/ci-scripts/epc.py +++ b/ci-scripts/epc.py @@ -96,7 +96,7 @@ class EPCManagement(): def InitializeHSS(self): if self.IPAddress == '' or self.UserName == '' or self.Password == '' or self.SourceCodePath == '' or self.Type == '': - HELP.GenericHelp(Version) + HELP.GenericHelp(CONST.Version) HELP.EPCSrvHelp(self.IPAddress, self.UserName, self.Password, self.SourceCodePath, self.Type) sys.exit('Insufficient EPC Parameters') mySSH = SSH.SSHConnection() @@ -134,7 +134,7 @@ class EPCManagement(): def InitializeMME(self): if self.IPAddress == '' or self.UserName == '' or self.Password == '' or self.SourceCodePath == '' or self.Type == '': - HELP.GenericHelp(Version) + HELP.GenericHelp(CONST.Version) HELP.EPCSrvHelp(self.IPAddress, self.UserName, self.Password, self.SourceCodePath, self.Type) sys.exit('Insufficient EPC Parameters') mySSH = SSH.SSHConnection() @@ -168,7 +168,7 @@ class EPCManagement(): def InitializeSPGW(self): if self.IPAddress == '' or self.UserName == '' or self.Password == '' or self.SourceCodePath == '' or self.Type == '': - HELP.GenericHelp(Version) + HELP.GenericHelp(CONST.Version) HELP.EPCSrvHelp(self.IPAddress, self.UserName, self.Password, self.SourceCodePath, self.Type) sys.exit('Insufficient EPC Parameters') mySSH = SSH.SSHConnection() diff --git a/ci-scripts/html.py b/ci-scripts/html.py index 67deaa75ce..3d0c8f3897 100644 --- a/ci-scripts/html.py +++ b/ci-scripts/html.py @@ -363,8 +363,8 @@ class HTMLManagement(): def CreateHtmlRetrySeparator(self, cntnumfails): if ((not self.htmlFooterCreated) and (self.htmlHeaderCreated)): self.htmlFile = open('test_results.html', 'a') - self.htmlFile.write(' \n') - self.htmlFile.write(' Try Run #' + str(cntnumfails) + '\n') + self.htmlFile.write(' \n') + self.htmlFile.write(' ---- Try Run #' + str(cntnumfails) + ' ---- \n') self.htmlFile.write(' \n') self.htmlFile.close() diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 837c592bd7..1e149c4050 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -30,11 +30,6 @@ import constants as CONST -#----------------------------------------------------------- -# Version -#----------------------------------------------------------- -Version = '0.1' - #----------------------------------------------------------- # Import #----------------------------------------------------------- @@ -61,6 +56,12 @@ logging.basicConfig( class OaiCiTest(): def __init__(self): + self.ranRepository = '' + self.ranBranch = '' + self.ranCommitID = '' + self.ranAllowMerge = False + self.ranTargetBranch = '' + self.FailReportCnt = 0 self.ADBIPAddress = '' self.ADBUserName = '' @@ -105,8 +106,8 @@ class OaiCiTest(): self.expectedNbOfConnectedUEs = 0 def BuildOAIUE(self): - if self.UEIPAddress == '' or RAN.GetranRepository() == '' or RAN.GetranBranch() == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': - GenericHelp(Version) + if self.UEIPAddress == '' or self.ranRepository == '' or self.ranBranch == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) result = re.search('--nrUE', self.Build_OAI_UE_args) @@ -116,11 +117,11 @@ class OaiCiTest(): else: RAN.Setair_interface('lte') ue_prefix = '' - result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', RAN.GetranRepository()) + result = re.search('([a-zA-Z0-9\:\-\.\/])+\.git', self.ranRepository) if result is not None: - full_ran_repo_name = RAN.GetranRepository() + full_ran_repo_name = self.ranRepository else: - full_ran_repo_name = RAN.GetranRepository() + '.git' + full_ran_repo_name = self.ranRepository + '.git' SSH.command('mkdir -p ' + self.UESourceCodePath, '\$', 5) SSH.command('cd ' + self.UESourceCodePath, '\$', 5) SSH.command('if [ ! -e .git ]; then stdbuf -o0 git clone ' + full_ran_repo_name + ' .; else stdbuf -o0 git fetch --prune; fi', '\$', 600) @@ -133,19 +134,19 @@ class OaiCiTest(): if result is not None: mismatch = False SSH.command('grep SRC_COMMIT LAST_BUILD_INFO.txt', '\$', 2) - result = re.search(RAN.GetranCommitID(), SSH.getBefore()) + result = re.search(self.ranCommitID, SSH.getBefore()) if result is None: mismatch = True SSH.command('grep MERGED_W_TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) - if (RAN.GetranAllowMerge()): + if self.ranAllowMerge: result = re.search('YES', SSH.getBefore()) if result is None: mismatch = True SSH.command('grep TGT_BRANCH LAST_BUILD_INFO.txt', '\$', 2) - if RAN.GetranTargetBranch() == '': + if self.ranTargetBranch == '': result = re.search('develop', SSH.getBefore()) else: - result = re.search(RAN.GetranTargetBranch(), SSH.getBefore()) + result = re.search(self.ranTargetBranch, SSH.getBefore()) if result is None: mismatch = True else: @@ -160,17 +161,17 @@ class OaiCiTest(): SSH.command('echo ' + self.UEPassword + ' | sudo -S git clean -x -d -ff', '\$', 30) # if the commit ID is provided use it to point to it - if RAN.GetranCommitID() != '': - SSH.command('git checkout -f ' + RAN.GetranCommitID(), '\$', 5) + if self.ranCommitID != '': + SSH.command('git checkout -f ' + self.ranCommitID, '\$', 5) # if the branch is not develop, then it is a merge request and we need to do # the potential merge. Note that merge conflicts should already been checked earlier - if (RAN.GetranAllowMerge()): - if RAN.GetranTargetBranch() == '': - if (RAN.GetranBranch() != 'develop') and (RAN.GetranBranch() != 'origin/develop'): + if self.ranAllowMerge: + if self.ranTargetBranch == '': + if (self.ranBranch != 'develop') and (self.ranBranch != 'origin/develop'): SSH.command('git merge --ff origin/develop -m "Temporary merge for CI"', '\$', 5) else: - logging.debug('Merging with the target branch: ' + RAN.GetranTargetBranch()) - SSH.command('git merge --ff origin/' + RAN.GetranTargetBranch() + ' -m "Temporary merge for CI"', '\$', 5) + logging.debug('Merging with the target branch: ' + self.ranTargetBranch) + SSH.command('git merge --ff origin/' + self.ranTargetBranch + ' -m "Temporary merge for CI"', '\$', 5) SSH.command('source oaienv', '\$', 5) SSH.command('cd cmake_targets', '\$', 5) SSH.command('mkdir -p log', '\$', 5) @@ -188,14 +189,14 @@ class OaiCiTest(): SSH.command('mv compile_oai_ue.log ' + 'build_log_' + self.testCase_id, '\$', 5) if buildStatus: # Generating a BUILD INFO file - SSH.command('echo "SRC_BRANCH: ' + RAN.GetranBranch() + '" > ../LAST_BUILD_INFO.txt', '\$', 2) - SSH.command('echo "SRC_COMMIT: ' + RAN.GetranCommitID() + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) - if (RAN.GetranAllowMerge()): + SSH.command('echo "SRC_BRANCH: ' + self.ranBranch + '" > ../LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('echo "SRC_COMMIT: ' + self.ranCommitID + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) + if self.ranAllowMerge: SSH.command('echo "MERGED_W_TGT_BRANCH: YES" >> ../LAST_BUILD_INFO.txt', '\$', 2) - if RAN.GetranTargetBranch() == '': + if self.ranTargetBranch == '': SSH.command('echo "TGT_BRANCH: develop" >> ../LAST_BUILD_INFO.txt', '\$', 2) else: - SSH.command('echo "TGT_BRANCH: ' + RAN.GetranTargetBranch() + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) + SSH.command('echo "TGT_BRANCH: ' + self.ranTargetBranch + '" >> ../LAST_BUILD_INFO.txt', '\$', 2) else: SSH.command('echo "MERGED_W_TGT_BRANCH: NO" >> ../LAST_BUILD_INFO.txt', '\$', 2) SSH.close() @@ -222,7 +223,7 @@ class OaiCiTest(): if RAN.GetflexranCtrlInstalled() == False: return if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) SSH.command('cd /opt/flexran_rtc', '\$', 5) @@ -287,7 +288,7 @@ class OaiCiTest(): def InitializeUE(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') multi_jobs = [] i = 0 @@ -303,7 +304,7 @@ class OaiCiTest(): def InitializeOAIUE(self): if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') if RAN.Getair_interface() == 'lte': result = re.search('--no-L2-connect', str(self.Initialize_OAI_UE_args)) @@ -501,7 +502,7 @@ class OaiCiTest(): def InitializeCatM(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') SSH.enablePicocomClosure() SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) @@ -540,7 +541,7 @@ class OaiCiTest(): def TerminateCatM(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') SSH.enablePicocomClosure() SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) @@ -561,7 +562,7 @@ class OaiCiTest(): def AttachCatM(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') SSH.enablePicocomClosure() SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) @@ -635,7 +636,7 @@ class OaiCiTest(): def PingCatM(self): if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') check_eNB = True check_OAI_UE = False @@ -801,7 +802,7 @@ class OaiCiTest(): def AttachUE(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') check_eNB = True check_OAI_UE = False @@ -875,7 +876,7 @@ class OaiCiTest(): def DetachUE(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') check_eNB = True check_OAI_UE = False @@ -946,7 +947,7 @@ class OaiCiTest(): def RebootUE(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') check_eNB = True check_OAI_UE = False @@ -980,7 +981,7 @@ class OaiCiTest(): def DataDisableUE(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') multi_jobs = [] i = 0 @@ -1009,7 +1010,7 @@ class OaiCiTest(): def DataEnableUE(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') multi_jobs = [] i = 0 @@ -1025,7 +1026,7 @@ class OaiCiTest(): def GetAllUEDevices(self, terminate_ue_flag): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) if self.ADBCentralized: @@ -1069,7 +1070,7 @@ class OaiCiTest(): def GetAllCatMDevices(self, terminate_ue_flag): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') SSH.open(self.ADBIPAddress, self.ADBUserName, self.ADBPassword) if self.ADBCentralized: @@ -1141,7 +1142,7 @@ class OaiCiTest(): def CheckStatusUE(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') check_eNB = True check_OAI_UE = False @@ -1205,13 +1206,13 @@ class OaiCiTest(): def GetAllUEIPAddresses(self): if self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') ue_ip_status = 0 self.UEIPAddresses = [] if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '' or self.UESourceCodePath == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') SSH.open(self.UEIPAddress, self.UEUserName, self.UEPassword) SSH.command('ifconfig oaitun_ue1', '\$', 4) @@ -1373,11 +1374,11 @@ class OaiCiTest(): ping_from_eNB = re.search('oaitun_enb1', str(self.ping_args)) if ping_from_eNB is not None: if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') else: if self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') try: if ping_from_eNB is not None: @@ -1460,7 +1461,7 @@ class OaiCiTest(): self.PingNoS1() return if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') check_eNB = True if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): @@ -2087,7 +2088,7 @@ class OaiCiTest(): def IperfNoS1(self): if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or self.UEIPAddress == '' or self.UEUserName == '' or self.UEPassword == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') check_eNB = True check_OAI_UE = True @@ -2200,7 +2201,7 @@ class OaiCiTest(): self.IperfNoS1() return if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '' or self.ADBIPAddress == '' or self.ADBUserName == '' or self.ADBPassword == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') check_eNB = True if (len(self.UEDevices) == 1) and (self.UEDevices[0] == 'OAI-UE'): @@ -2625,7 +2626,7 @@ class OaiCiTest(): if RAN.GetflexranCtrlInstalled() == False or RAN.GetflexranCtrlStarted() == False: return if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') SSH.open(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword()) SSH.command('echo ' + EPC.GetPassword() + ' | sudo -S daemon --name=flexran_rtc_daemon --stop', '\$', 5) @@ -2737,18 +2738,21 @@ class OaiCiTest(): self.testCase_id = 'AUTO-KILL-UE' HTML.SettestCase_id(self.testCase_id) self.desc = 'Automatic Termination of UE' + HTML.Setdesc('Automatic Termination of UE') self.ShowTestID() self.TerminateUE() if (self.Initialize_OAI_UE_args != ''): - self.testCase_id = 'AUTO-KILL-UE' + self.testCase_id = 'AUTO-KILL-OAI-UE' HTML.SettestCase_id(self.testCase_id) - self.desc = 'Automatic Termination of UE' + self.desc = 'Automatic Termination of OAI-UE' + HTML.Setdesc('Automatic Termination of OAI-UE') self.ShowTestID() self.TerminateOAIUE() if (RAN.GetInitialize_eNB_args() != ''): self.testCase_id = 'AUTO-KILL-eNB' HTML.SettestCase_id(self.testCase_id) self.desc = 'Automatic Termination of eNB' + HTML.Setdesc('Automatic Termination of eNB') self.ShowTestID() RAN.SeteNB_instance('0') RAN.TerminateeNB() @@ -2756,6 +2760,7 @@ class OaiCiTest(): self.testCase_id = 'AUTO-KILL-flexran-ctl' HTML.SettestCase_id(self.testCase_id) self.desc = 'Automatic Termination of FlexRan CTL' + HTML.Setdesc('Automatic Termination of FlexRan CTL') self.ShowTestID() self.TerminateFlexranCtrl() RAN.SetprematureExit(True) @@ -3189,7 +3194,7 @@ CiTestObj = OaiCiTest() import sshconnection import epc -import helpreadme +import helpreadme as HELP import ran import html import constants @@ -3211,7 +3216,7 @@ while len(argvs) > 1: myArgv = argvs.pop(1) # 0th is this file's name if re.match('^\-\-help$', myArgv, re.IGNORECASE): - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit(0) elif re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE): matchReg = re.match('^\-\-mode=(.+)$', myArgv, re.IGNORECASE) @@ -3221,6 +3226,7 @@ while len(argvs) > 1: matchReg = re.match('^\-\-eNBRepository=(.+)$', myArgv, re.IGNORECASE) else: matchReg = re.match('^\-\-ranRepository=(.+)$', myArgv, re.IGNORECASE) + CiTestObj.ranRepository = matchReg.group(1) RAN.SetranRepository(matchReg.group(1)) HTML.SetranRepository(matchReg.group(1)) elif re.match('^\-\-eNB_AllowMerge=(.+)$|^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE): @@ -3230,6 +3236,7 @@ while len(argvs) > 1: matchReg = re.match('^\-\-ranAllowMerge=(.+)$', myArgv, re.IGNORECASE) doMerge = matchReg.group(1) if ((doMerge == 'true') or (doMerge == 'True')): + CiTestObj.ranAllowMerge = True RAN.SetranAllowMerge(True) HTML.SetranAllowMerge(True) elif re.match('^\-\-eNBBranch=(.+)$|^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE): @@ -3237,6 +3244,7 @@ while len(argvs) > 1: matchReg = re.match('^\-\-eNBBranch=(.+)$', myArgv, re.IGNORECASE) else: matchReg = re.match('^\-\-ranBranch=(.+)$', myArgv, re.IGNORECASE) + CiTestObj.ranBranch = matchReg.group(1) RAN.SetranBranch(matchReg.group(1)) HTML.SetranBranch(matchReg.group(1)) elif re.match('^\-\-eNBCommitID=(.*)$|^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE): @@ -3244,6 +3252,7 @@ while len(argvs) > 1: matchReg = re.match('^\-\-eNBCommitID=(.*)$', myArgv, re.IGNORECASE) else: matchReg = re.match('^\-\-ranCommitID=(.*)$', myArgv, re.IGNORECASE) + CiTestObj.ranCommitID = matchReg.group(1) RAN.SetranCommitID(matchReg.group(1)) HTML.SetranCommitID(matchReg.group(1)) elif re.match('^\-\-eNBTargetBranch=(.*)$|^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE): @@ -3251,6 +3260,7 @@ while len(argvs) > 1: matchReg = re.match('^\-\-eNBTargetBranch=(.*)$', myArgv, re.IGNORECASE) else: matchReg = re.match('^\-\-ranTargetBranch=(.*)$', myArgv, re.IGNORECASE) + CiTestObj.ranTargetBranch = matchReg.group(1) RAN.SetranTargetBranch(matchReg.group(1)) HTML.SetranTargetBranch(matchReg.group(1)) elif re.match('^\-\-eNBIPAddress=(.+)$|^\-\-eNB[1-2]IPAddress=(.+)$', myArgv, re.IGNORECASE): @@ -3352,12 +3362,12 @@ while len(argvs) > 1: if ((finalStatus == 'true') or (finalStatus == 'True')): CiTestObj.finalStatus = True else: - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Invalid Parameter: ' + myArgv) if re.match('^TerminateeNB$', mode, re.IGNORECASE): if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') RAN.SeteNB_serverId('0') RAN.SeteNB_instance('0') @@ -3365,74 +3375,74 @@ if re.match('^TerminateeNB$', mode, re.IGNORECASE): RAN.TerminateeNB() elif re.match('^TerminateUE$', mode, re.IGNORECASE): if (CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == ''): - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') signal.signal(signal.SIGUSR1, receive_signal) CiTestObj.TerminateUE() elif re.match('^TerminateOAIUE$', mode, re.IGNORECASE): if CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') signal.signal(signal.SIGUSR1, receive_signal) CiTestObj.TerminateOAIUE() elif re.match('^TerminateHSS$', mode, re.IGNORECASE): if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') EPC.TerminateHSS() elif re.match('^TerminateMME$', mode, re.IGNORECASE): if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') EPC.TerminateMME() elif re.match('^TerminateSPGW$', mode, re.IGNORECASE): if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') EPC.TerminateSPGW() elif re.match('^LogCollectBuild$', mode, re.IGNORECASE): if (RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '') and (CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == ''): - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') CiTestObj.LogCollectBuild() elif re.match('^LogCollecteNB$', mode, re.IGNORECASE): if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') RAN.LogCollecteNB() elif re.match('^LogCollectHSS$', mode, re.IGNORECASE): if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') EPC.LogCollectHSS() elif re.match('^LogCollectMME$', mode, re.IGNORECASE): if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') EPC.LogCollectMME() elif re.match('^LogCollectSPGW$', mode, re.IGNORECASE): if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') EPC.LogCollectSPGW() elif re.match('^LogCollectPing$', mode, re.IGNORECASE): if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') CiTestObj.LogCollectPing() elif re.match('^LogCollectIperf$', mode, re.IGNORECASE): if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') CiTestObj.LogCollectIperf() elif re.match('^LogCollectOAIUE$', mode, re.IGNORECASE): if CiTestObj.UEIPAddress == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') CiTestObj.LogCollectOAIUE() elif re.match('^InitiateHtml$', mode, re.IGNORECASE): if (CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == ''): - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') count = 0 foundCount = 0 @@ -3472,21 +3482,21 @@ elif re.match('^FinalizeHtml$', mode, re.IGNORECASE): elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re.IGNORECASE): if re.match('^TesteNB$', mode, re.IGNORECASE): if RAN.GeteNBIPAddress() == '' or RAN.GetranRepository() == '' or RAN.GetranBranch() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '' or EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetType() == '' or EPC.GetSourceCodePath() == '' or CiTestObj.ADBIPAddress == '' or CiTestObj.ADBUserName == '' or CiTestObj.ADBPassword == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) if EPC.GetIPAddress() == '' or EPC.GetUserName() == '' or EPC.GetPassword() == '' or EPC.GetSourceCodePath() == '' or EPC.GetType() == '': - EPCSrvHelp(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), EPC.GetSourceCodePath(), EPC.GetType()) + HELP.EPCSrvHelp(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), EPC.GetSourceCodePath(), EPC.GetType()) if RAN.GetranRepository() == '': - GitSrvHelp(RAN.GetranRepository(),RAN.GetranBranch(),RAN.GetranCommitID(),RAN.GetranAllowMerge(),RAN.GetranTargetBranch()) + HELP.GitSrvHelp(RAN.GetranRepository(), RAN.GetranBranch(), RAN.GetranCommitID(), RAN.GetranAllowMerge(), RAN.GetranTargetBranch()) if RAN.GeteNBIPAddress() == '' or RAN.GeteNBUserName() == '' or RAN.GeteNBPassword() == '' or RAN.GeteNBSourceCodePath() == '': - eNBSrvHelp(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath()) + HELP.eNBSrvHelp(RAN.GeteNBIPAddress(), RAN.GeteNBUserName(), RAN.GeteNBPassword(), RAN.GeteNBSourceCodePath()) sys.exit('Insufficient Parameter') if (EPC.GetIPAddress() != '') and (EPC.GetIPAddress() != 'none'): SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), cwd + "/tcp_iperf_stats.awk", "/tmp") SSH.copyout(EPC.GetIPAddress(), EPC.GetUserName(), EPC.GetPassword(), cwd + "/active_net_interfaces.awk", "/tmp") else: - if CiTestObj.UEIPAddress == '' or RAN.GetranRepository() == '' or RAN.GetranBranch() == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == '': - GenericHelp(Version) + if CiTestObj.UEIPAddress == '' or CiTestObj.ranRepository == '' or CiTestObj.ranBranch == '' or CiTestObj.UEUserName == '' or CiTestObj.UEPassword == '' or CiTestObj.UESourceCodePath == '': + HELP.GenericHelp(CONST.Version) sys.exit('UE: Insufficient Parameter') #read test_case_list.xml file @@ -3663,6 +3673,6 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re logging.info('Testsuite passed after ' + str(CiTestObj.FailReportCnt) + ' time(s)') HTML.CreateHtmlTabFooter(True) else: - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Invalid mode') sys.exit(0) diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py index c65c21c252..350098e66e 100644 --- a/ci-scripts/ran.py +++ b/ci-scripts/ran.py @@ -232,7 +232,7 @@ class RANManagement(): def BuildeNB(self): if self.ranRepository == '' or self.ranBranch == '' or self.ranCommitID == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') if self.eNB_serverId == '0': lIpAddr = self.eNBIPAddress @@ -250,7 +250,7 @@ class RANManagement(): lPassWord = self.eNB2Password lSourcePath = self.eNB2SourceCodePath if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') mySSH = SSH.SSHConnection() mySSH.open(lIpAddr, lUserName, lPassWord) @@ -359,7 +359,7 @@ class RANManagement(): lPassWord = self.eNB2Password lSourcePath = self.eNB2SourceCodePath if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') mySSH = SSH.SSHConnection() mySSH.open(lIpAddr, lUserName, lPassWord) @@ -454,7 +454,7 @@ class RANManagement(): lPassWord = self.eNB2Password lSourcePath = self.eNB2SourceCodePath if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') if self.htmlObj is not None: @@ -679,7 +679,7 @@ class RANManagement(): lPassWord = self.eNB2Password lSourcePath = self.eNB2SourceCodePath if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': - GenericHelp(Version) + HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') mySSH = SSH.SSHConnection() mySSH.open(lIpAddr, lUserName, lPassWord) diff --git a/ci-scripts/xml_files/enb_usrp210_band40_test_05mhz_tm2.xml b/ci-scripts/xml_files/enb_usrp210_band40_test_05mhz_tm2.xml index 2a035396c5..09aa0b04a2 100644 --- a/ci-scripts/xml_files/enb_usrp210_band40_test_05mhz_tm2.xml +++ b/ci-scripts/xml_files/enb_usrp210_band40_test_05mhz_tm2.xml @@ -25,7 +25,7 @@ test-05-tm2 Test-05MHz-TM2 tasks - 3 + 2 030201 040101 From 6d8aa8d6b92b6a0d89f03e81bf49f3e350757c7b Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 23 Apr 2020 01:17:11 +0200 Subject: [PATCH 190/240] added 3-bit payload for pucch0 to nr_pucchsim, fixed SNR scaling for pucch2 --- openair1/SIMULATION/NR_PHY/pucchsim.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/pucchsim.c b/openair1/SIMULATION/NR_PHY/pucchsim.c index 9e1609c3b4..d36f42f6c6 100644 --- a/openair1/SIMULATION/NR_PHY/pucchsim.c +++ b/openair1/SIMULATION/NR_PHY/pucchsim.c @@ -104,6 +104,7 @@ int main(int argc, char **argv) NR_DL_FRAME_PARMS *frame_parms; //unsigned char frame_type = 0; int loglvl=OAILOG_WARNING; + int sr_flag = 0; cpuf = get_cpu_freq_GHz(); @@ -114,7 +115,7 @@ int main(int argc, char **argv) randominit(0); logInit(); - while ((c = getopt (argc, argv, "f:hA:f:g:i:I:P:B:b:T:m:n:r:o:s:S:x:y:z:N:F:GR:IL:q:")) != -1) { + while ((c = getopt (argc, argv, "f:hA:f:g:i:I:P:B:b:T:m:n:r:o:s:S:x:y:z:N:F:GR:IL:q:c")) != -1) { switch (c) { case 'f': //write_output_file=1; @@ -275,6 +276,9 @@ int main(int argc, char **argv) case 'b': nr_bit=atoi(optarg); break; + case 'c': + sr_flag=1; + break; case 'B': actual_payload=atoi(optarg); break; @@ -455,10 +459,13 @@ int main(int argc, char **argv) uint32_t dmrs_scrambling_id = 0, data_scrambling_id=0; if(format==0){ // for now we are not considering SR just HARQ-ACK - if(nr_bit==1) + if (nr_bit ==0) + mcs=table1_mcs[0]; + else if(nr_bit==1) mcs=table1_mcs[actual_payload]; else if(nr_bit==2) mcs=table2_mcs[actual_payload]; + else AssertFatal(1==0,"Either nr_bit %d or sr_flag %d must be non-zero\n"); } for(SNR=snr0;SNR<=snr1;SNR=SNR+1){ @@ -480,8 +487,9 @@ int main(int argc, char **argv) frame_parms->ofdm_symbol_size); // printf("txlev %d (%d dB), offset %d\n",txlev,dB_fixed(txlev),startingSymbolIndex*frame_parms->ofdm_symbol_size); - // note : this scaling is for 1 PRB, to be updated for PUCCH 2 - sigma2_dB = 10*log10((double)txlev*UE->frame_parms.ofdm_symbol_size/12)-SNR; + // note : this scaling + int nb_re = (format == 0 || format == 1)? 12 : 12*nrofPRB; + sigma2_dB = 10*log10((double)txlev*UE->frame_parms.ofdm_symbol_size/nb_re)-SNR; sigma2 = pow(10,sigma2_dB/10); for(i=startingSymbolIndex*frame_parms->ofdm_symbol_size; i<(startingSymbolIndex+1)*frame_parms->ofdm_symbol_size; i++) { @@ -498,7 +506,7 @@ int main(int argc, char **argv) pucch_pdu.group_hop_flag = PUCCH_GroupHopping&1; pucch_pdu.sequence_hop_flag = (PUCCH_GroupHopping>>1)&1; pucch_pdu.bit_len_harq = nr_bit; - pucch_pdu.sr_flag = 0; + pucch_pdu.sr_flag = sr_flag; pucch_pdu.nr_of_symbols = nrofSymbols; pucch_pdu.hopping_id = hopping_id; pucch_pdu.initial_cyclic_shift = 0; From 0d1edf6c477367415d9a8fd2e43f72f73ac6d676 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Thu, 23 Apr 2020 11:30:48 +0200 Subject: [PATCH 191/240] CI: add missing import Signed-off-by: Raphael Defosseux --- ci-scripts/sshconnection.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ci-scripts/sshconnection.py b/ci-scripts/sshconnection.py index 649ffef26c..68a1d7836c 100644 --- a/ci-scripts/sshconnection.py +++ b/ci-scripts/sshconnection.py @@ -35,6 +35,7 @@ import pexpect # pexpect import logging import time # sleep import re +import sys #----------------------------------------------------------- # Class Declaration From 381f44843d32a9ad6e84d8ca13a7de4f9fa13546 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Thu, 23 Apr 2020 11:39:15 +0200 Subject: [PATCH 192/240] DOC: fix some formatting issues Signed-off-by: Raphael Defosseux --- doc/SystemX-tutorial-design.md | 71 +++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 26 deletions(-) diff --git a/doc/SystemX-tutorial-design.md b/doc/SystemX-tutorial-design.md index 371cb33a75..3e4496f7de 100644 --- a/doc/SystemX-tutorial-design.md +++ b/doc/SystemX-tutorial-design.md @@ -1,10 +1,10 @@ # OpenAirInterface for SystemX -#Terminology +# Terminology ****This document use the 5G terminology**** -**Central Unit (CU): **It is a logical node that includes the gNB +**Central Unit (CU):** It is a logical node that includes the gNB functions like Transfer of user data, Mobility control, Radio access network sharing, Positioning, Session Management etc., except those functions allocated exclusively to the DU. CU controls the operation of @@ -19,7 +19,9 @@ names like RRH/RRU/RE/RU/PNF. In OpenAir code, the terminology is often RU and BBU. # OpenAirUsage -##EPC and general environment + +## EPC and general environment + ### OAI EPC Use the stable OAI EPC, that can run in one machine (VM or standalone) @@ -27,9 +29,10 @@ Use the stable OAI EPC, that can run in one machine (VM or standalone) Draft description: -##Standalone 4G +## Standalone 4G EPC+eNB on one machine, the UE can be commercial or OAI UE. + ### USRP B210 Main current issue: traffic is good only on coaxial link between UE and @@ -55,7 +58,8 @@ the same IP tunnel end point as the UE. So, we have to create a network namespace for the UE and to route data in/out of the namespace. -``` bash + +```bash ip netns delete aNameSpace 2> /dev/null ip link delete v-eth1 2> /dev/null @@ -70,7 +74,7 @@ ip addr add 10.200.1.1/24 dev v-eth1 ip link set v-eth1 up -iptables -t nat -A POSTROUTING -s 10.200.1.0/255.255.255.0 -o enp0s31f6 +iptables -t nat -A POSTROUTING -s 10.200.1.0/255.255.255.0 -o enp0s31f6 \ -j MASQUERADE iptables -A FORWARD -i enp0s31f6 -o v-eth1 -j ACCEPT @@ -92,13 +96,15 @@ to run the UE. To make user plan traffic, the traffic generator has to run in the same namespace -`ip netns exec aNameSpace bash -` +```bash +ip netns exec aNameSpace bash +``` The traffic genenrator has to specify the interface: -`route add default oaitun_ue1 -` +```bash +route add default oaitun_ue1 +``` or specify the outgoing route in the traffic generator (like option “-I” in ping command). @@ -111,6 +117,7 @@ is this work the downlink “functional split 6”. The customer required after signature to develop also the uplink functional split 6. This is accepted, as long as the whole work is research with no delivery completeness warranty. + ### Simulation To be able to verify the new features and to help in all future @@ -119,11 +126,12 @@ during this contract. We added the channel modeling simulation, that offer to simulate various 3GPP defined channels. + ### Main loop The main log is in RF simulator is in - targets/RT/USER/lte-ru.c and targets/RT/USER/lte-enb.c + `targets/RT/USER/lte-ru.c and targets/RT/USER/lte-enb.c` As this piece of SW is very complex and doesn’t meet our goals (functional split 6), a cleaned version replaces these 2 files in @@ -142,8 +150,8 @@ The reworked main loop take care of a uniq variable that comes directly from har To use OAI, we need to set all OAI variables that derivates from this timestamp value. The function setAllfromTS() implements this. - ### Splitted main level + When FS6 is actived, a main loop for DU (du_fs6()) a main loop for CU case replaces the uniq eNB main loop. Each of these main loops calls initialization of OAI LTE data and the FS6 transport layer initialization. @@ -262,29 +270,36 @@ The end line option “--split73” enables the fs6 (also called split 7.3) mode Example: +```bash ./ocp-softmodem -O $OPENAIR_DIR/enb.fs6.example.conf --rfsim --log_config.phy_log_level debug --split73 cu:127.0.0.1 -` +``` + Run the CU init of the split 6 eNB, that will call du on 127.0.0.1 address +```bash ./ocp-softmodem -O $OPENAIR_DIR/enb.fs6.example.conf --rfsim --log_config.phy_log_level debug --split73 du:127.0.0.1 +``` will run the du, calling the cu on 127.0.0.1 -` + If the CU and the DU are not on the same machine, the remote address of each side need to be specified as per this example +```bash ./ocp-softmodem -O $OPENAIR_DIR/enb.fs6.example.conf --rfsim --log_config.phy_log_level debug --split73 du:192.168.1.55 -` +``` + runs the functional split 6 DU -`./lte-uesoftmodem -C 2685000000 -r 50 --rfsim --rfsimulator.serveraddr 192.168.1.1 -d -` +```bash +./lte-uesoftmodem -C 2685000000 -r 50 --rfsim --rfsimulator.serveraddr 192.168.1.1 -d +``` Runs the UE (to have the UE signal scope, compile it with make uescope) -CU+DU+UE can run with option --noS1 to avoid to use a EPC and/or with --rfsim to simulate RF board +CU+DU+UE can run with option `--noS1` to avoid to use a EPC and/or with `--rfsim` to simulate RF board -##5G and F1 +## 5G and F1 Today 5G achievement is limited to physical layer. @@ -305,13 +320,17 @@ frames). Usage with RFsimulator: -gNB +**gNB** -`sudo RFSIMULATOR=server ./nr-softmodem -O -../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf ---parallel-config PARALLEL\_SINGLE\_THREAD` +```bash +sudo RFSIMULATOR=server ./nr-softmodem -O \ +../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf \ +--parallel-config PARALLEL\_SINGLE\_THREAD +``` -nrUE +**nrUE** -`sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --numerology 1 -r 106 -C -3510000000 -d` +```bash +sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --numerology 1 -r 106 -C \ +3510000000 -d +``` From 591b45d29f85ffb19b6cefa9d0f3e3c40c548ffd Mon Sep 17 00:00:00 2001 From: Javier Morgade Date: Thu, 23 Apr 2020 11:45:07 +0200 Subject: [PATCH 193/240] Configure right lcid range at MBMS config file Now is aligned with RMSIMULATOR config file (this should solve CI issues with monolithic tests) --- ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf b/ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf index fbb8c5d6f8..de58950df4 100644 --- a/ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf +++ b/ci-scripts/conf_files/enb.band17.tm1.mbms.25PRB.usrpb210.conf @@ -288,7 +288,7 @@ MCEs = ( mnc_length = 2; } service_id=0; - lcid=8; #this must be properly defined lcid:8+service:0 -> rab_id:8 + lcid=5; #this must be properly defined lcid:8+service:0 -> rab_id:5 } ); } From e957d9cb49cecb9cc713ffe72d835b897a7e354a Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Thu, 23 Apr 2020 16:37:11 +0200 Subject: [PATCH 194/240] DOC: put correct license Signed-off-by: Raphael Defosseux --- executables/nr-ru.c | 57 ++++++++++++++++----------------------------- 1 file changed, 20 insertions(+), 37 deletions(-) diff --git a/executables/nr-ru.c b/executables/nr-ru.c index a6970973a6..f947395f4a 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -1,41 +1,24 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2014 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE - -*******************************************************************************/ - -/*! \file lte-enb.c - * \brief Top-level threads for eNodeB - * \author R. Knopp, F. Kaltenberger, Navid Nikaein - * \date 2012 - * \version 0.1 - * \company Eurecom - * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr - * \note - * \warning +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org */ + #define _GNU_SOURCE #include #include From ddf947100254d5010d028f5613c71904264f3195 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Thu, 23 Apr 2020 16:40:52 +0200 Subject: [PATCH 195/240] DOC: license for all LFDS versions updated Signed-off-by: Raphael Defosseux --- NOTICE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NOTICE.md b/NOTICE.md index 65c6105660..96b5d4c552 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -4,7 +4,7 @@ For more details of the license, refer to [LICENSE](LICENSE) file in the same di However, the source code also contains third party software that is acknowledged here for reference. -## Credits for LFDS user space source code located in folder openair2/UTILS/LFDS/liblfds6.1.1/ ## +## Credits for LFDS user space source code located in folder openair2/UTILS/LFDS/ ## See on [liblfds website](https://liblfds.org/) the license section. From 6b307e8123ebecba54a9bf49d31f91eedb91d30a Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Thu, 23 Apr 2020 19:44:04 +0200 Subject: [PATCH 196/240] bugfix in ratematching for higher rv --- openair1/PHY/CODING/nr_rate_matching.c | 9 +++++---- openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c | 3 +++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/openair1/PHY/CODING/nr_rate_matching.c b/openair1/PHY/CODING/nr_rate_matching.c index 0cffc2d852..5294e79b9f 100644 --- a/openair1/PHY/CODING/nr_rate_matching.c +++ b/openair1/PHY/CODING/nr_rate_matching.c @@ -364,8 +364,8 @@ int nr_rate_matching_ldpc(uint8_t Ilbrm, if (ind < Foffset) { // case where we have some bits before the filler and the rest after memcpy((void*)e,(void*)(w+ind),Foffset-ind); - if (E + F <= Ncb) { // E+F doesn't contain all coded bits - memcpy((void*)(e+Foffset-ind),(void*)(w+Foffset+F-ind),E-Foffset+ind); + if (E + F <= Ncb-ind) { // E+F doesn't contain all coded bits + memcpy((void*)(e+Foffset-ind),(void*)(w+Foffset+F),E-Foffset+ind); k=E; } else { @@ -375,11 +375,12 @@ int nr_rate_matching_ldpc(uint8_t Ilbrm, } else { if (E + F <= Ncb-ind) { //E+F doesn't contain all coded bits - memcpy((void*)(e+Foffset-ind),(void*)(w+Foffset+F-ind),E-Foffset+ind); + memcpy((void*)(e),(void*)(w+ind),E); k=E; } else { - + memcpy((void*)(e),(void*)(w+ind),Ncb-ind); + k=Ncb-ind; } } diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index 856a7863f4..6242008387 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -460,6 +460,9 @@ int nr_dlsch_encoding(unsigned char *a, } + F = dlsch->harq_processes[harq_pid]->F; + + Kr = dlsch->harq_processes[harq_pid]->K; for (r=0; rharq_processes[harq_pid]->C; r++) { if (F>0) { From 93e745b8ec4153445a65a4589858e3875403b64e Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Thu, 23 Apr 2020 19:45:00 +0200 Subject: [PATCH 197/240] updated dlsim to test harq --- openair1/SIMULATION/NR_PHY/dlsim.c | 240 ++++++++++-------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 6 +- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 6 + 3 files changed, 137 insertions(+), 115 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 491fd52e5e..e806a6867a 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -154,6 +154,8 @@ int main(int argc, char **argv) int trial, n_trials = 1, n_errors = 0, n_false_positive = 0; //int n_errors2, n_alamouti; uint8_t transmission_mode = 1,n_tx=1,n_rx=1; + uint8_t round; + uint8_t num_rounds = 4; channel_desc_t *gNB2UE; //uint32_t nsymb,tx_lev,tx_lev1 = 0,tx_lev2 = 0; @@ -678,6 +680,8 @@ int main(int argc, char **argv) nr_ue_phy_config_request(&UE_mac->phy_config); + NR_UE_list_t *UE_list = &RC.nrmac[0]->UE_list; + NR_COMMON_channels_t *cc = RC.nrmac[0]->common_channels; for (SNR = snr0; SNR < snr1; SNR += .2) { @@ -704,95 +708,6 @@ int main(int argc, char **argv) errors_bit = 0; //multipath channel //multipath_channel(gNB2UE,s_re,s_im,r_re,r_im,frame_length_complex_samples,0); - - memset(RC.nrmac[0]->cce_list[1][0],0,MAX_NUM_CCE*sizeof(int)); - clear_nr_nfapi_information(RC.nrmac[0], 0, frame, slot); - if (css_flag == 0) nr_schedule_uss_dlsch_phytest(0,frame,slot,&pucch_sched,&dlsch_config); - else nr_schedule_css_dlsch_phytest(0,frame,slot); - - - Sched_INFO.module_id = 0; - Sched_INFO.CC_id = 0; - Sched_INFO.frame = frame; - Sched_INFO.slot = slot; - Sched_INFO.DL_req = &gNB_mac->DL_req[0]; - Sched_INFO.UL_tti_req = &gNB_mac->UL_tti_req[0]; - Sched_INFO.UL_dci_req = NULL; - Sched_INFO.TX_req = &gNB_mac->TX_req[0]; - nr_schedule_response(&Sched_INFO); - - if (run_initial_sync) - nr_common_signal_procedures(gNB,frame,slot); - else - phy_procedures_gNB_TX(gNB,frame,slot,0); - - int txdataF_offset = (slot%2) * frame_parms->samples_per_slot_wCP; - - if (n_trials==1) { - LOG_M("txsigF0.m","txsF0", gNB->common_vars.txdataF[0],frame_length_complex_samples_no_prefix,1,1); - if (gNB->frame_parms.nb_antennas_tx>1) - LOG_M("txsigF1.m","txsF1", gNB->common_vars.txdataF[1],frame_length_complex_samples_no_prefix,1,1); - } - int tx_offset = frame_parms->get_samples_slot_timestamp(slot,frame_parms,0); - if (n_trials==1) printf("samples_per_slot_wCP = %d\n", frame_parms->samples_per_slot_wCP); - - //TODO: loop over slots - for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { - - if (cyclic_prefix_type == 1) { - PHY_ofdm_mod(&gNB->common_vars.txdataF[aa][txdataF_offset], - &txdata[aa][tx_offset], - frame_parms->ofdm_symbol_size, - 12, - frame_parms->nb_prefix_samples, - CYCLIC_PREFIX); - } else { - nr_normal_prefix_mod(&gNB->common_vars.txdataF[aa][txdataF_offset], - &txdata[aa][tx_offset], - 14, - frame_parms); - } - } - - if (n_trials==1) { - LOG_M("txsig0.m","txs0", txdata[0],frame_length_complex_samples,1,1); - if (gNB->frame_parms.nb_antennas_tx>1) - LOG_M("txsig1.m","txs1", txdata[1],frame_length_complex_samples,1,1); - } - if (output_fd) - fwrite(txdata[0],sizeof(int32_t),frame_length_complex_samples,output_fd); - - int txlev = signal_energy(&txdata[0][frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)+5*frame_parms->ofdm_symbol_size + 4*frame_parms->nb_prefix_samples + frame_parms->nb_prefix_samples0], - frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples); - - // if (n_trials==1) printf("txlev %d (%f)\n",txlev,10*log10((double)txlev)); - - for (i=(frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)); - i<(frame_parms->get_samples_slot_timestamp(slot+1,frame_parms,0)); - i++) { - for (aa=0; aanb_antennas_tx; aa++) { - r_re[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)]); - r_im[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)+1]); - } - } - - NR_gNB_DLSCH_t *gNB_dlsch = gNB->dlsch[0][0]; - nfapi_nr_dl_tti_pdsch_pdu_rel15_t rel15 = gNB_dlsch->harq_processes[0]->pdsch_pdu.pdsch_pdu_rel15; - - //AWGN - sigma2_dB = 10 * log10((double)txlev * ((double)UE->frame_parms.ofdm_symbol_size/(12*rel15.rbSize))) - SNR; - sigma2 = pow(10, sigma2_dB/10); - if (n_trials==1) printf("sigma2 %f (%f dB), txlev %f (factor %f)\n",sigma2,sigma2_dB,10*log10((double)txlev),(double)(double)UE->frame_parms.ofdm_symbol_size/(12*rel15.rbSize)); - - for (i=frame_parms->get_samples_slot_timestamp(slot,frame_parms,0); - iget_samples_slot_timestamp(slot+1,frame_parms,0); - i++) { - for (aa=0; aanb_antennas_rx; aa++) { - ((short*) UE->common_vars.rxdata[aa])[2*i] = (short) ((r_re[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0))); - ((short*) UE->common_vars.rxdata[aa])[2*i+1] = (short) ((r_im[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0))); - } - } - UE->rx_offset=0; UE_proc.frame_rx = frame; UE_proc.nr_tti_rx= slot; @@ -800,43 +715,144 @@ int main(int argc, char **argv) dcireq.frame = frame; dcireq.slot = slot; + + NR_UE_DLSCH_t *dlsch0 = UE->dlsch[UE->current_thread_id[UE_proc.nr_tti_rx]][0][0]; + + int harq_pid = dlsch0->current_harq_pid; + NR_DL_UE_HARQ_t *UE_harq_process = dlsch0->harq_processes[harq_pid]; + + NR_gNB_DLSCH_t *gNB_dlsch = gNB->dlsch[0][0]; + nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &gNB_dlsch->harq_processes[0]->pdsch_pdu.pdsch_pdu_rel15; - nr_ue_dcireq(&dcireq); //to be replaced with function pointer later - nr_ue_scheduled_response(&scheduled_response); + UE_harq_process->harq_ack.ack = 0; + round = 0; + + while ((roundharq_ack.ack==0)) { + memset(RC.nrmac[0]->cce_list[1][0],0,MAX_NUM_CCE*sizeof(int)); + memset(RC.nrmac[0]->cce_list[1][1],0,MAX_NUM_CCE*sizeof(int)); + clear_nr_nfapi_information(RC.nrmac[0], 0, frame, slot); + + UE_list->UE_sched_ctrl[0].harq_processes[0].ndi = (round==0) ? 1 : 0; + + UE_list->UE_sched_ctrl[0].harq_processes[0].round = round; + gNB->dlsch[0][0]->harq_processes[0]->round = round; - phy_procedures_nrUE_RX(UE, - &UE_proc, - 0, - do_pdcch_flag, - normal_txrx); + if (css_flag == 0) nr_schedule_uss_dlsch_phytest(0,frame,slot,&pucch_sched,&dlsch_config); + else nr_schedule_css_dlsch_phytest(0,frame,slot); + Sched_INFO.module_id = 0; + Sched_INFO.CC_id = 0; + Sched_INFO.frame = frame; + Sched_INFO.slot = slot; + Sched_INFO.DL_req = &gNB_mac->DL_req[0]; + Sched_INFO.UL_tti_req = &gNB_mac->UL_tti_req[0]; + Sched_INFO.UL_dci_req = NULL; + Sched_INFO.TX_req = &gNB_mac->TX_req[0]; + nr_schedule_response(&Sched_INFO); + + if (run_initial_sync) + nr_common_signal_procedures(gNB,frame,slot); + else + phy_procedures_gNB_TX(gNB,frame,slot,0); + + int txdataF_offset = (slot%2) * frame_parms->samples_per_slot_wCP; + + if (n_trials==1) { + LOG_M("txsigF0.m","txsF0", gNB->common_vars.txdataF[0],frame_length_complex_samples_no_prefix,1,1); + if (gNB->frame_parms.nb_antennas_tx>1) + LOG_M("txsigF1.m","txsF1", gNB->common_vars.txdataF[1],frame_length_complex_samples_no_prefix,1,1); + } + int tx_offset = frame_parms->get_samples_slot_timestamp(slot,frame_parms,0); + if (n_trials==1) printf("samples_per_slot_wCP = %d\n", frame_parms->samples_per_slot_wCP); + + //TODO: loop over slots + for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { + + if (cyclic_prefix_type == 1) { + PHY_ofdm_mod(&gNB->common_vars.txdataF[aa][txdataF_offset], + &txdata[aa][tx_offset], + frame_parms->ofdm_symbol_size, + 12, + frame_parms->nb_prefix_samples, + CYCLIC_PREFIX); + } else { + nr_normal_prefix_mod(&gNB->common_vars.txdataF[aa][txdataF_offset], + &txdata[aa][tx_offset], + 14, + frame_parms); + } + } + + if (n_trials==1) { + LOG_M("txsig0.m","txs0", txdata[0],frame_length_complex_samples,1,1); + if (gNB->frame_parms.nb_antennas_tx>1) + LOG_M("txsig1.m","txs1", txdata[1],frame_length_complex_samples,1,1); + } + if (output_fd) + fwrite(txdata[0],sizeof(int32_t),frame_length_complex_samples,output_fd); + + int txlev = signal_energy(&txdata[0][frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)+5*frame_parms->ofdm_symbol_size + 4*frame_parms->nb_prefix_samples + frame_parms->nb_prefix_samples0], + frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples); + + // if (n_trials==1) printf("txlev %d (%f)\n",txlev,10*log10((double)txlev)); + + for (i=(frame_parms->get_samples_slot_timestamp(slot,frame_parms,0)); + i<(frame_parms->get_samples_slot_timestamp(slot+1,frame_parms,0)); + i++) { + for (aa=0; aanb_antennas_tx; aa++) { + r_re[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)]); + r_im[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)+1]); + } + } + + //AWGN + sigma2_dB = 10 * log10((double)txlev * ((double)UE->frame_parms.ofdm_symbol_size/(12*rel15->rbSize))) - SNR; + sigma2 = pow(10, sigma2_dB/10); + if (n_trials==1) printf("sigma2 %f (%f dB), txlev %f (factor %f)\n",sigma2,sigma2_dB,10*log10((double)txlev),(double)(double)UE->frame_parms.ofdm_symbol_size/(12*rel15->rbSize)); + + for (i=frame_parms->get_samples_slot_timestamp(slot,frame_parms,0); + iget_samples_slot_timestamp(slot+1,frame_parms,0); + i++) { + for (aa=0; aanb_antennas_rx; aa++) { + ((short*) UE->common_vars.rxdata[aa])[2*i] = (short) ((r_re[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0))); + ((short*) UE->common_vars.rxdata[aa])[2*i+1] = (short) ((r_im[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0))); + } + } + + nr_ue_dcireq(&dcireq); //to be replaced with function pointer later + nr_ue_scheduled_response(&scheduled_response); + + phy_procedures_nrUE_RX(UE, + &UE_proc, + 0, + do_pdcch_flag, + normal_txrx); + + if (UE->dlsch[UE->current_thread_id[slot]][0][0]->last_iteration_cnt >= + UE->dlsch[UE->current_thread_id[slot]][0][0]->max_ldpc_iterations+1) + n_errors++; - if (UE->dlsch[UE->current_thread_id[slot]][0][0]->last_iteration_cnt >= - UE->dlsch[UE->current_thread_id[slot]][0][0]->max_ldpc_iterations+1) - n_errors++; + printf("dlsim round %d ends\n",round); + round++; + } // round //---------------------------------------------------------- //---------------------- count errors ---------------------- //---------------------------------------------------------- - - - NR_UE_DLSCH_t *dlsch0 = UE->dlsch[UE->current_thread_id[UE_proc.nr_tti_rx]][0][0]; - - int harq_pid = dlsch0->current_harq_pid; - NR_DL_UE_HARQ_t *UE_harq_process = dlsch0->harq_processes[harq_pid]; - + + NR_UE_PDSCH **pdsch_vars = UE->pdsch_vars[UE->current_thread_id[UE_proc.nr_tti_rx]]; int16_t *UE_llr = pdsch_vars[0]->llr[0]; - uint32_t TBS = rel15.TBSize[0]; + uint32_t TBS = rel15->TBSize[0]; uint16_t length_dmrs = 1; - uint16_t nb_rb = rel15.rbSize; - uint8_t nb_re_dmrs = rel15.dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6 : 4; - uint8_t mod_order = rel15.qamModOrder[0]; - uint8_t nb_symb_sch = rel15.NrOfSymbols; + uint16_t nb_rb = rel15->rbSize; + uint8_t nb_re_dmrs = rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6 : 4; + uint8_t mod_order = rel15->qamModOrder[0]; + uint8_t nb_symb_sch = rel15->NrOfSymbols; - available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, mod_order, rel15.nrOfLayers); + available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, mod_order, rel15->nrOfLayers); for (i = 0; i < available_bits; i++) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index b98b6ae305..d1d2547ad6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -311,7 +311,7 @@ int configure_fapi_dl_pdu(int Mod_idP, pdsch_pdu_rel15->qamModOrder[0] = 2; pdsch_pdu_rel15->mcsIndex[0] = mcs; pdsch_pdu_rel15->mcsTable[0] = 0; - pdsch_pdu_rel15->rvIndex[0] = 0; + pdsch_pdu_rel15->rvIndex[0] = UE_list->UE_sched_ctrl[UE_id].harq_processes[0].round; pdsch_pdu_rel15->dataScramblingId = *scc->physCellId; pdsch_pdu_rel15->nrOfLayers = 1; pdsch_pdu_rel15->transmissionScheme = 0; @@ -361,10 +361,10 @@ int configure_fapi_dl_pdu(int Mod_idP, dci_pdu_rel15[0].time_domain_assignment.val = time_domain_assignment; // row index used here instead of SLIV; // mcs ndi and rv dci_pdu_rel15[0].mcs = pdsch_pdu_rel15->mcsIndex[0]; - dci_pdu_rel15[0].ndi = 1; - dci_pdu_rel15[0].rv = 0; + dci_pdu_rel15[0].rv = pdsch_pdu_rel15->rvIndex[0]; // harq pid dci_pdu_rel15[0].harq_pid = 0; + dci_pdu_rel15[0].ndi = UE_list->UE_sched_ctrl[UE_id].harq_processes[0].ndi; // DAI dci_pdu_rel15[0].dai[0].val = (pucch_sched->dai_c-1)&3; // TPC for PUCCH diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index e3a30c9b19..af5f6d2992 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -111,6 +111,11 @@ typedef struct NR_sched_pucch { struct NR_sched_pucch *next_sched_pucch; } NR_sched_pucch; +typedef struct NR_UE_harq { + uint8_t ndi; + uint8_t round; +} NR_UE_harq_t; + /*! \brief scheduling control information set through an API */ typedef struct { uint64_t dlsch_in_slot_bitmap; // static bitmap signaling which slot in a tdd period contains dlsch @@ -118,6 +123,7 @@ typedef struct { NR_sched_pucch *sched_pucch; uint16_t ta_timer; int16_t ta_update; + NR_UE_harq_t harq_processes[NR_MAX_NB_HARQ_PROCESSES]; } NR_UE_sched_ctrl_t; /*! \brief UE list used by eNB to order UEs/CC for scheduling*/ From d7d196c280af839100d9fa66ef6d5db6389f1f51 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 23 Apr 2020 22:27:28 +0200 Subject: [PATCH 198/240] CI tests for nr_pucchsim : added PUCCH format 2 tests --- cmake_targets/autotests/test_case_list.xml | 28 ++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 085e5fb07b..7eed0ae8a1 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1177,17 +1177,37 @@ execution nr_pucchsim Test cases. (Test1: Format 0 1-bit ACK miss 106 PRB), - (Test2: Format 0 2-bit ACK miss 106 PRB) + (Test2: Format 0 2-bit ACK miss 106 PRB), + (Test3: Format 0 2-bit ACK miss, 1-bit SR 106 PRB), + (Test4: Format 2 3-bit 106 PRB), + (Test5: Format 2 4-bit 106 PRB), + (Test6: Format 2 5-bit 106 PRB), + (Test7: Format 2 6-bit 106 PRB), + (Test8: Format 2 7-bit 106 PRB), + (Test9: Format 2 8-bit 106 PRB), + (Test10: Format 2 9-bit 106 PRB), + (Test11: Format 2 10-bit 106 PRB), + (Test12: Format 2 11-bit 106 PRB) $OPENAIR_DIR/cmake_targets/build_oai --phy_simulators -c $OPENAIR_DIR/cmake_targets/autotests/tools/free_mem.bash $OPENAIR_DIR/targets/bin/nr_pucchsim.Rel15 - -R 106 -i 1 -P 0 -b 1 -s-7 -n1000 - -R 106 -i 1 -P 0 -b 2 -s-7 -n1000 + -R 106 -i 1 -P 0 -b 1 -s-2 -n1000 + -R 106 -i 1 -P 0 -b 2 -s-2 -n1000 + -R 106 -i 1 -P 0 -b 2 -s-2 -c -n1000 + -R 106 -i 1 -P 2 -b 3 -s0 -n1000 + -R 106 -i 1 -P 2 -b 4 -s0 -n1000 + -R 106 -i 1 -P 2 -b 5 -s1 -n1000 + -R 106 -i 1 -P 2 -b 6 -s2 -n1000 + -R 106 -i 1 -P 2 -b 7 -s3 -n1000 + -R 106 -i 1 -P 2 -b 8 -s4 -n1000 + -R 106 -i 1 -P 2 -b 9 -s5 -n1000 + -R 106 -i 1 -P 2 -b 10 -s6 -n1000 + -R 106 -i 1 -P 2 -b 11 -s6 -n1000 - nr_pucchsim.test1 nr_pucchsim.test2 + nr_pucchsim.test1 nr_pucchsim.test2 nr_pucchsim.test3 nr_pucchsim.test4 nr_pucchsim.test5 nr_pucchsim.test6 nr_pucchsim.test7 nr_pucchsim.test8 nr_pucchsim.test9 nr_pucchsim.test10 nr_pucchsim.test11 nr_pucchsim.test12 PUCCH test OK segmentation fault|assertion|exiting|fatal 3 From 7689b9394ac88d6130a9fe280bf84770174875b5 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 23 Apr 2020 22:49:33 +0200 Subject: [PATCH 199/240] added missing file --- openair1/PHY/NR_REFSIG/scrambling_luts.c | 62 ++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 openair1/PHY/NR_REFSIG/scrambling_luts.c diff --git a/openair1/PHY/NR_REFSIG/scrambling_luts.c b/openair1/PHY/NR_REFSIG/scrambling_luts.c new file mode 100644 index 0000000000..eae54f94fb --- /dev/null +++ b/openair1/PHY/NR_REFSIG/scrambling_luts.c @@ -0,0 +1,62 @@ +/* + * 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 + */ + +/* Lookup tables for 3GPP scrambling/unscrambling */ + +/* Author R. Knopp / EURECOM / OpenAirInterface.org */ +#ifndef __SCRAMBLING_LUTS__C__ +#define __SCRAMBLING_LUTS__C__ + +#include "PHY/impl_defs_nr.h" +#include "PHY/sse_intrin.h" + +__m64 byte2m64_re[256]; +__m64 byte2m64_im[256]; + +void init_byte2m64() { + + for (int s=0;s<256;s++) { + byte2m64_re[s] = _mm_insert_pi16(byte2m64_re[s],(1-2*(s&1)),0); + byte2m64_im[s] = _mm_insert_pi16(byte2m64_im[s],(1-2*((s>>1)&1)),0); + byte2m64_re[s] = _mm_insert_pi16(byte2m64_re[s],(1-2*((s>>2)&1)),1); + byte2m64_im[s] = _mm_insert_pi16(byte2m64_im[s],(1-2*((s>>3)&1)),1); + byte2m64_re[s] = _mm_insert_pi16(byte2m64_re[s],(1-2*((s>>4)&1)),2); + byte2m64_im[s] = _mm_insert_pi16(byte2m64_im[s],(1-2*((s>>5)&1)),2); + byte2m64_re[s] = _mm_insert_pi16(byte2m64_re[s],(1-2*((s>>6)&1)),3); + byte2m64_im[s] = _mm_insert_pi16(byte2m64_im[s],(1-2*((s>>7)&1)),3); + printf("init_scrambling_luts: s %x (%d) ((%d,%d),(%d,%d),(%d,%d),(%d,%d))\n", + ((uint16_t*)&s)[0], + (1-2*(s&1)), + ((int16_t*)&byte2m64_re[s])[0],((int16_t*)&byte2m64_im[s])[0], + ((int16_t*)&byte2m64_re[s])[1],((int16_t*)&byte2m64_im[s])[1], + ((int16_t*)&byte2m64_re[s])[2],((int16_t*)&byte2m64_im[s])[2], + ((int16_t*)&byte2m64_re[s])[3],((int16_t*)&byte2m64_im[s])[3]); + + } +} + +void init_scrambling_luts() { + + init_byte2m64(); + +} + +#endif From fd50f1b5bd6d0264531f5181984f57dcbb485c90 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Fri, 24 Apr 2020 01:44:47 +0200 Subject: [PATCH 200/240] fixed round update in UE --- openair1/SCHED_NR_UE/fapi_nr_ue_l1.c | 5 +++-- openair1/SIMULATION/NR_PHY/dlsim.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index 69876159d6..a78024f70c 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -34,6 +34,7 @@ #include "fapi_nr_ue_interface.h" #include "fapi_nr_ue_l1.h" +#include "harq_nr.h" //#include "PHY/phy_vars_nr_ue.h" #include "PHY/defs_nr_UE.h" @@ -95,14 +96,14 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response) dlsch0_harq->dlDmrsSymbPos = dlsch_config_pdu->dlDmrsSymbPos; dlsch0_harq->dmrsConfigType = dlsch_config_pdu->dmrsConfigType; dlsch0_harq->mcs = dlsch_config_pdu->mcs; - dlsch0_harq->DCINdi = dlsch_config_pdu->ndi; dlsch0_harq->rvidx = dlsch_config_pdu->rv; dlsch0->g_pucch = dlsch_config_pdu->accumulated_delta_PUCCH; dlsch0_harq->harq_ack.pucch_resource_indicator = dlsch_config_pdu->pucch_resource_id; dlsch0_harq->harq_ack.slot_for_feedback_ack = dlsch_config_pdu->pdsch_to_harq_feedback_time_ind; dlsch0_harq->Nl=1; dlsch0_harq->mcs_table=0; - dlsch0_harq->status = ACTIVE; + dlsch0_harq->harq_ack.rx_status = downlink_harq_process(dlsch0_harq, dlsch0->current_harq_pid, dlsch_config_pdu->ndi, dlsch0->rnti_type); +ACTIVE; LOG_D(MAC,">>>> \tdlsch0->g_pucch=%d\tdlsch0_harq.mcs=%d\n",dlsch0->g_pucch,dlsch0_harq->mcs); } diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index e806a6867a..50ea3f21de 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -732,7 +732,7 @@ int main(int argc, char **argv) memset(RC.nrmac[0]->cce_list[1][1],0,MAX_NUM_CCE*sizeof(int)); clear_nr_nfapi_information(RC.nrmac[0], 0, frame, slot); - UE_list->UE_sched_ctrl[0].harq_processes[0].ndi = (round==0) ? 1 : 0; + UE_list->UE_sched_ctrl[0].harq_processes[0].ndi = !(trial&1); UE_list->UE_sched_ctrl[0].harq_processes[0].round = round; gNB->dlsch[0][0]->harq_processes[0]->round = round; From b1da29427c07af02c4f9fcef955fc1a19e4a20bd Mon Sep 17 00:00:00 2001 From: laurent Date: Tue, 28 Apr 2020 14:32:31 +0200 Subject: [PATCH 201/240] justone log line --- openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c | 1 - 1 file changed, 1 deletion(-) diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c index 0e7bdd2ae4..f357e385f0 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c @@ -780,7 +780,6 @@ void ulsch_channel_compensation(int32_t **rxdataF_ext, #endif for (rb=0; rb Date: Tue, 28 Apr 2020 15:39:50 +0200 Subject: [PATCH 202/240] set back rrc as a separate thread, lead to create back race conditions --- common/utils/ocp_itti/intertask_interface.h | 2 +- openair2/RRC/LTE/rrc_eNB.c | 15 ++++++--------- targets/COMMON/create_tasks.c | 6 +++--- targets/RT/USER/lte-softmodem.c | 9 ++++++--- targets/RT/USER/lte-uesoftmodem.c | 6 ------ 5 files changed, 16 insertions(+), 22 deletions(-) diff --git a/common/utils/ocp_itti/intertask_interface.h b/common/utils/ocp_itti/intertask_interface.h index 265a57ca63..ed4192eed6 100644 --- a/common/utils/ocp_itti/intertask_interface.h +++ b/common/utils/ocp_itti/intertask_interface.h @@ -288,7 +288,7 @@ void * rrc_enb_process_msg(void*); TASK_DEF(TASK_PDCP_ENB, TASK_PRIORITY_MED, 200, NULL, NULL) \ TASK_DEF(TASK_DATA_FORWARDING, TASK_PRIORITY_MED, 200, NULL, NULL) \ TASK_DEF(TASK_END_MARKER, TASK_PRIORITY_MED, 200, NULL, NULL) \ - TASK_DEF(TASK_RRC_ENB, TASK_PRIORITY_MED, 200, rrc_enb_process_msg,NULL)\ + TASK_DEF(TASK_RRC_ENB, TASK_PRIORITY_MED, 200, NULL,NULL)\ TASK_DEF(TASK_RRC_GNB, TASK_PRIORITY_MED, 200, NULL,NULL)\ TASK_DEF(TASK_RAL_ENB, TASK_PRIORITY_MED, 200, NULL, NULL) \ TASK_DEF(TASK_S1AP, TASK_PRIORITY_MED, 200, NULL, NULL) \ diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index 9cca00ca2e..181346a014 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -8884,29 +8884,26 @@ void *rrc_enb_process_itti_msg(void *notUsed) { return NULL; } -// as there are race conditions, no rrc thread //----------------------------------------------------------------------------- void * -rrc_enb_process_msg( +rrc_enb_task( void *args_p ) //----------------------------------------------------------------------------- { + rrc_enb_init(); + itti_mark_task_ready(TASK_RRC_ENB); + LOG_I(RRC,"Entering main loop of RRC message task\n"); - //while (1) { - //(void) rrc_enb_process_itti_msg(NULL); - //} - - //while (1) { + while (1) { (void) rrc_enb_process_itti_msg(NULL); { //extern volatile int go_nr; void rrc_go_nr(void); //if (go_nr) rrc_go_nr(); } - //} -return NULL; + } } /*------------------------------------------------------------------------------*/ diff --git a/targets/COMMON/create_tasks.c b/targets/COMMON/create_tasks.c index 10691d2db8..4d57ab4e16 100644 --- a/targets/COMMON/create_tasks.c +++ b/targets/COMMON/create_tasks.c @@ -56,9 +56,9 @@ int create_tasks(uint32_t enb_nb) { rc = itti_create_task (TASK_ENB_APP, eNB_app_task, NULL); AssertFatal(rc >= 0, "Create task for eNB APP failed\n"); - // No more rrc thread, as many race conditions are hidden behind - rrc_enb_init(); - itti_mark_task_ready(TASK_RRC_ENB); + LOG_I(RRC,"Creating RRC eNB Task\n"); + rc = itti_create_task (TASK_RRC_ENB, rrc_enb_task, NULL); + AssertFatal(rc >= 0, "Create task for RRC eNB failed\n"); if (EPC_MODE_ENABLED && ! ( split73==SPLIT73_DU ) ) { rc = itti_create_task(TASK_SCTP, sctp_eNB_task, NULL); diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index f5db3d3c5a..d8c5e25593 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -446,9 +446,12 @@ int restart_L1L2(module_id_t enb_id) { init_UE_info(&RC.mac[enb_id]->UE_info); LOG_I(ENB_APP, "attempting to create ITTI tasks\n"); - // No more rrc thread, as many race conditions are hidden behind - rrc_enb_init(); - itti_mark_task_ready(TASK_RRC_ENB); + if (itti_create_task (TASK_RRC_ENB, rrc_enb_task, NULL) < 0) { + LOG_E(RRC, "Create task for RRC eNB failed\n"); + return -1; + } else { + LOG_I(RRC, "Re-created task for RRC eNB successfully\n"); + } /* pass a reconfiguration request which will configure everything down to * RC.eNB[i][j]->frame_parms, too */ diff --git a/targets/RT/USER/lte-uesoftmodem.c b/targets/RT/USER/lte-uesoftmodem.c index 395e73bb66..2c9271888b 100644 --- a/targets/RT/USER/lte-uesoftmodem.c +++ b/targets/RT/USER/lte-uesoftmodem.c @@ -541,12 +541,6 @@ void init_pdcp(void) { pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind); } -// Stupid function addition because UE itti messages queues definition is common with eNB -void *rrc_enb_process_msg(void *notUsed) { -AssertFatal(false,""); - return NULL; -} - int main( int argc, char **argv ) { int CC_id; uint8_t abstraction_flag=0; From 9480293cdab282f33ad1da46cd292c96ed80c50a Mon Sep 17 00:00:00 2001 From: laurent Date: Tue, 28 Apr 2020 16:33:50 +0200 Subject: [PATCH 203/240] include dir --- cmake_targets/nas_sim_tools/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake_targets/nas_sim_tools/CMakeLists.txt b/cmake_targets/nas_sim_tools/CMakeLists.txt index c1a0bb419b..308c71be4c 100644 --- a/cmake_targets/nas_sim_tools/CMakeLists.txt +++ b/cmake_targets/nas_sim_tools/CMakeLists.txt @@ -14,6 +14,7 @@ set(CMAKE_C_FLAGS set(OPENAIR_DIR $ENV{OPENAIR_DIR}) set(OPENAIR3_DIR $ENV{OPENAIR_DIR}/openair3) +include_directories (${OPENAIR_DIR}/openair2/COMMON) set(CONF2UEDATA_LIB_SRC ${OPENAIR_DIR}/openair3/NAS/TOOLS/conf_emm.c From 4eb78faaa13d5b9d0692f066c7148a5315ae2bf7 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Tue, 28 Apr 2020 21:59:34 +0200 Subject: [PATCH 204/240] added harq stats in dlsim --- openair1/SIMULATION/NR_PHY/dlsim.c | 33 +++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 50ea3f21de..00552fc953 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -139,6 +139,9 @@ int main(int argc, char **argv) int i,aa;//,l; double sigma2, sigma2_dB=10, SNR, snr0=-2.0, snr1=2.0; uint8_t snr1set=0; + float roundStats[50]; + float psnr; + uint8_t snrRun; int **txdata; double **s_re,**s_im,**r_re,**r_im; //double iqim = 0.0; @@ -682,6 +685,7 @@ int main(int argc, char **argv) nr_ue_phy_config_request(&UE_mac->phy_config); NR_UE_list_t *UE_list = &RC.nrmac[0]->UE_list; NR_COMMON_channels_t *cc = RC.nrmac[0]->common_channels; + snrRun = 0; for (SNR = snr0; SNR < snr1; SNR += .2) { @@ -726,6 +730,8 @@ int main(int argc, char **argv) UE_harq_process->harq_ack.ack = 0; round = 0; + UE_harq_process->round = round; + UE_harq_process->first_tx = 1; while ((roundharq_ack.ack==0)) { memset(RC.nrmac[0]->cce_list[1][0],0,MAX_NUM_CCE*sizeof(int)); @@ -827,11 +833,7 @@ int main(int argc, char **argv) do_pdcch_flag, normal_txrx); - if (UE->dlsch[UE->current_thread_id[slot]][0][0]->last_iteration_cnt >= - UE->dlsch[UE->current_thread_id[slot]][0][0]->max_ldpc_iterations+1) - n_errors++; - - printf("dlsim round %d ends\n",round); + //printf("dlsim round %d ends\n",round); round++; } // round @@ -839,12 +841,13 @@ int main(int argc, char **argv) //---------------------- count errors ---------------------- //---------------------------------------------------------- - + if (UE->dlsch[UE->current_thread_id[slot]][0][0]->last_iteration_cnt >= + UE->dlsch[UE->current_thread_id[slot]][0][0]->max_ldpc_iterations+1) + n_errors++; NR_UE_PDSCH **pdsch_vars = UE->pdsch_vars[UE->current_thread_id[UE_proc.nr_tti_rx]]; int16_t *UE_llr = pdsch_vars[0]->llr[0]; - uint32_t TBS = rel15->TBSize[0]; uint16_t length_dmrs = 1; uint16_t nb_rb = rel15->rbSize; @@ -892,15 +895,16 @@ int main(int argc, char **argv) if (n_trials == 1) printf("errors_bit = %u (trial %d)\n", errors_bit, trial); } - + roundStats[snrRun]+=((float)round); } // noise trials + roundStats[snrRun]/=((float)n_trials); printf("*****************************************\n"); printf("SNR %f, (false positive %f)\n", SNR, (float) n_errors / (float) n_trials); printf("*****************************************\n"); printf("\n"); - printf("SNR %f : n_errors (negative CRC) = %d/%d, Channel BER %e\n", SNR, n_errors, n_trials,(double)errors_scrambling/available_bits/n_trials); + printf("SNR %f : n_errors (negative CRC) = %d/%d, Avg round %.2f, Channel BER %e\n", SNR, n_errors, n_trials,roundStats[snrRun],(double)errors_scrambling/available_bits/n_trials); printf("\n"); if (n_trials == 1) { @@ -910,7 +914,6 @@ int main(int argc, char **argv) LOG_M("rxsig1.m","rxs1", UE->common_vars.rxdata[1], frame_length_complex_samples, 1, 1); LOG_M("chestF0.m","chF0",UE->pdsch_vars[0][0]->dl_ch_estimates_ext,N_RB_DL*12*14,1,1); write_output("rxF_comp.m","rxFc",&UE->pdsch_vars[0][0]->rxdataF_comp0[0][0],N_RB_DL*12*14,1,1); - break; } if ((float)n_errors/(float)n_trials <= target_error_rate) { @@ -969,8 +972,18 @@ int main(int argc, char **argv) printStatIndent2(&UE->dlsch_tc_intl2_stats,"intl2+HardDecode+CRC"); */ } + snrRun++; } // NSR + if (n_trials>1) { + printf("HARQ stats:\nSNR\tRounds\n"); + psnr = snr0; + for (uint8_t i=0; i Date: Wed, 29 Apr 2020 10:29:02 +0200 Subject: [PATCH 205/240] LIC: wrong license banner on proto-agent files Signed-off-by: Raphael Defosseux --- openair2/LAYER2/PROTO_AGENT/proto_agent.c | 48 ++++++++---------- openair2/LAYER2/PROTO_AGENT/proto_agent.h | 49 ++++++++----------- .../LAYER2/PROTO_AGENT/proto_agent_async.c | 49 ++++++++----------- .../LAYER2/PROTO_AGENT/proto_agent_async.h | 48 ++++++++---------- .../LAYER2/PROTO_AGENT/proto_agent_common.c | 48 ++++++++---------- .../LAYER2/PROTO_AGENT/proto_agent_common.h | 48 ++++++++---------- .../LAYER2/PROTO_AGENT/proto_agent_defs.h | 48 ++++++++---------- .../LAYER2/PROTO_AGENT/proto_agent_handler.c | 48 ++++++++---------- .../LAYER2/PROTO_AGENT/proto_agent_net_comm.c | 48 ++++++++---------- .../LAYER2/PROTO_AGENT/proto_agent_net_comm.h | 48 ++++++++---------- 10 files changed, 200 insertions(+), 282 deletions(-) diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent.c b/openair2/LAYER2/PROTO_AGENT/proto_agent.c index bead6ad28d..6bf9cdce22 100644 --- a/openair2/LAYER2/PROTO_AGENT/proto_agent.c +++ b/openair2/LAYER2/PROTO_AGENT/proto_agent.c @@ -1,31 +1,23 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2014 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France. - - *******************************************************************************/ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ /*! \file enb_agent.h * \brief top level enb agent receive thread and itti task diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent.h b/openair2/LAYER2/PROTO_AGENT/proto_agent.h index 927b714b2c..6898c9e447 100644 --- a/openair2/LAYER2/PROTO_AGENT/proto_agent.h +++ b/openair2/LAYER2/PROTO_AGENT/proto_agent.h @@ -1,32 +1,23 @@ - -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2014 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France. - - *******************************************************************************/ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ /*! \file proto_agent.h * \brief top level protocol agent diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent_async.c b/openair2/LAYER2/PROTO_AGENT/proto_agent_async.c index eef697c5bb..df3684ee27 100644 --- a/openair2/LAYER2/PROTO_AGENT/proto_agent_async.c +++ b/openair2/LAYER2/PROTO_AGENT/proto_agent_async.c @@ -1,32 +1,23 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2014 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France. - - *******************************************************************************/ - +/* + * 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 "proto_agent_async.h" #include "proto_agent_defs.h" diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent_async.h b/openair2/LAYER2/PROTO_AGENT/proto_agent_async.h index 27030924cd..6bc952e804 100644 --- a/openair2/LAYER2/PROTO_AGENT/proto_agent_async.h +++ b/openair2/LAYER2/PROTO_AGENT/proto_agent_async.h @@ -1,31 +1,23 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2014 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France. - - *******************************************************************************/ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ /*! \file enb_agent_async.h * \brief channel implementation for async interface diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent_common.c b/openair2/LAYER2/PROTO_AGENT/proto_agent_common.c index a11c029bd3..6e343343cd 100644 --- a/openair2/LAYER2/PROTO_AGENT/proto_agent_common.c +++ b/openair2/LAYER2/PROTO_AGENT/proto_agent_common.c @@ -1,31 +1,23 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2014 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France. - - *******************************************************************************/ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ /*! \file proto_agent_common.c * \brief common primitives for all agents diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent_common.h b/openair2/LAYER2/PROTO_AGENT/proto_agent_common.h index 70e6b2a84e..c805b81543 100644 --- a/openair2/LAYER2/PROTO_AGENT/proto_agent_common.h +++ b/openair2/LAYER2/PROTO_AGENT/proto_agent_common.h @@ -1,31 +1,23 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2014 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France. - - *******************************************************************************/ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ /*! \file enb_agent_common.h * \brief common message primitves and utilities diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent_defs.h b/openair2/LAYER2/PROTO_AGENT/proto_agent_defs.h index 08c91e7085..cd730a6de8 100644 --- a/openair2/LAYER2/PROTO_AGENT/proto_agent_defs.h +++ b/openair2/LAYER2/PROTO_AGENT/proto_agent_defs.h @@ -1,31 +1,23 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2016 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France. - - *******************************************************************************/ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ /*! \file enb_agent_defs.h * \brief enb agent common definitions diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent_handler.c b/openair2/LAYER2/PROTO_AGENT/proto_agent_handler.c index cb65da2803..82f7849717 100644 --- a/openair2/LAYER2/PROTO_AGENT/proto_agent_handler.c +++ b/openair2/LAYER2/PROTO_AGENT/proto_agent_handler.c @@ -1,31 +1,23 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2014 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France. - - *******************************************************************************/ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ /*! \file enb_agent_handler.c * \brief enb agent tx and rx message handler diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent_net_comm.c b/openair2/LAYER2/PROTO_AGENT/proto_agent_net_comm.c index f64a58f8e1..9a63427ed5 100644 --- a/openair2/LAYER2/PROTO_AGENT/proto_agent_net_comm.c +++ b/openair2/LAYER2/PROTO_AGENT/proto_agent_net_comm.c @@ -1,31 +1,23 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2016 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France. - - *******************************************************************************/ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ /*! \file enb_agent_net_comm.c * \brief enb agent network interface abstraction diff --git a/openair2/LAYER2/PROTO_AGENT/proto_agent_net_comm.h b/openair2/LAYER2/PROTO_AGENT/proto_agent_net_comm.h index c956bf48b1..55fca5a928 100644 --- a/openair2/LAYER2/PROTO_AGENT/proto_agent_net_comm.h +++ b/openair2/LAYER2/PROTO_AGENT/proto_agent_net_comm.h @@ -1,31 +1,23 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2016 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France. - - *******************************************************************************/ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ /*! \file enb_agent_net_comm.h * \brief enb agent network interface abstraction From 9ac5f6015de28abd02ccb3ac36cc367d6e205157 Mon Sep 17 00:00:00 2001 From: laurent Date: Wed, 29 Apr 2020 11:31:00 +0200 Subject: [PATCH 206/240] update license text --- cmake_targets/CMakeLists.txt | 1 + common/utils/ocp_itti/intertask_interface.cpp | 23 ++++++++++++++-- common/utils/ocp_itti/intertask_interface.h | 23 ++++++++++++++-- common/utils/threadPool/measurement_display.c | 23 ++++++++++++++-- common/utils/threadPool/thread-pool.c | 23 ++++++++++++++-- common/utils/threadPool/thread-pool.h | 23 ++++++++++++++-- executables/main-fs6.c | 23 ++++++++++++++-- executables/main-ocp.c | 26 +++++++++++++++++-- executables/split_headers.h | 24 +++++++++++++++-- executables/transport_split.c | 25 ++++++++++++++++-- targets/ARCH/rfsimulator/apply_channelmod.c | 23 +++++++++++++--- targets/ARCH/rfsimulator/simulator.c | 23 ++++++++++++++-- targets/ARCH/rfsimulator/stored_node.c | 23 ++++++++++++++-- 13 files changed, 258 insertions(+), 25 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 6382bbea51..acacba5cbc 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -884,6 +884,7 @@ include_directories("${OPENAIR2_DIR}/LAYER2/PDCP_v10.1.0") include_directories("${OPENAIR2_DIR}/RRC/LTE/MESSAGES") include_directories("${OPENAIR2_DIR}/RRC/LTE") include_directories("${OPENAIR_DIR}/common/utils") +include_directories("${OPENAIR_DIR}/common/utils/collection") include_directories("${OPENAIR_DIR}/common/utils/ocp_itti") include_directories("${OPENAIR3_DIR}/NAS/COMMON") include_directories("${OPENAIR3_DIR}/NAS/COMMON/API/NETWORK") diff --git a/common/utils/ocp_itti/intertask_interface.cpp b/common/utils/ocp_itti/intertask_interface.cpp index 42c3828dc4..3d4d356dcf 100644 --- a/common/utils/ocp_itti/intertask_interface.cpp +++ b/common/utils/ocp_itti/intertask_interface.cpp @@ -1,7 +1,26 @@ /* - Author: Laurent THOMAS, Open Cells - copyleft: OpenAirInterface Software Alliance and it's licence +* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The OpenAirInterface Software Alliance licenses this file to You under +* the OAI Public License, Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.openairinterface.org/?page_id=698 +* +* Author and copyright: Laurent Thomas, open-cells.com +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*------------------------------------------------------------------------------- +* For more information about the OpenAirInterface (OAI) Software Alliance: +* contact@openairinterface.org */ + #include #include #include diff --git a/common/utils/ocp_itti/intertask_interface.h b/common/utils/ocp_itti/intertask_interface.h index ed4192eed6..0cd25ee231 100644 --- a/common/utils/ocp_itti/intertask_interface.h +++ b/common/utils/ocp_itti/intertask_interface.h @@ -1,7 +1,26 @@ /* - Author: Laurent THOMAS, Open Cells - Copyleft: OpenAirInterface software alliance and it's license +* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The OpenAirInterface Software Alliance licenses this file to You under +* the OAI Public License, Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.openairinterface.org/?page_id=698 +* +* Author and copyright: Laurent Thomas, open-cells.com +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*------------------------------------------------------------------------------- +* For more information about the OpenAirInterface (OAI) Software Alliance: +* contact@openairinterface.org */ + #ifndef INTERTASK_INTERFACE_H_ #define INTERTASK_INTERFACE_H_ #include diff --git a/common/utils/threadPool/measurement_display.c b/common/utils/threadPool/measurement_display.c index 8f6e2c239a..0f5a3e0f69 100644 --- a/common/utils/threadPool/measurement_display.c +++ b/common/utils/threadPool/measurement_display.c @@ -1,7 +1,26 @@ /* - Author: Laurent THOMAS, Open Cells - copyleft: OpenAirInterface Software Alliance and it's licence +* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The OpenAirInterface Software Alliance licenses this file to You under +* the OAI Public License, Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.openairinterface.org/?page_id=698 +* +* Author and copyright: Laurent Thomas, open-cells.com +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*------------------------------------------------------------------------------- +* For more information about the OpenAirInterface (OAI) Software Alliance: +* contact@openairinterface.org */ + #include #include "thread-pool.h" diff --git a/common/utils/threadPool/thread-pool.c b/common/utils/threadPool/thread-pool.c index dd3d16d717..cbb2dbe3d9 100644 --- a/common/utils/threadPool/thread-pool.c +++ b/common/utils/threadPool/thread-pool.c @@ -1,8 +1,27 @@ /* - Author: Laurent THOMAS, Open Cells - copyleft: OpenAirInterface Software Alliance and it's licence +* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The OpenAirInterface Software Alliance licenses this file to You under +* the OAI Public License, Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.openairinterface.org/?page_id=698 +* +* Author and copyright: Laurent Thomas, open-cells.com +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*------------------------------------------------------------------------------- +* For more information about the OpenAirInterface (OAI) Software Alliance: +* contact@openairinterface.org */ + #define _GNU_SOURCE #include #include diff --git a/common/utils/threadPool/thread-pool.h b/common/utils/threadPool/thread-pool.h index 1b59fb1589..0ed8715811 100644 --- a/common/utils/threadPool/thread-pool.h +++ b/common/utils/threadPool/thread-pool.h @@ -1,8 +1,27 @@ /* - Author: Laurent THOMAS, Open Cells - copyleft: OpenAirInterface Software Alliance and it's licence +* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The OpenAirInterface Software Alliance licenses this file to You under +* the OAI Public License, Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.openairinterface.org/?page_id=698 +* +* Author and copyright: Laurent Thomas, open-cells.com +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*------------------------------------------------------------------------------- +* For more information about the OpenAirInterface (OAI) Software Alliance: +* contact@openairinterface.org */ + #ifndef THREAD_POOL_H #define THREAD_POOL_H #include diff --git a/executables/main-fs6.c b/executables/main-fs6.c index a10d96b556..45a6271887 100644 --- a/executables/main-fs6.c +++ b/executables/main-fs6.c @@ -1,7 +1,26 @@ /* - Author: Laurent THOMAS, Open Cells Project company, funded by IRT SystemX - copyleft: OpenAirInterface Software Alliance and it's licence +* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The OpenAirInterface Software Alliance licenses this file to You under +* the OAI Public License, Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.openairinterface.org/?page_id=698 +* +* Author and copyright: Laurent Thomas, open-cells.com +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*------------------------------------------------------------------------------- +* For more information about the OpenAirInterface (OAI) Software Alliance: +* contact@openairinterface.org */ + #include #include #include diff --git a/executables/main-ocp.c b/executables/main-ocp.c index 8171d78d5b..d2ee9418dc 100644 --- a/executables/main-ocp.c +++ b/executables/main-ocp.c @@ -1,6 +1,28 @@ /* - Author: Laurent THOMAS, Open Cells Project company, funded by IRT SystemX - copyleft: OpenAirInterface Software Alliance and it's licence +* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The OpenAirInterface Software Alliance licenses this file to You under +* the OAI Public License, Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.openairinterface.org/?page_id=698 +* +* Author and copyright: Laurent Thomas, open-cells.com +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*------------------------------------------------------------------------------- +* For more information about the OpenAirInterface (OAI) Software Alliance: +* contact@openairinterface.org +*/ + + +/* * This file replaces * targets/RT/USER/lte-softmodem.c * targets/RT/USER/rt_wrapper.c diff --git a/executables/split_headers.h b/executables/split_headers.h index 62293c7369..4e328f74c4 100644 --- a/executables/split_headers.h +++ b/executables/split_headers.h @@ -1,7 +1,27 @@ /* - Author: Laurent THOMAS, Open Cells Project company, funded by IRT SystemX - copyleft: OpenAirInterface Software Alliance and it's licence +* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The OpenAirInterface Software Alliance licenses this file to You under +* the OAI Public License, Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.openairinterface.org/?page_id=698 +* +* Author and copyright: Laurent Thomas, open-cells.com +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*------------------------------------------------------------------------------- +* For more information about the OpenAirInterface (OAI) Software Alliance: +* contact@openairinterface.org */ + + #ifndef __SPLIT_HEADERS_H #define __SPLIT_HEADERS_H diff --git a/executables/transport_split.c b/executables/transport_split.c index 7a1ee3e85e..f380eb90e3 100644 --- a/executables/transport_split.c +++ b/executables/transport_split.c @@ -1,7 +1,28 @@ /* - Author: Laurent THOMAS, Open Cells Project company, funded by IRT SystemX - copyleft: OpenAirInterface Software Alliance and it's licence +* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The OpenAirInterface Software Alliance licenses this file to You under +* the OAI Public License, Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.openairinterface.org/?page_id=698 +* +* Author and copyright: Laurent Thomas, open-cells.com +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*------------------------------------------------------------------------------- +* For more information about the OpenAirInterface (OAI) Software Alliance: +* contact@openairinterface.org */ + + + #include #include /* See NOTES */ #include diff --git a/targets/ARCH/rfsimulator/apply_channelmod.c b/targets/ARCH/rfsimulator/apply_channelmod.c index ef4e564343..faf84bb0aa 100644 --- a/targets/ARCH/rfsimulator/apply_channelmod.c +++ b/targets/ARCH/rfsimulator/apply_channelmod.c @@ -1,7 +1,24 @@ /* - Author: Laurent THOMAS, Open Cells for Nokia - copyleft: OpenAirInterface Software Alliance and it's licence - +* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The OpenAirInterface Software Alliance licenses this file to You under +* the OAI Public License, Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.openairinterface.org/?page_id=698 +* +* Author and copyright: Laurent Thomas, open-cells.com +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*------------------------------------------------------------------------------- +* For more information about the OpenAirInterface (OAI) Software Alliance: +* contact@openairinterface.org */ diff --git a/targets/ARCH/rfsimulator/simulator.c b/targets/ARCH/rfsimulator/simulator.c index a1b517a1ed..dc448b33e9 100644 --- a/targets/ARCH/rfsimulator/simulator.c +++ b/targets/ARCH/rfsimulator/simulator.c @@ -1,8 +1,27 @@ /* - Author: Laurent THOMAS, Open Cells for Nokia - copyleft: OpenAirInterface Software Alliance and it's licence +* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The OpenAirInterface Software Alliance licenses this file to You under +* the OAI Public License, Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.openairinterface.org/?page_id=698 +* +* Author and copyright: Laurent Thomas, open-cells.com +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*------------------------------------------------------------------------------- +* For more information about the OpenAirInterface (OAI) Software Alliance: +* contact@openairinterface.org */ + /* * Open issues and limitations * The read and write should be called in the same thread, that is not new USRP UHD design diff --git a/targets/ARCH/rfsimulator/stored_node.c b/targets/ARCH/rfsimulator/stored_node.c index 2b77c5322d..73f6321ffe 100644 --- a/targets/ARCH/rfsimulator/stored_node.c +++ b/targets/ARCH/rfsimulator/stored_node.c @@ -1,8 +1,27 @@ /* - Author: Laurent THOMAS, Open Cells - copyleft: OpenAirInterface Software Alliance and it's licence +* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The OpenAirInterface Software Alliance licenses this file to You under +* the OAI Public License, Version 1.1 (the "License"); you may not use this file +* except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.openairinterface.org/?page_id=698 +* +* Author and copyright: Laurent Thomas, open-cells.com +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*------------------------------------------------------------------------------- +* For more information about the OpenAirInterface (OAI) Software Alliance: +* contact@openairinterface.org */ + #include volatile int oai_exit = 0; From e5ea8a5a034baecdff08dc0f1260aeb80821b309 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Wed, 29 Apr 2020 16:15:59 +0200 Subject: [PATCH 207/240] rlc v2: fix cmake file --- cmake_targets/CMakeLists.txt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index b5d2e0bc79..bfbec4766b 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -1701,7 +1701,6 @@ set(L2_SRC ${PDCP_DIR}/pdcp_util.c ${PDCP_DIR}/pdcp_security.c ${PDCP_DIR}/pdcp_netlink.c - ${RLC_V2} # ${RRC_DIR}/rrc_UE.c ${RRC_DIR}/rrc_eNB.c ${RRC_DIR}/rrc_eNB_endc.c @@ -1715,7 +1714,7 @@ set(L2_SRC ) set(L2_LTE_SRC - ${RLC_V1} + ${RLC_V2} ) set(L2_NR_SRC @@ -1738,7 +1737,6 @@ set(L2_SRC_UE ${PDCP_DIR}/pdcp_util.c ${PDCP_DIR}/pdcp_security.c ${PDCP_DIR}/pdcp_netlink.c - ${RLC_V2} ${RRC_DIR}/rrc_UE.c ${RRC_DIR}/rrc_common.c ${RRC_DIR}/L2_interface_common.c @@ -1753,7 +1751,7 @@ set(LTE_NR_L2_SRC_UE ${PDCP_DIR}/pdcp_util.c ${PDCP_DIR}/pdcp_security.c ${PDCP_DIR}/pdcp_netlink.c - ${RLC_V1} + ${RLC_V2} ) set(NR_L2_SRC_UE From cd3f5ad001d936e36e3b7e47eaf23f3b1ca7c29b Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 30 Apr 2020 09:18:54 +0200 Subject: [PATCH 208/240] added parameters to generate_pucch2 in ue pucch procedures --- openair1/SCHED_NR_UE/pucch_uci_ue_nr.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c index 326c617dfb..1b62ff81bf 100644 --- a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c +++ b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c @@ -186,6 +186,8 @@ bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_ int pucch_resource_id = MAX_NB_OF_PUCCH_RESOURCES; int pucch_resource_indicator = MAX_PUCCH_RESOURCE_INDICATOR; int n_HARQ_ACK; + uint16_t crnti=0x1234; + int dmrs_scrambling_id=0,data_scrambling_id=0; /* update current context */ @@ -591,7 +593,9 @@ bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_ case pucch_format2_nr: { nr_generate_pucch2(ue, - 0,//ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][gNB_id]->crnti, + crnti, + dmrs_scrambling_id, + data_scrambling_id, ue->common_vars.txdataF, &ue->frame_parms, &ue->pucch_config_dedicated[gNB_id], From 4210c41179f1fae72fd92f22d4ad1188eb7051f4 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 30 Apr 2020 15:48:37 +0200 Subject: [PATCH 209/240] removal of a massive number of warnings --- .../PHY/CODING/nrLDPC_decoder/nrLDPC_mPass.h | 236 +++++++++--------- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 4 +- 2 files changed, 120 insertions(+), 120 deletions(-) diff --git a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_mPass.h b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_mPass.h index 10b45ac0e7..b76750459d 100644 --- a/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_mPass.h +++ b/openair1/PHY/CODING/nrLDPC_decoder/nrLDPC_mPass.h @@ -135,25 +135,25 @@ static inline void nrLDPC_llr2llrProcBuf(t_nrLDPC_lut* p_lut, int8_t* llr, t_nrL */ static inline void nrLDPC_llr2CnProcBuf_BG1(t_nrLDPC_lut* p_lut, int8_t* llr, t_nrLDPC_procBuf* p_procBuf, uint16_t Z) { - const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG1_R13[0]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[0]]) p_lut->circShift[0]; - const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG1_R13[1]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[1]]) p_lut->circShift[1]; - const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG1_R13[2]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[2]]) p_lut->circShift[2]; - const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG1_R13[3]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[3]]) p_lut->circShift[3]; - const uint16_t (*lut_circShift_CNG7) [lut_numCnInCnGroups_BG1_R13[4]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[4]]) p_lut->circShift[4]; - const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG1_R13[5]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[5]]) p_lut->circShift[5]; - const uint16_t (*lut_circShift_CNG9) [lut_numCnInCnGroups_BG1_R13[6]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[6]]) p_lut->circShift[6]; - const uint16_t (*lut_circShift_CNG10)[lut_numCnInCnGroups_BG1_R13[7]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[7]]) p_lut->circShift[7]; - const uint16_t (*lut_circShift_CNG19)[lut_numCnInCnGroups_BG1_R13[8]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[8]]) p_lut->circShift[8]; + const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG1_R13[0]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[0]]) p_lut->circShift[0]; + const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG1_R13[1]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[1]]) p_lut->circShift[1]; + const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG1_R13[2]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[2]]) p_lut->circShift[2]; + const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG1_R13[3]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[3]]) p_lut->circShift[3]; + const uint16_t (*lut_circShift_CNG7) [lut_numCnInCnGroups_BG1_R13[4]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[4]]) p_lut->circShift[4]; + const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG1_R13[5]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[5]]) p_lut->circShift[5]; + const uint16_t (*lut_circShift_CNG9) [lut_numCnInCnGroups_BG1_R13[6]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[6]]) p_lut->circShift[6]; + const uint16_t (*lut_circShift_CNG10)[lut_numCnInCnGroups_BG1_R13[7]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[7]]) p_lut->circShift[7]; + const uint16_t (*lut_circShift_CNG19)[lut_numCnInCnGroups_BG1_R13[8]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[8]]) p_lut->circShift[8]; - const uint8_t (*lut_posBnInCnProcBuf_CNG3) [lut_numCnInCnGroups_BG1_R13[0]] = (uint8_t(*)[lut_numCnInCnGroups_BG1_R13[0]]) p_lut->posBnInCnProcBuf[0]; - const uint8_t (*lut_posBnInCnProcBuf_CNG4) [lut_numCnInCnGroups_BG1_R13[1]] = (uint8_t(*)[lut_numCnInCnGroups_BG1_R13[1]]) p_lut->posBnInCnProcBuf[1]; - const uint8_t (*lut_posBnInCnProcBuf_CNG5) [lut_numCnInCnGroups_BG1_R13[2]] = (uint8_t(*)[lut_numCnInCnGroups_BG1_R13[2]]) p_lut->posBnInCnProcBuf[2]; - const uint8_t (*lut_posBnInCnProcBuf_CNG6) [lut_numCnInCnGroups_BG1_R13[3]] = (uint8_t(*)[lut_numCnInCnGroups_BG1_R13[3]]) p_lut->posBnInCnProcBuf[3]; - const uint8_t (*lut_posBnInCnProcBuf_CNG7) [lut_numCnInCnGroups_BG1_R13[4]] = (uint8_t(*)[lut_numCnInCnGroups_BG1_R13[4]]) p_lut->posBnInCnProcBuf[4]; - const uint8_t (*lut_posBnInCnProcBuf_CNG8) [lut_numCnInCnGroups_BG1_R13[5]] = (uint8_t(*)[lut_numCnInCnGroups_BG1_R13[5]]) p_lut->posBnInCnProcBuf[5]; - const uint8_t (*lut_posBnInCnProcBuf_CNG9) [lut_numCnInCnGroups_BG1_R13[6]] = (uint8_t(*)[lut_numCnInCnGroups_BG1_R13[6]]) p_lut->posBnInCnProcBuf[6]; - const uint8_t (*lut_posBnInCnProcBuf_CNG10)[lut_numCnInCnGroups_BG1_R13[7]] = (uint8_t(*)[lut_numCnInCnGroups_BG1_R13[7]]) p_lut->posBnInCnProcBuf[7]; - const uint8_t (*lut_posBnInCnProcBuf_CNG19)[lut_numCnInCnGroups_BG1_R13[8]] = (uint8_t(*)[lut_numCnInCnGroups_BG1_R13[8]]) p_lut->posBnInCnProcBuf[8]; + const uint8_t (*lut_posBnInCnProcBuf_CNG3) [lut_numCnInCnGroups_BG1_R13[0]] = (const uint8_t(*)[lut_numCnInCnGroups_BG1_R13[0]]) p_lut->posBnInCnProcBuf[0]; + const uint8_t (*lut_posBnInCnProcBuf_CNG4) [lut_numCnInCnGroups_BG1_R13[1]] = (const uint8_t(*)[lut_numCnInCnGroups_BG1_R13[1]]) p_lut->posBnInCnProcBuf[1]; + const uint8_t (*lut_posBnInCnProcBuf_CNG5) [lut_numCnInCnGroups_BG1_R13[2]] = (const uint8_t(*)[lut_numCnInCnGroups_BG1_R13[2]]) p_lut->posBnInCnProcBuf[2]; + const uint8_t (*lut_posBnInCnProcBuf_CNG6) [lut_numCnInCnGroups_BG1_R13[3]] = (const uint8_t(*)[lut_numCnInCnGroups_BG1_R13[3]]) p_lut->posBnInCnProcBuf[3]; + const uint8_t (*lut_posBnInCnProcBuf_CNG7) [lut_numCnInCnGroups_BG1_R13[4]] = (const uint8_t(*)[lut_numCnInCnGroups_BG1_R13[4]]) p_lut->posBnInCnProcBuf[4]; + const uint8_t (*lut_posBnInCnProcBuf_CNG8) [lut_numCnInCnGroups_BG1_R13[5]] = (const uint8_t(*)[lut_numCnInCnGroups_BG1_R13[5]]) p_lut->posBnInCnProcBuf[5]; + const uint8_t (*lut_posBnInCnProcBuf_CNG9) [lut_numCnInCnGroups_BG1_R13[6]] = (const uint8_t(*)[lut_numCnInCnGroups_BG1_R13[6]]) p_lut->posBnInCnProcBuf[6]; + const uint8_t (*lut_posBnInCnProcBuf_CNG10)[lut_numCnInCnGroups_BG1_R13[7]] = (const uint8_t(*)[lut_numCnInCnGroups_BG1_R13[7]]) p_lut->posBnInCnProcBuf[7]; + const uint8_t (*lut_posBnInCnProcBuf_CNG19)[lut_numCnInCnGroups_BG1_R13[8]] = (const uint8_t(*)[lut_numCnInCnGroups_BG1_R13[8]]) p_lut->posBnInCnProcBuf[8]; const uint8_t* lut_numCnInCnGroups = p_lut->numCnInCnGroups; const uint32_t* lut_startAddrCnGroups = p_lut->startAddrCnGroups; @@ -344,19 +344,19 @@ static inline void nrLDPC_llr2CnProcBuf_BG1(t_nrLDPC_lut* p_lut, int8_t* llr, t_ */ static inline void nrLDPC_llr2CnProcBuf_BG2(t_nrLDPC_lut* p_lut, int8_t* llr, t_nrLDPC_procBuf* p_procBuf, uint16_t Z) { - const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG2_R15[0]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[0]]) p_lut->circShift[0]; - const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG2_R15[1]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[1]]) p_lut->circShift[1]; - const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG2_R15[2]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[2]]) p_lut->circShift[2]; - const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG2_R15[3]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[3]]) p_lut->circShift[3]; - const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG2_R15[4]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[4]]) p_lut->circShift[4]; - const uint16_t (*lut_circShift_CNG10) [lut_numCnInCnGroups_BG2_R15[5]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[5]]) p_lut->circShift[5]; + const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG2_R15[0]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[0]]) p_lut->circShift[0]; + const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG2_R15[1]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[1]]) p_lut->circShift[1]; + const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG2_R15[2]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[2]]) p_lut->circShift[2]; + const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG2_R15[3]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[3]]) p_lut->circShift[3]; + const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG2_R15[4]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[4]]) p_lut->circShift[4]; + const uint16_t (*lut_circShift_CNG10) [lut_numCnInCnGroups_BG2_R15[5]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[5]]) p_lut->circShift[5]; - const uint8_t (*lut_posBnInCnProcBuf_CNG3) [lut_numCnInCnGroups_BG2_R15[0]] = (uint8_t(*)[lut_numCnInCnGroups_BG2_R15[0]]) p_lut->posBnInCnProcBuf[0]; - const uint8_t (*lut_posBnInCnProcBuf_CNG4) [lut_numCnInCnGroups_BG2_R15[1]] = (uint8_t(*)[lut_numCnInCnGroups_BG2_R15[1]]) p_lut->posBnInCnProcBuf[1]; - const uint8_t (*lut_posBnInCnProcBuf_CNG5) [lut_numCnInCnGroups_BG2_R15[2]] = (uint8_t(*)[lut_numCnInCnGroups_BG2_R15[2]]) p_lut->posBnInCnProcBuf[2]; - const uint8_t (*lut_posBnInCnProcBuf_CNG6) [lut_numCnInCnGroups_BG2_R15[3]] = (uint8_t(*)[lut_numCnInCnGroups_BG2_R15[3]]) p_lut->posBnInCnProcBuf[3]; - const uint8_t (*lut_posBnInCnProcBuf_CNG8) [lut_numCnInCnGroups_BG2_R15[4]] = (uint8_t(*)[lut_numCnInCnGroups_BG2_R15[4]]) p_lut->posBnInCnProcBuf[4]; - const uint8_t (*lut_posBnInCnProcBuf_CNG10) [lut_numCnInCnGroups_BG2_R15[5]] = (uint8_t(*)[lut_numCnInCnGroups_BG2_R15[5]]) p_lut->posBnInCnProcBuf[5]; + const uint8_t (*lut_posBnInCnProcBuf_CNG3) [lut_numCnInCnGroups_BG2_R15[0]] = (const uint8_t(*)[lut_numCnInCnGroups_BG2_R15[0]]) p_lut->posBnInCnProcBuf[0]; + const uint8_t (*lut_posBnInCnProcBuf_CNG4) [lut_numCnInCnGroups_BG2_R15[1]] = (const uint8_t(*)[lut_numCnInCnGroups_BG2_R15[1]]) p_lut->posBnInCnProcBuf[1]; + const uint8_t (*lut_posBnInCnProcBuf_CNG5) [lut_numCnInCnGroups_BG2_R15[2]] = (const uint8_t(*)[lut_numCnInCnGroups_BG2_R15[2]]) p_lut->posBnInCnProcBuf[2]; + const uint8_t (*lut_posBnInCnProcBuf_CNG6) [lut_numCnInCnGroups_BG2_R15[3]] = (const uint8_t(*)[lut_numCnInCnGroups_BG2_R15[3]]) p_lut->posBnInCnProcBuf[3]; + const uint8_t (*lut_posBnInCnProcBuf_CNG8) [lut_numCnInCnGroups_BG2_R15[4]] = (const uint8_t(*)[lut_numCnInCnGroups_BG2_R15[4]]) p_lut->posBnInCnProcBuf[4]; + const uint8_t (*lut_posBnInCnProcBuf_CNG10) [lut_numCnInCnGroups_BG2_R15[5]] = (const uint8_t(*)[lut_numCnInCnGroups_BG2_R15[5]]) p_lut->posBnInCnProcBuf[5]; const uint8_t* lut_numCnInCnGroups = p_lut->numCnInCnGroups; const uint32_t* lut_startAddrCnGroups = p_lut->startAddrCnGroups; @@ -483,26 +483,26 @@ static inline void nrLDPC_cn2bnProcBuf_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf const uint8_t* lut_numCnInCnGroups = p_lut->numCnInCnGroups; const uint32_t* lut_startAddrCnGroups = p_lut->startAddrCnGroups; - const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG2_R15[0]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[0]]) p_lut->circShift[0]; - const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG2_R15[1]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[1]]) p_lut->circShift[1]; - const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG2_R15[2]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[2]]) p_lut->circShift[2]; - const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG2_R15[3]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[3]]) p_lut->circShift[3]; - const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG2_R15[4]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[4]]) p_lut->circShift[4]; - const uint16_t (*lut_circShift_CNG10) [lut_numCnInCnGroups_BG2_R15[5]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[5]]) p_lut->circShift[5]; + const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG2_R15[0]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[0]]) p_lut->circShift[0]; + const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG2_R15[1]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[1]]) p_lut->circShift[1]; + const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG2_R15[2]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[2]]) p_lut->circShift[2]; + const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG2_R15[3]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[3]]) p_lut->circShift[3]; + const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG2_R15[4]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[4]]) p_lut->circShift[4]; + const uint16_t (*lut_circShift_CNG10) [lut_numCnInCnGroups_BG2_R15[5]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[5]]) p_lut->circShift[5]; - const uint32_t (*lut_startAddrBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (uint32_t(*)[lut_numCnInCnGroups[0]]) p_lut->startAddrBnProcBuf[0]; - const uint32_t (*lut_startAddrBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (uint32_t(*)[lut_numCnInCnGroups[1]]) p_lut->startAddrBnProcBuf[1]; - const uint32_t (*lut_startAddrBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (uint32_t(*)[lut_numCnInCnGroups[2]]) p_lut->startAddrBnProcBuf[2]; - const uint32_t (*lut_startAddrBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (uint32_t(*)[lut_numCnInCnGroups[3]]) p_lut->startAddrBnProcBuf[3]; - const uint32_t (*lut_startAddrBnProcBuf_CNG8) [lut_numCnInCnGroups[4]] = (uint32_t(*)[lut_numCnInCnGroups[4]]) p_lut->startAddrBnProcBuf[4]; - const uint32_t (*lut_startAddrBnProcBuf_CNG10) [lut_numCnInCnGroups[5]] = (uint32_t(*)[lut_numCnInCnGroups[5]]) p_lut->startAddrBnProcBuf[5]; + const uint32_t (*lut_startAddrBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (const uint32_t(*)[lut_numCnInCnGroups[0]]) p_lut->startAddrBnProcBuf[0]; + const uint32_t (*lut_startAddrBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (const uint32_t(*)[lut_numCnInCnGroups[1]]) p_lut->startAddrBnProcBuf[1]; + const uint32_t (*lut_startAddrBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (const uint32_t(*)[lut_numCnInCnGroups[2]]) p_lut->startAddrBnProcBuf[2]; + const uint32_t (*lut_startAddrBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (const uint32_t(*)[lut_numCnInCnGroups[3]]) p_lut->startAddrBnProcBuf[3]; + const uint32_t (*lut_startAddrBnProcBuf_CNG8) [lut_numCnInCnGroups[4]] = (const uint32_t(*)[lut_numCnInCnGroups[4]]) p_lut->startAddrBnProcBuf[4]; + const uint32_t (*lut_startAddrBnProcBuf_CNG10) [lut_numCnInCnGroups[5]] = (const uint32_t(*)[lut_numCnInCnGroups[5]]) p_lut->startAddrBnProcBuf[5]; - const uint8_t (*lut_bnPosBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (uint8_t(*)[lut_numCnInCnGroups[0]]) p_lut->bnPosBnProcBuf[0]; - const uint8_t (*lut_bnPosBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (uint8_t(*)[lut_numCnInCnGroups[1]]) p_lut->bnPosBnProcBuf[1]; - const uint8_t (*lut_bnPosBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (uint8_t(*)[lut_numCnInCnGroups[2]]) p_lut->bnPosBnProcBuf[2]; - const uint8_t (*lut_bnPosBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (uint8_t(*)[lut_numCnInCnGroups[3]]) p_lut->bnPosBnProcBuf[3]; - const uint8_t (*lut_bnPosBnProcBuf_CNG8) [lut_numCnInCnGroups[4]] = (uint8_t(*)[lut_numCnInCnGroups[4]]) p_lut->bnPosBnProcBuf[4]; - const uint8_t (*lut_bnPosBnProcBuf_CNG10) [lut_numCnInCnGroups[5]] = (uint8_t(*)[lut_numCnInCnGroups[5]]) p_lut->bnPosBnProcBuf[5]; + const uint8_t (*lut_bnPosBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (const uint8_t(*)[lut_numCnInCnGroups[0]]) p_lut->bnPosBnProcBuf[0]; + const uint8_t (*lut_bnPosBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (const uint8_t(*)[lut_numCnInCnGroups[1]]) p_lut->bnPosBnProcBuf[1]; + const uint8_t (*lut_bnPosBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (const uint8_t(*)[lut_numCnInCnGroups[2]]) p_lut->bnPosBnProcBuf[2]; + const uint8_t (*lut_bnPosBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (const uint8_t(*)[lut_numCnInCnGroups[3]]) p_lut->bnPosBnProcBuf[3]; + const uint8_t (*lut_bnPosBnProcBuf_CNG8) [lut_numCnInCnGroups[4]] = (const uint8_t(*)[lut_numCnInCnGroups[4]]) p_lut->bnPosBnProcBuf[4]; + const uint8_t (*lut_bnPosBnProcBuf_CNG10) [lut_numCnInCnGroups[5]] = (const uint8_t(*)[lut_numCnInCnGroups[5]]) p_lut->bnPosBnProcBuf[5]; int8_t* cnProcBufRes = p_procBuf->cnProcBufRes; int8_t* bnProcBuf = p_procBuf->bnProcBuf; @@ -626,34 +626,34 @@ static inline void nrLDPC_cn2bnProcBuf_BG1(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf const uint8_t* lut_numCnInCnGroups = p_lut->numCnInCnGroups; const uint32_t* lut_startAddrCnGroups = p_lut->startAddrCnGroups; - const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG1_R13[0]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[0]]) p_lut->circShift[0]; - const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG1_R13[1]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[1]]) p_lut->circShift[1]; - const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG1_R13[2]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[2]]) p_lut->circShift[2]; - const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG1_R13[3]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[3]]) p_lut->circShift[3]; - const uint16_t (*lut_circShift_CNG7) [lut_numCnInCnGroups_BG1_R13[4]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[4]]) p_lut->circShift[4]; - const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG1_R13[5]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[5]]) p_lut->circShift[5]; - const uint16_t (*lut_circShift_CNG9) [lut_numCnInCnGroups_BG1_R13[6]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[6]]) p_lut->circShift[6]; - const uint16_t (*lut_circShift_CNG10)[lut_numCnInCnGroups_BG1_R13[7]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[7]]) p_lut->circShift[7]; - const uint16_t (*lut_circShift_CNG19)[lut_numCnInCnGroups_BG1_R13[8]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[8]]) p_lut->circShift[8]; + const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG1_R13[0]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[0]]) p_lut->circShift[0]; + const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG1_R13[1]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[1]]) p_lut->circShift[1]; + const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG1_R13[2]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[2]]) p_lut->circShift[2]; + const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG1_R13[3]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[3]]) p_lut->circShift[3]; + const uint16_t (*lut_circShift_CNG7) [lut_numCnInCnGroups_BG1_R13[4]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[4]]) p_lut->circShift[4]; + const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG1_R13[5]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[5]]) p_lut->circShift[5]; + const uint16_t (*lut_circShift_CNG9) [lut_numCnInCnGroups_BG1_R13[6]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[6]]) p_lut->circShift[6]; + const uint16_t (*lut_circShift_CNG10)[lut_numCnInCnGroups_BG1_R13[7]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[7]]) p_lut->circShift[7]; + const uint16_t (*lut_circShift_CNG19)[lut_numCnInCnGroups_BG1_R13[8]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[8]]) p_lut->circShift[8]; - const uint32_t (*lut_startAddrBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (uint32_t(*)[lut_numCnInCnGroups[0]]) p_lut->startAddrBnProcBuf[0]; - const uint32_t (*lut_startAddrBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (uint32_t(*)[lut_numCnInCnGroups[1]]) p_lut->startAddrBnProcBuf[1]; - const uint32_t (*lut_startAddrBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (uint32_t(*)[lut_numCnInCnGroups[2]]) p_lut->startAddrBnProcBuf[2]; - const uint32_t (*lut_startAddrBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (uint32_t(*)[lut_numCnInCnGroups[3]]) p_lut->startAddrBnProcBuf[3]; - const uint32_t (*lut_startAddrBnProcBuf_CNG7) [lut_numCnInCnGroups[4]] = (uint32_t(*)[lut_numCnInCnGroups[4]]) p_lut->startAddrBnProcBuf[4]; - const uint32_t (*lut_startAddrBnProcBuf_CNG8) [lut_numCnInCnGroups[5]] = (uint32_t(*)[lut_numCnInCnGroups[5]]) p_lut->startAddrBnProcBuf[5]; - const uint32_t (*lut_startAddrBnProcBuf_CNG9) [lut_numCnInCnGroups[6]] = (uint32_t(*)[lut_numCnInCnGroups[6]]) p_lut->startAddrBnProcBuf[6]; - const uint32_t (*lut_startAddrBnProcBuf_CNG10)[lut_numCnInCnGroups[7]] = (uint32_t(*)[lut_numCnInCnGroups[7]]) p_lut->startAddrBnProcBuf[7]; - const uint32_t (*lut_startAddrBnProcBuf_CNG19)[lut_numCnInCnGroups[8]] = (uint32_t(*)[lut_numCnInCnGroups[8]]) p_lut->startAddrBnProcBuf[8]; + const uint32_t (*lut_startAddrBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (const uint32_t(*)[lut_numCnInCnGroups[0]]) p_lut->startAddrBnProcBuf[0]; + const uint32_t (*lut_startAddrBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (const uint32_t(*)[lut_numCnInCnGroups[1]]) p_lut->startAddrBnProcBuf[1]; + const uint32_t (*lut_startAddrBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (const uint32_t(*)[lut_numCnInCnGroups[2]]) p_lut->startAddrBnProcBuf[2]; + const uint32_t (*lut_startAddrBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (const uint32_t(*)[lut_numCnInCnGroups[3]]) p_lut->startAddrBnProcBuf[3]; + const uint32_t (*lut_startAddrBnProcBuf_CNG7) [lut_numCnInCnGroups[4]] = (const uint32_t(*)[lut_numCnInCnGroups[4]]) p_lut->startAddrBnProcBuf[4]; + const uint32_t (*lut_startAddrBnProcBuf_CNG8) [lut_numCnInCnGroups[5]] = (const uint32_t(*)[lut_numCnInCnGroups[5]]) p_lut->startAddrBnProcBuf[5]; + const uint32_t (*lut_startAddrBnProcBuf_CNG9) [lut_numCnInCnGroups[6]] = (const uint32_t(*)[lut_numCnInCnGroups[6]]) p_lut->startAddrBnProcBuf[6]; + const uint32_t (*lut_startAddrBnProcBuf_CNG10)[lut_numCnInCnGroups[7]] = (const uint32_t(*)[lut_numCnInCnGroups[7]]) p_lut->startAddrBnProcBuf[7]; + const uint32_t (*lut_startAddrBnProcBuf_CNG19)[lut_numCnInCnGroups[8]] = (const uint32_t(*)[lut_numCnInCnGroups[8]]) p_lut->startAddrBnProcBuf[8]; - const uint8_t (*lut_bnPosBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (uint8_t(*)[lut_numCnInCnGroups[1]]) p_lut->bnPosBnProcBuf[1]; - const uint8_t (*lut_bnPosBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (uint8_t(*)[lut_numCnInCnGroups[2]]) p_lut->bnPosBnProcBuf[2]; - const uint8_t (*lut_bnPosBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (uint8_t(*)[lut_numCnInCnGroups[3]]) p_lut->bnPosBnProcBuf[3]; - const uint8_t (*lut_bnPosBnProcBuf_CNG7) [lut_numCnInCnGroups[4]] = (uint8_t(*)[lut_numCnInCnGroups[4]]) p_lut->bnPosBnProcBuf[4]; - const uint8_t (*lut_bnPosBnProcBuf_CNG8) [lut_numCnInCnGroups[5]] = (uint8_t(*)[lut_numCnInCnGroups[5]]) p_lut->bnPosBnProcBuf[5]; - const uint8_t (*lut_bnPosBnProcBuf_CNG9) [lut_numCnInCnGroups[6]] = (uint8_t(*)[lut_numCnInCnGroups[6]]) p_lut->bnPosBnProcBuf[6]; - const uint8_t (*lut_bnPosBnProcBuf_CNG10)[lut_numCnInCnGroups[7]] = (uint8_t(*)[lut_numCnInCnGroups[7]]) p_lut->bnPosBnProcBuf[7]; - const uint8_t (*lut_bnPosBnProcBuf_CNG19)[lut_numCnInCnGroups[8]] = (uint8_t(*)[lut_numCnInCnGroups[8]]) p_lut->bnPosBnProcBuf[8]; + const uint8_t (*lut_bnPosBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (const uint8_t(*)[lut_numCnInCnGroups[1]]) p_lut->bnPosBnProcBuf[1]; + const uint8_t (*lut_bnPosBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (const uint8_t(*)[lut_numCnInCnGroups[2]]) p_lut->bnPosBnProcBuf[2]; + const uint8_t (*lut_bnPosBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (const uint8_t(*)[lut_numCnInCnGroups[3]]) p_lut->bnPosBnProcBuf[3]; + const uint8_t (*lut_bnPosBnProcBuf_CNG7) [lut_numCnInCnGroups[4]] = (const uint8_t(*)[lut_numCnInCnGroups[4]]) p_lut->bnPosBnProcBuf[4]; + const uint8_t (*lut_bnPosBnProcBuf_CNG8) [lut_numCnInCnGroups[5]] = (const uint8_t(*)[lut_numCnInCnGroups[5]]) p_lut->bnPosBnProcBuf[5]; + const uint8_t (*lut_bnPosBnProcBuf_CNG9) [lut_numCnInCnGroups[6]] = (const uint8_t(*)[lut_numCnInCnGroups[6]]) p_lut->bnPosBnProcBuf[6]; + const uint8_t (*lut_bnPosBnProcBuf_CNG10)[lut_numCnInCnGroups[7]] = (const uint8_t(*)[lut_numCnInCnGroups[7]]) p_lut->bnPosBnProcBuf[7]; + const uint8_t (*lut_bnPosBnProcBuf_CNG19)[lut_numCnInCnGroups[8]] = (const uint8_t(*)[lut_numCnInCnGroups[8]]) p_lut->bnPosBnProcBuf[8]; int8_t* cnProcBufRes = p_procBuf->cnProcBufRes; int8_t* bnProcBuf = p_procBuf->bnProcBuf; @@ -824,26 +824,26 @@ static inline void nrLDPC_bn2cnProcBuf_BG2(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf const uint8_t* lut_numCnInCnGroups = p_lut->numCnInCnGroups; const uint32_t* lut_startAddrCnGroups = p_lut->startAddrCnGroups; - const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG2_R15[0]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[0]]) p_lut->circShift[0]; - const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG2_R15[1]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[1]]) p_lut->circShift[1]; - const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG2_R15[2]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[2]]) p_lut->circShift[2]; - const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG2_R15[3]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[3]]) p_lut->circShift[3]; - const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG2_R15[4]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[4]]) p_lut->circShift[4]; - const uint16_t (*lut_circShift_CNG10) [lut_numCnInCnGroups_BG2_R15[5]] = (uint16_t(*)[lut_numCnInCnGroups_BG2_R15[5]]) p_lut->circShift[5]; + const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG2_R15[0]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[0]]) p_lut->circShift[0]; + const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG2_R15[1]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[1]]) p_lut->circShift[1]; + const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG2_R15[2]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[2]]) p_lut->circShift[2]; + const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG2_R15[3]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[3]]) p_lut->circShift[3]; + const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG2_R15[4]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[4]]) p_lut->circShift[4]; + const uint16_t (*lut_circShift_CNG10) [lut_numCnInCnGroups_BG2_R15[5]] = (const uint16_t(*)[lut_numCnInCnGroups_BG2_R15[5]]) p_lut->circShift[5]; - const uint32_t (*lut_startAddrBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (uint32_t(*)[lut_numCnInCnGroups[0]]) p_lut->startAddrBnProcBuf[0]; - const uint32_t (*lut_startAddrBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (uint32_t(*)[lut_numCnInCnGroups[1]]) p_lut->startAddrBnProcBuf[1]; - const uint32_t (*lut_startAddrBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (uint32_t(*)[lut_numCnInCnGroups[2]]) p_lut->startAddrBnProcBuf[2]; - const uint32_t (*lut_startAddrBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (uint32_t(*)[lut_numCnInCnGroups[3]]) p_lut->startAddrBnProcBuf[3]; - const uint32_t (*lut_startAddrBnProcBuf_CNG8) [lut_numCnInCnGroups[4]] = (uint32_t(*)[lut_numCnInCnGroups[4]]) p_lut->startAddrBnProcBuf[4]; - const uint32_t (*lut_startAddrBnProcBuf_CNG10) [lut_numCnInCnGroups[5]] = (uint32_t(*)[lut_numCnInCnGroups[5]]) p_lut->startAddrBnProcBuf[5]; + const uint32_t (*lut_startAddrBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (const uint32_t(*)[lut_numCnInCnGroups[0]]) p_lut->startAddrBnProcBuf[0]; + const uint32_t (*lut_startAddrBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (const uint32_t(*)[lut_numCnInCnGroups[1]]) p_lut->startAddrBnProcBuf[1]; + const uint32_t (*lut_startAddrBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (const uint32_t(*)[lut_numCnInCnGroups[2]]) p_lut->startAddrBnProcBuf[2]; + const uint32_t (*lut_startAddrBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (const uint32_t(*)[lut_numCnInCnGroups[3]]) p_lut->startAddrBnProcBuf[3]; + const uint32_t (*lut_startAddrBnProcBuf_CNG8) [lut_numCnInCnGroups[4]] = (const uint32_t(*)[lut_numCnInCnGroups[4]]) p_lut->startAddrBnProcBuf[4]; + const uint32_t (*lut_startAddrBnProcBuf_CNG10) [lut_numCnInCnGroups[5]] = (const uint32_t(*)[lut_numCnInCnGroups[5]]) p_lut->startAddrBnProcBuf[5]; - const uint8_t (*lut_bnPosBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (uint8_t(*)[lut_numCnInCnGroups[0]]) p_lut->bnPosBnProcBuf[0]; - const uint8_t (*lut_bnPosBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (uint8_t(*)[lut_numCnInCnGroups[1]]) p_lut->bnPosBnProcBuf[1]; - const uint8_t (*lut_bnPosBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (uint8_t(*)[lut_numCnInCnGroups[2]]) p_lut->bnPosBnProcBuf[2]; - const uint8_t (*lut_bnPosBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (uint8_t(*)[lut_numCnInCnGroups[3]]) p_lut->bnPosBnProcBuf[3]; - const uint8_t (*lut_bnPosBnProcBuf_CNG8) [lut_numCnInCnGroups[4]] = (uint8_t(*)[lut_numCnInCnGroups[4]]) p_lut->bnPosBnProcBuf[4]; - const uint8_t (*lut_bnPosBnProcBuf_CNG10) [lut_numCnInCnGroups[5]] = (uint8_t(*)[lut_numCnInCnGroups[5]]) p_lut->bnPosBnProcBuf[5]; + const uint8_t (*lut_bnPosBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (const uint8_t(*)[lut_numCnInCnGroups[0]]) p_lut->bnPosBnProcBuf[0]; + const uint8_t (*lut_bnPosBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (const uint8_t(*)[lut_numCnInCnGroups[1]]) p_lut->bnPosBnProcBuf[1]; + const uint8_t (*lut_bnPosBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (const uint8_t(*)[lut_numCnInCnGroups[2]]) p_lut->bnPosBnProcBuf[2]; + const uint8_t (*lut_bnPosBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (const uint8_t(*)[lut_numCnInCnGroups[3]]) p_lut->bnPosBnProcBuf[3]; + const uint8_t (*lut_bnPosBnProcBuf_CNG8) [lut_numCnInCnGroups[4]] = (const uint8_t(*)[lut_numCnInCnGroups[4]]) p_lut->bnPosBnProcBuf[4]; + const uint8_t (*lut_bnPosBnProcBuf_CNG10) [lut_numCnInCnGroups[5]] = (const uint8_t(*)[lut_numCnInCnGroups[5]]) p_lut->bnPosBnProcBuf[5]; int8_t* cnProcBuf = p_procBuf->cnProcBuf; int8_t* bnProcBufRes = p_procBuf->bnProcBufRes; @@ -966,34 +966,34 @@ static inline void nrLDPC_bn2cnProcBuf_BG1(t_nrLDPC_lut* p_lut, t_nrLDPC_procBuf const uint8_t* lut_numCnInCnGroups = p_lut->numCnInCnGroups; const uint32_t* lut_startAddrCnGroups = p_lut->startAddrCnGroups; - const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG1_R13[0]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[0]]) p_lut->circShift[0]; - const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG1_R13[1]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[1]]) p_lut->circShift[1]; - const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG1_R13[2]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[2]]) p_lut->circShift[2]; - const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG1_R13[3]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[3]]) p_lut->circShift[3]; - const uint16_t (*lut_circShift_CNG7) [lut_numCnInCnGroups_BG1_R13[4]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[4]]) p_lut->circShift[4]; - const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG1_R13[5]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[5]]) p_lut->circShift[5]; - const uint16_t (*lut_circShift_CNG9) [lut_numCnInCnGroups_BG1_R13[6]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[6]]) p_lut->circShift[6]; - const uint16_t (*lut_circShift_CNG10)[lut_numCnInCnGroups_BG1_R13[7]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[7]]) p_lut->circShift[7]; - const uint16_t (*lut_circShift_CNG19)[lut_numCnInCnGroups_BG1_R13[8]] = (uint16_t(*)[lut_numCnInCnGroups_BG1_R13[8]]) p_lut->circShift[8]; + const uint16_t (*lut_circShift_CNG3) [lut_numCnInCnGroups_BG1_R13[0]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[0]]) p_lut->circShift[0]; + const uint16_t (*lut_circShift_CNG4) [lut_numCnInCnGroups_BG1_R13[1]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[1]]) p_lut->circShift[1]; + const uint16_t (*lut_circShift_CNG5) [lut_numCnInCnGroups_BG1_R13[2]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[2]]) p_lut->circShift[2]; + const uint16_t (*lut_circShift_CNG6) [lut_numCnInCnGroups_BG1_R13[3]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[3]]) p_lut->circShift[3]; + const uint16_t (*lut_circShift_CNG7) [lut_numCnInCnGroups_BG1_R13[4]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[4]]) p_lut->circShift[4]; + const uint16_t (*lut_circShift_CNG8) [lut_numCnInCnGroups_BG1_R13[5]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[5]]) p_lut->circShift[5]; + const uint16_t (*lut_circShift_CNG9) [lut_numCnInCnGroups_BG1_R13[6]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[6]]) p_lut->circShift[6]; + const uint16_t (*lut_circShift_CNG10)[lut_numCnInCnGroups_BG1_R13[7]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[7]]) p_lut->circShift[7]; + const uint16_t (*lut_circShift_CNG19)[lut_numCnInCnGroups_BG1_R13[8]] = (const uint16_t(*)[lut_numCnInCnGroups_BG1_R13[8]]) p_lut->circShift[8]; - const uint32_t (*lut_startAddrBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (uint32_t(*)[lut_numCnInCnGroups[0]]) p_lut->startAddrBnProcBuf[0]; - const uint32_t (*lut_startAddrBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (uint32_t(*)[lut_numCnInCnGroups[1]]) p_lut->startAddrBnProcBuf[1]; - const uint32_t (*lut_startAddrBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (uint32_t(*)[lut_numCnInCnGroups[2]]) p_lut->startAddrBnProcBuf[2]; - const uint32_t (*lut_startAddrBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (uint32_t(*)[lut_numCnInCnGroups[3]]) p_lut->startAddrBnProcBuf[3]; - const uint32_t (*lut_startAddrBnProcBuf_CNG7) [lut_numCnInCnGroups[4]] = (uint32_t(*)[lut_numCnInCnGroups[4]]) p_lut->startAddrBnProcBuf[4]; - const uint32_t (*lut_startAddrBnProcBuf_CNG8) [lut_numCnInCnGroups[5]] = (uint32_t(*)[lut_numCnInCnGroups[5]]) p_lut->startAddrBnProcBuf[5]; - const uint32_t (*lut_startAddrBnProcBuf_CNG9) [lut_numCnInCnGroups[6]] = (uint32_t(*)[lut_numCnInCnGroups[6]]) p_lut->startAddrBnProcBuf[6]; - const uint32_t (*lut_startAddrBnProcBuf_CNG10)[lut_numCnInCnGroups[7]] = (uint32_t(*)[lut_numCnInCnGroups[7]]) p_lut->startAddrBnProcBuf[7]; - const uint32_t (*lut_startAddrBnProcBuf_CNG19)[lut_numCnInCnGroups[8]] = (uint32_t(*)[lut_numCnInCnGroups[8]]) p_lut->startAddrBnProcBuf[8]; + const uint32_t (*lut_startAddrBnProcBuf_CNG3) [lut_numCnInCnGroups[0]] = (const uint32_t(*)[lut_numCnInCnGroups[0]]) p_lut->startAddrBnProcBuf[0]; + const uint32_t (*lut_startAddrBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (const uint32_t(*)[lut_numCnInCnGroups[1]]) p_lut->startAddrBnProcBuf[1]; + const uint32_t (*lut_startAddrBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (const uint32_t(*)[lut_numCnInCnGroups[2]]) p_lut->startAddrBnProcBuf[2]; + const uint32_t (*lut_startAddrBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (const uint32_t(*)[lut_numCnInCnGroups[3]]) p_lut->startAddrBnProcBuf[3]; + const uint32_t (*lut_startAddrBnProcBuf_CNG7) [lut_numCnInCnGroups[4]] = (const uint32_t(*)[lut_numCnInCnGroups[4]]) p_lut->startAddrBnProcBuf[4]; + const uint32_t (*lut_startAddrBnProcBuf_CNG8) [lut_numCnInCnGroups[5]] = (const uint32_t(*)[lut_numCnInCnGroups[5]]) p_lut->startAddrBnProcBuf[5]; + const uint32_t (*lut_startAddrBnProcBuf_CNG9) [lut_numCnInCnGroups[6]] = (const uint32_t(*)[lut_numCnInCnGroups[6]]) p_lut->startAddrBnProcBuf[6]; + const uint32_t (*lut_startAddrBnProcBuf_CNG10)[lut_numCnInCnGroups[7]] = (const uint32_t(*)[lut_numCnInCnGroups[7]]) p_lut->startAddrBnProcBuf[7]; + const uint32_t (*lut_startAddrBnProcBuf_CNG19)[lut_numCnInCnGroups[8]] = (const uint32_t(*)[lut_numCnInCnGroups[8]]) p_lut->startAddrBnProcBuf[8]; - const uint8_t (*lut_bnPosBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (uint8_t(*)[lut_numCnInCnGroups[1]]) p_lut->bnPosBnProcBuf[1]; - const uint8_t (*lut_bnPosBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (uint8_t(*)[lut_numCnInCnGroups[2]]) p_lut->bnPosBnProcBuf[2]; - const uint8_t (*lut_bnPosBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (uint8_t(*)[lut_numCnInCnGroups[3]]) p_lut->bnPosBnProcBuf[3]; - const uint8_t (*lut_bnPosBnProcBuf_CNG7) [lut_numCnInCnGroups[4]] = (uint8_t(*)[lut_numCnInCnGroups[4]]) p_lut->bnPosBnProcBuf[4]; - const uint8_t (*lut_bnPosBnProcBuf_CNG8) [lut_numCnInCnGroups[5]] = (uint8_t(*)[lut_numCnInCnGroups[5]]) p_lut->bnPosBnProcBuf[5]; - const uint8_t (*lut_bnPosBnProcBuf_CNG9) [lut_numCnInCnGroups[6]] = (uint8_t(*)[lut_numCnInCnGroups[6]]) p_lut->bnPosBnProcBuf[6]; - const uint8_t (*lut_bnPosBnProcBuf_CNG10)[lut_numCnInCnGroups[7]] = (uint8_t(*)[lut_numCnInCnGroups[7]]) p_lut->bnPosBnProcBuf[7]; - const uint8_t (*lut_bnPosBnProcBuf_CNG19)[lut_numCnInCnGroups[8]] = (uint8_t(*)[lut_numCnInCnGroups[8]]) p_lut->bnPosBnProcBuf[8]; + const uint8_t (*lut_bnPosBnProcBuf_CNG4) [lut_numCnInCnGroups[1]] = (const uint8_t(*)[lut_numCnInCnGroups[1]]) p_lut->bnPosBnProcBuf[1]; + const uint8_t (*lut_bnPosBnProcBuf_CNG5) [lut_numCnInCnGroups[2]] = (const uint8_t(*)[lut_numCnInCnGroups[2]]) p_lut->bnPosBnProcBuf[2]; + const uint8_t (*lut_bnPosBnProcBuf_CNG6) [lut_numCnInCnGroups[3]] = (const uint8_t(*)[lut_numCnInCnGroups[3]]) p_lut->bnPosBnProcBuf[3]; + const uint8_t (*lut_bnPosBnProcBuf_CNG7) [lut_numCnInCnGroups[4]] = (const uint8_t(*)[lut_numCnInCnGroups[4]]) p_lut->bnPosBnProcBuf[4]; + const uint8_t (*lut_bnPosBnProcBuf_CNG8) [lut_numCnInCnGroups[5]] = (const uint8_t(*)[lut_numCnInCnGroups[5]]) p_lut->bnPosBnProcBuf[5]; + const uint8_t (*lut_bnPosBnProcBuf_CNG9) [lut_numCnInCnGroups[6]] = (const uint8_t(*)[lut_numCnInCnGroups[6]]) p_lut->bnPosBnProcBuf[6]; + const uint8_t (*lut_bnPosBnProcBuf_CNG10)[lut_numCnInCnGroups[7]] = (const uint8_t(*)[lut_numCnInCnGroups[7]]) p_lut->bnPosBnProcBuf[7]; + const uint8_t (*lut_bnPosBnProcBuf_CNG19)[lut_numCnInCnGroups[8]] = (const uint8_t(*)[lut_numCnInCnGroups[8]]) p_lut->bnPosBnProcBuf[8]; int8_t* cnProcBuf = p_procBuf->cnProcBuf; int8_t* bnProcBufRes = p_procBuf->bnProcBufRes; diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index a2f4b57121..60f9d4747a 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -439,8 +439,8 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) case 2: break; default: - AssertFatal(1==0,"Only PUCCH format 0,1 and 2 are currently supported\n") - } + AssertFatal(1==0,"Only PUCCH format 0,1 and 2 are currently supported\n"); + } } } } From da54778c4ab381743c388078676103663addafcc Mon Sep 17 00:00:00 2001 From: laurent Date: Sun, 3 May 2020 18:27:07 +0200 Subject: [PATCH 210/240] fix warnings --- executables/nr-ru.c | 1 - executables/nr-softmodem.c | 1 - openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c | 3 +- openair1/PHY/NR_TRANSPORT/nr_transport.h | 7 ++ .../NR_TRANSPORT/nr_transport_proto_common.h | 69 +------------------ openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c | 3 +- .../PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c | 3 +- openair1/PHY/NR_UE_TRANSPORT/nr_prach.c | 1 + .../PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c | 5 +- openair1/PHY/TOOLS/nr_phy_scope.c | 6 +- openair1/SCHED_NR/nr_prach_procedures.c | 2 +- openair1/SCHED_NR_UE/phy_frame_config_nr.h | 5 +- openair1/SIMULATION/NR_PHY/pbchsim.c | 2 +- openair1/SIMULATION/NR_PHY/prachsim.c | 7 +- openair1/SIMULATION/NR_PHY/ulsim.c | 6 +- openair2/GNB_APP/gnb_config.c | 2 - openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 3 +- openair2/RRC/NR/rrc_gNB.c | 1 + 18 files changed, 31 insertions(+), 96 deletions(-) diff --git a/executables/nr-ru.c b/executables/nr-ru.c index f947395f4a..3584a59e5d 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -2147,7 +2147,6 @@ void init_NR_RU(char *rf_config_file) PHY_VARS_gNB *gNB0= (PHY_VARS_gNB *)NULL; NR_DL_FRAME_PARMS *fp = (NR_DL_FRAME_PARMS *)NULL; int i; - int CC_id; // create status mask RC.ru_mask = 0; pthread_mutex_init(&RC.ru_mutex,NULL); diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 6dd3807f3c..f473d0161b 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -708,7 +708,6 @@ int stop_L1L2(module_id_t gnb_id) { */ int restart_L1L2(module_id_t gnb_id) { RU_t *ru = RC.ru[gnb_id]; - int cc_id; MessageDef *msg_p = NULL; LOG_W(GNB_APP, "restarting nr-softmodem\n"); /* block threads */ diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index 856a7863f4..f120864184 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -64,7 +64,6 @@ void free_gNB_dlsch(NR_gNB_DLSCH_t **dlschptr,uint16_t N_RB) a_segments = a_segments/273; } - uint16_t dlsch_bytes = a_segments*1056; // allocated bytes per segment #ifdef DEBUG_DLSCH_FREE @@ -82,7 +81,7 @@ void free_gNB_dlsch(NR_gNB_DLSCH_t **dlschptr,uint16_t N_RB) #endif if (dlsch->harq_processes[i]->b) { - free16(dlsch->harq_processes[i]->b,dlsch_bytes); + free16(dlsch->harq_processes[i]->b,a_segments*1056); dlsch->harq_processes[i]->b = NULL; #ifdef DEBUG_DLSCH_FREE LOG_D(PHY,"Freeing dlsch process %d b (%p)\n",i,dlsch->harq_processes[i]->b); diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport.h b/openair1/PHY/NR_TRANSPORT/nr_transport.h index be73875058..fea782c30e 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport.h @@ -123,4 +123,11 @@ void rx_nr_prach_ru(RU_t *ru, int frame, int subframe); +void compute_nr_prach_seq(uint16_t rootSequenceIndex, + uint8_t prach_ConfigIndex, + uint8_t zeroCorrelationZoneConfig, + uint8_t highSpeedFlag, + lte_frame_type_t frame_type, + nr_frequency_range_e fr, + uint32_t X_u[64][839]); #endif /*__NR_TRANSPORT__H__*/ diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto_common.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto_common.h index dd37455e26..f41dd2f0a6 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto_common.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto_common.h @@ -29,8 +29,8 @@ * \note * \warning */ -#ifndef __NR_TRANSPORT_PROTO_UE__H__ -#define __NR_TRANSPORT_PROTO_UE__H__ +#ifndef __NR_TRANSPORT_PROTO_COMMON_H__ +#define __NR_TRANSPORT_PROTO_COMMON_H__ #include "PHY/defs_nr_UE.h" #include "SCHED_NR_UE/defs.h" //#include "PHY/LTE_TRANSPORT/transport_common_proto.h" @@ -43,29 +43,6 @@ * @{ */ -/** \fn free_ue_dlsch(NR_UE_DLSCH_t *dlsch) - \brief This function frees memory allocated for a particular DLSCH at UE - @param dlsch Pointer to DLSCH to be removed -*/ -void free_nr_ue_dlsch(NR_UE_DLSCH_t *dlsch); - -/** \fn new_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t abstraction_flag) - \brief This function allocates structures for a particular DLSCH at UE - @returns Pointer to DLSCH to be removed - @param Kmimo Kmimo factor from 36-212/36-213 - @param Mdlharq Maximum number of HARQ rounds (36-212/36-213) - @param Nsoft Soft-LLR buffer size from UE-Category - @params N_RB_DL total number of resource blocks (determine the operating BW) - @param abstraction_flag Flag to indicate abstracted interface -*/ -NR_UE_DLSCH_t *new_nr_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t max_turbo_iterations,uint8_t N_RB_DL, uint8_t abstraction_flag); - - -void free_nr_ue_ulsch(NR_UE_ULSCH_t *ulsch); - - -NR_UE_ULSCH_t *new_nr_ue_ulsch(unsigned char N_RB_UL, int number_of_harq_pids, uint8_t abstraction_flag); - void fill_UE_dlsch_MCH(PHY_VARS_NR_UE *ue,int mcs,int ndi,int rvidx,int eNB_id); int rx_pmch(PHY_VARS_NR_UE *phy_vars_ue, @@ -1055,21 +1032,6 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch, NR_DL_FRAME_PARMS* frame_parms, uint8_t harq_pid); -/*! \brief Perform PUSCH scrambling. TS 38.211 V15.4.0 subclause 6.3.1.1 - @param[in] in Pointer to input bits - @param[in] size of input bits - @param[in] Nid cell id - @param[in] n_RNTI CRNTI - @param[out] out the scrambled bits -*/ - -void nr_pusch_codeword_scrambling(uint8_t *in, - uint16_t size, - uint32_t Nid, - uint32_t n_RNTI, - uint32_t* out); - - uint32_t nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue, UE_nr_rxtx_proc_t *proc, int eNB_id, @@ -1128,17 +1090,6 @@ int32_t nr_rx_pdsch(PHY_VARS_NR_UE *phy_vars_ue, uint8_t i_mod, uint8_t harq_pid); -int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, - uint32_t frame, - uint8_t nr_tti_rx, - uint8_t eNB_id, - MIMO_mode_t mimo_mode, - uint32_t high_speed_flag, - uint8_t is_secondary_ue, - int nb_coreset_active, - uint16_t symbol_mon, - NR_SEARCHSPACE_TYPE_t searchSpaceType); - /*! \brief Extract PSS and SSS resource elements @param phy_vars_ue Pointer to UE variables @param[out] pss_ext contain the PSS signals after the extraction @@ -1471,18 +1422,6 @@ void init_transport_channels(uint8_t); void generate_RIV_tables(void); -/*! - \brief This function performs the initial cell search procedure - PSS detection, SSS detection and PBCH detection. At the - end, the basic frame parameters are known (Frame configuration - TDD/FDD and cyclic prefix length, - N_RB_DL, PHICH_CONFIG and Nid_cell) and the UE can begin decoding PDCCH and DLSCH SI to retrieve the rest. Once these - parameters are know, the routine calls some basic initialization routines (cell-specific reference signals, etc.) - @param phy_vars_ue Pointer to UE variables - @param mode current running mode -*/ -int nr_initial_sync(UE_nr_rxtx_proc_t *proc, - PHY_VARS_NR_UE *phy_vars_ue, runmode_t mode); - - /*! \brief Encoding of PUSCH/ACK/RI/ACK from 36-212. @param a Pointer to ulsch SDU @@ -1724,10 +1663,6 @@ uint8_t get_prach_prb_offset(NR_DL_FRAME_PARMS *frame_parms, uint8_t n_ra_prboffset, uint8_t tdd_mapindex, uint16_t Nf); -void nr_pdcch_unscrambling(uint16_t crnti, NR_DL_FRAME_PARMS *frame_parms, uint8_t nr_tti_rx, - int16_t *z, uint32_t length, uint16_t pdcch_DMRS_scrambling_id, int do_common); - - uint32_t lte_gold_generic(uint32_t *x1, uint32_t *x2, uint8_t reset); int nr_rx_pdsch(PHY_VARS_NR_UE *ue, diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c index 050c230212..6c6ff4fd05 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c @@ -70,13 +70,12 @@ void free_gNB_ulsch(NR_gNB_ULSCH_t **ulschptr,uint8_t N_RB_UL) a_segments = a_segments/273; } - uint16_t ulsch_bytes = a_segments*1056; // allocated bytes per segment for (i=0; iharq_processes[i]) { if (ulsch->harq_processes[i]->b) { - free16(ulsch->harq_processes[i]->b,ulsch_bytes); + free16(ulsch->harq_processes[i]->b,a_segments*1056); ulsch->harq_processes[i]->b = NULL; } for (r=0; rMdlharq; i++) { if (dlsch->harq_processes[i]) { if (dlsch->harq_processes[i]->b) { - free16(dlsch->harq_processes[i]->b,dlsch_bytes); + free16(dlsch->harq_processes[i]->b,a_segments*1056); dlsch->harq_processes[i]->b = NULL; } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c index adef4a7592..f81e809d18 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c @@ -40,6 +40,7 @@ #include "common/utils/LOG/vcd_signal_dumper.h" #include "T.h" +#include diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c index 00627ac3ae..a6fd5259ae 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c @@ -60,17 +60,16 @@ void free_nr_ue_ulsch(NR_UE_ULSCH_t **ulschptr,unsigned char N_RB_UL) a_segments = a_segments/273; } - uint16_t ulsch_bytes = a_segments*1056; // allocated bytes per segment for (i=0; iharq_processes[i]) { if (ulsch->harq_processes[i]->a) { - free16(ulsch->harq_processes[i]->a,ulsch_bytes); + free16(ulsch->harq_processes[i]->a,a_segments*1056); ulsch->harq_processes[i]->a = NULL; } if (ulsch->harq_processes[i]->b) { - free16(ulsch->harq_processes[i]->b,ulsch_bytes); + free16(ulsch->harq_processes[i]->b,a_segments*1056); ulsch->harq_processes[i]->b = NULL; } if (ulsch->harq_processes[i]->e) { diff --git a/openair1/PHY/TOOLS/nr_phy_scope.c b/openair1/PHY/TOOLS/nr_phy_scope.c index 4682a89029..67ec027a9d 100644 --- a/openair1/PHY/TOOLS/nr_phy_scope.c +++ b/openair1/PHY/TOOLS/nr_phy_scope.c @@ -157,9 +157,9 @@ void phy_scope_gNB(FD_phy_scope_gnb *form, { int i, arx; //int i,i2,arx,atx,ind,k; NR_DL_FRAME_PARMS *frame_parms = &phy_vars_gnb->frame_parms; - int nsymb_ce = 12*frame_parms->N_RB_UL*frame_parms->symbols_per_tti; + //int nsymb_ce = 12*frame_parms->N_RB_UL*frame_parms->symbols_per_tti; uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx; - uint8_t nb_antennas_tx = 1; // frame_parms->nb_antennas_tx; // in LTE Rel. 8 and 9 only a single transmit antenna is assumed at the UE + //uint8_t nb_antennas_tx = 1; // frame_parms->nb_antennas_tx; // in LTE Rel. 8 and 9 only a single transmit antenna is assumed at the UE int16_t **rxsig_t, **rxsig_f; // int16_t **chest_t=NULL; // int16_t **chest_f=NULL; @@ -966,7 +966,7 @@ FD_stats_form * create_form_stats_form( void ) { } void startScope(scopeParms_t * p) { - FD_stats_form *form_stats=NULL,*form_stats_l2=NULL; + //FD_stats_form *form_stats=NULL,*form_stats_l2=NULL; char title[255]; fl_initialize (p->argc, p->argv, NULL, 0, 0); /* diff --git a/openair1/SCHED_NR/nr_prach_procedures.c b/openair1/SCHED_NR/nr_prach_procedures.c index 1ed8f28b49..9054ddbae5 100644 --- a/openair1/SCHED_NR/nr_prach_procedures.c +++ b/openair1/SCHED_NR/nr_prach_procedures.c @@ -55,7 +55,7 @@ extern int oai_nfapi_nr_rach_ind(nfapi_rach_indication_t *rach_ind); void L1_nr_prach_procedures(PHY_VARS_gNB *gNB,int frame,int slot, nfapi_nr_prach_pdu_t *prach_pdu) { - uint16_t max_preamble[4],max_preamble_energy[4],max_preamble_delay[4]; + uint16_t max_preamble[4]={0},max_preamble_energy[4]={0},max_preamble_delay[4]={0}; uint16_t i; diff --git a/openair1/SCHED_NR_UE/phy_frame_config_nr.h b/openair1/SCHED_NR_UE/phy_frame_config_nr.h index a939584584..81b6d373df 100644 --- a/openair1/SCHED_NR_UE/phy_frame_config_nr.h +++ b/openair1/SCHED_NR_UE/phy_frame_config_nr.h @@ -29,8 +29,8 @@ * ************************************************************************/ -#ifndef PHY_FRAME_CONFIG_NR_H -#define PHY_FRAME_CONFIG_NR_H +#ifndef PHY_FRAME_CONFIG_NR_UE_H +#define PHY_FRAME_CONFIG_NR_UE_H /************** DEFINE ********************************************/ @@ -78,5 +78,6 @@ void free_tdd_configuration_nr(NR_DL_FRAME_PARMS *frame_parms); void free_tdd_configuration_dedicated_nr(NR_DL_FRAME_PARMS *frame_parms); +void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag,runmode_t mod); #endif /* PHY_FRAME_CONFIG_NR_H */ diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index 99ca466fee..9d14391f71 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -410,7 +410,7 @@ int main(int argc, char **argv) uint8_t n_hf = 0; int cyclic_prefix_type = NFAPI_CP_NORMAL; - double fs, eps; + double fs=0, eps; double scs = 30000; double bw = 100e6; diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index 5c00352515..e6106ce462 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -108,7 +108,7 @@ int main(int argc, char **argv) uint8_t hs_flag=0; int n_frames=1; channel_desc_t *UE2gNB; - uint32_t nsymb,tx_lev; //,tx_lev_dB; + uint32_t tx_lev=0; //,tx_lev_dB; // int8_t interf1=-19,interf2=-19; NR_DL_FRAME_PARMS *frame_parms; @@ -120,7 +120,6 @@ int main(int argc, char **argv) uint32_t prach_errors=0; uint8_t subframe=9; uint16_t preamble_energy_list[64],preamble_tx=50,preamble_delay_list[64]; - uint16_t preamble_max,preamble_energy_max; PRACH_RESOURCES_t prach_resources; //uint8_t prach_fmt; //int N_ZC; @@ -397,7 +396,7 @@ int main(int argc, char **argv) frame_parms->frame_type = TDD; frame_parms->freq_range = nr_FR1; - nsymb = (frame_parms->Ncp == 0) ? 14 : 12; + //nsymb = (frame_parms->Ncp == 0) ? 14 : 12; printf("FFT Size %d, Extended Prefix %d, Samples per subframe %d,Frame type %s, Frequency Range %s\n",NUMBER_OF_OFDM_CARRIERS, frame_parms->Ncp,frame_parms->samples_per_subframe,frame_parms->frame_type == FDD ? "FDD" : "TDD", frame_parms->freq_range == nr_FR1 ? "FR1" : "FR2"); @@ -434,7 +433,7 @@ int main(int argc, char **argv) bw = N_RB_UL*(180e3)*(1<frame_parms.numerology_index); - AssertFatal(bw<=122.88e6,"Illegal channel bandwidth %f (mu %d,N_RB_UL %d)\n",gNB->frame_parms.numerology_index,N_RB_UL); + AssertFatal(bw<=122.88e6,"Illegal channel bandwidth %f (mu %d,N_RB_UL %d)\n",bw, gNB->frame_parms.numerology_index,N_RB_UL); if (bw <= 30.72e6) fs = 30.72e6; else if (bw <= 61.44e6) fs = 61.44e6; else if (bw <= 122.88e6) fs = 122.88e6; diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 7c1b441b6a..47e7c215e2 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -105,7 +105,7 @@ openair0_config_t openair0_cfg[MAX_CARDS]; int main(int argc, char **argv) { char c; - int i,sf; + int i; double SNR, snr0 = -2.0, snr1 = 2.0; double sigma, sigma_dB; double snr_step = 1; @@ -393,7 +393,7 @@ int main(int argc, char **argv) for (i = 0; i < RC.nb_nr_macrlc_inst; i++) RC.nb_nr_mac_CC[i] = 1; mac_top_init_gNB(); - gNB_MAC_INST* gNB_mac = RC.nrmac[0]; + //gNB_MAC_INST* gNB_mac = RC.nrmac[0]; gNB_RRC_INST rrc; memset((void*)&rrc,0,sizeof(rrc)); @@ -449,7 +449,7 @@ int main(int argc, char **argv) init_nr_ue_transport(UE, 0); /* - for (sf = 0; sf < 2; sf++) { + for (int sf = 0; sf < 2; sf++) { for (i = 0; i < 2; i++) { UE->ulsch[sf][0][i] = new_nr_ue_ulsch(N_RB_UL, 8, 0); diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 9355517072..e7fd2f3cf8 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -978,8 +978,6 @@ void NRRCConfig(void) { paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0}; paramdef_t GNBSParams[] = GNBSPARAMS_DESC; - char aprefix[MAX_OPTNAME_SIZE*2 + 8]; - /* get global parameters, defined outside any section in the config file */ LOG_I(GNB_APP, "Getting GNBSParams\n"); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 860b73276c..a584305adc 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -468,7 +468,6 @@ int8_t nr_ue_decode_mib(module_id_t module_id, uint32_t number_of_search_space_per_slot=UINT_MAX; uint32_t first_symbol_index=UINT_MAX; uint32_t search_space_duration; // element of search space - uint32_t coreset_duration; // element of coreset // 38.213 table 10.1-1 /// MUX PATTERN 1 @@ -604,8 +603,8 @@ int8_t nr_ue_decode_mib(module_id_t module_id, } AssertFatal(number_of_search_space_per_slot!=UINT_MAX,""); - coreset_duration = num_symbols * number_of_search_space_per_slot; /* + uint32_t coreset_duration = num_symbols * number_of_search_space_per_slot; mac->type0_pdcch_dci_config.number_of_candidates[0] = table_38213_10_1_1_c2[0]; mac->type0_pdcch_dci_config.number_of_candidates[1] = table_38213_10_1_1_c2[1]; mac->type0_pdcch_dci_config.number_of_candidates[2] = table_38213_10_1_1_c2[2]; // CCE aggregation level = 4 diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index fba6610554..6675f07427 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -81,6 +81,7 @@ #include "SIMULATION/TOOLS/sim.h" // for taus #include "executables/softmodem-common.h" +#include //#define XER_PRINT From 76551239972ccb44de9aed53ef3f563d5464aee3 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Mon, 4 May 2020 09:29:36 +0200 Subject: [PATCH 211/240] included throughput print --- openair1/SIMULATION/NR_PHY/dlsim.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 00552fc953..c7ac2ec0cf 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -140,8 +140,10 @@ int main(int argc, char **argv) double sigma2, sigma2_dB=10, SNR, snr0=-2.0, snr1=2.0; uint8_t snr1set=0; float roundStats[50]; + float effRate; float psnr; uint8_t snrRun; + uint32_t TBS; int **txdata; double **s_re,**s_im,**r_re,**r_im; //double iqim = 0.0; @@ -703,6 +705,7 @@ int main(int argc, char **argv) reset_meas(&gNB->toutput); n_errors = 0; + effRate = 0; //n_errors2 = 0; //n_alamouti = 0; errors_scrambling=0; @@ -848,7 +851,7 @@ int main(int argc, char **argv) NR_UE_PDSCH **pdsch_vars = UE->pdsch_vars[UE->current_thread_id[UE_proc.nr_tti_rx]]; int16_t *UE_llr = pdsch_vars[0]->llr[0]; - uint32_t TBS = rel15->TBSize[0]; + TBS = rel15->TBSize[0]; uint16_t length_dmrs = 1; uint16_t nb_rb = rel15->rbSize; uint8_t nb_re_dmrs = rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6 : 4; @@ -896,15 +899,17 @@ int main(int argc, char **argv) printf("errors_bit = %u (trial %d)\n", errors_bit, trial); } roundStats[snrRun]+=((float)round); + if (UE_harq_process->harq_ack.ack==1) effRate += ((float)TBS)/round; } // noise trials roundStats[snrRun]/=((float)n_trials); + effRate /= n_trials; printf("*****************************************\n"); printf("SNR %f, (false positive %f)\n", SNR, (float) n_errors / (float) n_trials); printf("*****************************************\n"); printf("\n"); - printf("SNR %f : n_errors (negative CRC) = %d/%d, Avg round %.2f, Channel BER %e\n", SNR, n_errors, n_trials,roundStats[snrRun],(double)errors_scrambling/available_bits/n_trials); + printf("SNR %f : n_errors (negative CRC) = %d/%d, Avg round %.2f, Channel BER %e, Eff Rate %.4f bits/slot, Eff Throughput %.2f\%, TBS %d bits/slot\n", SNR, n_errors, n_trials,roundStats[snrRun],(double)errors_scrambling/available_bits/n_trials,effRate,effRate/TBS*100,TBS); printf("\n"); if (n_trials == 1) { @@ -916,7 +921,8 @@ int main(int argc, char **argv) write_output("rxF_comp.m","rxFc",&UE->pdsch_vars[0][0]->rxdataF_comp0[0][0],N_RB_DL*12*14,1,1); } - if ((float)n_errors/(float)n_trials <= target_error_rate) { + //if ((float)n_errors/(float)n_trials <= target_error_rate) { + if (effRate >= (0.7*TBS)) { printf("PDSCH test OK\n"); break; } @@ -975,14 +981,14 @@ int main(int argc, char **argv) snrRun++; } // NSR - if (n_trials>1) { + /*if (n_trials>1) { printf("HARQ stats:\nSNR\tRounds\n"); psnr = snr0; for (uint8_t i=0; i Date: Mon, 4 May 2020 15:42:15 +0200 Subject: [PATCH 212/240] updated CI test list with harq test --- cmake_targets/autotests/test_case_list.xml | 12 +++++++++--- openair1/SIMULATION/NR_PHY/dlsim.c | 9 ++++++++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 7908772bb6..245039fe0f 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1087,8 +1087,11 @@ (Test6: 217 PRB 100 PDSCH-PRBs), (Test7: 217 PRB 80 PDSCH-Offset), (Test8: 217 PRB 100 PDSCH-PRBs 110 PDSCH-Offset), - (Test9: 106 PRBs 50 PDSCH-PRBs MCS Index 27) - (Test10: 106 PRBs 50 PDSCH-PRBs MCS Index 16) + (Test9: 106 PRBs 50 PDSCH-PRBs MCS Index 27), + (Test10: 106 PRBs 50 PDSCH-PRBs MCS Index 16), + (Test11: HARQ test 25% TP (4 rounds), + (Test12: HARQ test 33% TP (3 rounds), + (Test13: HARQ test 50% TP (2 rounds) $OPENAIR_DIR/cmake_targets/build_oai --phy_simulators -c @@ -1105,8 +1108,11 @@ -n100 -R217 -a110 -s5 -b100 -n100 -e27 -s30 -n100 -e16 -s10 + -n100 -s1 -t25 + -n100 -s1 -t33 + -n100 -s1 -t50 - nr_dlsim.test1 nr_dlsim.test2 nr_dlsim.test3 nr_dlsim.test4 nr_dlsim.test5 nr_dlsim.test6 nr_dlsim.test7 nr_dlsim.test8 nr_dlsim.test9 nr_dlsim.test10 + nr_dlsim.test1 nr_dlsim.test2 nr_dlsim.test3 nr_dlsim.test4 nr_dlsim.test5 nr_dlsim.test6 nr_dlsim.test7 nr_dlsim.test8 nr_dlsim.test9 nr_dlsim.test10 nr_dlsim.test11 nr_dlsim.test12 nr_dlsim.test13 PDSCH test OK segmentation fault|assertion|exiting|fatal 3 diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index c7ac2ec0cf..a102da5744 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -142,6 +142,7 @@ int main(int argc, char **argv) float roundStats[50]; float effRate; float psnr; + float eff_tp_check = 0.7; uint8_t snrRun; uint32_t TBS; int **txdata; @@ -391,6 +392,10 @@ int main(int argc, char **argv) mu = atoi(optarg); break; + case 't': + eff_tp_check = (float)atoi(optarg)/100; + break; + default: case 'h': printf("%s -h(elp) -p(extended_prefix) -N cell_id -f output_filename -F input_filename -g channel_model -n n_frames -t Delayspread -s snr0 -S snr1 -x transmission_mode -y TXant -z RXant -i Intefrence0 -j Interference1 -A interpolation_file -C(alibration offset dB) -N CellId\n", @@ -420,6 +425,7 @@ int main(int argc, char **argv) printf("-c Start symbol for PDSCH (fixed for now)\n"); printf("-j Number of symbols for PDSCH (fixed for now)\n"); printf("-e MSC index\n"); + printf("-t Acceptable effective throughput (in percentage)\n"); exit (-1); break; } @@ -919,10 +925,11 @@ int main(int argc, char **argv) LOG_M("rxsig1.m","rxs1", UE->common_vars.rxdata[1], frame_length_complex_samples, 1, 1); LOG_M("chestF0.m","chF0",UE->pdsch_vars[0][0]->dl_ch_estimates_ext,N_RB_DL*12*14,1,1); write_output("rxF_comp.m","rxFc",&UE->pdsch_vars[0][0]->rxdataF_comp0[0][0],N_RB_DL*12*14,1,1); + break; } //if ((float)n_errors/(float)n_trials <= target_error_rate) { - if (effRate >= (0.7*TBS)) { + if (effRate >= (eff_tp_check*TBS)) { printf("PDSCH test OK\n"); break; } From 29f984a60abb649e56dfe541555ea6ee34272a86 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Mon, 4 May 2020 16:16:27 +0200 Subject: [PATCH 213/240] CI: fix missing class member for EPC Signed-off-by: Raphael Defosseux --- ci-scripts/epc.py | 3 +++ ci-scripts/main.py | 1 + 2 files changed, 4 insertions(+) diff --git a/ci-scripts/epc.py b/ci-scripts/epc.py index 4926f2d6e8..3a52a6118c 100644 --- a/ci-scripts/epc.py +++ b/ci-scripts/epc.py @@ -62,6 +62,7 @@ class EPCManagement(): self.Type = '' self.PcapFileName = '' self.htmlObj = None + self.testCase_id = '' #----------------------------------------------------------- # Setter and Getters on Public Members @@ -89,6 +90,8 @@ class EPCManagement(): return self.Type def SetHtmlObj(self, obj): self.htmlObj = obj + def SetTestCase_id(self, idx): + self.testCase_id = idx #----------------------------------------------------------- # EPC management functions diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 1e149c4050..36d6a16d17 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -3583,6 +3583,7 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re continue CiTestObj.testCase_id = id HTML.SettestCase_id(CiTestObj.testCase_id) + EPC.SetTestCase_id(CiTestObj.testCase_id) CiTestObj.desc = test.findtext('desc') HTML.Setdesc(CiTestObj.desc) action = test.findtext('class') From ae5a1e4131d7d520dd154683fa9b6deebb89fa3a Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Mon, 4 May 2020 16:19:04 +0200 Subject: [PATCH 214/240] CI: fix unresolved merge conflicts Signed-off-by: Raphael Defosseux --- .../inria/enb_usrp210_band7_x2_ho_test_05Mhz_tm1.xml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ci-scripts/xml_files/inria/enb_usrp210_band7_x2_ho_test_05Mhz_tm1.xml b/ci-scripts/xml_files/inria/enb_usrp210_band7_x2_ho_test_05Mhz_tm1.xml index 8116b9dcdf..22f8b63266 100644 --- a/ci-scripts/xml_files/inria/enb_usrp210_band7_x2_ho_test_05Mhz_tm1.xml +++ b/ci-scripts/xml_files/inria/enb_usrp210_band7_x2_ho_test_05Mhz_tm1.xml @@ -72,11 +72,7 @@ Initialize_eNB Initialize eNB #1 (FDD/Band7/5MHz) -<<<<<<< HEAD - -O ci-scripts/conf_files/enb.band7.tm1.25PRB.usrpb210.conf --eNBs.[0].rrc_inactivity_threshold 0 --RUs.[0].max_rxgain 120 --eNBs.[0].component_carriers.[0].pusch_p0_Nominal -90 --eNBs.[0].component_carriers.[0].pucch_p0_Nominal -96 --eNBs.[0].tracking_area_code 600 --eNBs.[0].plmn_list.[0].mnc 95 --THREAD_STRUCT.[0].parallel_config PARALLEL_RU_L1_TRX_SPLIT --eNBs.[0].enable_measurement_reports yes --eNBs.[0].enable_x2 yes --eNBs.[0].target_enb_x2_ip_address.[0].ipv4 CI_RCC_IP_ADDR --eNBs.[0].target_enb_x2_ip_address.[0].preference ipv4 --eNBs.[0].eNB_ID 0xe01 --eNBs.[0].component_carriers.[0].Nid_cell 1 --eNBs.[0].nr_cellid 98765 -======= -O ci-scripts/conf_files/enb.band7.tm1.25PRB.slave.usrpb210.conf --eNBs.[0].rrc_inactivity_threshold 0 --RUs.[0].max_rxgain 120 --eNBs.[0].component_carriers.[0].pusch_p0_Nominal -90 --eNBs.[0].component_carriers.[0].pucch_p0_Nominal -96 --eNBs.[0].tracking_area_code 600 --eNBs.[0].plmn_list.[0].mnc 95 --THREAD_STRUCT.[0].parallel_config PARALLEL_RU_L1_TRX_SPLIT --eNBs.[0].enable_measurement_reports yes --eNBs.[0].enable_x2 yes --eNBs.[0].nr_cellid 98765 ->>>>>>> origin/develop_inria_ci_deployment 1 1 From 87ecb918859044e207941d5b52d88d98584f73e6 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Wed, 6 May 2020 13:45:14 +0200 Subject: [PATCH 215/240] updated cmakelist --- cmake_targets/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 465d2dcada..521eb28407 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -2765,6 +2765,7 @@ target_link_libraries(ldpctest add_executable(nr_dlschsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/dlschsim.c ${OPENAIR_DIR}/common/utils/system.c + ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${UTIL_SRC} ${T_SOURCE} ${SHLIB_LOADER_SOURCES} @@ -2777,6 +2778,7 @@ target_link_libraries(nr_dlschsim add_executable(nr_pbchsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/pbchsim.c ${OPENAIR_DIR}/common/utils/system.c + ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${UTIL_SRC} ${T_SOURCE} ${SHLIB_LOADER_SOURCES} @@ -2830,6 +2832,7 @@ target_link_libraries(nr_prachsim add_executable(nr_ulschsim ${OPENAIR1_DIR}/SIMULATION/NR_PHY/ulschsim.c ${OPENAIR_DIR}/common/utils/system.c + ${OPENAIR_DIR}/common/utils/nr/nr_common.c ${UTIL_SRC} ${T_SOURCE} ${SHLIB_LOADER_SOURCES} From 454139ac63f799963d66bded4d56c32a961f7e26 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Thu, 7 May 2020 16:34:53 +0200 Subject: [PATCH 216/240] CI: fix a few typos in python framework Signed-off-by: Raphael Defosseux --- ci-scripts/html.py | 7 +++++-- ci-scripts/main.py | 1 - 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/ci-scripts/html.py b/ci-scripts/html.py index 3d0c8f3897..1a6e3f8fdb 100644 --- a/ci-scripts/html.py +++ b/ci-scripts/html.py @@ -83,7 +83,7 @@ class HTMLManagement(): # Setters and Getters #----------------------------------------------------------- def SethtmlUEFailureMsg(self,huefa): - self.htmlUEFailureMsg = huefa + self.htmlUEFailureMsg = huefa def GethtmlUEFailureMsg(self): return self.htmlUEFailureMsg def SetHmleNBFailureMsg(self, msg): @@ -112,7 +112,10 @@ class HTMLManagement(): self.ranTargetBranch = tbranch def SethtmlUEConnected(self, nbUEs): - self.htmlUEConnected = nbUEs + if nbUEs > 0: + self.htmlUEConnected = nbUEs + else: + self.htmlUEConnected = 1 def SethtmlNb_Smartphones(self, nbUEs): self.htmlNb_Smartphones = nbUEs def SethtmlNb_CATM_Modules(self, nbUEs): diff --git a/ci-scripts/main.py b/ci-scripts/main.py index 36d6a16d17..a01eed2ac5 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -86,7 +86,6 @@ class OaiCiTest(): self.UEDevicesRebootCmd = [] self.CatMDevices = [] self.UEIPAddresses = [] - self.htmlUEConnected = -1 self.idle_sleep_time = 0 self.x2_ho_options = 'network' self.x2NbENBs = 0 From 2a8dacc009865689275e7dcc83138926bd1588f9 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Thu, 7 May 2020 16:35:28 +0200 Subject: [PATCH 217/240] CI: better code guideline analysis -- check if C file has a GNU GPL license -- check if C file has s suspect license -- check if C header is having correct circular dependency protection (with Laurent Thomas's help) Signed-off-by: Raphael Defosseux --- ci-scripts/checkCodingFormattingRules.sh | 65 ++++++++++++++++++++++ ci-scripts/reportBuildLocally.sh | 71 ++++++++++++++++++++++++ 2 files changed, 136 insertions(+) diff --git a/ci-scripts/checkCodingFormattingRules.sh b/ci-scripts/checkCodingFormattingRules.sh index 6ac43ca19f..fb159d4da0 100755 --- a/ci-scripts/checkCodingFormattingRules.sh +++ b/ci-scripts/checkCodingFormattingRules.sh @@ -62,6 +62,30 @@ then NB_FILES_TO_FORMAT=`astyle --dry-run --options=ci-scripts/astyle-options.txt --recursive *.c *.h | grep -c Formatted ` echo "Nb Files that do NOT follow OAI rules: $NB_FILES_TO_FORMAT" echo $NB_FILES_TO_FORMAT > ./oai_rules_result.txt + + # Testing Circular Dependencies protection + awk '/#[ \t]*ifndef/ { gsub("^.*ifndef *",""); if (names[$1]!="") print "files with same {define ", FILENAME, names[$1]; names[$1]=FILENAME } /#[ \t]*define/ { gsub("^.*define *",""); if(names[$1]!=FILENAME) print "error in declaration", FILENAME, $1, names[$1]; nextfile }' `find openair* common targets executables -name *.h |grep -v LFDS` > header-files-w-incorrect-define.txt + + # Testing if explicit GNU GPL license banner + egrep -irl --exclude-dir=.git --include=*.cpp --include=*.c --include=*.h "General Public License" . > files-w-gnu-gpl-license-banner.txt + + # Looking at exotic/suspect banner + LIST_OF_FILES_W_BANNER=`egrep -irl --exclude-dir=.git --include=*.cpp --include=*.c --include=*.h "Copyright|copyleft" .` + if [ -f ./files-w-suspect-banner.txt ]; then rm -f ./files-w-suspect-banner.txt; fi + for FILE in $LIST_OF_FILES_W_BANNER + do + IS_NFAPI=`echo $FILE | egrep -c "nfapi/open-nFAPI|nfapi/oai_integration/vendor_ext"` + IS_OAI_LICENCE_PRESENT=`egrep -c "OAI Public License" $FILE` + IS_BSD_LICENCE_PRESENT=`egrep -c "the terms of the BSD Licence" $FILE` + IS_EXCEPTION=`echo $FILE | egrep -c "common/utils/collection/tree.h|common/utils/collection/queue.h|common/utils/itti_analyzer/common/queue.h|openair3/UTILS/tree.h|openair3/UTILS/queue.h"` + if [ $IS_OAI_LICENCE_PRESENT -eq 0 ] && [ $IS_BSD_LICENCE_PRESENT -eq 0 ] + then + if [ $IS_NFAPI -eq 0 ] && [ $IS_EXCEPTION -eq 0 ] + then + echo $FILE >> ./files-w-suspect-banner.txt + fi + fi + done exit 0 fi @@ -131,8 +155,25 @@ if [ -f oai_rules_result_list.txt ] then rm -f oai_rules_result_list.txt fi +if [ -f header-files-w-incorrect-define.txt ] +then + rm -f header-files-w-incorrect-define.txt +fi +if [ -f files-w-gnu-gpl-license-banner.txt ] +then + rm -f files-w-gnu-gpl-license-banner.txt +fi +if [ -f files-w-suspect-banner.txt ] +then + rm -f files-w-suspect-banner.txt +fi +awk '/#[ \t]*ifndef/ { gsub("^.*ifndef *",""); if (names[$1]!="") print "files with same {define ", FILENAME, names[$1]; names[$1]=FILENAME } /#[ \t]*define/ { gsub("^.*define *",""); if(names[$1]!=FILENAME) print "error in declaration", FILENAME, $1, names[$1]; nextfile }' `find openair* common targets executables -name *.h |grep -v LFDS` > header-files-w-incorrect-define-tmp.txt + for FULLFILE in $MODIFIED_FILES do + # sometimes, we remove files + if [ ! -f $FULLFILE ]; then continue; fi + filename=$(basename -- "$FULLFILE") EXT="${filename##*.}" if [ $EXT = "c" ] || [ $EXT = "h" ] || [ $EXT = "cpp" ] || [ $EXT = "hpp" ] @@ -144,8 +185,32 @@ do echo $FULLFILE echo $FULLFILE >> ./oai_rules_result_list.txt fi + # Testing if explicit GNU GPL license banner + egrep -i "General Public License" $FULLFILE >> files-w-gnu-gpl-license-banner.txt + # Looking at exotic/suspect banner + IS_BANNER=`egrep -i -c "Copyright|copyleft" $FULLFILE` + if [ $IS_BANNER -ne 0 ] + then + IS_NFAPI=`echo $FULLFILE | egrep -c "nfapi/open-nFAPI|nfapi/oai_integration/vendor_ext"` + IS_OAI_LICENCE_PRESENT=`egrep -c "OAI Public License" $FULLFILE` + IS_BSD_LICENCE_PRESENT=`egrep -c "the terms of the BSD Licence" $FULLFILE` + IS_EXCEPTION=`echo $FILE | egrep -c "common/utils/collection/tree.h|common/utils/collection/queue.h|common/utils/itti_analyzer/common/queue.h|openair3/UTILS/tree.h|openair3/UTILS/queue.h"` + if [ $IS_OAI_LICENCE_PRESENT -eq 0 ] && [ $IS_BSD_LICENCE_PRESENT -eq 0 ] + then + if [ $IS_NFAPI -eq 0 ] && [ $IS_EXCEPTION -eq 0 ] + then + echo $FILE >> ./files-w-suspect-banner.txt + fi + fi + fi + fi + # Testing Circular Dependencies protection + if [ $EXT = "h" ] || [ $EXT = "hpp" ] + then + grep $FULLFILE header-files-w-incorrect-define-tmp.txt >> header-files-w-incorrect-define.txt fi done +rm -f header-files-w-incorrect-define-tmp.txt echo "" echo " ----------------------------------------------------------" echo "Nb Files that do NOT follow OAI rules: $NB_TO_FORMAT" diff --git a/ci-scripts/reportBuildLocally.sh b/ci-scripts/reportBuildLocally.sh index 54372ac6ba..0a75ff25b7 100755 --- a/ci-scripts/reportBuildLocally.sh +++ b/ci-scripts/reportBuildLocally.sh @@ -492,6 +492,77 @@ function report_build { awk '{print " "$1""}' ./oai_rules_result_list.txt >> ./build_results.html echo " " >> ./build_results.html echo "

" >> ./build_results.html + echo "
" >> ./build_results.html + fi + if [ -f ./header-files-w-incorrect-define.txt ] + then + NB_FILES_IN_ERROR=`wc -l ./header-files-w-incorrect-define.txt | sed -e "s@ .*@@"` + if [ $NB_FILES_IN_ERROR -eq 0 ] + then + echo "
" >> ./build_results.html + if [ $MR_TRIG -eq 1 ]; then echo " No Issue for CIRCULAR DEPENDENCY PROTECTION in modified files" >> ./build_results.html; fi + if [ $PU_TRIG -eq 1 ]; then echo " No Issue for CIRCULAR DEPENDENCY PROTECTION in the whole repository" >> ./build_results.html; fi + echo "
" >> ./build_results.html + else + echo "
" >> ./build_results.html + if [ $MR_TRIG -eq 1 ]; then echo " ${NB_FILES_IN_ERROR} modified files MAY NOT HAVE CIRCULAR DEPENDENCY PROTECTION" >> ./build_results.html; fi + if [ $PU_TRIG -eq 1 ]; then echo " ${NB_FILES_IN_ERROR} files in repository MAY NOT HAVE CIRCULAR DEPENDENCY PROTECTION in the whole repository" >> ./build_results.html; fi + echo "
" >> ./build_results.html + echo " " >> ./build_results.html + echo "
" >> ./build_results.html + echo " " >> ./build_results.html + echo " " >> ./build_results.html + echo " " >> ./build_results.html + echo " " >> ./build_results.html + echo " " >> ./build_results.html + echo " " >> ./build_results.html + awk '{if($0 ~/error in/){print " "};if($0 ~/files with same/){print " "}}' ./header-files-w-incorrect-define.txt >> ./build_results.html + echo "
Potential IssueImpacted FileIncorrect Macro
error in declaration"$4""$5"
files with same #define"$5""$6"
" >> ./build_results.html + echo "
" >> ./build_results.html + echo "
" >> ./build_results.html + fi + fi + if [ -f ./files-w-gnu-gpl-license-banner.txt ] + then + NB_FILES_IN_ERROR=`wc -l ./files-w-gnu-gpl-license-banner.txt | sed -e "s@ .*@@"` + if [ $NB_FILES_IN_ERROR -ne 0 ] + then + echo "
" >> ./build_results.html + if [ $MR_TRIG -eq 1 ]; then echo " ${NB_FILES_IN_ERROR} modified files HAVE a GNU GPL license banner" >> ./build_results.html; fi + if [ $PU_TRIG -eq 1 ]; then echo " ${NB_FILES_IN_ERROR} files in repository HAVE a GNU GPL license banner" >> ./build_results.html; fi + echo "
" >> ./build_results.html + echo " " >> ./build_results.html + echo "
" >> ./build_results.html + echo " " >> ./build_results.html + echo " " >> ./build_results.html + echo " " >> ./build_results.html + echo " " >> ./build_results.html + awk '{print " "}' ./files-w-gnu-gpl-license-banner.txt >> ./build_results.html + echo "
Filename
"$1"
" >> ./build_results.html + echo "
" >> ./build_results.html + echo "
" >> ./build_results.html + fi + fi + if [ -f ./files-w-suspect-banner.txt ] + then + NB_FILES_IN_ERROR=`wc -l ./files-w-suspect-banner.txt | sed -e "s@ .*@@"` + if [ $NB_FILES_IN_ERROR -ne 0 ] + then + echo "
" >> ./build_results.html + if [ $MR_TRIG -eq 1 ]; then echo " ${NB_FILES_IN_ERROR} modified files HAVE a suspect license banner" >> ./build_results.html; fi + if [ $PU_TRIG -eq 1 ]; then echo " ${NB_FILES_IN_ERROR} files in repository HAVE a suspect license banner" >> ./build_results.html; fi + echo "
" >> ./build_results.html + echo " " >> ./build_results.html + echo "
" >> ./build_results.html + echo " " >> ./build_results.html + echo " " >> ./build_results.html + echo " " >> ./build_results.html + echo " " >> ./build_results.html + awk '{print " "}' ././files-w-suspect-banner.txt >> ./build_results.html + echo "
Filename
"$1"
" >> ./build_results.html + echo "
" >> ./build_results.html + echo "
" >> ./build_results.html + fi fi fi From bca9ecfd3cb028b92d6f0d191385394ba8d2e4a6 Mon Sep 17 00:00:00 2001 From: Raphael Defosseux Date: Thu, 7 May 2020 16:38:00 +0200 Subject: [PATCH 218/240] add missing circular dependency protection Signed-off-by: Raphael Defosseux --- openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h index 510abb8373..a2446dccf9 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h +++ b/openair1/PHY/NR_UE_TRANSPORT/pucch_nr.h @@ -29,6 +29,9 @@ * \note * \warning */ +#ifndef __PUCCH_NR__H__ +#define __PUCCH_NR__H__ + //#include "PHY/defs.h" #include "PHY/impl_defs_nr.h" #include "PHY/defs_nr_common.h" @@ -417,3 +420,4 @@ void nr_generate_pucch3_4(PHY_VARS_NR_UE *ue, 73, 79, 83, 89, 97, 101,103,107,109,113, 127,131,137,139,149,151,157,163,167,173, 179,181,191,193,197,199}; +#endif From 21a2a8c6e139659dd859f1e7dc93c2a956d241f9 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Thu, 7 May 2020 18:00:21 +0200 Subject: [PATCH 219/240] rlc v2: some fixes for 'bugs' found by coverity scan Minor fixes, doesn't change anything. Not sure these are 'bugs' either, but let's be polite with coverity scan... One thing was not changed. Coverity scan says: *** CID 357991: Memory - illegal accesses (USE_AFTER_FREE) /home/carabe/raphael/openairinterface5g/openair2/LAYER2/rlc_v2/rlc_entity_am.c: 507 in tx_list_remove_sn() 501 } else { 502 prev = cur; 503 cur = cur->next; 504 } 505 } 506 >>> CID 357991: Memory - illegal accesses (USE_AFTER_FREE) >>> Using freed pointer "head.next". 507 return head.next; 508 } 509 510 void cleanup_sdu_list(rlc_entity_am_t *entity) 511 { 512 rlc_sdu_t head; But as far as I understand, there is no problem. We don't access head.next at all if it has been freed. Or is there some aliasing going on there (pointer aliasing)? I doubt it. False positive? --- openair2/LAYER2/rlc_v2/rlc_entity_um.c | 1 + openair2/LAYER2/rlc_v2/rlc_oai_api.c | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/rlc_v2/rlc_entity_um.c b/openair2/LAYER2/rlc_v2/rlc_entity_um.c index f0fe33789b..54707875a0 100644 --- a/openair2/LAYER2/rlc_v2/rlc_entity_um.c +++ b/openair2/LAYER2/rlc_v2/rlc_entity_um.c @@ -360,6 +360,7 @@ static tx_pdu_size_t tx_pdu_size(rlc_entity_um_t *entity, int maxsize) ret.data_size = 0; ret.header_size = 0; ret.last_sdu_is_full = 1; + ret.first_sdu_length = 0; /* TX PDU - let's make the biggest PDU we can with the SDUs we have */ sdu_count = 0; diff --git a/openair2/LAYER2/rlc_v2/rlc_oai_api.c b/openair2/LAYER2/rlc_v2/rlc_oai_api.c index c81cc6ff5e..bd3eebe635 100644 --- a/openair2/LAYER2/rlc_v2/rlc_oai_api.c +++ b/openair2/LAYER2/rlc_v2/rlc_oai_api.c @@ -134,7 +134,10 @@ tbs_size_t mac_rlc_data_req( } if (MBMS_flagP == MBMS_FLAG_YES) { - rb = ue->drb[channel_idP - 1]; + if (channel_idP >= 1 && channel_idP <= 5) + rb = ue->drb[channel_idP - 1]; + else + rb = NULL; } @@ -192,7 +195,10 @@ mac_rlc_status_resp_t mac_rlc_status_ind( } if (MBMS_flagP == MBMS_FLAG_YES) { - rb = ue->drb[channel_idP - 1]; + if (channel_idP >= 1 && channel_idP <= 5) + rb = ue->drb[channel_idP - 1]; + else + rb = NULL; } if (rb != NULL) { @@ -316,7 +322,9 @@ rlc_op_status_t rlc_data_req (const protocol_ctxt_t *const ctxt_pP, if (rb_idP >= 1 && rb_idP <= 5) rb = ue->drb[rb_idP - 1]; } + if( MBMS_flagP == MBMS_FLAG_YES) { + if (rb_idP >= 1 && rb_idP <= 5) rb = ue->drb[rb_idP - 1]; } @@ -875,12 +883,19 @@ rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt_pP mbms_service_id = MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[2]; //serviceId is 3-octet string // mbms_service_id = j; +#if 0 + /* TODO: check if this code should stay there + * as it is both enb and ue cases do the same thing + */ // can set the mch_id = i if (ctxt_pP->enb_flag) { drb_id = (mbms_service_id * LTE_maxSessionPerPMCH ) + mbms_session_id;//+ (LTE_maxDRB + 3) * MAX_MOBILES_PER_ENB; // 1 } else { drb_id = (mbms_service_id * LTE_maxSessionPerPMCH ) + mbms_session_id; // + (LTE_maxDRB + 3); // 15 } +#endif + + drb_id = (mbms_service_id * LTE_maxSessionPerPMCH ) + mbms_session_id; LOG_I(RLC, PROTOCOL_CTXT_FMT" CONFIG REQ MBMS ASN1 LC ID %u RB ID %u SESSION ID %u SERVICE ID %u, mbms_rnti %x\n", PROTOCOL_CTXT_ARGS(ctxt_pP), From 301ea42482f4abc523e1dc183e1c4f9233b8d76a Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Sat, 9 May 2020 10:12:38 +0200 Subject: [PATCH 220/240] hotfix: fix compilation of UE with --musim The following was failing: ./build_oai --UE --musim Not sure this fix is correct, but it seems consistent with the rest of platform_constants.h. --- openair2/COMMON/platform_constants.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openair2/COMMON/platform_constants.h b/openair2/COMMON/platform_constants.h index 7a7e984aca..1eb58b16b2 100644 --- a/openair2/COMMON/platform_constants.h +++ b/openair2/COMMON/platform_constants.h @@ -73,7 +73,9 @@ #ifdef UESIM_EXPANSION #define MAX_MOBILES_PER_ENB 256 #define MAX_MOBILES_PER_ENB_NB_IoT 256 + #define MAX_MOBILES_PER_GNB 256 #define MAX_eNB 2 + #define MAX_gNB 2 #else #ifdef LARGE_SCALE #define MAX_MOBILES_PER_ENB 128 From ad246f961bf40683e14088e6001a6af5cc6c9aaa Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Tue, 12 May 2020 14:14:41 +0200 Subject: [PATCH 221/240] reset rnti and harq_mask in dlsch structure --- openair1/SCHED_NR/fapi_nr_l1.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c index 1576ab9e64..dccb7fab27 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ b/openair1/SCHED_NR/fapi_nr_l1.c @@ -156,6 +156,10 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ int pdcch_received=0; gNB->num_pdsch_rnti=0; + for (int i=0; idlsch[i][0]->rnti=0; + gNB->dlsch[i][0]->harq_mask=0; + } gNB->pdcch_pdu = NULL; gNB->pbch_configured=0; From 6f0e4fe149469a90585972cd6524418077af8417 Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Wed, 13 May 2020 16:22:05 +0200 Subject: [PATCH 222/240] using numDmrsCdmGrpsNoData for PDSCH in PHY --- openair1/PHY/NR_TRANSPORT/nr_dlsch.c | 23 +++++++++++-------- openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c | 9 ++++---- openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.c | 21 +++++++++++++++++ openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.h | 7 +++++- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 14 +++++++---- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 2 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 7 +++--- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 2 +- 8 files changed, 60 insertions(+), 25 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index b8d9fdea18..8324508361 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -133,19 +133,22 @@ uint8_t nr_generate_pdsch(NR_gNB_DLSCH_t *dlsch, int16_t **mod_symbs = (int16_t**)dlsch->mod_symbs; int16_t **tx_layers = (int16_t**)dlsch->txdataF; int8_t Wf[2], Wt[2], l0, l_prime[2], delta; - uint8_t nodata_dmrs = 1; uint8_t dmrs_Type = rel15->dmrsConfigType; - int nb_re_dmrs = (dmrs_Type== NFAPI_NR_DMRS_TYPE1) ? 6:4; - uint16_t n_dmrs = ((rel15->rbSize+rel15->rbStart)*nb_re_dmrs)<<1; - int16_t mod_dmrs[n_dmrs<<1]; - + int nb_re_dmrs; + uint16_t n_dmrs; + if (rel15->dmrsConfigType==NFAPI_NR_DMRS_TYPE1) { + nb_re_dmrs = 6*rel15->numDmrsCdmGrpsNoData; + n_dmrs = ((rel15->rbSize+rel15->rbStart)*6)<<1; + } + else { + nb_re_dmrs = 4*rel15->numDmrsCdmGrpsNoData; + n_dmrs = ((rel15->rbSize+rel15->rbStart)*4)<<1; + } uint16_t nb_re; - if (nodata_dmrs) // no data in dmrs symbol - nb_re = ((12*rel15->NrOfSymbols)-12-xOverhead)*rel15->rbSize*rel15->NrOfCodewords; - else - nb_re = ((12*rel15->NrOfSymbols)-nb_re_dmrs-xOverhead)*rel15->rbSize*rel15->NrOfCodewords; + nb_re = ((12*rel15->NrOfSymbols)-nb_re_dmrs-xOverhead)*rel15->rbSize*rel15->NrOfCodewords; uint8_t Qm = rel15->qamModOrder[0]; uint32_t encoded_length = nb_re*Qm; + int16_t mod_dmrs[n_dmrs<<1]; /// CRC, coding, interleaving and rate matching AssertFatal(harq->pdu!=NULL,"harq->pdu is null\n"); @@ -301,7 +304,7 @@ uint8_t nr_generate_pdsch(NR_gNB_DLSCH_t *dlsch, } else { - if( (l != dmrs_symbol) || !nodata_dmrs) { + if( (l != dmrs_symbol) || allowed_pdsch_re_in_dmrs_symbol(k,start_sc,rel15->numDmrsCdmGrpsNoData,dmrs_Type)) { ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = (amp * tx_layers[ap][m<<1]) >> 15; ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = (amp * tx_layers[ap][(m<<1) + 1]) >> 15; #ifdef DEBUG_DLSCH_MAPPING diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index 065e62a2cb..5e10e1dd06 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -336,12 +336,13 @@ int nr_dlsch_encoding(unsigned char *a, uint32_t E; uint8_t Ilbrm = 1; uint32_t Tbslbrm = 950984; //max tbs - uint8_t nodata_dmrs = 1; uint8_t nb_re_dmrs; - if (nodata_dmrs) - nb_re_dmrs = 12; + + if (rel15->dmrsConfigType==NFAPI_NR_DMRS_TYPE1) + nb_re_dmrs = 6*rel15->numDmrsCdmGrpsNoData; else - nb_re_dmrs = rel15->dmrsConfigType==NFAPI_NR_DMRS_TYPE1 ? 6:4; + nb_re_dmrs = 4*rel15->numDmrsCdmGrpsNoData; + uint16_t length_dmrs = get_num_dmrs(rel15->dlDmrsSymbPos); uint16_t R=rel15->targetCodeRate[0]; float Coderate = 0.0; diff --git a/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.c b/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.c index 04045380eb..d74819f87f 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.c +++ b/openair1/PHY/NR_TRANSPORT/nr_sch_dmrs.c @@ -84,6 +84,27 @@ uint16_t get_dmrs_freq_idx(uint16_t n, uint8_t k_prime, uint8_t delta, uint8_t d return dmrs_idx; } + +uint8_t allowed_pdsch_re_in_dmrs_symbol(uint16_t k, + uint16_t start_sc, + uint8_t numDmrsCdmGrpsNoData, + uint8_t dmrs_type) { + uint8_t delta; + for (int i = 0; ipdsch_pdu_rel15; uint16_t N_PRB_oh = x_overhead; uint8_t N_PRB_DMRS; - if (nodata_dmrs) - N_PRB_DMRS = 12; - else - N_PRB_DMRS = (pdsch_rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1)?6:4; //This only works for antenna port 1000 + if (pdsch_rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1) { + // if no data in dmrs cdm group is 1 only even REs have no data + // if no data in dmrs cdm group is 2 both odd and even REs have no data + N_PRB_DMRS = numdmrscdmgroupnodata*6; + } + else { + N_PRB_DMRS = numdmrscdmgroupnodata*4; + } uint8_t N_sh_symb = pdsch_rel15->NrOfSymbols; uint8_t Imcs = pdsch_rel15->mcsIndex[0]; uint16_t N_RE_prime = NR_NB_SC_PER_RB*N_sh_symb - N_PRB_DMRS - N_PRB_oh; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 5b7bf3ce02..31bdfc6a1b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -698,7 +698,7 @@ void nr_generate_Msg2(module_id_t module_idP, LOG_D(MAC,"[gNB %d][RAPROC] Frame %d, Subframe %d: RA state %d\n", module_idP, frameP, slotP, ra->state); x_Overhead = 0; - nr_get_tbs_dl(&dl_tti_pdsch_pdu->pdsch_pdu, x_Overhead, 1, dci_pdu_rel15[0].tb_scaling); + nr_get_tbs_dl(&dl_tti_pdsch_pdu->pdsch_pdu, x_Overhead, pdsch_pdu_rel15->numDmrsCdmGrpsNoData, dci_pdu_rel15[0].tb_scaling); // DL TX request tx_req->PDU_length = pdsch_pdu_rel15->TBSize[0]; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 9255d633f8..46d08cd6d2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -369,6 +369,7 @@ int configure_fapi_dl_pdu(int Mod_idP, dci_pdu_rel15[0].harq_pid = 0; // DAI dci_pdu_rel15[0].dai[0].val = (pucch_sched->dai_c-1)&3; + // TPC for PUCCH dci_pdu_rel15[0].tpc = 1; // table 7.2.1-1 in 38.213 // PUCCH resource indicator @@ -377,7 +378,7 @@ int configure_fapi_dl_pdu(int Mod_idP, dci_pdu_rel15[0].pdsch_to_harq_feedback_timing_indicator.val = pucch_sched->timing_indicator; // antenna ports dci_pdu_rel15[0].antenna_ports.val = 0; // nb of cdm groups w/o data 1 and dmrs port 0 - + LOG_I(MAC, "[gNB scheduler phytest] DCI type 1 payload: freq_alloc %d (%d,%d,%d), time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d ndi %d rv %d\n", dci_pdu_rel15[0].frequency_domain_assignment.val, pdsch_pdu_rel15->rbStart, @@ -409,7 +410,7 @@ int configure_fapi_dl_pdu(int Mod_idP, } } AssertFatal(found==1,"Couldn't find an adequate searchspace\n"); - + int ret = nr_configure_pdcch(nr_mac, pdcch_pdu_rel15, UE_list->rnti[UE_id], @@ -444,7 +445,7 @@ int configure_fapi_dl_pdu(int Mod_idP, pdcch_pdu_rel15->DurationSymbols); int x_Overhead = 0; // should be 0 for initialBWP - nr_get_tbs_dl(&dl_tti_pdsch_pdu->pdsch_pdu, x_Overhead,1,0); + nr_get_tbs_dl(&dl_tti_pdsch_pdu->pdsch_pdu,x_Overhead,pdsch_pdu_rel15->numDmrsCdmGrpsNoData,0); // Hardcode it for now TBS = dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15.TBSize[0]; diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index cc0254cc3a..fc50a4d239 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -226,7 +226,7 @@ int to_absslot(nfapi_nr_config_request_scf_t *cfg,int frame,int slot); void nr_get_tbs_dl(nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu, int x_overhead, - uint8_t nodata_dmrs, + uint8_t numdmrscdmgroupnodata, uint8_t tb_scaling); /** \brief Computes Q based on I_MCS PDSCH and table_idx for downlink. Implements MCS Tables from 38.214. */ uint8_t nr_get_Qm_dl(uint8_t Imcs, uint8_t table_idx); From 1c7ee3caba8f8606df4fdbd916e8387a11671eea Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Wed, 13 May 2020 18:05:15 +0200 Subject: [PATCH 223/240] using num_dmrs_cdm_grps_no_data for PUSCH in PHY --- openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c | 14 +++++++++----- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 9 ++++----- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 13 ++++++++++--- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 2824ac1544..5c440f7a12 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -1028,7 +1028,6 @@ int nr_rx_pusch(PHY_VARS_gNB *gNB, int avg[4]; NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; nfapi_nr_pusch_pdu_t *rel15_ul = &gNB->ulsch[ulsch_id][0]->harq_processes[harq_pid]->ulsch_pdu; - uint8_t nodata_dmrs = 1; // FIXME to be properly configured from fapi dmrs_symbol_flag = 0; ptrs_symbol_flag = 0; @@ -1060,10 +1059,15 @@ int nr_rx_pusch(PHY_VARS_gNB *gNB, if (dmrs_symbol_flag == 1){ if (((rel15_ul->ul_dmrs_symb_pos)>>((symbol+1)%frame_parms->symbols_per_slot))&0x01) AssertFatal(1==0,"Double DMRS configuration is not yet supported\n"); - if (nodata_dmrs) - nb_re_pusch = 0; - else - nb_re_pusch = rel15_ul->rb_size * ((rel15_ul->dmrs_config_type==pusch_dmrs_type1)?6:8); + + if (rel15_ul->dmrs_config_type == 0) { + // if no data in dmrs cdm group is 1 only even REs have no data + // if no data in dmrs cdm group is 2 both odd and even REs have no data + nb_re_pusch = rel15_ul->rb_size *(12 - (rel15_ul->num_dmrs_cdm_grps_no_data*6)); + } + else { + nb_re_pusch = rel15_ul->rb_size *(12 - (rel15_ul->num_dmrs_cdm_grps_no_data*4)); + } gNB->pusch_vars[ulsch_id]->dmrs_symbol = symbol; } else { nb_re_pusch = rel15_ul->rb_size * NR_NB_SC_PER_RB; diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 6b49d64338..11eec5db0a 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -218,7 +218,7 @@ void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; nfapi_nr_pusch_pdu_t *pusch_pdu = &gNB->ulsch[ULSCH_id][0]->harq_processes[harq_pid]->ulsch_pdu; - uint8_t ret, nodata_dmrs = 1; + uint8_t ret; uint8_t l, number_dmrs_symbols = 0; uint32_t G; uint16_t start_symbol, number_symbols, nb_re_dmrs; @@ -229,11 +229,10 @@ void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH for (l = start_symbol; l < start_symbol + number_symbols; l++) number_dmrs_symbols += ((pusch_pdu->ul_dmrs_symb_pos)>>l)&0x01; - if (nodata_dmrs) - nb_re_dmrs = 12; + if (pusch_pdu->dmrs_config_type==pusch_dmrs_type1) + nb_re_dmrs = 6*pusch_pdu->num_dmrs_cdm_grps_no_data; else - nb_re_dmrs = ((pusch_pdu->dmrs_config_type == pusch_dmrs_type1)?6:4); - + nb_re_dmrs = 4*pusch_pdu->num_dmrs_cdm_grps_no_data; G = nr_get_G(pusch_pdu->rb_size, number_symbols, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 46d08cd6d2..218c7acbe6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -801,7 +801,7 @@ void nr_schedule_uss_ulsch_phytest(int Mod_idP, pusch_pdu->dmrs_config_type = 0; //dmrs-type 1 (the one with a single DMRS symbol in the beginning) pusch_pdu->ul_dmrs_scrambling_id = 0; //If provided and the PUSCH is not a msg3 PUSCH, otherwise, L2 should set this to physical cell id. pusch_pdu->scid = 0; //DMRS sequence initialization [TS38.211, sec 6.4.1.1.1]. Should match what is sent in DCI 0_1, otherwise set to 0. - //pusch_pdu->num_dmrs_cdm_grps_no_data; + pusch_pdu->num_dmrs_cdm_grps_no_data = 1; //pusch_pdu->dmrs_ports; //DMRS ports. [TS38.212 7.3.1.1.2] provides description between DCI 0-1 content and DMRS ports. Bitmap occupying the 11 LSBs with: bit 0: antenna port 1000 bit 11: antenna port 1011 and for each bit 0: DMRS port not used 1: DMRS port used //Pusch Allocation in frequency domain [TS38.214, sec 6.1.2.2] pusch_pdu->resource_alloc = 1; //type 1 @@ -820,17 +820,24 @@ void nr_schedule_uss_ulsch_phytest(int Mod_idP, pusch_pdu->pusch_data.harq_process_id = 0; pusch_pdu->pusch_data.new_data_indicator = 0; - uint8_t no_data_in_dmrs = 1; // temp implementation uint8_t num_dmrs_symb = 0; for(int dmrs_counter = pusch_pdu->start_symbol_index; dmrs_counter < pusch_pdu->start_symbol_index + pusch_pdu->nr_of_symbols; dmrs_counter++) num_dmrs_symb += ((pusch_pdu->ul_dmrs_symb_pos >> dmrs_counter) & 1); + uint8_t N_PRB_DMRS; + if (pusch_pdu->dmrs_config_type == 0) { + N_PRB_DMRS = pusch_pdu->num_dmrs_cdm_grps_no_data*6; + } + else { + N_PRB_DMRS = pusch_pdu->num_dmrs_cdm_grps_no_data*4; + } + pusch_pdu->pusch_data.tb_size = nr_compute_tbs(pusch_pdu->qam_mod_order, pusch_pdu->target_code_rate, pusch_pdu->rb_size, pusch_pdu->nr_of_symbols, - ( no_data_in_dmrs ? 12 : ((pusch_pdu->dmrs_config_type == pusch_dmrs_type1) ? 6 : 4) ) * num_dmrs_symb, + N_PRB_DMRS * num_dmrs_symb, 0, //nb_rb_oh 0, pusch_pdu->nrOfLayers)>>3; From 0add4fdb553b79e8c0e30ff0732f02111dae35b7 Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Fri, 15 May 2020 09:14:30 +0200 Subject: [PATCH 224/240] bugfix in pucch timing indicator selection --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 742a74ed9f..8f5bef1cc7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -1457,7 +1457,7 @@ void nr_update_pucch_scheduling(int Mod_idP, if (found == 1) { // computing slot in which pucch is scheduled sched_pucch->ul_slot = first_ul_slot_tdd + k + (slotP - (slotP % slots_per_tdd)); - sched_pucch->timing_indicator = pdsch_to_harq_feedback[i]; + sched_pucch->timing_indicator = i; // index in the list of timing indicators } else AssertFatal(1==0,"No Uplink slot available in accordance to allowed timing indicator\n"); From b5b78125c9786da8b6e9aa0671911caebabb2a75 Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Fri, 15 May 2020 18:47:06 +0200 Subject: [PATCH 225/240] test scheduling of pucch reception --- openair1/PHY/NR_TRANSPORT/pucch_rx.c | 4 ++-- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index 0e9a8b0a89..177217d23f 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -367,9 +367,9 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, uint8_t xrtmag_dB = dB_fixed(xrtmag); -#ifdef DEBUG_NR_PUCCH_RX +//#ifdef DEBUG_NR_PUCCH_RX printf("PUCCH 0 : maxpos %d\n",maxpos); -#endif +//#endif index=maxpos; #endif diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 4751fb1237..21bf6b1172 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -321,6 +321,8 @@ void nr_schedule_pucch(int Mod_idP, O_ack = curr_pucch->dai_c; O_uci = O_ack; // for now we are just sending acknacks in pucch + LOG_I(MAC, "Scheduling pucch reception for frame %d slot %d\n", frameP, slotP); + nr_configure_pucch(pucch_pdu, scc, ubwp, @@ -485,6 +487,9 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, if (is_nr_UL_slot(cc->ServingCellConfigCommon,slot_rxP)) { if (get_softmodem_params()->phy_test == 0) { + NR_sched_pucch *curr_pucch = UE_list->UE_sched_ctrl[UE_id].sched_pucch; + if (curr_pucch != NULL) + nr_schedule_pucch(module_idP, UE_id, frame_rxP, slot_rxP); schedule_nr_prach(module_idP, (frame_rxP+1)&1023, slot_rxP); nr_schedule_reception_msg3(module_idP, 0, frame_rxP, slot_rxP); } From 54ca9ea5ab77730fbb8d7f4edfb5690c3a1e62b9 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Mon, 18 May 2020 12:57:24 +0200 Subject: [PATCH 226/240] fixed pucch procedures to use rrc struct in UE --- openair1/PHY/impl_defs_nr.h | 10 +- openair1/SCHED_NR_UE/fapi_nr_ue_l1.c | 4 +- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 6 + openair1/SCHED_NR_UE/pucch_uci_ue_nr.c | 208 +++++++++++++----- openair1/SCHED_NR_UE/pucch_uci_ue_nr.h | 14 +- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 2 +- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 14 +- 7 files changed, 180 insertions(+), 78 deletions(-) diff --git a/openair1/PHY/impl_defs_nr.h b/openair1/PHY/impl_defs_nr.h index 44f2e314ea..3e09f3f593 100644 --- a/openair1/PHY/impl_defs_nr.h +++ b/openair1/PHY/impl_defs_nr.h @@ -757,11 +757,11 @@ typedef struct { #define MAX_NR_OF_SPATIAL_RELATION_INFOS (8) typedef enum { - pucch_format0_nr = 0, - pucch_format1_nr = 1, - pucch_format2_nr = 2, - pucch_format3_nr = 3, - pucch_format4_nr = 4, + pucch_format0_nr = 1, + pucch_format1_nr = 2, + pucch_format2_nr = 3, + pucch_format3_nr = 4, + pucch_format4_nr = 5 } pucch_format_nr_t; typedef enum { diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index a78024f70c..19f0f9312f 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -57,7 +57,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response) NR_UE_PDCCH *pdcch_vars = PHY_vars_UE_g[module_id][cc_id]->pdcch_vars[thread_id][0]; NR_UE_DLSCH_t *dlsch0 = PHY_vars_UE_g[module_id][cc_id]->dlsch[thread_id][0][0]; NR_UE_ULSCH_t *ulsch0 = PHY_vars_UE_g[module_id][cc_id]->ulsch[thread_id][0][0]; - //NR_DL_FRAME_PARMS frame_parms = PHY_vars_UE_g[module_id][cc_id]->frame_parms; + NR_DL_FRAME_PARMS frame_parms = PHY_vars_UE_g[module_id][cc_id]->frame_parms; PRACH_RESOURCES_t *prach_resources = PHY_vars_UE_g[module_id][cc_id]->prach_resources[0]; // PUCCH_ConfigCommon_nr_t *pucch_config_common = PHY_vars_UE_g[module_id][cc_id]->pucch_config_common_nr[0]; @@ -99,7 +99,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response) dlsch0_harq->rvidx = dlsch_config_pdu->rv; dlsch0->g_pucch = dlsch_config_pdu->accumulated_delta_PUCCH; dlsch0_harq->harq_ack.pucch_resource_indicator = dlsch_config_pdu->pucch_resource_id; - dlsch0_harq->harq_ack.slot_for_feedback_ack = dlsch_config_pdu->pdsch_to_harq_feedback_time_ind; + dlsch0_harq->harq_ack.slot_for_feedback_ack = (slot+dlsch_config_pdu->pdsch_to_harq_feedback_time_ind)%frame_parms.slots_per_frame; dlsch0_harq->Nl=1; dlsch0_harq->mcs_table=0; dlsch0_harq->harq_ack.rx_status = downlink_harq_process(dlsch0_harq, dlsch0->current_harq_pid, dlsch_config_pdu->ndi, dlsch0->rnti_type); diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 509f4b6021..f1406c45a2 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -2356,6 +2356,12 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, } // UE_mode==PUSCH */ + LOG_D(PHY, "Sending PUCCH\n"); + pucch_procedures_ue_nr(ue, + gNB_id, + proc, + TRUE); + LOG_D(PHY, "Sending data \n"); nr_ue_pusch_common_procedures(ue, harq_pid, diff --git a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c index 326c617dfb..61b304bc18 100644 --- a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c +++ b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c @@ -37,7 +37,6 @@ #include "PHY/defs_nr_UE.h" #include #include -#include "openair2/LAYER2/NR_MAC_UE/mac_proto.h" #ifndef NO_RAT_NR @@ -162,6 +161,8 @@ void nr_generate_pucch3_4(int32_t **txdataF, * *********************************************************************/ +static int bwp_id = 1; + bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t *proc, bool reset_harq) { uint8_t sr_payload = 0; @@ -186,6 +187,9 @@ bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_ int pucch_resource_id = MAX_NB_OF_PUCCH_RESOURCES; int pucch_resource_indicator = MAX_PUCCH_RESOURCE_INDICATOR; int n_HARQ_ACK; + NR_UE_MAC_INST_t *mac = get_mac_inst(0); + NR_PUCCH_Resource_t *pucch_resource; + //NR_UE_MAC_INST_t *mac = get_mac_inst(0); /* update current context */ @@ -212,11 +216,11 @@ bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_ /* sr_payload = 1 means that this is a positive SR, sr_payload = 0 means that it is a negative SR */ sr_payload = nr_ue_get_SR(Mod_id, - CC_id, - frame_tx, - gNB_id, - 0,//ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][gNB_id]->crnti, - nr_tti_tx); // nr_tti_rx used for meas gap + CC_id, + frame_tx, + gNB_id, + 0,//ue->pdcch_vars[ue->current_thread_id[proc->nr_tti_rx]][gNB_id]->crnti, + nr_tti_tx); // nr_tti_rx used for meas gap } else { sr_payload = 1; @@ -248,10 +252,10 @@ bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_ } else { /* a resource set and a resource should be find according to payload size */ - pucch_resource_set = find_pucch_resource_set( ue, gNB_id, N_UCI); + pucch_resource_set = find_pucch_resource_set( mac, gNB_id, N_UCI); if (pucch_resource_set != MAX_NB_OF_PUCCH_RESOURCE_SETS) { pucch_resource_indicator = 0; - pucch_resource_id = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_ResourceSet[pucch_resource_set]->pucch_resource_id[pucch_resource_indicator]; /* get the first resource of the set */ + pucch_resource_id = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[pucch_resource_set]->resourceList.list.array[pucch_resource_indicator][0]; /* get the first resource of the set */ } else { LOG_W(PHY,"PUCCH no resource set found for CSI at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); @@ -297,7 +301,7 @@ bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_ NR_UE_HARQ_STATUS_t *harq_status = &ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->harq_processes[dl_harq_pid]->harq_ack; - if (select_pucch_resource(ue, gNB_id, N_UCI, pucch_resource_indicator, &initial_pucch_id, &pucch_resource_set, + if (select_pucch_resource(ue, mac, gNB_id, N_UCI, pucch_resource_indicator, &initial_pucch_id, &pucch_resource_set, &pucch_resource_id, harq_status) == TRUE) { /* use of initial pucch configuration provided by system information 1 */ /***********************************************************************/ @@ -338,33 +342,42 @@ bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_ /**********************************************/ else if ((pucch_resource_set != MAX_NB_OF_PUCCH_RESOURCE_SETS) && (pucch_resource_id != MAX_NB_OF_PUCCH_RESOURCES)) { /* check that current configuration is supported */ - if ((ue->cell_group_config.physicalCellGroupConfig.harq_ACK_SpatialBundlingPUCCH != FALSE) - || (ue->cell_group_config.physicalCellGroupConfig.pdsch_HARQ_ACK_Codebook != dynamic)) { + if ((mac->scg->physicalCellGroupConfig->harq_ACK_SpatialBundlingPUCCH[0] != FALSE) + || (mac->scg->physicalCellGroupConfig->pdsch_HARQ_ACK_Codebook != 1)) { LOG_E(PHY,"PUCCH Unsupported cell group configuration : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); return(FALSE); } - else if (ue->PDSCH_ServingCellConfig.codeBlockGroupTransmission != NULL) { + else if (mac->scg->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->codeBlockGroupTransmission != NULL) { LOG_E(PHY,"PUCCH Unsupported code block group for serving cell config : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); return(FALSE); } - format = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_Resource[pucch_resource_id]->format_parameters.format; - nb_symbols_total = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_Resource[pucch_resource_id]->format_parameters.nrofSymbols; - starting_symbol_index = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_Resource[pucch_resource_id]->format_parameters.startingSymbolIndex; - starting_prb = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_Resource[pucch_resource_id]->startingPRB; + pucch_resource = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceToAddModList->list.array[pucch_resource_id]; + format = pucch_resource->format.present; + nb_symbols_total = get_nb_symbols_pucch(pucch_resource, format); + starting_symbol_index = pucch_resource->startingPRB; + starting_prb = get_starting_symb_idx(pucch_resource, format); second_hop = starting_prb; - time_domain_occ = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_Resource[pucch_resource_id]->format_parameters.timeDomainOCC; /* format 1 only */ - occ_length = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_Resource[pucch_resource_id]->format_parameters.occ_length; /* format 4 only */ - occ_Index = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_Resource[pucch_resource_id]->format_parameters.occ_Index; /* format 4 only */ - - if ((format == pucch_format0_nr) || (format == pucch_format1_nr)) { - m_0 = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_Resource[pucch_resource_id]->format_parameters.initialCyclicShift; + if (format==pucch_format1_nr) + time_domain_occ = pucch_resource->format.choice.format1->timeDomainOCC; + if (format==pucch_format4_nr) { + occ_length = pucch_resource->format.choice.format4->occ_Length; + occ_Index = pucch_resource->format.choice.format4->occ_Index; } - else if ((format == pucch_format3_nr) || (format == pucch_format4_nr)) { - if (ue->pucch_config_dedicated_nr[gNB_id].formatConfig[format-1]->additionalDMRS == enable_feature) { + + m_0 = get_ics_pucch(pucch_resource, format); + if (format == pucch_format3_nr) { + if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format3->choice.setup->additionalDMRS[0] == 1) { index_additional_dmrs = I_PUCCH_ADDITIONAL_DMRS; } + } + else if (format == pucch_format4_nr) { + if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format4->choice.setup->additionalDMRS[0] == 1) { + index_additional_dmrs = I_PUCCH_ADDITIONAL_DMRS; + } + } - if (ue->pucch_config_dedicated_nr[gNB_id].PUCCH_Resource[pucch_resource_id]->intraSlotFrequencyHopping == feature_enabled) { + if ((format == pucch_format3_nr) || (format == pucch_format4_nr)) { + if (pucch_resource->intraSlotFrequencyHopping[0] == 1) { index_hopping = I_PUCCH_HOPING; } } @@ -383,6 +396,7 @@ bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_ int O_CRC = 0; nb_symbols = nb_symbols_total; /* by default, it can be reduced due to symbols reserved for dmrs */ + pucch_resource = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceToAddModList->list.array[pucch_resource_id]; switch(format) { case pucch_format0_nr: @@ -399,14 +413,14 @@ bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_ } case pucch_format2_nr: { - nb_of_prbs = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_Resource[pucch_resource_id]->format_parameters.nrofPRBs; + nb_of_prbs = pucch_resource->format.choice.format2->nrofPRBs; N_sc_ctrl_RB = N_SC_RB - 4; break; } case pucch_format3_nr: { - nb_of_prbs = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_Resource[pucch_resource_id]->format_parameters.nrofPRBs; - if (ue->pucch_config_dedicated_nr[gNB_id].formatConfig[format-1]->pi2PBSK == feature_enabled) { + nb_of_prbs = pucch_resource->format.choice.format3->nrofPRBs; + if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format3->choice.setup->pi2BPSK[0] == 1) { Q_m = BITS_PER_SYMBOL_BPSK; /* set bpsk modulation type with 1 bit per modulation symbol */ } N_sc_ctrl_RB = N_SC_RB; @@ -415,7 +429,7 @@ bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_ } case pucch_format4_nr: { - if (ue->pucch_config_dedicated_nr[gNB_id].formatConfig[format-1]->pi2PBSK == feature_enabled) { + if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format4->choice.setup->pi2BPSK[0] == 1) { Q_m = BITS_PER_SYMBOL_BPSK; /* set bpsk modulation type with 1 bit per modulation symbol */ } nb_symbols = nb_symbols_excluding_dmrs[nb_symbols_total-4][index_additional_dmrs][index_hopping]; @@ -432,10 +446,10 @@ bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_ /* drop CSI report if simultaneous HARQ-ACK/SR and periodic/semi-periodic CSI cannot be transmitted at the same time */ if (format != pucch_format0_nr) { - if (ue->pucch_config_dedicated_nr[gNB_id].formatConfig[format-1] != NULL) { - max_code_rate = code_rate_r_time_100[ue->pucch_config_dedicated_nr[gNB_id].formatConfig[format-1]->maxCodeRate]; /* it is code rate * 10 */ + if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format1 != NULL) { + max_code_rate = code_rate_r_time_100[mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format1->choice.setup->maxCodeRate[0]]; /* it is code rate * 10 */ - if ((O_ACK != 0) && (ue->pucch_config_dedicated_nr[gNB_id].formatConfig[format-1]->simultaneousHARQ_ACK_CSI == disable_feature)) { + if ((O_ACK != 0) && (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format1->choice.setup->simultaneousHARQ_ACK_CSI[0] == 0)) { N_UCI = N_UCI - O_CSI; O_CSI = cqi_status = ri_status = 0; csi_payload = 0; /* csi should be dropped in this case */ @@ -675,8 +689,9 @@ uint8_t get_downlink_ack(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t int U_DAI_c = 0; int N_m_c_rx = 0; int V_DAI_m_DL = 0; + NR_UE_MAC_INST_t *mac = get_mac_inst(0); - if (ue->PDSCH_Config.maxNrofCodeWordsScheduledByDCI == nb_code_n2) { + if (mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI[0] == 2) { two_transport_blocks = TRUE; number_of_code_word = 2; } @@ -752,8 +767,8 @@ uint8_t get_downlink_ack(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t U_DAI_c = number_harq_feedback/number_of_code_word; N_m_c_rx = number_harq_feedback; int N_SPS_c = 0; /* FFS TODO_NR multicells and SPS are not supported at the moment */ - if (ue->cell_group_config.physicalCellGroupConfig.harq_ACK_SpatialBundlingPUCCH == FALSE) { - int N_TB_max_DL = ue->PDSCH_Config.maxNrofCodeWordsScheduledByDCI; + if (mac->scg->physicalCellGroupConfig->harq_ACK_SpatialBundlingPUCCH[0] == FALSE) { + int N_TB_max_DL = mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI[0]; *n_HARQ_ACK = (((V_DAI_m_DL - U_DAI_c)%4) * N_TB_max_DL) + N_m_c_rx + N_SPS_c; NR_TST_PHY_PRINTF("PUCCH power n(%d) = ( V(%d) - U(%d) )mod4 * N_TB(%d) + N(%d) \n", *n_HARQ_ACK, V_DAI_m_DL, U_DAI_c, N_TB_max_DL, N_m_c_rx); } @@ -849,7 +864,7 @@ uint8_t get_downlink_ack(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t * *********************************************************************/ -boolean_t select_pucch_resource(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int uci_size, int pucch_resource_indicator, +boolean_t select_pucch_resource(PHY_VARS_NR_UE *ue, NR_UE_MAC_INST_t *mac, uint8_t gNB_id, int uci_size, int pucch_resource_indicator, int *initial_pucch_id, int *resource_set_id, int *resource_id, NR_UE_HARQ_STATUS_t *harq_status) { boolean_t resource_set_found = FALSE; @@ -857,18 +872,19 @@ boolean_t select_pucch_resource(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int uci_size int current_resource_id = MAX_NB_OF_PUCCH_RESOURCES; pucch_format_nr_t format_pucch; int ready_pucch_resource_id = FALSE; /* in the case that it is already given */ + NR_PUCCH_Resource_t *pucch_resource; /* ini values to unset */ *initial_pucch_id = NB_INITIAL_PUCCH_RESOURCE; //*resource_set_id = MAX_NB_OF_PUCCH_RESOURCE_SETS; //*resource_id = MAX_NB_OF_PUCCH_RESOURCES; - if (ue->pucch_config_dedicated_nr[gNB_id].PUCCH_ResourceSet[0] == NULL) { + if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[0] == NULL) { /* No resource set has been already configured so pucch_configCommon from Sib1 should be used in this case */ if (ue->UE_mode[gNB_id] != PUSCH) { - *initial_pucch_id = ue->pucch_config_common_nr[gNB_id].pucch_ResourceCommon; + *initial_pucch_id = mac->ULbwp[bwp_id-1]->bwp_Common->pucch_ConfigCommon->choice.setup->pucch_ResourceCommon; if (*initial_pucch_id >= NB_INITIAL_PUCCH_RESOURCE) { LOG_E(PHY,"PUCCH Invalid initial resource index : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); *initial_pucch_id = NB_INITIAL_PUCCH_RESOURCE; @@ -893,7 +909,7 @@ boolean_t select_pucch_resource(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int uci_size } nb_symbols_for_tx = initial_pucch_resource[*initial_pucch_id].nrofSymbols; format_pucch = initial_pucch_resource[*initial_pucch_id].format; - if (check_pucch_format(ue, gNB_id, format_pucch, nb_symbols_for_tx, uci_size) == TRUE) { + if (check_pucch_format(mac, gNB_id, format_pucch, nb_symbols_for_tx, uci_size) == TRUE) { return (TRUE); } else { @@ -913,7 +929,7 @@ boolean_t select_pucch_resource(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int uci_size -- This field can take integer values that are multiples of 4. Corresponds to L1 parameter 'N_2' or 'N_3' (see 38.213, section 9.2) */ /* look for the first resource set which supports uci_size number of bits for payload */ - pucch_resource_set_id = find_pucch_resource_set( ue, gNB_id, uci_size); + pucch_resource_set_id = find_pucch_resource_set(mac, gNB_id, uci_size); if (pucch_resource_set_id != MAX_NB_OF_PUCCH_RESOURCE_SETS) { resource_set_found = TRUE; } @@ -928,13 +944,13 @@ boolean_t select_pucch_resource(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int uci_size if (resource_set_found == TRUE) { if (pucch_resource_indicator < MAX_PUCCH_RESOURCE_INDICATOR) { /* check if resource indexing by pucch_resource_indicator of this set is compatible */ - if ((ready_pucch_resource_id == TRUE) || (ue->pucch_config_dedicated_nr[gNB_id].PUCCH_ResourceSet[pucch_resource_set_id]->pucch_resource_id[pucch_resource_indicator] != MAX_NB_OF_PUCCH_RESOURCES)) { + if ((ready_pucch_resource_id == TRUE) || (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[pucch_resource_set_id]->resourceList.list.array[pucch_resource_indicator][0] != MAX_NB_OF_PUCCH_RESOURCES)) { if (ready_pucch_resource_id == TRUE) { current_resource_id = *resource_id; } else { - int R_PUCCH = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_ResourceSet[pucch_resource_set_id]->first_resources_set_R_PUCCH; + int R_PUCCH = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[pucch_resource_set_id]->resourceList.list.count; /* is it the first resource and its size exceeds 8 */ if ((pucch_resource_set_id == 0) && (R_PUCCH > MAX_NB_OF_PUCCH_RESOURCES_PER_SET_NOT_0)) { @@ -956,15 +972,22 @@ boolean_t select_pucch_resource(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int uci_size current_resource_id = r_PUCCH; } else { - current_resource_id = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_ResourceSet[pucch_resource_set_id]->pucch_resource_id[pucch_resource_indicator]; + current_resource_id = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[pucch_resource_set_id]->resourceList.list.array[pucch_resource_indicator][0]; } } - if (ue->pucch_config_dedicated_nr[gNB_id].PUCCH_Resource[current_resource_id] != NULL) { - nb_symbols_for_tx = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_Resource[current_resource_id]->format_parameters.nrofSymbols; - format_pucch = ue->pucch_config_dedicated_nr[gNB_id].PUCCH_Resource[current_resource_id]->format_parameters.format; + /*uint8_t pucch_resource_count = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceToAddModList.list.count; + for (uint8_t i=0; iULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceToAddModList.list.array[i]->pucch_ResourceId == current_resource_id) + pucch_resource = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceToAddModList.list.array[i]; + }*/ - if (check_pucch_format(ue, gNB_id, format_pucch, nb_symbols_for_tx, uci_size) == TRUE) { + pucch_resource = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceToAddModList->list.array[current_resource_id]; + if (pucch_resource != NULL) { + format_pucch = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceToAddModList->list.array[current_resource_id]->format.present; + nb_symbols_for_tx = get_nb_symbols_pucch(pucch_resource, format_pucch); + + if (check_pucch_format(mac, gNB_id, format_pucch, nb_symbols_for_tx, uci_size) == TRUE) { *resource_set_id = pucch_resource_set_id; *resource_id = current_resource_id; return (TRUE); @@ -1010,7 +1033,7 @@ boolean_t select_pucch_resource(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int uci_size * *********************************************************************/ -int find_pucch_resource_set(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int uci_size) +int find_pucch_resource_set(NR_UE_MAC_INST_t *mac, uint8_t gNB_id, int uci_size) { int pucch_resource_set_id = 0; @@ -1023,8 +1046,8 @@ int find_pucch_resource_set(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int uci_size) */ /* look for the first resource set which supports uci_size number of bits for payload */ while (pucch_resource_set_id < MAX_NB_OF_PUCCH_RESOURCE_SETS) { - if (ue->pucch_config_dedicated_nr[gNB_id].PUCCH_ResourceSet[pucch_resource_set_id] != NULL) { - if (uci_size <= ue->pucch_config_dedicated_nr[gNB_id].PUCCH_ResourceSet[pucch_resource_set_id]->maxPayloadMinus1 + 1) { + if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[pucch_resource_set_id] != NULL) { + if (uci_size <= mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[pucch_resource_set_id]->maxPayloadMinus1 + 1) { NR_TST_PHY_PRINTF("PUCCH found resource set %d \n", pucch_resource_set_id); return (pucch_resource_set_id); break; @@ -1053,18 +1076,37 @@ int find_pucch_resource_set(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int uci_size) * *********************************************************************/ -boolean_t check_pucch_format(PHY_VARS_NR_UE *ue, uint8_t gNB_id, pucch_format_nr_t format_pucch, int nb_symbols_for_tx, int uci_size) +boolean_t check_pucch_format(NR_UE_MAC_INST_t *mac, uint8_t gNB_id, pucch_format_nr_t format_pucch, int nb_symbols_for_tx, int uci_size) { pucch_format_nr_t selected_pucch_format; pucch_format_nr_t selected_pucch_format_second; + NR_SetupRelease_PUCCH_FormatConfig_t *identified_format; - if (format_pucch != pucch_format0_nr) { - if (ue->pucch_config_dedicated_nr[gNB_id].formatConfig[format_pucch-1] != NULL) { - if (ue->pucch_config_dedicated_nr[gNB_id].formatConfig[format_pucch-1]->nrofSlots != 1) { - LOG_E(PHY,"PUCCH not implemented multislots transmission : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); - return (FALSE); - } - } + switch (format_pucch) { + case pucch_format1_nr: + if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format1 != NULL) + identified_format = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format1; + break; + + case pucch_format2_nr: + if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format2 != NULL) + identified_format = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format2; + break; + + case pucch_format3_nr: + if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format3 != NULL) + identified_format = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format3; + break; + + case pucch_format4_nr: + if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format4 != NULL) + identified_format = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->format4; + break; + } + + if (identified_format->choice.setup->nrofSlots != 1) { + LOG_E(PHY,"PUCCH not implemented multislots transmission : at line %d in function %s of file %s \n", LINE_FILE , __func__, FILE_NAME); + return (FALSE); } if (nb_symbols_for_tx <= 2) { @@ -1215,4 +1257,54 @@ void set_csi_nr(int csi_status, uint32_t csi_payload) } } +uint8_t get_nb_symbols_pucch(NR_PUCCH_Resource_t *pucch_resource, pucch_format_nr_t format_type) +{ + switch (format_type) { + case pucch_format0_nr: + return pucch_resource->format.choice.format0->nrofSymbols; + + case pucch_format1_nr: + return pucch_resource->format.choice.format1->nrofSymbols; + + case pucch_format2_nr: + return pucch_resource->format.choice.format2->nrofSymbols; + + case pucch_format3_nr: + return pucch_resource->format.choice.format3->nrofSymbols; + + case pucch_format4_nr: + return pucch_resource->format.choice.format4->nrofSymbols; + } +} + +uint16_t get_starting_symb_idx(NR_PUCCH_Resource_t *pucch_resource, pucch_format_nr_t format_type) +{ + switch (format_type) { + case pucch_format0_nr: + return pucch_resource->format.choice.format0->startingSymbolIndex; + + case pucch_format1_nr: + return pucch_resource->format.choice.format1->startingSymbolIndex; + + case pucch_format2_nr: + return pucch_resource->format.choice.format2->startingSymbolIndex; + + case pucch_format3_nr: + return pucch_resource->format.choice.format3->startingSymbolIndex; + + case pucch_format4_nr: + return pucch_resource->format.choice.format4->startingSymbolIndex; + } +} + +int get_ics_pucch(NR_PUCCH_Resource_t *pucch_resource, pucch_format_nr_t format_type) +{ + switch (format_type) { + case pucch_format0_nr: + return pucch_resource->format.choice.format0->initialCyclicShift; + + case pucch_format1_nr: + return pucch_resource->format.choice.format1->initialCyclicShift; + } +} diff --git a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.h b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.h index 85cd969e26..8fea1d5ab3 100644 --- a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.h +++ b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.h @@ -41,6 +41,9 @@ /************** INCLUDE *******************************************/ #include "PHY/defs_nr_UE.h" +#include "openair2/LAYER2/NR_MAC_UE/mac_proto.h" +#include "openair2/LAYER2/NR_MAC_UE/mac_defs.h" +#include "RRC/NR_UE/rrc_proto.h" #ifdef DEFINE_VARIABLES_PUCCH_UE_NR_H #define EXTERN @@ -187,7 +190,7 @@ uint8_t get_downlink_ack(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t @param resource_id pucch resource id if any @returns TRUE a pucch resource has been found FALSE no valid pucch resource */ -boolean_t select_pucch_resource(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int uci_size, int pucch_resource_indicator, +boolean_t select_pucch_resource(PHY_VARS_NR_UE *ue, NR_UE_MAC_INST_t *mac, uint8_t gNB_id, int uci_size, int pucch_resource_indicator, int *initial_pucch_id, int *resource_set_id, int *resource_id, NR_UE_HARQ_STATUS_t *harq_status); /** \brief This function select a pucch resource set @@ -196,7 +199,7 @@ boolean_t select_pucch_resource(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int uci_size @param uci size number of uci bits @returns number of the pucch resource set */ -int find_pucch_resource_set(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int uci_size); +int find_pucch_resource_set(NR_UE_MAC_INST_t *mac, uint8_t gNB_id, int uci_size); /** \brief This function check pucch format @param ue context @@ -206,7 +209,7 @@ int find_pucch_resource_set(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int uci_size); @param uci size number of uci bits @returns TRUE pucch format matched uci size and constraints, FALSE invalid pucch format */ -boolean_t check_pucch_format(PHY_VARS_NR_UE *ue, uint8_t gNB_id, pucch_format_nr_t format_pucch, int nb_symbols_for_tx, +boolean_t check_pucch_format(NR_UE_MAC_INST_t *mac, uint8_t gNB_id, pucch_format_nr_t format_pucch, int nb_symbols_for_tx, int uci_size); /** \brief This function selects a pucch resource @@ -232,4 +235,9 @@ int get_csi_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint32_t *csi_payload); void set_csi_nr(int csi_status, uint32_t csi_payload); +uint8_t get_nb_symbols_pucch(NR_PUCCH_Resource_t *pucch_resource, pucch_format_nr_t format_type); + +uint16_t get_starting_symb_idx(NR_PUCCH_Resource_t *pucch_resource, pucch_format_nr_t format_type); + +int get_ics_pucch(NR_PUCCH_Resource_t *pucch_resource, pucch_format_nr_t format_type); #endif /* PUCCH_UCI_UE_NR_H */ diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 20ca1cd60b..bbf8e670b2 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -649,7 +649,7 @@ uint16_t nr_dci_size(NR_CellGroupConfig_t *secondaryCellGroup, dci_pdu->time_domain_assignment.nbits = (int)ceil(log2(num_entries)); size += dci_pdu->time_domain_assignment.nbits; // VRB to PRB mapping - if (pdsch_config->resourceAllocation == 1) { + if ((pdsch_config->resourceAllocation == 1) && (bwp->bwp_Dedicated->pdsch_Config->choice.setup->vrb_ToPRB_Interleaver != NULL)) { dci_pdu->vrb_to_prb_mapping.nbits = 1; size += dci_pdu->vrb_to_prb_mapping.nbits; } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index e292a596a5..7082bb15f7 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -65,6 +65,7 @@ //#define ENABLE_MAC_PAYLOAD_DEBUG 1 #define DEBUG_EXTRACT_DCI 1 +extern int bwp_id; extern dci_pdu_rel15_t *def_dci_pdu_rel15; extern void mac_rlc_data_ind ( @@ -1923,6 +1924,8 @@ int nr_ue_process_dci_indication_pdu(module_id_t module_id,int cc_id, int gNB_in int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dci_pdu_rel15_t *dci, uint16_t rnti, uint32_t dci_format){ + int bwp_id = 1; + NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request; fapi_nr_ul_config_request_t *ul_config = &mac->ul_config_request; @@ -2518,17 +2521,10 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, dc if (dci->tpc == 2) dlsch_config_pdu_1_1->accumulated_delta_PUCCH = 1; if (dci->tpc == 3) dlsch_config_pdu_1_1->accumulated_delta_PUCCH = 3; /* PUCCH_RESOURCE_IND */ - if (dci->pucch_resource_indicator == 0) dlsch_config_pdu_1_1->pucch_resource_id = 0; //pucch-ResourceId obtained from the 1st value of resourceList FIXME!!! - if (dci->pucch_resource_indicator == 1) dlsch_config_pdu_1_1->pucch_resource_id = 0; //pucch-ResourceId obtained from the 2nd value of resourceList FIXME!! - if (dci->pucch_resource_indicator == 2) dlsch_config_pdu_1_1->pucch_resource_id = 0; //pucch-ResourceId obtained from the 3rd value of resourceList FIXME!! - if (dci->pucch_resource_indicator == 3) dlsch_config_pdu_1_1->pucch_resource_id = 0; //pucch-ResourceId obtained from the 4th value of resourceList FIXME!! - if (dci->pucch_resource_indicator == 4) dlsch_config_pdu_1_1->pucch_resource_id = 0; //pucch-ResourceId obtained from the 5th value of resourceList FIXME!! - if (dci->pucch_resource_indicator == 5) dlsch_config_pdu_1_1->pucch_resource_id = 0; //pucch-ResourceId obtained from the 6th value of resourceList FIXME!! - if (dci->pucch_resource_indicator == 6) dlsch_config_pdu_1_1->pucch_resource_id = 0; //pucch-ResourceId obtained from the 7th value of resourceList FIXME!! - if (dci->pucch_resource_indicator == 7) dlsch_config_pdu_1_1->pucch_resource_id = 0; //pucch-ResourceId obtained from the 8th value of resourceList FIXME!! + dlsch_config_pdu_1_1->pucch_resource_id = dci->pucch_resource_indicator; /* PDSCH_TO_HARQ_FEEDBACK_TIME_IND */ // according to TS 38.213 Table 9.2.3-1 - dlsch_config_pdu_1_1-> pdsch_to_harq_feedback_time_ind = mac->phy_config.config_req.ul_bwp_dedicated.pucch_config_dedicated.dl_data_to_ul_ack[dci->pdsch_to_harq_feedback_timing_indicator.val]; + dlsch_config_pdu_1_1->pdsch_to_harq_feedback_time_ind = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->dl_DataToUL_ACK->list.array[dci->pdsch_to_harq_feedback_timing_indicator.val][0]; /* ANTENNA_PORTS */ uint8_t n_codewords = 1; // FIXME!!! if ((mac->phy_config.config_req.dl_bwp_dedicated.pdsch_config_dedicated.dmrs_dl_for_pdsch_mapping_type_a.dmrs_type == 1) && From 49991e100b263984d2346a5d6b99cbb39778fedb Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Tue, 19 May 2020 19:09:29 +0200 Subject: [PATCH 227/240] bugfix for 2 acknacks in pucch0 --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 8f5bef1cc7..4df24d7a16 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -1476,9 +1476,10 @@ void nr_update_pucch_scheduling(int Mod_idP, if (found == 0) i++; } if (found == 1) { // scheduling this harq-ack in current pucch - sched_pucch = curr_pucch; - sched_pucch->dai_c = 1 + sched_pucch->dai_c; - sched_pucch->timing_indicator = pdsch_to_harq_feedback[i]; + curr_pucch->dai_c = 1 + curr_pucch->dai_c; + memcpy(sched_pucch,curr_pucch,sizeof(NR_sched_pucch)); + sched_pucch->timing_indicator = i; + return; } } if (curr_pucch->dai_c==MAX_ACK_BITS || found == 0) { // if current pucch is full or no timing indicator allowed @@ -1498,7 +1499,7 @@ void nr_update_pucch_scheduling(int Mod_idP, sched_pucch->next_sched_pucch = curr_pucch; sched_pucch->dai_c = 1; sched_pucch->resource_indicator = 0; // in phytest with only 1 UE we are using just the 1st resource - sched_pucch->timing_indicator = pdsch_to_harq_feedback[i]; + sched_pucch->timing_indicator = i; UE_list->UE_sched_ctrl[UE_id].sched_pucch = sched_pucch; } else { @@ -1508,7 +1509,7 @@ void nr_update_pucch_scheduling(int Mod_idP, sched_pucch->frame = frameP; sched_pucch->next_sched_pucch = NULL; sched_pucch->dai_c = 1; - sched_pucch->timing_indicator = pdsch_to_harq_feedback[i]; + sched_pucch->timing_indicator = i; sched_pucch->resource_indicator = 0; // in phytest with only 1 UE we are using just the 1st resource sched_pucch->ul_slot = k + (slotP - (slotP % slots_per_tdd)); curr_pucch->next_sched_pucch = (NR_sched_pucch*) malloc(sizeof(NR_sched_pucch)); @@ -1520,7 +1521,7 @@ void nr_update_pucch_scheduling(int Mod_idP, else { // scheduling this harq-ack in current pucch sched_pucch = curr_pucch; sched_pucch->dai_c = 1 + sched_pucch->dai_c; - sched_pucch->timing_indicator = pdsch_to_harq_feedback[i]; + sched_pucch->timing_indicator = i; } } } From dd8cb9844317f1933a6cff47da046df4438580a8 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Tue, 19 May 2020 23:58:28 +0200 Subject: [PATCH 228/240] added support in gNB and UE for long PRACH sequences. Tested format 0 with unitary simulation only. --- openair1/PHY/INIT/nr_init_ru.c | 4 +- openair1/PHY/NR_TRANSPORT/nr_prach.c | 11 +- openair1/PHY/NR_UE_TRANSPORT/nr_prach.c | 7 +- openair1/PHY/TOOLS/Makefile | 20 +- openair1/PHY/TOOLS/oai_dfts.c | 850 +++++++++++++++++- openair1/SIMULATION/NR_PHY/prachsim.c | 45 +- openair1/SIMULATION/TOOLS/taus.c | 3 +- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 1 + 8 files changed, 893 insertions(+), 48 deletions(-) diff --git a/openair1/PHY/INIT/nr_init_ru.c b/openair1/PHY/INIT/nr_init_ru.c index 60921da1cb..30700b4cc6 100644 --- a/openair1/PHY/INIT/nr_init_ru.c +++ b/openair1/PHY/INIT/nr_init_ru.c @@ -113,8 +113,8 @@ int nr_phy_init_RU(RU_t *ru) { ru->prach_rxsigF = (int16_t**)malloc(ru->nb_rx * sizeof(int16_t*)); for (i=0; inb_rx; i++) { - // for preamble format 1 and 2, more memory should be allocated - ru->prach_rxsigF[i] = (int16_t*)malloc16_clear( fp->ofdm_symbol_size*12*(1<prach_rxsigF[i] = (int16_t*)malloc16_clear( 4*98304*2*sizeof(int16_t) ); LOG_D(PHY,"[INIT] prach_vars->rxsigF[%d] = %p\n",i,ru->prach_rxsigF[i]); } diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c index e317f71fbc..52ed4a5f19 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c @@ -283,6 +283,7 @@ void rx_nr_prach_ru(RU_t *ru, if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { dftlen=49152; dft(DFT_49152,prach2,rxsigF[aa],1); + LOG_M("prach_rxsigF.m","prach_rxF0",rxsigF[aa],49152,1,1); } if (prachFormat == 1 || prachFormat == 2) { dft(DFT_49152,prach2+98304,rxsigF[aa]+98304,1); @@ -503,6 +504,7 @@ void rx_nr_prach_ru(RU_t *ru, } //Coherent combining of PRACH repetitions (assumes channel does not change, to be revisted for "long" PRACH) + LOG_D(PHY,"Doing PRACH combining of %d reptitions N_ZC %d\n",reps,N_ZC); int16_t rxsigF_tmp[N_ZC<<1]; // if (k+N_ZC > dftlen) { // PRACH signal is split around DC int16_t *rxsigF2=rxsigF[aa]; @@ -583,8 +585,6 @@ void rx_nr_prach(PHY_VARS_gNB *gNB, restricted_set = cfg->restricted_set_config.value; - AssertFatal(prach_sequence_length == 1, "no support yet for long prachSequenceLength\n"); - uint8_t prach_fmt = prach_pdu->prach_format; uint16_t N_ZC = (prach_sequence_length==0)?839:139; @@ -624,7 +624,7 @@ void rx_nr_prach(PHY_VARS_gNB *gNB, if (LOG_DEBUGFLAG(PRACH)){ int en = dB_fixed(signal_energy((int32_t*)&rxsigF[0][0],(N_ZC==839) ? 840: 140)); - if (en>60) LOG_I(PHY,"frame %d, subframe %d : Trying preamble %d \n",frame,subframe,preamble_index); + if (en>60) LOG_D(PHY,"frame %d, subframe %d : Trying preamble %d \n",frame,subframe,preamble_index); } if (restricted_set == 0) { // This is the relative offset in the root sequence table (5.7.2-4 from 36.211) for the given preamble index @@ -750,10 +750,10 @@ void rx_nr_prach(PHY_VARS_gNB *gNB, prach_ifft[i] += ((int32_t)prach_ifft_tmp[i<<1]*(int32_t)prach_ifft_tmp[(i<<1)] + (int32_t)prach_ifft_tmp[1+(i<<1)]*(int32_t)prach_ifft_tmp[1+(i<<1)])>>10; } - if (LOG_DUMPFLAG(PRACH)) { + // if (LOG_DUMPFLAG(PRACH)) { if (aa==0) LOG_M("prach_rxF_comp0.m","prach_rxF_comp0",prachF,1024,1,1); if (aa==1) LOG_M("prach_rxF_comp1.m","prach_rxF_comp1",prachF,1024,1,1); - } + // } }// antennas_rx } // new dft @@ -766,6 +766,7 @@ void rx_nr_prach(PHY_VARS_gNB *gNB, lev = (int32_t)prach_ifft[(preamble_shift2+i)]; levdB = dB_fixed_times10(lev); if (levdB>*max_preamble_energy) { + LOG_D(PHY,"preamble_index %d, delay %d en %d dB > %d dB\n",preamble_index,i,levdB,*max_preamble_energy); *max_preamble_energy = levdB; *max_preamble_delay = i; // Note: This has to be normalized to the 30.72 Ms/s sampling rate *max_preamble = preamble_index; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c index 5c049f06c5..82af0b88e5 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c @@ -60,6 +60,7 @@ extern int64_t table_6_3_3_2_4_prachConfig_Index [256][10]; extern uint16_t nr_du[838]; extern int16_t nr_ru[2*839]; extern const char *prachfmt[9]; +extern const char *prachfmt03[4]; // Note: // - prach_fmt_id is an ID used to map to the corresponding PRACH format value in prachfmt @@ -210,9 +211,9 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){ #ifdef NR_PRACH_DEBUG if (NCS>0) LOG_I(PHY, "PRACH [UE %d] generate PRACH for RootSeqIndex %d, Preamble Index %d, PRACH Format %s, NCS %d (N_ZC %d): Preamble_offset %d, Preamble_shift %d\n", Mod_id, - rootSequenceIndex, - preamble_index, - prachfmt[prach_fmt_id], + rootSequenceIndex, + preamble_index, + prach_sequence_length == 0 ? prachfmt03[prach_fmt_id] : prachfmt[prach_fmt_id], NCS, N_ZC, preamble_offset, diff --git a/openair1/PHY/TOOLS/Makefile b/openair1/PHY/TOOLS/Makefile index c71717dc87..a59700bb7c 100644 --- a/openair1/PHY/TOOLS/Makefile +++ b/openair1/PHY/TOOLS/Makefile @@ -1,16 +1,16 @@ -lte_dfts_sse4: lte_dfts.c - gcc-7 -O3 -std=gnu99 -msse4.1 -o lte_dfts_sse4 lte_dfts.c time_meas.c ../../SIMULATION/TOOLS/taus.c -I$$OPENAIR_HOME -I$$OPENAIR1_DIR -I$$OPENAIR_TARGETS -I$$OPENAIR2_DIR -I$$OPENAIR2_DIR/COMMON -I$$OPENAIR_HOME/common/utils -I$$OPENAIR_HOME/common/utils/T -DMR_MAIN -DNB_ANTENNAS_RX=1 -lm -lpthread # -DD256STATS #-DD64STATS +oai_dfts_sse4: oai_dfts.c + gcc-7 -O3 -std=gnu99 -msse4.1 -o oai_dfts_sse4 oai_dfts.c time_meas.c ../../SIMULATION/TOOLS/taus.c -I$$OPENAIR_HOME -I$$OPENAIR1_DIR -I$$OPENAIR_TARGETS -I$$OPENAIR_TARGETS/COMMON -I$$OPENAIR_TARGETS/ARCH/COMMON -I$$OPENAIR2_DIR -I$$OPENAIR2_DIR/COMMON -I$$OPENAIR_HOME/common/utils -I$$OPENAIR_HOME/common/utils/T -I$$OPENAIR_HOME/common/utils/msc -I$$OPENAIR_HOME/nfapi/open-nFAPI/nfapi/public_inc -DMR_MAIN -DNB_ANTENNAS_RX=1 -lm -lpthread # -DD256STATS #-DD64STATS -lte_dfts_avx2: lte_dfts.c - gcc -O2 -std=gnu99 -mavx2 -g -ggdb -o lte_dfts_avx2 lte_dfts.c time_meas.c ../../SIMULATION/TOOLS/taus.c $$OPENAIR_HOME/common/utils/backtrace.c -I$$OPENAIR_HOME -I$$OPENAIR1_DIR -I$$OPENAIR_TARGETS -I$$OPENAIR2_DIR -I$$OPENAIR2_DIR/COMMON -I$$OPENAIR_HOME/common/utils -I$$OPENAIR_HOME/common/utils/T -DMR_MAIN -DNB_ANTENNAS_RX=1 -lm -lpthread # -DD256STATS #-DD64STATS +oai_dfts_avx2: oai_dfts.c + gcc -O2 -std=gnu99 -mavx2 -g -ggdb -o oai_dfts_avx2 oai_dfts.c time_meas.c ../../SIMULATION/TOOLS/taus.c $$OPENAIR_HOME/common/utils/backtrace.c -I$$OPENAIR_HOME -I$$OPENAIR1_DIR -I$$OPENAIR_TARGETS -I$$OPENAIR_TARGETS/COMMON -I$$OPENAIR_TARGETS/ARCH/COMMON -I$$OPENAIR2_DIR -I$$OPENAIR2_DIR/COMMON -I$$OPENAIR_HOME/common/utils -I$$OPENAIR_HOME/common/utils/T -I$$OPENAIR_HOME/common/utils/msc -I$$OPENAIR_HOME/nfapi/open-nFAPI/nfapi/public_inc -DMR_MAIN -DNB_ANTENNAS_RX=1 -lm -lpthread # -DD256STATS #-DD64STATS -lte_dfts_avx2.s: lte_dfts.c - gcc -O2 -std=gnu99 -mavx2 -S lte_dfts.c time_meas.c ../../SIMULATION/TOOLS/taus.c $$OPENAIR_HOME/common/utils/backtrace.c -I$$OPENAIR_HOME -I$$OPENAIR1_DIR -I$$OPENAIR_TARGETS -I$$OPENAIR2_DIR -I$$OPENAIR2_DIR/COMMON -I$$OPENAIR_HOME/common/utils -I$$OPENAIR_HOME/common/utils/T -DMR_MAIN -DNB_ANTENNAS_RX=1 -lm -lpthread # -DD256STATS #-DD64STATS +oai_dfts_avx2.s: oai_dfts.c + gcc -O2 -std=gnu99 -mavx2 -S oai_dfts.c time_meas.c ../../SIMULATION/TOOLS/taus.c $$OPENAIR_HOME/common/utils/backtrace.c -I$$OPENAIR_HOME -I$$OPENAIR1_DIR -I$$OPENAIR_TARGETS -I$$OPENAIR_TARGETS/COMMON -I$$OPENAIR_TARGETS/ARCH/COMMON -I$$OPENAIR2_DIR -I$$OPENAIR2_DIR/COMMON -I$$OPENAIR_HOME/common/utils -I$$OPENAIR_HOME/common/utils/T -I$$OPENAIR_HOME/common/utils/msc -I$$OPENAIR_HOME/nfapi/open-nFAPI/nfapi/public_inc -DMR_MAIN -DNB_ANTENNAS_RX=1 -lm -lpthread # -DD256STATS #-DD64STATS -lte_dfts_sse4.s: lte_dfts.c - gcc -O2 -std=gnu99 -msse4.1 -S lte_dfts.c time_meas.c ../../SIMULATION/TOOLS/taus.c $$OPENAIR_HOME/common/utils/backtrace.c -I$$OPENAIR_HOME -I$$OPENAIR1_DIR -I$$OPENAIR_TARGETS -I$$OPENAIR2_DIR -I$$OPENAIR2_DIR/COMMON -I$$OPENAIR_HOME/common/utils -I$$OPENAIR_HOME/common/utils/T -DMR_MAIN -DNB_ANTENNAS_RX=1 -lm -lpthread # -DD256STATS #-DD64STATS +oai_dfts_sse4.s: oai_dfts.c + gcc -O2 -std=gnu99 -msse4.1 -S oai_dfts.c time_meas.c ../../SIMULATION/TOOLS/taus.c $$OPENAIR_HOME/common/utils/backtrace.c -I$$OPENAIR_HOME -I$$OPENAIR1_DIR -I$$OPENAIR_TARGETS -I$$OPENAIR_TARGETS/COMMON -I$$OPENAIR_TARGETS/ARCH/COMMON -I$$OPENAIR2_DIR -I$$OPENAIR2_DIR/COMMON -I$$OPENAIR_HOME/common/utils -I$$OPENAIR_HOME/common/utils/T -I$$OPENAIR_HOME/common/utils/msc -I$$OPENAIR_HOME/nfapi/open-nFAPI/nfapi/public_inc -DMR_MAIN -DNB_ANTENNAS_RX=1 -lm -lpthread # -DD256STATS #-DD64STATS -dft_cycles_avx2: lte_dfts_avx2 - ./lte_dfts_avx2 | egrep cycles +dft_cycles_avx2: oai_dfts_avx2 + ./oai_dfts_avx2 | egrep cycles diff --git a/openair1/PHY/TOOLS/oai_dfts.c b/openair1/PHY/TOOLS/oai_dfts.c index bb8c46592c..6ae852b127 100644 --- a/openair1/PHY/TOOLS/oai_dfts.c +++ b/openair1/PHY/TOOLS/oai_dfts.c @@ -5353,6 +5353,607 @@ void idft8192(int16_t *x,int16_t *y,unsigned char scale) #endif +int16_t tw16384[3*2*4096]; + +#ifndef __AVX2__ +void dft16384(int16_t *x,int16_t *y,unsigned char scale) +{ + + simd_q15_t xtmp[4096],ytmp[4096],*tw16384_128p=(simd_q15_t *)tw16384,*x128=(simd_q15_t *)x,*y128=(simd_q15_t *)y,*y128p=(simd_q15_t *)y; + simd_q15_t *ytmpp = &ytmp[0]; + int i,j; + + for (i=0,j=0; i<4096; i+=4,j++) { + transpose16_ooff(x128+i,xtmp+j,1024); + } + + + dft4096((int16_t*)(xtmp),(int16_t*)(ytmp),1); + dft4096((int16_t*)(xtmp+1024),(int16_t*)(ytmp+1024),1); + dft4096((int16_t*)(xtmp+2048),(int16_t*)(ytmp+2048),1); + dft4096((int16_t*)(xtmp+3072),(int16_t*)(ytmp+3072),1); + + for (i=0; i<1024; i++) { + bfly4(ytmpp,ytmpp+1024,ytmpp+2048,ytmpp+3072, + y128p,y128p+1024,y128p+2048,y128p+3072, + tw16384_128p,tw16384_128p+1024,tw16384_128p+2048); + tw16384_128p++; + y128p++; + ytmpp++; + } + + if (scale>0) { + + for (i=0; i<256; i++) { + y128[0] = shiftright_int16(y128[0],1); + y128[1] = shiftright_int16(y128[1],1); + y128[2] = shiftright_int16(y128[2],1); + y128[3] = shiftright_int16(y128[3],1); + y128[4] = shiftright_int16(y128[4],1); + y128[5] = shiftright_int16(y128[5],1); + y128[6] = shiftright_int16(y128[6],1); + y128[7] = shiftright_int16(y128[7],1); + y128[8] = shiftright_int16(y128[8],1); + y128[9] = shiftright_int16(y128[9],1); + y128[10] = shiftright_int16(y128[10],1); + y128[11] = shiftright_int16(y128[11],1); + y128[12] = shiftright_int16(y128[12],1); + y128[13] = shiftright_int16(y128[13],1); + y128[14] = shiftright_int16(y128[14],1); + y128[15] = shiftright_int16(y128[15],1); + + y128+=16; + } + + } + + _mm_empty(); + _m_empty(); + +} + + + +void idft16384(int16_t *x,int16_t *y,unsigned char scale) +{ + + simd_q15_t xtmp[4096],ytmp[4096],*tw16384_128p=(simd_q15_t *)tw16384,*x128=(simd_q15_t *)x,*y128=(simd_q15_t *)y,*y128p=(simd_q15_t *)y; + simd_q15_t *ytmpp = &ytmp[0]; + int i,j; + + for (i=0,j=0; i<4096; i+=4,j++) { + transpose16_ooff(x128+i,xtmp+j,1024); + } + + + idft4096((int16_t*)(xtmp),(int16_t*)(ytmp),1); + idft4096((int16_t*)(xtmp+1024),(int16_t*)(ytmp+1024),1); + idft4096((int16_t*)(xtmp+2048),(int16_t*)(ytmp+2048),1); + idft4096((int16_t*)(xtmp+3072),(int16_t*)(ytmp+3072),1); + + for (i=0; i<1024; i++) { + ibfly4(ytmpp,ytmpp+1024,ytmpp+2048,ytmpp+3072, + y128p,y128p+1024,y128p+2048,y128p+3072, + tw16384_128p,tw16384_128p+1024,tw16384_128p+2048); + tw16384_128p++; + y128p++; + ytmpp++; + } + + if (scale>0) { + + for (i=0; i<256; i++) { + y128[0] = shiftright_int16(y128[0],scale); + y128[1] = shiftright_int16(y128[1],scale); + y128[2] = shiftright_int16(y128[2],scale); + y128[3] = shiftright_int16(y128[3],scale); + y128[4] = shiftright_int16(y128[4],scale); + y128[5] = shiftright_int16(y128[5],scale); + y128[6] = shiftright_int16(y128[6],scale); + y128[7] = shiftright_int16(y128[7],scale); + y128[8] = shiftright_int16(y128[8],scale); + y128[9] = shiftright_int16(y128[9],scale); + y128[10] = shiftright_int16(y128[10],scale); + y128[11] = shiftright_int16(y128[11],scale); + y128[12] = shiftright_int16(y128[12],scale); + y128[13] = shiftright_int16(y128[13],scale); + y128[14] = shiftright_int16(y128[14],scale); + y128[15] = shiftright_int16(y128[15],scale); + + y128+=16; + } + + } + + _mm_empty(); + _m_empty(); + +} + +#else //__AVX2__ +void dft16384(int16_t *x,int16_t *y,unsigned char scale) +{ + + simd256_q15_t xtmp[2048],ytmp[2048],*tw16384_256p=(simd256_q15_t *)tw16384,*x256=(simd256_q15_t *)x,*y256=(simd256_q15_t *)y,*y256p=(simd256_q15_t *)y; + simd256_q15_t *ytmpp = &ytmp[0]; + int i,j; + + for (i=0,j=0; i<2048; i+=4,j++) { + transpose16_ooff_simd256(x256+i,xtmp+j,512); + } + + + dft4096((int16_t*)(xtmp),(int16_t*)(ytmp),1); + dft4096((int16_t*)(xtmp+512),(int16_t*)(ytmp+512),1); + dft4096((int16_t*)(xtmp+1024),(int16_t*)(ytmp+1024),1); + dft4096((int16_t*)(xtmp+1536),(int16_t*)(ytmp+1536),1); + + for (i=0; i<512; i++) { + bfly4_256(ytmpp,ytmpp+512,ytmpp+1024,ytmpp+1536, + y256p,y256p+512,y256p+1024,y256p+1536, + tw16384_256p,tw16384_256p+512,tw16384_256p+1024); + tw16384_256p++; + y256p++; + ytmpp++; + } + + if (scale>0) { + + for (i=0; i<128; i++) { + y256[0] = shiftright_int16_simd256(y256[0],1); + y256[1] = shiftright_int16_simd256(y256[1],1); + y256[2] = shiftright_int16_simd256(y256[2],1); + y256[3] = shiftright_int16_simd256(y256[3],1); + y256[4] = shiftright_int16_simd256(y256[4],1); + y256[5] = shiftright_int16_simd256(y256[5],1); + y256[6] = shiftright_int16_simd256(y256[6],1); + y256[7] = shiftright_int16_simd256(y256[7],1); + y256[8] = shiftright_int16_simd256(y256[8],1); + y256[9] = shiftright_int16_simd256(y256[9],1); + y256[10] = shiftright_int16_simd256(y256[10],1); + y256[11] = shiftright_int16_simd256(y256[11],1); + y256[12] = shiftright_int16_simd256(y256[12],1); + y256[13] = shiftright_int16_simd256(y256[13],1); + y256[14] = shiftright_int16_simd256(y256[14],1); + y256[15] = shiftright_int16_simd256(y256[15],1); + + y256+=16; + } + + } + + _mm_empty(); + _m_empty(); + +} + +void idft16384(int16_t *x,int16_t *y,unsigned char scale) +{ + + simd256_q15_t xtmp[2048],ytmp[2048],*tw16384_256p=(simd256_q15_t *)tw16384,*x256=(simd256_q15_t *)x,*y256=(simd256_q15_t *)y,*y256p=(simd256_q15_t *)y; + simd256_q15_t *ytmpp = &ytmp[0]; + int i,j; + + for (i=0,j=0; i<2048; i+=4,j++) { + transpose16_ooff_simd256(x256+i,xtmp+j,512); + } + + + idft4096((int16_t*)(xtmp),(int16_t*)(ytmp),1); + idft4096((int16_t*)(xtmp+512),(int16_t*)(ytmp+512),1); + idft4096((int16_t*)(xtmp+1024),(int16_t*)(ytmp+1024),1); + idft4096((int16_t*)(xtmp+1536),(int16_t*)(ytmp+1536),1); + + for (i=0; i<512; i++) { + ibfly4_256(ytmpp,ytmpp+512,ytmpp+1024,ytmpp+1536, + y256p,y256p+512,y256p+1024,y256p+1536, + tw16384_256p,tw16384_256p+512,tw16384_256p+1024); + tw16384_256p++; + y256p++; + ytmpp++; + } + + if (scale>0) { + + for (i=0; i<128; i++) { + y256[0] = shiftright_int16_simd256(y256[0],1); + y256[1] = shiftright_int16_simd256(y256[1],1); + y256[2] = shiftright_int16_simd256(y256[2],1); + y256[3] = shiftright_int16_simd256(y256[3],1); + y256[4] = shiftright_int16_simd256(y256[4],1); + y256[5] = shiftright_int16_simd256(y256[5],1); + y256[6] = shiftright_int16_simd256(y256[6],1); + y256[7] = shiftright_int16_simd256(y256[7],1); + y256[8] = shiftright_int16_simd256(y256[8],1); + y256[9] = shiftright_int16_simd256(y256[9],1); + y256[10] = shiftright_int16_simd256(y256[10],1); + y256[11] = shiftright_int16_simd256(y256[11],1); + y256[12] = shiftright_int16_simd256(y256[12],1); + y256[13] = shiftright_int16_simd256(y256[13],1); + y256[14] = shiftright_int16_simd256(y256[14],1); + y256[15] = shiftright_int16_simd256(y256[15],1); + + y256+=16; + } + + } + + _mm_empty(); + _m_empty(); + +} + +#endif //__AVX2__ + +int16_t tw32768[2*16384] __attribute__((aligned(32))); + +#ifndef __AVX2__ +void dft32768(int16_t *x,int16_t *y,unsigned char scale) +{ + + simdshort_q15_t xtmp[16384],*xtmpp,*x64 = (simdshort_q15_t *)x; + simd_q15_t ytmp[8192],*tw32768_128p=(simd_q15_t *)tw32768,*y128=(simd_q15_t *)y,*y128p=(simd_q15_t *)y; + simd_q15_t *ytmpp = &ytmp[0]; + int i; + simd_q15_t ONE_OVER_SQRT2_Q15_128 = set1_int16(ONE_OVER_SQRT2_Q15); + + xtmpp = xtmp; + + for (i=0; i<256; i++) { + transpose4_ooff(x64 ,xtmpp,8192); + transpose4_ooff(x64+2,xtmpp+1,8192); + transpose4_ooff(x64+4,xtmpp+2,8192); + transpose4_ooff(x64+6,xtmpp+3,8192); + transpose4_ooff(x64+8,xtmpp+4,8192); + transpose4_ooff(x64+10,xtmpp+5,8192); + transpose4_ooff(x64+12,xtmpp+6,8192); + transpose4_ooff(x64+14,xtmpp+7,8192); + transpose4_ooff(x64+16,xtmpp+8,8192); + transpose4_ooff(x64+18,xtmpp+9,8192); + transpose4_ooff(x64+20,xtmpp+10,8192); + transpose4_ooff(x64+22,xtmpp+11,8192); + transpose4_ooff(x64+24,xtmpp+12,8192); + transpose4_ooff(x64+26,xtmpp+13,8192); + transpose4_ooff(x64+28,xtmpp+14,8192); + transpose4_ooff(x64+30,xtmpp+15,8192); + transpose4_ooff(x64+32,xtmpp+16,8192); + transpose4_ooff(x64+34,xtmpp+17,8192); + transpose4_ooff(x64+36,xtmpp+18,8192); + transpose4_ooff(x64+38,xtmpp+19,8192); + transpose4_ooff(x64+40,xtmpp+20,8192); + transpose4_ooff(x64+42,xtmpp+21,8192); + transpose4_ooff(x64+44,xtmpp+22,8192); + transpose4_ooff(x64+46,xtmpp+23,8192); + transpose4_ooff(x64+48,xtmpp+24,8192); + transpose4_ooff(x64+50,xtmpp+25,8192); + transpose4_ooff(x64+52,xtmpp+26,8192); + transpose4_ooff(x64+54,xtmpp+27,8192); + transpose4_ooff(x64+56,xtmpp+28,8192); + transpose4_ooff(x64+58,xtmpp+29,8192); + transpose4_ooff(x64+60,xtmpp+30,8192); + transpose4_ooff(x64+62,xtmpp+31,8192); + x64+=64; + xtmpp+=32; + } + + dft16384((int16_t*)(xtmp),(int16_t*)ytmp,1); + dft16384((int16_t*)(xtmp+8192),(int16_t*)(ytmp+4096),1); + + + for (i=0; i<4096; i++) { + bfly2(ytmpp,ytmpp+4096, + y128p,y128p+4096, + tw32768_128p); + tw32768_128p++; + y128p++; + ytmpp++; + } + + if (scale>0) { + y128p = y128; + + for (i=0; i<512; i++) { + y128p[0] = mulhi_int16(y128p[0],ONE_OVER_SQRT2_Q15_128); + y128p[1] = mulhi_int16(y128p[1],ONE_OVER_SQRT2_Q15_128); + y128p[2] = mulhi_int16(y128p[2],ONE_OVER_SQRT2_Q15_128); + y128p[3] = mulhi_int16(y128p[3],ONE_OVER_SQRT2_Q15_128); + y128p[4] = mulhi_int16(y128p[4],ONE_OVER_SQRT2_Q15_128); + y128p[5] = mulhi_int16(y128p[5],ONE_OVER_SQRT2_Q15_128); + y128p[6] = mulhi_int16(y128p[6],ONE_OVER_SQRT2_Q15_128); + y128p[7] = mulhi_int16(y128p[7],ONE_OVER_SQRT2_Q15_128); + y128p[8] = mulhi_int16(y128p[8],ONE_OVER_SQRT2_Q15_128); + y128p[9] = mulhi_int16(y128p[9],ONE_OVER_SQRT2_Q15_128); + y128p[10] = mulhi_int16(y128p[10],ONE_OVER_SQRT2_Q15_128); + y128p[11] = mulhi_int16(y128p[11],ONE_OVER_SQRT2_Q15_128); + y128p[12] = mulhi_int16(y128p[12],ONE_OVER_SQRT2_Q15_128); + y128p[13] = mulhi_int16(y128p[13],ONE_OVER_SQRT2_Q15_128); + y128p[14] = mulhi_int16(y128p[14],ONE_OVER_SQRT2_Q15_128); + y128p[15] = mulhi_int16(y128p[15],ONE_OVER_SQRT2_Q15_128); + y128p+=16; + } + } + + _mm_empty(); + _m_empty(); + +} + +void idft32768(int16_t *x,int16_t *y,unsigned char scale) +{ + + simdshort_q15_t xtmp[16384],*xtmpp,*x64 = (simdshort_q15_t *)x; + simd_q15_t ytmp[8192],*tw32768_128p=(simd_q15_t *)tw32768,*y128=(simd_q15_t *)y,*y128p=(simd_q15_t *)y; + simd_q15_t *ytmpp = &ytmp[0]; + int i; + simd_q15_t ONE_OVER_SQRT2_Q15_128 = set1_int16(ONE_OVER_SQRT2_Q15); + + xtmpp = xtmp; + + for (i=0; i<256; i++) { + transpose4_ooff(x64 ,xtmpp,8192); + transpose4_ooff(x64+2,xtmpp+1,8192); + transpose4_ooff(x64+4,xtmpp+2,8192); + transpose4_ooff(x64+6,xtmpp+3,8192); + transpose4_ooff(x64+8,xtmpp+4,8192); + transpose4_ooff(x64+10,xtmpp+5,8192); + transpose4_ooff(x64+12,xtmpp+6,8192); + transpose4_ooff(x64+14,xtmpp+7,8192); + transpose4_ooff(x64+16,xtmpp+8,8192); + transpose4_ooff(x64+18,xtmpp+9,8192); + transpose4_ooff(x64+20,xtmpp+10,8192); + transpose4_ooff(x64+22,xtmpp+11,8192); + transpose4_ooff(x64+24,xtmpp+12,8192); + transpose4_ooff(x64+26,xtmpp+13,8192); + transpose4_ooff(x64+28,xtmpp+14,8192); + transpose4_ooff(x64+30,xtmpp+15,8192); + transpose4_ooff(x64+32,xtmpp+16,8192); + transpose4_ooff(x64+34,xtmpp+17,8192); + transpose4_ooff(x64+36,xtmpp+18,8192); + transpose4_ooff(x64+38,xtmpp+19,8192); + transpose4_ooff(x64+40,xtmpp+20,8192); + transpose4_ooff(x64+42,xtmpp+21,8192); + transpose4_ooff(x64+44,xtmpp+22,8192); + transpose4_ooff(x64+46,xtmpp+23,8192); + transpose4_ooff(x64+48,xtmpp+24,8192); + transpose4_ooff(x64+50,xtmpp+25,8192); + transpose4_ooff(x64+52,xtmpp+26,8192); + transpose4_ooff(x64+54,xtmpp+27,8192); + transpose4_ooff(x64+56,xtmpp+28,8192); + transpose4_ooff(x64+58,xtmpp+29,8192); + transpose4_ooff(x64+60,xtmpp+30,8192); + transpose4_ooff(x64+62,xtmpp+31,8192); + x64+=64; + xtmpp+=32; + } + + idft16384((int16_t*)(xtmp),(int16_t*)ytmp,1); + idft16384((int16_t*)(xtmp+8192),(int16_t*)(ytmp+4096),1); + + + for (i=0; i<4096; i++) { + ibfly2(ytmpp,ytmpp+4096, + y128p,y128p+4096, + tw32768_128p); + tw32768_128p++; + y128p++; + ytmpp++; + } + + if (scale>0) { + y128p = y128; + + for (i=0; i<512; i++) { + y128p[0] = mulhi_int16(y128p[0],ONE_OVER_SQRT2_Q15_128); + y128p[1] = mulhi_int16(y128p[1],ONE_OVER_SQRT2_Q15_128); + y128p[2] = mulhi_int16(y128p[2],ONE_OVER_SQRT2_Q15_128); + y128p[3] = mulhi_int16(y128p[3],ONE_OVER_SQRT2_Q15_128); + y128p[4] = mulhi_int16(y128p[4],ONE_OVER_SQRT2_Q15_128); + y128p[5] = mulhi_int16(y128p[5],ONE_OVER_SQRT2_Q15_128); + y128p[6] = mulhi_int16(y128p[6],ONE_OVER_SQRT2_Q15_128); + y128p[7] = mulhi_int16(y128p[7],ONE_OVER_SQRT2_Q15_128); + y128p[8] = mulhi_int16(y128p[8],ONE_OVER_SQRT2_Q15_128); + y128p[9] = mulhi_int16(y128p[9],ONE_OVER_SQRT2_Q15_128); + y128p[10] = mulhi_int16(y128p[10],ONE_OVER_SQRT2_Q15_128); + y128p[11] = mulhi_int16(y128p[11],ONE_OVER_SQRT2_Q15_128); + y128p[12] = mulhi_int16(y128p[12],ONE_OVER_SQRT2_Q15_128); + y128p[13] = mulhi_int16(y128p[13],ONE_OVER_SQRT2_Q15_128); + y128p[14] = mulhi_int16(y128p[14],ONE_OVER_SQRT2_Q15_128); + y128p[15] = mulhi_int16(y128p[15],ONE_OVER_SQRT2_Q15_128); + y128p+=16; + } + } + + _mm_empty(); + _m_empty(); + +} + +#else // __AVX2__ +void dft32768(int16_t *x,int16_t *y,unsigned char scale) +{ + + simd256_q15_t xtmp[4096],*xtmpp,*x256 = (simd256_q15_t *)x; + simd256_q15_t ytmp[4096],*tw32768_256p=(simd256_q15_t *)tw32768,*y256=(simd256_q15_t *)y,*y256p=(simd256_q15_t *)y; + + simd256_q15_t *ytmpp = &ytmp[0]; + int i; + simd256_q15_t ONE_OVER_SQRT2_Q15_128 = set1_int16_simd256(ONE_OVER_SQRT2_Q15); + + xtmpp = xtmp; + + for (i=0; i<256; i++) { + transpose4_ooff_simd256(x256 ,xtmpp,2048); + transpose4_ooff_simd256(x256+2,xtmpp+1,2048); + transpose4_ooff_simd256(x256+4,xtmpp+2,2048); + transpose4_ooff_simd256(x256+6,xtmpp+3,2048); + transpose4_ooff_simd256(x256+8,xtmpp+4,2048); + transpose4_ooff_simd256(x256+10,xtmpp+5,2048); + transpose4_ooff_simd256(x256+12,xtmpp+6,2048); + transpose4_ooff_simd256(x256+14,xtmpp+7,2048); + transpose4_ooff_simd256(x256+16,xtmpp+8,2048); + transpose4_ooff_simd256(x256+18,xtmpp+9,2048); + transpose4_ooff_simd256(x256+20,xtmpp+10,2048); + transpose4_ooff_simd256(x256+22,xtmpp+11,2048); + transpose4_ooff_simd256(x256+24,xtmpp+12,2048); + transpose4_ooff_simd256(x256+26,xtmpp+13,2048); + transpose4_ooff_simd256(x256+28,xtmpp+14,2048); + transpose4_ooff_simd256(x256+30,xtmpp+15,2048); + transpose4_ooff_simd256(x256+32,xtmpp+16,2048); + transpose4_ooff_simd256(x256+34,xtmpp+17,2048); + transpose4_ooff_simd256(x256+36,xtmpp+18,2048); + transpose4_ooff_simd256(x256+38,xtmpp+19,2048); + transpose4_ooff_simd256(x256+40,xtmpp+20,2048); + transpose4_ooff_simd256(x256+42,xtmpp+21,2048); + transpose4_ooff_simd256(x256+44,xtmpp+22,2048); + transpose4_ooff_simd256(x256+46,xtmpp+23,2048); + transpose4_ooff_simd256(x256+48,xtmpp+24,2048); + transpose4_ooff_simd256(x256+50,xtmpp+25,2048); + transpose4_ooff_simd256(x256+52,xtmpp+26,2048); + transpose4_ooff_simd256(x256+54,xtmpp+27,2048); + transpose4_ooff_simd256(x256+56,xtmpp+28,2048); + transpose4_ooff_simd256(x256+58,xtmpp+29,2048); + transpose4_ooff_simd256(x256+60,xtmpp+30,2048); + transpose4_ooff_simd256(x256+62,xtmpp+31,2048); + x256+=64; + xtmpp+=32; + } + + dft16384((int16_t*)(xtmp),(int16_t*)ytmp,1); + dft16384((int16_t*)(xtmp+2048),(int16_t*)(ytmp+2048),1); + + + for (i=0; i<2048; i++) { + bfly2_256(ytmpp,ytmpp+2048, + y256p,y256p+2048, + tw32768_256p); + tw32768_256p++; + y256p++; + ytmpp++; + } + + if (scale>0) { + y256p = y256; + + for (i=0; i<64; i++) { + y256p[0] = mulhi_int16_simd256(y256p[0],ONE_OVER_SQRT2_Q15_128); + y256p[1] = mulhi_int16_simd256(y256p[1],ONE_OVER_SQRT2_Q15_128); + y256p[2] = mulhi_int16_simd256(y256p[2],ONE_OVER_SQRT2_Q15_128); + y256p[3] = mulhi_int16_simd256(y256p[3],ONE_OVER_SQRT2_Q15_128); + y256p[4] = mulhi_int16_simd256(y256p[4],ONE_OVER_SQRT2_Q15_128); + y256p[5] = mulhi_int16_simd256(y256p[5],ONE_OVER_SQRT2_Q15_128); + y256p[6] = mulhi_int16_simd256(y256p[6],ONE_OVER_SQRT2_Q15_128); + y256p[7] = mulhi_int16_simd256(y256p[7],ONE_OVER_SQRT2_Q15_128); + y256p[8] = mulhi_int16_simd256(y256p[8],ONE_OVER_SQRT2_Q15_128); + y256p[9] = mulhi_int16_simd256(y256p[9],ONE_OVER_SQRT2_Q15_128); + y256p[10] = mulhi_int16_simd256(y256p[10],ONE_OVER_SQRT2_Q15_128); + y256p[11] = mulhi_int16_simd256(y256p[11],ONE_OVER_SQRT2_Q15_128); + y256p[12] = mulhi_int16_simd256(y256p[12],ONE_OVER_SQRT2_Q15_128); + y256p[13] = mulhi_int16_simd256(y256p[13],ONE_OVER_SQRT2_Q15_128); + y256p[14] = mulhi_int16_simd256(y256p[14],ONE_OVER_SQRT2_Q15_128); + y256p[15] = mulhi_int16_simd256(y256p[15],ONE_OVER_SQRT2_Q15_128); + y256p+=16; + } + } + + _mm_empty(); + _m_empty(); + +} + +void idft32768(int16_t *x,int16_t *y,unsigned char scale) +{ + + simd256_q15_t xtmp[4096],*xtmpp,*x256 = (simd256_q15_t *)x; + simd256_q15_t ytmp[4096],*tw32768_256p=(simd256_q15_t *)tw32768,*y256=(simd256_q15_t *)y,*y256p=(simd256_q15_t *)y; + simd256_q15_t *ytmpp = &ytmp[0]; + int i; + simd256_q15_t ONE_OVER_SQRT2_Q15_128 = set1_int16_simd256(ONE_OVER_SQRT2_Q15); + + xtmpp = xtmp; + + for (i=0; i<64; i++) { + transpose4_ooff_simd256(x256 ,xtmpp,2048); + transpose4_ooff_simd256(x256+2,xtmpp+1,2048); + transpose4_ooff_simd256(x256+4,xtmpp+2,2048); + transpose4_ooff_simd256(x256+6,xtmpp+3,2048); + transpose4_ooff_simd256(x256+8,xtmpp+4,2048); + transpose4_ooff_simd256(x256+10,xtmpp+5,2048); + transpose4_ooff_simd256(x256+12,xtmpp+6,2048); + transpose4_ooff_simd256(x256+14,xtmpp+7,2048); + transpose4_ooff_simd256(x256+16,xtmpp+8,2048); + transpose4_ooff_simd256(x256+18,xtmpp+9,2048); + transpose4_ooff_simd256(x256+20,xtmpp+10,2048); + transpose4_ooff_simd256(x256+22,xtmpp+11,2048); + transpose4_ooff_simd256(x256+24,xtmpp+12,2048); + transpose4_ooff_simd256(x256+26,xtmpp+13,2048); + transpose4_ooff_simd256(x256+28,xtmpp+14,2048); + transpose4_ooff_simd256(x256+30,xtmpp+15,2048); + transpose4_ooff_simd256(x256+32,xtmpp+16,2048); + transpose4_ooff_simd256(x256+34,xtmpp+17,2048); + transpose4_ooff_simd256(x256+36,xtmpp+18,2048); + transpose4_ooff_simd256(x256+38,xtmpp+19,2048); + transpose4_ooff_simd256(x256+40,xtmpp+20,2048); + transpose4_ooff_simd256(x256+42,xtmpp+21,2048); + transpose4_ooff_simd256(x256+44,xtmpp+22,2048); + transpose4_ooff_simd256(x256+46,xtmpp+23,2048); + transpose4_ooff_simd256(x256+48,xtmpp+24,2048); + transpose4_ooff_simd256(x256+50,xtmpp+25,2048); + transpose4_ooff_simd256(x256+52,xtmpp+26,2048); + transpose4_ooff_simd256(x256+54,xtmpp+27,2048); + transpose4_ooff_simd256(x256+56,xtmpp+28,2048); + transpose4_ooff_simd256(x256+58,xtmpp+29,2048); + transpose4_ooff_simd256(x256+60,xtmpp+30,2048); + transpose4_ooff_simd256(x256+62,xtmpp+31,2048); + x256+=64; + xtmpp+=32; + } + + idft16384((int16_t*)(xtmp),(int16_t*)ytmp,1); + idft16384((int16_t*)(xtmp+2048),(int16_t*)(ytmp+2048),1); + + + for (i=0; i<2048; i++) { + ibfly2_256(ytmpp,ytmpp+2048, + y256p,y256p+2048, + tw32768_256p); + tw32768_256p++; + y256p++; + ytmpp++; + } + + if (scale>0) { + y256p = y256; + + for (i=0; i<256; i++) { + y256p[0] = mulhi_int16_simd256(y256p[0],ONE_OVER_SQRT2_Q15_128); + y256p[1] = mulhi_int16_simd256(y256p[1],ONE_OVER_SQRT2_Q15_128); + y256p[2] = mulhi_int16_simd256(y256p[2],ONE_OVER_SQRT2_Q15_128); + y256p[3] = mulhi_int16_simd256(y256p[3],ONE_OVER_SQRT2_Q15_128); + y256p[4] = mulhi_int16_simd256(y256p[4],ONE_OVER_SQRT2_Q15_128); + y256p[5] = mulhi_int16_simd256(y256p[5],ONE_OVER_SQRT2_Q15_128); + y256p[6] = mulhi_int16_simd256(y256p[6],ONE_OVER_SQRT2_Q15_128); + y256p[7] = mulhi_int16_simd256(y256p[7],ONE_OVER_SQRT2_Q15_128); + y256p[8] = mulhi_int16_simd256(y256p[8],ONE_OVER_SQRT2_Q15_128); + y256p[9] = mulhi_int16_simd256(y256p[9],ONE_OVER_SQRT2_Q15_128); + y256p[10] = mulhi_int16_simd256(y256p[10],ONE_OVER_SQRT2_Q15_128); + y256p[11] = mulhi_int16_simd256(y256p[11],ONE_OVER_SQRT2_Q15_128); + y256p[12] = mulhi_int16_simd256(y256p[12],ONE_OVER_SQRT2_Q15_128); + y256p[13] = mulhi_int16_simd256(y256p[13],ONE_OVER_SQRT2_Q15_128); + y256p[14] = mulhi_int16_simd256(y256p[14],ONE_OVER_SQRT2_Q15_128); + y256p[15] = mulhi_int16_simd256(y256p[15],ONE_OVER_SQRT2_Q15_128); + y256p+=16; + } + } + + _mm_empty(); + _m_empty(); + +} + + +#endif + + int16_t twa1536[1024],twb1536[1024]; // 512 x 3 @@ -6176,12 +6777,99 @@ int16_t twb49152[32768] __attribute__((aligned(32))); // 16384 x 3 void dft49152(int16_t *input, int16_t *output,uint8_t scale) { - AssertFatal(1==0,"Need to do this ..\n"); + int i,i2,j; + uint32_t tmp[3][16384] __attribute__((aligned(32))); + uint32_t tmpo[3][16384] __attribute__((aligned(32))); + simd_q15_t *y128p=(simd_q15_t*)output; + simd_q15_t ONE_OVER_SQRT3_Q15_128 = set1_int16(ONE_OVER_SQRT3_Q15); + + for (i=0,j=0; i<16384; i++) { + tmp[0][i] = ((uint32_t *)input)[j++]; + tmp[1][i] = ((uint32_t *)input)[j++]; + tmp[2][i] = ((uint32_t *)input)[j++]; + } + + dft16384((int16_t*)(tmp[0]),(int16_t*)(tmpo[0]),1); + dft16384((int16_t*)(tmp[1]),(int16_t*)(tmpo[1]),1); + dft16384((int16_t*)(tmp[2]),(int16_t*)(tmpo[2]),1); + + for (i=0,i2=0; i<32768; i+=8,i2+=4) { + bfly3((simd_q15_t*)(&tmpo[0][i2]),(simd_q15_t*)(&tmpo[1][i2]),((simd_q15_t*)&tmpo[2][i2]), + (simd_q15_t*)(output+i),(simd_q15_t*)(output+32768+i),(simd_q15_t*)(output+65536+i), + (simd_q15_t*)(twa49152+i),(simd_q15_t*)(twb49152+i)); + } + if (scale==1) { + for (i=0; i<768; i++) { + y128p[0] = mulhi_int16(y128p[0],ONE_OVER_SQRT3_Q15_128); + y128p[1] = mulhi_int16(y128p[1],ONE_OVER_SQRT3_Q15_128); + y128p[2] = mulhi_int16(y128p[2],ONE_OVER_SQRT3_Q15_128); + y128p[3] = mulhi_int16(y128p[3],ONE_OVER_SQRT3_Q15_128); + y128p[4] = mulhi_int16(y128p[4],ONE_OVER_SQRT3_Q15_128); + y128p[5] = mulhi_int16(y128p[5],ONE_OVER_SQRT3_Q15_128); + y128p[6] = mulhi_int16(y128p[6],ONE_OVER_SQRT3_Q15_128); + y128p[7] = mulhi_int16(y128p[7],ONE_OVER_SQRT3_Q15_128); + y128p[8] = mulhi_int16(y128p[8],ONE_OVER_SQRT3_Q15_128); + y128p[9] = mulhi_int16(y128p[9],ONE_OVER_SQRT3_Q15_128); + y128p[10] = mulhi_int16(y128p[10],ONE_OVER_SQRT3_Q15_128); + y128p[11] = mulhi_int16(y128p[11],ONE_OVER_SQRT3_Q15_128); + y128p[12] = mulhi_int16(y128p[12],ONE_OVER_SQRT3_Q15_128); + y128p[13] = mulhi_int16(y128p[13],ONE_OVER_SQRT3_Q15_128); + y128p[14] = mulhi_int16(y128p[14],ONE_OVER_SQRT3_Q15_128); + y128p[15] = mulhi_int16(y128p[15],ONE_OVER_SQRT3_Q15_128); + y128p+=16; + } + } + _mm_empty(); + _m_empty(); + } void idft49152(int16_t *input, int16_t *output,uint8_t scale) { - AssertFatal(1==0,"Need to do this ..\n"); + int i,i2,j; + uint32_t tmp[3][16384] __attribute__((aligned(32))); + uint32_t tmpo[3][16384] __attribute__((aligned(32))); + simd_q15_t *y128p=(simd_q15_t*)output; + simd_q15_t ONE_OVER_SQRT3_Q15_128 = set1_int16(ONE_OVER_SQRT3_Q15); + + for (i=0,j=0; i<16384; i++) { + tmp[0][i] = ((uint32_t *)input)[j++]; + tmp[1][i] = ((uint32_t *)input)[j++]; + tmp[2][i] = ((uint32_t *)input)[j++]; + } + + idft16384((int16_t*)(tmp[0]),(int16_t*)(tmpo[0]),1); + idft16384((int16_t*)(tmp[1]),(int16_t*)(tmpo[1]),1); + idft16384((int16_t*)(tmp[2]),(int16_t*)(tmpo[2]),1); + + for (i=0,i2=0; i<32768; i+=8,i2+=4) { + ibfly3((simd_q15_t*)(&tmpo[0][i2]),(simd_q15_t*)(&tmpo[1][i2]),((simd_q15_t*)&tmpo[2][i2]), + (simd_q15_t*)(output+i),(simd_q15_t*)(output+32768+i),(simd_q15_t*)(output+65536+i), + (simd_q15_t*)(twa49152+i),(simd_q15_t*)(twb49152+i)); + } + if (scale==1) { + for (i=0; i<768; i++) { + y128p[0] = mulhi_int16(y128p[0],ONE_OVER_SQRT3_Q15_128); + y128p[1] = mulhi_int16(y128p[1],ONE_OVER_SQRT3_Q15_128); + y128p[2] = mulhi_int16(y128p[2],ONE_OVER_SQRT3_Q15_128); + y128p[3] = mulhi_int16(y128p[3],ONE_OVER_SQRT3_Q15_128); + y128p[4] = mulhi_int16(y128p[4],ONE_OVER_SQRT3_Q15_128); + y128p[5] = mulhi_int16(y128p[5],ONE_OVER_SQRT3_Q15_128); + y128p[6] = mulhi_int16(y128p[6],ONE_OVER_SQRT3_Q15_128); + y128p[7] = mulhi_int16(y128p[7],ONE_OVER_SQRT3_Q15_128); + y128p[8] = mulhi_int16(y128p[8],ONE_OVER_SQRT3_Q15_128); + y128p[9] = mulhi_int16(y128p[9],ONE_OVER_SQRT3_Q15_128); + y128p[10] = mulhi_int16(y128p[10],ONE_OVER_SQRT3_Q15_128); + y128p[11] = mulhi_int16(y128p[11],ONE_OVER_SQRT3_Q15_128); + y128p[12] = mulhi_int16(y128p[12],ONE_OVER_SQRT3_Q15_128); + y128p[13] = mulhi_int16(y128p[13],ONE_OVER_SQRT3_Q15_128); + y128p[14] = mulhi_int16(y128p[14],ONE_OVER_SQRT3_Q15_128); + y128p[15] = mulhi_int16(y128p[15],ONE_OVER_SQRT3_Q15_128); + y128p+=16; + } + } + _mm_empty(); + _m_empty(); } int16_t twa73728[49152] __attribute__((aligned(32))); @@ -6198,17 +6886,104 @@ void idft73728(int16_t *input, int16_t *output,uint8_t scale) { } -int16_t twa98304[49152] __attribute__((aligned(32))); -int16_t twb98304[49152] __attribute__((aligned(32))); +int16_t twa98304[65536] __attribute__((aligned(32))); +int16_t twb98304[65536] __attribute__((aligned(32))); // 32768 x 3 void dft98304(int16_t *input, int16_t *output,uint8_t scale) { - AssertFatal(1==0,"Need to do this ..\n"); + int i,i2,j; + uint32_t tmp[3][32768] __attribute__((aligned(32))); + uint32_t tmpo[3][32768] __attribute__((aligned(32))); + simd_q15_t *y128p=(simd_q15_t*)output; + simd_q15_t ONE_OVER_SQRT3_Q15_128 = set1_int16(ONE_OVER_SQRT3_Q15); + + for (i=0,j=0; i<32768; i++) { + tmp[0][i] = ((uint32_t *)input)[j++]; + tmp[1][i] = ((uint32_t *)input)[j++]; + tmp[2][i] = ((uint32_t *)input)[j++]; + } + + dft32768((int16_t*)(tmp[0]),(int16_t*)(tmpo[0]),1); + dft32768((int16_t*)(tmp[1]),(int16_t*)(tmpo[1]),1); + dft32768((int16_t*)(tmp[2]),(int16_t*)(tmpo[2]),1); + + for (i=0,i2=0; i<65536; i+=8,i2+=4) { + bfly3((simd_q15_t*)(&tmpo[0][i2]),(simd_q15_t*)(&tmpo[1][i2]),((simd_q15_t*)&tmpo[2][i2]), + (simd_q15_t*)(output+i),(simd_q15_t*)(output+65536+i),(simd_q15_t*)(output+131072+i), + (simd_q15_t*)(twa98304+i),(simd_q15_t*)(twb98304+i)); + } + if (scale==1) { + for (i=0; i<1536; i++) { + y128p[0] = mulhi_int16(y128p[0],ONE_OVER_SQRT3_Q15_128); + y128p[1] = mulhi_int16(y128p[1],ONE_OVER_SQRT3_Q15_128); + y128p[2] = mulhi_int16(y128p[2],ONE_OVER_SQRT3_Q15_128); + y128p[3] = mulhi_int16(y128p[3],ONE_OVER_SQRT3_Q15_128); + y128p[4] = mulhi_int16(y128p[4],ONE_OVER_SQRT3_Q15_128); + y128p[5] = mulhi_int16(y128p[5],ONE_OVER_SQRT3_Q15_128); + y128p[6] = mulhi_int16(y128p[6],ONE_OVER_SQRT3_Q15_128); + y128p[7] = mulhi_int16(y128p[7],ONE_OVER_SQRT3_Q15_128); + y128p[8] = mulhi_int16(y128p[8],ONE_OVER_SQRT3_Q15_128); + y128p[9] = mulhi_int16(y128p[9],ONE_OVER_SQRT3_Q15_128); + y128p[10] = mulhi_int16(y128p[10],ONE_OVER_SQRT3_Q15_128); + y128p[11] = mulhi_int16(y128p[11],ONE_OVER_SQRT3_Q15_128); + y128p[12] = mulhi_int16(y128p[12],ONE_OVER_SQRT3_Q15_128); + y128p[13] = mulhi_int16(y128p[13],ONE_OVER_SQRT3_Q15_128); + y128p[14] = mulhi_int16(y128p[14],ONE_OVER_SQRT3_Q15_128); + y128p[15] = mulhi_int16(y128p[15],ONE_OVER_SQRT3_Q15_128); + y128p+=16; + } + } + _mm_empty(); + _m_empty(); + } void idft98304(int16_t *input, int16_t *output,uint8_t scale) { - AssertFatal(1==0,"Need to do this ..\n"); + int i,i2,j; + uint32_t tmp[3][32768] __attribute__((aligned(32))); + uint32_t tmpo[3][32768] __attribute__((aligned(32))); + simd_q15_t *y128p=(simd_q15_t*)output; + simd_q15_t ONE_OVER_SQRT3_Q15_128 = set1_int16(ONE_OVER_SQRT3_Q15); + + for (i=0,j=0; i<32768; i++) { + tmp[0][i] = ((uint32_t *)input)[j++]; + tmp[1][i] = ((uint32_t *)input)[j++]; + tmp[2][i] = ((uint32_t *)input)[j++]; + } + + idft32768((int16_t*)(tmp[0]),(int16_t*)(tmpo[0]),1); + idft32768((int16_t*)(tmp[1]),(int16_t*)(tmpo[1]),1); + idft32768((int16_t*)(tmp[2]),(int16_t*)(tmpo[2]),1); + + for (i=0,i2=0; i<65536; i+=8,i2+=4) { + ibfly3((simd_q15_t*)(&tmpo[0][i2]),(simd_q15_t*)(&tmpo[1][i2]),((simd_q15_t*)&tmpo[2][i2]), + (simd_q15_t*)(output+i),(simd_q15_t*)(output+65536+i),(simd_q15_t*)(output+131072+i), + (simd_q15_t*)(twa98304+i),(simd_q15_t*)(twb98304+i)); + } + if (scale==1) { + for (i=0; i<1536; i++) { + y128p[0] = mulhi_int16(y128p[0],ONE_OVER_SQRT3_Q15_128); + y128p[1] = mulhi_int16(y128p[1],ONE_OVER_SQRT3_Q15_128); + y128p[2] = mulhi_int16(y128p[2],ONE_OVER_SQRT3_Q15_128); + y128p[3] = mulhi_int16(y128p[3],ONE_OVER_SQRT3_Q15_128); + y128p[4] = mulhi_int16(y128p[4],ONE_OVER_SQRT3_Q15_128); + y128p[5] = mulhi_int16(y128p[5],ONE_OVER_SQRT3_Q15_128); + y128p[6] = mulhi_int16(y128p[6],ONE_OVER_SQRT3_Q15_128); + y128p[7] = mulhi_int16(y128p[7],ONE_OVER_SQRT3_Q15_128); + y128p[8] = mulhi_int16(y128p[8],ONE_OVER_SQRT3_Q15_128); + y128p[9] = mulhi_int16(y128p[9],ONE_OVER_SQRT3_Q15_128); + y128p[10] = mulhi_int16(y128p[10],ONE_OVER_SQRT3_Q15_128); + y128p[11] = mulhi_int16(y128p[11],ONE_OVER_SQRT3_Q15_128); + y128p[12] = mulhi_int16(y128p[12],ONE_OVER_SQRT3_Q15_128); + y128p[13] = mulhi_int16(y128p[13],ONE_OVER_SQRT3_Q15_128); + y128p[14] = mulhi_int16(y128p[14],ONE_OVER_SQRT3_Q15_128); + y128p[15] = mulhi_int16(y128p[15],ONE_OVER_SQRT3_Q15_128); + y128p+=16; + } + } + _mm_empty(); + _m_empty(); } @@ -8823,6 +9598,8 @@ int dfts_autoinit(void) init_rad2(2048,tw2048); init_rad4(4096,tw4096); init_rad2(8192,tw8192); + init_rad4(16384,tw16384); + init_rad2(32768,tw32768); init_rad3(1536,twa1536,twb1536); init_rad3(3072,twa3072,twb3072); @@ -8830,6 +9607,9 @@ int dfts_autoinit(void) init_rad3(12288,twa12288,twb12288); init_rad3(18432,twa18432,twb18432); init_rad3(24576,twa24576,twb24576); + init_rad3(49152,twa49152,twb49152); + init_rad3(98304,twa98304,twb98304); + init_rad2_rep(24,tw24); init_rad3_rep(36,twa36,twb36); @@ -8869,6 +9649,7 @@ int dfts_autoinit(void) +#ifndef MR_MAIN void dft(uint8_t sizeidx, int16_t *sigF,int16_t *sig,unsigned char scale_flag){ AssertFatal((sizeidx>=0 && sizeidx<(int)DFT_SIZE_IDXTABLESIZE),"Invalid dft size index %i\n",sizeidx); @@ -8879,6 +9660,7 @@ void idft(uint8_t sizeidx, int16_t *sigF,int16_t *sig,unsigned char scale_flag){ AssertFatal((sizeidx>=0 && sizeidx<(int)IDFT_SIZE_IDXTABLESIZE),"Invalid idft size index %i\n",sizeidx); idft_ftab[sizeidx](sigF,sig,scale_flag); }; +#endif /*---------------------------------------------------------------------------------------*/ @@ -9049,9 +9831,9 @@ int main(int argc, char**argv) time_stats_t ts; #ifdef __AVX2__ - simd256_q15_t x[4096],x2[4096],y[4096],tw0,tw1,tw2,tw3; + simd256_q15_t x[16384],x2[16384],y[16384],tw0,tw1,tw2,tw3; #else - simd_q15_t x[8192],y[8192],tw0,tw1,tw2,tw3; + simd_q15_t x[32768],y[32768],tw0,tw1,tw2,tw3; #endif int i; simd_q15_t *x128=(simd_q15_t*)x,*y128=(simd_q15_t*)y; @@ -9613,10 +10395,34 @@ int main(int argc, char**argv) stop_meas(&ts); } - printf("\n\n1536-point(%f cycles)\n",(double)ts.diff/(double)ts.trials); + printf("\n\n8192-point(%f cycles)\n",(double)ts.diff/(double)ts.trials); LOG_M("y8192.m","y8192",y,8192,1,1); LOG_M("x8192.m","x8192",x,8192,1,1); + memset((void*)x,0,16384*sizeof(int32_t)); + for (i=2;i<9602;i++) { + if ((taus() & 1)==0) + ((int16_t*)x)[i] = 364; + else + ((int16_t*)x)[i] = -364; + } + for (i=2*(16384-4800);i<32768;i++) { + if ((taus() & 1)==0) + ((int16_t*)x)[i] = 364; + else + ((int16_t*)x)[i] = -364; + } + reset_meas(&ts); + for (i=0; i<10000; i++) { + start_meas(&ts); + dft16384((int16_t *)x,(int16_t *)y,1); + stop_meas(&ts); + } + + printf("\n\n16384-point(%f cycles)\n",(double)ts.diff/(double)ts.trials); + LOG_M("y16384.m","y16384",y,16384,1,1); + LOG_M("x16384.m","x16384",x,16384,1,1); + memset((void*)x,0,1536*sizeof(int32_t)); for (i=2;i<1202;i++) { if ((taus() & 1)==0) @@ -9765,6 +10571,30 @@ int main(int argc, char**argv) LOG_M("y24576.m","y24576",y,24576,1,1); LOG_M("x24576.m","x24576",x,24576,1,1); + memset((void*)x,0,49152*sizeof(int32_t)); + for (i=2;i<28402;i++) { + if ((taus() & 1)==0) + ((int16_t*)x)[i] = 364; + else + ((int16_t*)x)[i] = -364; + } + for (i=2*(49152-14400);i<98304;i++) { + if ((taus() & 1)==0) + ((int16_t*)x)[i] = 364; + else + ((int16_t*)x)[i] = -364; + } + reset_meas(&ts); + for (i=0; i<10000; i++) { + start_meas(&ts); + idft49152((int16_t *)x,(int16_t *)y,1); + stop_meas(&ts); + } + + printf("\n\n49152-point(%f cycles)\n",(double)ts.diff/(double)ts.trials); + LOG_M("y49152.m","y49152",y,49152,1,1); + LOG_M("x49152.m","x49152",x,49152,1,1); + /* int dftsizes[33]={24,36,48,60,72,96,108,120,144,180,192,216,240,288,300,324,360,384,432,480,540,576,600,648,720,768,864,900,960,972,1080,1152,1200}; void (*dft)(int16_t *x,int16_t *y,uint8_t scale)[33] = {dft24,dft36,dft48,dft60,dft72,dft96,dft108,dft120,dft144,dft180,dft192,dft216,dft240,dft288,dft300,dft324,dft360,dft384,dft432,dft480,dft540,dft576,dft600,dft648,dft720,dft768,dft864,dft900,dft960,dft972,dft1080,dft1152,dft1200}; for (int n=0;n<33;n++) { @@ -9797,7 +10627,7 @@ int main(int argc, char**argv) LOG_M(ystr,ystr2,y,dftsizes[n]*4,1,1); LOG_M(xstr,xstr2,x,dftsizes[n]*4,1,1); } - + */ return(0); } diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index 10bdd23ef2..ec3fce08d8 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -89,7 +89,7 @@ int main(int argc, char **argv){ int i, aa, aarx, **txdata, trial, n_frames = 1, prach_start, rx_prach_start; //, ntrials=1; int N_RB_UL = 106, delay = 0, NCS_config = 13, rootSequenceIndex = 1, threequarter_fs = 0, mu = 1, fd_occasion = 0, loglvl = OAILOG_INFO, numRA = 0, prachStartSymbol = 0; uint8_t snr1set = 0, ue_speed1set = 0, transmission_mode = 1, n_tx = 1, n_rx = 1, awgn_flag = 0, msg1_frequencystart = 0, num_prach_fd_occasions = 1, prach_format; - uint8_t frame = 1, subframe = 19, config_index = 98, prach_sequence_length = 1, num_root_sequences = 16, restrictedSetConfig = 0, N_dur, N_t_slot, start_symbol; + uint8_t frame = 1, subframe = 9, slot=19, config_index = 98, prach_sequence_length = 1, num_root_sequences = 16, restrictedSetConfig = 0, N_dur, N_t_slot, start_symbol; uint16_t Nid_cell = 0, preamble_tx = 0, preamble_delay, format, format0, format1; uint32_t tx_lev = 10000, prach_errors = 0, samp_count; //,tx_lev_dB; uint64_t SSB_positions = 0x01, absoluteFrequencyPointA = 640000; @@ -118,7 +118,7 @@ int main(int argc, char **argv){ randominit(0); - while ((c = getopt (argc, argv, "hHaA:Cr:p:g:n:s:S:t:x:y:v:V:z:N:F:d:Z:L:R:E")) != -1) { + while ((c = getopt (argc, argv, "hHaA:Cc:r:p:g:n:s:S:t:x:y:v:V:z:N:F:d:Z:L:R:E")) != -1) { switch (c) { case 'a': printf("Running AWGN simulation\n"); @@ -127,6 +127,10 @@ int main(int argc, char **argv){ //ntrials=1; break; + case 'c': + config_index = atoi(optarg); + break; + case 'd': delay = atoi(optarg); break; @@ -313,6 +317,11 @@ int main(int argc, char **argv){ } } + + if (config_index<67) { prach_sequence_length=0; slot = subframe*2; } + + printf("Config_index %d, prach_sequence_length %d\n",config_index,prach_sequence_length); + // Configure log logInit(); set_glog(loglvl); @@ -373,11 +382,11 @@ int main(int argc, char **argv){ gNB->gNB_config.prach_config.num_prach_fd_occasions.value = num_prach_fd_occasions; gNB->gNB_config.prach_config.num_prach_fd_occasions_list = (nfapi_nr_num_prach_fd_occasions_t *) malloc(num_prach_fd_occasions*sizeof(nfapi_nr_num_prach_fd_occasions_t)); - gNB->proc.slot_rx = subframe; + gNB->proc.slot_rx = slot; get_nr_prach_info_from_index(config_index, (int)frame, - (int)subframe, + (int)slot, absoluteFrequencyPointA, mu, frame_parms->frame_type, @@ -562,7 +571,7 @@ int main(int argc, char **argv){ UE_nr_rxtx_proc_t proc={0}; proc.frame_tx = frame; - proc.nr_tti_tx = subframe; + proc.nr_tti_tx = slot; nr_ue_prach_procedures(UE,&proc,0,0); /* tx_lev_dB not used later, no need to set */ @@ -571,19 +580,19 @@ int main(int argc, char **argv){ if (mu == 0) samp_count = frame_parms->samples_per_subframe; else - samp_count = (subframe%(frame_parms->slots_per_subframe/2)) ? frame_parms->samples_per_slotN0 : frame_parms->samples_per_slot0; + samp_count = ((slot)%(frame_parms->slots_per_subframe/2)) ? frame_parms->samples_per_slotN0 : frame_parms->samples_per_slot0; - prach_start = subframe*samp_count - UE->N_TA_offset; + prach_start = slot*samp_count - UE->N_TA_offset; #ifdef NR_PRACH_DEBUG - LOG_M("txsig0.m", "txs0", &txdata[0][prach_start], samp_count, 1, 1); + LOG_M("txsig0.m", "txs0", &txdata[0][prach_start], frame_parms->samples_per_subframe, 1, 1); //LOG_M("txsig1.m","txs1", txdata[1],FRAME_LENGTH_COMPLEX_SAMPLES,1,1); #endif // multipath channel // dump_nr_prach_config(&gNB->frame_parms,subframe); - for (i = 0; i < samp_count<<1; i++) { + for (i = 0; i < frame_parms->samples_per_subframe<<1; i++) { for (aa=0; aa<1; aa++) { if (awgn_flag == 0) { s_re[aa][i] = ((double)(((short *)&txdata[aa][prach_start]))[(i<<1)]); @@ -618,7 +627,10 @@ int main(int argc, char **argv){ ue_speed1 = ue_speed0 + 50; } - rx_prach_start = subframe*frame_parms->get_samples_per_slot(subframe,frame_parms); + rx_prach_start = slot*frame_parms->get_samples_per_slot(slot,frame_parms); + if (n_frames==1) printf("slot %d, rx_prach_start %d\n",slot,rx_prach_start); + uint16_t preamble_rx, preamble_energy, N_ZC; + N_ZC = prach_sequence_length == 0 ? 839 : 139; for (SNR=snr0; SNRget_samples_per_slot(subframe,frame_parms); i++) { + for (i = 0; i< frame_parms->samples_per_subframe; i++) { for (aa = 0; aa < frame_parms->nb_antennas_rx; aa++) { - ((short*) &gNB->common_vars.rxdata[aa][rx_prach_start])[2*i] = (short) (.167*(r_re[aa][i] +sqrt(sigma2/2)*gaussdouble(0.0,1.0))); - ((short*) &gNB->common_vars.rxdata[aa][rx_prach_start])[2*i+1] = (short) (.167*(r_im[aa][i] + (iqim*r_re[aa][i]) + sqrt(sigma2/2)*gaussdouble(0.0,1.0))); + ((short*) &ru->common.rxdata[aa][rx_prach_start])[2*i] = (short) (.167*(r_re[aa][i] +sqrt(sigma2/2)*gaussdouble(0.0,1.0))); + ((short*) &ru->common.rxdata[aa][rx_prach_start])[2*i+1] = (short) (.167*(r_im[aa][i] + (iqim*r_re[aa][i]) + sqrt(sigma2/2)*gaussdouble(0.0,1.0))); } } - rx_nr_prach_ru(ru, prach_format, numRA, prachStartSymbol, frame, subframe); + rx_nr_prach_ru(ru, prach_format, numRA, prachStartSymbol, frame, slot); gNB->prach_vars.rxsigF = ru->prach_rxsigF; rx_nr_prach(gNB, prach_pdu, frame, subframe, &preamble_rx, &preamble_energy, &preamble_delay); - printf(" preamble_energy %d preamble_rx %d preamble_tx %d \n", preamble_energy, preamble_rx, preamble_tx); + // printf(" preamble_energy %d preamble_rx %d preamble_tx %d \n", preamble_energy, preamble_rx, preamble_tx); if (preamble_rx != preamble_tx) prach_errors++; diff --git a/openair1/SIMULATION/TOOLS/taus.c b/openair1/SIMULATION/TOOLS/taus.c index 5fe0ce4d78..cdd4aebec3 100644 --- a/openair1/SIMULATION/TOOLS/taus.c +++ b/openair1/SIMULATION/TOOLS/taus.c @@ -21,7 +21,8 @@ #include #include -#include "SIMULATION/TOOLS/sim.h" +//#include "SIMULATION/TOOLS/sim.h" + unsigned int s0, s1, s2, b; diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 5ac4de0280..5adcf42560 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -46,6 +46,7 @@ uint16_t NCS_restricted_TypeB_delta_f_RA_5[14] = {36,57,60,63,65,68,71,77,81,8 uint16_t NCS_unrestricted_delta_f_RA_15[16] = {0,2,4,6,8,10,12,13,15,17,19,23,27,34,46,69}; const char *prachfmt[]={"A1","A2","A3","B1","B2","B3","B4","C0","C2"}; +const char *prachfmt03[]={"0","1","2","3"}; uint16_t get_NCS(uint8_t index, uint16_t format0, uint8_t restricted_set_config) { From b0ff2cef54abb72188a595b12a8fdd91dd53ded2 Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Wed, 20 May 2020 15:05:33 +0200 Subject: [PATCH 229/240] rearranged function to prepare pucch scheduling --- openair2/LAYER2/NR_MAC_gNB/config.c | 3 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 33 +++-- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 113 ++++-------------- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 2 +- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 1 - 5 files changed, 47 insertions(+), 105 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 1e5a6bed29..36b81927f8 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -290,8 +290,7 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, NR_ServingCellConfigComm scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots, scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols, scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots, - scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols - ); + scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols); if (return_tdd !=0){ LOG_E(PHY,"TDD configuration can not be done\n"); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 21bf6b1172..b36e4af9eb 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -305,12 +305,14 @@ void nr_schedule_pucch(int Mod_idP, NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_id-1]; nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[Mod_idP]->UL_tti_req[0]; - NR_sched_pucch *curr_pucch = UE_list->UE_sched_ctrl[UE_id].sched_pucch; - NR_sched_pucch *temp_pucch; - int release_pucch = 0; + NR_sched_pucch *curr_pucch; + int nr_ulmix_slots = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; + if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols!=0) + nr_ulmix_slots++; - if (curr_pucch != NULL) { - if ((frameP == curr_pucch->frame) && (slotP == curr_pucch->ul_slot)) { + for (int k=0; kUE_sched_ctrl[UE_id].sched_pucch[k]; + if ((curr_pucch->dai_c > 0) && (frameP == curr_pucch->frame) && (slotP == curr_pucch->ul_slot)) { UL_tti_req->SFN = frameP; UL_tti_req->Slot = slotP; UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE; @@ -331,16 +333,9 @@ void nr_schedule_pucch(int Mod_idP, O_ack, SR_flag); - release_pucch = 1; + curr_pucch->dai_c = 0; } } - - if (release_pucch) { - temp_pucch = UE_list->UE_sched_ctrl[UE_id].sched_pucch; - UE_list->UE_sched_ctrl[UE_id].sched_pucch = UE_list->UE_sched_ctrl[UE_id].sched_pucch->next_sched_pucch; - free(temp_pucch); - } - } bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot){ @@ -378,6 +373,18 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; int num_slots_per_tdd = (nr_slots_per_frame[*scc->ssbSubcarrierSpacing])>>(7-scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity); + int nr_ulmix_slots = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; + if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols!=0) + nr_ulmix_slots++; + + if (slot_txP == 0) { + for (int k=0; kUE_sched_ctrl[UE_id].sched_pucch[k], + 0, + sizeof(NR_sched_pucch)); + } + } + start_meas(&RC.nrmac[module_idP]->eNB_scheduler); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_IN); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 4df24d7a16..2a90fc26e9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -1330,6 +1330,11 @@ int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP){ int UE_id; int i; NR_UE_list_t *UE_list = &RC.nrmac[mod_idP]->UE_list; + NR_COMMON_channels_t *cc = RC.nrmac[mod_idP]->common_channels; + NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; + int num_slots_ul = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; + if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols>0) + num_slots_ul++; LOG_I(MAC, "[gNB %d] Adding UE with rnti %x (next avail %d, num_UEs %d)\n", mod_idP, rntiP, @@ -1348,6 +1353,7 @@ int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP){ memset((void *) &UE_list->UE_sched_ctrl[UE_id], 0, sizeof(NR_UE_sched_ctrl_t)); + UE_list->UE_sched_ctrl[UE_id].sched_pucch = (NR_sched_pucch *)malloc(num_slots_ul*sizeof(NR_sched_pucch)); LOG_I(MAC, "gNB %d] Add NR UE_id %d : rnti %x\n", mod_idP, UE_id, @@ -1420,15 +1426,13 @@ void nr_update_pucch_scheduling(int Mod_idP, frame_t frameP, sub_frame_t slotP, int slots_per_tdd, - NR_sched_pucch *sched_pucch) { + NR_sched_pucch *curr_pucch) { NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon; NR_UE_list_t *UE_list = &RC.nrmac[Mod_idP]->UE_list; - int first_ul_slot_tdd,k; - NR_sched_pucch *curr_pucch; + int first_ul_slot_tdd,k,i; uint8_t pdsch_to_harq_feedback[8]; int found = 0; - int i = 0; int nr_ulmix_slots = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots; if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols!=0) nr_ulmix_slots++; @@ -1437,101 +1441,34 @@ void nr_update_pucch_scheduling(int Mod_idP, NR_SearchSpace__searchSpaceType_PR ss_type = NR_SearchSpace__searchSpaceType_PR_ue_Specific; get_pdsch_to_harq_feedback(Mod_idP,UE_id,ss_type,pdsch_to_harq_feedback); - // if the list of pucch to be scheduled is empty - if (UE_list->UE_sched_ctrl[UE_id].sched_pucch == NULL) { - sched_pucch->frame = frameP; - sched_pucch->next_sched_pucch = NULL; - sched_pucch->dai_c = 1; - sched_pucch->resource_indicator = 0; // in phytest with only 1 UE we are using just the 1st resource - if ( nr_ulmix_slots > 0 ) { + // for each possible ul or mixed slot + for (k=0; kUE_sched_ctrl[UE_id].sched_pucch[k]; + // if there is free room in current pucch structure + if (curr_pucch->dai_cframe = frameP; + curr_pucch->dai_c++; + curr_pucch->resource_indicator = 0; // in phytest with only 1 UE we are using just the 1st resource // first pucch occasion in first UL or MIXED slot first_ul_slot_tdd = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots; - for (k=0; kul_slot = first_ul_slot_tdd + k + (slotP - (slotP % slots_per_tdd)); - sched_pucch->timing_indicator = i; // index in the list of timing indicators - } - else - AssertFatal(1==0,"No Uplink slot available in accordance to allowed timing indicator\n"); - } - else - AssertFatal(1==0,"No Uplink Slots in this Frame\n"); - - UE_list->UE_sched_ctrl[UE_id].sched_pucch = sched_pucch; - } - else { // to be tested - curr_pucch = UE_list->UE_sched_ctrl[UE_id].sched_pucch; - if (curr_pucch->dai_cul_slot % slots_per_tdd)-(slotP % slots_per_tdd)) + i = 0; + while (i<8 && found == 0) { // look if timing indicator is among allowed values + if (pdsch_to_harq_feedback[i]==(first_ul_slot_tdd+k)-(slotP % slots_per_tdd)) found = 1; if (found == 0) i++; } - if (found == 1) { // scheduling this harq-ack in current pucch - curr_pucch->dai_c = 1 + curr_pucch->dai_c; - memcpy(sched_pucch,curr_pucch,sizeof(NR_sched_pucch)); - sched_pucch->timing_indicator = i; + if (found == 1) { + // computing slot in which pucch is scheduled + curr_pucch->ul_slot = first_ul_slot_tdd + k + (slotP - (slotP % slots_per_tdd)); + curr_pucch->timing_indicator = i; // index in the list of timing indicators return; } } - if (curr_pucch->dai_c==MAX_ACK_BITS || found == 0) { // if current pucch is full or no timing indicator allowed - // look for pucch occasions in other UL of mixed slots - for (k=scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots; kul_slot % slots_per_tdd)) { // skip current scheduled slot (already checked) - i = 0; - while (i<8 && found == 0) { // look if timing indicator is among allowed values - if (pdsch_to_harq_feedback[i]==k-(slotP % slots_per_tdd)) - found = 1; - if (found == 0) i++; - } - if (found == 1) { - if (k<(curr_pucch->ul_slot % slots_per_tdd)) { // we need to add a pucch occasion before current pucch - sched_pucch->frame = frameP; - sched_pucch->ul_slot = k + (slotP - (slotP % slots_per_tdd)); - sched_pucch->next_sched_pucch = curr_pucch; - sched_pucch->dai_c = 1; - sched_pucch->resource_indicator = 0; // in phytest with only 1 UE we are using just the 1st resource - sched_pucch->timing_indicator = i; - UE_list->UE_sched_ctrl[UE_id].sched_pucch = sched_pucch; - } - else { - while (curr_pucch->next_sched_pucch != NULL && k!=(curr_pucch->ul_slot % slots_per_tdd)) - curr_pucch = curr_pucch->next_sched_pucch; - if (curr_pucch == NULL) { // creating a new item in the list - sched_pucch->frame = frameP; - sched_pucch->next_sched_pucch = NULL; - sched_pucch->dai_c = 1; - sched_pucch->timing_indicator = i; - sched_pucch->resource_indicator = 0; // in phytest with only 1 UE we are using just the 1st resource - sched_pucch->ul_slot = k + (slotP - (slotP % slots_per_tdd)); - curr_pucch->next_sched_pucch = (NR_sched_pucch*) malloc(sizeof(NR_sched_pucch)); - curr_pucch->next_sched_pucch = sched_pucch; - } - else { - if (curr_pucch->dai_c==MAX_ACK_BITS) - found = 0; // if pucch at index k is already full we have to find a new one in a following occasion - else { // scheduling this harq-ack in current pucch - sched_pucch = curr_pucch; - sched_pucch->dai_c = 1 + sched_pucch->dai_c; - sched_pucch->timing_indicator = i; - } - } - } - } - } - } - } } + AssertFatal(1==0,"No Uplink slot available in accordance to allowed timing indicator\n"); } + void find_monitoring_periodicity_offset_common(NR_SearchSpace_t *ss, uint16_t *slot_period, uint16_t *offset) { diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index fc50a4d239..6190f42976 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -157,7 +157,7 @@ void nr_update_pucch_scheduling(int Mod_idP, frame_t frameP, sub_frame_t slotP, int slots_per_tdd, - NR_sched_pucch *sched_pucch); + NR_sched_pucch *curr_pucch); void get_pdsch_to_harq_feedback(int Mod_idP, int UE_id, diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 3d6c9fc58e..aba5908aa5 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -185,7 +185,6 @@ typedef struct NR_sched_pucch { uint8_t dai_c; uint8_t timing_indicator; uint8_t resource_indicator; - struct NR_sched_pucch *next_sched_pucch; } NR_sched_pucch; typedef struct NR_UE_harq { From 2f4f90ba24e907eba2f2a4c609e1ac51b0b683ff Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Wed, 20 May 2020 15:49:43 +0200 Subject: [PATCH 230/240] bugfix --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 10 +++++----- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 4 +++- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index b36e4af9eb..ee70c9617b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -361,7 +361,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, int UE_id; uint64_t *dlsch_in_slot_bitmap=NULL; uint64_t *ulsch_in_slot_bitmap=NULL; - NR_sched_pucch *pucch_sched = (NR_sched_pucch*) malloc(sizeof(NR_sched_pucch)); + int pucch_sched; UE_id=0; int bwp_id = 1; @@ -467,16 +467,16 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, // Phytest scheduling if (get_softmodem_params()->phy_test && (is_xlsch_in_slot(*dlsch_in_slot_bitmap,slot_txP%num_slots_per_tdd))) { - nr_update_pucch_scheduling(module_idP, UE_id, frame_txP, slot_txP, num_slots_per_tdd,pucch_sched); - nr_schedule_uss_dlsch_phytest(module_idP, frame_txP, slot_txP, pucch_sched, NULL); + nr_update_pucch_scheduling(module_idP, UE_id, frame_txP, slot_txP, num_slots_per_tdd,&pucch_sched); + nr_schedule_uss_dlsch_phytest(module_idP, frame_txP, slot_txP, &UE_list->UE_sched_ctrl[UE_id].sched_pucch[pucch_sched], NULL); // resetting ta flag gNB->ta_len = 0; } // Test DL scheduling if (get_softmodem_params()->phy_test == 0 && slot_txP == 1 && UE_list->fiveG_connected[UE_id]) { - nr_update_pucch_scheduling(module_idP, UE_id, frame_txP, slot_txP, num_slots_per_tdd,pucch_sched); - nr_schedule_uss_dlsch_phytest(module_idP, frame_txP, slot_txP, pucch_sched, NULL); + nr_update_pucch_scheduling(module_idP, UE_id, frame_txP, slot_txP, num_slots_per_tdd,&pucch_sched); + nr_schedule_uss_dlsch_phytest(module_idP, frame_txP, slot_txP, &UE_list->UE_sched_ctrl[UE_id].sched_pucch[pucch_sched], NULL); // resetting ta flag gNB->ta_len = 0; UE_list->fiveG_connected[UE_id] = false; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 2a90fc26e9..fa1e860c57 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -1426,10 +1426,11 @@ void nr_update_pucch_scheduling(int Mod_idP, frame_t frameP, sub_frame_t slotP, int slots_per_tdd, - NR_sched_pucch *curr_pucch) { + int *pucch_id) { NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon; NR_UE_list_t *UE_list = &RC.nrmac[Mod_idP]->UE_list; + NR_sched_pucch *curr_pucch; int first_ul_slot_tdd,k,i; uint8_t pdsch_to_harq_feedback[8]; int found = 0; @@ -1461,6 +1462,7 @@ void nr_update_pucch_scheduling(int Mod_idP, // computing slot in which pucch is scheduled curr_pucch->ul_slot = first_ul_slot_tdd + k + (slotP - (slotP % slots_per_tdd)); curr_pucch->timing_indicator = i; // index in the list of timing indicators + *pucch_id = k; return; } } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 6190f42976..4e29adf978 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -157,7 +157,7 @@ void nr_update_pucch_scheduling(int Mod_idP, frame_t frameP, sub_frame_t slotP, int slots_per_tdd, - NR_sched_pucch *curr_pucch); + int *pucch_id); void get_pdsch_to_harq_feedback(int Mod_idP, int UE_id, From 8f8894d76466ff6947d33f11b8a46906bf5efa7d Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 21 May 2020 23:02:08 +0200 Subject: [PATCH 231/240] suppressed some LOG_M that were killing real-time. --- openair1/PHY/NR_TRANSPORT/nr_prach.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c index 52ed4a5f19..2200768f47 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c @@ -283,7 +283,6 @@ void rx_nr_prach_ru(RU_t *ru, if (prachFormat == 0 || prachFormat == 1 || prachFormat == 2) { dftlen=49152; dft(DFT_49152,prach2,rxsigF[aa],1); - LOG_M("prach_rxsigF.m","prach_rxF0",rxsigF[aa],49152,1,1); } if (prachFormat == 1 || prachFormat == 2) { dft(DFT_49152,prach2+98304,rxsigF[aa]+98304,1); @@ -750,10 +749,10 @@ void rx_nr_prach(PHY_VARS_gNB *gNB, prach_ifft[i] += ((int32_t)prach_ifft_tmp[i<<1]*(int32_t)prach_ifft_tmp[(i<<1)] + (int32_t)prach_ifft_tmp[1+(i<<1)]*(int32_t)prach_ifft_tmp[1+(i<<1)])>>10; } - // if (LOG_DUMPFLAG(PRACH)) { + if (LOG_DUMPFLAG(PRACH)) { if (aa==0) LOG_M("prach_rxF_comp0.m","prach_rxF_comp0",prachF,1024,1,1); if (aa==1) LOG_M("prach_rxF_comp1.m","prach_rxF_comp1",prachF,1024,1,1); - // } + } }// antennas_rx } // new dft From eb5a7a9ab1e9728954bfdf654797adb6b36535cf Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Fri, 22 May 2020 12:41:28 +0200 Subject: [PATCH 232/240] added harq handling in gnb mac --- openair1/PHY/NR_TRANSPORT/nr_dci_tools.c | 3 +- openair1/PHY/NR_TRANSPORT/nr_dlsch.c | 2 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 2 + .../LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 8 ++-- openair2/LAYER2/NR_MAC_gNB/main.c | 4 ++ openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 2 + openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 39 ++++++++++++++++++- 7 files changed, 53 insertions(+), 7 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c index ec5aee3c8a..96e370eb97 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c @@ -219,7 +219,8 @@ void nr_fill_dci(PHY_VARS_gNB *gNB, } dlsch = gNB->dlsch[dlsch_id][0]; - int harq_pid = 0;//extract_harq_pid(i,pdu_rel15); + int num_slots_tdd = (gNB->frame_params.p_tdd_UL_DL_Configuration->dl_UL_TransmissionPeriodicity/10000) * gNB->frame_params.slots_per_frame; + int harq_pid = slot % num_slots_tdd; dlsch->slot_tx[slot] = 1; dlsch->harq_ids[frame%2][slot] = harq_pid; diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index 8324508361..78d6619d6b 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -126,7 +126,7 @@ uint8_t nr_generate_pdsch(NR_gNB_DLSCH_t *dlsch, time_stats_t *dlsch_interleaving_stats, time_stats_t *dlsch_segmentation_stats) { - int harq_pid = 0; + int harq_pid = dlsch->harq_ids[frame%2][slot]; NR_DL_gNB_HARQ_t *harq = dlsch->harq_processes[harq_pid]; nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15; uint32_t scrambled_output[NR_MAX_NB_CODEWORDS][NR_MAX_PDSCH_ENCODED_LENGTH>>5]; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 21bf6b1172..79e616b6eb 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -461,6 +461,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, // Phytest scheduling if (get_softmodem_params()->phy_test && (is_xlsch_in_slot(*dlsch_in_slot_bitmap,slot_txP%num_slots_per_tdd))) { nr_update_pucch_scheduling(module_idP, UE_id, frame_txP, slot_txP, num_slots_per_tdd,pucch_sched); + ue_sched_ctl->current_harq_pid = slot_txP % num_slots_per_tdd; nr_schedule_uss_dlsch_phytest(module_idP, frame_txP, slot_txP, pucch_sched, NULL); // resetting ta flag gNB->ta_len = 0; @@ -469,6 +470,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, // Test DL scheduling if (get_softmodem_params()->phy_test == 0 && slot_txP == 1 && UE_list->fiveG_connected[UE_id]) { nr_update_pucch_scheduling(module_idP, UE_id, frame_txP, slot_txP, num_slots_per_tdd,pucch_sched); + ue_sched_ctl->current_harq_pid = slot_txP % num_slots_per_tdd; nr_schedule_uss_dlsch_phytest(module_idP, frame_txP, slot_txP, pucch_sched, NULL); // resetting ta flag gNB->ta_len = 0; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 3b73db4c97..bc435ec047 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -309,11 +309,12 @@ int configure_fapi_dl_pdu(int Mod_idP, pdsch_pdu_rel15->NrOfCodewords = 1; int mcs = (mcsIndex!=NULL) ? *mcsIndex : 9; + int current_harq_pid = UE_list->UE_sched_ctrl[UE_id].current_harq_pid; pdsch_pdu_rel15->targetCodeRate[0] = nr_get_code_rate_dl(mcs,0); pdsch_pdu_rel15->qamModOrder[0] = 2; pdsch_pdu_rel15->mcsIndex[0] = mcs; pdsch_pdu_rel15->mcsTable[0] = 0; - pdsch_pdu_rel15->rvIndex[0] = UE_list->UE_sched_ctrl[UE_id].harq_processes[0].round; + pdsch_pdu_rel15->rvIndex[0] = UE_list->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].round; pdsch_pdu_rel15->dataScramblingId = *scc->physCellId; pdsch_pdu_rel15->nrOfLayers = 1; pdsch_pdu_rel15->transmissionScheme = 0; @@ -365,8 +366,8 @@ int configure_fapi_dl_pdu(int Mod_idP, dci_pdu_rel15[0].mcs = pdsch_pdu_rel15->mcsIndex[0]; dci_pdu_rel15[0].rv = pdsch_pdu_rel15->rvIndex[0]; // harq pid - dci_pdu_rel15[0].harq_pid = 0; - dci_pdu_rel15[0].ndi = UE_list->UE_sched_ctrl[UE_id].harq_processes[0].ndi; + dci_pdu_rel15[0].harq_pid = current_harq_pid; + dci_pdu_rel15[0].ndi = UE_list->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].ndi; // DAI dci_pdu_rel15[0].dai[0].val = (pucch_sched->dai_c-1)&3; @@ -376,6 +377,7 @@ int configure_fapi_dl_pdu(int Mod_idP, dci_pdu_rel15[0].pucch_resource_indicator = pucch_sched->resource_indicator; // PDSCH to HARQ TI dci_pdu_rel15[0].pdsch_to_harq_feedback_timing_indicator.val = pucch_sched->timing_indicator; + UE_list->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].feedback_slot = pucch_sched->ul_slot; // antenna ports dci_pdu_rel15[0].antenna_ports.val = 0; // nb of cdm groups w/o data 1 and dmrs port 0 diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index d38a251a2b..669bc1cd5a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -113,6 +113,10 @@ void mac_top_init_gNB(void) UE_list->next[list_el] = list_el + 1; UE_list->next_ul[list_el] = list_el + 1; UE_list->active[list_el] = FALSE; + for (int list_harq = 0; list_harq < NR_MAX_NB_HARQ_PROCESSES; list_harq++) { + UE_list->UE_sched_ctrl[list_el].harq_processes[list_harq].round = 0; + UE_list->UE_sched_ctrl[list_el].harq_processes[list_harq].ndi = 0; + } } UE_list->next[list_el] = -1; diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 3d6c9fc58e..82463e61f4 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -191,6 +191,7 @@ typedef struct NR_sched_pucch { typedef struct NR_UE_harq { uint8_t ndi; uint8_t round; + uint16_t feedback_slot; } NR_UE_harq_t; /*! \brief scheduling control information set through an API */ @@ -200,6 +201,7 @@ typedef struct { NR_sched_pucch *sched_pucch; uint16_t ta_timer; int16_t ta_update; + uint8_t current_harq_pid; NR_UE_harq_t harq_processes[NR_MAX_NB_HARQ_PROCESSES]; } NR_UE_sched_ctrl_t; diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index f347a33581..797499c990 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -76,8 +76,43 @@ void handle_nr_rach(NR_UL_IND_t *UL_info) { } -void handle_nr_uci(NR_UL_IND_t *UL_info) { +void handle_nr_uci(NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_crtl) { // TODO + int max_harq_rounds = 4; // TODO define macro + int num_ucis = UL_info->uci_ind.num_ucis; + nfapi_nr_uci_t *uci_list = UL_info->uci_ind.uci_list; + + for (int i = 0; i < num_ucis; i++) { + switch (uci_list[i].pdu_type) { + case NFAPI_NR_UCI_PDCCH_PDU_TYPE: break; + + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: + nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &uci_list[i].pucch_pdu_format_0_1; + // handle harq + int harq_idx_s = 0; + // iterate over received harq bits + for (int harq_bit = 0; harq_bit < uci_pdu->harq->num_harq; harq_bit++) { + // search for the right harq process + for (int harq_idx = harq_idx_s; harq_idx < NR_MAX_NB_HARQ_PROCESSES-1; harq_idx++) { + if ((UL_info->slot-1) == sched_ctrl->harq_processes[harq_idx].feedback_slot) { + if (uci_pdu->harq->harq_list[harq_bit].harq_value == 0) + sched_ctrl->harq_processes[harq_idx].round++; + if ((uci_pdu->harq->harq_list[harq_bit].harq_value == 1) || + (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds)) { + sched_ctrl->harq_processes[harq_idx].ndi ^= 1; + sched_ctrl->harq_processes[harq_idx].round = 0; + } + harq_idx_s = harq_idx + 1; + break; + } + } + } + break; + + case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: break; + } + } + UL_info->uci_ind.num_ucis = 0; } @@ -180,7 +215,7 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { // clear DL/UL info for new scheduling round clear_nr_nfapi_information(mac,CC_id,UL_info->frame,UL_info->slot); handle_nr_rach(UL_info); - handle_nr_uci(UL_info); + handle_nr_uci(UL_info, mac->UE_list->UE_sched_ctrl[0]); // clear HI prior to handling ULSCH mac->UL_dci_req[CC_id].numPdus = 0; handle_nr_ulsch(UL_info); From 94b88cf2cf2ee84d55e254e333c1e5236b618a98 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Fri, 22 May 2020 13:16:30 +0200 Subject: [PATCH 233/240] bug fixes --- openair1/PHY/NR_TRANSPORT/nr_dci_tools.c | 2 +- openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c index 96e370eb97..f928645212 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c @@ -219,7 +219,7 @@ void nr_fill_dci(PHY_VARS_gNB *gNB, } dlsch = gNB->dlsch[dlsch_id][0]; - int num_slots_tdd = (gNB->frame_params.p_tdd_UL_DL_Configuration->dl_UL_TransmissionPeriodicity/10000) * gNB->frame_params.slots_per_frame; + int num_slots_tdd = (gNB->frame_parms.p_tdd_UL_DL_Configuration->dl_UL_TransmissionPeriodicity/10000) * gNB->frame_parms.slots_per_frame; int harq_pid = slot % num_slots_tdd; dlsch->slot_tx[slot] = 1; diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index 797499c990..58a8171e8e 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -76,7 +76,7 @@ void handle_nr_rach(NR_UL_IND_t *UL_info) { } -void handle_nr_uci(NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_crtl) { +void handle_nr_uci(NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_ctrl) { // TODO int max_harq_rounds = 4; // TODO define macro int num_ucis = UL_info->uci_ind.num_ucis; @@ -86,7 +86,7 @@ void handle_nr_uci(NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_crtl) { switch (uci_list[i].pdu_type) { case NFAPI_NR_UCI_PDCCH_PDU_TYPE: break; - case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: + case NFAPI_NR_UCI_FORMAT_0_1_PDU_TYPE: { nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_pdu = &uci_list[i].pucch_pdu_format_0_1; // handle harq int harq_idx_s = 0; @@ -108,6 +108,7 @@ void handle_nr_uci(NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_crtl) { } } break; + } case NFAPI_NR_UCI_FORMAT_2_3_4_PDU_TYPE: break; } @@ -215,7 +216,7 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { // clear DL/UL info for new scheduling round clear_nr_nfapi_information(mac,CC_id,UL_info->frame,UL_info->slot); handle_nr_rach(UL_info); - handle_nr_uci(UL_info, mac->UE_list->UE_sched_ctrl[0]); + handle_nr_uci(UL_info, &mac->UE_list.UE_sched_ctrl[0]); // clear HI prior to handling ULSCH mac->UL_dci_req[CC_id].numPdus = 0; handle_nr_ulsch(UL_info); From 17e52131d3f9d2744498ddce22089eba5fd67d58 Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Fri, 22 May 2020 15:00:37 +0200 Subject: [PATCH 234/240] scheduling continuous dl transmission in first half frame --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index ee70c9617b..203978b114 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -377,7 +377,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols!=0) nr_ulmix_slots++; - if (slot_txP == 0) { + if ((slot_txP == 0) && (UE_list->fiveG_connected[UE_id] || get_softmodem_params()->phy_test)) { for (int k=0; kUE_sched_ctrl[UE_id].sched_pucch[k], 0, @@ -474,12 +474,11 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, } // Test DL scheduling - if (get_softmodem_params()->phy_test == 0 && slot_txP == 1 && UE_list->fiveG_connected[UE_id]) { + if (get_softmodem_params()->phy_test == 0 && slot_txP>0 && slot_txP<7 && UE_list->fiveG_connected[UE_id]) { nr_update_pucch_scheduling(module_idP, UE_id, frame_txP, slot_txP, num_slots_per_tdd,&pucch_sched); nr_schedule_uss_dlsch_phytest(module_idP, frame_txP, slot_txP, &UE_list->UE_sched_ctrl[UE_id].sched_pucch[pucch_sched], NULL); // resetting ta flag gNB->ta_len = 0; - UE_list->fiveG_connected[UE_id] = false; } @@ -494,8 +493,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, if (is_nr_UL_slot(cc->ServingCellConfigCommon,slot_rxP)) { if (get_softmodem_params()->phy_test == 0) { - NR_sched_pucch *curr_pucch = UE_list->UE_sched_ctrl[UE_id].sched_pucch; - if (curr_pucch != NULL) + if (UE_list->fiveG_connected[UE_id]) nr_schedule_pucch(module_idP, UE_id, frame_rxP, slot_rxP); schedule_nr_prach(module_idP, (frame_rxP+1)&1023, slot_rxP); nr_schedule_reception_msg3(module_idP, 0, frame_rxP, slot_rxP); From 6fa5a6cf89ffbada59a725d6825f51d2da2dc0e1 Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Fri, 22 May 2020 15:35:31 +0200 Subject: [PATCH 235/240] bugfix --- openair1/PHY/NR_TRANSPORT/nr_dci_tools.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c index f928645212..02ecfc4404 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci_tools.c @@ -219,7 +219,7 @@ void nr_fill_dci(PHY_VARS_gNB *gNB, } dlsch = gNB->dlsch[dlsch_id][0]; - int num_slots_tdd = (gNB->frame_parms.p_tdd_UL_DL_Configuration->dl_UL_TransmissionPeriodicity/10000) * gNB->frame_parms.slots_per_frame; + int num_slots_tdd = (gNB->frame_parms.slots_per_frame)>>(7-gNB->gNB_config.tdd_table.tdd_period.value); int harq_pid = slot % num_slots_tdd; dlsch->slot_tx[slot] = 1; From fe5cd3d28d376dbc53c63c97dff18faa3991701c Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Tue, 26 May 2020 00:04:49 +0200 Subject: [PATCH 236/240] fixed bug for long PRACH sequence configuration, flipped HARQ bits for 2-bit PUCCH0 UCI report --- openair1/PHY/NR_TRANSPORT/pucch_rx.c | 4 ++-- openair1/SCHED_NR_UE/pucch_uci_ue_nr.c | 8 +++++--- openair1/SIMULATION/NR_PHY/ulsim.c | 1 + openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/pucch_rx.c b/openair1/PHY/NR_TRANSPORT/pucch_rx.c index 177217d23f..d3943f5265 100644 --- a/openair1/PHY/NR_TRANSPORT/pucch_rx.c +++ b/openair1/PHY/NR_TRANSPORT/pucch_rx.c @@ -409,8 +409,8 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB, uci_pdu->harq->harq_confidence_level = xrtmag_dB-(gNB->measurements.n0_subband_power_tot_dB[pucch_pdu->prb_start]+gNB->pucch0_thres); uci_pdu->harq->harq_list = (nfapi_nr_harq_t*)malloc(2); - uci_pdu->harq->harq_list[0].harq_value = index&0x01; - uci_pdu->harq->harq_list[1].harq_value = (index>>1)&0x01; + uci_pdu->harq->harq_list[1].harq_value = index&0x01; + uci_pdu->harq->harq_list[0].harq_value = (index>>1)&0x01; if (pucch_pdu->sr_flag == 1) { uci_pdu->sr = calloc(1,sizeof(*uci_pdu->sr)); diff --git a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c index 12992a3a57..a2452248b8 100644 --- a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c +++ b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c @@ -198,7 +198,7 @@ bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_ /* update current context */ - int subframe_number = (proc->nr_tti_rx)/(ue->frame_parms.ttis_per_subframe); + int subframe_number = (proc->nr_tti_rx)/(ue->frame_parms.slots_per_subframe);//ttis_per_subframe); nb_pucch_format_4_in_subframes[subframe_number] = 0; /* reset pucch format 4 counter at current rx position */ int dl_harq_pid = ue->dlsch[ue->current_thread_id[proc->nr_tti_rx]][gNB_id][0]->current_harq_pid; @@ -439,7 +439,7 @@ bool pucch_procedures_ue_nr(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_ } nb_symbols = nb_symbols_excluding_dmrs[nb_symbols_total-4][index_additional_dmrs][index_hopping]; nb_of_prbs = 1; - subframe_number = nr_tti_tx/(ue->frame_parms.ttis_per_subframe); + subframe_number = nr_tti_tx/(ue->frame_parms.slots_per_subframe);//ttis_per_subframe); nb_pucch_format_4_in_subframes[subframe_number]++; /* increment number of transmit pucch 4 in current subframe */ NR_TST_PHY_PRINTF("PUCCH Number of pucch format 4 in subframe %d is %d \n", subframe_number, nb_pucch_format_4_in_subframes[subframe_number]); N_sc_ctrl_RB = N_SC_RB/(nb_pucch_format_4_in_subframes[subframe_number]); @@ -698,6 +698,8 @@ uint8_t get_downlink_ack(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_nr_rxtx_proc_t int V_DAI_m_DL = 0; NR_UE_MAC_INST_t *mac = get_mac_inst(0); + if (mac->DLbwp[0] == NULL) return; + if (mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI[0] == 2) { two_transport_blocks = TRUE; number_of_code_word = 2; @@ -1205,7 +1207,7 @@ int trigger_periodic_scheduling_request(PHY_VARS_NR_UE *ue, uint8_t gNB_id, UE_n return (1); /* period is slot */ } - int16_t N_slot_frame = NR_NUMBER_OF_SUBFRAMES_PER_FRAME * ue->frame_parms.ttis_per_subframe; + int16_t N_slot_frame = NR_NUMBER_OF_SUBFRAMES_PER_FRAME * ue->frame_parms.slots_per_subframe;//ttis_per_subframe; if (((proc->frame_tx * N_slot_frame) + proc->nr_tti_tx - SR_offset)%SR_periodicity == 0) { return (1); } diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 840eaa9ffe..d2c713ab7d 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -747,6 +747,7 @@ int main(int argc, char **argv) ((int16_t*)&gNB->common_vars.rxdata[0][slot_offset])[i], ((int16_t*)&gNB->common_vars.rxdata[0][slot_offset])[1+i]); fclose(input_fd); + LOG_M("rxsig0.m","rx0",gNB->common_vars.rxdata[0][slot_offset],slot_length,1,1); } //////////////////////////////////////////////////////////// diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 5adcf42560..ed7a3b8c78 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -1065,7 +1065,7 @@ uint8_t compute_nr_root_seq(NR_RACH_ConfigCommon_t *rach_config, uint8_t ncs_index = rach_config->rach_ConfigGeneric.zeroCorrelationZoneConfig; uint16_t format0 = get_format0(config_index, unpaired); uint16_t NCS = get_NCS(ncs_index, format0, rach_config->restrictedSetConfig); - uint16_t L_ra = (rach_config->prach_RootSequenceIndex.present) ? 139 : 839; + uint16_t L_ra = (rach_config->prach_RootSequenceIndex.present==NR_RACH_ConfigCommon__prach_RootSequenceIndex_PR_l139) ? 139 : 839; uint16_t r,u,index,q,d_u,n_shift_ra,n_shift_ra_bar,d_start; uint32_t w; uint8_t found_preambles = 0; From d37f077082afc95de7f95b0ef3b96267037d211d Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Tue, 26 May 2020 00:22:48 +0200 Subject: [PATCH 237/240] handling failed ack/nack reception --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 1 + openair2/LAYER2/NR_MAC_gNB/main.c | 1 + openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 1 + openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 11 +++++++++++ 4 files changed, 14 insertions(+) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index bc435ec047..0167a5579b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -378,6 +378,7 @@ int configure_fapi_dl_pdu(int Mod_idP, // PDSCH to HARQ TI dci_pdu_rel15[0].pdsch_to_harq_feedback_timing_indicator.val = pucch_sched->timing_indicator; UE_list->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].feedback_slot = pucch_sched->ul_slot; + UE_list->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].is_waiting = 1; // antenna ports dci_pdu_rel15[0].antenna_ports.val = 0; // nb of cdm groups w/o data 1 and dmrs port 0 diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index 669bc1cd5a..56e020838d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -116,6 +116,7 @@ void mac_top_init_gNB(void) for (int list_harq = 0; list_harq < NR_MAX_NB_HARQ_PROCESSES; list_harq++) { UE_list->UE_sched_ctrl[list_el].harq_processes[list_harq].round = 0; UE_list->UE_sched_ctrl[list_el].harq_processes[list_harq].ndi = 0; + UE_list->UE_sched_ctrl[list_el].harq_processes[list_harq].is_waiting = 0; } } diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index c5ef191506..0125535071 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -188,6 +188,7 @@ typedef struct NR_sched_pucch { } NR_sched_pucch; typedef struct NR_UE_harq { + uint8_t is_waiting; uint8_t ndi; uint8_t round; uint16_t feedback_slot; diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index 58a8171e8e..2b8dc0ec02 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -102,9 +102,20 @@ void handle_nr_uci(NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_ctrl) { sched_ctrl->harq_processes[harq_idx].ndi ^= 1; sched_ctrl->harq_processes[harq_idx].round = 0; } + sched_ctrl->harq_processes[harq_idx].is_waiting = 0; harq_idx_s = harq_idx + 1; break; } + // if gNB fails to receive a ACK/NACK + else if (((UL_info->slot-1) > sched_ctrl->harq_processes[harq_idx].feedback_slot) && + (sched_ctrl->harq_processes[harq_idx].is_waiting)) { + sched_ctrl->harq_processes[harq_idx].round++; + if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) { + sched_ctrl->harq_processes[harq_idx].ndi ^= 1; + sched_ctrl->harq_processes[harq_idx].round = 0; + } + sched_ctrl->harq_processes[harq_idx].is_waiting = 0; + } } } break; From c042f7c26af6750d6aa6d356c5517ee2481529ec Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Tue, 26 May 2020 11:40:54 +0200 Subject: [PATCH 238/240] fixed issue related to scheduing of PRACH for long sequence (only gets done in last slot of subframe now, not both) and start point of DFT in RU processing for long-sequence. Removes fatal segfault. --- openair1/PHY/NR_TRANSPORT/nr_prach.c | 10 ++++++---- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 8 ++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c index 2200768f47..887cc7cd84 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prach.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c @@ -150,6 +150,7 @@ void rx_nr_prach_ru(RU_t *ru, int16_t **rxsigF=NULL; NR_DL_FRAME_PARMS *fp=ru->nr_frame_parms; + int slot2=slot; int16_t *prach[ru->nb_rx]; int prach_sequence_length = ru->config.prach_config.prach_sequence_length.value; @@ -159,9 +160,10 @@ void rx_nr_prach_ru(RU_t *ru, rxsigF = ru->prach_rxsigF; AssertFatal(ru->if_south == LOCAL_RF,"we shouldn't call this if if_south != LOCAL_RF\n"); - for (int aa=0; aanb_rx; aa++) - prach[aa] = (int16_t*)&ru->common.rxdata[aa][(slot*fp->get_samples_per_slot(slot,fp))-ru->N_TA_offset]; - + for (int aa=0; aanb_rx; aa++){ + if (prach_sequence_length == 0) slot2=(slot/fp->slots_per_subframe)*fp->slots_per_subframe; + prach[aa] = (int16_t*)&ru->common.rxdata[aa][(slot2*fp->get_samples_per_slot(slot,fp))-ru->N_TA_offset]; + } int mu = fp->numerology_index; @@ -170,7 +172,7 @@ void rx_nr_prach_ru(RU_t *ru, if (prach_sequence_length == 0) { LOG_D(PHY,"PRACH (ru %d) in %d.%d, format %d, msg1_frequencyStart %d\n", - ru->idx,frame,slot,prachFormat,msg1_frequencystart); + ru->idx,frame,slot2,prachFormat,msg1_frequencystart); AssertFatal(prachFormat<4,"Illegal prach format %d for length 839\n",prachFormat); switch (prachFormat) { case 0: diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index ed7a3b8c78..37322b3d48 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -944,7 +944,7 @@ int get_nr_prach_info_from_index(uint8_t index, s_map = table_6_3_3_2_3_prachConfig_Index[index][4]; if ( (s_map>>subframe)&0x01 ) { if (mu == 1) { - if ( (table_6_3_3_2_3_prachConfig_Index[index][6] == 1) && (slot%2 == 0) ) + if ( (table_6_3_3_2_3_prachConfig_Index[index][6] <= 1) && (slot%2 == 0) ) return 0; // no prach in even slots @ 30kHz for 1 prach per subframe } if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ @@ -954,9 +954,9 @@ int get_nr_prach_info_from_index(uint8_t index, if (table_6_3_3_2_3_prachConfig_Index[index][1] != -1) format2 = (uint8_t) table_6_3_3_2_3_prachConfig_Index[index][1]; *format = ((uint8_t) table_6_3_3_2_3_prachConfig_Index[index][0]) | (format2<<8); - LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u \n", frame, + LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d (col 6 %d) absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u \n", frame, slot, - index, + index, table_6_3_3_2_3_prachConfig_Index[index][6], pointa, mu, unpaired, @@ -980,7 +980,7 @@ int get_nr_prach_info_from_index(uint8_t index, s_map = table_6_3_3_2_2_prachConfig_Index[index][4]; if ( (s_map>>subframe)&0x01 ) { if (mu == 1) { - if ( (table_6_3_3_2_2_prachConfig_Index[index][6] == 1) && (slot%2 == 0) ) + if ( (table_6_3_3_2_2_prachConfig_Index[index][6] <= 1) && (slot%2 == 0) ) return 0; // no prach in even slots @ 30kHz for 1 prach per subframe } if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ From 0a45909bd1aa8a8453531d6c2624fa37297b9a1c Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Tue, 26 May 2020 15:37:10 +0200 Subject: [PATCH 239/240] minor changes --- openair1/PHY/TOOLS/oai_dfts.c | 26 +++++++++++++++++++ openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 6 ++--- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/openair1/PHY/TOOLS/oai_dfts.c b/openair1/PHY/TOOLS/oai_dfts.c index 6ae852b127..7d3cf0d2c0 100644 --- a/openair1/PHY/TOOLS/oai_dfts.c +++ b/openair1/PHY/TOOLS/oai_dfts.c @@ -10571,6 +10571,32 @@ int main(int argc, char**argv) LOG_M("y24576.m","y24576",y,24576,1,1); LOG_M("x24576.m","x24576",x,24576,1,1); + + memset((void*)x,0,2*18432*sizeof(int32_t)); + for (i=2;i<(2*14402);i++) { + if ((taus() & 1)==0) + ((int16_t*)x)[i] = 364; + else + ((int16_t*)x)[i] = -364; + } + for (i=2*(36864-14400);i<(36864*2);i++) { + if ((taus() & 1)==0) + ((int16_t*)x)[i] = 364; + else + ((int16_t*)x)[i] = -364; + } + reset_meas(&ts); + for (i=0; i<10000; i++) { + start_meas(&ts); + idft36864((int16_t *)x,(int16_t *)y,1); + stop_meas(&ts); + } + + printf("\n\n36864-point(%f cycles)\n",(double)ts.diff/(double)ts.trials); + LOG_M("y36864.m","y36864",y,36864,1,1); + LOG_M("x36864.m","x36864",x,36864,1,1); + + memset((void*)x,0,49152*sizeof(int32_t)); for (i=2;i<28402;i++) { if ((taus() & 1)==0) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index ed7a3b8c78..f69ec11432 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -904,7 +904,7 @@ int get_nr_prach_info_from_index(uint8_t index, if ( (frame%x)==y || (frame%x)==y2 ) { slot_60khz = slot >> (mu-2); // in table slots are numbered wrt 60kHz s_map = table_6_3_3_2_4_prachConfig_Index[index][5]; - if ( (s_map>>slot_60khz)&0x01 ) { + if ( ((s_map>>slot_60khz)&0x01) ) { if (mu == 3) { if ( (table_6_3_3_2_4_prachConfig_Index[index][7] == 1) && (slot%2 == 0) ) return 0; // no prach in even slots @ 120kHz for 1 prach per 60khz slot @@ -944,7 +944,7 @@ int get_nr_prach_info_from_index(uint8_t index, s_map = table_6_3_3_2_3_prachConfig_Index[index][4]; if ( (s_map>>subframe)&0x01 ) { if (mu == 1) { - if ( (table_6_3_3_2_3_prachConfig_Index[index][6] == 1) && (slot%2 == 0) ) + if ( (table_6_3_3_2_3_prachConfig_Index[index][6] <= 1) && (slot%2 == 0) ) return 0; // no prach in even slots @ 30kHz for 1 prach per subframe } if (start_symbol != NULL && N_t_slot != NULL && N_dur != NULL && format != NULL){ @@ -954,7 +954,7 @@ int get_nr_prach_info_from_index(uint8_t index, if (table_6_3_3_2_3_prachConfig_Index[index][1] != -1) format2 = (uint8_t) table_6_3_3_2_3_prachConfig_Index[index][1]; *format = ((uint8_t) table_6_3_3_2_3_prachConfig_Index[index][0]) | (format2<<8); - LOG_D(MAC,"Frame %d slot %d: Getting PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u \n", frame, + LOG_I(MAC,"Frame %d slot %d: Getting PRACH info from index %d absoluteFrequencyPointA %u mu %u frame_type %u start_symbol %u N_t_slot %u N_dur %u \n", frame, slot, index, pointa, From 4e12c394718c9f5dbe1b15d1dc0dcb3a2a24160c Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Thu, 28 May 2020 17:56:42 +0200 Subject: [PATCH 240/240] static bitmap to schedule dl slots (also to test phone) --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 48 +++++++++------------- 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 7cd3bd3c91..8652d7fce6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -377,7 +377,7 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols!=0) nr_ulmix_slots++; - if ((slot_txP == 0) && (UE_list->fiveG_connected[UE_id] || get_softmodem_params()->phy_test)) { + if (slot_txP== 0 && (UE_list->fiveG_connected[UE_id] || get_softmodem_params()->phy_test)) { for (int k=0; kUE_sched_ctrl[UE_id].sched_pucch[k], 0, @@ -394,25 +394,23 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, RC.nrmac[module_idP]->frame = frame_rxP; RC.nrmac[module_idP]->slot = slot_rxP; - if (get_softmodem_params()->phy_test) { - dlsch_in_slot_bitmap = &RC.nrmac[module_idP]->UE_list.UE_sched_ctrl[UE_id].dlsch_in_slot_bitmap; // static bitmap signaling which slot in a tdd period contains dlsch - ulsch_in_slot_bitmap = &RC.nrmac[module_idP]->UE_list.UE_sched_ctrl[UE_id].ulsch_in_slot_bitmap; // static bitmap signaling which slot in a tdd period contains ulsch + dlsch_in_slot_bitmap = &RC.nrmac[module_idP]->UE_list.UE_sched_ctrl[UE_id].dlsch_in_slot_bitmap; // static bitmap signaling which slot in a tdd period contains dlsch + ulsch_in_slot_bitmap = &RC.nrmac[module_idP]->UE_list.UE_sched_ctrl[UE_id].ulsch_in_slot_bitmap; // static bitmap signaling which slot in a tdd period contains ulsch - // hardcoding dlsch to be in slot 1 - if (!(slot_txP%num_slots_per_tdd)) { - if(slot_txP==0) - *dlsch_in_slot_bitmap = 0x02; - else - *dlsch_in_slot_bitmap = 0x00; - } + // hardcoding dlsch to be in slot 1 + if (!(slot_txP%num_slots_per_tdd)) { + if(slot_txP==0) + *dlsch_in_slot_bitmap = 0x7e; + else + *dlsch_in_slot_bitmap = 0x00; + } - // hardcoding ulsch to be in slot 8 - if (!(slot_rxP%num_slots_per_tdd)) { - if(slot_rxP==0) - *ulsch_in_slot_bitmap = 0x100; - else - *ulsch_in_slot_bitmap = 0x00; - } + // hardcoding ulsch to be in slot 8 + if (!(slot_rxP%num_slots_per_tdd)) { + if(slot_rxP==0) + *ulsch_in_slot_bitmap = 0x100; + else + *ulsch_in_slot_bitmap = 0x00; } // Check if there are downlink symbols in the slot, @@ -464,9 +462,11 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, if (get_softmodem_params()->phy_test == 0) nr_schedule_RA(module_idP, frame_txP, slot_txP); + else + UE_list->fiveG_connected[UE_id] = true; // Phytest scheduling - if (get_softmodem_params()->phy_test && (is_xlsch_in_slot(*dlsch_in_slot_bitmap,slot_txP%num_slots_per_tdd))) { + if (UE_list->fiveG_connected[UE_id] && (is_xlsch_in_slot(*dlsch_in_slot_bitmap,slot_txP%num_slots_per_tdd))) { ue_sched_ctl->current_harq_pid = slot_txP % num_slots_per_tdd; nr_update_pucch_scheduling(module_idP, UE_id, frame_txP, slot_txP, num_slots_per_tdd,&pucch_sched); nr_schedule_uss_dlsch_phytest(module_idP, frame_txP, slot_txP, &UE_list->UE_sched_ctrl[UE_id].sched_pucch[pucch_sched], NULL); @@ -474,16 +474,6 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, gNB->ta_len = 0; } - // Test DL scheduling - if (get_softmodem_params()->phy_test == 0 && slot_txP>0 && slot_txP<7 && UE_list->fiveG_connected[UE_id]) { - ue_sched_ctl->current_harq_pid = slot_txP % num_slots_per_tdd; - nr_update_pucch_scheduling(module_idP, UE_id, frame_txP, slot_txP, num_slots_per_tdd,&pucch_sched); - nr_schedule_uss_dlsch_phytest(module_idP, frame_txP, slot_txP, &UE_list->UE_sched_ctrl[UE_id].sched_pucch[pucch_sched], NULL); - // resetting ta flag - gNB->ta_len = 0; - } - - /* // Allocate CCEs for good after scheduling is done for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++)