Merge branch 'develop' into NR_RRC_harq_hacks
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+35
-38
@@ -61,10 +61,7 @@
|
||||
|
||||
#include "PHY/phy_extern.h"
|
||||
|
||||
|
||||
#include "LAYER2/MAC/mac.h"
|
||||
#include "NR_MAC_COMMON/nr_mac_extern.h"
|
||||
#include "LAYER2/MAC/mac_proto.h"
|
||||
#include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h"
|
||||
#include "RRC/LTE/rrc_extern.h"
|
||||
#include "PHY_INTERFACE/phy_interface.h"
|
||||
#include "common/utils/LOG/log_extern.h"
|
||||
@@ -187,8 +184,8 @@ static inline int rxtx(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int frame_t
|
||||
wakeup_prach_gNB(gNB,NULL,proc->frame_rx,proc->slot_rx);
|
||||
}
|
||||
*/
|
||||
|
||||
// Call the scheduler
|
||||
|
||||
pthread_mutex_lock(&gNB->UL_INFO_mutex);
|
||||
gNB->UL_INFO.frame = frame_rx;
|
||||
gNB->UL_INFO.slot = slot_rx;
|
||||
@@ -333,7 +330,7 @@ static void *gNB_L1_thread( void *param ) {
|
||||
gNB_L1_rxtx_proc_t *L1_proc = &gNB_proc->L1_proc;
|
||||
//PHY_VARS_gNB *gNB = RC.gNB[0][proc->CC_id];
|
||||
char thread_name[100];
|
||||
|
||||
// set default return value
|
||||
// set default return value
|
||||
gNB_thread_rxtx_status = 0;
|
||||
|
||||
@@ -430,7 +427,7 @@ int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot
|
||||
|
||||
int waitret = 0, ret = 0, time_ns = 1000*1000;
|
||||
struct timespec now, abstime;
|
||||
|
||||
// note this should depend on the numerology used by the TX L1 thread, set here for 500us slot time
|
||||
// note this should depend on the numerology used by the TX L1 thread, set here for 500us slot time
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,1);
|
||||
time_ns = time_ns/gNB->frame_parms.slots_per_subframe;
|
||||
@@ -452,27 +449,27 @@ int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,0);
|
||||
|
||||
if (waitret == ETIMEDOUT) {
|
||||
LOG_W(PHY,"Dropping TX slot (%d.%d) because FH is blocked more than 1 slot times (500us)\n",frame_tx,slot_tx);
|
||||
LOG_W(PHY,"Dropping TX slot (%d.%d) because FH is blocked more than 1 slot times (500us)\n",frame_tx,slot_tx);
|
||||
|
||||
AssertFatal((ret=pthread_mutex_lock(&gNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret);
|
||||
gNB->proc.RU_mask_tx = 0;
|
||||
AssertFatal((ret=pthread_mutex_unlock(&gNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret);
|
||||
AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RUs_tx))==0,"mutex_lock returns %d\n",ret);
|
||||
proc->instance_cnt_RUs = 0;
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs);
|
||||
AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RUs_tx))==0,"mutex_unlock returns %d\n",ret);
|
||||
AssertFatal((ret=pthread_mutex_lock(&gNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret);
|
||||
gNB->proc.RU_mask_tx = 0;
|
||||
AssertFatal((ret=pthread_mutex_unlock(&gNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret);
|
||||
AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RUs_tx))==0,"mutex_lock returns %d\n",ret);
|
||||
proc->instance_cnt_RUs = 0;
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs);
|
||||
AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RUs_tx))==0,"mutex_unlock returns %d\n",ret);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,1);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,0);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,1);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE,0);
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
for(int i=0; i<gNB->num_RU; i++)
|
||||
{
|
||||
ru = gNB->RU_list[i];
|
||||
ru_proc = &ru->proc;
|
||||
|
||||
|
||||
|
||||
if (ru_proc->instance_cnt_gNBs == 0) {
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST_UE, 1);
|
||||
@@ -493,10 +490,10 @@ int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_UE, ru_proc->instance_cnt_gNBs);
|
||||
|
||||
LOG_D(PHY,"Signaling tx_thread_fh for %d.%d\n",frame_tx,slot_tx);
|
||||
LOG_D(PHY,"Signaling tx_thread_fh for %d.%d\n",frame_tx,slot_tx);
|
||||
// the thread can now be woken up
|
||||
AssertFatal(pthread_cond_signal(&ru_proc->cond_gNBs) == 0,
|
||||
"[gNB] ERROR pthread_cond_signal for gNB TXnp4 thread\n");
|
||||
"[gNB] ERROR pthread_cond_signal for gNB TXnp4 thread\n");
|
||||
AssertFatal((ret=pthread_mutex_unlock(&ru_proc->mutex_gNBs))==0,"mutex_unlock returned %d\n",ret);
|
||||
|
||||
}
|
||||
@@ -514,7 +511,7 @@ int wakeup_tx(PHY_VARS_gNB *gNB,int frame_rx,int slot_rx,int frame_tx,int slot_t
|
||||
AssertFatal((ret = pthread_mutex_lock(&L1_proc_tx->mutex))==0,"mutex_lock returns %d\n",ret);
|
||||
|
||||
|
||||
while(L1_proc_tx->instance_cnt == 0){
|
||||
while(L1_proc_tx->instance_cnt == 0) {
|
||||
pthread_cond_wait(&L1_proc_tx->cond,&L1_proc_tx->mutex);
|
||||
}
|
||||
|
||||
@@ -530,7 +527,7 @@ int wakeup_tx(PHY_VARS_gNB *gNB,int frame_rx,int slot_rx,int frame_tx,int slot_t
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_UE,1);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_UE,0);
|
||||
|
||||
// the thread can now be woken up
|
||||
// the thread can now be woken up
|
||||
AssertFatal(pthread_cond_signal(&L1_proc_tx->cond) == 0, "ERROR pthread_cond_signal for gNB L1 thread\n");
|
||||
|
||||
@@ -550,11 +547,11 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) {
|
||||
int time_ns = 50000;
|
||||
|
||||
AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RU))==0,"mutex_lock returns %d\n",ret);
|
||||
for (i=0;i<gNB->num_RU;i++) {
|
||||
for (i=0; i<gNB->num_RU; i++) {
|
||||
if (ru == gNB->RU_list[i]) {
|
||||
if ((proc->RU_mask&(1<<i)) > 0)
|
||||
LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n",
|
||||
gNB->Mod_id,proc->frame_rx,proc->slot_rx,ru->idx,gNB->num_RU,proc->RU_mask);
|
||||
LOG_E(PHY,"gNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n",
|
||||
gNB->Mod_id,proc->frame_rx,proc->slot_rx,ru->idx,gNB->num_RU,proc->RU_mask);
|
||||
proc->RU_mask |= (1<<i);
|
||||
}
|
||||
}
|
||||
@@ -581,16 +578,16 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) {
|
||||
AssertFatal((ret=pthread_mutex_timedlock(&L1_proc->mutex, &abstime)) == 0,"mutex_lock returns %d\n", ret);
|
||||
|
||||
if (L1_proc->instance_cnt == 0) { // L1_thread is busy so abort the subframe
|
||||
AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"muex_unlock return %d\n",ret);
|
||||
LOG_W(PHY,"L1_thread isn't ready in %d.%d, aborting RX processing\n",ru_proc->frame_rx,ru_proc->tti_rx);
|
||||
return(-1);
|
||||
AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"muex_unlock return %d\n",ret);
|
||||
LOG_W(PHY,"L1_thread isn't ready in %d.%d, aborting RX processing\n",ru_proc->frame_rx,ru_proc->tti_rx);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
||||
++L1_proc->instance_cnt;
|
||||
|
||||
// We have just received and processed the common part of a subframe, say n.
|
||||
// TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired
|
||||
// We have just received and processed the common part of a subframe, say n.
|
||||
// TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired
|
||||
// transmitted timestamp of the next TX slot (first).
|
||||
|
||||
// The last (TS_rx mod samples_per_frame) was n*samples_per_tti,
|
||||
// we want to generate subframe (n+sf_ahead), so TS_tx = TX_rx+sf_ahead*samples_per_tti,
|
||||
// and proc->slot_tx = proc->slot_rx+sf_ahead
|
||||
@@ -610,7 +607,7 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) {
|
||||
exit_fun( "ERROR pthread_cond_signal" );
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
||||
return(0);
|
||||
}
|
||||
/*
|
||||
@@ -714,9 +711,9 @@ static void* gNB_thread_prach( void* param ) {
|
||||
extern void init_td_thread(PHY_VARS_gNB *);
|
||||
extern void init_te_thread(PHY_VARS_gNB *);
|
||||
|
||||
static void* process_stats_thread(void* param) {
|
||||
static void *process_stats_thread(void *param) {
|
||||
|
||||
PHY_VARS_gNB *gNB = (PHY_VARS_gNB*)param;
|
||||
PHY_VARS_gNB *gNB = (PHY_VARS_gNB *)param;
|
||||
|
||||
reset_meas(&gNB->dlsch_encoding_stats);
|
||||
reset_meas(&gNB->dlsch_scrambling_stats);
|
||||
|
||||
+54
-54
@@ -1,41 +1,24 @@
|
||||
/*******************************************************************************
|
||||
OpenAirInterface
|
||||
Copyright(c) 1999 - 2014 Eurecom
|
||||
|
||||
OpenAirInterface is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenAirInterface is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenAirInterface.The full GNU General Public License is
|
||||
included in this distribution in the file called "COPYING". If not,
|
||||
see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Contact Information
|
||||
OpenAirInterface Admin: openair_admin@eurecom.fr
|
||||
OpenAirInterface Tech : openair_tech@eurecom.fr
|
||||
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
|
||||
|
||||
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
/*! \file lte-enb.c
|
||||
* \brief Top-level threads for eNodeB
|
||||
* \author R. Knopp, F. Kaltenberger, Navid Nikaein
|
||||
* \date 2012
|
||||
* \version 0.1
|
||||
* \company Eurecom
|
||||
* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr
|
||||
* \note
|
||||
* \warning
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -73,9 +56,8 @@
|
||||
#include "SCHED/sched_eNB.h"
|
||||
#include "SCHED_NR/sched_nr.h"
|
||||
|
||||
#include "LAYER2/MAC/mac.h"
|
||||
#include "NR_MAC_COMMON/nr_mac_extern.h"
|
||||
#include "LAYER2/MAC/mac_proto.h"
|
||||
|
||||
#include "RRC/LTE/rrc_extern.h"
|
||||
#include "PHY_INTERFACE/phy_interface.h"
|
||||
|
||||
@@ -94,7 +76,7 @@ unsigned short config_frames[4] = {2,9,11,13};
|
||||
static int DEFBANDS[] = {7};
|
||||
static int DEFENBS[] = {0};
|
||||
static int DEFBFW[] = {0x00007fff};
|
||||
|
||||
|
||||
//static int DEFNRBANDS[] = {7};
|
||||
//static int DEFGNBS[] = {0};
|
||||
|
||||
@@ -714,7 +696,7 @@ void rx_rf(RU_t *ru,int *frame,int *slot) {
|
||||
}
|
||||
|
||||
|
||||
void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) {
|
||||
void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) {
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
nfapi_nr_config_request_scf_t *cfg = &ru->config;
|
||||
@@ -885,7 +867,7 @@ void *ru_thread_prach( void *param ) {
|
||||
0,0
|
||||
);
|
||||
}
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 );*/
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 );*/
|
||||
if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break;
|
||||
}
|
||||
|
||||
@@ -1112,16 +1094,16 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) {
|
||||
}
|
||||
} else if(N_RB == 106) {
|
||||
if (fp->threequarter_fs) {
|
||||
cfg->sample_rate=46.08e6;
|
||||
cfg->samples_per_frame = 460800;
|
||||
cfg->tx_bw = 40e6;
|
||||
cfg->rx_bw = 40e6;
|
||||
cfg->sample_rate=46.08e6;
|
||||
cfg->samples_per_frame = 460800;
|
||||
cfg->tx_bw = 40e6;
|
||||
cfg->rx_bw = 40e6;
|
||||
}
|
||||
else {
|
||||
cfg->sample_rate=61.44e6;
|
||||
cfg->samples_per_frame = 614400;
|
||||
cfg->tx_bw = 40e6;
|
||||
cfg->rx_bw = 40e6;
|
||||
cfg->sample_rate=61.44e6;
|
||||
cfg->samples_per_frame = 614400;
|
||||
cfg->tx_bw = 40e6;
|
||||
cfg->rx_bw = 40e6;
|
||||
}
|
||||
} else {
|
||||
AssertFatal(0==1,"N_RB %d not yet supported for numerology %d\n",N_RB,mu);
|
||||
@@ -1285,7 +1267,7 @@ void *ru_stats_thread(void *param) {
|
||||
|
||||
if (ru->feprx) print_meas(&ru->ofdm_demod_stats,"feprx",NULL,NULL);
|
||||
|
||||
if (ru->feptx_ofdm){
|
||||
if (ru->feptx_ofdm) {
|
||||
print_meas(&ru->precoding_stats,"feptx_prec",NULL,NULL);
|
||||
print_meas(&ru->txdataF_copy_stats,"txdataF_copy",NULL,NULL);
|
||||
print_meas(&ru->ofdm_mod_stats,"feptx_ofdm",NULL,NULL);
|
||||
@@ -1294,7 +1276,7 @@ void *ru_stats_thread(void *param) {
|
||||
|
||||
if (ru->fh_north_asynch_in) print_meas(&ru->rx_fhaul,"rx_fhaul",NULL,NULL);
|
||||
|
||||
print_meas(&ru->tx_fhaul,"tx_fhaul",NULL,NULL);
|
||||
print_meas(&ru->tx_fhaul,"tx_fhaul",NULL,NULL);
|
||||
if (ru->fh_north_out) {
|
||||
print_meas(&ru->compression,"compression",NULL,NULL);
|
||||
print_meas(&ru->transport,"transport",NULL,NULL);
|
||||
@@ -1425,7 +1407,7 @@ void *ru_thread_tx( void *param ) {
|
||||
L1_proc->instance_cnt_RUs = 0;
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,L1_proc->instance_cnt_RUs);
|
||||
AssertFatal(pthread_cond_signal(&L1_proc->cond_RUs) == 0,
|
||||
"ERROR pthread_cond_signal for gNB_L1_thread\n");
|
||||
"ERROR pthread_cond_signal for gNB_L1_thread\n");
|
||||
} //else AssertFatal(1==0,"gNB TX thread is not ready\n");
|
||||
ret = pthread_mutex_unlock(&L1_proc->mutex_RUs_tx);
|
||||
AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret);
|
||||
@@ -2350,9 +2332,27 @@ void RCconfig_RU(void)
|
||||
}
|
||||
}
|
||||
else {
|
||||
RC.ru[j]->openair0_cfg.clock_source = unset;
|
||||
RC.ru[j]->openair0_cfg.clock_source = unset;
|
||||
}
|
||||
|
||||
if (config_isparamset(RUParamList.paramarray[j], RU_SDR_TME_SRC)) {
|
||||
if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "internal") == 0) {
|
||||
RC.ru[j]->openair0_cfg.time_source = internal;
|
||||
LOG_D(PHY, "RU time source set as internal\n");
|
||||
} else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "external") == 0) {
|
||||
RC.ru[j]->openair0_cfg.time_source = external;
|
||||
LOG_D(PHY, "RU time source set as external\n");
|
||||
} else if (strcmp(*(RUParamList.paramarray[j][RU_SDR_TME_SRC].strptr), "gpsdo") == 0) {
|
||||
RC.ru[j]->openair0_cfg.time_source = gpsdo;
|
||||
LOG_D(PHY, "RU time source set as gpsdo\n");
|
||||
} else {
|
||||
LOG_E(PHY, "Erroneous RU time source in the provided configuration file: '%s'\n", *(RUParamList.paramarray[j][RU_SDR_CLK_SRC].strptr));
|
||||
}
|
||||
}
|
||||
else {
|
||||
RC.ru[j]->openair0_cfg.time_source = unset;
|
||||
}
|
||||
|
||||
if (strcmp(*(RUParamList.paramarray[j][RU_LOCAL_RF_IDX].strptr), "yes") == 0) {
|
||||
if ( !(config_isparamset(RUParamList.paramarray[j],RU_LOCAL_IF_NAME_IDX)) ) {
|
||||
RC.ru[j]->if_south = LOCAL_RF;
|
||||
|
||||
+40
-42
@@ -49,8 +49,6 @@
|
||||
#include "PHY/phy_vars.h"
|
||||
#include "SCHED/sched_common_vars.h"
|
||||
#include "LAYER2/MAC/mac_vars.h"
|
||||
#include "LAYER2/MAC/mac.h"
|
||||
#include "LAYER2/MAC/mac_proto.h"
|
||||
#include "RRC/LTE/rrc_vars.h"
|
||||
#include "PHY_INTERFACE/phy_interface_vars.h"
|
||||
#include "gnb_config.h"
|
||||
@@ -108,7 +106,7 @@ static int wait_for_sync = 0;
|
||||
unsigned int mmapped_dma=0;
|
||||
int single_thread_flag=1;
|
||||
|
||||
static int8_t threequarter_fs=0;
|
||||
int8_t threequarter_fs=0;
|
||||
|
||||
uint64_t downlink_frequency[MAX_NUM_CCs][4];
|
||||
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
|
||||
@@ -171,6 +169,10 @@ uint32_t target_ul_mcs = 20;
|
||||
uint32_t timing_advance = 0;
|
||||
uint64_t num_missed_slots=0; // counter for the number of missed slots
|
||||
|
||||
int split73=0;
|
||||
void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset) {
|
||||
AssertFatal(false, "Must not be called in this context\n");
|
||||
}
|
||||
|
||||
extern void reset_opp_meas(void);
|
||||
extern void print_opp_meas(void);
|
||||
@@ -725,13 +727,9 @@ int restart_L1L2(module_id_t gnb_id) {
|
||||
memcpy(&ru->nr_frame_parms, &RC.gNB[gnb_id]->frame_parms, sizeof(NR_DL_FRAME_PARMS));
|
||||
set_function_spec_param(RC.ru[gnb_id]);
|
||||
LOG_I(GNB_APP, "attempting to create ITTI tasks\n");
|
||||
|
||||
if (itti_create_task (TASK_RRC_ENB, rrc_enb_task, NULL) < 0) {
|
||||
LOG_E(RRC, "Create task for RRC eNB failed\n");
|
||||
return -1;
|
||||
} else {
|
||||
LOG_I(RRC, "Re-created task for RRC gNB successfully\n");
|
||||
}
|
||||
// No more rrc thread, as many race conditions are hidden behind
|
||||
rrc_enb_init();
|
||||
itti_mark_task_ready(TASK_RRC_ENB);
|
||||
|
||||
if (itti_create_task (TASK_L2L1, l2l1_task, NULL) < 0) {
|
||||
LOG_E(PDCP, "Create task for L2L1 failed\n");
|
||||
@@ -774,23 +772,23 @@ static void wait_nfapi_init(char *thread_name) {
|
||||
|
||||
void init_pdcp(void) {
|
||||
//if (!NODE_IS_DU(RC.rrc[0]->node_type)) {
|
||||
pdcp_layer_init();
|
||||
uint32_t pdcp_initmask = (IS_SOFTMODEM_NOS1) ?
|
||||
(PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT;
|
||||
pdcp_layer_init();
|
||||
uint32_t pdcp_initmask = (IS_SOFTMODEM_NOS1) ?
|
||||
(PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT;
|
||||
|
||||
if (IS_SOFTMODEM_NOS1){
|
||||
printf("IS_SOFTMODEM_NOS1 option enabled \n");
|
||||
pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT ;
|
||||
}
|
||||
if (IS_SOFTMODEM_NOS1) {
|
||||
printf("IS_SOFTMODEM_NOS1 option enabled \n");
|
||||
pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT ;
|
||||
}
|
||||
|
||||
pdcp_module_init(pdcp_initmask);
|
||||
pdcp_module_init(pdcp_initmask);
|
||||
|
||||
/*if (NODE_IS_CU(RC.rrc[0]->node_type)) {
|
||||
pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t)proto_agent_send_rlc_data_req);
|
||||
} else {*/
|
||||
pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req);
|
||||
pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind);
|
||||
//}
|
||||
/*if (NODE_IS_CU(RC.rrc[0]->node_type)) {
|
||||
pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t)proto_agent_send_rlc_data_req);
|
||||
} else {*/
|
||||
pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req);
|
||||
pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind);
|
||||
//}
|
||||
/*} else {
|
||||
pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) proto_agent_send_pdcp_data_ind);
|
||||
}*/
|
||||
@@ -848,7 +846,7 @@ int main( int argc, char **argv )
|
||||
MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX);
|
||||
|
||||
|
||||
init_opt();
|
||||
init_opt();
|
||||
|
||||
|
||||
#ifdef PDCP_USE_NETLINK
|
||||
@@ -865,7 +863,7 @@ if(!IS_SOFTMODEM_NOS1)
|
||||
LOG_I(HW, "Version: %s\n", PACKAGE_VERSION);
|
||||
|
||||
if(IS_SOFTMODEM_NOS1)
|
||||
init_pdcp();
|
||||
init_pdcp();
|
||||
|
||||
if (RC.nb_nr_inst > 0) {
|
||||
// don't create if node doesn't connect to RRC/S1/GTP
|
||||
@@ -995,27 +993,27 @@ if(!IS_SOFTMODEM_NOS1)
|
||||
printf("oai_exit=%d\n",oai_exit);
|
||||
|
||||
// stop threads
|
||||
/*#ifdef XFORMS
|
||||
/*#ifdef XFORMS
|
||||
|
||||
printf("waiting for XFORMS thread\n");
|
||||
printf("waiting for XFORMS thread\n");
|
||||
|
||||
if (do_forms==1) {
|
||||
pthread_join(forms_thread,&status);
|
||||
fl_hide_form(form_stats->stats_form);
|
||||
fl_free_form(form_stats->stats_form);
|
||||
if (do_forms==1) {
|
||||
pthread_join(forms_thread,&status);
|
||||
fl_hide_form(form_stats->stats_form);
|
||||
fl_free_form(form_stats->stats_form);
|
||||
|
||||
fl_hide_form(form_stats_l2->stats_form);
|
||||
fl_free_form(form_stats_l2->stats_form);
|
||||
fl_hide_form(form_stats_l2->stats_form);
|
||||
fl_free_form(form_stats_l2->stats_form);
|
||||
|
||||
for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
|
||||
for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
|
||||
fl_hide_form(form_enb[CC_id][UE_id]->phy_scope_gNB);
|
||||
fl_free_form(form_enb[CC_id][UE_id]->phy_scope_gNB);
|
||||
}
|
||||
}
|
||||
}
|
||||
for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
|
||||
for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
|
||||
fl_hide_form(form_enb[CC_id][UE_id]->phy_scope_gNB);
|
||||
fl_free_form(form_enb[CC_id][UE_id]->phy_scope_gNB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif*/
|
||||
#endif*/
|
||||
printf("stopping MODEM threads\n");
|
||||
// cleanup
|
||||
stop_gNB(NB_gNB_INST);
|
||||
|
||||
+22
-5
@@ -481,6 +481,23 @@ void processSlotRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) {
|
||||
pdcp_run(&ctxt);
|
||||
}
|
||||
}
|
||||
|
||||
// no UL for now
|
||||
// no UL for now
|
||||
/*
|
||||
if (UE->mac_enabled==1) {
|
||||
// trigger L2 to run ue_scheduler thru IF module
|
||||
// [TODO] mapping right after NR initial sync
|
||||
if(UE->if_inst != NULL && UE->if_inst->ul_indication != NULL) {
|
||||
UE->ul_indication.module_id = 0;
|
||||
UE->ul_indication.gNB_index = 0;
|
||||
UE->ul_indication.cc_id = 0;
|
||||
UE->ul_indication.frame = proc->frame_rx;
|
||||
UE->ul_indication.slot = proc->nr_tti_rx;
|
||||
UE->if_inst->ul_indication(&UE->ul_indication);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -519,9 +536,9 @@ void UE_processing(void *arg) {
|
||||
// then timing advance is processed and set to be applied in the next UL transmission */
|
||||
if (UE->mac_enabled == 1) {
|
||||
|
||||
if (frame_tx == ul_time_alignment->ta_frame && slot_tx == ul_time_alignment->ta_slot){
|
||||
if (frame_tx == ul_time_alignment->ta_frame && slot_tx == ul_time_alignment->ta_slot) {
|
||||
LOG_D(PHY,"Applying timing advance -- frame %d -- slot %d\n", frame_tx, slot_tx);
|
||||
|
||||
//if (nfapi_mode!=3){
|
||||
//if (nfapi_mode!=3){
|
||||
nr_process_timing_advance(UE->Mod_id, UE->CC_id, ul_time_alignment->ta_command, numerology, bwp_ul_NB_RB);
|
||||
ul_time_alignment->ta_frame = -1;
|
||||
@@ -603,8 +620,8 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, bool toTrash)
|
||||
|
||||
void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) {
|
||||
|
||||
LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode);
|
||||
void *dummy_tx[UE->frame_parms.nb_antennas_tx];
|
||||
LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode);
|
||||
void *dummy_tx[UE->frame_parms.nb_antennas_tx];
|
||||
|
||||
*timestamp += UE->frame_parms.get_samples_per_slot(1,&UE->frame_parms);
|
||||
for ( int size=UE->rx_offset ; size > 0 ; size -= UE->frame_parms.samples_per_subframe ) {
|
||||
@@ -761,7 +778,7 @@ void *UE_thread(void *arg) {
|
||||
#ifdef OAI_ADRV9371_ZC706
|
||||
/*uint32_t total_gain_dB_prev = 0;
|
||||
if (total_gain_dB_prev != UE->rx_total_gain_dB) {
|
||||
total_gain_dB_prev = UE->rx_total_gain_dB;
|
||||
total_gain_dB_prev = UE->rx_total_gain_dB;
|
||||
openair0_cfg[0].rx_gain[0] = UE->rx_total_gain_dB;
|
||||
UE->rfdevice.trx_set_gains_func(&UE->rfdevice,&openair0_cfg[0]);
|
||||
}*/
|
||||
|
||||
@@ -47,7 +47,6 @@
|
||||
#include "PHY/NR_REFSIG/nr_mod_table.h"
|
||||
|
||||
#include "LAYER2/MAC/mac_vars.h"
|
||||
#include "LAYER2/MAC/mac_proto.h"
|
||||
#include "RRC/LTE/rrc_vars.h"
|
||||
#include "PHY_INTERFACE/phy_interface_vars.h"
|
||||
#include "openair1/SIMULATION/TOOLS/sim.h"
|
||||
@@ -127,7 +126,6 @@ volatile int start_eNB = 0;
|
||||
volatile int start_UE = 0;
|
||||
volatile int oai_exit = 0;
|
||||
|
||||
static clock_source_t clock_source = unset;
|
||||
int single_thread_flag=1;
|
||||
static double snr_dB=20;
|
||||
|
||||
@@ -215,7 +213,7 @@ int emulate_rf = 0;
|
||||
|
||||
tpool_t *Tpool;
|
||||
#ifdef UE_DLSCH_PARALLELISATION
|
||||
tpool_t *Tpool_dl;
|
||||
tpool_t *Tpool_dl;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -311,8 +309,8 @@ static void *scope_thread(void *arg) {
|
||||
|
||||
while (!oai_exit) {
|
||||
phy_scope_nrUE(form_nrue[0],
|
||||
PHY_vars_UE_g[0][0],
|
||||
0,0,1);
|
||||
PHY_vars_UE_g[0][0],
|
||||
0,0,1);
|
||||
usleep(100*1000);
|
||||
}
|
||||
|
||||
@@ -383,9 +381,9 @@ static void get_options(void) {
|
||||
int tddflag=0, nonbiotflag, vcdflag=0;
|
||||
char *loopfile=NULL;
|
||||
int dumpframe=0;
|
||||
|
||||
//uint32_t noS1;
|
||||
//uint32_t nokrnmod;
|
||||
//uint32_t nokrnmod;
|
||||
paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC_UE ;
|
||||
config_process_cmdline( cmdline_params,sizeof(cmdline_params)/sizeof(paramdef_t),NULL);
|
||||
|
||||
@@ -529,12 +527,12 @@ void init_openair0(void) {
|
||||
else {
|
||||
openair0_cfg[card].sample_rate=122.88e6;
|
||||
openair0_cfg[card].samples_per_frame = 1228800;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG_E(PHY,"Unsupported numerology!\n");
|
||||
exit(-1);
|
||||
}
|
||||
}else if(frame_parms[0]->N_RB_DL == 273) {
|
||||
} else if(frame_parms[0]->N_RB_DL == 273) {
|
||||
if (numerology==1) {
|
||||
if (frame_parms[0]->threequarter_fs) {
|
||||
AssertFatal(0 == 1,"three quarter sampling not supported for N_RB 273\n");
|
||||
@@ -542,12 +540,12 @@ void init_openair0(void) {
|
||||
else {
|
||||
openair0_cfg[card].sample_rate=122.88e6;
|
||||
openair0_cfg[card].samples_per_frame = 1228800;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG_E(PHY,"Unsupported numerology!\n");
|
||||
exit(-1);
|
||||
}
|
||||
}else if(frame_parms[0]->N_RB_DL == 106) {
|
||||
} else if(frame_parms[0]->N_RB_DL == 106) {
|
||||
if (numerology==0) {
|
||||
if (frame_parms[0]->threequarter_fs) {
|
||||
openair0_cfg[card].sample_rate=23.04e6;
|
||||
@@ -556,15 +554,15 @@ void init_openair0(void) {
|
||||
openair0_cfg[card].sample_rate=30.72e6;
|
||||
openair0_cfg[card].samples_per_frame = 307200;
|
||||
}
|
||||
} else if (numerology==1) {
|
||||
} else if (numerology==1) {
|
||||
if (frame_parms[0]->threequarter_fs) {
|
||||
openair0_cfg[card].sample_rate=46.08e6;
|
||||
openair0_cfg[card].samples_per_frame = 460800;
|
||||
openair0_cfg[card].sample_rate=46.08e6;
|
||||
openair0_cfg[card].samples_per_frame = 460800;
|
||||
}
|
||||
else {
|
||||
openair0_cfg[card].sample_rate=61.44e6;
|
||||
openair0_cfg[card].samples_per_frame = 614400;
|
||||
}
|
||||
openair0_cfg[card].sample_rate=61.44e6;
|
||||
openair0_cfg[card].samples_per_frame = 614400;
|
||||
}
|
||||
} else if (numerology==2) {
|
||||
openair0_cfg[card].sample_rate=122.88e6;
|
||||
openair0_cfg[card].samples_per_frame = 1228800;
|
||||
@@ -597,7 +595,8 @@ void init_openair0(void) {
|
||||
PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx);
|
||||
openair0_cfg[card].Mod_id = 0;
|
||||
openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL;
|
||||
openair0_cfg[card].clock_source = clock_source;
|
||||
openair0_cfg[card].clock_source = get_softmodem_params()->clock_source;
|
||||
openair0_cfg[card].time_source = get_softmodem_params()->timing_source;
|
||||
openair0_cfg[card].tx_num_channels=min(2,PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx);
|
||||
openair0_cfg[card].rx_num_channels=min(2,PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx);
|
||||
|
||||
@@ -639,7 +638,7 @@ void init_pdcp(void) {
|
||||
pdcp_initmask = pdcp_initmask | UE_NAS_USE_TUN_BIT;
|
||||
|
||||
/*if (rlc_module_init() != 0) {
|
||||
LOG_I(RLC, "Problem at RLC initiation \n");
|
||||
LOG_I(RLC, "Problem at RLC initiation \n");
|
||||
}
|
||||
pdcp_layer_init();
|
||||
nr_ip_over_LTE_DRB_preconfiguration();*/
|
||||
@@ -649,6 +648,11 @@ void init_pdcp(void) {
|
||||
LOG_I(PDCP, "Before getting out from init_pdcp() \n");
|
||||
}
|
||||
|
||||
// Stupid function addition because UE itti messages queues definition is common with eNB
|
||||
void *rrc_enb_process_msg(void *notUsed) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int main( int argc, char **argv ) {
|
||||
//uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2;
|
||||
@@ -676,12 +680,12 @@ int main( int argc, char **argv ) {
|
||||
set_taus_seed (0);
|
||||
tpool_t pool;
|
||||
Tpool = &pool;
|
||||
char params[]="-1,-1";
|
||||
char params[]="-1,-1";
|
||||
initTpool(params, Tpool, false);
|
||||
#ifdef UE_DLSCH_PARALLELISATION
|
||||
tpool_t pool_dl;
|
||||
Tpool_dl = &pool_dl;
|
||||
char params_dl[]="-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1";
|
||||
char params_dl[]="-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1";
|
||||
initTpool(params_dl, Tpool_dl, false);
|
||||
#endif
|
||||
cpuf=get_cpu_freq_GHz();
|
||||
|
||||
@@ -58,7 +58,6 @@
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt */
|
||||
/*----------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
#define CMDLINE_PARAMS_DESC_UE { \
|
||||
{"clock-source", CONFIG_HLP_EXCCLK, 0, iptr:&clock_source, defintval:0, TYPE_INT, 0}, \
|
||||
{"single-thread-disable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&single_thread_flag, defintval:1, TYPE_INT, 0}, \
|
||||
{"nr-dlsch-demod-shift", CONFIG_HLP_DLSHIFT, 0, iptr:(int32_t *)&nr_dlsch_demod_shift, defintval:0, TYPE_INT, 0}, \
|
||||
{"A" , CONFIG_HLP_TADV, 0, uptr:&timing_advance, defintval:0, TYPE_UINT, 0}, \
|
||||
|
||||
@@ -81,8 +81,8 @@ char *get_softmodem_function(uint64_t *sofmodemfunc_mask_ptr) {
|
||||
}
|
||||
|
||||
void get_common_options(uint32_t execmask) {
|
||||
uint32_t online_log_messages;
|
||||
uint32_t glog_level ;
|
||||
uint32_t online_log_messages=0;
|
||||
uint32_t glog_level=0 ;
|
||||
uint32_t start_telnetsrv = 0;
|
||||
uint32_t noS1 = 0, nokrnmod = 0, nonbiot = 0;
|
||||
uint32_t rfsim = 0, basicsim = 0, do_forms = 0;
|
||||
@@ -145,27 +145,27 @@ void get_common_options(uint32_t execmask) {
|
||||
if(worker_config != NULL) set_worker_conf(worker_config);
|
||||
}
|
||||
void softmodem_printresources(int sig, telnet_printfunc_t pf) {
|
||||
struct rusage usage;
|
||||
struct timespec stop;
|
||||
struct rusage usage;
|
||||
struct timespec stop;
|
||||
|
||||
clock_gettime(CLOCK_BOOTTIME, &stop);
|
||||
clock_gettime(CLOCK_BOOTTIME, &stop);
|
||||
|
||||
uint64_t elapse = (stop.tv_sec - start.tv_sec) ; // in seconds
|
||||
uint64_t elapse = (stop.tv_sec - start.tv_sec) ; // in seconds
|
||||
|
||||
|
||||
int st = getrusage(RUSAGE_SELF,&usage);
|
||||
if (!st) {
|
||||
pf("\nRun time: %lluh %llus\n",(unsigned long long)elapse/3600,(unsigned long long)(elapse - (elapse/3600)));
|
||||
pf("\tTime executing user inst.: %lds %ldus\n",(long)usage.ru_utime.tv_sec,(long)usage.ru_utime.tv_usec);
|
||||
pf("\tTime executing system inst.: %lds %ldus\n",(long)usage.ru_stime.tv_sec,(long)usage.ru_stime.tv_usec);
|
||||
pf("\tMax. Phy. memory usage: %ldkB\n",(long)usage.ru_maxrss);
|
||||
pf("\tPage fault number (no io): %ld\n",(long)usage.ru_minflt);
|
||||
pf("\tPage fault number (requiring io): %ld\n",(long)usage.ru_majflt);
|
||||
pf("\tNumber of file system read: %ld\n",(long)usage.ru_inblock);
|
||||
pf("\tNumber of filesystem write: %ld\n",(long)usage.ru_oublock);
|
||||
pf("\tNumber of context switch (process origin, io...): %ld\n",(long)usage.ru_nvcsw);
|
||||
pf("\tNumber of context switch (os origin, priority...): %ld\n",(long)usage.ru_nivcsw);
|
||||
}
|
||||
int st = getrusage(RUSAGE_SELF,&usage);
|
||||
if (!st) {
|
||||
pf("\nRun time: %lluh %llus\n",(unsigned long long)elapse/3600,(unsigned long long)(elapse - (elapse/3600)));
|
||||
pf("\tTime executing user inst.: %lds %ldus\n",(long)usage.ru_utime.tv_sec,(long)usage.ru_utime.tv_usec);
|
||||
pf("\tTime executing system inst.: %lds %ldus\n",(long)usage.ru_stime.tv_sec,(long)usage.ru_stime.tv_usec);
|
||||
pf("\tMax. Phy. memory usage: %ldkB\n",(long)usage.ru_maxrss);
|
||||
pf("\tPage fault number (no io): %ld\n",(long)usage.ru_minflt);
|
||||
pf("\tPage fault number (requiring io): %ld\n",(long)usage.ru_majflt);
|
||||
pf("\tNumber of file system read: %ld\n",(long)usage.ru_inblock);
|
||||
pf("\tNumber of filesystem write: %ld\n",(long)usage.ru_oublock);
|
||||
pf("\tNumber of context switch (process origin, io...): %ld\n",(long)usage.ru_nvcsw);
|
||||
pf("\tNumber of context switch (os origin, priority...): %ld\n",(long)usage.ru_nivcsw);
|
||||
}
|
||||
}
|
||||
|
||||
void signal_handler(int sig) {
|
||||
@@ -180,9 +180,9 @@ void signal_handler(int sig) {
|
||||
backtrace_symbols_fd(array, size, 2);
|
||||
exit(-1);
|
||||
} else {
|
||||
if(sig==SIGINT ||sig==SOFTMODEM_RTSIGNAL)
|
||||
softmodem_printresources(sig,(telnet_printfunc_t)printf);
|
||||
if (sig != SOFTMODEM_RTSIGNAL) {
|
||||
if(sig==SIGINT ||sig==SOFTMODEM_RTSIGNAL)
|
||||
softmodem_printresources(sig,(telnet_printfunc_t)printf);
|
||||
if (sig != SOFTMODEM_RTSIGNAL) {
|
||||
printf("Linux signal %s...\n",strsignal(sig));
|
||||
exit_function(__FILE__, __FUNCTION__, __LINE__,"softmodem starting exit procedure\n");
|
||||
}
|
||||
@@ -192,7 +192,7 @@ void signal_handler(int sig) {
|
||||
|
||||
|
||||
void set_softmodem_sighandler(void) {
|
||||
struct sigaction act,oldact;
|
||||
struct sigaction act,oldact;
|
||||
clock_gettime(CLOCK_BOOTTIME, &start);
|
||||
memset(&act,0,sizeof(act));
|
||||
act.sa_handler=signal_handler;
|
||||
@@ -201,6 +201,6 @@ void set_softmodem_sighandler(void) {
|
||||
signal(SIGSEGV, signal_handler);
|
||||
signal(SIGINT, signal_handler);
|
||||
signal(SIGTERM, signal_handler);
|
||||
signal(SIGABRT, signal_handler);
|
||||
signal(SIGABRT, signal_handler);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,11 @@ extern "C"
|
||||
#endif
|
||||
/* help strings definition for command line options, used in CMDLINE_XXX_DESC macros and printed when -h option is used */
|
||||
#define CONFIG_HLP_RFCFGF "Configuration file for front-end (e.g. LMS7002M)\n"
|
||||
#define CONFIG_HLP_SPLIT73 "Split 7.3 (below rate matching) option: <cu|du>:<remote ip address>:<remote port>"
|
||||
#define CONFIG_HLP_TPOOL "Thread pool configuration: \n\
|
||||
default no pool (runs in calling thread),\n\
|
||||
list of cores, comma separated (negative value is no core affinity)\n\
|
||||
example: -1,3 launches two working threads one floating, the second set on core 3"
|
||||
#define CONFIG_HLP_ULMAXE "set the eNodeB max ULSCH erros\n"
|
||||
#define CONFIG_HLP_CALUER "set UE RX calibration\n"
|
||||
#define CONFIG_HLP_CALUERM ""
|
||||
@@ -54,6 +59,7 @@ extern "C"
|
||||
#define CONFIG_HLP_EXTS "tells hardware to use an external timing reference\n"
|
||||
#define CONFIG_HLP_DMRSSYNC "tells RU to insert DMRS in subframe 1 slot 0"
|
||||
#define CONFIG_HLP_CLK "tells hardware to use a clock reference (0:internal, 1:external, 2:gpsdo)\n"
|
||||
#define CONFIG_HLP_TME "tells hardware to use a time reference (0:internal, 1:external, 2:gpsdo)\n"
|
||||
#define CONFIG_HLP_USIM "use XOR autentication algo in case of test usim mode\n"
|
||||
#define CONFIG_HLP_NOSNGLT "Disables single-thread mode in lte-softmodem\n"
|
||||
#define CONFIG_HLP_DLF "Set the downlink frequency for all component carriers\n"
|
||||
@@ -89,6 +95,8 @@ extern "C"
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt */
|
||||
/*-----------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
#define RF_CONFIG_FILE softmodem_params.rf_config_file
|
||||
#define SPLIT73 softmodem_params.split73
|
||||
#define TP_CONFIG softmodem_params.threadPoolConfig
|
||||
#define PHY_TEST softmodem_params.phy_test
|
||||
#define DO_RA softmodem_params.do_ra
|
||||
#define WAIT_FOR_SYNC softmodem_params.wait_for_sync
|
||||
@@ -105,10 +113,13 @@ extern "C"
|
||||
|
||||
#define CMDLINE_PARAMS_DESC { \
|
||||
{"rf-config-file", CONFIG_HLP_RFCFGF, 0, strptr:(char **)&RF_CONFIG_FILE, defstrval:NULL, TYPE_STRING, sizeof(RF_CONFIG_FILE)},\
|
||||
{"split73", CONFIG_HLP_SPLIT73, 0, strptr:(char **)&SPLIT73, defstrval:NULL, TYPE_STRING, sizeof(SPLIT73)},\
|
||||
{"thread-pool", CONFIG_HLP_TPOOL, 0, strptr:(char **)&TP_CONFIG, defstrval:"n", TYPE_STRING, sizeof(TP_CONFIG)}, \
|
||||
{"phy-test", CONFIG_HLP_PHYTST, PARAMFLAG_BOOL, iptr:&PHY_TEST, defintval:0, TYPE_INT, 0}, \
|
||||
{"do-ra", CONFIG_HLP_DORA, PARAMFLAG_BOOL, iptr:&DO_RA, defintval:0, TYPE_INT, 0}, \
|
||||
{"usim-test", CONFIG_HLP_USIM, PARAMFLAG_BOOL, u8ptr:&USIM_TEST, defintval:0, TYPE_UINT8, 0}, \
|
||||
{"clock", CONFIG_HLP_CLK, 0, uptr:&CLOCK_SOURCE, defintval:0, TYPE_UINT, 0}, \
|
||||
{"clock-source", CONFIG_HLP_CLK, 0, uptr:&CLOCK_SOURCE, defintval:0, TYPE_UINT, 0}, \
|
||||
{"time-source", CONFIG_HLP_TME, 0, uptr:&TIMING_SOURCE, defintval:0, TYPE_UINT, 0}, \
|
||||
{"wait-for-sync", NULL, PARAMFLAG_BOOL, iptr:&WAIT_FOR_SYNC, defintval:0, TYPE_INT, 0}, \
|
||||
{"single-thread-enable", CONFIG_HLP_NOSNGLT, PARAMFLAG_BOOL, iptr:&SINGLE_THREAD_FLAG, defintval:0, TYPE_INT, 0}, \
|
||||
{"C" , CONFIG_HLP_DLF, 0, u64ptr:&(downlink_frequency[0][0]), defuintval:0, TYPE_UINT64, 0}, \
|
||||
@@ -194,6 +205,8 @@ typedef struct {
|
||||
uint64_t optmask;
|
||||
//THREAD_STRUCT thread_struct;
|
||||
char rf_config_file[1024];
|
||||
char split73[1024];
|
||||
char threadPoolConfig[1024];
|
||||
int phy_test;
|
||||
int do_ra;
|
||||
uint8_t usim_test;
|
||||
|
||||
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* Author and copyright: Laurent Thomas, open-cells.com
|
||||
*
|
||||
* 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 __SPLIT_HEADERS_H
|
||||
#define __SPLIT_HEADERS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <openair1/PHY/defs_eNB.h>
|
||||
|
||||
#define CU_PORT "7878"
|
||||
#define DU_PORT "8787"
|
||||
#define SPLIT73_CU 1
|
||||
#define SPLIT73_DU 2
|
||||
extern int split73;
|
||||
|
||||
#define MTU 65536
|
||||
#define UDP_TIMEOUT 900000L // in micro second (struct timeval, NOT struct timespec)
|
||||
// linux may timeout for a much longer time (up to 10ms)
|
||||
#define blockAlign 32 //bytes to align memory for SIMD copy (256 bits vectors)
|
||||
|
||||
// FS6 transport configuration and handler
|
||||
typedef struct {
|
||||
char *sourceIP;
|
||||
char *sourcePort;
|
||||
char *destIP;
|
||||
char *destPort;
|
||||
struct addrinfo *destAddr;
|
||||
int sockHandler;
|
||||
} UDPsock_t;
|
||||
|
||||
#define CTsentCUv0 0xA500
|
||||
#define CTsentDUv0 0x5A00
|
||||
|
||||
// Main FS6 transport layer header
|
||||
// All packets starts with this header
|
||||
typedef struct commonUDP_s {
|
||||
uint64_t timestamp; // id of the group (subframe for LTE)
|
||||
uint16_t nbBlocks; // total number of blocks for this timestamp
|
||||
uint16_t blockID; // id: 0..nbBocks-1
|
||||
uint16_t contentType; // defines the content format
|
||||
uint16_t contentBytes; // will be sent in a UDP packet, so must be < 2^16 bytes
|
||||
uint64_t senderClock;
|
||||
} commonUDP_t;
|
||||
|
||||
// FS6 UL common header (DU to CU)
|
||||
// gives the RACH detection data and is always sent to inform the CU that a subframe arrived
|
||||
typedef struct {
|
||||
uint16_t max_preamble[4];
|
||||
uint16_t max_preamble_energy[4];
|
||||
uint16_t max_preamble_delay[4];
|
||||
uint16_t avg_preamble_energy[4];
|
||||
} fs6_ul_t;
|
||||
|
||||
// FS6 DL common header (CU to DU)
|
||||
// gives the DCI configuration from each subframe
|
||||
typedef struct {
|
||||
uint8_t pbch_pdu[4];
|
||||
int num_pdcch_symbols;
|
||||
int num_dci;
|
||||
DCI_ALLOC_t dci_alloc[8];
|
||||
int num_mdci;
|
||||
int amp;
|
||||
LTE_eNB_PHICH phich_vars;
|
||||
uint64_t DuClock;
|
||||
uint64_t CuSpentMicroSec;
|
||||
} fs6_dl_t;
|
||||
|
||||
// a value to type all sub packets,
|
||||
// to detect errors, and to be able to extend to other versions
|
||||
// the first byte of each sub structure should match one of these values
|
||||
enum pckType {
|
||||
fs6UlConfig=25,
|
||||
fs6DlConfig=26,
|
||||
fs6ULConfigCCH=27,
|
||||
fs6ULsch=28,
|
||||
fs6ULcch=29,
|
||||
fs6ULindicationHarq=40,
|
||||
fs6ULindicationSr=41,
|
||||
};
|
||||
|
||||
// CU to DU definition of a future UL subframe decode
|
||||
// defines a UE future data plane
|
||||
typedef struct {
|
||||
enum pckType type:8;
|
||||
uint16_t UE_id;
|
||||
int8_t harq_pid;
|
||||
UE_type_t ue_type;
|
||||
|
||||
uint8_t dci_alloc;
|
||||
uint8_t rar_alloc;
|
||||
SCH_status_t status;
|
||||
uint8_t Msg3_flag;
|
||||
uint8_t subframe;
|
||||
uint32_t frame;
|
||||
uint8_t handled;
|
||||
uint8_t phich_active;
|
||||
uint8_t phich_ACK;
|
||||
uint16_t previous_first_rb;
|
||||
uint32_t B;
|
||||
uint32_t G;
|
||||
UCI_format_t uci_format;
|
||||
uint8_t Or2;
|
||||
uint8_t o_RI[2];
|
||||
uint8_t o_ACK[4];
|
||||
uint8_t O_ACK;
|
||||
uint8_t o_RCC;
|
||||
int16_t q_ACK[MAX_ACK_PAYLOAD];
|
||||
int16_t q_RI[MAX_RI_PAYLOAD];
|
||||
uint32_t RTC[MAX_NUM_ULSCH_SEGMENTS];
|
||||
uint8_t ndi;
|
||||
uint8_t round;
|
||||
uint8_t rvidx;
|
||||
uint8_t Nl;
|
||||
uint8_t n_DMRS;
|
||||
uint8_t previous_n_DMRS;
|
||||
uint8_t n_DMRS2;
|
||||
int32_t delta_TF;
|
||||
uint32_t repetition_number ;
|
||||
uint32_t total_number_of_repetitions;
|
||||
|
||||
uint16_t harq_mask;
|
||||
uint16_t nb_rb;
|
||||
uint8_t Qm;
|
||||
uint16_t first_rb;
|
||||
uint8_t O_RI;
|
||||
uint8_t Or1;
|
||||
uint16_t Msc_initial;
|
||||
uint8_t Nsymb_initial;
|
||||
uint8_t V_UL_DAI;
|
||||
uint8_t srs_active;
|
||||
uint32_t TBS;
|
||||
uint8_t Nsymb_pusch;
|
||||
uint8_t Mlimit;
|
||||
uint8_t max_turbo_iterations;
|
||||
uint8_t bundling;
|
||||
uint16_t beta_offset_cqi_times8;
|
||||
uint16_t beta_offset_ri_times8;
|
||||
uint16_t beta_offset_harqack_times8;
|
||||
uint8_t Msg3_active;
|
||||
uint16_t rnti;
|
||||
uint8_t cyclicShift;
|
||||
uint8_t cooperation_flag;
|
||||
uint8_t num_active_cba_groups;
|
||||
uint16_t cba_rnti[4];//NUM_MAX_CBA_GROUP];
|
||||
} fs6_dl_ulsched_t;
|
||||
|
||||
// CU to DU defintion of a DL packet for a given UE
|
||||
// The data itself is padded at the end of this structure
|
||||
typedef struct {
|
||||
enum pckType type:8;
|
||||
int UE_id;
|
||||
int8_t harq_pid;
|
||||
uint16_t rnti;
|
||||
int16_t sqrt_rho_a;
|
||||
int16_t sqrt_rho_b;
|
||||
CEmode_t CEmode:8;
|
||||
uint16_t nb_rb;
|
||||
uint8_t Qm;
|
||||
int8_t Nl;
|
||||
uint8_t pdsch_start;
|
||||
uint8_t sib1_br_flag;
|
||||
uint16_t i0;
|
||||
uint32_t rb_alloc[4];
|
||||
int dataLen;
|
||||
} fs6_dl_uespec_t;
|
||||
|
||||
// CU to DU definition of CCH channel
|
||||
typedef struct {
|
||||
int16_t UE_id;
|
||||
LTE_eNB_UCI cch_vars;
|
||||
} fs6_dl_uespec_ulcch_element_t;
|
||||
|
||||
// header to group all UE CCH channels definitions in one UDP packet
|
||||
typedef struct {
|
||||
enum pckType type:8;
|
||||
int16_t nb_active_ue;
|
||||
} fs6_dl_uespec_ulcch_t;
|
||||
|
||||
// code internal, not transmitted as this
|
||||
typedef struct {
|
||||
int ta;
|
||||
} ul_propagation_t;
|
||||
|
||||
// One UE UL data, data plane, UE data appended after the header
|
||||
typedef struct {
|
||||
enum pckType type:8;
|
||||
short UE_id;
|
||||
uint8_t harq_id;
|
||||
uint8_t segment;
|
||||
int segLen;
|
||||
int r_offset;
|
||||
int G;
|
||||
int ulsch_power[2];
|
||||
uint8_t o_ACK[4];
|
||||
uint8_t O_ACK;
|
||||
int ta;
|
||||
uint8_t o[MAX_CQI_BYTES];
|
||||
uint8_t cqi_crc_status;
|
||||
} fs6_ul_uespec_t;
|
||||
|
||||
// UL UCI (control plane), per UE
|
||||
typedef struct {
|
||||
enum pckType type:8;
|
||||
int UEid;
|
||||
int frame;
|
||||
int subframe;
|
||||
LTE_eNB_UCI uci;
|
||||
uint8_t harq_ack[4];
|
||||
uint8_t tdd_mapping_mode;
|
||||
uint16_t tdd_multiplexing_mask;
|
||||
unsigned short n0_subband_power_dB;
|
||||
uint16_t rnti;
|
||||
int32_t stat;
|
||||
} fs6_ul_uespec_uci_element_t;
|
||||
|
||||
// all segments UCI grouped in one UDP packet
|
||||
typedef struct {
|
||||
enum pckType type:8;
|
||||
int16_t nb_active_ue;
|
||||
} fs6_ul_uespec_uci_t;
|
||||
|
||||
|
||||
bool createUDPsock (char *sourceIP, char *sourcePort, char *destIP, char *destPort, UDPsock_t *result);
|
||||
int receiveSubFrame(UDPsock_t *sock, void *bufferZone, int bufferSize, uint16_t contentType);
|
||||
int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize, uint16_t contentType);
|
||||
|
||||
#define initBufferZone(xBuf) \
|
||||
uint8_t xBuf[FS6_BUF_SIZE]; \
|
||||
((commonUDP_t *)xBuf)->nbBlocks=0;
|
||||
|
||||
#define hUDP(xBuf) ((commonUDP_t *)xBuf)
|
||||
#define hDL(xBuf) ((fs6_dl_t*)(((commonUDP_t *)xBuf)+1))
|
||||
#define hUL(xBuf) ((fs6_ul_t*)(((commonUDP_t *)xBuf)+1))
|
||||
#define hDLUE(xBuf) ((fs6_dl_uespec_t*) (((fs6_dl_t*)(((commonUDP_t *)xBuf)+1))+1))
|
||||
#define hTxULUE(xBuf) ((fs6_dl_ulsched_t*) (((fs6_dl_t*)(((commonUDP_t *)xBuf)+1))+1))
|
||||
#define hTxULcch(xBuf) ((fs6_dl_uespec_ulcch_t*) (((fs6_dl_t*)(((commonUDP_t *)xBuf)+1))+1))
|
||||
#define hULUE(xBuf) ((fs6_ul_uespec_t*) (((fs6_ul_t*)(((commonUDP_t *)xBuf)+1))+1))
|
||||
#define hULUEuci(xBuf) ((fs6_ul_uespec_uci_t*) (((fs6_ul_t*)(((commonUDP_t *)xBuf)+1))+1))
|
||||
|
||||
static inline size_t alignedSize(uint8_t *ptr) {
|
||||
commonUDP_t *header=(commonUDP_t *) ptr;
|
||||
return ((header->contentBytes+sizeof(commonUDP_t)+blockAlign-1)/blockAlign)*blockAlign;
|
||||
}
|
||||
|
||||
static inline void *commonUDPdata(uint8_t *ptr) {
|
||||
return (void *) (((commonUDP_t *)ptr)+1);
|
||||
}
|
||||
|
||||
void setAllfromTS(uint64_t TS, L1_rxtx_proc_t *proc);
|
||||
void sendFs6Ulharq(enum pckType type, int UEid, PHY_VARS_eNB *eNB,LTE_eNB_UCI *uci, int frame, int subframe, uint8_t *harq_ack, uint8_t tdd_mapping_mode, uint16_t tdd_multiplexing_mask,
|
||||
uint16_t rnti, int32_t stat);
|
||||
void sendFs6Ul(PHY_VARS_eNB *eNB, int UE_id, int harq_pid, int segmentID, int16_t *data, int dataLen, int r_offset);
|
||||
void *cu_fs6(void *arg);
|
||||
void *du_fs6(void *arg);
|
||||
void fill_rf_config(RU_t *ru, char *rf_config_file);
|
||||
int init_rf(RU_t *ru);
|
||||
void rx_rf(RU_t *ru, L1_rxtx_proc_t *proc);
|
||||
void tx_rf(RU_t *ru, L1_rxtx_proc_t *proc);
|
||||
void common_signal_procedures (PHY_VARS_eNB *eNB,int frame, int subframe);
|
||||
void pmch_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc);
|
||||
bool dlsch_procedures(PHY_VARS_eNB *eNB,
|
||||
L1_rxtx_proc_t *proc,
|
||||
int harq_pid,
|
||||
LTE_eNB_DLSCH_t *dlsch,
|
||||
LTE_eNB_UE_stats *ue_stats) ;
|
||||
void postDecode(L1_rxtx_proc_t *proc, notifiedFIFO_elt_t *req);
|
||||
void pdsch_procedures(PHY_VARS_eNB *eNB,
|
||||
L1_rxtx_proc_t *proc,
|
||||
int harq_pid,
|
||||
LTE_eNB_DLSCH_t *dlsch,
|
||||
LTE_eNB_DLSCH_t *dlsch1);
|
||||
void srs_procedures(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc);
|
||||
void uci_procedures(PHY_VARS_eNB *eNB,
|
||||
L1_rxtx_proc_t *proc);
|
||||
void ocp_rx_prach(PHY_VARS_eNB *eNB,
|
||||
L1_rxtx_proc_t *proc,
|
||||
RU_t *ru,
|
||||
uint16_t *max_preamble,
|
||||
uint16_t *max_preamble_energy,
|
||||
uint16_t *max_preamble_delay,
|
||||
uint16_t *avg_preamble_energy,
|
||||
uint16_t Nf,
|
||||
uint8_t tdd_mapindex,
|
||||
uint8_t br_flag);
|
||||
void rx_prach0(PHY_VARS_eNB *eNB,
|
||||
RU_t *ru,
|
||||
int frame_prach,
|
||||
int subframe,
|
||||
uint16_t *max_preamble,
|
||||
uint16_t *max_preamble_energy,
|
||||
uint16_t *max_preamble_delay,
|
||||
uint16_t *avg_preamble_energy,
|
||||
uint16_t Nf,
|
||||
uint8_t tdd_mapindex,
|
||||
uint8_t br_flag,
|
||||
uint8_t ce_level
|
||||
);
|
||||
void ocp_tx_rf(RU_t *ru, L1_rxtx_proc_t *proc);
|
||||
|
||||
// mistakes in main OAI
|
||||
void phy_init_RU(RU_t *);
|
||||
void fep_full(RU_t *ru, int subframe);
|
||||
void feptx_prec(RU_t *ru,int frame,int subframe);
|
||||
void feptx_ofdm(RU_t *ru, int frame, int subframe);
|
||||
void oai_subframe_ind(uint16_t sfn, uint16_t sf);
|
||||
extern uint16_t sf_ahead;
|
||||
#endif
|
||||
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* Author and copyright: Laurent Thomas, open-cells.com
|
||||
*
|
||||
* 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 <executables/split_headers.h>
|
||||
#include <sys/types.h> /* See NOTES */
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netdb.h>
|
||||
#include <targets/RT/USER/lte-softmodem.h>
|
||||
|
||||
bool createUDPsock (char *sourceIP, char *sourcePort, char *destIP, char *destPort, UDPsock_t *result) {
|
||||
struct addrinfo hints= {0}, *servinfo, *p;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_socktype = SOCK_DGRAM;
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
int status;
|
||||
|
||||
if ((status = getaddrinfo(sourceIP, sourcePort, &hints, &servinfo)) != 0) {
|
||||
LOG_E(GTPU,"getaddrinfo error: %s\n", gai_strerror(status));
|
||||
return false;
|
||||
}
|
||||
|
||||
// loop through all the results and bind to the first we can
|
||||
for(p = servinfo; p != NULL; p = p->ai_next) {
|
||||
if ((result->sockHandler = socket(p->ai_family, p->ai_socktype,
|
||||
p->ai_protocol)) == -1) {
|
||||
LOG_W(GTPU,"socket: %s\n", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bind(result->sockHandler, p->ai_addr, p->ai_addrlen) == -1) {
|
||||
close(result->sockHandler);
|
||||
LOG_W(GTPU,"bind: %s\n", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
break; // if we get here, we must have connected successfully
|
||||
}
|
||||
|
||||
if (p == NULL) {
|
||||
// looped off the end of the list with no successful bind
|
||||
LOG_E(GTPU,"failed to bind socket: %s %s \n",sourceIP,sourcePort);
|
||||
return false;
|
||||
}
|
||||
|
||||
freeaddrinfo(servinfo); // all done with this structure
|
||||
|
||||
if ((status = getaddrinfo(destIP, destPort, &hints, &servinfo)) != 0) {
|
||||
LOG_E(GTPU,"getaddrinfo error: %s\n", gai_strerror(status));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (servinfo) {
|
||||
result->destAddr=servinfo;
|
||||
} else {
|
||||
LOG_E(PHY,"No valid UDP addr: %s:%s\n",destIP, destPort);
|
||||
return false;
|
||||
}
|
||||
|
||||
int enable=1;
|
||||
AssertFatal(setsockopt(result->sockHandler, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable))==0,"");
|
||||
struct timeval tv= {0,UDP_TIMEOUT};
|
||||
|
||||
if (IS_SOFTMODEM_RFSIM)
|
||||
tv.tv_sec=2; //debug: wait 2 seconds for human understanding
|
||||
|
||||
AssertFatal(setsockopt(result->sockHandler, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(tv)) ==0,"");
|
||||
// Make a send/recv buffer larger than a a couple of subframe
|
||||
// so the kernel will store for us in and out paquets
|
||||
int buff=1000*1000*10;
|
||||
AssertFatal ( setsockopt(result->sockHandler, SOL_SOCKET, SO_SNDBUF, &buff, sizeof(buff)) == 0, "");
|
||||
AssertFatal ( setsockopt(result->sockHandler, SOL_SOCKET, SO_RCVBUF, &buff, sizeof(buff)) == 0, "");
|
||||
return true;
|
||||
}
|
||||
|
||||
// sock: udp socket
|
||||
// bufferZone: a reception area of bufferSize
|
||||
int receiveSubFrame(UDPsock_t *sock, void *bufferZone, int bufferSize, uint16_t contentType) {
|
||||
int rcved=0;
|
||||
commonUDP_t *bufOrigin=(commonUDP_t *)bufferZone;
|
||||
static uint8_t crossData[65536];
|
||||
static int crossDataSize=0;
|
||||
|
||||
if (crossDataSize) {
|
||||
LOG_D(HW,"copy a block received in previous subframe\n");
|
||||
memcpy(bufferZone, crossData, crossDataSize);
|
||||
rcved=1;
|
||||
bufferZone+=crossDataSize;
|
||||
crossDataSize=0;
|
||||
}
|
||||
|
||||
do {
|
||||
//read all subframe data from the control unit
|
||||
int ret=recv(sock->sockHandler, bufferZone, bufferSize, 0);
|
||||
|
||||
if ( ret==-1) {
|
||||
if ( errno == EWOULDBLOCK || errno== EINTR ) {
|
||||
LOG_I(HW,"Received: Timeout, subframe incomplete\n");
|
||||
return rcved;
|
||||
} else {
|
||||
LOG_E(HW,"Critical issue in socket: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (hUDP(bufferZone)->contentType != contentType)
|
||||
abort();
|
||||
|
||||
if (rcved && bufOrigin->timestamp != hUDP(bufferZone)->timestamp ) {
|
||||
if ( hUDP(bufferZone)->timestamp > bufOrigin->timestamp ) {
|
||||
LOG_W(HW,"Received data for TS: %lu before end of TS : %lu completion\n",
|
||||
hUDP(bufferZone)->timestamp,
|
||||
bufOrigin->timestamp);
|
||||
memcpy(crossData, bufferZone, ret );
|
||||
crossDataSize=ret;
|
||||
return rcved;
|
||||
} else {
|
||||
LOG_W(HW,"Dropping late packet\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
rcved++;
|
||||
bufferZone+=ret;
|
||||
}
|
||||
|
||||
LOG_D(HW,"Received: blocks: %d/%d, size %d, TS: %lu\n",
|
||||
rcved, bufOrigin->nbBlocks, ret, bufOrigin->timestamp);
|
||||
} while ( rcved == 0 || rcved < bufOrigin->nbBlocks );
|
||||
|
||||
return rcved;
|
||||
}
|
||||
|
||||
int sendSubFrame(UDPsock_t *sock, void *bufferZone, ssize_t secondHeaderSize, uint16_t contentType) {
|
||||
commonUDP_t *UDPheader=(commonUDP_t *)bufferZone ;
|
||||
UDPheader->contentType=contentType;
|
||||
UDPheader->senderClock=rdtsc();
|
||||
int nbBlocks=UDPheader->nbBlocks;
|
||||
int blockId=0;
|
||||
|
||||
if (nbBlocks <= 0 ) {
|
||||
LOG_E(PHY,"FS6: can't send blocks: %d\n", nbBlocks);
|
||||
return 0;
|
||||
}
|
||||
|
||||
do {
|
||||
if (blockId > 0 ) {
|
||||
commonUDP_t *currentHeader=(commonUDP_t *)bufferZone;
|
||||
currentHeader->timestamp=UDPheader->timestamp;
|
||||
currentHeader->nbBlocks=UDPheader->nbBlocks;
|
||||
currentHeader->blockID=blockId;
|
||||
currentHeader->contentType=UDPheader->contentType;
|
||||
memcpy(commonUDPdata((void *)currentHeader), commonUDPdata(bufferZone), secondHeaderSize);
|
||||
}
|
||||
|
||||
blockId++;
|
||||
int sz=alignedSize(bufferZone);
|
||||
// Let's use the first address returned by getaddrinfo()
|
||||
int ret=sendto(sock->sockHandler, bufferZone, sz, 0,
|
||||
sock->destAddr->ai_addr, sock->destAddr->ai_addrlen);
|
||||
|
||||
if ( ret != sz )
|
||||
LOG_W(HW,"Wrote socket doesn't return size %d (val: %d, errno:%d, %s)\n",
|
||||
sz, ret, errno, strerror(errno));
|
||||
|
||||
LOG_D(HW,"Sent: TS: %lu, blocks %d/%d, block size : %d \n",
|
||||
UDPheader->timestamp, UDPheader->nbBlocks-nbBlocks, UDPheader->nbBlocks, sz);
|
||||
bufferZone+=sz;
|
||||
nbBlocks--;
|
||||
} while (nbBlocks);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user