Add O-RAN 7.2 FHI library
- Add the O-RAN 7.2 FHI library, interfacing with OSC xRAN library (E release) - Add Findxran.cmake to detect the library and headers, including version information - Test for numa and DPDK presence - Add patch for OSC xRAN to make interworking possible - Add sample config files for LiteOn, Benetel, and VVDN units. Documentation is provided in the next commit. Co-authored-by: Raymond Knopp <raymond.knopp@eurecom.fr> Co-authored-by: Cedric Roux <cedric.roux@eurecom.fr> Co-authored-by: Manish Kumar Singh <manish1.kumar@amd.com> Co-authored-by: thamizhselvan.k <thamizhselvan.k@vvdntech.in> Co-authored-by: rajeshwari.p <rajeshwari.p@vvdntech.in> Co-authored-by: Hongzhi Wang <hongzhi.wang@openairinterface.org> Co-authored-by: Sofia Pison <Sofia.Pison@eurecom.fr>
This commit is contained in:
co-authored by
Raymond Knopp
Cedric Roux
Manish Kumar Singh
thamizhselvan.k
rajeshwari.p
Hongzhi Wang
Sofia Pison
parent
eca56653c1
commit
baea11c35c
@@ -0,0 +1,318 @@
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include "common_lib.h"
|
||||
#include "radio/ETHERNET/ethernet_lib.h"
|
||||
#include "oran_isolate.h"
|
||||
#include "oran-init.h"
|
||||
#include "xran_fh_o_du.h"
|
||||
#include "xran_sync_api.h"
|
||||
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
#include "openair1/PHY/defs_gNB.h"
|
||||
#include "common/utils/threadPool/thread-pool.h"
|
||||
#include "oaioran.h"
|
||||
|
||||
typedef struct {
|
||||
eth_state_t e;
|
||||
rru_config_msg_type_t last_msg;
|
||||
int capabilities_sent;
|
||||
void *oran_priv;
|
||||
} oran_eth_state_t;
|
||||
|
||||
notifiedFIFO_t oran_sync_fifo;
|
||||
|
||||
int trx_oran_start(openair0_device *device)
|
||||
{
|
||||
printf("ORAN: %s\n", __FUNCTION__);
|
||||
|
||||
oran_eth_state_t *s = device->priv;
|
||||
|
||||
// Start ORAN
|
||||
if (xran_start(s->oran_priv) != 0) {
|
||||
printf("%s:%d:%s: Start ORAN failed ... Exit\n", __FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
} else {
|
||||
printf("Start ORAN. Done\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void trx_oran_end(openair0_device *device)
|
||||
{
|
||||
printf("ORAN: %s\n", __FUNCTION__);
|
||||
oran_eth_state_t *s = device->priv;
|
||||
xran_close(s->oran_priv);
|
||||
}
|
||||
|
||||
int trx_oran_stop(openair0_device *device)
|
||||
{
|
||||
printf("ORAN: %s\n", __FUNCTION__);
|
||||
oran_eth_state_t *s = device->priv;
|
||||
xran_stop(s->oran_priv);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int trx_oran_set_freq(openair0_device *device, openair0_config_t *openair0_cfg)
|
||||
{
|
||||
printf("ORAN: %s\n", __FUNCTION__);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int trx_oran_set_gains(openair0_device *device, openair0_config_t *openair0_cfg)
|
||||
{
|
||||
printf("ORAN: %s\n", __FUNCTION__);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int trx_oran_get_stats(openair0_device *device)
|
||||
{
|
||||
printf("ORAN: %s\n", __FUNCTION__);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int trx_oran_reset_stats(openair0_device *device)
|
||||
{
|
||||
printf("ORAN: %s\n", __FUNCTION__);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int ethernet_tune(openair0_device *device, unsigned int option, int value)
|
||||
{
|
||||
printf("ORAN: %s\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int trx_oran_write_raw(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags)
|
||||
{
|
||||
printf("ORAN: %s\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int trx_oran_read_raw(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc)
|
||||
{
|
||||
printf("ORAN: %s\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *msg_type(int t)
|
||||
{
|
||||
static char *s[12] = {
|
||||
"RAU_tick",
|
||||
"RRU_capabilities",
|
||||
"RRU_config",
|
||||
"RRU_config_ok",
|
||||
"RRU_start",
|
||||
"RRU_stop",
|
||||
"RRU_sync_ok",
|
||||
"RRU_frame_resynch",
|
||||
"RRU_MSG_max_num",
|
||||
"RRU_check_sync",
|
||||
"RRU_config_update",
|
||||
"RRU_config_update_ok",
|
||||
};
|
||||
|
||||
if (t < 0 || t > 11)
|
||||
return "UNKNOWN";
|
||||
return s[t];
|
||||
}
|
||||
|
||||
int trx_oran_ctlsend(openair0_device *device, void *msg, ssize_t msg_len)
|
||||
{
|
||||
RRU_CONFIG_msg_t *rru_config_msg = msg;
|
||||
oran_eth_state_t *s = device->priv;
|
||||
|
||||
printf("ORAN: %s\n", __FUNCTION__);
|
||||
|
||||
printf(" rru_config_msg->type %d [%s]\n", rru_config_msg->type, msg_type(rru_config_msg->type));
|
||||
|
||||
s->last_msg = rru_config_msg->type;
|
||||
|
||||
return msg_len;
|
||||
}
|
||||
|
||||
int trx_oran_ctlrecv(openair0_device *device, void *msg, ssize_t msg_len)
|
||||
{
|
||||
RRU_CONFIG_msg_t *rru_config_msg = msg;
|
||||
oran_eth_state_t *s = device->priv;
|
||||
|
||||
printf("ORAN: %s\n", __FUNCTION__);
|
||||
|
||||
if (s->last_msg == RAU_tick && s->capabilities_sent == 0) {
|
||||
printf("ORAN ctrlrcv RRU_tick received and send capabilities hard coded\n");
|
||||
RRU_capabilities_t *cap;
|
||||
rru_config_msg->type = RRU_capabilities;
|
||||
rru_config_msg->len = sizeof(RRU_CONFIG_msg_t) - MAX_RRU_CONFIG_SIZE + sizeof(RRU_capabilities_t);
|
||||
// Fill RRU capabilities (see openair1/PHY/defs_RU.h)
|
||||
// For now they are hard coded - try to retreive the params from openari device
|
||||
|
||||
cap = (RRU_capabilities_t *)&rru_config_msg->msg[0];
|
||||
cap->FH_fmt = OAI_IF4p5_only;
|
||||
cap->num_bands = 1;
|
||||
cap->band_list[0] = 78;
|
||||
// cap->num_concurrent_bands = 1; component carriers
|
||||
cap->nb_rx[0] = 1; // device->openair0_cfg->rx_num_channels;
|
||||
cap->nb_tx[0] = 1; // device->openair0_cfg->tx_num_channels;
|
||||
cap->max_pdschReferenceSignalPower[0] = -27;
|
||||
cap->max_rxgain[0] = 90;
|
||||
cap->N_RB_DL[0] = 106;
|
||||
cap->N_RB_UL[0] = 106;
|
||||
|
||||
s->capabilities_sent = 1;
|
||||
|
||||
return rru_config_msg->len;
|
||||
}
|
||||
if (s->last_msg == RRU_config) {
|
||||
printf("Oran RRU_config\n");
|
||||
rru_config_msg->type = RRU_config_ok;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void oran_fh_if4p5_south_in(RU_t *ru, int *frame, int *slot)
|
||||
{
|
||||
ru_info_t ru_info;
|
||||
ru_info.nb_rx = ru->nb_rx;
|
||||
ru_info.rxdataF = ru->common.rxdataF;
|
||||
ru_info.prach_buf = ru->prach_rxsigF[0]; // index: [prach_oca][ant_id]
|
||||
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
extern uint16_t sl_ahead;
|
||||
int f, sl;
|
||||
LOG_D(PHY, "Read rxdataF %p,%p\n", ru_info.rxdataF[0], ru_info.rxdataF[1]);
|
||||
start_meas(&ru->rx_fhaul);
|
||||
int ret = xran_fh_rx_read_slot(&ru_info, &f, &sl);
|
||||
stop_meas(&ru->rx_fhaul);
|
||||
LOG_D(PHY, "Read %d.%d rxdataF %p,%p\n", f, sl, ru_info.rxdataF[0], ru_info.rxdataF[1]);
|
||||
if (ret != 0) {
|
||||
printf("ORAN: %d.%d ORAN_fh_if4p5_south_in ERROR in RX function \n", f, sl);
|
||||
}
|
||||
|
||||
proc->tti_rx = sl;
|
||||
proc->frame_rx = f;
|
||||
proc->tti_tx = (sl + sl_ahead) % 20;
|
||||
proc->frame_tx = (sl > (19 - sl_ahead)) ? (f + 1) & 1023 : f;
|
||||
|
||||
if (proc->first_rx == 0) {
|
||||
if (proc->tti_rx != *slot) {
|
||||
LOG_E(PHY,
|
||||
"Received Time doesn't correspond to the time we think it is (slot mismatch, received %d.%d, expected %d.%d)\n",
|
||||
proc->frame_rx,
|
||||
proc->tti_rx,
|
||||
*frame,
|
||||
*slot);
|
||||
*slot = proc->tti_rx;
|
||||
}
|
||||
|
||||
if (proc->frame_rx != *frame) {
|
||||
LOG_E(PHY,
|
||||
"Received Time doesn't correspond to the time we think it is (frame mismatch, %d.%d , expected %d.%d)\n",
|
||||
proc->frame_rx,
|
||||
proc->tti_rx,
|
||||
*frame,
|
||||
*slot);
|
||||
*frame = proc->frame_rx;
|
||||
}
|
||||
} else {
|
||||
proc->first_rx = 0;
|
||||
LOG_I(PHY, "before adjusting, OAI: frame=%d slot=%d, XRAN: frame=%d slot=%d\n", *frame, *slot, proc->frame_rx, proc->tti_rx);
|
||||
*frame = proc->frame_rx;
|
||||
*slot = proc->tti_rx;
|
||||
LOG_I(PHY, "After adjusting, OAI: frame=%d slot=%d, XRAN: frame=%d slot=%d\n", *frame, *slot, proc->frame_rx, proc->tti_rx);
|
||||
}
|
||||
}
|
||||
|
||||
void oran_fh_if4p5_south_out(RU_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
{
|
||||
start_meas(&ru->tx_fhaul);
|
||||
ru_info_t ru_info;
|
||||
ru_info.nb_tx = ru->nb_tx;
|
||||
ru_info.txdataF_BF = ru->common.txdataF_BF;
|
||||
// printf("south_out:\tframe=%d\tslot=%d\ttimestamp=%ld\n",frame,slot,timestamp);
|
||||
|
||||
int ret = xran_fh_tx_send_slot(&ru_info, frame, slot, timestamp);
|
||||
if (ret != 0) {
|
||||
printf("ORAN: ORAN_fh_if4p5_south_out ERROR in TX function \n");
|
||||
}
|
||||
stop_meas(&ru->tx_fhaul);
|
||||
}
|
||||
|
||||
void *get_internal_parameter(char *name)
|
||||
{
|
||||
printf("ORAN: %s\n", __FUNCTION__);
|
||||
|
||||
if (!strcmp(name, "fh_if4p5_south_in"))
|
||||
return (void *)oran_fh_if4p5_south_in;
|
||||
if (!strcmp(name, "fh_if4p5_south_out"))
|
||||
return (void *)oran_fh_if4p5_south_out;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
__attribute__((__visibility__("default"))) int transport_init(openair0_device *device,
|
||||
openair0_config_t *openair0_cfg,
|
||||
eth_params_t *eth_params)
|
||||
{
|
||||
oran_eth_state_t *eth;
|
||||
|
||||
device->Mod_id = 0;
|
||||
device->transp_type = ETHERNET_TP;
|
||||
device->trx_start_func = trx_oran_start;
|
||||
device->trx_get_stats_func = trx_oran_get_stats;
|
||||
device->trx_reset_stats_func = trx_oran_reset_stats;
|
||||
device->trx_end_func = trx_oran_end;
|
||||
device->trx_stop_func = trx_oran_stop;
|
||||
device->trx_set_freq_func = trx_oran_set_freq;
|
||||
device->trx_set_gains_func = trx_oran_set_gains;
|
||||
|
||||
device->trx_write_func = trx_oran_write_raw;
|
||||
device->trx_read_func = trx_oran_read_raw;
|
||||
|
||||
device->trx_ctlsend_func = trx_oran_ctlsend;
|
||||
device->trx_ctlrecv_func = trx_oran_ctlrecv;
|
||||
|
||||
device->get_internal_parameter = get_internal_parameter;
|
||||
|
||||
eth = (oran_eth_state_t *)calloc(1, sizeof(oran_eth_state_t));
|
||||
if (eth == NULL) {
|
||||
AssertFatal(0 == 1, "out of memory\n");
|
||||
}
|
||||
|
||||
eth->e.flags = ETH_RAW_IF4p5_MODE;
|
||||
eth->e.compression = NO_COMPRESS;
|
||||
eth->e.if_name = eth_params->local_if_name;
|
||||
eth->oran_priv = NULL; // define_oran_pointer();
|
||||
device->priv = eth;
|
||||
device->openair0_cfg = &openair0_cfg[0];
|
||||
|
||||
eth->last_msg = (rru_config_msg_type_t)-1;
|
||||
|
||||
printf("ORAN: %s\n", __FUNCTION__);
|
||||
|
||||
initNotifiedFIFO(&oran_sync_fifo);
|
||||
eth->oran_priv = oai_oran_initialize(openair0_cfg);
|
||||
AssertFatal(eth->oran_priv != NULL, "can not initialize fronthaul");
|
||||
// create message queues for ORAN sync
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user