benetel: driver for Benetel's 4G and 5G RRUs
This commit contains work done by Eurecom and by Benetel.
This commit is contained in:
@@ -763,6 +763,42 @@ set(HWLIB_TCP_BRIDGE_OAI_SOURCE
|
||||
add_library(tcp_bridge_oai MODULE ${HWLIB_TCP_BRIDGE_OAI_SOURCE} )
|
||||
set_target_properties(tcp_bridge_oai PROPERTIES COMPILE_FLAGS "-fvisibility=hidden")
|
||||
|
||||
# Benetel 4G library
|
||||
######################################################################
|
||||
|
||||
set(HWLIB_BENETEL_4G_SOURCE
|
||||
${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/4g/benetel.c
|
||||
${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/4g/shared_buffers.c
|
||||
${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/4g/low.c
|
||||
${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/4g/low_dpdk.c
|
||||
${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/4g/dpdk_driver.c
|
||||
)
|
||||
add_library(benetel_4g MODULE ${HWLIB_BENETEL_4G_SOURCE} )
|
||||
|
||||
set_target_properties(benetel_4g PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -march=native -I$ENV{RTE_SDK}/$ENV{RTE_TARGET}/include")
|
||||
|
||||
SET(DPDK_LIBS "-Wl,-rpath,$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -Wl,--whole-archive -L$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -ldpdk -Wl,--no-whole-archive")
|
||||
TARGET_LINK_LIBRARIES(benetel_4g ${DPDK_LIBS})
|
||||
TARGET_LINK_LIBRARIES(benetel_4g pthread dl rt m numa)
|
||||
|
||||
# Benetel 5G library
|
||||
######################################################################
|
||||
|
||||
set(HWLIB_BENETEL_5G_SOURCE
|
||||
${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/5g/benetel.c
|
||||
${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/5g/shared_buffers.c
|
||||
${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/5g/low.c
|
||||
${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/5g/low_dpdk.c
|
||||
${OPENAIR_TARGETS}/ARCH/ETHERNET/benetel/5g/dpdk_driver.c
|
||||
)
|
||||
add_library(benetel_5g MODULE ${HWLIB_BENETEL_5G_SOURCE} )
|
||||
|
||||
set_target_properties(benetel_5g PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -march=native -I$ENV{RTE_SDK}/$ENV{RTE_TARGET}/include")
|
||||
|
||||
SET(DPDK_LIBS "-Wl,-rpath,$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -Wl,--whole-archive -L$ENV{RTE_SDK}/$ENV{RTE_TARGET}/lib -ldpdk -Wl,--no-whole-archive")
|
||||
TARGET_LINK_LIBRARIES(benetel_5g ${DPDK_LIBS})
|
||||
TARGET_LINK_LIBRARIES(benetel_5g pthread dl rt m numa)
|
||||
|
||||
##########################################################
|
||||
|
||||
include_directories ("${OPENAIR_TARGETS}/ARCH/COMMON")
|
||||
|
||||
+44
-19
@@ -180,6 +180,17 @@ int attach_rru(RU_t *ru)
|
||||
((RRU_config_t *)&rru_config_msg.msg[0])->prach_ConfigIndex[0]);
|
||||
AssertFatal((ru->ifdevice.trx_ctlsend_func(&ru->ifdevice,&rru_config_msg,rru_config_msg.len)!=-1),
|
||||
"RU %d failed send configuration to remote radio\n",ru->idx);
|
||||
|
||||
if ((len = ru->ifdevice.trx_ctlrecv_func(&ru->ifdevice,
|
||||
&rru_config_msg,
|
||||
msg_len))<0) {
|
||||
LOG_I(PHY,"Waiting for RRU %d\n",ru->idx);
|
||||
} else if (rru_config_msg.type == RRU_config_ok) {
|
||||
LOG_I(PHY, "RRU_config_ok received\n");
|
||||
} else {
|
||||
LOG_E(PHY,"Received incorrect message %d from RRU %d\n",rru_config_msg.type,ru->idx);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1442,6 +1453,8 @@ void *ru_thread( void *param ) {
|
||||
|
||||
LOG_I(PHY,"Starting RU %d (%s,%s),\n",ru->idx,NB_functions[ru->function],NB_timing[ru->if_timing]);
|
||||
|
||||
memcpy((void*)&ru->config,(void*)&RC.gNB[0]->gNB_config,sizeof(ru->config));
|
||||
|
||||
if(emulate_rf) {
|
||||
fill_rf_config(ru,ru->rf_config_file);
|
||||
nr_init_frame_parms(&ru->config, fp);
|
||||
@@ -1464,8 +1477,6 @@ void *ru_thread( void *param ) {
|
||||
AssertFatal(ret==0,"Cannot connect to remote radio\n");
|
||||
}
|
||||
|
||||
memcpy((void*)&ru->config,(void*)&RC.gNB[0]->gNB_config,sizeof(ru->config));
|
||||
|
||||
if (ru->if_south == LOCAL_RF) { // configure RF parameters only
|
||||
nr_init_frame_parms(&ru->config, fp);
|
||||
nr_dump_frame_parms(fp);
|
||||
@@ -1571,7 +1582,8 @@ void *ru_thread( void *param ) {
|
||||
if (slot_type == NR_UPLINK_SLOT || slot_type == NR_MIXED_SLOT) {
|
||||
//if (proc->tti_rx==8) {
|
||||
|
||||
if (ru->feprx) ru->feprx(ru,proc->tti_rx);
|
||||
if (ru->feprx) {
|
||||
ru->feprx(ru,proc->tti_rx);
|
||||
//LOG_M("rxdata.m","rxs",ru->common.rxdata[0],1228800,1,1);
|
||||
|
||||
LOG_D(PHY,"RU proc: frame_rx = %d, tti_rx = %d\n", proc->frame_rx, proc->tti_rx);
|
||||
@@ -1591,6 +1603,7 @@ void *ru_thread( void *param ) {
|
||||
proc->frame_rx,proc->tti_rx);
|
||||
free_nr_ru_prach_entry(ru,prach_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// At this point, all information for subframe has been received on FH interface
|
||||
@@ -2131,26 +2144,29 @@ void set_function_spec_param(RU_t *ru) {
|
||||
ru->fh_north_out = NULL; // no outgoing fronthaul to north
|
||||
ru->nr_start_if = NULL; // no if interface
|
||||
ru->rfdevice.host_type = RAU_HOST;
|
||||
|
||||
// FK this here looks messed up. The following lines should be part of the if (ru->function == gNodeB_3GPP), shouldn't they?
|
||||
|
||||
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->start_write_thread = start_write_thread; // starting RF TX in different thread
|
||||
printf("configuring ru_id %u (start_rf %p)\n", ru->idx, start_rf);
|
||||
}
|
||||
|
||||
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->start_write_thread = start_write_thread; // starting RF TX in different thread
|
||||
printf("configuring ru_id %u (start_rf %p)\n", ru->idx, start_rf);
|
||||
/*
|
||||
if (ru->function == gNodeB_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);
|
||||
nr_phy_init_RU(ru);
|
||||
}
|
||||
printf("configuring ru_id %u (start_rf %p)\n", ru->idx, start_rf);
|
||||
fill_rf_config(ru,rf_config_file);
|
||||
init_frame_parms(&ru->frame_parms,1);
|
||||
nr_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);
|
||||
}*/
|
||||
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;
|
||||
|
||||
case REMOTE_IF5: // the remote unit is IF5 RRU
|
||||
@@ -2203,6 +2219,15 @@ void set_function_spec_param(RU_t *ru) {
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (ru->ifdevice.get_internal_parameter != NULL) {
|
||||
void *t = ru->ifdevice.get_internal_parameter("fh_if4p5_south_in");
|
||||
if (t != NULL)
|
||||
ru->fh_south_in = t;
|
||||
t = ru->ifdevice.get_internal_parameter("fh_if4p5_south_out");
|
||||
if (t != NULL)
|
||||
ru->fh_south_out = t;
|
||||
}
|
||||
|
||||
malloc_IF4p5_buffer(ru);
|
||||
break;
|
||||
|
||||
|
||||
@@ -219,7 +219,7 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){
|
||||
LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_TTI_PRACH_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot);
|
||||
nfapi_nr_prach_pdu_t *prach_pdu = &UL_tti_req->pdus_list[i].prach_pdu;
|
||||
nr_fill_prach(gNB, UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu);
|
||||
nr_fill_prach_ru(gNB->RU_list[0], UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu);
|
||||
if (gNB->RU_list[0]->if_south == LOCAL_RF) nr_fill_prach_ru(gNB->RU_list[0], UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1151,8 +1151,9 @@ uint8_t compute_nr_root_seq(NR_RACH_ConfigCommon_t *rach_config,
|
||||
if (NCS == 0) return nb_preambles;
|
||||
else {
|
||||
r = L_ra/NCS;
|
||||
printf(" found_sequences %u\n", (nb_preambles/r));
|
||||
return (nb_preambles/r);
|
||||
found_sequences = (nb_preambles/r) + (nb_preambles%r!=0); //ceil(nb_preambles/r)
|
||||
printf(" found_sequences %u\n", found_sequences);
|
||||
return (found_sequences);
|
||||
}
|
||||
}
|
||||
else{
|
||||
|
||||
@@ -451,6 +451,29 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
|
||||
else
|
||||
UE_list->fiveG_connected[UE_id] = true;
|
||||
|
||||
if (get_softmodem_params()->phy_test == 1) {
|
||||
if (slot_txP == 7){
|
||||
NR_RA_t *ra = &RC.nrmac[module_idP]->common_channels[0].ra[0];
|
||||
ra->Msg2_frame = frame_txP;
|
||||
ra->Msg2_slot = slot_txP;
|
||||
ra->state = Msg2;
|
||||
ra->bwp_id = 1;
|
||||
NR_CellGroupConfig_t *secondaryCellGroup = UE_list->secondaryCellGroup[UE_id];
|
||||
NR_BWP_Downlink_t *bwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id-1];
|
||||
struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList = bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList;
|
||||
for (int i=0;i<commonSearchSpaceList->list.count;i++) {
|
||||
NR_SearchSpace_t *ss=commonSearchSpaceList->list.array[i];
|
||||
if(ss->searchSpaceId == *bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->ra_SearchSpace)
|
||||
ra->ra_ss=ss;
|
||||
}
|
||||
AssertFatal(ra->ra_ss!=NULL,"no search space for RA'n");
|
||||
|
||||
nr_generate_Msg2(module_idP, 0/*CC_id*/,
|
||||
frame_txP,
|
||||
slot_txP);
|
||||
}
|
||||
}
|
||||
|
||||
// Phytest scheduling
|
||||
|
||||
if (get_softmodem_params()->phy_test) {
|
||||
|
||||
@@ -435,7 +435,10 @@ void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t
|
||||
NR_UE_list_t *UE_list = &mac->UE_list;
|
||||
int UE_id = 0;
|
||||
|
||||
AssertFatal(ra->state != RA_IDLE, "RA is not active for RA %X\n", ra->rnti);
|
||||
if (ra->state != RA_IDLE) {
|
||||
LOG_W(MAC,"RA is not active for RA %X. skipping msg3 scheduling\n", ra->rnti);
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_D(MAC, "[gNB %d][RAPROC] Frame %d, Subframe %d : CC_id %d RA is active, Msg3 in (%d,%d)\n", module_idP, frameP, slotP, CC_id, ra->Msg3_frame, ra->Msg3_slot);
|
||||
|
||||
|
||||
+41
-35
@@ -9075,47 +9075,53 @@ void rrc_eNB_process_AdditionResponseInformation(const module_id_t enb_mod_idP,
|
||||
return;
|
||||
}
|
||||
|
||||
protocol_ctxt_t ctxt;
|
||||
rrc_eNB_ue_context_t *ue_context;
|
||||
unsigned char buffer[8192];
|
||||
int size;
|
||||
ue_context = rrc_eNB_get_ue_context(RC.rrc[enb_mod_idP], m->rnti);
|
||||
ue_context->ue_context.nb_of_modify_endc_e_rabs = m->nb_e_rabs_admitted_tobeadded;
|
||||
int j=0;
|
||||
protocol_ctxt_t ctxt;
|
||||
rrc_eNB_ue_context_t *ue_context;
|
||||
unsigned char buffer[8192];
|
||||
int size;
|
||||
|
||||
while(j < m->nb_e_rabs_admitted_tobeadded) {
|
||||
for (int e_rab_idx=0; e_rab_idx<ue_context->ue_context.setup_e_rabs; e_rab_idx++) {
|
||||
//Update ue_context information with gNB's address and new GTP tunnel ID
|
||||
if( ue_context->ue_context.e_rab[e_rab_idx].param.e_rab_id == m->e_rabs_admitted_tobeadded[j].e_rab_id) {
|
||||
memcpy(ue_context->ue_context.gnb_gtp_endc_addrs[e_rab_idx].buffer,
|
||||
m->e_rabs_admitted_tobeadded[j].gnb_addr.buffer,
|
||||
m->e_rabs_admitted_tobeadded[j].gnb_addr.length);
|
||||
ue_context->ue_context.gnb_gtp_endc_addrs[e_rab_idx].length = m->e_rabs_admitted_tobeadded[j].gnb_addr.length;
|
||||
ue_context->ue_context.gnb_gtp_endc_teid[e_rab_idx] = m->e_rabs_admitted_tobeadded[j].gtp_teid;
|
||||
ue_context->ue_context.e_rab[e_rab_idx].status = E_RAB_STATUS_TOMODIFY;
|
||||
break;
|
||||
ue_context = rrc_eNB_get_ue_context(RC.rrc[enb_mod_idP], m->rnti);
|
||||
if (ue_context) {
|
||||
ue_context->ue_context.nb_of_modify_endc_e_rabs = m->nb_e_rabs_admitted_tobeadded;
|
||||
|
||||
int j=0;
|
||||
while(j < m->nb_e_rabs_admitted_tobeadded){
|
||||
for (int e_rab_idx=0; e_rab_idx<ue_context->ue_context.setup_e_rabs; e_rab_idx++){
|
||||
//Update ue_context information with gNB's address and new GTP tunnel ID
|
||||
if( ue_context->ue_context.e_rab[e_rab_idx].param.e_rab_id == m->e_rabs_admitted_tobeadded[j].e_rab_id){
|
||||
memcpy(ue_context->ue_context.gnb_gtp_endc_addrs[e_rab_idx].buffer,
|
||||
m->e_rabs_admitted_tobeadded[j].gnb_addr.buffer,
|
||||
m->e_rabs_admitted_tobeadded[j].gnb_addr.length);
|
||||
ue_context->ue_context.gnb_gtp_endc_addrs[e_rab_idx].length = m->e_rabs_admitted_tobeadded[j].gnb_addr.length;
|
||||
ue_context->ue_context.gnb_gtp_endc_teid[e_rab_idx] = m->e_rabs_admitted_tobeadded[j].gtp_teid;
|
||||
ue_context->ue_context.e_rab[e_rab_idx].status = E_RAB_STATUS_TOMODIFY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
j++;
|
||||
}
|
||||
|
||||
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt,
|
||||
0,
|
||||
ENB_FLAG_YES,
|
||||
m->rnti,
|
||||
0, 0);
|
||||
|
||||
size = rrc_eNB_generate_RRCConnectionReconfiguration_endc(&ctxt, ue_context, buffer, 8192, scg_CellGroupConfig, nr1_conf);
|
||||
|
||||
rrc_data_req(&ctxt,
|
||||
DCCH,
|
||||
rrc_eNB_mui++,
|
||||
SDU_CONFIRM_NO,
|
||||
size,
|
||||
buffer,
|
||||
PDCP_TRANSMISSION_MODE_CONTROL);
|
||||
} else {
|
||||
LOG_E(F1AP, "no ue_context for RNTI %x, acknowledging release\n", m->rnti);
|
||||
}
|
||||
|
||||
j++;
|
||||
}
|
||||
|
||||
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt,
|
||||
0,
|
||||
ENB_FLAG_YES,
|
||||
m->rnti,
|
||||
0, 0);
|
||||
size = rrc_eNB_generate_RRCConnectionReconfiguration_endc(&ctxt, ue_context, buffer, 8192, scg_CellGroupConfig, nr1_conf);
|
||||
rrc_data_req(&ctxt,
|
||||
DCCH,
|
||||
rrc_eNB_mui++,
|
||||
SDU_CONFIRM_NO,
|
||||
size,
|
||||
buffer,
|
||||
PDCP_TRANSMISSION_MODE_CONTROL);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void *rrc_enb_process_itti_msg(void *notUsed) {
|
||||
MessageDef *msg_p;
|
||||
|
||||
@@ -434,6 +434,11 @@ struct openair0_device_t {
|
||||
* \param arg pointer to capabilities or configuration
|
||||
*/
|
||||
int (*trx_write_init)(openair0_device *device);
|
||||
/* \brief Get internal parameter
|
||||
* \param id parameter to get
|
||||
* \return a pointer to the parameter
|
||||
*/
|
||||
void *(*get_internal_parameter)(char *id);
|
||||
};
|
||||
|
||||
/* type of device init function, implemented in shared lib */
|
||||
|
||||
@@ -0,0 +1,386 @@
|
||||
/*
|
||||
* 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 "common_lib.h"
|
||||
#include "ethernet_lib.h"
|
||||
#include "shared_buffers.h"
|
||||
#include "low.h"
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "common/utils/LOG/vcd_signal_dumper.h"
|
||||
|
||||
typedef struct {
|
||||
eth_state_t e;
|
||||
shared_buffers buffers;
|
||||
rru_config_msg_type_t last_msg;
|
||||
int capabilities_sent;
|
||||
void *benetel_priv;
|
||||
char *dpdk_main_command_line;
|
||||
} benetel_eth_state_t;
|
||||
|
||||
int trx_benetel_start(openair0_device *device)
|
||||
{
|
||||
printf("BENETEL: %s\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void trx_benetel_end(openair0_device *device)
|
||||
{
|
||||
printf("BENETEL: %s\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
|
||||
int trx_benetel_stop(openair0_device *device)
|
||||
{
|
||||
printf("BENETEL: %s\n", __FUNCTION__);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int trx_benetel_set_freq(openair0_device* device,
|
||||
openair0_config_t *openair0_cfg,
|
||||
int exmimo_dump_config)
|
||||
{
|
||||
printf("BENETEL: %s\n", __FUNCTION__);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int trx_benetel_set_gains(openair0_device* device,
|
||||
openair0_config_t *openair0_cfg)
|
||||
{
|
||||
printf("BENETEL: %s\n", __FUNCTION__);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int trx_benetel_get_stats(openair0_device* device)
|
||||
{
|
||||
printf("BENETEL: %s\n", __FUNCTION__);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int trx_benetel_reset_stats(openair0_device* device)
|
||||
{
|
||||
printf("BENETEL: %s\n", __FUNCTION__);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int ethernet_tune(openair0_device *device,
|
||||
unsigned int option,
|
||||
int value)
|
||||
{
|
||||
printf("BENETEL: %s\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int trx_benetel_write_raw(openair0_device *device,
|
||||
openair0_timestamp timestamp,
|
||||
void **buff, int nsamps, int cc, int flags)
|
||||
{
|
||||
printf("BENETEL: %s\n", __FUNCTION__);
|
||||
return nsamps*4;
|
||||
}
|
||||
|
||||
int trx_benetel_read_raw(openair0_device *device,
|
||||
openair0_timestamp *timestamp,
|
||||
void **buff, int nsamps, int cc)
|
||||
{
|
||||
printf("BENETEL: %s\n", __FUNCTION__);
|
||||
return nsamps*4;
|
||||
}
|
||||
|
||||
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_benetel_ctlsend(openair0_device *device, void *msg, ssize_t msg_len)
|
||||
{
|
||||
RRU_CONFIG_msg_t *rru_config_msg = msg;
|
||||
benetel_eth_state_t *s = device->priv;
|
||||
|
||||
printf("BENETEL: %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_benetel_ctlrecv(openair0_device *device, void *msg, ssize_t msg_len)
|
||||
{
|
||||
RRU_CONFIG_msg_t *rru_config_msg = msg;
|
||||
benetel_eth_state_t *s = device->priv;
|
||||
|
||||
printf("BENETEL: %s\n", __FUNCTION__);
|
||||
|
||||
if (s->last_msg == RAU_tick && s->capabilities_sent == 0) {
|
||||
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);
|
||||
cap = (RRU_capabilities_t*)&rru_config_msg->msg[0];
|
||||
cap->FH_fmt = OAI_IF4p5_only;
|
||||
cap->num_bands = 1;
|
||||
cap->band_list[0] = 7;
|
||||
cap->nb_rx[0] = 1;
|
||||
cap->nb_tx[0] = 1;
|
||||
cap->max_pdschReferenceSignalPower[0] = -27;
|
||||
cap->max_rxgain[0] = 90;
|
||||
|
||||
s->capabilities_sent = 1;
|
||||
|
||||
return rru_config_msg->len;
|
||||
}
|
||||
if (s->last_msg == RRU_config) {
|
||||
rru_config_msg->type = RRU_config_ok;
|
||||
return 0;
|
||||
}
|
||||
if (s->last_msg == RRU_start) {
|
||||
s->benetel_priv = benetel_start(s->e.if_name, &s->buffers, s->dpdk_main_command_line);
|
||||
}
|
||||
/* correct? */
|
||||
while (1) pause();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void benetel_fh_if4p5_south_in(RU_t *ru,
|
||||
int *frame,
|
||||
int *subframe)
|
||||
{
|
||||
benetel_eth_state_t *s = ru->ifdevice.priv;
|
||||
PHY_VARS_eNB **eNB_list = ru->eNB_list, *eNB;
|
||||
LTE_DL_FRAME_PARMS *fp;
|
||||
int symbol;
|
||||
int32_t *rxdata;
|
||||
int antenna = 0;
|
||||
|
||||
lock_ul_buffer(&s->buffers, *subframe);
|
||||
next:
|
||||
while (!(s->buffers.ul_busy[*subframe] == 0x3fff ||
|
||||
s->buffers.prach_busy[*subframe] == 1))
|
||||
wait_ul_buffer(&s->buffers, *subframe);
|
||||
if (s->buffers.prach_busy[*subframe] == 1) {
|
||||
int i;
|
||||
int antenna = 0;
|
||||
uint16_t *in;
|
||||
uint16_t *out;
|
||||
in = (uint16_t *)s->buffers.prach[*subframe];
|
||||
out = (uint16_t *)ru->prach_rxsigF[antenna];
|
||||
for (i = 0; i < 840*2; i++)
|
||||
out[i] = ntohs(in[i]);
|
||||
s->buffers.prach_busy[*subframe] = 0;
|
||||
ru->wakeup_prach_eNB(ru->eNB_list[0], ru, *frame, *subframe);
|
||||
goto next;
|
||||
}
|
||||
|
||||
eNB = eNB_list[0];
|
||||
fp = &eNB->frame_parms;
|
||||
for (symbol = 0; symbol < 14; symbol++) {
|
||||
int i;
|
||||
uint16_t *p = (uint16_t *)(&s->buffers.ul[*subframe][symbol*1200*4]);
|
||||
for (i = 0; i < 1200*2; i++) {
|
||||
p[i] = htons(p[i]);
|
||||
}
|
||||
rxdata = &ru->common.rxdataF[antenna][symbol * fp->ofdm_symbol_size];
|
||||
#if 1
|
||||
memcpy(rxdata + 2048 - 600,
|
||||
&s->buffers.ul[*subframe][symbol*1200*4],
|
||||
600 * 4);
|
||||
memcpy(rxdata,
|
||||
&s->buffers.ul[*subframe][symbol*1200*4] + 600*4,
|
||||
600 * 4);
|
||||
#endif
|
||||
}
|
||||
|
||||
s->buffers.ul_busy[*subframe] = 0;
|
||||
signal_ul_buffer(&s->buffers, *subframe);
|
||||
unlock_ul_buffer(&s->buffers, *subframe);
|
||||
|
||||
//printf("BENETEL: %s (f.sf %d.%d)\n", __FUNCTION__, *frame, *subframe);
|
||||
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
extern uint16_t sf_ahead;
|
||||
int f = *frame;
|
||||
int sf = *subframe;
|
||||
|
||||
//calculate timestamp_rx, timestamp_tx based on frame and subframe
|
||||
proc->tti_rx = sf;
|
||||
proc->frame_rx = f;
|
||||
proc->timestamp_rx = ((proc->frame_rx * 10) + proc->tti_rx ) * fp->samples_per_tti ;
|
||||
|
||||
if (get_nprocs()<=4) {
|
||||
proc->tti_tx = (sf+sf_ahead)%10;
|
||||
proc->frame_tx = (sf>(9-sf_ahead)) ? (f+1)&1023 : f;
|
||||
}
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_IF4P5_SOUTH_IN_RU+ru->idx,f);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_IF4P5_SOUTH_IN_RU+ru->idx,sf);
|
||||
proc->symbol_mask[sf] = 0;
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff);
|
||||
|
||||
}
|
||||
|
||||
void benetel_fh_if4p5_south_out(RU_t *ru,
|
||||
int frame,
|
||||
int subframe,
|
||||
uint64_t timestamp)
|
||||
{
|
||||
benetel_eth_state_t *s = ru->ifdevice.priv;
|
||||
PHY_VARS_eNB **eNB_list = ru->eNB_list, *eNB;
|
||||
LTE_DL_FRAME_PARMS *fp;
|
||||
int symbol;
|
||||
int32_t *txdata;
|
||||
int aa = 0;
|
||||
|
||||
//printf("BENETEL: %s (f.sf %d.%d ts %ld)\n", __FUNCTION__, frame, subframe, timestamp);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, ru->proc.timestamp_tx&0xffffffff );
|
||||
|
||||
lock_dl_buffer(&s->buffers, subframe);
|
||||
if (s->buffers.dl_busy[subframe]) {
|
||||
printf("%s: fatal: DL buffer busy for subframe %d\n", __FUNCTION__, subframe);
|
||||
unlock_dl_buffer(&s->buffers, subframe);
|
||||
return;
|
||||
}
|
||||
eNB = eNB_list[0];
|
||||
fp = &eNB->frame_parms;
|
||||
if (ru->num_eNB != 1 || ru->nb_tx != 1 || fp->ofdm_symbol_size != 2048 ||
|
||||
fp->Ncp != NORMAL || fp->symbols_per_tti != 14) {
|
||||
printf("%s:%d:%s: unsupported configuration\n",
|
||||
__FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (symbol = 0; symbol < 14; symbol++) {
|
||||
txdata = &ru->common.txdataF_BF[aa][symbol * fp->ofdm_symbol_size];
|
||||
#if 1
|
||||
memcpy(&s->buffers.dl[subframe][symbol*1200*4],
|
||||
txdata + 2048 - 600,
|
||||
600 * 4);
|
||||
memcpy(&s->buffers.dl[subframe][symbol*1200*4] + 600*4,
|
||||
txdata + 1,
|
||||
600 * 4);
|
||||
#endif
|
||||
int i;
|
||||
uint16_t *p = (uint16_t *)(&s->buffers.dl[subframe][symbol*1200*4]);
|
||||
for (i = 0; i < 1200*2; i++) {
|
||||
p[i] = htons(p[i]);
|
||||
}
|
||||
}
|
||||
|
||||
s->buffers.dl_busy[subframe] = 0x3fff;
|
||||
unlock_dl_buffer(&s->buffers, subframe);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_IF4P5_SOUTH_OUT_RU+ru->idx, ru->proc.frame_tx);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_IF4P5_SOUTH_OUT_RU+ru->idx, ru->proc.tti_tx);
|
||||
|
||||
}
|
||||
|
||||
void *get_internal_parameter(char *name)
|
||||
{
|
||||
printf("BENETEL: %s\n", __FUNCTION__);
|
||||
|
||||
if (!strcmp(name, "fh_if4p5_south_in"))
|
||||
return benetel_fh_if4p5_south_in;
|
||||
if (!strcmp(name, "fh_if4p5_south_out"))
|
||||
return benetel_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 )
|
||||
{
|
||||
benetel_eth_state_t *eth;
|
||||
|
||||
printf("BENETEL: %s\n", __FUNCTION__);
|
||||
|
||||
device->Mod_id = 0;
|
||||
device->transp_type = ETHERNET_TP;
|
||||
device->trx_start_func = trx_benetel_start;
|
||||
device->trx_get_stats_func = trx_benetel_get_stats;
|
||||
device->trx_reset_stats_func = trx_benetel_reset_stats;
|
||||
device->trx_end_func = trx_benetel_end;
|
||||
device->trx_stop_func = trx_benetel_stop;
|
||||
device->trx_set_freq_func = trx_benetel_set_freq;
|
||||
device->trx_set_gains_func = trx_benetel_set_gains;
|
||||
|
||||
device->trx_write_func = trx_benetel_write_raw;
|
||||
device->trx_read_func = trx_benetel_read_raw;
|
||||
|
||||
device->trx_ctlsend_func = trx_benetel_ctlsend;
|
||||
device->trx_ctlrecv_func = trx_benetel_ctlrecv;
|
||||
|
||||
device->get_internal_parameter = get_internal_parameter;
|
||||
|
||||
eth = calloc(1, sizeof(benetel_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;
|
||||
device->priv = eth;
|
||||
device->openair0_cfg=&openair0_cfg[0];
|
||||
|
||||
if (openair0_cfg->sdr_addrs == NULL) {
|
||||
printf("benetel: fatal: sdr_addrs not set in configuration file\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
eth->dpdk_main_command_line = strdup(openair0_cfg->sdr_addrs);
|
||||
if (eth->dpdk_main_command_line == NULL) {
|
||||
AssertFatal(0==1, "out of memory\n");
|
||||
}
|
||||
|
||||
eth->last_msg = -1;
|
||||
|
||||
init_buffers(ð->buffers);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,787 @@
|
||||
/* license: to be defined */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/queue.h>
|
||||
#include <netinet/in.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <rte_common.h>
|
||||
#include <rte_log.h>
|
||||
#include <rte_malloc.h>
|
||||
#include <rte_memory.h>
|
||||
#include <rte_memcpy.h>
|
||||
#include <rte_eal.h>
|
||||
#include <rte_launch.h>
|
||||
#include <rte_atomic.h>
|
||||
#include <rte_cycles.h>
|
||||
#include <rte_prefetch.h>
|
||||
#include <rte_lcore.h>
|
||||
#include <rte_per_lcore.h>
|
||||
#include <rte_branch_prediction.h>
|
||||
#include <rte_interrupts.h>
|
||||
#include <rte_random.h>
|
||||
#include <rte_debug.h>
|
||||
#include <rte_ether.h>
|
||||
#include <rte_ethdev.h>
|
||||
#include <rte_mempool.h>
|
||||
#include <rte_mbuf.h>
|
||||
|
||||
#include "low.h"
|
||||
|
||||
// HEADER DEFINITION
|
||||
#define ANT_NUM buf[23]
|
||||
#define PAYLOAD_1 buf[20]
|
||||
#define PAYLOAD_2 buf[21]
|
||||
#define ETH_TYPE buf[17]
|
||||
#define SYMBOL buf[29]
|
||||
#define SUBFRAME buf[28]
|
||||
#define FRAME buf[27]
|
||||
|
||||
static volatile bool force_quit;
|
||||
|
||||
unsigned short iq[33600];
|
||||
unsigned char iq_swap[67200];
|
||||
|
||||
unsigned short *iq_ptr[14];
|
||||
unsigned int dl_start = 0;
|
||||
|
||||
/* MAC updating enabled by default */
|
||||
static int mac_updating = 1;
|
||||
#define RTE_LOGTYPE_L2FWD RTE_LOGTYPE_USER1
|
||||
#define MAX_PKT_BURST 32
|
||||
#define BURST_TX_DRAIN_US 5 /* TX drain every ~100us */
|
||||
#define MEMPOOL_CACHE_SIZE 256
|
||||
/*
|
||||
* Configurable number of RX/TX ring descriptors
|
||||
*/
|
||||
#define RTE_TEST_RX_DESC_DEFAULT 1024
|
||||
#define RTE_TEST_TX_DESC_DEFAULT 1024
|
||||
static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
|
||||
static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
|
||||
/* ethernet addresses of ports */
|
||||
static struct ether_addr l2fwd_ports_eth_addr[RTE_MAX_ETHPORTS];
|
||||
/* mask of enabled ports */
|
||||
static uint32_t l2fwd_enabled_port_mask = 0;
|
||||
/* list of enabled ports */
|
||||
static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS];
|
||||
static unsigned int l2fwd_rx_queue_per_lcore = 1;
|
||||
#define MAX_RX_QUEUE_PER_LCORE 16
|
||||
#define MAX_TX_QUEUE_PER_PORT 16
|
||||
struct lcore_queue_conf {
|
||||
unsigned n_rx_port;
|
||||
unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE];
|
||||
} __rte_cache_aligned;
|
||||
struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE];
|
||||
static struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS];
|
||||
static struct rte_eth_conf port_conf = {
|
||||
.rxmode = {
|
||||
.split_hdr_size = 0,
|
||||
.offloads = DEV_RX_OFFLOAD_CRC_STRIP,
|
||||
.offloads = DEV_RX_OFFLOAD_JUMBO_FRAME,
|
||||
.split_hdr_size = 0,
|
||||
.max_rx_pkt_len = 9500,
|
||||
},
|
||||
.txmode = {
|
||||
.mq_mode = ETH_MQ_TX_NONE,
|
||||
},
|
||||
};
|
||||
struct rte_mempool * l2fwd_pktmbuf_pool = NULL;
|
||||
/* Per-port statistics struct */
|
||||
struct l2fwd_port_statistics {
|
||||
uint64_t tx;
|
||||
uint64_t rx;
|
||||
uint64_t dropped;
|
||||
} __rte_cache_aligned;
|
||||
struct l2fwd_port_statistics port_statistics[RTE_MAX_ETHPORTS];
|
||||
#define MAX_TIMER_PERIOD 86400 /* 1 day max */
|
||||
/* A tsc-based timer responsible for triggering statistics printout */
|
||||
static uint64_t timer_period = 10; /* default period is 10 seconds */
|
||||
/* Print out statistics on packets dropped */
|
||||
static void
|
||||
print_stats(void)
|
||||
{
|
||||
uint64_t total_packets_dropped, total_packets_tx, total_packets_rx;
|
||||
unsigned portid;
|
||||
total_packets_dropped = 0;
|
||||
total_packets_tx = 0;
|
||||
total_packets_rx = 0;
|
||||
const char clr[] = { 27, '[', '2', 'J', '\0' };
|
||||
const char topLeft[] = { 27, '[', '1', ';', '1', 'H','\0' };
|
||||
/* Clear screen and move to top left */
|
||||
printf("%s%s", clr, topLeft);
|
||||
printf("\nPort statistics ====================================");
|
||||
for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {
|
||||
/* skip disabled ports */
|
||||
if ((l2fwd_enabled_port_mask & (1 << portid)) == 0)
|
||||
continue;
|
||||
printf("\nStatistics for port %u ------------------------------"
|
||||
"\nPackets sent: %24"PRIu64
|
||||
"\nPackets received: %20"PRIu64
|
||||
"\nPackets dropped: %21"PRIu64,
|
||||
portid,
|
||||
port_statistics[portid].tx,
|
||||
port_statistics[portid].rx,
|
||||
port_statistics[portid].dropped);
|
||||
total_packets_dropped += port_statistics[portid].dropped;
|
||||
total_packets_tx += port_statistics[portid].tx;
|
||||
total_packets_rx += port_statistics[portid].rx;
|
||||
}
|
||||
printf("\nAggregate statistics ==============================="
|
||||
"\nTotal packets sent: %18"PRIu64
|
||||
"\nTotal packets received: %14"PRIu64
|
||||
"\nTotal packets dropped: %15"PRIu64,
|
||||
total_packets_tx,
|
||||
total_packets_rx,
|
||||
total_packets_dropped);
|
||||
printf("\n====================================================\n");
|
||||
}
|
||||
static void
|
||||
l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid, benetel_t *bs)
|
||||
{
|
||||
unsigned char *buf, *buf_tx;
|
||||
unsigned int len;
|
||||
struct ether_hdr *eth;
|
||||
|
||||
unsigned dst_port;
|
||||
int sent, prach_ctrl = 0;
|
||||
struct rte_eth_dev_tx_buffer *buffer;
|
||||
|
||||
unsigned char * IQ_ptr;
|
||||
|
||||
ul_packet_t p;
|
||||
|
||||
buf = rte_pktmbuf_mtod(m, unsigned char *);
|
||||
//rte_memdump(stdout, "Rx Packet",buf ,34);
|
||||
eth = rte_pktmbuf_mtod(m, struct ether_hdr *);
|
||||
len = rte_pktmbuf_data_len(m);
|
||||
|
||||
IQ_ptr = &buf[34];
|
||||
|
||||
//destination mac address (RRU MAC)
|
||||
eth->d_addr.addr_bytes[0] = 0x02;
|
||||
eth->d_addr.addr_bytes[1] = 0x00;
|
||||
eth->d_addr.addr_bytes[2] = 0x5e;
|
||||
eth->d_addr.addr_bytes[3] = 0x01;
|
||||
eth->d_addr.addr_bytes[4] = 0x01;
|
||||
eth->d_addr.addr_bytes[5] = 0x01;
|
||||
|
||||
//source mac address (DU MAC)
|
||||
eth->s_addr.addr_bytes[0] = 0xdd;
|
||||
eth->s_addr.addr_bytes[1] = 0xdd;
|
||||
eth->s_addr.addr_bytes[2] = 0xdd;
|
||||
eth->s_addr.addr_bytes[3] = 0xdd;
|
||||
eth->s_addr.addr_bytes[4] = 0xdd;
|
||||
eth->s_addr.addr_bytes[5] = 0xdd;
|
||||
|
||||
dst_port = l2fwd_dst_ports[portid];
|
||||
#if 1
|
||||
|
||||
if (buf[18] == 0xAA) //msg1 check
|
||||
{
|
||||
printf("\nHandshake MSG 1 Received\n");
|
||||
printf("\n====================================================\n");
|
||||
|
||||
buf[18] = 0xBB;//change to msg2 after receive msg1
|
||||
|
||||
printf("Handshake MSG 2 Sent\n");
|
||||
printf("\n====================================================\n");
|
||||
}
|
||||
|
||||
#else
|
||||
// Handshake Condition
|
||||
if (buf[18] == 0x01 || buf[18] == 0x03) // ORAN handshake msgs.
|
||||
{
|
||||
if (buf[18] == 0x01) //msg1 check
|
||||
{
|
||||
printf("\nHandshake MSG 1 Received\n");
|
||||
printf("\n====================================================\n");
|
||||
|
||||
buf[18] = 0x02;//change to msg2 after receive msg1
|
||||
|
||||
printf("Handshake MSG 2 Sent\n");
|
||||
printf("\n====================================================\n");
|
||||
}
|
||||
|
||||
else if(buf[18] == 0x03) //msg3 check
|
||||
{
|
||||
printf("Handshake MSG 3 Sent\n");
|
||||
printf("\n====================================================\n");
|
||||
|
||||
buf[18] = 0x04;
|
||||
|
||||
printf("Handshake MSG 4 Sent\n");
|
||||
printf("\n====================================================\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// Trigger start send DL packets
|
||||
if(PAYLOAD_1 == 0x12 && PAYLOAD_2 == 0xce && SYMBOL == 0x09 && ANT_NUM == 0x00 && dl_start == 0){
|
||||
|
||||
printf("\nU-Plane Started\n");
|
||||
printf("\n====================================================\n");
|
||||
|
||||
dl_start = 1;
|
||||
}
|
||||
|
||||
|
||||
if(PAYLOAD_1 == 0x12 && PAYLOAD_2 == 0xce && ANT_NUM == 0x00) {
|
||||
p.frame = FRAME;
|
||||
p.subframe = SUBFRAME >> 4;
|
||||
p.slot = 0; /* unused */
|
||||
p.symbol = SYMBOL;
|
||||
p.antenna = 0;
|
||||
memcpy(p.iq, IQ_ptr, 4800);
|
||||
store_ul(bs, &p);
|
||||
}
|
||||
|
||||
// U-PLANE UL ANT_0 PROCESSING
|
||||
if(PAYLOAD_1 == 0x12 && PAYLOAD_2 == 0xce && ANT_NUM == 0x00 && dl_start == 1)
|
||||
{
|
||||
int tx_frame = FRAME;
|
||||
int tx_subframe = SUBFRAME >> 4;
|
||||
int tx_symbol = SYMBOL + 5;
|
||||
if (tx_symbol > 13) {
|
||||
tx_symbol -= 14;
|
||||
tx_subframe++;
|
||||
if (tx_subframe == 10) {
|
||||
tx_subframe = 0;
|
||||
tx_frame = (tx_frame + 1) & 255;
|
||||
}
|
||||
}
|
||||
|
||||
// ANT_NUM = 0x00;
|
||||
// SYMBOL = (SYMBOL + 5) % 14;
|
||||
PAYLOAD_2 = 0xc8;
|
||||
|
||||
FRAME = tx_frame;
|
||||
SUBFRAME = tx_subframe << 4;
|
||||
SYMBOL = tx_symbol;
|
||||
|
||||
/* antenna 0 - send actual DL data (if available) */
|
||||
lock_dl_buffer(bs->buffers, tx_subframe);
|
||||
if (!(bs->buffers->dl_busy[tx_subframe] & (1 << tx_symbol))) {
|
||||
printf("%s: warning, DL underflow (sf.symbol %d.%d)\n", __FUNCTION__,
|
||||
tx_subframe, tx_symbol);
|
||||
memset(IQ_ptr, 0, 1200 * 4);
|
||||
} else {
|
||||
memcpy(IQ_ptr, bs->buffers->dl[tx_subframe] + tx_symbol * 1200*4,
|
||||
1200*4);
|
||||
}
|
||||
bs->buffers->dl_busy[tx_subframe] &= ~(1 << tx_symbol);
|
||||
unlock_dl_buffer(bs->buffers, tx_subframe);
|
||||
|
||||
// fill DL Data for ant 0 with 0 value
|
||||
// memset(IQ_ptr, 0, 4800);
|
||||
}
|
||||
|
||||
// U-PLANE UL ANT_1 PROCESSING
|
||||
else if(PAYLOAD_1 == 0x12 && PAYLOAD_2 == 0xce && ANT_NUM == 0x01 && dl_start == 1)
|
||||
{
|
||||
|
||||
// ANT_NUM = 0x01;
|
||||
SYMBOL = (SYMBOL + 5) % 14;
|
||||
PAYLOAD_2 = 0xc8;
|
||||
|
||||
// fill DL Data for ant 1 with 0 value
|
||||
memset(IQ_ptr, 0, 4800);
|
||||
}
|
||||
|
||||
// U-PLANE PRACH PROCESSING
|
||||
else if(PAYLOAD_1 == 0x0d && PAYLOAD_2 == 0x28){
|
||||
if (ANT_NUM == 0) {
|
||||
store_prach(bs, FRAME, SUBFRAME>>4, IQ_ptr);
|
||||
}
|
||||
|
||||
rte_pktmbuf_free(m);
|
||||
return;
|
||||
}
|
||||
|
||||
// Send Packets
|
||||
buffer = tx_buffer[dst_port];
|
||||
|
||||
sent = rte_eth_tx_buffer(dst_port, 0, buffer, m);
|
||||
|
||||
if (sent)
|
||||
port_statistics[dst_port].tx += sent;
|
||||
|
||||
}
|
||||
/* main processing loop */
|
||||
static void
|
||||
l2fwd_main_loop(benetel_t *bs)
|
||||
{
|
||||
struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
|
||||
struct rte_mbuf *m;
|
||||
int sent;
|
||||
unsigned lcore_id;
|
||||
uint64_t prev_tsc, diff_tsc, cur_tsc, timer_tsc;
|
||||
unsigned i, j, portid, nb_rx;
|
||||
struct lcore_queue_conf *qconf;
|
||||
const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S *
|
||||
BURST_TX_DRAIN_US;
|
||||
struct rte_eth_dev_tx_buffer *buffer;
|
||||
prev_tsc = 0;
|
||||
timer_tsc = 0;
|
||||
lcore_id = rte_lcore_id();
|
||||
qconf = &lcore_queue_conf[lcore_id];
|
||||
if (qconf->n_rx_port == 0) {
|
||||
RTE_LOG(INFO, L2FWD, "lcore %u has nothing to do\n", lcore_id);
|
||||
return;
|
||||
}
|
||||
RTE_LOG(INFO, L2FWD, "entering main loop on lcore %u\n", lcore_id);
|
||||
for (i = 0; i < qconf->n_rx_port; i++) {
|
||||
portid = qconf->rx_port_list[i];
|
||||
RTE_LOG(INFO, L2FWD, " -- lcoreid=%u portid=%u\n", lcore_id,
|
||||
portid);
|
||||
}
|
||||
while (!force_quit) {
|
||||
cur_tsc = rte_rdtsc();
|
||||
/*
|
||||
* TX burst queue drain
|
||||
*/
|
||||
diff_tsc = cur_tsc - prev_tsc;
|
||||
if (unlikely(diff_tsc > drain_tsc)) {
|
||||
for (i = 0; i < qconf->n_rx_port; i++) {
|
||||
portid = l2fwd_dst_ports[qconf->rx_port_list[i]];
|
||||
buffer = tx_buffer[portid];
|
||||
sent = rte_eth_tx_buffer_flush(portid, 0, buffer);
|
||||
if (sent)
|
||||
port_statistics[portid].tx += sent;
|
||||
}
|
||||
/* if timer is enabled */
|
||||
if (timer_period > 0) {
|
||||
/* advance the timer */
|
||||
timer_tsc += diff_tsc;
|
||||
/* if timer has reached its timeout */
|
||||
if (unlikely(timer_tsc >= timer_period)) {
|
||||
/* do this only on master core */
|
||||
if (lcore_id == rte_get_master_lcore()) {
|
||||
//print_stats();
|
||||
/* reset the timer */
|
||||
timer_tsc = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
prev_tsc = cur_tsc;
|
||||
}
|
||||
/*
|
||||
* Read packet from RX queues
|
||||
*/
|
||||
for (i = 0; i < qconf->n_rx_port; i++) {
|
||||
portid = qconf->rx_port_list[i];
|
||||
nb_rx = rte_eth_rx_burst(portid, 0,
|
||||
pkts_burst, MAX_PKT_BURST);
|
||||
port_statistics[portid].rx += nb_rx;
|
||||
for (j = 0; j < nb_rx; j++) {
|
||||
m = pkts_burst[j];
|
||||
rte_prefetch0(rte_pktmbuf_mtod(m, void *));
|
||||
l2fwd_simple_forward(m, portid, bs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
static int
|
||||
l2fwd_launch_one_lcore(void *bs)
|
||||
{
|
||||
l2fwd_main_loop(bs);
|
||||
return 0;
|
||||
}
|
||||
/* display usage */
|
||||
static void
|
||||
l2fwd_usage(const char *prgname)
|
||||
{
|
||||
printf("%s [EAL options] -- -p PORTMASK [-q NQ]\n"
|
||||
" -p PORTMASK: hexadecimal bitmask of ports to configure\n"
|
||||
" -q NQ: number of queue (=ports) per lcore (default is 1)\n"
|
||||
" -T PERIOD: statistics will be refreshed each PERIOD seconds (0 to disable, 10 default, 86400 maximum)\n"
|
||||
" --[no-]mac-updating: Enable or disable MAC addresses updating (enabled by default)\n"
|
||||
" When enabled:\n"
|
||||
" - The source MAC address is replaced by the TX port MAC address\n"
|
||||
" - The destination MAC address is replaced by 02:00:00:00:00:TX_PORT_ID\n",
|
||||
prgname);
|
||||
}
|
||||
static int
|
||||
l2fwd_parse_portmask(const char *portmask)
|
||||
{
|
||||
char *end = NULL;
|
||||
unsigned long pm;
|
||||
/* parse hexadecimal string */
|
||||
pm = strtoul(portmask, &end, 16);
|
||||
if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0'))
|
||||
return -1;
|
||||
if (pm == 0)
|
||||
return -1;
|
||||
return pm;
|
||||
}
|
||||
static unsigned int
|
||||
l2fwd_parse_nqueue(const char *q_arg)
|
||||
{
|
||||
char *end = NULL;
|
||||
unsigned long n;
|
||||
/* parse hexadecimal string */
|
||||
n = strtoul(q_arg, &end, 10);
|
||||
if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0'))
|
||||
return 0;
|
||||
if (n == 0)
|
||||
return 0;
|
||||
if (n >= MAX_RX_QUEUE_PER_LCORE)
|
||||
return 0;
|
||||
return n;
|
||||
}
|
||||
static int
|
||||
l2fwd_parse_timer_period(const char *q_arg)
|
||||
{
|
||||
char *end = NULL;
|
||||
int n;
|
||||
/* parse number string */
|
||||
n = strtol(q_arg, &end, 10);
|
||||
if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0'))
|
||||
return -1;
|
||||
if (n >= MAX_TIMER_PERIOD)
|
||||
return -1;
|
||||
return n;
|
||||
}
|
||||
static const char short_options[] =
|
||||
"p:" /* portmask */
|
||||
"q:" /* number of queues */
|
||||
"T:" /* timer period */
|
||||
;
|
||||
#define CMD_LINE_OPT_MAC_UPDATING "mac-updating"
|
||||
#define CMD_LINE_OPT_NO_MAC_UPDATING "no-mac-updating"
|
||||
enum {
|
||||
/* long options mapped to a short option */
|
||||
/* first long only option value must be >= 256, so that we won't
|
||||
* conflict with short options */
|
||||
CMD_LINE_OPT_MIN_NUM = 256,
|
||||
};
|
||||
static const struct option lgopts[] = {
|
||||
{ CMD_LINE_OPT_MAC_UPDATING, no_argument, &mac_updating, 1},
|
||||
{ CMD_LINE_OPT_NO_MAC_UPDATING, no_argument, &mac_updating, 0},
|
||||
{NULL, 0, 0, 0}
|
||||
};
|
||||
/* Parse the argument given in the command line of the application */
|
||||
static int
|
||||
l2fwd_parse_args(int argc, char **argv)
|
||||
{
|
||||
int opt, ret, timer_secs;
|
||||
char **argvopt;
|
||||
int option_index;
|
||||
char *prgname = argv[0];
|
||||
argvopt = argv;
|
||||
while ((opt = getopt_long(argc, argvopt, short_options,
|
||||
lgopts, &option_index)) != EOF) {
|
||||
switch (opt) {
|
||||
/* portmask */
|
||||
case 'p':
|
||||
l2fwd_enabled_port_mask = l2fwd_parse_portmask(optarg);
|
||||
if (l2fwd_enabled_port_mask == 0) {
|
||||
printf("invalid portmask\n");
|
||||
l2fwd_usage(prgname);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
/* nqueue */
|
||||
case 'q':
|
||||
l2fwd_rx_queue_per_lcore = l2fwd_parse_nqueue(optarg);
|
||||
if (l2fwd_rx_queue_per_lcore == 0) {
|
||||
printf("invalid queue number\n");
|
||||
l2fwd_usage(prgname);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
/* timer period */
|
||||
case 'T':
|
||||
timer_secs = l2fwd_parse_timer_period(optarg);
|
||||
if (timer_secs < 0) {
|
||||
printf("invalid timer period\n");
|
||||
l2fwd_usage(prgname);
|
||||
return -1;
|
||||
}
|
||||
timer_period = timer_secs;
|
||||
break;
|
||||
/* long options */
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
l2fwd_usage(prgname);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (optind >= 0)
|
||||
argv[optind-1] = prgname;
|
||||
ret = optind-1;
|
||||
optind = 1; /* reset getopt lib */
|
||||
return ret;
|
||||
}
|
||||
/* Check the link status of all ports in up to 9s, and print them finally */
|
||||
static void
|
||||
check_all_ports_link_status(uint32_t port_mask)
|
||||
{
|
||||
#define CHECK_INTERVAL 100 /* 100ms */
|
||||
#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
|
||||
uint16_t portid;
|
||||
uint8_t count, all_ports_up, print_flag = 0;
|
||||
struct rte_eth_link link;
|
||||
printf("\nChecking link status");
|
||||
fflush(stdout);
|
||||
for (count = 0; count <= MAX_CHECK_TIME; count++) {
|
||||
if (force_quit)
|
||||
return;
|
||||
all_ports_up = 1;
|
||||
RTE_ETH_FOREACH_DEV(portid) {
|
||||
if (force_quit)
|
||||
return;
|
||||
if ((port_mask & (1 << portid)) == 0)
|
||||
continue;
|
||||
memset(&link, 0, sizeof(link));
|
||||
rte_eth_link_get_nowait(portid, &link);
|
||||
/* print link status if flag set */
|
||||
if (print_flag == 1) {
|
||||
if (link.link_status)
|
||||
printf(
|
||||
"Port%d Link Up. Speed %u Mbps - %s\n",
|
||||
portid, link.link_speed,
|
||||
(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
|
||||
("full-duplex") : ("half-duplex\n"));
|
||||
else
|
||||
printf("Port %d Link Down\n", portid);
|
||||
continue;
|
||||
}
|
||||
/* clear all_ports_up flag if any link down */
|
||||
if (link.link_status == ETH_LINK_DOWN) {
|
||||
all_ports_up = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* after finally printing all link status, get out */
|
||||
if (print_flag == 1)
|
||||
break;
|
||||
if (all_ports_up == 0) {
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
rte_delay_ms(CHECK_INTERVAL);
|
||||
}
|
||||
/* set the print_flag if all ports up or timeout */
|
||||
if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
|
||||
print_flag = 1;
|
||||
printf("done\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
static void
|
||||
signal_handler(int signum)
|
||||
{
|
||||
if (signum == SIGINT || signum == SIGTERM) {
|
||||
printf("\n\nSignal %d received, preparing to exit...\n",
|
||||
signum);
|
||||
force_quit = true;
|
||||
}
|
||||
}
|
||||
int
|
||||
dpdk_main(int argc, char **argv, benetel_t *bs)
|
||||
{
|
||||
struct lcore_queue_conf *qconf;
|
||||
int ret;
|
||||
uint16_t nb_ports;
|
||||
uint16_t nb_ports_available = 0;
|
||||
uint16_t portid, last_port;
|
||||
unsigned lcore_id, rx_lcore_id;
|
||||
unsigned nb_ports_in_mask = 0;
|
||||
unsigned int nb_lcores = 0;
|
||||
unsigned int nb_mbufs;
|
||||
/* init EAL */
|
||||
ret = rte_eal_init(argc, argv);
|
||||
if (ret < 0)
|
||||
rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n");
|
||||
argc -= ret;
|
||||
argv += ret;
|
||||
force_quit = false;
|
||||
signal(SIGINT, signal_handler);
|
||||
signal(SIGTERM, signal_handler);
|
||||
/* parse application arguments (after the EAL ones) */
|
||||
ret = l2fwd_parse_args(argc, argv);
|
||||
if (ret < 0)
|
||||
rte_exit(EXIT_FAILURE, "Invalid L2FWD arguments\n");
|
||||
printf("MAC updating %s\n", mac_updating ? "enabled" : "disabled");
|
||||
/* convert to number of cycles */
|
||||
timer_period *= rte_get_timer_hz();
|
||||
nb_ports = rte_eth_dev_count_avail();
|
||||
if (nb_ports == 0)
|
||||
rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
|
||||
/* check port mask to possible port mask */
|
||||
if (l2fwd_enabled_port_mask & ~((1 << nb_ports) - 1))
|
||||
rte_exit(EXIT_FAILURE, "Invalid portmask; possible (0x%x)\n",
|
||||
(1 << nb_ports) - 1);
|
||||
/* reset l2fwd_dst_ports */
|
||||
for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++)
|
||||
l2fwd_dst_ports[portid] = 0;
|
||||
last_port = 0;
|
||||
/*
|
||||
* Each logical core is assigned a dedicated TX queue on each port.
|
||||
*/
|
||||
RTE_ETH_FOREACH_DEV(portid) {
|
||||
/* skip ports that are not enabled */
|
||||
if ((l2fwd_enabled_port_mask & (1 << portid)) == 0)
|
||||
continue;
|
||||
if (nb_ports_in_mask % 2) {
|
||||
l2fwd_dst_ports[portid] = last_port;
|
||||
l2fwd_dst_ports[last_port] = portid;
|
||||
}
|
||||
else
|
||||
last_port = portid;
|
||||
nb_ports_in_mask++;
|
||||
}
|
||||
if (nb_ports_in_mask % 2) {
|
||||
printf("Notice: odd number of ports in portmask.\n");
|
||||
l2fwd_dst_ports[last_port] = last_port;
|
||||
}
|
||||
rx_lcore_id = 0;
|
||||
qconf = NULL;
|
||||
/* Initialize the port/queue configuration of each logical core */
|
||||
RTE_ETH_FOREACH_DEV(portid) {
|
||||
/* skip ports that are not enabled */
|
||||
if ((l2fwd_enabled_port_mask & (1 << portid)) == 0)
|
||||
continue;
|
||||
/* get the lcore_id for this port */
|
||||
while (rte_lcore_is_enabled(rx_lcore_id) == 0 ||
|
||||
lcore_queue_conf[rx_lcore_id].n_rx_port ==
|
||||
l2fwd_rx_queue_per_lcore) {
|
||||
rx_lcore_id++;
|
||||
if (rx_lcore_id >= RTE_MAX_LCORE)
|
||||
rte_exit(EXIT_FAILURE, "Not enough cores\n");
|
||||
}
|
||||
if (qconf != &lcore_queue_conf[rx_lcore_id]) {
|
||||
/* Assigned a new logical core in the loop above. */
|
||||
qconf = &lcore_queue_conf[rx_lcore_id];
|
||||
nb_lcores++;
|
||||
}
|
||||
qconf->rx_port_list[qconf->n_rx_port] = portid;
|
||||
qconf->n_rx_port++;
|
||||
printf("Lcore %u: RX port %u\n", rx_lcore_id, portid);
|
||||
}
|
||||
nb_mbufs = RTE_MAX(nb_ports * (nb_rxd + nb_txd + MAX_PKT_BURST +
|
||||
nb_lcores * MEMPOOL_CACHE_SIZE), 8192U);
|
||||
/* create the mbuf pool */
|
||||
l2fwd_pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", nb_mbufs,
|
||||
MEMPOOL_CACHE_SIZE, 0, 9680,
|
||||
rte_socket_id());
|
||||
if (l2fwd_pktmbuf_pool == NULL)
|
||||
rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n");
|
||||
/* Initialise each port */
|
||||
RTE_ETH_FOREACH_DEV(portid) {
|
||||
struct rte_eth_rxconf rxq_conf;
|
||||
struct rte_eth_txconf txq_conf;
|
||||
struct rte_eth_conf local_port_conf = port_conf;
|
||||
struct rte_eth_dev_info dev_info;
|
||||
/* skip ports that are not enabled */
|
||||
if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) {
|
||||
printf("Skipping disabled port %u\n", portid);
|
||||
continue;
|
||||
}
|
||||
nb_ports_available++;
|
||||
/* init port */
|
||||
printf("Initializing port %u... ", portid);
|
||||
fflush(stdout);
|
||||
rte_eth_dev_info_get(portid, &dev_info);
|
||||
if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE)
|
||||
local_port_conf.txmode.offloads |=
|
||||
DEV_TX_OFFLOAD_MBUF_FAST_FREE;
|
||||
ret = rte_eth_dev_configure(portid, 1, 1, &local_port_conf);
|
||||
if (ret < 0)
|
||||
rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%u\n",
|
||||
ret, portid);
|
||||
ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd,
|
||||
&nb_txd);
|
||||
if (ret < 0)
|
||||
rte_exit(EXIT_FAILURE,
|
||||
"Cannot adjust number of descriptors: err=%d, port=%u\n",
|
||||
ret, portid);
|
||||
rte_eth_macaddr_get(portid,&l2fwd_ports_eth_addr[portid]);
|
||||
/* init one RX queue */
|
||||
fflush(stdout);
|
||||
rxq_conf = dev_info.default_rxconf;
|
||||
rxq_conf.offloads = local_port_conf.rxmode.offloads;
|
||||
ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd,
|
||||
rte_eth_dev_socket_id(portid),
|
||||
&rxq_conf,
|
||||
l2fwd_pktmbuf_pool);
|
||||
if (ret < 0)
|
||||
rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup:err=%d, port=%u\n",
|
||||
ret, portid);
|
||||
/* init one TX queue on each port */
|
||||
fflush(stdout);
|
||||
txq_conf = dev_info.default_txconf;
|
||||
txq_conf.offloads = local_port_conf.txmode.offloads;
|
||||
ret = rte_eth_tx_queue_setup(portid, 0, nb_txd,
|
||||
rte_eth_dev_socket_id(portid),
|
||||
&txq_conf);
|
||||
if (ret < 0)
|
||||
rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup:err=%d, port=%u\n",
|
||||
ret, portid);
|
||||
/* Initialize TX buffers */
|
||||
tx_buffer[portid] = rte_zmalloc_socket("tx_buffer",
|
||||
RTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST), 0,
|
||||
rte_eth_dev_socket_id(portid));
|
||||
if (tx_buffer[portid] == NULL)
|
||||
rte_exit(EXIT_FAILURE, "Cannot allocate buffer for tx on port %u\n",
|
||||
portid);
|
||||
rte_eth_tx_buffer_init(tx_buffer[portid], MAX_PKT_BURST);
|
||||
ret = rte_eth_tx_buffer_set_err_callback(tx_buffer[portid],
|
||||
rte_eth_tx_buffer_count_callback,
|
||||
&port_statistics[portid].dropped);
|
||||
if (ret < 0)
|
||||
rte_exit(EXIT_FAILURE,
|
||||
"Cannot set error callback for tx buffer on port %u\n",
|
||||
portid);
|
||||
/* Start device */
|
||||
ret = rte_eth_dev_start(portid);
|
||||
if (ret < 0)
|
||||
rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err=%d, port=%u\n",
|
||||
ret, portid);
|
||||
printf("done: \n");
|
||||
rte_eth_promiscuous_enable(portid);
|
||||
printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n",
|
||||
portid,
|
||||
l2fwd_ports_eth_addr[portid].addr_bytes[0],
|
||||
l2fwd_ports_eth_addr[portid].addr_bytes[1],
|
||||
l2fwd_ports_eth_addr[portid].addr_bytes[2],
|
||||
l2fwd_ports_eth_addr[portid].addr_bytes[3],
|
||||
l2fwd_ports_eth_addr[portid].addr_bytes[4],
|
||||
l2fwd_ports_eth_addr[portid].addr_bytes[5]);
|
||||
/* initialize port stats */
|
||||
memset(&port_statistics, 0, sizeof(port_statistics));
|
||||
}
|
||||
if (!nb_ports_available) {
|
||||
rte_exit(EXIT_FAILURE,
|
||||
"All available ports are disabled. Please set portmask.\n");
|
||||
}
|
||||
check_all_ports_link_status(l2fwd_enabled_port_mask);
|
||||
ret = 0;
|
||||
/* launch per-lcore init on every lcore */
|
||||
rte_eal_mp_remote_launch(l2fwd_launch_one_lcore, bs, CALL_MASTER);
|
||||
RTE_LCORE_FOREACH_SLAVE(lcore_id) {
|
||||
if (rte_eal_wait_lcore(lcore_id) < 0) {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
RTE_ETH_FOREACH_DEV(portid) {
|
||||
if ((l2fwd_enabled_port_mask & (1 << portid)) == 0)
|
||||
continue;
|
||||
printf("Closing port %d...", portid);
|
||||
rte_eth_dev_stop(portid);
|
||||
rte_eth_dev_close(portid);
|
||||
printf(" Done\n");
|
||||
}
|
||||
printf("Bye...\n");
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* 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 "low.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void store_ul(benetel_t *bs, ul_packet_t *ul)
|
||||
{
|
||||
/* only antenna 0 for the moment */
|
||||
if (ul->antenna != 0)
|
||||
return;
|
||||
|
||||
if (ul->subframe != bs->next_subframe ||
|
||||
ul->symbol != bs->next_symbol) {
|
||||
printf("%s: fatal, expected frame.sf.symbol %d.%d.%d, got %d.%d.%d\n",
|
||||
__FUNCTION__,
|
||||
bs->expected_benetel_frame, bs->next_subframe, bs->next_symbol,
|
||||
ul->frame, ul->subframe, ul->symbol);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
lock_ul_buffer(bs->buffers, bs->next_subframe);
|
||||
if (bs->buffers->ul_busy[bs->next_subframe] & (1 << bs->next_symbol)) {
|
||||
printf("%s: warning, UL overflow (sf.symbol %d.%d)\n", __FUNCTION__,
|
||||
bs->next_subframe, bs->next_symbol);
|
||||
}
|
||||
memcpy(bs->buffers->ul[bs->next_subframe] + bs->next_symbol * 1200*4,
|
||||
ul->iq, 1200*4);
|
||||
bs->buffers->ul_busy[bs->next_subframe] |= (1 << bs->next_symbol);
|
||||
signal_ul_buffer(bs->buffers, bs->next_subframe);
|
||||
unlock_ul_buffer(bs->buffers, bs->next_subframe);
|
||||
|
||||
bs->next_symbol++;
|
||||
if (bs->next_symbol == 14) {
|
||||
bs->next_symbol = 0;
|
||||
bs->next_subframe = (bs->next_subframe + 1) % 10;
|
||||
if (bs->next_subframe == 0) {
|
||||
bs->expected_benetel_frame++;
|
||||
bs->expected_benetel_frame &= 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void store_prach(benetel_t *bs, int frame, int subframe, void *data)
|
||||
{
|
||||
static int last_frame = -1;
|
||||
static int last_subframe = -1;
|
||||
/* hack: antenna number is always 0, discard second packet with same f/sf */
|
||||
if (frame == last_frame && subframe == last_subframe) return;
|
||||
last_frame = frame;
|
||||
last_subframe = subframe;
|
||||
|
||||
lock_ul_buffer(bs->buffers, subframe);
|
||||
if (bs->buffers->prach_busy[subframe]) {
|
||||
printf("store_prach: fatal: previous prach buffer not processed\n");
|
||||
unlock_ul_buffer(bs->buffers, subframe);
|
||||
return;
|
||||
}
|
||||
bs->buffers->prach_busy[subframe] = 1;
|
||||
memcpy(bs->buffers->prach[subframe], data, 849*4);
|
||||
signal_ul_buffer(bs->buffers, subframe);
|
||||
unlock_ul_buffer(bs->buffers, subframe);
|
||||
|
||||
}
|
||||
|
||||
void *benetel_start_dpdk(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line);
|
||||
|
||||
void *benetel_start(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line)
|
||||
{
|
||||
if (!strcmp(ifname, "dpdk"))
|
||||
return benetel_start_dpdk(ifname, buffers, dpdk_main_command_line);
|
||||
printf("benetel: fatal: interface %s not supported, only dpdpk is supported\n", ifname);
|
||||
exit(1);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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 _BENETEL_LOW_H_
|
||||
#define _BENETEL_LOW_H_
|
||||
|
||||
#include "shared_buffers.h"
|
||||
|
||||
typedef struct {
|
||||
shared_buffers *buffers;
|
||||
int next_subframe;
|
||||
int next_symbol;
|
||||
int expected_benetel_frame;
|
||||
char *dpdk_main_command_line;
|
||||
} benetel_t;
|
||||
|
||||
typedef struct {
|
||||
int frame;
|
||||
int subframe;
|
||||
int slot;
|
||||
int symbol;
|
||||
int antenna;
|
||||
unsigned char iq[4800];
|
||||
} ul_packet_t;
|
||||
|
||||
void *benetel_start(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line);
|
||||
|
||||
void store_ul(benetel_t *bs, ul_packet_t *ul);
|
||||
void store_prach(benetel_t *bs, int frame, int subframe, void *data);
|
||||
|
||||
#endif /* _BENETEL_LOW_H_ */
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* those 2 lines for CPU_SET */
|
||||
#define _GNU_SOURCE
|
||||
#include <sched.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "low.h"
|
||||
|
||||
int dpdk_main(int argc, char **argv, benetel_t *);
|
||||
|
||||
void *dpdk_thread(void *_bs)
|
||||
{
|
||||
benetel_t *bs = _bs;
|
||||
int n = 0;
|
||||
char **v = NULL; // { "softmodem", "-n", "2", "-l", "8", "--", "-p", "0x2" };
|
||||
char *s = bs->dpdk_main_command_line;
|
||||
char *tok;
|
||||
|
||||
while ((tok = strtok(s, " ")) != NULL) {
|
||||
n++;
|
||||
v = realloc(v, n * sizeof(char *));
|
||||
if (v == NULL) {
|
||||
printf("%s: out of memory\n", __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
v[n-1] = tok;
|
||||
s = NULL;
|
||||
}
|
||||
|
||||
dpdk_main(n, v, bs);
|
||||
exit(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *benetel_start_dpdk(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line)
|
||||
{
|
||||
benetel_t *bs;
|
||||
|
||||
bs = calloc(1, sizeof(benetel_t));
|
||||
if (bs == NULL) {
|
||||
printf("%s: out of memory\n", __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
bs->buffers = buffers;
|
||||
|
||||
bs->expected_benetel_frame = 255;
|
||||
|
||||
bs->dpdk_main_command_line = dpdk_main_command_line;
|
||||
|
||||
pthread_attr_t attr;
|
||||
|
||||
if (pthread_attr_init(&attr) != 0) {
|
||||
printf("pthread_attr_init failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cpu_set_t cpuset;
|
||||
CPU_ZERO(&cpuset);
|
||||
CPU_SET(12,&cpuset);
|
||||
if (pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset) != 0) {
|
||||
printf("pthread_attr_setaffinity_np failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO) != 0) {
|
||||
printf("pthread_attr_setschedpolicy failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct sched_param params;
|
||||
params.sched_priority = sched_get_priority_max(SCHED_FIFO);
|
||||
if (sched_get_priority_max(SCHED_FIFO) == -1) {
|
||||
printf("sched_get_priority_max failed\n");
|
||||
exit(1);
|
||||
}
|
||||
if (pthread_attr_setschedparam(&attr, ¶ms) != 0) {
|
||||
printf("pthread_setschedparam failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pthread_t t;
|
||||
if (pthread_create(&t, &attr, dpdk_thread, bs) != 0) {
|
||||
printf("%s: thread creation failed\n", __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pthread_attr_destroy(&attr) != 0) {
|
||||
printf("pthread_attr_init failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return bs;
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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 "shared_buffers.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void init_buffers(shared_buffers *s)
|
||||
{
|
||||
int subframe;
|
||||
|
||||
memset(s, 0, sizeof(*s));
|
||||
|
||||
for (subframe = 0; subframe < 10; subframe++) {
|
||||
if (pthread_mutex_init(&s->m_dl[subframe], NULL) != 0 ||
|
||||
pthread_cond_init(&s->c_dl[subframe], NULL) != 0 ||
|
||||
pthread_mutex_init(&s->m_ul[subframe], NULL) != 0 ||
|
||||
pthread_cond_init(&s->c_ul[subframe], NULL) != 0) {
|
||||
printf("%s: error initializing mutex/cond\n", __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* in FDD the eNB's first transmitted DL subframe is 4 but the device
|
||||
* needs to have subframes 1, 2 and 3 ready. Let's pretend there are ready.
|
||||
*/
|
||||
s->dl_busy[1] = 0x3fff;
|
||||
s->dl_busy[2] = 0x3fff;
|
||||
s->dl_busy[3] = 0x3fff;
|
||||
}
|
||||
|
||||
void lock_dl_buffer(shared_buffers *s, int subframe)
|
||||
{
|
||||
if (pthread_mutex_lock(&s->m_dl[subframe]) != 0) {
|
||||
printf("%s: fatal: lock fails\n", __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void unlock_dl_buffer(shared_buffers *s, int subframe)
|
||||
{
|
||||
if (pthread_mutex_unlock(&s->m_dl[subframe]) != 0) {
|
||||
printf("%s: fatal: unlock fails\n", __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void wait_dl_buffer(shared_buffers *s, int subframe)
|
||||
{
|
||||
if (pthread_cond_wait(&s->c_dl[subframe], &s->m_dl[subframe]) != 0) {
|
||||
printf("%s: fatal: cond_wait fails\n", __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void signal_dl_buffer(shared_buffers *s, int subframe)
|
||||
{
|
||||
if (pthread_cond_broadcast(&s->c_dl[subframe]) != 0) {
|
||||
printf("%s: fatal: cond_broadcast fails\n", __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void lock_ul_buffer(shared_buffers *s, int subframe)
|
||||
{
|
||||
if (pthread_mutex_lock(&s->m_ul[subframe]) != 0) {
|
||||
printf("%s: fatal: lock fails\n", __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void unlock_ul_buffer(shared_buffers *s, int subframe)
|
||||
{
|
||||
if (pthread_mutex_unlock(&s->m_ul[subframe]) != 0) {
|
||||
printf("%s: fatal: unlock fails\n", __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void wait_ul_buffer(shared_buffers *s, int subframe)
|
||||
{
|
||||
if (pthread_cond_wait(&s->c_ul[subframe], &s->m_ul[subframe]) != 0) {
|
||||
printf("%s: fatal: cond_wait fails\n", __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void signal_ul_buffer(shared_buffers *s, int subframe)
|
||||
{
|
||||
if (pthread_cond_broadcast(&s->c_ul[subframe]) != 0) {
|
||||
printf("%s: fatal: cond_broadcast fails\n", __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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 _SHARED_BUFFERS_H_
|
||||
#define _SHARED_BUFFERS_H_
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
unsigned char dl[10][14*1200*4];
|
||||
unsigned char ul[10][14*1200*4];
|
||||
uint16_t dl_busy[10];
|
||||
uint16_t ul_busy[10];
|
||||
|
||||
pthread_mutex_t m_ul[10];
|
||||
pthread_cond_t c_ul[10];
|
||||
|
||||
pthread_mutex_t m_dl[10];
|
||||
pthread_cond_t c_dl[10];
|
||||
|
||||
unsigned char prach[10][849*4];
|
||||
unsigned char prach_busy[10];
|
||||
|
||||
/* statistics/error counting */
|
||||
int ul_overflow;
|
||||
int dl_underflow;
|
||||
} shared_buffers;
|
||||
|
||||
void init_buffers(shared_buffers *s);
|
||||
|
||||
void lock_dl_buffer(shared_buffers *s, int subframe);
|
||||
void unlock_dl_buffer(shared_buffers *s, int subframe);
|
||||
void wait_dl_buffer(shared_buffers *s, int subframe);
|
||||
void signal_dl_buffer(shared_buffers *s, int subframe);
|
||||
|
||||
void lock_ul_buffer(shared_buffers *s, int subframe);
|
||||
void unlock_ul_buffer(shared_buffers *s, int subframe);
|
||||
void wait_ul_buffer(shared_buffers *s, int subframe);
|
||||
void signal_ul_buffer(shared_buffers *s, int subframe);
|
||||
|
||||
#endif /* _SHARED_BUFFERS_H_ */
|
||||
@@ -0,0 +1,388 @@
|
||||
/*
|
||||
* 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 "common_lib.h"
|
||||
#include "ethernet_lib.h"
|
||||
#include "shared_buffers.h"
|
||||
#include "low.h"
|
||||
#include "openair1/PHY/defs_gNB.h"
|
||||
|
||||
typedef struct {
|
||||
eth_state_t e;
|
||||
shared_buffers buffers;
|
||||
rru_config_msg_type_t last_msg;
|
||||
int capabilities_sent;
|
||||
void *benetel_priv;
|
||||
char *dpdk_main_command_line;
|
||||
} benetel_eth_state_t;
|
||||
|
||||
int trx_benetel_start(openair0_device *device)
|
||||
{
|
||||
printf("BENETEL: %s\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void trx_benetel_end(openair0_device *device)
|
||||
{
|
||||
printf("BENETEL: %s\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
|
||||
int trx_benetel_stop(openair0_device *device)
|
||||
{
|
||||
printf("BENETEL: %s\n", __FUNCTION__);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int trx_benetel_set_freq(openair0_device* device,
|
||||
openair0_config_t *openair0_cfg,
|
||||
int exmimo_dump_config)
|
||||
{
|
||||
printf("BENETEL: %s\n", __FUNCTION__);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int trx_benetel_set_gains(openair0_device* device,
|
||||
openair0_config_t *openair0_cfg)
|
||||
{
|
||||
printf("BENETEL: %s\n", __FUNCTION__);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int trx_benetel_get_stats(openair0_device* device)
|
||||
{
|
||||
printf("BENETEL: %s\n", __FUNCTION__);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int trx_benetel_reset_stats(openair0_device* device)
|
||||
{
|
||||
printf("BENETEL: %s\n", __FUNCTION__);
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
int ethernet_tune(openair0_device *device,
|
||||
unsigned int option,
|
||||
int value)
|
||||
{
|
||||
printf("BENETEL: %s\n", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int trx_benetel_write_raw(openair0_device *device,
|
||||
openair0_timestamp timestamp,
|
||||
void **buff, int nsamps, int cc, int flags)
|
||||
{
|
||||
printf("BENETEL: %s\n", __FUNCTION__);
|
||||
return nsamps*4;
|
||||
}
|
||||
|
||||
int trx_benetel_read_raw(openair0_device *device,
|
||||
openair0_timestamp *timestamp,
|
||||
void **buff, int nsamps, int cc)
|
||||
{
|
||||
printf("BENETEL: %s\n", __FUNCTION__);
|
||||
return nsamps*4;
|
||||
}
|
||||
|
||||
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_benetel_ctlsend(openair0_device *device, void *msg, ssize_t msg_len)
|
||||
{
|
||||
RRU_CONFIG_msg_t *rru_config_msg = msg;
|
||||
benetel_eth_state_t *s = device->priv;
|
||||
|
||||
printf("BENETEL: %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_benetel_ctlrecv(openair0_device *device, void *msg, ssize_t msg_len)
|
||||
{
|
||||
RRU_CONFIG_msg_t *rru_config_msg = msg;
|
||||
benetel_eth_state_t *s = device->priv;
|
||||
|
||||
printf("BENETEL: %s\n", __FUNCTION__);
|
||||
|
||||
if (s->last_msg == RAU_tick && s->capabilities_sent == 0) {
|
||||
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);
|
||||
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->nb_rx[0] = 1;
|
||||
cap->nb_tx[0] = 1;
|
||||
cap->max_pdschReferenceSignalPower[0] = -27;
|
||||
cap->max_rxgain[0] = 90;
|
||||
|
||||
s->capabilities_sent = 1;
|
||||
|
||||
return rru_config_msg->len;
|
||||
}
|
||||
#if 0
|
||||
if (s->last_msg == RRU_config) {
|
||||
rru_config_msg->type = RRU_config_ok;
|
||||
return 0;
|
||||
}
|
||||
if (s->last_msg == RRU_start) {
|
||||
printf("***************** benetel start\n");
|
||||
s->benetel_priv = benetel_start(s->e.if_name, &s->buffers, s->dpdk_main_command_line);
|
||||
}
|
||||
#endif
|
||||
if (s->last_msg == RRU_config) {
|
||||
rru_config_msg->type = RRU_config_ok;
|
||||
s->benetel_priv = benetel_start(s->e.if_name, &s->buffers, s->dpdk_main_command_line);
|
||||
}
|
||||
/* correct? */
|
||||
//printf("***************** benetel pause\n");
|
||||
// while (1) pause();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void benetel_fh_if4p5_south_in(RU_t *ru,
|
||||
int *frame,
|
||||
int *slot)
|
||||
{
|
||||
//printf("XXX benetel_fh_if4p5_south_in %d %d\n", *frame, *slot);
|
||||
benetel_eth_state_t *s = ru->ifdevice.priv;
|
||||
NR_DL_FRAME_PARMS *fp;
|
||||
int symbol;
|
||||
int32_t *rxdata;
|
||||
int antenna = 0;
|
||||
|
||||
lock_ul_buffer(&s->buffers, *slot);
|
||||
#if 1
|
||||
next:
|
||||
while (!(s->buffers.ul_busy[*slot] == 0x3fff ||
|
||||
s->buffers.prach_busy[*slot] == 1))
|
||||
wait_ul_buffer(&s->buffers, *slot);
|
||||
if (s->buffers.prach_busy[*slot] == 1) {
|
||||
int i;
|
||||
int antenna = 0;
|
||||
uint16_t *in;
|
||||
uint16_t *out;
|
||||
in = (uint16_t *)s->buffers.prach[*slot];
|
||||
out = (uint16_t *)ru->prach_rxsigF[antenna];
|
||||
for (i = 0; i < 839*2; i++)
|
||||
out[i] = ntohs(in[i]);
|
||||
s->buffers.prach_busy[*slot] = 0;
|
||||
//printf("prach for f.sl %d.%d\n", *frame, *slot);
|
||||
//ru->wakeup_prach_gNB(ru->gNB_list[0], ru, *frame, *slot);
|
||||
goto next;
|
||||
}
|
||||
#endif
|
||||
|
||||
fp = ru->nr_frame_parms;
|
||||
for (symbol = 0; symbol < 14; symbol++) {
|
||||
int i;
|
||||
uint16_t *p = (uint16_t *)(&s->buffers.ul[*slot][symbol*1272*4]);
|
||||
for (i = 0; i < 1272*2; i++) {
|
||||
p[i] = htons(p[i]);
|
||||
}
|
||||
rxdata = &ru->common.rxdataF[antenna][symbol * fp->ofdm_symbol_size];
|
||||
#if 1
|
||||
memcpy(rxdata + 2048 - 1272/2,
|
||||
&s->buffers.ul[*slot][symbol*1272*4],
|
||||
(1272/2) * 4);
|
||||
memcpy(rxdata,
|
||||
&s->buffers.ul[*slot][symbol*1272*4] + (1272/2)*4,
|
||||
(1272/2) * 4);
|
||||
#endif
|
||||
}
|
||||
|
||||
s->buffers.ul_busy[*slot] = 0;
|
||||
signal_ul_buffer(&s->buffers, *slot);
|
||||
unlock_ul_buffer(&s->buffers, *slot);
|
||||
|
||||
//printf("BENETEL: %s (f.sf %d.%d)\n", __FUNCTION__, *frame, *slot);
|
||||
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
extern uint16_t sl_ahead;
|
||||
int f = *frame;
|
||||
int sl = *slot;
|
||||
|
||||
//calculate timestamp_rx, timestamp_tx based on frame and slot
|
||||
proc->tti_rx = sl;
|
||||
proc->frame_rx = f;
|
||||
/* TODO: be sure of samples_per_slot0
|
||||
FK: should use get_samples_per_slot(slot)
|
||||
but for mu=1 its ok
|
||||
*/
|
||||
proc->timestamp_rx = ((proc->frame_rx * 20) + proc->tti_rx ) * fp->samples_per_slot0;
|
||||
|
||||
if (get_nprocs()<=4) {
|
||||
// why? what if there are more?
|
||||
proc->tti_tx = (sl+sl_ahead)%20;
|
||||
proc->frame_tx = (sl>(19-sl_ahead)) ? (f+1)&1023 : f;
|
||||
}
|
||||
}
|
||||
|
||||
void benetel_fh_if4p5_south_out(RU_t *ru,
|
||||
int frame,
|
||||
int slot,
|
||||
uint64_t timestamp)
|
||||
{
|
||||
//printf("XXX benetel_fh_if4p5_south_out %d %d %ld\n", frame, slot, timestamp);
|
||||
benetel_eth_state_t *s = ru->ifdevice.priv;
|
||||
NR_DL_FRAME_PARMS *fp;
|
||||
int symbol;
|
||||
int32_t *txdata;
|
||||
int aa = 0;
|
||||
|
||||
//printf("BENETEL: %s (f.sf %d.%d ts %ld)\n", __FUNCTION__, frame, slot, timestamp);
|
||||
|
||||
lock_dl_buffer(&s->buffers, slot);
|
||||
if (s->buffers.dl_busy[slot]) {
|
||||
printf("%s: fatal: DL buffer busy for subframe %d\n", __FUNCTION__, slot);
|
||||
unlock_dl_buffer(&s->buffers, slot);
|
||||
return;
|
||||
}
|
||||
|
||||
fp = ru->nr_frame_parms;
|
||||
if (ru->num_gNB != 1 || ru->nb_tx != 1 || fp->ofdm_symbol_size != 2048 ||
|
||||
fp->Ncp != NORMAL || fp->symbols_per_slot != 14) {
|
||||
printf("%s:%d:%s: unsupported configuration\n",
|
||||
__FILE__, __LINE__, __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (symbol = 0; symbol < 14; symbol++) {
|
||||
txdata = &ru->common.txdataF_BF[aa][symbol * fp->ofdm_symbol_size];
|
||||
#if 1
|
||||
memcpy(&s->buffers.dl[slot][symbol*1272*4],
|
||||
txdata + 2048 - (1272/2),
|
||||
(1272/2) * 4);
|
||||
memcpy(&s->buffers.dl[slot][symbol*1272*4] + (1272/2)*4,
|
||||
txdata,
|
||||
(1272/2) * 4);
|
||||
#endif
|
||||
int i;
|
||||
uint16_t *p = (uint16_t *)(&s->buffers.dl[slot][symbol*1272*4]);
|
||||
for (i = 0; i < 1272*2; i++) {
|
||||
p[i] = htons(p[i]);
|
||||
}
|
||||
}
|
||||
|
||||
s->buffers.dl_busy[slot] = 0x3fff;
|
||||
unlock_dl_buffer(&s->buffers, slot);
|
||||
}
|
||||
|
||||
void *get_internal_parameter(char *name)
|
||||
{
|
||||
printf("BENETEL: %s\n", __FUNCTION__);
|
||||
|
||||
if (!strcmp(name, "fh_if4p5_south_in"))
|
||||
return benetel_fh_if4p5_south_in;
|
||||
if (!strcmp(name, "fh_if4p5_south_out"))
|
||||
return benetel_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 )
|
||||
{
|
||||
benetel_eth_state_t *eth;
|
||||
|
||||
printf("BENETEL: %s\n", __FUNCTION__);
|
||||
|
||||
device->Mod_id = 0;
|
||||
device->transp_type = ETHERNET_TP;
|
||||
device->trx_start_func = trx_benetel_start;
|
||||
device->trx_get_stats_func = trx_benetel_get_stats;
|
||||
device->trx_reset_stats_func = trx_benetel_reset_stats;
|
||||
device->trx_end_func = trx_benetel_end;
|
||||
device->trx_stop_func = trx_benetel_stop;
|
||||
device->trx_set_freq_func = trx_benetel_set_freq;
|
||||
device->trx_set_gains_func = trx_benetel_set_gains;
|
||||
|
||||
device->trx_write_func = trx_benetel_write_raw;
|
||||
device->trx_read_func = trx_benetel_read_raw;
|
||||
|
||||
device->trx_ctlsend_func = trx_benetel_ctlsend;
|
||||
device->trx_ctlrecv_func = trx_benetel_ctlrecv;
|
||||
|
||||
device->get_internal_parameter = get_internal_parameter;
|
||||
|
||||
eth = calloc(1, sizeof(benetel_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;
|
||||
device->priv = eth;
|
||||
device->openair0_cfg=&openair0_cfg[0];
|
||||
|
||||
if (openair0_cfg->sdr_addrs == NULL) {
|
||||
printf("benetel: fatal: sdr_addrs not set in configuration file\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
eth->dpdk_main_command_line = strdup(openair0_cfg->sdr_addrs);
|
||||
if (eth->dpdk_main_command_line == NULL) {
|
||||
AssertFatal(0==1, "out of memory\n");
|
||||
}
|
||||
|
||||
eth->last_msg = -1;
|
||||
|
||||
init_buffers(ð->buffers);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,856 @@
|
||||
/* license: to be defined */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/queue.h>
|
||||
#include <netinet/in.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <rte_common.h>
|
||||
#include <rte_log.h>
|
||||
#include <rte_malloc.h>
|
||||
#include <rte_memory.h>
|
||||
#include <rte_memcpy.h>
|
||||
#include <rte_eal.h>
|
||||
#include <rte_launch.h>
|
||||
#include <rte_atomic.h>
|
||||
#include <rte_cycles.h>
|
||||
#include <rte_prefetch.h>
|
||||
#include <rte_lcore.h>
|
||||
#include <rte_per_lcore.h>
|
||||
#include <rte_branch_prediction.h>
|
||||
#include <rte_interrupts.h>
|
||||
#include <rte_random.h>
|
||||
#include <rte_debug.h>
|
||||
#include <rte_ether.h>
|
||||
#include <rte_ethdev.h>
|
||||
#include <rte_mempool.h>
|
||||
#include <rte_mbuf.h>
|
||||
|
||||
#include "low.h"
|
||||
|
||||
// HEADER DEFINITION
|
||||
#define ANT_NUM buf[23]
|
||||
#define PAYLOAD_1 buf[20]
|
||||
#define PAYLOAD_2 buf[21]
|
||||
#define ETH_TYPE buf[17]
|
||||
#define SYMBOL buf[29]
|
||||
#define SUBFRAME buf[28]
|
||||
#define FRAME buf[27]
|
||||
|
||||
static volatile bool force_quit;
|
||||
|
||||
unsigned short iq[712320];
|
||||
unsigned char iq_swap[1424640];
|
||||
|
||||
unsigned short *iq_ptr[14];
|
||||
unsigned int dl_start = 0, slot_id_ctrl = 0, count_symbol = 0, sf = 0x10;
|
||||
|
||||
/* MAC updating enabled by default */
|
||||
static int mac_updating = 1;
|
||||
#define RTE_LOGTYPE_L2FWD RTE_LOGTYPE_USER1
|
||||
#define MAX_PKT_BURST 32
|
||||
#define BURST_TX_DRAIN_US 5 /* TX drain every ~100us */
|
||||
#define MEMPOOL_CACHE_SIZE 256
|
||||
/*
|
||||
* Configurable number of RX/TX ring descriptors
|
||||
*/
|
||||
#define RTE_TEST_RX_DESC_DEFAULT 1024
|
||||
#define RTE_TEST_TX_DESC_DEFAULT 1024
|
||||
static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
|
||||
static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
|
||||
/* ethernet addresses of ports */
|
||||
static struct ether_addr l2fwd_ports_eth_addr[RTE_MAX_ETHPORTS];
|
||||
/* mask of enabled ports */
|
||||
static uint32_t l2fwd_enabled_port_mask = 0;
|
||||
/* list of enabled ports */
|
||||
static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS];
|
||||
static unsigned int l2fwd_rx_queue_per_lcore = 1;
|
||||
#define MAX_RX_QUEUE_PER_LCORE 16
|
||||
#define MAX_TX_QUEUE_PER_PORT 16
|
||||
struct lcore_queue_conf {
|
||||
unsigned n_rx_port;
|
||||
unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE];
|
||||
} __rte_cache_aligned;
|
||||
struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE];
|
||||
static struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS];
|
||||
static struct rte_eth_conf port_conf = {
|
||||
.rxmode = {
|
||||
.split_hdr_size = 0,
|
||||
.offloads = DEV_RX_OFFLOAD_CRC_STRIP,
|
||||
.offloads = DEV_RX_OFFLOAD_JUMBO_FRAME,
|
||||
.split_hdr_size = 0,
|
||||
.max_rx_pkt_len = 9500,
|
||||
},
|
||||
.txmode = {
|
||||
.mq_mode = ETH_MQ_TX_NONE,
|
||||
},
|
||||
};
|
||||
struct rte_mempool * l2fwd_pktmbuf_pool = NULL;
|
||||
/* Per-port statistics struct */
|
||||
struct l2fwd_port_statistics {
|
||||
uint64_t tx;
|
||||
uint64_t rx;
|
||||
uint64_t dropped;
|
||||
} __rte_cache_aligned;
|
||||
struct l2fwd_port_statistics port_statistics[RTE_MAX_ETHPORTS];
|
||||
#define MAX_TIMER_PERIOD 86400 /* 1 day max */
|
||||
/* A tsc-based timer responsible for triggering statistics printout */
|
||||
static uint64_t timer_period = 10; /* default period is 10 seconds */
|
||||
/* Print out statistics on packets dropped */
|
||||
static void
|
||||
print_stats(void)
|
||||
{
|
||||
uint64_t total_packets_dropped, total_packets_tx, total_packets_rx;
|
||||
unsigned portid;
|
||||
total_packets_dropped = 0;
|
||||
total_packets_tx = 0;
|
||||
total_packets_rx = 0;
|
||||
const char clr[] = { 27, '[', '2', 'J', '\0' };
|
||||
const char topLeft[] = { 27, '[', '1', ';', '1', 'H','\0' };
|
||||
/* Clear screen and move to top left */
|
||||
printf("%s%s", clr, topLeft);
|
||||
printf("\nPort statistics ====================================");
|
||||
for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) {
|
||||
/* skip disabled ports */
|
||||
if ((l2fwd_enabled_port_mask & (1 << portid)) == 0)
|
||||
continue;
|
||||
printf("\nStatistics for port %u ------------------------------"
|
||||
"\nPackets sent: %24"PRIu64
|
||||
"\nPackets received: %20"PRIu64
|
||||
"\nPackets dropped: %21"PRIu64,
|
||||
portid,
|
||||
port_statistics[portid].tx,
|
||||
port_statistics[portid].rx,
|
||||
port_statistics[portid].dropped);
|
||||
total_packets_dropped += port_statistics[portid].dropped;
|
||||
total_packets_tx += port_statistics[portid].tx;
|
||||
total_packets_rx += port_statistics[portid].rx;
|
||||
}
|
||||
printf("\nAggregate statistics ==============================="
|
||||
"\nTotal packets sent: %18"PRIu64
|
||||
"\nTotal packets received: %14"PRIu64
|
||||
"\nTotal packets dropped: %15"PRIu64,
|
||||
total_packets_tx,
|
||||
total_packets_rx,
|
||||
total_packets_dropped);
|
||||
printf("\n====================================================\n");
|
||||
}
|
||||
static void
|
||||
l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid, benetel_t *bs)
|
||||
{
|
||||
unsigned char *buf, *buf_tx;
|
||||
unsigned int len;
|
||||
struct ether_hdr *eth;
|
||||
|
||||
unsigned dst_port;
|
||||
int sent, prach_ctrl = 0;
|
||||
struct rte_eth_dev_tx_buffer *buffer;
|
||||
|
||||
unsigned char * IQ_ptr;
|
||||
|
||||
ul_packet_t p;
|
||||
|
||||
buf = rte_pktmbuf_mtod(m, unsigned char *);
|
||||
//DD Debug
|
||||
//rte_memdump(stdout, "Rx Packet",buf ,34);
|
||||
eth = rte_pktmbuf_mtod(m, struct ether_hdr *);
|
||||
len = rte_pktmbuf_data_len(m);
|
||||
|
||||
IQ_ptr = &buf[34];
|
||||
if (portid == 0)
|
||||
{
|
||||
//destination mac address (RRU MAC)
|
||||
/*eth->d_addr.addr_bytes[0] = 0x02;
|
||||
eth->d_addr.addr_bytes[1] = 0x00;
|
||||
eth->d_addr.addr_bytes[2] = 0x5e;
|
||||
eth->d_addr.addr_bytes[3] = 0x01;
|
||||
eth->d_addr.addr_bytes[4] = 0x01;
|
||||
eth->d_addr.addr_bytes[5] = 0x01;*/
|
||||
|
||||
eth->d_addr.addr_bytes[0] = buf[6];
|
||||
eth->d_addr.addr_bytes[1] = buf[7];
|
||||
eth->d_addr.addr_bytes[2] = buf[8];
|
||||
eth->d_addr.addr_bytes[3] = buf[9];
|
||||
eth->d_addr.addr_bytes[4] = buf[10];
|
||||
eth->d_addr.addr_bytes[5] = buf[11];
|
||||
|
||||
//source mac address (DU MAC)
|
||||
eth->s_addr.addr_bytes[0] = 0xdd;
|
||||
eth->s_addr.addr_bytes[1] = 0xdd;
|
||||
eth->s_addr.addr_bytes[2] = 0xdd;
|
||||
eth->s_addr.addr_bytes[3] = 0xdd;
|
||||
eth->s_addr.addr_bytes[4] = 0xdd;
|
||||
eth->s_addr.addr_bytes[5] = 0xdd;
|
||||
}
|
||||
else
|
||||
{
|
||||
//destination mac address (RRU MAC)
|
||||
/*eth->d_addr.addr_bytes[0] = 0x02;
|
||||
eth->d_addr.addr_bytes[1] = 0x00;
|
||||
eth->d_addr.addr_bytes[2] = 0x5e;
|
||||
eth->d_addr.addr_bytes[3] = 0x01;
|
||||
eth->d_addr.addr_bytes[4] = 0x01;
|
||||
eth->d_addr.addr_bytes[5] = 0x01;*/
|
||||
|
||||
eth->d_addr.addr_bytes[0] = buf[6];
|
||||
eth->d_addr.addr_bytes[1] = buf[7];
|
||||
eth->d_addr.addr_bytes[2] = buf[8];
|
||||
eth->d_addr.addr_bytes[3] = buf[9];
|
||||
eth->d_addr.addr_bytes[4] = buf[10];
|
||||
eth->d_addr.addr_bytes[5] = buf[11];
|
||||
//source mac address (DU MAC)
|
||||
eth->s_addr.addr_bytes[0] = 0xdd;
|
||||
eth->s_addr.addr_bytes[1] = 0xdd;
|
||||
eth->s_addr.addr_bytes[2] = 0xdd;
|
||||
eth->s_addr.addr_bytes[3] = 0xdd;
|
||||
eth->s_addr.addr_bytes[4] = 0xdd;
|
||||
eth->s_addr.addr_bytes[5] = 0xde;
|
||||
|
||||
}
|
||||
dst_port = l2fwd_dst_ports[portid];
|
||||
//DD Debug
|
||||
//printf("dstPort =%d\n", dst_port);
|
||||
// Handshake Condition
|
||||
if (buf[18] == 0xAA ) // ORAN handshake msgs.
|
||||
{
|
||||
printf("\n Start UP Request Received\n");
|
||||
printf("\n====================================================\n");
|
||||
|
||||
buf[18] = 0xBB;//change to msg2 after receive msg1
|
||||
|
||||
printf(" Start Up Response Sent\n");
|
||||
printf("\n====================================================\n");
|
||||
|
||||
}
|
||||
|
||||
// Trigger start send DL packets
|
||||
if(PAYLOAD_1 == 0x13 && PAYLOAD_2 == 0xe4 && SYMBOL == 0x46 && ANT_NUM == 0x00 && SUBFRAME == 0x00 && dl_start == 0){
|
||||
|
||||
printf("\nU-Plane Started\n");
|
||||
printf("\n====================================================\n");
|
||||
|
||||
dl_start = 1;
|
||||
count_symbol = 28;
|
||||
}
|
||||
|
||||
|
||||
if(PAYLOAD_1 == 0x13 && PAYLOAD_2 == 0xe4 && ANT_NUM == 0x00) {
|
||||
int subframe = SUBFRAME >> 4;
|
||||
int slot = ((SUBFRAME & 0x0f) << 2) | ((SYMBOL >> 6) & 0x03);
|
||||
p.frame = FRAME;
|
||||
p.slot = subframe * 2 + slot;
|
||||
p.symbol = SYMBOL & 0x3f;
|
||||
p.antenna = 0;
|
||||
memcpy(p.iq, IQ_ptr, 5088);
|
||||
store_ul(bs, &p);
|
||||
//if (p.symbol==0) printf("store ul f.sl.sy %d.%d.%d\n", p.frame, p.slot, p.symbol);
|
||||
}
|
||||
|
||||
// U-PLANE UL ANT_0 PROCESSING
|
||||
if(PAYLOAD_1 == 0x13 && PAYLOAD_2 == 0xe4 && ANT_NUM == 0x00 && dl_start == 1)
|
||||
{
|
||||
int frame = FRAME;
|
||||
int subframe = SUBFRAME >> 4;
|
||||
int slot = ((SUBFRAME & 0x0f) << 2) | ((SYMBOL >> 6) & 0x03);
|
||||
int symbol = SYMBOL & 0x3f;
|
||||
int oai_slot;
|
||||
|
||||
int tx_frame = frame;
|
||||
int tx_subframe = subframe;
|
||||
int tx_slot = slot;
|
||||
int tx_symbol = symbol + 8;
|
||||
|
||||
if (tx_symbol > 13) {
|
||||
tx_symbol -= 14;
|
||||
tx_slot++;
|
||||
if (tx_slot == 2) {
|
||||
tx_slot = 0;
|
||||
tx_subframe++;
|
||||
if (tx_subframe == 10) {
|
||||
tx_subframe = 0;
|
||||
tx_frame = (tx_frame + 1) & 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ANT_NUM = 0x00;
|
||||
|
||||
// Mask the symbol bits from UL packet received and apply the shift.
|
||||
SYMBOL = ((SYMBOL & 0b00111111) + 8) % 14;
|
||||
|
||||
ANT_NUM = 0x00;
|
||||
SUBFRAME = sf;
|
||||
|
||||
// Slot id control for DL
|
||||
if(slot_id_ctrl > 13){
|
||||
SYMBOL = SYMBOL | 0b01000000;
|
||||
}
|
||||
|
||||
/* antenna 0 - send actual DL data (if available) */
|
||||
oai_slot = tx_subframe * 2 + tx_slot;
|
||||
lock_dl_buffer(bs->buffers, oai_slot);
|
||||
if (!(bs->buffers->dl_busy[oai_slot] & (1 << tx_symbol))) {
|
||||
printf("%s: warning, DL underflow (sl.symbol %d.%d)\n", __FUNCTION__,
|
||||
oai_slot, tx_symbol);
|
||||
memset(IQ_ptr, 0, 1272 * 4);
|
||||
} else {
|
||||
memcpy(IQ_ptr, bs->buffers->dl[oai_slot] + tx_symbol * 1272*4,
|
||||
1272*4);
|
||||
}
|
||||
bs->buffers->dl_busy[oai_slot] &= ~(1 << tx_symbol);
|
||||
unlock_dl_buffer(bs->buffers, oai_slot);
|
||||
|
||||
// fill DL Data for ant 0 with 0 value
|
||||
// memset(IQ_ptr, 0, 5088);
|
||||
}
|
||||
|
||||
// U-PLANE UL ANT_1 PROCESSING
|
||||
if(PAYLOAD_1 == 0x13 && PAYLOAD_2 == 0xe4 && ANT_NUM == 0x01 && dl_start == 1)
|
||||
{
|
||||
|
||||
// Mask the symbol bits from UL packet received and apply the shift.
|
||||
SYMBOL = ((SYMBOL & 0b00111111) + 8) % 14;
|
||||
|
||||
ANT_NUM = 0x01;
|
||||
SUBFRAME = sf;
|
||||
|
||||
slot_id_ctrl++;
|
||||
|
||||
// Slot id control for DL
|
||||
if(slot_id_ctrl > 13){
|
||||
SYMBOL = SYMBOL | 0b01000000;
|
||||
|
||||
if(slot_id_ctrl > 27){
|
||||
slot_id_ctrl = 0;
|
||||
sf = sf + 0x10;
|
||||
|
||||
if (sf >0x90){
|
||||
sf = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fill DL Data for ant 1 with 0 value
|
||||
memset(IQ_ptr, 0, 5088);
|
||||
}
|
||||
|
||||
// U-PLANE PRACH PROCESSING
|
||||
else if(PAYLOAD_1 == 0x0d && PAYLOAD_2 == 0x28){
|
||||
if (ANT_NUM == 0) {
|
||||
int subframe = SUBFRAME >> 4;
|
||||
int slot = ((SUBFRAME & 0x0f) << 2) | ((SYMBOL >> 6) & 0x03);
|
||||
if (subframe==9) {
|
||||
//printf("store prach f.sf.sl %d.%d.%d %d\n", FRAME, subframe, slot, subframe * 2 + slot);
|
||||
store_prach(bs, FRAME, slot /*subframe * 2 + slot*/, IQ_ptr);
|
||||
}
|
||||
}
|
||||
rte_pktmbuf_free(m);
|
||||
return;
|
||||
}
|
||||
|
||||
// Send Packets
|
||||
buffer = tx_buffer[dst_port];
|
||||
|
||||
sent = rte_eth_tx_buffer(dst_port, 0, buffer, m);
|
||||
|
||||
if (sent)
|
||||
port_statistics[dst_port].tx += sent;
|
||||
|
||||
}
|
||||
/* main processing loop */
|
||||
static void
|
||||
l2fwd_main_loop(benetel_t *bs)
|
||||
{
|
||||
struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
|
||||
struct rte_mbuf *m;
|
||||
int sent;
|
||||
unsigned lcore_id;
|
||||
uint64_t prev_tsc, diff_tsc, cur_tsc, timer_tsc;
|
||||
unsigned i, j, portid, nb_rx;
|
||||
struct lcore_queue_conf *qconf;
|
||||
const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S *
|
||||
BURST_TX_DRAIN_US;
|
||||
struct rte_eth_dev_tx_buffer *buffer;
|
||||
prev_tsc = 0;
|
||||
timer_tsc = 0;
|
||||
lcore_id = rte_lcore_id();
|
||||
qconf = &lcore_queue_conf[lcore_id];
|
||||
if (qconf->n_rx_port == 0) {
|
||||
RTE_LOG(INFO, L2FWD, "lcore %u has nothing to do\n", lcore_id);
|
||||
return;
|
||||
}
|
||||
RTE_LOG(INFO, L2FWD, "entering main loop on lcore %u\n", lcore_id);
|
||||
for (i = 0; i < qconf->n_rx_port; i++) {
|
||||
portid = qconf->rx_port_list[i];
|
||||
RTE_LOG(INFO, L2FWD, " -- lcoreid=%u portid=%u\n", lcore_id,
|
||||
portid);
|
||||
}
|
||||
while (!force_quit) {
|
||||
cur_tsc = rte_rdtsc();
|
||||
/*
|
||||
* TX burst queue drain
|
||||
*/
|
||||
diff_tsc = cur_tsc - prev_tsc;
|
||||
if (unlikely(diff_tsc > drain_tsc)) {
|
||||
for (i = 0; i < qconf->n_rx_port; i++) {
|
||||
portid = l2fwd_dst_ports[qconf->rx_port_list[i]];
|
||||
buffer = tx_buffer[portid];
|
||||
sent = rte_eth_tx_buffer_flush(portid, 0, buffer);
|
||||
if (sent)
|
||||
port_statistics[portid].tx += sent;
|
||||
}
|
||||
/* if timer is enabled */
|
||||
if (timer_period > 0) {
|
||||
/* advance the timer */
|
||||
timer_tsc += diff_tsc;
|
||||
/* if timer has reached its timeout */
|
||||
if (unlikely(timer_tsc >= timer_period)) {
|
||||
/* do this only on master core */
|
||||
if (lcore_id == rte_get_master_lcore()) {
|
||||
print_stats();
|
||||
/* reset the timer */
|
||||
timer_tsc = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
prev_tsc = cur_tsc;
|
||||
}
|
||||
/*
|
||||
* Read packet from RX queues
|
||||
*/
|
||||
for (i = 0; i < qconf->n_rx_port; i++) {
|
||||
portid = qconf->rx_port_list[i];
|
||||
nb_rx = rte_eth_rx_burst(portid, 0,
|
||||
pkts_burst, MAX_PKT_BURST);
|
||||
port_statistics[portid].rx += nb_rx;
|
||||
for (j = 0; j < nb_rx; j++) {
|
||||
m = pkts_burst[j];
|
||||
rte_prefetch0(rte_pktmbuf_mtod(m, void *));
|
||||
l2fwd_simple_forward(m, portid, bs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
static int
|
||||
l2fwd_launch_one_lcore(void *bs)
|
||||
{
|
||||
l2fwd_main_loop(bs);
|
||||
return 0;
|
||||
}
|
||||
/* display usage */
|
||||
static void
|
||||
l2fwd_usage(const char *prgname)
|
||||
{
|
||||
printf("%s [EAL options] -- -p PORTMASK [-q NQ]\n"
|
||||
" -p PORTMASK: hexadecimal bitmask of ports to configure\n"
|
||||
" -q NQ: number of queue (=ports) per lcore (default is 1)\n"
|
||||
" -T PERIOD: statistics will be refreshed each PERIOD seconds (0 to disable, 10 default, 86400 maximum)\n"
|
||||
" --[no-]mac-updating: Enable or disable MAC addresses updating (enabled by default)\n"
|
||||
" When enabled:\n"
|
||||
" - The source MAC address is replaced by the TX port MAC address\n"
|
||||
" - The destination MAC address is replaced by 02:00:00:00:00:TX_PORT_ID\n",
|
||||
prgname);
|
||||
}
|
||||
static int
|
||||
l2fwd_parse_portmask(const char *portmask)
|
||||
{
|
||||
char *end = NULL;
|
||||
unsigned long pm;
|
||||
/* parse hexadecimal string */
|
||||
pm = strtoul(portmask, &end, 16);
|
||||
if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0'))
|
||||
return -1;
|
||||
if (pm == 0)
|
||||
return -1;
|
||||
return pm;
|
||||
}
|
||||
static unsigned int
|
||||
l2fwd_parse_nqueue(const char *q_arg)
|
||||
{
|
||||
char *end = NULL;
|
||||
unsigned long n;
|
||||
/* parse hexadecimal string */
|
||||
n = strtoul(q_arg, &end, 10);
|
||||
if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0'))
|
||||
return 0;
|
||||
if (n == 0)
|
||||
return 0;
|
||||
if (n >= MAX_RX_QUEUE_PER_LCORE)
|
||||
return 0;
|
||||
return n;
|
||||
}
|
||||
static int
|
||||
l2fwd_parse_timer_period(const char *q_arg)
|
||||
{
|
||||
char *end = NULL;
|
||||
int n;
|
||||
/* parse number string */
|
||||
n = strtol(q_arg, &end, 10);
|
||||
if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0'))
|
||||
return -1;
|
||||
if (n >= MAX_TIMER_PERIOD)
|
||||
return -1;
|
||||
return n;
|
||||
}
|
||||
static const char short_options[] =
|
||||
"p:" /* portmask */
|
||||
"q:" /* number of queues */
|
||||
"T:" /* timer period */
|
||||
;
|
||||
#define CMD_LINE_OPT_MAC_UPDATING "mac-updating"
|
||||
#define CMD_LINE_OPT_NO_MAC_UPDATING "no-mac-updating"
|
||||
enum {
|
||||
/* long options mapped to a short option */
|
||||
/* first long only option value must be >= 256, so that we won't
|
||||
* conflict with short options */
|
||||
CMD_LINE_OPT_MIN_NUM = 256,
|
||||
};
|
||||
static const struct option lgopts[] = {
|
||||
{ CMD_LINE_OPT_MAC_UPDATING, no_argument, &mac_updating, 1},
|
||||
{ CMD_LINE_OPT_NO_MAC_UPDATING, no_argument, &mac_updating, 0},
|
||||
{NULL, 0, 0, 0}
|
||||
};
|
||||
/* Parse the argument given in the command line of the application */
|
||||
static int
|
||||
l2fwd_parse_args(int argc, char **argv)
|
||||
{
|
||||
int opt, ret, timer_secs;
|
||||
char **argvopt;
|
||||
int option_index;
|
||||
char *prgname = argv[0];
|
||||
argvopt = argv;
|
||||
while ((opt = getopt_long(argc, argvopt, short_options,
|
||||
lgopts, &option_index)) != EOF) {
|
||||
switch (opt) {
|
||||
/* portmask */
|
||||
case 'p':
|
||||
l2fwd_enabled_port_mask = l2fwd_parse_portmask(optarg);
|
||||
if (l2fwd_enabled_port_mask == 0) {
|
||||
printf("invalid portmask\n");
|
||||
l2fwd_usage(prgname);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
/* nqueue */
|
||||
case 'q':
|
||||
l2fwd_rx_queue_per_lcore = l2fwd_parse_nqueue(optarg);
|
||||
if (l2fwd_rx_queue_per_lcore == 0) {
|
||||
printf("invalid queue number\n");
|
||||
l2fwd_usage(prgname);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
/* timer period */
|
||||
case 'T':
|
||||
timer_secs = l2fwd_parse_timer_period(optarg);
|
||||
if (timer_secs < 0) {
|
||||
printf("invalid timer period\n");
|
||||
l2fwd_usage(prgname);
|
||||
return -1;
|
||||
}
|
||||
timer_period = timer_secs;
|
||||
break;
|
||||
/* long options */
|
||||
case 0:
|
||||
break;
|
||||
case 'proc-type':
|
||||
break;
|
||||
case 'socket-mem':
|
||||
break;
|
||||
case 'file-prefix':
|
||||
l2fwd_rx_queue_per_lcore = l2fwd_parse_nqueue(optarg);
|
||||
if (l2fwd_rx_queue_per_lcore == 0) {
|
||||
printf("invalid queue number\n");
|
||||
l2fwd_usage(prgname);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
/* timer period */
|
||||
/* timer period */
|
||||
/* timer period */
|
||||
default:
|
||||
l2fwd_usage(prgname);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (optind >= 0)
|
||||
argv[optind-1] = prgname;
|
||||
ret = optind-1;
|
||||
optind = 1; /* reset getopt lib */
|
||||
return ret;
|
||||
}
|
||||
/* Check the link status of all ports in up to 9s, and print them finally */
|
||||
static void
|
||||
check_all_ports_link_status(uint32_t port_mask)
|
||||
{
|
||||
#define CHECK_INTERVAL 100 /* 100ms */
|
||||
#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */
|
||||
uint16_t portid;
|
||||
uint8_t count, all_ports_up, print_flag = 0;
|
||||
struct rte_eth_link link;
|
||||
printf("\nChecking link status");
|
||||
fflush(stdout);
|
||||
for (count = 0; count <= MAX_CHECK_TIME; count++) {
|
||||
if (force_quit)
|
||||
return;
|
||||
all_ports_up = 1;
|
||||
RTE_ETH_FOREACH_DEV(portid) {
|
||||
if (force_quit)
|
||||
return;
|
||||
if ((port_mask & (1 << portid)) == 0)
|
||||
continue;
|
||||
memset(&link, 0, sizeof(link));
|
||||
rte_eth_link_get_nowait(portid, &link);
|
||||
/* print link status if flag set */
|
||||
if (print_flag == 1) {
|
||||
if (link.link_status)
|
||||
printf(
|
||||
"Port%d Link Up. Speed %u Mbps - %s\n",
|
||||
portid, link.link_speed,
|
||||
(link.link_duplex == ETH_LINK_FULL_DUPLEX) ?
|
||||
("full-duplex") : ("half-duplex\n"));
|
||||
else
|
||||
printf("Port %d Link Down\n", portid);
|
||||
continue;
|
||||
}
|
||||
/* clear all_ports_up flag if any link down */
|
||||
if (link.link_status == ETH_LINK_DOWN) {
|
||||
all_ports_up = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* after finally printing all link status, get out */
|
||||
if (print_flag == 1)
|
||||
break;
|
||||
if (all_ports_up == 0) {
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
rte_delay_ms(CHECK_INTERVAL);
|
||||
}
|
||||
/* set the print_flag if all ports up or timeout */
|
||||
if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) {
|
||||
print_flag = 1;
|
||||
printf("done\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
static void
|
||||
signal_handler(int signum)
|
||||
{
|
||||
if (signum == SIGINT || signum == SIGTERM) {
|
||||
printf("\n\nSignal %d received, preparing to exit...\n",
|
||||
signum);
|
||||
force_quit = true;
|
||||
}
|
||||
}
|
||||
int
|
||||
dpdk_main(int argc, char **argv, benetel_t *bs)
|
||||
{
|
||||
struct lcore_queue_conf *qconf;
|
||||
int ret;
|
||||
uint16_t nb_ports;
|
||||
uint16_t nb_ports_available = 0;
|
||||
uint16_t portid, last_port;
|
||||
unsigned lcore_id, rx_lcore_id;
|
||||
unsigned nb_ports_in_mask = 0;
|
||||
unsigned int nb_lcores = 0;
|
||||
unsigned int nb_mbufs;
|
||||
/* init EAL */
|
||||
ret = rte_eal_init(argc, argv);
|
||||
if (ret < 0)
|
||||
rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n");
|
||||
argc -= ret;
|
||||
argv += ret;
|
||||
force_quit = false;
|
||||
signal(SIGINT, signal_handler);
|
||||
signal(SIGTERM, signal_handler);
|
||||
/* parse application arguments (after the EAL ones) */
|
||||
ret = l2fwd_parse_args(argc, argv);
|
||||
if (ret < 0)
|
||||
rte_exit(EXIT_FAILURE, "Invalid L2FWD arguments\n");
|
||||
printf("MAC updating %s\n", mac_updating ? "enabled" : "disabled");
|
||||
/* convert to number of cycles */
|
||||
timer_period *= rte_get_timer_hz();
|
||||
nb_ports = rte_eth_dev_count_avail();
|
||||
if (nb_ports == 0)
|
||||
rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
|
||||
/* check port mask to possible port mask */
|
||||
if (l2fwd_enabled_port_mask & ~((1 << nb_ports) - 1))
|
||||
rte_exit(EXIT_FAILURE, "Invalid portmask; possible (0x%x)\n",
|
||||
(1 << nb_ports) - 1);
|
||||
/* reset l2fwd_dst_ports */
|
||||
for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++)
|
||||
l2fwd_dst_ports[portid] = 0;
|
||||
last_port = 0;
|
||||
/*
|
||||
* Each logical core is assigned a dedicated TX queue on each port.
|
||||
*/
|
||||
RTE_ETH_FOREACH_DEV(portid) {
|
||||
/* skip ports that are not enabled */
|
||||
if ((l2fwd_enabled_port_mask & (1 << portid)) == 0)
|
||||
continue;
|
||||
if (nb_ports_in_mask % 2) {
|
||||
l2fwd_dst_ports[portid] = last_port;
|
||||
l2fwd_dst_ports[last_port] = portid;
|
||||
}
|
||||
else
|
||||
last_port = portid;
|
||||
nb_ports_in_mask++;
|
||||
}
|
||||
if (nb_ports_in_mask % 2) {
|
||||
printf("Notice: odd number of ports in portmask.\n");
|
||||
l2fwd_dst_ports[last_port] = last_port;
|
||||
}
|
||||
rx_lcore_id = 0;
|
||||
qconf = NULL;
|
||||
/* Initialize the port/queue configuration of each logical core */
|
||||
RTE_ETH_FOREACH_DEV(portid) {
|
||||
/* skip ports that are not enabled */
|
||||
if ((l2fwd_enabled_port_mask & (1 << portid)) == 0)
|
||||
continue;
|
||||
/* get the lcore_id for this port */
|
||||
while (rte_lcore_is_enabled(rx_lcore_id) == 0 ||
|
||||
lcore_queue_conf[rx_lcore_id].n_rx_port ==
|
||||
l2fwd_rx_queue_per_lcore) {
|
||||
rx_lcore_id++;
|
||||
if (rx_lcore_id >= RTE_MAX_LCORE)
|
||||
rte_exit(EXIT_FAILURE, "Not enough cores\n");
|
||||
}
|
||||
if (qconf != &lcore_queue_conf[rx_lcore_id]) {
|
||||
/* Assigned a new logical core in the loop above. */
|
||||
qconf = &lcore_queue_conf[rx_lcore_id];
|
||||
nb_lcores++;
|
||||
}
|
||||
qconf->rx_port_list[qconf->n_rx_port] = portid;
|
||||
qconf->n_rx_port++;
|
||||
printf("Lcore %u: RX port %u\n", rx_lcore_id, portid);
|
||||
}
|
||||
nb_mbufs = RTE_MAX(nb_ports * (nb_rxd + nb_txd + MAX_PKT_BURST +
|
||||
nb_lcores * MEMPOOL_CACHE_SIZE), 8192U);
|
||||
/* create the mbuf pool */
|
||||
//DD Debug
|
||||
//printf ("Proc Type %d \n", rte_eal_process_type());
|
||||
l2fwd_pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", nb_mbufs,
|
||||
MEMPOOL_CACHE_SIZE, 0, 9680,
|
||||
rte_socket_id());
|
||||
if (l2fwd_pktmbuf_pool == NULL)
|
||||
rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n");
|
||||
/* Initialise each port */
|
||||
RTE_ETH_FOREACH_DEV(portid) {
|
||||
struct rte_eth_rxconf rxq_conf;
|
||||
struct rte_eth_txconf txq_conf;
|
||||
struct rte_eth_conf local_port_conf = port_conf;
|
||||
struct rte_eth_dev_info dev_info;
|
||||
/* skip ports that are not enabled */
|
||||
if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) {
|
||||
printf("Skipping disabled port %u\n", portid);
|
||||
continue;
|
||||
}
|
||||
nb_ports_available++;
|
||||
/* init port */
|
||||
printf("Initializing port %u... ", portid);
|
||||
fflush(stdout);
|
||||
rte_eth_dev_info_get(portid, &dev_info);
|
||||
if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE)
|
||||
local_port_conf.txmode.offloads |=
|
||||
DEV_TX_OFFLOAD_MBUF_FAST_FREE;
|
||||
ret = rte_eth_dev_configure(portid, 1, 1, &local_port_conf);
|
||||
if (ret < 0)
|
||||
rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%u\n",
|
||||
ret, portid);
|
||||
ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd,
|
||||
&nb_txd);
|
||||
if (ret < 0)
|
||||
rte_exit(EXIT_FAILURE,
|
||||
"Cannot adjust number of descriptors: err=%d, port=%u\n",
|
||||
ret, portid);
|
||||
rte_eth_macaddr_get(portid,&l2fwd_ports_eth_addr[portid]);
|
||||
/* init one RX queue */
|
||||
fflush(stdout);
|
||||
rxq_conf = dev_info.default_rxconf;
|
||||
rxq_conf.offloads = local_port_conf.rxmode.offloads;
|
||||
ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd,
|
||||
rte_eth_dev_socket_id(portid),
|
||||
&rxq_conf,
|
||||
l2fwd_pktmbuf_pool);
|
||||
if (ret < 0)
|
||||
rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup:err=%d, port=%u\n",
|
||||
ret, portid);
|
||||
/* init one TX queue on each port */
|
||||
fflush(stdout);
|
||||
txq_conf = dev_info.default_txconf;
|
||||
txq_conf.offloads = local_port_conf.txmode.offloads;
|
||||
ret = rte_eth_tx_queue_setup(portid, 0, nb_txd,
|
||||
rte_eth_dev_socket_id(portid),
|
||||
&txq_conf);
|
||||
if (ret < 0)
|
||||
rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup:err=%d, port=%u\n",
|
||||
ret, portid);
|
||||
/* Initialize TX buffers */
|
||||
tx_buffer[portid] = rte_zmalloc_socket("tx_buffer",
|
||||
RTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST), 0,
|
||||
rte_eth_dev_socket_id(portid));
|
||||
if (tx_buffer[portid] == NULL)
|
||||
rte_exit(EXIT_FAILURE, "Cannot allocate buffer for tx on port %u\n",
|
||||
portid);
|
||||
rte_eth_tx_buffer_init(tx_buffer[portid], MAX_PKT_BURST);
|
||||
ret = rte_eth_tx_buffer_set_err_callback(tx_buffer[portid],
|
||||
rte_eth_tx_buffer_count_callback,
|
||||
&port_statistics[portid].dropped);
|
||||
if (ret < 0)
|
||||
rte_exit(EXIT_FAILURE,
|
||||
"Cannot set error callback for tx buffer on port %u\n",
|
||||
portid);
|
||||
/* Start device */
|
||||
ret = rte_eth_dev_start(portid);
|
||||
if (ret < 0)
|
||||
rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err=%d, port=%u\n",
|
||||
ret, portid);
|
||||
printf("done: \n");
|
||||
rte_eth_promiscuous_enable(portid);
|
||||
printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n",
|
||||
portid,
|
||||
l2fwd_ports_eth_addr[portid].addr_bytes[0],
|
||||
l2fwd_ports_eth_addr[portid].addr_bytes[1],
|
||||
l2fwd_ports_eth_addr[portid].addr_bytes[2],
|
||||
l2fwd_ports_eth_addr[portid].addr_bytes[3],
|
||||
l2fwd_ports_eth_addr[portid].addr_bytes[4],
|
||||
l2fwd_ports_eth_addr[portid].addr_bytes[5]);
|
||||
/* initialize port stats */
|
||||
memset(&port_statistics, 0, sizeof(port_statistics));
|
||||
}
|
||||
if (!nb_ports_available) {
|
||||
rte_exit(EXIT_FAILURE,
|
||||
"All available ports are disabled. Please set portmask.\n");
|
||||
}
|
||||
check_all_ports_link_status(l2fwd_enabled_port_mask);
|
||||
ret = 0;
|
||||
/* launch per-lcore init on every lcore */
|
||||
rte_eal_mp_remote_launch(l2fwd_launch_one_lcore, bs, CALL_MASTER);
|
||||
RTE_LCORE_FOREACH_SLAVE(lcore_id) {
|
||||
if (rte_eal_wait_lcore(lcore_id) < 0) {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
RTE_ETH_FOREACH_DEV(portid) {
|
||||
if ((l2fwd_enabled_port_mask & (1 << portid)) == 0)
|
||||
continue;
|
||||
printf("Closing port %d...", portid);
|
||||
rte_eth_dev_stop(portid);
|
||||
rte_eth_dev_close(portid);
|
||||
printf(" Done\n");
|
||||
}
|
||||
printf("Bye...\n");
|
||||
return ret;
|
||||
}
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
#include "low.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void store_ul(benetel_t *bs, ul_packet_t *ul)
|
||||
{
|
||||
/* only antenna 0 for the moment */
|
||||
if (ul->antenna != 0)
|
||||
return;
|
||||
|
||||
if (ul->slot != bs->next_slot ||
|
||||
ul->symbol != bs->next_symbol) {
|
||||
printf("%s: fatal, expected frame.sl.symbol %d.%d.%d, got %d.%d.%d\n",
|
||||
__FUNCTION__,
|
||||
bs->expected_benetel_frame, bs->next_slot, bs->next_symbol,
|
||||
ul->frame, ul->slot, ul->symbol);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
lock_ul_buffer(bs->buffers, bs->next_slot);
|
||||
if (bs->buffers->ul_busy[bs->next_slot] & (1 << bs->next_symbol)) {
|
||||
printf("%s: warning, UL overflow (sl.symbol %d.%d)\n", __FUNCTION__,
|
||||
bs->next_slot, bs->next_symbol);
|
||||
}
|
||||
|
||||
memcpy(bs->buffers->ul[bs->next_slot] + bs->next_symbol * 1272*4,
|
||||
ul->iq, 1272*4);
|
||||
bs->buffers->ul_busy[bs->next_slot] |= (1 << bs->next_symbol);
|
||||
signal_ul_buffer(bs->buffers, bs->next_slot);
|
||||
unlock_ul_buffer(bs->buffers, bs->next_slot);
|
||||
|
||||
bs->next_symbol++;
|
||||
if (bs->next_symbol == 14) {
|
||||
bs->next_symbol = 0;
|
||||
bs->next_slot = (bs->next_slot + 1) % 20;
|
||||
if (bs->next_slot == 0) {
|
||||
bs->expected_benetel_frame++;
|
||||
bs->expected_benetel_frame &= 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void store_prach(benetel_t *bs, int frame, int slot, void *data)
|
||||
{
|
||||
static int last_frame = -1;
|
||||
static int last_slot = -1;
|
||||
/* hack: antenna number is always 0, discard second packet with same f/sf */
|
||||
//if (frame == last_frame && slot == last_slot) return;
|
||||
if (frame == last_frame && slot == last_slot) { printf("got f.sl %d.%d twice\n", frame, slot); return; }
|
||||
last_frame = frame;
|
||||
last_slot = slot;
|
||||
|
||||
lock_ul_buffer(bs->buffers, slot);
|
||||
if (bs->buffers->prach_busy[slot]) {
|
||||
printf("store_prach: fatal: previous prach buffer not processed\n");
|
||||
unlock_ul_buffer(bs->buffers, slot);
|
||||
return;
|
||||
}
|
||||
bs->buffers->prach_busy[slot] = 1;
|
||||
memcpy(bs->buffers->prach[slot], data, 839*4);
|
||||
signal_ul_buffer(bs->buffers, slot);
|
||||
unlock_ul_buffer(bs->buffers, slot);
|
||||
|
||||
}
|
||||
|
||||
void *benetel_start_dpdk(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line);
|
||||
|
||||
void *benetel_start(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line)
|
||||
{
|
||||
if (!strcmp(ifname, "dpdk"))
|
||||
return benetel_start_dpdk(ifname, buffers, dpdk_main_command_line);
|
||||
printf("benetel: fatal: interface %s not supported, only dpdpk is supported\n", ifname);
|
||||
exit(1);
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 _BENETEL_LOW_H_
|
||||
#define _BENETEL_LOW_H_
|
||||
|
||||
#include "shared_buffers.h"
|
||||
|
||||
typedef struct {
|
||||
shared_buffers *buffers;
|
||||
int next_slot;
|
||||
int next_symbol;
|
||||
int expected_benetel_frame;
|
||||
char *dpdk_main_command_line;
|
||||
} benetel_t;
|
||||
|
||||
typedef struct {
|
||||
int frame;
|
||||
int slot;
|
||||
int symbol;
|
||||
int antenna;
|
||||
unsigned char iq[5088];
|
||||
} ul_packet_t;
|
||||
|
||||
void *benetel_start(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line);
|
||||
|
||||
void store_ul(benetel_t *bs, ul_packet_t *ul);
|
||||
void store_prach(benetel_t *bs, int frame, int slot, void *data);
|
||||
|
||||
#endif /* _BENETEL_LOW_H_ */
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/* those 2 lines for CPU_SET */
|
||||
#define _GNU_SOURCE
|
||||
#include <sched.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "low.h"
|
||||
|
||||
int dpdk_main(int argc, char **argv, benetel_t *);
|
||||
|
||||
void *dpdk_thread(void *_bs)
|
||||
{
|
||||
benetel_t *bs = _bs;
|
||||
int n = 0;
|
||||
char **v = NULL; // = { "softmodem", "-n", "2", "--file-prefix", "pg2", "-l", "6", "--", "-p", "0x1" };
|
||||
char *s = bs->dpdk_main_command_line;
|
||||
char *tok;
|
||||
|
||||
while ((tok = strtok(s, " ")) != NULL) {
|
||||
n++;
|
||||
v = realloc(v, n * sizeof(char *));
|
||||
if (v == NULL) {
|
||||
printf("%s: out of memory\n", __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
v[n-1] = tok;
|
||||
s = NULL;
|
||||
}
|
||||
|
||||
dpdk_main(n, v, bs);
|
||||
exit(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *benetel_start_dpdk(char *ifname, shared_buffers *buffers, char *dpdk_main_command_line)
|
||||
{
|
||||
benetel_t *bs;
|
||||
|
||||
bs = calloc(1, sizeof(benetel_t));
|
||||
if (bs == NULL) {
|
||||
printf("%s: out of memory\n", __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
bs->buffers = buffers;
|
||||
|
||||
bs->expected_benetel_frame = 255;
|
||||
|
||||
bs->dpdk_main_command_line = dpdk_main_command_line;
|
||||
|
||||
pthread_attr_t attr;
|
||||
|
||||
if (pthread_attr_init(&attr) != 0) {
|
||||
printf("pthread_attr_init failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
cpu_set_t cpuset;
|
||||
CPU_ZERO(&cpuset);
|
||||
CPU_SET(10,&cpuset);
|
||||
if (pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset) != 0) {
|
||||
printf("pthread_attr_setaffinity_np failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO) != 0) {
|
||||
printf("pthread_attr_setschedpolicy failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct sched_param params;
|
||||
params.sched_priority = sched_get_priority_max(SCHED_FIFO);
|
||||
if (sched_get_priority_max(SCHED_FIFO) == -1) {
|
||||
printf("sched_get_priority_max failed\n");
|
||||
exit(1);
|
||||
}
|
||||
if (pthread_attr_setschedparam(&attr, ¶ms) != 0) {
|
||||
printf("pthread_setschedparam failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pthread_t t;
|
||||
if (pthread_create(&t, &attr, dpdk_thread, bs) != 0) {
|
||||
printf("%s: thread creation failed\n", __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pthread_attr_destroy(&attr) != 0) {
|
||||
printf("pthread_attr_init failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return bs;
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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 "shared_buffers.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void init_buffers(shared_buffers *s)
|
||||
{
|
||||
int slot;
|
||||
|
||||
memset(s, 0, sizeof(*s));
|
||||
|
||||
for (slot = 0; slot < 20; slot++) {
|
||||
if (pthread_mutex_init(&s->m_dl[slot], NULL) != 0 ||
|
||||
pthread_cond_init(&s->c_dl[slot], NULL) != 0 ||
|
||||
pthread_mutex_init(&s->m_ul[slot], NULL) != 0 ||
|
||||
pthread_cond_init(&s->c_ul[slot], NULL) != 0) {
|
||||
printf("%s: error initializing mutex/cond\n", __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* the gNB's first transmitted DL slot is 6 but the device
|
||||
* needs to have slots 1, 2 and 3, 4 and 5 ready. Let's pretend
|
||||
* they are ready.
|
||||
*/
|
||||
s->dl_busy[1] = 0x3fff;
|
||||
s->dl_busy[2] = 0x3fff;
|
||||
s->dl_busy[3] = 0x3fff;
|
||||
s->dl_busy[4] = 0x3fff;
|
||||
s->dl_busy[5] = 0x3fff;
|
||||
}
|
||||
|
||||
void lock_dl_buffer(shared_buffers *s, int slot)
|
||||
{
|
||||
if (pthread_mutex_lock(&s->m_dl[slot]) != 0) {
|
||||
printf("%s: fatal: lock fails\n", __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void unlock_dl_buffer(shared_buffers *s, int slot)
|
||||
{
|
||||
if (pthread_mutex_unlock(&s->m_dl[slot]) != 0) {
|
||||
printf("%s: fatal: unlock fails\n", __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void wait_dl_buffer(shared_buffers *s, int slot)
|
||||
{
|
||||
if (pthread_cond_wait(&s->c_dl[slot], &s->m_dl[slot]) != 0) {
|
||||
printf("%s: fatal: cond_wait fails\n", __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void signal_dl_buffer(shared_buffers *s, int slot)
|
||||
{
|
||||
if (pthread_cond_broadcast(&s->c_dl[slot]) != 0) {
|
||||
printf("%s: fatal: cond_broadcast fails\n", __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void lock_ul_buffer(shared_buffers *s, int slot)
|
||||
{
|
||||
if (pthread_mutex_lock(&s->m_ul[slot]) != 0) {
|
||||
printf("%s: fatal: lock fails\n", __FUNCTION__);
|
||||
printf("%s: fatal: lock fails slot %d\n", __FUNCTION__, slot);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void unlock_ul_buffer(shared_buffers *s, int slot)
|
||||
{
|
||||
if (pthread_mutex_unlock(&s->m_ul[slot]) != 0) {
|
||||
printf("%s: fatal: unlock fails\n", __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void wait_ul_buffer(shared_buffers *s, int slot)
|
||||
{
|
||||
if (pthread_cond_wait(&s->c_ul[slot], &s->m_ul[slot]) != 0) {
|
||||
printf("%s: fatal: cond_wait fails\n", __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void signal_ul_buffer(shared_buffers *s, int slot)
|
||||
{
|
||||
if (pthread_cond_broadcast(&s->c_ul[slot]) != 0) {
|
||||
printf("%s: fatal: cond_broadcast fails\n", __FUNCTION__);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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 _SHARED_BUFFERS_H_
|
||||
#define _SHARED_BUFFERS_H_
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
unsigned char dl[20][14*1272*4];
|
||||
unsigned char ul[20][14*1272*4];
|
||||
uint16_t dl_busy[20];
|
||||
uint16_t ul_busy[20];
|
||||
|
||||
pthread_mutex_t m_ul[20];
|
||||
pthread_cond_t c_ul[20];
|
||||
|
||||
pthread_mutex_t m_dl[20];
|
||||
pthread_cond_t c_dl[20];
|
||||
|
||||
unsigned char prach[20][849*4];
|
||||
unsigned char prach_busy[20];
|
||||
|
||||
/* statistics/error counting */
|
||||
int ul_overflow;
|
||||
int dl_underflow;
|
||||
} shared_buffers;
|
||||
|
||||
void init_buffers(shared_buffers *s);
|
||||
|
||||
void lock_dl_buffer(shared_buffers *s, int slot);
|
||||
void unlock_dl_buffer(shared_buffers *s, int slot);
|
||||
void wait_dl_buffer(shared_buffers *s, int slot);
|
||||
void signal_dl_buffer(shared_buffers *s, int slot);
|
||||
|
||||
void lock_ul_buffer(shared_buffers *s, int slot);
|
||||
void unlock_ul_buffer(shared_buffers *s, int slot);
|
||||
void wait_ul_buffer(shared_buffers *s, int slot);
|
||||
void signal_ul_buffer(shared_buffers *s, int slot);
|
||||
|
||||
#endif /* _SHARED_BUFFERS_H_ */
|
||||
@@ -0,0 +1,281 @@
|
||||
Active_eNBs = ( "eNB-Eurecom-LTEBox");
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity = "none";
|
||||
|
||||
eNBs =
|
||||
(
|
||||
{
|
||||
# real_time choice in {hard, rt-preempt, no}
|
||||
real_time = "no";
|
||||
|
||||
////////// 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 = 222; mnc = 01; mnc_length = 2; } );
|
||||
|
||||
tr_s_preference = "local_mac"
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
component_carriers = (
|
||||
{
|
||||
node_function = "NGFI_RCC_IF4p5";
|
||||
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 = 2655000000L;
|
||||
uplink_frequency_offset = -120000000;
|
||||
Nid_cell = 0;
|
||||
N_RB_DL = 100;
|
||||
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 = 90;
|
||||
pucch_delta_shift = 1;
|
||||
pucch_nRB_CQI = 0;
|
||||
pucch_nCS_AN = 0;
|
||||
pucch_n1_AN = 0;
|
||||
pdsch_referenceSignalPower = -10;
|
||||
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";
|
||||
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 = "192.168.61.195";
|
||||
ipv6 = "192:168:30::17";
|
||||
active = "yes";
|
||||
preference = "ipv4";
|
||||
}
|
||||
);
|
||||
|
||||
enable_measurement_reports = "no";
|
||||
|
||||
///X2
|
||||
enable_x2 = "yes";
|
||||
t_reloc_prep = 1000; /* unit: millisecond */
|
||||
tx2_reloc_overall = 2000; /* unit: millisecond */
|
||||
|
||||
NETWORK_INTERFACES :
|
||||
{
|
||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
||||
ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.160.46";
|
||||
ENB_INTERFACE_NAME_FOR_S1U = "eth0";
|
||||
ENB_IPV4_ADDRESS_FOR_S1U = "192.168.160.46";
|
||||
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";
|
||||
phy_test_mode = 0;
|
||||
puSch10xSnr = 160;
|
||||
puCch10xSnr = 160;
|
||||
}
|
||||
);
|
||||
|
||||
L1s = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_n_preference = "local_mac";
|
||||
prach_dtx_threshold = 150;
|
||||
}
|
||||
);
|
||||
|
||||
RUs = (
|
||||
{
|
||||
//local_if_name = "enp129s0f0";
|
||||
local_if_name = "dpdk";
|
||||
sdr_addrs = "softmodem -m 2048 -l 8 -n 2 -b 0000:3b:00.0 --proc-type auto --file-prefix ggg -- -p 0x1";
|
||||
#sdr_addrs = "softmodem -l 8 -n 2 -- -p 0x2";
|
||||
remote_address = "127.0.0.2";
|
||||
local_address = "127.0.0.1";
|
||||
local_portc = 50000;
|
||||
remote_portc = 50000;
|
||||
local_portd = 50001;
|
||||
remote_portd = 50001;
|
||||
local_rf = "no"
|
||||
tr_preference = "raw_if4p5"
|
||||
nb_tx = 1
|
||||
nb_rx = 1
|
||||
att_tx = 0
|
||||
att_rx = 0;
|
||||
eNB_instances = [0];
|
||||
}
|
||||
);
|
||||
|
||||
THREAD_STRUCT = (
|
||||
{
|
||||
#three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
|
||||
#parallel_config = "PARALLEL_RU_L1_TRX_SPLIT";
|
||||
parallel_config = "PARALLEL_SINGLE_THREAD";
|
||||
#two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
|
||||
worker_config = "WORKER_ENABLE";
|
||||
}
|
||||
);
|
||||
|
||||
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";
|
||||
};
|
||||
|
||||
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";
|
||||
};
|
||||
@@ -0,0 +1,307 @@
|
||||
Active_gNBs = ( "gNB-Eurecom-5GNRBox");
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity = "none";
|
||||
|
||||
gNBs =
|
||||
(
|
||||
{
|
||||
////////// Identification parameters:
|
||||
gNB_ID = 0xe00;
|
||||
|
||||
cell_type = "CELL_MACRO_GNB";
|
||||
|
||||
gNB_name = "gNB-Eurecom-5GNRBox";
|
||||
|
||||
// Tracking area code, 0x0000 and 0xfffe are reserved values
|
||||
tracking_area_code = 1;
|
||||
|
||||
plmn_list = ({mcc = 222; mnc = 01; mnc_length = 2;});
|
||||
|
||||
tr_s_preference = "local_mac"
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
ssb_SubcarrierOffset = 31; //0;
|
||||
pdsch_AntennaPorts = 1;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
#spCellConfigCommon
|
||||
|
||||
physCellId = 0;
|
||||
|
||||
# downlinkConfigCommon
|
||||
#frequencyInfoDL
|
||||
# this is is the central frequency of SSB
|
||||
absoluteFrequencySSB = 640000; //641272
|
||||
dl_frequencyBand = 78;
|
||||
# the carrier frequency is assumed to be in the middle of the carrier, i.e. dl_absoluteFrequencyPointA_kHz + dl_carrierBandwidth*12*SCS_kHz/2
|
||||
dl_absoluteFrequencyPointA = 638728; //640000;
|
||||
#scs-SpecificCarrierList
|
||||
dl_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
dl_subcarrierSpacing = 1;
|
||||
dl_carrierBandwidth = 106;
|
||||
#initialDownlinkBWP
|
||||
#genericParameters
|
||||
# this is RBstart=84,L=13 (275*(L-1))+RBstart
|
||||
initialDLBWPlocationAndBandwidth = 6366; //28875; //6366; #6407; #3384;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialDLBWPsubcarrierSpacing = 1;
|
||||
#pdcch-ConfigCommon
|
||||
initialDLBWPcontrolResourceSetZero = 0;
|
||||
initialDLBWPsearchSpaceZero = 0;
|
||||
#pdsch-ConfigCommon
|
||||
#pdschTimeDomainAllocationList (up to 16 entries)
|
||||
initialDLBWPk0_0 = 0;
|
||||
#initialULBWPmappingType
|
||||
#0=typeA,1=typeB
|
||||
initialDLBWPmappingType_0 = 0;
|
||||
#this is SS=1,L=13
|
||||
initialDLBWPstartSymbolAndLength_0 = 40;
|
||||
|
||||
initialDLBWPk0_1 = 0;
|
||||
initialDLBWPmappingType_1 = 0;
|
||||
#this is SS=2,L=12
|
||||
initialDLBWPstartSymbolAndLength_1 = 53;
|
||||
|
||||
initialDLBWPk0_2 = 0;
|
||||
initialDLBWPmappingType_2 = 0;
|
||||
#this is SS=1,L=12
|
||||
initialDLBWPstartSymbolAndLength_2 = 54;
|
||||
|
||||
initialDLBWPk0_3 = 0;
|
||||
initialDLBWPmappingType_3 = 0;
|
||||
#this is SS=1,L=4 //5 (4 is for 43, 5 is for 57)
|
||||
initialDLBWPstartSymbolAndLength_3 = 57; //43; //57;
|
||||
#uplinkConfigCommon
|
||||
#frequencyInfoUL
|
||||
ul_frequencyBand = 78;
|
||||
#scs-SpecificCarrierList
|
||||
ul_offstToCarrier = 0;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
ul_subcarrierSpacing = 1;
|
||||
ul_carrierBandwidth = 106;
|
||||
pMax = 20;
|
||||
#initialUplinkBWP
|
||||
#genericParameters
|
||||
initialULBWPlocationAndBandwidth = 6366; //28875; //6366; #6407; #3384;
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
initialULBWPsubcarrierSpacing = 1;
|
||||
#rach-ConfigCommon
|
||||
#rach-ConfigGeneric
|
||||
prach_ConfigurationIndex = 4;
|
||||
#prach_msg1_FDM
|
||||
#0 = one, 1=two, 2=four, 3=eight
|
||||
prach_msg1_FDM = 0;
|
||||
prach_msg1_FrequencyStart = 74;
|
||||
zeroCorrelationZoneConfig = 13;
|
||||
#preambleReceivedTargetPower = -118;
|
||||
preambleReceivedTargetPower = -104;
|
||||
#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200)
|
||||
preambleTransMax = 6;
|
||||
#powerRampingStep
|
||||
# 0=dB0,1=dB2,2=dB4,3=dB6
|
||||
powerRampingStep = 2;
|
||||
#ra_ReponseWindow
|
||||
#1,2,4,8,10,20,40,80
|
||||
ra_ResponseWindow = 5;
|
||||
#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR
|
||||
#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4;
|
||||
#oneHalf (0..15) 4,8,12,16,...60,64
|
||||
ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; //15;
|
||||
#ra_ContentionResolutionTimer
|
||||
#(0..7) 8,16,24,32,40,48,56,64
|
||||
ra_ContentionResolutionTimer = 7;
|
||||
rsrp_ThresholdSSB = 19;
|
||||
#prach-RootSequenceIndex_PR
|
||||
#1 = 839, 2 = 139
|
||||
prach_RootSequenceIndex_PR = 1;
|
||||
prach_RootSequenceIndex = 1;
|
||||
# SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex
|
||||
#
|
||||
#msg1_SubcarrierSpacing = 1,
|
||||
|
||||
# restrictedSetConfig
|
||||
# 0=unrestricted, 1=restricted type A, 2=restricted type B
|
||||
restrictedSetConfig = 0,
|
||||
# pusch-ConfigCommon (up to 16 elements)
|
||||
initialULBWPk2_0 = 2;
|
||||
initialULBWPmappingType_0 = 1
|
||||
# this is SS=0 L=11
|
||||
initialULBWPstartSymbolAndLength_0 = 55;
|
||||
|
||||
initialULBWPk2_1 = 2;
|
||||
initialULBWPmappingType_1 = 1;
|
||||
# this is SS=0 L=12
|
||||
initialULBWPstartSymbolAndLength_1 = 69;
|
||||
|
||||
initialULBWPk2_2 = 7;
|
||||
initialULBWPmappingType_2 = 1;
|
||||
# this is SS=10 L=4
|
||||
initialULBWPstartSymbolAndLength_2 = 52;
|
||||
|
||||
msg3_DeltaPreamble = 1;
|
||||
p0_NominalWithGrant =-90;
|
||||
|
||||
# pucch-ConfigCommon setup :
|
||||
# pucchGroupHopping
|
||||
# 0 = neither, 1= group hopping, 2=sequence hopping
|
||||
pucchGroupHopping = 0;
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
# ssb_PositionsInBurs_BitmapPR
|
||||
# 1=short, 2=medium, 3=long
|
||||
ssb_PositionsInBurst_PR = 2;
|
||||
ssb_PositionsInBurst_Bitmap = 1; #0x80;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
|
||||
ssb_periodicityServingCell = 2;
|
||||
|
||||
# dmrs_TypeA_position
|
||||
# 0 = pos2, 1 = pos3
|
||||
dmrs_TypeA_Position = 0;
|
||||
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
subcarrierSpacing = 1;
|
||||
|
||||
|
||||
#tdd-UL-DL-ConfigurationCommon
|
||||
# subcarrierSpacing
|
||||
# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120
|
||||
referenceSubcarrierSpacing = 1;
|
||||
# pattern1
|
||||
# dl_UL_TransmissionPeriodicity
|
||||
# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10
|
||||
dl_UL_TransmissionPeriodicity = 6;
|
||||
nrofDownlinkSlots = 7; //8; //7;
|
||||
nrofDownlinkSymbols = 6; //0; //6;
|
||||
nrofUplinkSlots = 2;
|
||||
nrofUplinkSymbols = 4; //0; //4;
|
||||
|
||||
#ssPBCH_BlockPower = 10;
|
||||
ssPBCH_BlockPower = 10;
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
|
||||
# ------- SCTP definitions
|
||||
SCTP :
|
||||
{
|
||||
# Number of streams to use in input/output
|
||||
SCTP_INSTREAMS = 2;
|
||||
SCTP_OUTSTREAMS = 2;
|
||||
};
|
||||
|
||||
|
||||
////////// MME parameters:
|
||||
mme_ip_address = ( { ipv4 = "192.168.61.195";
|
||||
ipv6 = "192:168:30::17";
|
||||
active = "yes";
|
||||
preference = "ipv4";
|
||||
}
|
||||
);
|
||||
|
||||
///X2
|
||||
enable_x2 = "yes";
|
||||
t_reloc_prep = 1000; /* unit: millisecond */
|
||||
tx2_reloc_overall = 2000; /* unit: millisecond */
|
||||
target_enb_x2_ip_address = (
|
||||
{ ipv4 = "127.0.0.1";
|
||||
ipv6 = "192:168:30::17";
|
||||
preference = "ipv4";
|
||||
}
|
||||
);
|
||||
|
||||
NETWORK_INTERFACES :
|
||||
{
|
||||
|
||||
GNB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
||||
GNB_IPV4_ADDRESS_FOR_S1_MME = "192.168.160.146/24";
|
||||
GNB_INTERFACE_NAME_FOR_S1U = "eth0";
|
||||
GNB_IPV4_ADDRESS_FOR_S1U = "192.168.160.146/24";
|
||||
GNB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||
GNB_IPV4_ADDRESS_FOR_X2C = "127.0.0.2/24";
|
||||
GNB_PORT_FOR_X2C = 36422; # Spec 36422
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
MACRLCs = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_s_preference = "local_L1";
|
||||
tr_n_preference = "local_RRC";
|
||||
}
|
||||
);
|
||||
|
||||
L1s = (
|
||||
{
|
||||
num_cc = 1;
|
||||
tr_n_preference = "local_mac";
|
||||
}
|
||||
);
|
||||
|
||||
RUs = (
|
||||
{
|
||||
local_rf = "no"
|
||||
nb_tx = 1
|
||||
nb_rx = 1
|
||||
att_tx = 0
|
||||
att_rx = 0;
|
||||
bands = [7];
|
||||
max_pdschReferenceSignalPower = -27;
|
||||
max_rxgain = 114;
|
||||
eNB_instances = [0];
|
||||
//clock_src = "internal";
|
||||
clock_src = "external";
|
||||
|
||||
local_if_name = "dpdk";
|
||||
sdr_addrs = "softmodem -m 2048 -l 6 -n 3 -b 0000:3b:00.1 --proc-type auto --file-prefix hhh -- -p 0x1";
|
||||
remote_address = "127.0.0.2";
|
||||
local_address = "127.0.0.1";
|
||||
local_portc = 50000;
|
||||
remote_portc = 50000;
|
||||
local_portd = 50001;
|
||||
remote_portd = 50001;
|
||||
tr_preference = "raw_if4p5"
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
THREAD_STRUCT = (
|
||||
{
|
||||
#three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
|
||||
//parallel_config = "PARALLEL_RU_L1_TRX_SPLIT";
|
||||
parallel_config = "PARALLEL_SINGLE_THREAD";
|
||||
#two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
|
||||
worker_config = "WORKER_DISABLE";
|
||||
}
|
||||
);
|
||||
|
||||
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";
|
||||
};
|
||||
|
||||
@@ -2675,6 +2675,15 @@ void set_function_spec_param(RU_t *ru) {
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (ru->ifdevice.get_internal_parameter != NULL) {
|
||||
void *t = ru->ifdevice.get_internal_parameter("fh_if4p5_south_in");
|
||||
if (t != NULL)
|
||||
ru->fh_south_in = t;
|
||||
t = ru->ifdevice.get_internal_parameter("fh_if4p5_south_out");
|
||||
if (t != NULL)
|
||||
ru->fh_south_out = t;
|
||||
}
|
||||
|
||||
malloc_IF4p5_buffer(ru);
|
||||
break;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user