Commit 1273846c authored by Robert Schmidt's avatar Robert Schmidt

Merge remote-tracking branch 'origin/if5_ECPRI_rework' into integration_2022_wk38

parents 5bf2626c 40b33845
......@@ -1541,7 +1541,6 @@ set(PHY_SRC
set(PHY_SRC_RU
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/if4_tools.c
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/if5_tools.c
${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/drs_modulation.c
${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/ulsch_demodulation.c
${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c
......
#this is a configuration file
#used to build real time processing statistics
#for 5G NR phy test (gNB terminate)
Title : Processing Time (us)
ColNames :
- Metric
- Average; Max; Count
- Average vs Reference Deviation (Reference Value; Acceptability Threshold)
Ref :
feprx : 48.0
feptx_prec : 16.0
feptx_ofdm : 35.0
feptx_total : 59.0
L1 Tx processing : 210.0
DLSCH encoding : 129.0
L1 Rx processing : 287.0
PUSCH inner-receiver : 166.0
PUSCH decoding : 176.0
Schedule Response : 42.0
DL & UL scheduling timing : 13.0
UL Indication : 55.0
Threshold :
feprx : 1.25
feptx_prec : 1.25
feptx_ofdm : 1.25
feptx_total : 1.25
L1 Tx processing : 1.25
DLSCH encoding : 1.25
L1 Rx processing : 1.25
PUSCH inner-receiver : 1.25
PUSCH decoding : 1.25
Schedule Response : 1.25
DL & UL scheduling timing : 1.25
UL Indication : 1.25
......@@ -7,18 +7,18 @@ ColNames :
- Average; Max; Count
- Average vs Reference Deviation (Reference Value; Acceptability Threshold)
Ref :
feprx : 60.0
feptx_prec : 8.0
feptx_ofdm : 50.0
feptx_total : 75.0
L1 Tx processing : 300.0
DLSCH encoding : 230.0
L1 Rx processing : 175.0
PUSCH inner-receiver : 100.0
#PUSCH decoding : 180.0
PUSCH decoding : 240.0
DL & UL scheduling timing : 37.0
UL Indication : 38.0
feprx : 53.0
feptx_prec : 20.0
feptx_ofdm : 37.0
feptx_total : 62.0
L1 Tx processing : 170.0
DLSCH encoding : 118.0
L1 Rx processing : 223.0
PUSCH inner-receiver : 107.0
PUSCH decoding : 170.0
Schedule Response : 15.0
DL & UL scheduling timing : 10.0
UL Indication : 27.0
Threshold :
feprx : 1.25
feptx_prec : 1.25
......@@ -29,5 +29,6 @@ Threshold :
L1 Rx processing : 1.25
PUSCH inner-receiver : 1.25
PUSCH decoding : 1.25
Schedule Response : 1.25
DL & UL scheduling timing : 1.25
UL Indication : 1.25
......@@ -21,8 +21,8 @@
-->
<testCaseList>
<htmlTabRef>gNB-PHY-Test</htmlTabRef>
<htmlTabName>Run-gNB-PHY-Test</htmlTabName>
<htmlTabRef>gNB-PHY-Test-40</htmlTabRef>
<htmlTabName>Timing phytest 40 MHz</htmlTabName>
<htmlTabIcon>tasks</htmlTabIcon>
<repeatCount>1</repeatCount>
<TestCaseRequestedList>
......@@ -33,7 +33,8 @@
<testCase id="090101">
<class>Initialize_eNB</class>
<desc>Initialize gNB USRP</desc>
<Initialize_eNB_args>-O ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf --phy-test -q -U 787200 -T 106 -t 28 -D 130175 -m 28 -M 106 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time</Initialize_eNB_args>
<Initialize_eNB_args>-O ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf --phy-test -q -U 787200 -T 106 -t 23 -D 130175 -m 28 -M 106 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time</Initialize_eNB_args>
<rt_stats_cfg>datalog_rt_stats.default.yaml</rt_stats_cfg>
<air_interface>NR</air_interface>
<USRP_IPAddress>192.168.20.2</USRP_IPAddress>
</testCase>
......@@ -41,7 +42,7 @@
<testCase id="000001">
<class>IdleSleep</class>
<desc>Sleep</desc>
<idle_sleep_time_in_sec>300</idle_sleep_time_in_sec>
<idle_sleep_time_in_sec>60</idle_sleep_time_in_sec>
</testCase>
......
<!--
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
-->
<testCaseList>
<htmlTabRef>gNB-PHY-Test-60</htmlTabRef>
<htmlTabName>Timing phytest 60 MHz</htmlTabName>
<htmlTabIcon>tasks</htmlTabIcon>
<repeatCount>1</repeatCount>
<TestCaseRequestedList>
190101 000001 190109
</TestCaseRequestedList>
<TestCaseExclusionList></TestCaseExclusionList>
<testCase id="190101">
<class>Initialize_eNB</class>
<desc>Initialize gNB USRP</desc>
<Initialize_eNB_args>-O ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf --phy-test --gNBs.[0].servingCellConfigCommon.[0].dl_carrierBandwidth 162 --gNBs.[0].servingCellConfigCommon.[0].ul_carrierBandwidth 162 -q -U 787200 -T 162 -t 23 -D 130175 -m 23 -M 162 --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time</Initialize_eNB_args>
<rt_stats_cfg>datalog_rt_stats.1x1.60.yaml</rt_stats_cfg>
<air_interface>NR</air_interface>
<USRP_IPAddress>192.168.20.2</USRP_IPAddress>
</testCase>
<testCase id="000001">
<class>IdleSleep</class>
<desc>Sleep</desc>
<idle_sleep_time_in_sec>60</idle_sleep_time_in_sec>
</testCase>
<testCase id="190109">
<class>Terminate_eNB</class>
<desc>Terminate gNB</desc>
<air_interface>NR</air_interface>
</testCase>
</testCaseList>
......@@ -85,21 +85,21 @@ void print_meas(time_stats_t *ts,
first_time=1;
if ((total_exec_time == NULL) || (sf_exec_time== NULL))
fprintf(stderr, "%25s %25s %25s %25s %25s %6f\n","Name","Total","Per Trials", "Num Trials","CPU_F_GHz", cpu_freq_GHz);
fprintf(stderr, "%30s %25s %25s %25s %25s %6f\n","Name","Total","Per Trials", "Num Trials","CPU_F_GHz", cpu_freq_GHz);
else
fprintf(stderr, "%25s %25s %25s %20s %15s %6f\n","Name","Total","Average/Frame","Trials", "CPU_F_GHz", cpu_freq_GHz);
fprintf(stderr, "%30s %25s %25s %20s %15s %6f\n","Name","Total","Average/Frame","Trials", "CPU_F_GHz", cpu_freq_GHz);
}
if (ts->trials>0) {
//printf("%20s: total: %10.3f ms, average: %10.3f us (%10d trials)\n", name, ts->diff/cpu_freq_GHz/1000000.0, ts->diff/ts->trials/cpu_freq_GHz/1000.0, ts->trials);
if ((total_exec_time == NULL) || (sf_exec_time== NULL)) {
fprintf(stderr, "%25s: %15.3f us; %15d; %15.3f us;\n",
fprintf(stderr, "%30s: %15.3f us; %15d; %15.3f us;\n",
name,
(ts->diff/ts->trials/cpu_freq_GHz/1000.0),
ts->trials,
ts->max/cpu_freq_GHz/1000.0);
} else {
fprintf(stderr, "%25s: %15.3f ms (%5.2f%%); %15.3f us (%5.2f%%); %15d;\n",
fprintf(stderr, "%30s: %15.3f ms (%5.2f%%); %15.3f us (%5.2f%%); %15d;\n",
name,
(ts->diff/cpu_freq_GHz/1000000.0),
((ts->diff/cpu_freq_GHz/1000000.0)/(total_exec_time->diff/cpu_freq_GHz/1000000.0))*100, // percentage
......
......@@ -66,6 +66,7 @@ static int DEFBANDS[] = {7};
static int DEFENBS[] = {0};
static int DEFBFW[] = {0x00007fff};
static int DEFRUTPCORES[] = {2,4,6,8};
THREAD_STRUCT thread_struct;
pthread_cond_t sync_cond;
......
......@@ -38,6 +38,7 @@
#include "assertions.h"
#include <common/utils/LOG/log.h>
#include <common/utils/system.h>
#include "rt_profiling.h"
#include "PHY/types.h"
......@@ -59,7 +60,6 @@
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
#include "PHY/LTE_TRANSPORT/if4_tools.h"
#include "PHY/LTE_TRANSPORT/if5_tools.h"
#include "PHY/phy_extern.h"
......@@ -115,10 +115,17 @@ void tx_func(void *param) {
int frame_tx = info->frame;
int slot_tx = info->slot;
int absslot_tx = info->timestamp_tx/info->gNB->frame_parms.get_samples_per_slot(slot_tx,&info->gNB->frame_parms);
int absslot_rx = absslot_tx-info->gNB->RU_list[0]->sl_ahead;
int rt_prof_idx = absslot_rx % RT_PROF_DEPTH;
clock_gettime(CLOCK_MONOTONIC,&info->gNB->rt_L1_profiling.start_L1_TX[rt_prof_idx]);
phy_procedures_gNB_TX(info,
frame_tx,
slot_tx,
1);
clock_gettime(CLOCK_MONOTONIC,&info->gNB->rt_L1_profiling.return_L1_TX[rt_prof_idx]);
}
void rx_func(void *param) {
......@@ -130,6 +137,11 @@ void rx_func(void *param) {
int slot_tx = info->slot_tx;
nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
int absslot_tx = info->timestamp_tx/gNB->frame_parms.get_samples_per_slot(slot_rx,&gNB->frame_parms);
int absslot_rx = absslot_tx - gNB->RU_list[0]->sl_ahead;
int rt_prof_idx = absslot_rx % RT_PROF_DEPTH;
clock_gettime(CLOCK_MONOTONIC,&info->gNB->rt_L1_profiling.start_L1_RX[rt_prof_idx]);
start_meas(&softmodem_stats_rxtx_sf);
// *******************************************************************
......@@ -228,6 +240,7 @@ void rx_func(void *param) {
stop_meas( &softmodem_stats_rxtx_sf );
LOG_D(PHY,"%s() Exit proc[rx:%d%d tx:%d%d]\n", __FUNCTION__, frame_rx, slot_rx, frame_tx, slot_tx);
clock_gettime(CLOCK_MONOTONIC,&info->gNB->rt_L1_profiling.return_L1_RX[rt_prof_idx]);
// Call the scheduler
start_meas(&gNB->ul_indication_stats);
......@@ -383,6 +396,8 @@ void *tx_reorder_thread(void* param) {
AssertFatal(resL1Reserve != NULL, "pullTpool() did not return start message in %s\n", __func__);
int next_tx_slot=((processingData_L1tx_t *)NotifiedFifoData(resL1Reserve))->slot;
LOG_I(PHY,"tx_reorder_thread started\n");
while (!oai_exit) {
notifiedFIFO_elt_t *resL1;
if (resL1Reserve) {
......@@ -419,6 +434,7 @@ void *tx_reorder_thread(void* param) {
pushNotifiedFIFO(&gNB->L1_tx_free, resL1);
if (resL1==resL1Reserve)
resL1Reserve=NULL;
LOG_D(PHY,"gNB: %d.%d : calling RU TX function\n",syncMsgL1->frame,syncMsgL1->slot);
ru_tx_func((void*)&syncMsgRU);
}
return(NULL);
......@@ -457,7 +473,9 @@ void init_gNB_Tpool(int inst) {
if ((!get_softmodem_params()->emulate_l1) && (!IS_SOFTMODEM_NOSTATS_BIT))
threadCreate(&proc->L1_stats_thread,nrL1_stats_thread,(void*)gNB,"L1_stats",-1,OAI_PRIORITY_RT_LOW);
threadCreate(&proc->pthread_tx_reorder, tx_reorder_thread, (void *)gNB, "thread_tx_reorder", -1, OAI_PRIORITY_RT_MAX);
LOG_I(PHY,"Creating thread for TX reordering and dispatching to RU\n");
threadCreate(&proc->pthread_tx_reorder, tx_reorder_thread, (void *)gNB, "thread_tx_reorder",
gNB->RU_list[0] ? gNB->RU_list[0]->tpcores[1] : -1, OAI_PRIORITY_RT_MAX);
}
......
This diff is collapsed.
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
......@@ -19,52 +20,45 @@
* contact@openairinterface.org
*/
/*! \file PHY/LTE_TRANSPORT/if5_tools.h
* \brief
* \author S. Sandeep Kumar, Raymond Knopp
* \date 2016
* \version 0.1
* \company Eurecom
* \email: ee13b1025@iith.ac.in, knopp@eurecom.fr
* \note
* \warning
*/
#ifndef __IF5_TOOLS_H__
#define __IF5_TOOLS_H__
#include <stdint.h>
#include "PHY/defs_eNB.h"
#define IF5_RRH_GW_DL 0x0022
#define IF5_RRH_GW_UL 0x0023
#define IF5_MOBIPASS 0xbffe
struct IF5_mobipass_header {
///
uint16_t flags;
///
uint16_t fifo_status;
///
uint8_t seqno;
///
uint8_t ack;
///
uint32_t word0;
///
uint32_t time_stamp;
} __attribute__ ((__packed__));
typedef struct IF5_mobipass_header IF5_mobipass_header_t;
#define sizeof_IF5_mobipass_header_t 14
void send_IF5(RU_t *, openair0_timestamp, int, uint8_t*, uint16_t);
void recv_IF5(RU_t *ru, openair0_timestamp *proc_timestamp, int subframe, uint16_t packet_type);
/*! \file time_profiling.h
* \brief Definitions for proflling real-time scheduling
* \author
* \date 2022
* \version 0.1
* \company Eurecom
* \email:
* \note
* \warning
*/
#ifndef TIME_PROFILING_H
#define TIME_PROFILING_H
#ifdef __cplusplus
extern "C"
{
#endif
void malloc_IF5_buffer(RU_t *ru);
// depth of trace in slots
#define RT_PROF_DEPTH 100
typedef struct {
int absslot_rx[RT_PROF_DEPTH];
struct timespec return_RU_south_in[RT_PROF_DEPTH];
struct timespec return_RU_feprx[RT_PROF_DEPTH];
struct timespec return_RU_prachrx[RT_PROF_DEPTH];
struct timespec return_RU_pushL1[RT_PROF_DEPTH];
struct timespec start_RU_TX[RT_PROF_DEPTH];
struct timespec return_RU_TX[RT_PROF_DEPTH];
} rt_ru_profiling_t;
typedef struct {
int absslot_ux[RT_PROF_DEPTH];
struct timespec start_L1_RX[RT_PROF_DEPTH];
struct timespec return_L1_RX[RT_PROF_DEPTH];
struct timespec start_L1_TX[RT_PROF_DEPTH];
struct timespec return_L1_TX[RT_PROF_DEPTH];
struct timespec return_L1_prachrx[RT_PROF_DEPTH];
struct timespec return_L1_puschL1[RT_PROF_DEPTH];
} rt_L1_profiling_t;
#ifdef __cplusplus
}
#endif
#endif
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -117,6 +117,7 @@ NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms,
a_segments = a_segments/273 +1;
}
LOG_I(PHY,"Allocating %d segments (MAX %d, N_PRB %d)\n",a_segments,MAX_NUM_NR_DLSCH_SEGMENTS_PER_LAYER,N_RB);
uint32_t dlsch_bytes = a_segments*1056; // allocated bytes per segment
NR_gNB_DLSCH_t *dlsch = malloc16(sizeof(NR_gNB_DLSCH_t));
AssertFatal(dlsch, "cannot allocate dlsch\n");
......
......@@ -410,7 +410,7 @@ void nr_decode_pucch0(PHY_VARS_gNB *gNB,
uci_stats->pucch0_thres = gNB->pucch0_thres; /* + (10*max_n0);*/
bool no_conf=false;
if (nr_sequences>1) {
if (/*xrtmag_dBtimes10 < (30+xrtmag_next_dBtimes10) ||*/ SNRtimes10 < uci_stats->pucch0_thres) {
if (/*xrtmag_dBtimes10 < (30+xrtmag_next_dBtimes10) ||*/ SNRtimes10 < gNB->pucch0_thres) {
no_conf=true;
LOG_D(PHY,"%d.%d PUCCH bad confidence: %d threshold, %d, %d, %d\n",
frame, slot,
......
......@@ -39,6 +39,8 @@
#include "time_meas.h"
#include "defs_common.h"
#include "nfapi_nr_interface_scf.h"
#include <common/utils/threadPool/thread-pool.h>
#include <executables/rt_profiling.h>
#define MAX_BANDS_PER_RRU 4
#define MAX_RRU_CONFIG_SIZE 1024
......@@ -168,25 +170,21 @@ typedef struct RU_prec_t_s{
int index;
} RU_prec_t;
typedef struct RU_feptx_t_s{
/// \internal This variable is protected by \ref mutex_feptx_prec
int instance_cnt_feptx;
/// pthread struct for RU TX FEP PREC worker thread
pthread_t pthread_feptx;
/// pthread attributes for worker feptx prec thread
pthread_attr_t attr_feptx;
/// condition varible for RU TX FEP PREC thread
pthread_cond_t cond_feptx;
/// mutex for fep PREC TX worker thread
pthread_mutex_t mutex_feptx;
struct RU_t_s *ru;
int aa;//physical MAX nb_tx
int half_slot;//first or second half of a slot
int slot;//current slot
int symbol;//current symbol
int nb_antenna_ports;//number of logical port
int index;
}RU_feptx_t;
typedef struct {
int aid;
struct RU_t_s *ru;
int startSymbol;
int endSymbol;
int slot;
} feprx_cmd_t;
typedef struct {
int aid;
struct RU_t_s *ru;
int slot;
int startSymbol;
int numSymbols;
} feptx_cmd_t;
typedef struct {
int frame;
......@@ -246,7 +244,7 @@ typedef struct RU_proc_t_s {
/// \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;
int instance_cnt_fep[8];
/// \internal This variable is protected by \ref mutex_feptx
int instance_cnt_feptx;
/// \internal This variable is protected by \ref mutex_ru_thread
......@@ -265,7 +263,7 @@ typedef struct RU_proc_t_s {
/// pthread struct for RU synch thread
pthread_t pthread_synch;
/// pthread struct for RU RX FEP worker thread
pthread_t pthread_fep;
pthread_t pthread_fep[8];
/// pthread struct for RU TX FEP worker thread
pthread_t pthread_feptx;
/// pthread struct for emulated RF
......@@ -318,7 +316,7 @@ typedef struct RU_proc_t_s {
/// condition variable for asynch RX/TX thread
pthread_cond_t cond_asynch_rxtx;
/// condition varible for RU RX FEP thread
pthread_cond_t cond_fep;
pthread_cond_t cond_fep[8];
/// condition varible for RU TX FEP thread
pthread_cond_t cond_feptx;
/// condition varible for emulated RF
......@@ -345,7 +343,7 @@ typedef struct RU_proc_t_s {
/// mutex for asynch RX/TX thread
pthread_mutex_t mutex_asynch_rxtx;
/// mutex for fep RX worker thread
pthread_mutex_t mutex_fep;
pthread_mutex_t mutex_fep[8];
/// mutex for fep TX worker thread
pthread_mutex_t mutex_feptx;
/// mutex for ru_thread
......@@ -395,10 +393,6 @@ typedef struct RU_proc_t_s {
/// structure for precoding thread
RU_prec_t prec[16];
/// structure for feptx thread
RU_feptx_t feptx[16];
/// mask for checking process finished
int feptx_mask;
} RU_proc_t;
typedef enum {
......@@ -433,6 +427,8 @@ typedef enum {
typedef struct RU_t_s {
/// ThreadPool for RU
tpool_t *threadPool;
/// index of this ru
uint32_t idx;
/// pointer to first RU
......@@ -507,6 +503,10 @@ typedef struct RU_t_s {
int sf_ahead;
/// TX processing advance in slots (for NR)
int sl_ahead;
/// flag to indicate TX FH is embedded in TX FEP
int txfh_in_fep;
/// flag to indicate half-slot parallelization
int half_slot_parallelization;
/// FAPI confiuration
nfapi_nr_config_request_scf_t config;
/// Frame parameters
......@@ -645,6 +645,22 @@ typedef struct RU_t_s {
uint64_t if_frequency;
/// UL IF frequency offset to DL IF frequency in Hz
int if_freq_offset;
/// to signal end of feprx
notifiedFIFO_t *respfeprx;
/// to signal end of feptx
notifiedFIFO_t *respfeptx;
/// core id for RX fhaul (IF5 ECPRI)
int rxfh_core_id;
/// core id for RX fhaul (IF5 ECPRI)
int txfh_core_id;
/// number of RU interfaces
int num_fd;
/// list of cores for RU ThreadPool
int tpcores[16];
/// number of cores for RU ThreadPool
int num_tpcores;
/// structure for analyzing high-level RT measurements
rt_ru_profiling_t rt_ru_profiling;
} RU_t;
......
......@@ -42,6 +42,7 @@
#include "PHY/defs_common.h"
#include "PHY/CODING/nrLDPC_extern.h"
#include "PHY/CODING/nrLDPC_decoder/nrLDPC_types.h"
#include "executables/rt_profiling.h"
#include "nfapi_nr_interface_scf.h"
......@@ -897,6 +898,8 @@ typedef struct PHY_VARS_gNB_s {
int number_of_nr_dlsch_max;
int number_of_nr_ulsch_max;
void * scopeData;
/// structure for analyzing high-level RT measurements
rt_L1_profiling_t rt_L1_profiling;
} PHY_VARS_gNB;
typedef struct LDPCDecode_s {
......
......@@ -57,7 +57,6 @@
#include "SCHED/sched_eNB.h"
#include "PHY/MODULATION/modulation_eNB.h"
#include "PHY/LTE_TRANSPORT/if4_tools.h"
#include "PHY/LTE_TRANSPORT/if5_tools.h"
#include "PHY/LTE_TRANSPORT/transport_common_proto.h"
#include "PHY/LTE_TRANSPORT/transport_proto.h"
#include "PHY/LTE_UE_TRANSPORT/transport_proto_ue.h"
......@@ -566,15 +565,15 @@ static void *fep_thread(void *param)
while (!oai_exit) {
if (wait_on_condition(&proc->mutex_fep,&proc->cond_fep,&proc->instance_cnt_fep,"fep thread")<0) break;
if (wait_on_condition(&proc->mutex_fep[0],&proc->cond_fep[0],&proc->instance_cnt_fep[0],"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 (release_thread(&proc->mutex_fep[0],&proc->instance_cnt_fep[0],"fep thread")<0) break;
if (pthread_cond_signal(&proc->cond_fep) != 0) {
if (pthread_cond_signal(&proc->cond_fep[0]) != 0) {
printf("[eNB] ERROR pthread_cond_signal for fep thread exit\n");
exit_fun( "ERROR pthread_cond_signal" );
return NULL;
......@@ -607,12 +606,12 @@ void init_fep_thread(RU_t *ru,
{
RU_proc_t *proc = &ru->proc;
proc->instance_cnt_fep = -1;
proc->instance_cnt_fep[0] = -1;
pthread_mutex_init( &proc->mutex_fep, NULL);
pthread_cond_init( &proc->cond_fep, NULL);
pthread_mutex_init( &proc->mutex_fep[0], NULL);
pthread_cond_init( &proc->cond_fep[0], NULL);
threadCreate(&proc->pthread_fep, fep_thread, (void*)ru, "fep", -1, OAI_PRIORITY_RT);
threadCreate(&proc->pthread_fep[0], fep_thread, (void*)ru, "fep", -1, OAI_PRIORITY_RT);
}
......@@ -621,14 +620,14 @@ void kill_fep_thread(RU_t *ru)
RU_proc_t *proc = &ru->proc;
if (proc->pthread_fep == 0)
return;
pthread_mutex_lock( &proc->mutex_fep );
proc->instance_cnt_fep = 0;
pthread_cond_signal(&proc->cond_fep);
pthread_mutex_unlock( &proc->mutex_fep );
pthread_mutex_lock( &proc->mutex_fep[0] );
proc->instance_cnt_fep[0] = 0;
pthread_cond_signal(&proc->cond_fep[0]);
pthread_mutex_unlock( &proc->mutex_fep[0] );
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 );
pthread_join(proc->pthread_fep[0], NULL);
pthread_mutex_destroy( &proc->mutex_fep[0] );
pthread_cond_destroy( &proc->cond_fep[0] );
}
......@@ -670,35 +669,35 @@ void ru_fep_full_2thread(RU_t *ru,
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);
if (pthread_mutex_timedlock(&proc->mutex_fep[0],&wait) != 0) {
printf("[RU] ERROR pthread_mutex_lock for fep thread (IC %d)\n", proc->instance_cnt_fep[0]);
exit_fun( "error locking mutex_fep" );
return;
}
if (proc->instance_cnt_fep==0) {
if (proc->instance_cnt_fep[0]==0) {
printf("[RU] FEP thread busy\n");
exit_fun("FEP thread busy");
pthread_mutex_unlock( &proc->mutex_fep );
pthread_mutex_unlock( &proc->mutex_fep[0] );
return;
}
++proc->instance_cnt_fep;
++proc->instance_cnt_fep[0];
if (pthread_cond_signal(&proc->cond_fep) != 0) {
if (pthread_cond_signal(&proc->cond_fep[0]) != 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 );
pthread_mutex_unlock( &proc->mutex_fep[0] );
// 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");
wait_on_busy_condition(&proc->mutex_fep[0],&proc->cond_fep[0],&proc->instance_cnt_fep[0],"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);
......
This diff is collapsed.
......@@ -41,18 +41,14 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx);
void L1_nr_prach_procedures(PHY_VARS_gNB *gNB,int frame,int slot);
void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame,int slot,nfapi_nr_dl_tti_ssb_pdu ssb_pdu);
void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx);
void nr_feptx_ofdm_2thread(RU_t *ru,int frame_tx,int tti_tx);
void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa);
void nr_init_feptx_thread(RU_t *ru);
void nr_kill_feptx_thread(RU_t *ru);
void fep_full(RU_t *ru,int slot);
void nr_feptx_prec(RU_t *ru,int frame_tx,int tti_tx);
void nr_init_feptx_prec_thread(RU_t *ru);
void nr_feptx_prec_control(RU_t *ru,int frame,int tti_tx);
void nr_init_feprx_thread(RU_t *ru);
void nr_kill_feprx_thread(RU_t *ru);
void nr_fep_full(RU_t *ru, int slot);
void nr_fep_full_2thread(RU_t *ru, int slot);
void nr_fep_tp(RU_t *ru, int slot);
void nr_feptx_tp(RU_t *ru, int frame_tx, int slot);
void feptx_prec(RU_t *ru,int frame_tx,int tti_tx);
int nr_phy_init_RU(RU_t *ru);
void nr_phy_free_RU(RU_t *ru);
......
......@@ -1533,7 +1533,7 @@ int main(int argc, char **argv) {
}//ch realization
oai_exit=1;
pthread_cond_signal(&ru->proc.cond_fep);
pthread_cond_signal(&ru->proc.cond_fep[0]);
if (abstx) { // ABSTRACTION
fprintf(csv_fdUL,"];");
......
......@@ -1063,7 +1063,6 @@ int main(int argc, char **argv)
double blerStats[4][100];
double berStats[4][100];
double snrStats[100];
double ldpcDecStats[100] = {0};
memset(errors_scrambling, 0, sizeof(uint32_t)*4*100);
memset(n_errors, 0, sizeof(int)*4*100);
memset(round_trials, 0, sizeof(int)*4*100);
......@@ -1633,8 +1632,6 @@ int main(int argc, char **argv)
printf("\n");
}
ldpcDecStats[snrRun] = gNB->ulsch_decoding_stats.trials?inMicroS(gNB->ulsch_decoding_stats.diff/gNB->ulsch_decoding_stats.trials):0;
if(n_trials==1)
break;
......
......@@ -103,11 +103,23 @@ typedef enum {
#define CONFIG_STRING_RU_SL_AHEAD "sl_ahead"
#define CONFIG_STRING_RU_NR_FLAG "nr_flag"
#define CONFIG_STRING_RU_NR_SCS_FOR_RASTER "nr_scs_for_raster"
#define CONFIG_STRING_RU_RXFH_CORE_ID "rxfh_core_id"
#define CONFIG_STRING_RU_TXFH_CORE_ID "txfh_core_id"
#define CONFIG_STRING_RU_TP_CORES "tp_cores"
#define CONFIG_STRING_RU_NUM_TP_CORES "num_tp_cores"
#define CONFIG_STRING_RU_NUM_INTERFACES "num_interfaces"
#define CONFIG_STRING_RU_HALF_SLOT_PARALLELIZATION "half_slot_parallelization"
#define HLP_RU_SF_AHEAD "LTE TX processing advance"
#define HLP_RU_SL_AHEAD "NR TX processing advance"
#define HLP_RU_NR_FLAG "Use NR numerology (for AW2SORI)"
#define HLP_RU_NR_SCS_FOR_RASTER "NR SCS for raster (for AW2SORI)"
#define HLP_RU_RXFH_CORE_ID "Core ID for RX Fronthaul thread (ECPRI IF5)"
#define HLP_RU_TXFH_CORE_ID "Core ID for TX Fronthaul thread (ECPRI IF5)"
#define HLP_RU_TP_CORES "List of cores for RU ThreadPool"
#define HLP_RU_NUM_TP_CORES "Number of cores for RU ThreadPool"
#define HLP_RU_NUM_INTERFACES "Number of network interfaces for RU"
#define HLP_RU_HALF_SLOT_PARALLELIZATION "run half slots in parallel in RU FEP"
#define RU_LOCAL_IF_NAME_IDX 0
#define RU_LOCAL_ADDRESS_IDX 1
......@@ -142,6 +154,12 @@ typedef enum {
#define RU_SL_AHEAD 30
#define RU_NR_FLAG 31
#define RU_NR_SCS_FOR_RASTER 32
#define RU_RXFH_CORE_ID 33
#define RU_TXFH_CORE_ID 34
#define RU_TP_CORES 35
#define RU_NUM_TP_CORES 36
#define RU_NUM_INTERFACES 37
#define RU_HALF_SLOT_PARALLELIZATION 38
/*-----------------------------------------------------------------------------------------------------------------------------------------*/
/* RU configuration parameters */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
......@@ -180,6 +198,12 @@ typedef enum {
{CONFIG_STRING_RU_SL_AHEAD, HLP_RU_SL_AHEAD, 0, iptr:NULL, defintval:6, TYPE_INT, 0}, \
{CONFIG_STRING_RU_NR_FLAG, HLP_RU_NR_FLAG, 0, iptr:NULL, defintval:0, TYPE_INT, 0}, \
{CONFIG_STRING_RU_NR_SCS_FOR_RASTER, HLP_RU_NR_SCS_FOR_RASTER, 0, iptr:NULL, defintval:1, TYPE_INT, 0}, \
{CONFIG_STRING_RU_RXFH_CORE_ID, HLP_RU_RXFH_CORE_ID, 0, uptr:NULL, defintval:0, TYPE_UINT, 0}, \
{CONFIG_STRING_RU_TXFH_CORE_ID, HLP_RU_TXFH_CORE_ID, 0, uptr:NULL, defintval:0, TYPE_UINT, 0}, \
{CONFIG_STRING_RU_TP_CORES, HLP_RU_TP_CORES, 0, uptr:NULL, defintarrayval:DEFRUTPCORES, TYPE_INTARRAY, 8}, \
{CONFIG_STRING_RU_NUM_TP_CORES, HLP_RU_NUM_TP_CORES, 0, uptr:NULL, defintval:2, TYPE_UINT, 0}, \
{CONFIG_STRING_RU_NUM_INTERFACES, HLP_RU_NUM_INTERFACES, 0, uptr:NULL, defintval:1, TYPE_UINT, 0}, \
{CONFIG_STRING_RU_HALF_SLOT_PARALLELIZATION, HLP_RU_HALF_SLOT_PARALLELIZATION, 0, uptr:NULL, defintval:1, TYPE_UINT, 0}, \
}
/*---------------------------------------------------------------------------------------------------------------------------------------*/
......
......@@ -1962,7 +1962,7 @@ void get_delta_arfcn(int i, uint32_t nrarfcn, uint64_t N_OFFs){
uint32_t delta_arfcn = nrarfcn - N_OFFs;
if(delta_arfcn%(nr_bandtable[i].step_size)!=0)
AssertFatal(1 == 0, "nrarfcn %u is not on the channel raster for step size %lu", nrarfcn, nr_bandtable[i].step_size);
AssertFatal(1==0, "nrarfcn %u is not on the channel raster for step size %lu", nrarfcn, nr_bandtable[i].step_size);
}
......@@ -1982,10 +1982,10 @@ uint32_t to_nrarfcn(int nr_bandP,
"Band %d, bw %u : DL carrier frequency %llu kHz < %llu\n",
nr_bandP, bw, (long long unsigned int)dl_CarrierFreq_by_1k,
(long long unsigned int)nr_bandtable[i].dl_min);
AssertFatal(dl_CarrierFreq_by_1k <= (nr_bandtable[i].dl_max - bw_kHz),
AssertFatal(dl_CarrierFreq_by_1k <= (nr_bandtable[i].dl_max - bw_kHz/2),
"Band %d, dl_CarrierFreq %llu bw %u: DL carrier frequency %llu kHz > %llu\n",
nr_bandP, (long long unsigned int)dl_CarrierFreq,bw, (long long unsigned int)dl_CarrierFreq_by_1k,
(long long unsigned int)(nr_bandtable[i].dl_max - bw_kHz));
(long long unsigned int)(nr_bandtable[i].dl_max - bw_kHz/2));
int deltaFglobal = 60;
uint32_t N_REF_Offs = 2016667;
......@@ -2005,7 +2005,7 @@ uint32_t to_nrarfcn(int nr_bandP,
// This is equation before Table 5.4.2.1-1 in 38101-1-f30
// F_REF=F_REF_Offs + deltaF_Global(N_REF-NREF_REF_Offs)
nrarfcn = (((dl_CarrierFreq_by_1k - F_REF_Offs_khz)/deltaFglobal)+N_REF_Offs);
get_delta_arfcn(i, nrarfcn, nr_bandtable[i].N_OFFs_DL);
//get_delta_arfcn(i, nrarfcn, nr_bandtable[i].N_OFFs_DL);
return nrarfcn;
}
......
......@@ -512,6 +512,7 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP,
int nr_dl_slots = n;
int nr_ulstart_slot = 0;
if (tdd) {
nr_ulstart_slot = tdd->nrofDownlinkSlots + (tdd->nrofUplinkSymbols == 0);
nr_dl_slots = tdd->nrofDownlinkSlots + (tdd->nrofDownlinkSymbols != 0);
nr_ulstart_slot = tdd->nrofDownlinkSlots + (tdd->nrofUplinkSymbols == 0);
nr_slots_period /= get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity);
......
......@@ -868,11 +868,12 @@ rrc_gNB_generate_dedicatedRRCReconfiguration(
DRB_config->pdcp_Config->drb->integrityProtection = NULL;
DRB_config->pdcp_Config->drb->statusReportRequired = NULL;
DRB_config->pdcp_Config->drb->outOfOrderDelivery = NULL;
DRB_config->pdcp_Config->drb->outOfOrderDelivery = calloc(1,sizeof(*DRB_config->pdcp_Config->drb->outOfOrderDelivery));
*DRB_config->pdcp_Config->drb->outOfOrderDelivery = NR_PDCP_Config__drb__outOfOrderDelivery_true;
DRB_config->pdcp_Config->moreThanOneRLC = NULL;
DRB_config->pdcp_Config->t_Reordering = calloc(1, sizeof(*DRB_config->pdcp_Config->t_Reordering));
*DRB_config->pdcp_Config->t_Reordering = NR_PDCP_Config__t_Reordering_ms0;
*DRB_config->pdcp_Config->t_Reordering = NR_PDCP_Config__t_Reordering_ms20;
DRB_config->pdcp_Config->ext1 = NULL;
if (rrc->security.do_drb_integrity) {
......
......@@ -16,16 +16,18 @@
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <net/if.h>
#include <netinet/ether.h>
#include <unistd.h>
#include <errno.h>
#include <linux/sysctl.h>
#include <sys/sysctl.h>
#include <pthread.h>
#include "common_lib.h"
#include "ethernet_lib.h"
#include "common/utils/system.h"
#include "ori.h"
#include "targets/ARCH/COMMON/common_lib.h"
......@@ -250,7 +252,6 @@ int aw2s_startstreaming(openair0_device *device) {
}
ORI_Object_s *link= ORI_FindObject(ori, ORI_ObjectType_ORILink, 0, NULL);
if (tx0 == NULL ||
(tx1 == NULL && openair0_cfg->tx_num_channels > 1) ||
(tx2 == NULL && openair0_cfg->tx_num_channels > 2) ||
......@@ -335,7 +336,7 @@ int aw2s_startstreaming(openair0_device *device) {
printf("\n\n\n========================================================\n");
/* Put Tx3 into service */
result = ORI_ObjectStateModification(ori, tx1, ORI_AST_Unlocked, &RE_result);
result = ORI_ObjectStateModification(ori, tx3, ORI_AST_Unlocked, &RE_result);
if(result != ORI_Result_SUCCESS)
{
printf("ORI_ObjectStateModify failed with error: %s\n", ORI_Result_Print(result));
......@@ -402,7 +403,7 @@ int aw2s_startstreaming(openair0_device *device) {
if (rx3) {
printf("\n\n\n========================================================\n");
/* Put Rx1 into service */
/* Put Rx3 into service */
result = ORI_ObjectStateModification(ori, rx3, ORI_AST_Unlocked, &RE_result);
if(result != ORI_Result_SUCCESS)
{
......@@ -412,37 +413,8 @@ int aw2s_startstreaming(openair0_device *device) {
}
printf("ORI_ObjectStateModify: %s\n", ORI_Result_Print(RE_result));
}
/*
while (rx0->fst != ORI_FST_Operational ||
(openair0_cfg->rx_num_channels > 1 && rx1->fst != ORI_FST_Operational) ||
tx0->fst != ORI_FST_Operational ||
(openair0_cfg->tx_num_channels > 1 && tx1->fst != ORI_FST_Operational))
{}*/
// test RX interface
uint64_t TS;
char temp_rx[2048] __attribute__((aligned(32)));
int aid,r0=0,r1=(openair0_cfg->rx_num_channels > 1) ? 0 : 1;
int r2=(openair0_cfg->rx_num_channels > 2) ? 0 : 1;
int r3=(openair0_cfg->rx_num_channels > 3) ? 0 : 1;
int i;
int Npackets=1024000;
for (i=0;i<Npackets;i++) {
device->trx_read_func2(device,
(openair0_timestamp*)&TS,
(void*)temp_rx,
256,
&aid);
if (aid == 0) r0=1;
if (aid == 1) r1=1;
if (aid == 2) r2=1;
if (aid == 3) r3=1;
}
if (r0==1 && r1==1 && r2==1 && r3==1) printf("Streaming started, returning to OAI\n");
else {
printf("Didn't get anything from one antenna port after %d packets %d,%d,%d,%d\n",Npackets,r0,r1,r2,r3);
return(-1);
}
device->fhstate.active=1;
return(0);
}
......@@ -924,7 +896,7 @@ int aw2s_oriinit(openair0_device *device) {
int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t * eth_params ) {
printf("Initializing AW2S (%p,%p,%p)\n",aw2s_oriinit,aw2s_oricleanup,aw2s_startstreaming);
device->thirdparty_init = aw2s_oriinit;
device->thirdparty_cleanup = aw2s_oricleanup;
device->thirdparty_startstreaming = aw2s_startstreaming;
......
......@@ -37,6 +37,7 @@
#include <sys/types.h>
#include <openair1/PHY/TOOLS/tools_defs.h>
#include "record_player.h"
#include <common/utils/threadPool/thread-pool.h>
/* default name of shared library implementing the radio front end */
#define OAI_RF_LIBNAME "oai_device"
......@@ -153,6 +154,14 @@ typedef enum {
gpsdo=2
} clock_source_t;
/*! \brief Structure used for initializing UDP read threads */
typedef struct {
openair0_device *device;
int thread_id;
pthread_t pthread;
notifiedFIFO_t *resp;
} udp_ctx_t;
/*! \brief RF frontend parameters set by application */
typedef struct {
......@@ -178,9 +187,11 @@ typedef struct {
int rx_num_channels;
//! number of TX channels (=TX antennas)
int tx_num_channels;
//! \brief RX base addresses for mmapped_dma
//! \brief RX base addresses for mmapped_dma or direct access
int32_t *rxbase[4];
//! \brief TX base addresses for mmapped_dma
//! \brief RX buffer size for direct access
int rxsize;
//! \brief TX base addresses for mmapped_dma or direct access
int32_t *txbase[4];
//! \brief Center frequency in Hz for RX.
//! index: [0..rx_num_channels[
......@@ -246,6 +257,10 @@ typedef struct {
int nr_band;
//! NR scs for raster
int nr_scs_for_raster;
//! Core IDs for RX FH
int rxfh_cores[4];
//! Core IDs for TX FH
int txfh_cores[4];
} openair0_config_t;
/*! \brief RF mapping */
......@@ -314,6 +329,19 @@ typedef struct {
bool write_thread_exit;
} openair0_thread_t;
typedef struct fhstate_s {
openair0_timestamp TS[8];
openair0_timestamp TS0;
openair0_timestamp olddeltaTS[8];
openair0_timestamp oldTS[8];
openair0_timestamp TS_read;
int first_read;
uint32_t *buff[8];
uint32_t buff_size;
int r[8];
int active;
} fhstate_t;
/*!\brief structure holds the parameters to configure USRP devices */
struct openair0_device_t {
/*!tx write thread*/
......@@ -348,6 +376,24 @@ struct openair0_device_t {
/*!brief Can be used by driver to hold internal structure*/
void *priv;
/*!brief pointer to FH state, used in ECPRI split 8*/
fhstate_t fhstate;
/*!brief message response for notification fifo*/
notifiedFIFO_t *respudpTX;
/*!brief UDP TX thread context*/
udp_ctx_t **utx;
/*!brief Used in ECPRI split 8 to indicate numerator of sampling rate ratio*/
int sampling_rate_ratio_n;
/*!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
......@@ -394,7 +440,7 @@ struct openair0_device_t {
@param antenna_id index of the antenna if the device has multiple anteannas
@param flags flags must be set to true if timestamp parameter needs to be applied
*/
int (*trx_write_func2)(openair0_device *device, openair0_timestamp timestamp, void *buff, int nsamps,int antenna_id, int flags);
int (*trx_write_func2)(openair0_device *device, openair0_timestamp timestamp, void **buff, int fd_ind,int nsamps, int flags,int nant);
/*! \brief Receive samples from hardware.
* Read \ref nsamps samples from each channel to buffers. buff[0] is the array for
......@@ -416,12 +462,13 @@ struct openair0_device_t {
* was received.
* \param device the hardware to use
* \param[out] ptimestamp the time at which the first sample was received.
* \param[out] buff A pointers to a buffer for received samples. The buffer must be large enough to hold the number of samples \ref nsamps.
* \param[out] buff A pointer to a buffer[ant_id][] for received samples. The buffer[ant_id] must be large enough to hold the number of samples \ref nsamps * the number of packets.
* \param nsamps Number of samples. One sample is 2 byte I + 2 byte Q => 4 byte.
* \param packet_idx offset into
* \param antenna_id Index of antenna from which samples were received
* \returns the number of sample read
*/
int (*trx_read_func2)(openair0_device *device, openair0_timestamp *ptimestamp, void *buff, int nsamps,int *antenna_id);
int (*trx_read_func2)(openair0_device *device, openair0_timestamp *ptimestamp, uint32_t **buff, int nsamps);
/*! \brief print the device statistics
* \param device the hardware to use
......@@ -470,6 +517,7 @@ struct openair0_device_t {
/*! \brief Pointer to generic RRU private information
*/
void *thirdparty_priv;
/*! \brief Callback for Third-party RRU Initialization routine
......@@ -496,6 +544,9 @@ struct openair0_device_t {
* \return a pointer to the parameter
*/
void *(*get_internal_parameter)(char *id);
/* \brief timing statistics for TX fronthaul (ethernet)
*/
time_stats_t tx_fhaul;
};
/* type of device init function, implemented in shared lib */
......
......@@ -80,10 +80,11 @@ int eth_socket_init_raw(openair0_device *device) {
perror("ETHERNET: Error opening RAW socket (control)");
exit(0);
}
if ((eth->sockfdd = socket(sock_dom, sock_type, sock_proto)) == -1) {
perror("ETHERNET: Error opening RAW socket (user)");
exit(0);
}
for (int i=0;i<eth->num_fd;i++)
if ((eth->sockfdd[i] = socket(sock_dom, sock_type, sock_proto)) == -1) {
perror("ETHERNET: Error opening RAW socket (user)");
exit(0);
}
/* initialize destination address */
bzero((void *)&(eth->local_addrc_ll), sizeof(struct sockaddr_ll));
......@@ -94,8 +95,9 @@ int eth_socket_init_raw(openair0_device *device) {
strcpy(eth->if_index.ifr_name,eth->if_name);
if (ioctl(eth->sockfdc, SIOCGIFINDEX, &(eth->if_index)) < 0)
perror("SIOCGIFINDEX");
if (ioctl(eth->sockfdd, SIOCGIFINDEX, &(eth->if_index)) < 0)
perror("SIOCGIFINDEX");
for (int i=0;i<eth->num_fd;i++)
if (ioctl(eth->sockfdd[i], SIOCGIFINDEX, &(eth->if_index)) < 0)
perror("SIOCGIFINDEX");
eth->local_addrc_ll.sll_family = AF_PACKET;
eth->local_addrc_ll.sll_ifindex = eth->if_index.ifr_ifindex;
......@@ -111,10 +113,11 @@ int eth_socket_init_raw(openair0_device *device) {
eth->local_addrd_ll.sll_pkttype = PACKET_OTHERHOST;
eth->addr_len = sizeof(struct sockaddr_ll);
if (bind(eth->sockfdd,(struct sockaddr *)&eth->local_addrd_ll,eth->addr_len)<0) {
perror("ETHERNET: Cannot bind to socket (user)");
exit(0);
}
for (int i=0;i<eth->num_fd;i++)
if (bind(eth->sockfdd[i],(struct sockaddr *)&eth->local_addrd_ll,eth->addr_len)<0) {
perror("ETHERNET: Cannot bind to socket (user)");
exit(0);
}
/* Construct the Ethernet header */
ether_aton_r(local_mac, (struct ether_addr *)(&(eth->ehd.ether_shost)));
......@@ -165,7 +168,7 @@ int trx_eth_write_raw(openair0_device *device, openair0_timestamp timestamp, voi
/* Send packet */
bytes_sent += send(eth->sockfdd,
bytes_sent += send(eth->sockfdd[cc % eth->num_fd],
buff2,
pktsize,
sendto_flag);
......@@ -214,7 +217,7 @@ int trx_eth_write_raw_IF4p5(openair0_device *device, openair0_timestamp timestam
memcpy(buff[0], (void*)&eth->ehd, MAC_HEADER_SIZE_BYTES);
bytes_sent = send(eth->sockfdd,
bytes_sent = send(eth->sockfdd[cc % eth->num_fd],
buff[0],
packet_size,
0);
......@@ -266,7 +269,7 @@ int trx_eth_read_raw(openair0_device *device, openair0_timestamp *timestamp, voi
while(bytes_received < receive_bytes) {
again:
ret = recv(eth->sockfdd,
ret = recv(eth->sockfdd[cc % eth->num_fd],
buff2,
receive_bytes,
rcvfrom_flag);
......@@ -345,7 +348,7 @@ int trx_eth_read_raw_IF4p5(openair0_device *device, openair0_timestamp *timestam
while (bytes_received < packet_size) {
again:
ret = recv(eth->sockfdd,
ret = recv(eth->sockfdd[cc % eth->num_fd],
buff[0],
packet_size,
MSG_PEEK);
......@@ -397,7 +400,7 @@ int trx_eth_read_raw_IF4p5(openair0_device *device, openair0_timestamp *timestam
}
while(bytes_received < packet_size) {
ret = recv(eth->sockfdd,
ret = recv(eth->sockfdd[cc % eth->num_fd],
buff[0],
packet_size,
0);
......
# Ethernet drivers
This directory contains ethernet-based drivers for fronthaul. The only functional versions today are ECPRI time-domain (split 8) over UDP for AW2S and IF4.5 (split 7) for OAI RU over UDP. The RAW ethernet implementation is currently not tested and quite possibly obsolete.
## license
Author:
Raymond Knopp, EURECOM
OAI License V1.1
# Top-level
The files implement the OAI IF device interface which provides the transmit/receive (trx) functions for generic ethernet-based devices. Some minimal control-plane socket handling for IF4p5 is also provided. It comprises the following top-level functions (ethernet_lib.c) which are mapped to the OAI device structure:
* trx_eth_start : create sockets and threads to handle I/O
* trx_eth_end : close sockets
* trx_eth_stop : stops 3rd party (AW2S) device
* trx_eth_set_freq : empty
* trx_eth_set_gains : empty
* trx_eth_get_stats : empty
* trx_eth_reset_stats : empty
* trx_eth_write_init : empty
* ethernet_tune : write certain performance-related parameters to ethernet device
* transport_init : entry routine to fill device data structure with function pointers
# IF4p5 U-plane implementation
It is contained in the eth_udp.c and eth_raw.c files. The two basic routines are
* trx_eth_read_udp_IF4p5() : implements a blocking read for three particular IF4p5 packets, IF4p5_PULFFT (for OAI RCC/DU), IF4p5_PRACH and IF4p5_PDLFFT (for OAI RU). The packets are parsed and mapped to the appropriate physical channels by the OAI physical layer
* trx_eth_write_udp_IF4p5 : implements a write for the three IF4p5 packets.
* trx_eth_ctlsend_udp : implements the sending component for the control socket
* trx_eth_ctlrecv_udp : implements the receive component for the control socket (blocking read)
# ECPRI U-plane implementation
It is contained in the eth_udp.c file and only implements ECPRI/UDP. The implementation has 2 top-level functions:
* trx_eth_write_udp : This sends a stream of packets containing 16-bit I/ 16-bit Q samples to the ECPRI RU. It uses the proprietary AW2S format (user-defined). Each packet carries 256 samples and some header information (timestamp, antenna index) and fits inslightly more than 1024 bytes. Each packet with Ethernet, IP and UDP headers fits into a regular Ethernet frame. The transmit function does not block and pushes the data to a worker thread (udp_write_thread) which runs in the background. The worker thread scales the IQ samples to fit in 16-bit units and forms the ECPRI packets for each antenna. The signals are split into 256-sample chunks and antennas are handled in sequence for each chunk. This ensures that all antennas receive their signals more or less at the same time.
* trx_eth_read_udp : This is a blocking read which waits for a worker thread (udp_read_thread) listening on the U-plane socket to have acquired enough samples satisfying the request (nsamps). The requests are usually a slot (NR) or subframe (LTE) worth of samples. The worker thread identifies the antenna index (aid) and timestamp of each packet and copies the received chunk into the destination memory location according to the timestamp modulo the length of the receive buffer. The memory location for read is identifited during initialization of the interface and is written circularly. Typically the buffer would contain a frame's worth of samples, but this is not a requirement. There is only one memcpy in the driver and the end OAI application can use the data in its normal local buffer (RU.common.rxdata[aid]). The memcpy is needed since the destination address depends on the antenna index which is carried in the received packet itself. Kernel filtering and redirection (C/EBPF,XDP) doesn't seem to be possible with the AW2S packet format.
The two threads should be pinned to isolated CPUs to maximize performance. Their CPU id's can be passed to the driver from the OAI application. tx_fh_core and rx_fh_core in the RU section of the OAI .conf file.
# Obsolete code
Non ECPRI split 8 and IF4p5 with RAW sockets is not functional anymore (eth_raw.c). split-8 will be resusitated if an RU implementing ECPRI is integrated with OAI. IF4p5 with raw sockets is replaced with the FHI Split 7.2 interface.
......@@ -41,6 +41,7 @@
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/ether.h>
#include <common/utils/threadPool/thread-pool.h>
#define MAX_INST 4
#define DEFAULT_IF "lo"
......@@ -59,12 +60,16 @@ typedef struct {
/*!\brief socket file desc (control)*/
int sockfdc;
/*!\brief number of sockets for user-plane*/
int num_fd;
/*!\brief socket file desc (user)*/
int sockfdd;
int sockfdd[8];
/*!\brief interface name */
char *if_name;
/*!\brief buffer size */
unsigned int buffer_size;
/*!\brief Fronthaul state */
fhstate_t *fhstate;
/*!\brief destination address (control) for UDP socket*/
struct sockaddr_in dest_addrc;
/*!\brief local address (control) for UDP socket*/
......@@ -205,6 +210,28 @@ typedef struct {
short q;
} iqoai_t ;
typedef struct udpTXelem_s {
openair0_device *device;
openair0_timestamp timestamp;
void **buff;
int fd_ind;
int nant;
int nsamps;
int flags;
} udpTXelem_t;
struct udpTXReqId {
uint64_t TS;
int aid;
int length;
uint16_t spare;
} __attribute__((packed));
union udpTXReqUnion {
struct udpTXReqId s;
uint64_t p;
};
void dump_packet(char *title, unsigned char* pkt, int bytes, unsigned int tx_rx_flag);
unsigned short calc_csum (unsigned short *buf, int nwords);
void dump_dev(openair0_device *device);
......@@ -214,7 +241,8 @@ void inline dump_txcounters(openair0_device *device);
*/
void dump_iqs(char * buff, int iq_cnt);
void *udp_read_thread(void *arg);
void *udp_write_thread(void *arg);
/*! \fn int ethernet_tune (openair0_device *device, unsigned int option, int value);
* \brief this function allows you to configure certain ethernet parameters in socket or device level
......@@ -237,8 +265,8 @@ int ethernet_tune(openair0_device *device, unsigned int option, int value);
* @ingroup _oai
*/
int eth_socket_init_udp(openair0_device *device);
int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, void *buff, int nsamps,int cc, int flags);
int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, void *buff, int nsamps, int *cc);
int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, void **buf, int fd_ind, int nsamps, int flags,int nant);
int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, uint32_t **buff, int nsamps);
int eth_socket_init_raw(openair0_device *device);
......
......@@ -38,7 +38,6 @@
#ifndef LITE_COMPILATION
#include "PHY/LTE_TRANSPORT/if4_tools.h"
#include "PHY/LTE_TRANSPORT/if5_tools.h"
#endif
// ETH transport preference modes
......
......@@ -67,7 +67,6 @@
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
#include "PHY/LTE_TRANSPORT/if4_tools.h"
#include "PHY/LTE_TRANSPORT/if5_tools.h"
#include "PHY/LTE_ESTIMATION/lte_estimation.h"
#include "PHY/phy_extern.h"
......
......@@ -54,7 +54,6 @@
#include "PHY/LTE_ESTIMATION/lte_estimation.h"
#include "PHY/LTE_REFSIG/lte_refsig.h"
#include "PHY/LTE_TRANSPORT/if4_tools.h"
#include "PHY/LTE_TRANSPORT/if5_tools.h"
#include "PHY/LTE_TRANSPORT/transport_proto.h"
#include "SCHED/sched_common.h"
#include "common/utils/LOG/log.h"
......@@ -66,6 +65,8 @@
static int DEFBANDS[] = {7};
static int DEFENBS[] = {0};
static int DEFBFW[] = {0x00007fff};
static int DEFRUTPCORES[] = {2,4,6,8};
#include "ENB_APP/enb_paramdef.h"
#include "common/config/config_userapi.h"
......@@ -134,8 +135,18 @@ static inline void fh_if5_south_out(RU_t *ru,int frame, int subframe, uint64_t t
if (ru->idx == 0) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );
ru->south_out_cnt++;
int offset = subframe*ru->frame_parms->samples_per_tti;
void *buffs[ru->nb_tx];
for (int aid=0;aid<ru->nb_tx;aid++) buffs[aid] = (void*)&ru->common.txdata[aid][offset];
ru->ifdevice.trx_write_func2(&ru->ifdevice,
timestamp,
buffs,
0,
ru->frame_parms->samples_per_tti,
0,
ru->nb_tx);
send_IF5(ru, timestamp, subframe, &ru->seqno, IF5_RRH_GW_DL);
}
......@@ -172,7 +183,7 @@ void fh_if5_south_in(RU_t *ru,
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);
ru->ifdevice.trx_read_func2(&ru->ifdevice,&proc->timestamp_rx,NULL,fp->samples_per_tti);
proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023;
proc->tti_rx = (proc->timestamp_rx / fp->samples_per_tti)%10;
......@@ -398,8 +409,8 @@ void fh_if5_north_asynch_in(RU_t *ru,
LTE_DL_FRAME_PARMS *fp = ru->frame_parms;
RU_proc_t *proc = &ru->proc;
int tti_tx,frame_tx;
openair0_timestamp timestamp_tx;
recv_IF5(ru, &timestamp_tx, *subframe, IF5_RRH_GW_DL);
openair0_timestamp timestamp_tx=0;
//recv_IF5(ru, &timestamp_tx, *subframe, IF5_RRH_GW_DL);
// LOG_I(PHY,"Received subframe %d (TS %llu) from RCC\n",tti_tx,timestamp_tx);
tti_tx = (timestamp_tx/fp->samples_per_tti)%10;
frame_tx = (timestamp_tx/(fp->samples_per_tti*10))&1023;
......@@ -492,11 +503,9 @@ void fh_if4p5_north_asynch_in(RU_t *ru,
void fh_if5_north_out(RU_t *ru) {
RU_proc_t *proc=&ru->proc;
uint8_t seqno=0;
/// **** send_IF5 of rxdata to BBU **** ///
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 );
send_IF5(ru, proc->timestamp_rx, proc->tti_rx, &seqno, IF5_RRH_GW_UL);
// send_IF5(ru, proc->timestamp_rx, proc->tti_rx, &seqno, IF5_RRH_GW_UL);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 );
}
......
......@@ -57,7 +57,6 @@
#include "../../ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h"
#include "PHY/LTE_TRANSPORT/if4_tools.h"
#include "PHY/LTE_TRANSPORT/if5_tools.h"
#include "PHY/LTE_TRANSPORT/transport_proto.h"
#include "SCHED/sched_eNB.h"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment