diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 48c57434bd..10c7b32142 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -296,22 +296,19 @@ void fh_if4p5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp) { // Synchronous if5 from south -uint64_t ts_rx[20]; void fh_if5_south_in(RU_t *ru, int *frame, int *tti) { NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms; RU_proc_t *proc = &ru->proc; - nfapi_nr_config_request_scf_t *cfg = &ru->config; - int is_rx=1; - int slot_type = nr_slot_select(cfg,*frame,*tti); - if (slot_type == NR_DOWNLINK_SLOT) is_rx=0; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 ); + start_meas(&ru->rx_fhaul); + ru->ifdevice.trx_read_func2(&ru->ifdevice,&proc->timestamp_rx,NULL,fp->get_samples_per_slot(*tti,fp)); if (proc->first_rx == 1) ru->ts_offset = proc->timestamp_rx; proc->frame_rx = ((proc->timestamp_rx-ru->ts_offset) / (fp->samples_per_subframe*10))&1023; proc->tti_rx = fp->get_slot_from_timestamp(proc->timestamp_rx-ru->ts_offset,fp); -//(idx_sf * fp->slots_per_subframe + (int)round((float)(proc->timestamp_rx % fp->samples_per_subframe) / fp->samples_per_slot0))%(fp->slots_per_frame); - ts_rx[*tti] = proc->timestamp_rx; + LOG_D(PHY,"IF5 %d.%d => RX %d.%d first_rx %d\n",*frame,*tti,proc->frame_rx,proc->tti_rx,proc->first_rx); if (proc->first_rx == 0) { @@ -330,7 +327,10 @@ void fh_if5_south_in(RU_t *ru, *tti = proc->tti_rx; } + stop_meas(&ru->rx_fhaul); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 0 ); + } // Synchronous if4p5 from south @@ -1313,7 +1313,7 @@ void *ru_thread( void *param ) { else LOG_I(PHY,"RU %d rf device ready\n",ru->idx); } else LOG_I(PHY,"RU %d no rf device\n",ru->idx); - LOG_I(PHY,"RU %d RF started\n",ru->idx); + LOG_I(PHY,"RU %d RF started opp_enabled %d\n",ru->idx,opp_enabled); // start trx write thread if(usrp_tx_thread == 1) { if (ru->start_write_thread) { @@ -1363,12 +1363,11 @@ void *ru_thread( void *param ) { } // synchronization on input FH interface, acquire signals/data and block - LOG_I(PHY,"[RU_thread] read data: frame_rx = %d, tti_rx = %d\n", frame, slot); + LOG_D(PHY,"[RU_thread] read data: frame_rx = %d, tti_rx = %d\n", frame, slot); if (ru->fh_south_in) ru->fh_south_in(ru,&frame,&slot); else AssertFatal(1==0, "No fronthaul interface at south port"); - continue; if (initial_wait == 1 && proc->frame_rx < 300 && ru->fh_south_in == rx_rf) { if (proc->frame_rx>0 && ((proc->frame_rx % 100) == 0) && proc->tti_rx==0) { @@ -1537,7 +1536,8 @@ void init_RU_proc(RU_t *ru) { if(emulate_rf) threadCreate( &proc->pthread_emulateRF, emulatedRF_thread, (void *)proc, "emulateRF", -1, OAI_PRIORITY_RT ); - + if (opp_enabled == 1) + threadCreate( &ru->ru_stats_thread, ru_stats_thread, (void *)ru,"ru_stats", -1, OAI_PRIORITY_RT ); if (get_thread_worker_conf() == WORKER_ENABLE) { if (ru->feprx) nr_init_feprx_thread(ru); diff --git a/openair1/PHY/LTE_TRANSPORT/if5_tools.c b/openair1/PHY/LTE_TRANSPORT/if5_tools.c index 5f6376c51b..8eb7934f99 100644 --- a/openair1/PHY/LTE_TRANSPORT/if5_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/if5_tools.c @@ -1116,15 +1116,6 @@ void send_IF5(RU_t *ru, openair0_timestamp proc_timestamp, int tti, uint8_t *seq siglen = spsf; } - if (ru->openair0_cfg.nr_flag==1) { - if (nrfp->N_RB_DL <= 162 && nrfp->N_RB_DL > 106) {factor_n=1; factor_d=2;} // 61.44 Ms/s - else if (nrfp->N_RB_DL <= 106 && nrfp->N_RB_DL > 51 ) {factor_n=3; factor_d=4;} // 46.08 Ms/s - else if (nrfp->N_RB_DL == 51 ) {factor_n=1; factor_d=1;} // 30.72 Ms/s - else AssertFatal(1==0,"N_RB_DL %d not supported yet\n",nrfp->N_RB_DL); - } - else { - factor_n = 30720/spsf; - } for (i=0; i < ru->nb_tx; i++) txp[i] = (int32_t*)&ru->common.txdata[i][offset]; @@ -1134,7 +1125,7 @@ void send_IF5(RU_t *ru, openair0_timestamp proc_timestamp, int tti, uint8_t *seq //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_IF0, 1 ); clock_gettime( CLOCK_MONOTONIC, &start_comp); ru->ifdevice.trx_write_func2(&ru->ifdevice, - ((proc_timestamp + packet_id*spp_eth-600)*factor_n)/factor_d, + (proc_timestamp + packet_id*spp_eth/*-1250*/), (void*)txp[aid], spp_eth, aid, diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index dc31c00221..e67655125e 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -366,12 +366,15 @@ struct openair0_device_t { /*!brief pointer to FH state, used in ECPRI split 8*/ fhstate_t fhstate; - /*!bried Used in ECPRI split 8 to indicate numerator of sampling rate ratio*/ + /*!brief Used in ECPRI split 8 to indicate numerator of sampling rate ratio*/ int sampling_rate_ratio_n; - /*!bried Used in ECPRI split 8 to indicate denominator of sampling rate ratio*/ + /*!brief Used in ECPRI split 8 to indicate denominator of sampling rate ratio*/ int sampling_rate_ratio_d; + /*!brief Used in ECPRI split 8 to indicate the TX/RX timing offset*/ + int txrx_offset; + /* Functions API, which are called by the application*/ /*! \brief Called to start the transceiver. Return 0 if OK, < 0 if error diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c index a39d27d55a..c50305a760 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -151,6 +152,22 @@ int eth_socket_init_udp(openair0_device *device) { printf("ETHERNET: Cannot set SO_REUSEPORT option on socket (user %d)",i); exit(0); } +#ifdef SO_ATTACH_REUSEPORT_EBPF + struct sock_filter code[]={ + { BPF_LD | BPF_W | BPF_ABS, 0, 0, SKF_AD_OFF + SKF_AD_CPU }, + /* return A */ + { BPF_RET | BPF_A, 0, 0, 0 }, + }; + struct sock_fprog bpf = { + .len = sizeof(code)/sizeof(struct sock_filter), + .filter = code, + }; + if (i==0 && setsockopt(eth->sockfdd[i], SOL_SOCKET, SO_ATTACH_REUSEPORT_CBPF, &bpf, sizeof(bpf))) { + printf("ETHERNET: Cannot set SO_ATTACH_REUSEPORT_EBPF option on socket (user %d)",i); + exit(0); + } +#endif + } /* want to receive -> so bind */ @@ -277,6 +294,7 @@ int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, voi int bytes_sent=0; eth_state_t *eth = (eth_state_t*)device->priv; int sendto_flag =0; + fhstate_t *fhstate = &device->fhstate; //sendto_flag|=flags; eth->tx_nsamps=nsamps; @@ -321,8 +339,9 @@ int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, voi /* buff[i] points to the position in tx buffer where the payload to be sent is buff2 points to the position in tx buffer where the packet header will be placed */ void *buff2 = ((void*)buff_tx2)- APP_HEADER_SIZE_BYTES; - - + openair0_timestamp TS = timestamp + fhstate->TS0; + TS = 6*device->sampling_rate_ratio_d*(TS/device->sampling_rate_ratio_n); + TS -= device->txrx_offset; bytes_sent = 0; @@ -338,7 +357,7 @@ int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, voi // ECPRI PC_ID (2 bytes) *(uint16_t *)(buff2 + 4) = cc; // OAI modified SEQ_ID (4 bytes) - *(uint64_t *)(buff2 + 6) = ((uint64_t )timestamp)*6; + *(uint64_t *)(buff2 + 6) = TS; /* printf("ECPRI TX (REV %x, MessType %d, Payload size %d, PC_ID %d, TS %llu\n", @@ -408,7 +427,7 @@ void *udp_read_thread(void *arg) { char buffer[UDP_PACKET_SIZE_BYTES(256)]; while (oai_exit == 0) { - printf("UDP read thread %d, waiting for start\n",u->thread_id); + LOG_I(PHY,"UDP read thread %d, waiting for start sampling_rate_d %d, sampling_rate_n %d\n",u->thread_id,device->sampling_rate_ratio_n,device->sampling_rate_ratio_d); while (fhstate->active > 0) { size_t count = recvfrom(((eth_state_t*)device->priv)->sockfdd[u->thread_id], buffer,sizeof(buffer),0, @@ -417,9 +436,8 @@ void *udp_read_thread(void *arg) { aid = *(uint16_t*)(&buffer[ECPRICOMMON_BYTES]); TS = *(openair0_timestamp *)(&buffer[ECPRICOMMON_BYTES+ECPRIPCID_BYTES]); // convert TS to samples, /6 for AW2S @ 30.72 Ms/s, this is converted for other sample rates in OAI application - TS = device->sampling_rate_ratio_n*(TS/device->sampling_rate_ratio_d/6); - printf("udp_thread_id %d count %d, aid %d, TS %llu\n",u->thread_id,count,aid,(unsigned long long)TS); - if (count <= 0) { printf("problem in recvfrom\n"); exit(-1); } + TS = device->sampling_rate_ratio_n*(TS/(device->sampling_rate_ratio_d*6)); + if ((int)count <= 0) continue; AssertFatal(aid < 8,"Cannot handle more than 8 antennas, got aid %d\n",aid); fhstate->r[aid]=1; if (aid==0 && fhstate->TS[0] == 0) fhstate->TS0 = TS; @@ -428,7 +446,6 @@ void *udp_read_thread(void *arg) { int64_t offset = TS - fhstate->TS0; if (offset > 0) offset = offset % device->openair0_cfg->rxsize; else offset = TS % device->openair0_cfg->rxsize + ((((uint64_t)1)<<63)-(fhstate->TS0-1)) % device->openair0_cfg->rxsize; - printf("udp_thread_id %d aid %d, TS %llu, TS0 %llu, offset %d, size %d\n",u->thread_id,aid,(unsigned long long)TS,fhstate->TS0,offset,device->openair0_cfg->rxsize); // need to do memcpy since there is no guarantee that aid is the same each time, otherwise we could have used // zero-copy and corrected the header component. memcpy((void*)(device->openair0_cfg->rxbase[aid]+offset), @@ -453,7 +470,7 @@ int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, uin min_TS = fhstate->TS[0]; for (int i=1;iopenair0_cfg->rx_num_channels;i++) min_TS = min(min_TS,fhstate->TS[i]); // poll/sleep until we accumulated enough samples on each antenna port - while (min_TS < prev_read_TS + nsamps) { + while (min_TS < fhstate->TS0+prev_read_TS + nsamps) { usleep(100); min_TS = fhstate->TS[0]; for (int i=1;iopenair0_cfg->rx_num_channels;i++) min_TS = min(min_TS,fhstate->TS[i]); diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index f50e9abde6..b5a21c5d16 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -76,16 +76,40 @@ int trx_eth_start(openair0_device *device) device->sampling_rate_ratio_n=1; device->sampling_rate_ratio_d=1; if (device->openair0_cfg->nr_flag==1) { // This check if RRU knows about NR numerologies - if (device->openair0_cfg->num_rb_dl <= 162 && device->openair0_cfg->num_rb_dl > 106) device->sampling_rate_ratio_n = 2; - else if (device->openair0_cfg->num_rb_dl <= 106 && device->openair0_cfg->num_rb_dl > 51) {device->sampling_rate_ratio_d=3;device->sampling_rate_ratio_n=4;} - else if (device->openair0_cfg->num_rb_dl == 51) {device->sampling_rate_ratio_n=1;device->sampling_rate_ratio_d=1;} + if (device->openair0_cfg->num_rb_dl <= 162 && device->openair0_cfg->num_rb_dl > 106) { + device->sampling_rate_ratio_n = 2; + device->txrx_offset=5500; + } + else if (device->openair0_cfg->num_rb_dl <= 106 && device->openair0_cfg->num_rb_dl > 51) { + device->sampling_rate_ratio_d=3; + device->sampling_rate_ratio_n=4; + device->txrx_offset=3750; + } + else if (device->openair0_cfg->num_rb_dl == 51) { + device->sampling_rate_ratio_n=1; + device->sampling_rate_ratio_d=1; + device->txrx_offset=7500; + } else AssertFatal(1==0,"num_rb_dl %d not ok with ECPRI\n",device->openair0_cfg->num_rb_dl); } else { - if (device->openair0_cfg->num_rb_dl == 100 || device->openair0_cfg->num_rb_dl == 51) device->sampling_rate_ratio_d = 1; - else if (device->openair0_cfg->num_rb_dl == 75) {device->sampling_rate_ratio_d = 4; device->sampling_rate_ratio_n=3;} - else if (device->openair0_cfg->num_rb_dl == 50) device->sampling_rate_ratio_d = 2; - else if (device->openair0_cfg->num_rb_dl == 25) device->sampling_rate_ratio_d = 4; + if (device->openair0_cfg->num_rb_dl == 100 || device->openair0_cfg->num_rb_dl == 51) { + device->sampling_rate_ratio_d = 1; + device->txrx_offset=7500; + } + else if (device->openair0_cfg->num_rb_dl == 75) { + device->sampling_rate_ratio_d = 4; + device->sampling_rate_ratio_n=3; + device->txrx_offset=7500; + } + else if (device->openair0_cfg->num_rb_dl == 50) { + device->sampling_rate_ratio_d = 2; + device->txrx_offset=7500; + } + else if (device->openair0_cfg->num_rb_dl == 25) { + device->sampling_rate_ratio_d = 4; + device->txrx_offset=7500; + } else AssertFatal(1==0,"num_rb_dl %d not ok with ECPRI\n",device->openair0_cfg->num_rb_dl); } } @@ -478,6 +502,7 @@ int transport_init(openair0_device *device, device->trx_ctlsend_func = trx_eth_ctlsend_udp; device->trx_ctlrecv_func = trx_eth_ctlrecv_udp; memset((void*)&device->fhstate,0,sizeof(device->fhstate)); + for (int i=openair0_cfg->rx_num_channels;i<8;i++) device->fhstate.r[i] = 1; } else if (eth->flags == ETH_RAW_IF4p5_MODE) { device->trx_write_func = trx_eth_write_raw_IF4p5; device->trx_read_func = trx_eth_read_raw_IF4p5;