diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 95d46184e3..43e86ad71c 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -1812,8 +1812,8 @@ void set_function_spec_param(RU_t *ru) { } else if (ru->function == gNodeB_3GPP) { ru->do_prach = 0; // no prach processing in RU ru->feprx = nr_fep_tp; // this is frequency-shift + DFTs - ru->feptx_ofdm = nr_feptx_tp; // this is fep with idft and precoding - ru->feptx_prec = nr_feptx_prec; // this is fep with idft and precoding + ru->feptx_ofdm = nr_feptx_tp; // this is fep with idft and precoding + ru->feptx_prec = NULL; ru->fh_north_in = NULL; // no incoming fronthaul from north ru->fh_north_out = NULL; // no outgoing fronthaul to north ru->nr_start_if = NULL; // no if interface @@ -1844,7 +1844,7 @@ void set_function_spec_param(RU_t *ru) { ru->do_prach = 0; ru->txfh_in_fep = 0; ru->feprx = nr_fep_tp; // this is frequency-shift + DFTs - ru->feptx_prec = nr_feptx_prec; // need to do transmit Precoding + IDFTs + ru->feptx_prec = NULL; // need to do transmit Precoding + IDFTs ru->feptx_ofdm = nr_feptx_tp; // need to do transmit Precoding + IDFTs ru->fh_south_in = fh_if5_south_in; // synchronous IF5 reception ru->fh_south_out = (ru->txfh_in_fep>0) ? NULL : fh_if5_south_out; // synchronous IF5 transmission @@ -1871,7 +1871,7 @@ void set_function_spec_param(RU_t *ru) { case REMOTE_IF4p5: ru->do_prach = 0; ru->feprx = NULL; // DFTs - ru->feptx_prec = nr_feptx_prec; // Precoding operation + ru->feptx_prec = NULL; // Precoding operation ru->feptx_ofdm = NULL; // no OFDM mod ru->fh_south_in = fh_if4p5_south_in; // synchronous IF4p5 reception ru->fh_south_out = fh_if4p5_south_out; // synchronous IF4p5 transmission diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet.md b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet.md index cdad36ad51..4751cfe74a 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet.md +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet.md @@ -9,7 +9,7 @@ This directory contains ethernet-based drivers for fronthaul. The only functiona OAI License V1.1 # Top-level -The implement the OAI IF device interface which provides the transmit/receive (trx) functions for OAI. 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: +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 @@ -38,9 +38,9 @@ It is contained in the eth_udp.c and eth_raw.c files. The two basic routines are 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 inslitly 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_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). Usually a slot or subframe 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. There is only one memcpy in the driver and the end OAI application can use the data in its normal local (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) doesn't seem to be possible with the AW2S packet format. +* 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.