Commit 4bbcf7cf authored by Raymond Knopp's avatar Raymond Knopp

Merge branch 'develop' into develop-sidekiq

parents 6433c1f7 1fb76157
......@@ -544,6 +544,19 @@ set(TPLIB_ETHERNET_SOURCE
)
add_library(oai_eth_transpro MODULE ${TPLIB_ETHERNET_SOURCE} )
include_directories("${OPENAIR_TARGETS}/ARCH/mobipass/")
set(TPLIB_MOBIPASS_SOURCE
${OPENAIR_TARGETS}/ARCH/mobipass/interface.c
${OPENAIR_TARGETS}/ARCH/mobipass/mobipass.c
${OPENAIR_TARGETS}/ARCH/mobipass/queues.c
)
add_library(oai_mobipass MODULE ${TPLIB_MOBIPASS_SOURCE} )
# Hide all functions/variables in the mobipass library.
# Use __attribute__((__visibility__("default")))
# in the source code to unhide a function/variable.
get_target_property(mobipas_cflags oai_mobipass COMPILE_FLAGS)
set_target_properties(oai_mobipass PROPERTIES COMPILE_FLAGS "${mobipass_cflags} -fvisibility=hidden")
##########################################################
......
......@@ -47,7 +47,7 @@ eNBs =
prach_zero_correlation = 1;
prach_freq_offset = 2;
pucch_delta_shift = 1;
pucch_nRB_CQI = 1;
pucch_nRB_CQI = 0;
pucch_nCS_AN = 0;
pucch_n1_AN = 32;
pdsch_referenceSignalPower = -24;
......
......@@ -47,7 +47,7 @@ eNBs =
prach_zero_correlation = 1;
prach_freq_offset = 2;
pucch_delta_shift = 1;
pucch_nRB_CQI = 1;
pucch_nRB_CQI = 0;
pucch_nCS_AN = 0;
pucch_n1_AN = 32;
pdsch_referenceSignalPower = -24;
......
......@@ -47,7 +47,7 @@ eNBs =
prach_zero_correlation = 1;
prach_freq_offset = 2;
pucch_delta_shift = 1;
pucch_nRB_CQI = 1;
pucch_nRB_CQI = 0;
pucch_nCS_AN = 0;
pucch_n1_AN = 32;
pdsch_referenceSignalPower = -24;
......
......@@ -47,7 +47,7 @@ eNBs =
prach_zero_correlation = 1;
prach_freq_offset = 2;
pucch_delta_shift = 1;
pucch_nRB_CQI = 1;
pucch_nRB_CQI = 0;
pucch_nCS_AN = 0;
pucch_n1_AN = 32;
pdsch_referenceSignalPower = -24;
......
......@@ -47,7 +47,7 @@ eNBs =
prach_zero_correlation = 1;
prach_freq_offset = 2;
pucch_delta_shift = 1;
pucch_nRB_CQI = 1;
pucch_nRB_CQI = 0;
pucch_nCS_AN = 0;
pucch_n1_AN = 32;
pdsch_referenceSignalPower = -24;
......
......@@ -47,7 +47,7 @@ eNBs =
prach_zero_correlation = 1;
prach_freq_offset = 2;
pucch_delta_shift = 1;
pucch_nRB_CQI = 1;
pucch_nRB_CQI = 0;
pucch_nCS_AN = 0;
pucch_n1_AN = 32;
pdsch_referenceSignalPower = -24;
......
......@@ -47,7 +47,7 @@ eNBs =
prach_zero_correlation = 1;
prach_freq_offset = 2;
pucch_delta_shift = 1;
pucch_nRB_CQI = 1;
pucch_nRB_CQI = 0;
pucch_nCS_AN = 0;
pucch_n1_AN = 32;
pdsch_referenceSignalPower = -29;
......
......@@ -47,7 +47,7 @@ eNBs =
prach_zero_correlation = 1;
prach_freq_offset = 2;
pucch_delta_shift = 1;
pucch_nRB_CQI = 1;
pucch_nRB_CQI = 0;
pucch_nCS_AN = 0;
pucch_n1_AN = 32;
pdsch_referenceSignalPower = -29;
......
......@@ -47,7 +47,7 @@ eNBs =
prach_zero_correlation = 1;
prach_freq_offset = 2;
pucch_delta_shift = 1;
pucch_nRB_CQI = 1;
pucch_nRB_CQI = 0;
pucch_nCS_AN = 0;
pucch_n1_AN = 32;
pdsch_referenceSignalPower = -29;
......
......@@ -47,7 +47,7 @@ eNBs =
prach_zero_correlation = 1;
prach_freq_offset = 2;
pucch_delta_shift = 1;
pucch_nRB_CQI = 1;
pucch_nRB_CQI = 0;
pucch_nCS_AN = 0;
pucch_n1_AN = 32;
pdsch_referenceSignalPower = -29;
......
......@@ -47,7 +47,7 @@ eNBs =
prach_zero_correlation = 1;
prach_freq_offset = 2;
pucch_delta_shift = 1;
pucch_nRB_CQI = 1;
pucch_nRB_CQI = 0;
pucch_nCS_AN = 0;
pucch_n1_AN = 32;
pdsch_referenceSignalPower = -29;
......
......@@ -47,7 +47,7 @@ eNBs =
prach_zero_correlation = 1;
prach_freq_offset = 2;
pucch_delta_shift = 1;
pucch_nRB_CQI = 1;
pucch_nRB_CQI = 0;
pucch_nCS_AN = 0;
pucch_n1_AN = 32;
pdsch_referenceSignalPower = -29;
......
......@@ -555,11 +555,7 @@ check_install_oai_software() {
$SUDO update-alternatives --set liblapack.so /usr/lib/atlas-base/atlas/liblapack.so
#Remove old gnutls/nettle installation that was done from sources
remove_nettle_from_source
$SUDO apt-get install -y nettle-dev nettle-bin
remove_gnutls_from_source
$SUDO apt-get install -y libgnutls-dev
elif [[ "$OS_BASEDISTRO" == "fedora" ]]; then
......@@ -647,56 +643,6 @@ check_install_oai_software() {
$SUDO git clone https://gist.github.com/2190472.git /opt/ssh
}
### Remove Nettle installation which was done from sources (only done for Ubuntu Distro)
remove_nettle_from_source() {
nettle_uninstall_log=$OPENAIR_DIR/cmake_targets/log/nettle_uninstall_log.txt
echo_info "\nUn-Installing Nettle from sources. The log file for nettle un-installation is here: $nettle_uninstall_log "
(
$SUDO apt-get remove -y nettle-dev nettle-bin
cd /tmp
echo "Downloading nettle archive"
$SUDO rm -rf /tmp/nettle-2.5.tar.gz* /tmp/nettle-2.5
wget https://ftp.gnu.org/gnu/nettle/nettle-2.5.tar.gz
if [ $? -ne 0 ]; then
wget ftp://ftp.lysator.liu.se/pub/security/lsh/nettle-2.5.tar.gz
fi
if [ ! -f nettle-2.5.tar.gz ]; then
echo_error "Could not download nettle source files"
cd -
return
fi
tar -xzf nettle-2.5.tar.gz
cd nettle-2.5/
./configure --disable-openssl --enable-shared --prefix=/usr
$SUDO make uninstall || true
$SUDO ldconfig
) >& $nettle_uninstall_log
}
### Remove Gnutls from source (Only done for Ubuntu Distro)
remove_gnutls_from_source(){
gnutls_uninstall_log=$OPENAIR_DIR/cmake_targets/log/gnutls_uninstall_log.txt
echo_info "\nUn-Installing Gnutls. The log file for Gnutls un-installation is here: $gnutls_uninstall_log "
(
$SUDO apt-get remove -y libgnutls-dev
cd /tmp
echo "Downloading gnutls archive"
$SUDO rm -rf /tmp/gnutls-3.1.23.tar.xz* /tmp/gnutls-3.1.23
wget http://mirrors.dotsrc.org/gcrypt/gnutls/v3.1/gnutls-3.1.23.tar.xz || \
wget ftp://ftp.gnutls.org/gcrypt/gnutls/v3.1/gnutls-3.1.23.tar.xz
if [ ! -f gnutls-3.1.23.tar.xz ]; then
echo_error "Could not download gnutls source files"
cd -
return
fi
tar -xJf gnutls-3.1.23.tar.xz
cd gnutls-3.1.23/
./configure --prefix=/usr
$SUDO make uninstall || true
$SUDO ldconfig
)>& $gnutls_uninstall_log
}
install_asn1c_from_source(){
asn1_install_log=$OPENAIR_DIR/cmake_targets/log/asn1c_install_log.txt
echo_info "\nInstalling ASN1. The log file for ASN1 installation is here: $asn1_install_log "
......
......@@ -29,10 +29,10 @@ typedef struct {
#define T_SHM_FILENAME "/T_shm_segment"
/* number of VCD functions (to be kept up to date! see in T_messages.txt) */
#define VCD_NUM_FUNCTIONS 142
#define VCD_NUM_FUNCTIONS 172
/* number of VCD variables (to be kept up to date! see in T_messages.txt) */
#define VCD_NUM_VARIABLES 107
#define VCD_NUM_VARIABLES 118
/* first VCD function (to be kept up to date! see in T_messages.txt) */
#define VCD_FIRST_FUNCTION ((uintptr_t)T_VCD_FUNCTION_RT_SLEEP)
......
......@@ -45,6 +45,10 @@ ID = ENB_PHY_INPUT_SIGNAL
DESC = eNodeB received signal in the time domain for a duration of 1ms
GROUP = ALL:PHY:GRAPHIC:HEAVY:ENB
FORMAT = int,eNB_ID : int,frame : int,subframe : int,antenna : buffer,rxdata
ID = ENB_PHY_OUTPUT_SIGNAL
DESC = eNodeB sent signal in the time domain for a duration of 1ms
GROUP = ALL:PHY:HEAVY:ENB
FORMAT = int,eNB_ID : int,CC_id : int,frame : int,subframe : int,antenna : buffer,txdata
ID = ENB_PHY_UL_CHANNEL_ESTIMATE
DESC = eNodeB channel estimation in the time domain
GROUP = ALL:PHY:GRAPHIC:HEAVY:ENB
......@@ -111,6 +115,10 @@ ID = ENB_MAC_UE_DL_PDU_WITH_DATA
DESC = MAC downlink PDU for an UE
GROUP = ALL:MAC:ENB
FORMAT = int,eNB_ID : int,CC_id : int,rnti : int,frame : int,subframe : int,harq_pid : buffer,data
ID = ENB_MAC_SCHEDULING_REQUEST
DESC = MAC scheduling request detected for an UE
GROUP = ALL:MAC:ENB
FORMAT = int,eNB_ID : int,CC_id : int,frame : int,subframe : int,rnti
#RLC logs
ID = ENB_RLC_DL
......@@ -1350,6 +1358,22 @@ ID = VCD_VARIABLE_UE0_SFN7
DESC = VCD variable UE0_SFN7
GROUP = ALL:VCD:ENB:VCD_VARIABLE
FORMAT = ulong,value
ID = VCD_VARIABLE_SEND_IF4_SYMBOL
DESC = VCD variable SEND_IF4_SYMBOL
GROUP = ALL:VCD:ENB:VCD_VARIABLE
FORMAT = ulong,value
ID = VCD_VARIABLE_RECV_IF4_SYMBOL
DESC = VCD variable RECV_IF4_SYMBOL
GROUP = ALL:VCD:ENB:VCD_VARIABLE
FORMAT = ulong,value
ID = VCD_VARIABLE_SEND_IF5_PKT_ID
DESC = VCD variable SEND_IF5_PKT_ID
GROUP = ALL:VCD:ENB:VCD_VARIABLE
FORMAT = ulong,value
ID = VCD_VARIABLE_RECV_IF5_PKT_ID
DESC = VCD variable RECV_IF5_PKT_ID
GROUP = ALL:VCD:ENB:VCD_VARIABLE
FORMAT = ulong,value
ID = VCD_VARIABLE_UE_PDCP_FLUSH_SIZE
DESC = VCD variable UE_PDCP_FLUSH_SIZE
GROUP = ALL:VCD:ENB:UE:VCD_VARIABLE
......@@ -2061,3 +2085,11 @@ ID = VCD_FUNCTION_RECV_IF5
DESC = VCD function RECV_IF5
GROUP = ALL:VCD:ENB:VCD_FUNCTION
FORMAT = int,value
ID = VCD_FUNCTION_TRX_COMPR_IF
DESC = VCD function TRX_COMPR_IF
GROUP = ALL:VCD:ENB:VCD_FUNCTION
FORMAT = int,value
ID = VCD_FUNCTION_TRX_DECOMPR_IF
DESC = VCD function TRX_DECOMPR_IF
GROUP = ALL:VCD:ENB:VCD_FUNCTION
FORMAT = int,value
......@@ -5,7 +5,8 @@ CFLAGS=-Wall -g -pthread -DT_TRACER -I.
LIBS=-lX11 -lm -lpng -lXft
all: record replay extract_config textlog enb ue vcd macpdu2wireshark
all: record replay extract_config textlog enb ue vcd macpdu2wireshark \
extract_input_subframe
record: utils.o record.o database.o config.o
$(CC) $(CFLAGS) -o record $^ $(LIBS)
......@@ -16,6 +17,10 @@ replay: utils.o replay.o
extract_config: extract_config.o
$(CC) $(CFLAGS) -o extract_config $^ $(LIBS)
extract_input_subframe: extract_input_subframe.o database.o event.o utils.o \
config.o
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
textlog: utils.o textlog.o database.o event.o handler.o config.o \
event_selector.o view/view.a gui/gui.a logger/logger.a \
filter/filter.a
......@@ -59,7 +64,7 @@ filter/filter.a:
clean:
rm -f *.o core tracer_remote textlog enb ue vcd record replay
rm -f extract_config macpdu2wireshark
rm -f extract_config macpdu2wireshark extract_input_subframe
cd gui && make clean
cd view && make clean
cd logger && make clean
......
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include "database.h"
#include "event.h"
#include "config.h"
void usage(void)
{
printf(
"usage: [options] <file> <frame> <subframe>\n"
"options:\n"
" -d <database file> this option is mandatory\n"
" -v verbose\n"
);
exit(1);
}
int main(int n, char **v)
{
char *database_filename = NULL;
void *database;
int i;
int input_event_id;
database_event_format f;
char *file = NULL;
int fd;
int frame = -1, subframe = -1;
int frame_arg, subframe_arg, buffer_arg;
int verbose = 0;
for (i = 1; i < n; i++) {
if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage();
if (!strcmp(v[i], "-d"))
{ if (i > n-2) usage(); database_filename = v[++i]; continue; }
if (!strcmp(v[i], "-v")) { verbose = 1; continue; }
if (file == NULL) { file = v[i]; continue; }
if (frame == -1) { frame = atoi(v[i]); continue; }
if (subframe == -1) { subframe = atoi(v[i]); continue; }
usage();
}
if (file == NULL || frame == -1 || subframe == -1) usage();
if (database_filename == NULL) {
printf("ERROR: provide a database file (-d)\n");
exit(1);
}
database = parse_database(database_filename);
load_config_file(database_filename);
input_event_id = event_id_from_name(database, "ENB_PHY_INPUT_SIGNAL");
f = get_format(database, input_event_id);
frame_arg = subframe_arg = buffer_arg = -1;
for (i = 0; i < f.count; i++) {
if (!strcmp(f.name[i], "frame")) {
if (frame_arg != -1) goto err;
if (strcmp(f.type[i], "int")) goto err;
frame_arg = i;
}
if (!strcmp(f.name[i], "subframe")) {
if (subframe_arg != -1) goto err;
if (strcmp(f.type[i], "int")) goto err;
subframe_arg = i;
}
if (!strcmp(f.name[i], "rxdata")) {
if (buffer_arg != -1) goto err;
if (strcmp(f.type[i], "buffer")) goto err;
buffer_arg = i;
}
continue;
err:
printf("cannot deal with ENB_PHY_INPUT_SIGNAL from database file\n");
exit(1);
}
if (frame_arg == -1 || subframe_arg == -1 || buffer_arg == -1) goto err;
fd = open(file, O_RDONLY);
if (fd == -1) { perror(file); exit(1); }
/* get wanted frame/subframe */
while (1) {
char v[T_BUFFER_MAX];
event e;
e = get_event(fd, v, database);
if (e.type == -1) break;
if (e.type != input_event_id) continue;
if (verbose)
printf("input frame %d subframe %d size %d\n",
e.e[frame_arg].i, e.e[subframe_arg].i, e.e[buffer_arg].bsize);
if (!(frame == e.e[frame_arg].i && subframe == e.e[subframe_arg].i))
continue;
#if 0
for (i = 0; i < e.e[buffer_arg].bsize/2; i++) {
short *x = e.e[buffer_arg].b;
x[i] *= 14;
}
#endif
fwrite(e.e[buffer_arg].b, e.e[buffer_arg].bsize, 1, stdout);
fflush(stdout);
return 0;
}
printf("frame %d subframe %d not found\n", frame, subframe);
return 0;
}
......@@ -2176,6 +2176,7 @@ uint8_t get_num_pdcch_symbols(uint8_t num_dci,
// printf("dci_alloc[%d].L = %d\n",i,dci_alloc[i].L);
//}
//exit(-1);
exit(1);
return(0);
}
......
This diff is collapsed.
......@@ -2074,12 +2074,12 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB,
rxptr = (int16_t *)&common_vars->rxdataF[0][aa][symbol_offset];
for (i=0; i<12; i++,j+=2,re_offset++) {
rxcomp[aa][j] = (int16_t)((rxptr[re_offset<<1]*(int32_t)zptr[j])>>15) - ((rxptr[1+(re_offset<<1)]*(int32_t)zptr[1+j])>>15);
rxcomp[aa][1+j] = (int16_t)((rxptr[re_offset<<1]*(int32_t)zptr[1+j])>>15) + ((rxptr[1+(re_offset<<1)]*(int32_t)zptr[j])>>15);
if (re_offset==frame_parms->ofdm_symbol_size)
re_offset = 0;
rxcomp[aa][j] = (int16_t)((rxptr[re_offset<<1]*(int32_t)zptr[j])>>15) - ((rxptr[1+(re_offset<<1)]*(int32_t)zptr[1+j])>>15);
rxcomp[aa][1+j] = (int16_t)((rxptr[re_offset<<1]*(int32_t)zptr[1+j])>>15) + ((rxptr[1+(re_offset<<1)]*(int32_t)zptr[j])>>15);
#ifdef DEBUG_PUCCH_RX
printf("[eNB] PUCCH subframe %d (%d,%d,%d,%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,i,re_offset,m,j,
rxptr[re_offset<<1],rxptr[1+(re_offset<<1)],
......@@ -2153,8 +2153,9 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB,
} //phase
stat_max *= nsymb; // normalize to energy per symbol
stat_max /= (frame_parms->N_RB_UL*12); //
// stat_max *= nsymb; // normalize to energy per symbol
// stat_max /= (frame_parms->N_RB_UL*12); //
stat_max /= (nsymb*12);
#ifdef DEBUG_PUCCH_RX
printf("[eNB] PUCCH: stat %d, stat_max %d, phase_max %d\n", stat,stat_max,phase_max);
#endif
......@@ -2202,7 +2203,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB,
LOG_I(PHY,"Doing PUCCH detection for format 1a/1b\n");
#endif
for (phase=3;phase<4;phase++){ //phase=0; phase<7; phase++) {
for (phase=0; phase<7; phase++) {
stat=0;
for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
......@@ -2339,8 +2340,8 @@ uint32_t rx_pucch(PHY_VARS_eNB *eNB,
off=(re<<1) + (24*l);
tmp_re = ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15);
tmp_im = ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15);
stat_re += (((tmp_re*chest_re)>>15) + ((tmp_im*chest_im)>>15)/4);
stat_im += (((tmp_re*chest_im)>>15) - ((tmp_im*chest_re)>>15)/4);
stat_re += (((tmp_re*chest_re)>>15) + ((tmp_im*chest_im)>>15))/4;
stat_im += (((tmp_re*chest_im)>>15) - ((tmp_im*chest_re)>>15))/4;
off+=2;
#ifdef DEBUG_PUCCH_RX
printf("[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,re,
......
......@@ -165,8 +165,9 @@ typedef enum {
} eNB_func_t;
typedef enum {
synch_to_ext_device=0, // synch to RF or Ethernet device
synch_to_other // synch to another source (timer, other CC_id)
synch_to_ext_device=0, // synch to RF or Ethernet device
synch_to_other, // synch to another source (timer, other CC_id)
synch_to_mobipass_standalone // special case for mobipass in standalone mode
} eNB_timing_t;
#endif
......
......@@ -290,6 +290,30 @@ int get_ue_active_harq_pid(const uint8_t Mod_id,const uint8_t CC_id,const uint16
return(0);
}
int get_ue_rbs(int Mod_id, int CC_id, int rnti, int frame, int subframe, int *start_rb, int *nb_rb)
{
LTE_eNB_ULSCH_t *ULSCH_ptr;
uint8_t ulsch_subframe,ulsch_frame;
int8_t UE_id = find_ue(rnti,PHY_vars_eNB_g[Mod_id][CC_id]);
int harq_pid;
if (UE_id==-1) {
LOG_E(PHY,"Cannot find UE with rnti %x (Mod_id %d, CC_id %d)\n",rnti, Mod_id, CC_id);
return(-1);
}
ULSCH_ptr = PHY_vars_eNB_g[Mod_id][CC_id]->ulsch[(uint32_t)UE_id];
ulsch_subframe = pdcch_alloc2ul_subframe(&PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms,subframe);
ulsch_frame = pdcch_alloc2ul_frame(&PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms,frame,subframe);
harq_pid = subframe2harq_pid(&PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms,
ulsch_frame,
ulsch_subframe);
*nb_rb = ULSCH_ptr->harq_processes[harq_pid]->nb_rb;
*start_rb = ULSCH_ptr->harq_processes[harq_pid]->first_rb;
return(0);
}
int16_t get_target_pusch_rx_power(const module_id_t module_idP, const uint8_t CC_id)
{
return PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.ul_power_control_config_common.p0_NominalPUSCH;
......
......@@ -947,6 +947,8 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
enb_properties.properties[enb_properties_index]->cc_node_timing[j] = synch_to_ext_device;
} else if (strcmp(cc_node_timing, "synch_to_other") == 0) {
enb_properties.properties[enb_properties_index]->cc_node_timing[j] = synch_to_other;
} else if (strcmp(cc_node_timing, "synch_to_mobipass_standalone") == 0) {
enb_properties.properties[enb_properties_index]->cc_node_timing[j] = synch_to_mobipass_standalone;
} else {
AssertError (0, parse_errors ++,
"Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for node_function choice: SYNCH_TO_DEVICE or SYNCH_TO_OTHER !\n",
......
......@@ -1087,7 +1087,13 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
// Allocate CCEs for good after scheduling is done
for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++)
allocate_CCEs(module_idP,CC_id,subframeP,0);
if (allocate_CCEs(module_idP,CC_id,subframeP,0)) {
LOG_D(MAC, "eNB %d CC_id %d frame %d subframe %d: CCE allocation failed\n",
module_idP, CC_id, frameP, subframeP);
printf("eNB %d CC_id %d frame %d subframe %d: CCE allocation failed\n",
module_idP, CC_id, frameP, subframeP);
abort();
}
#if defined(FLEXRAN_AGENT_SB_IF)
#ifndef DISABLE_CONT_STATS
......
......@@ -452,6 +452,7 @@ schedule_ue_spec(
static int32_t tpc_accumulated=0;
UE_sched_ctrl *ue_sched_ctl;
int i;
DCI_PDU saved_DCI_pdu[MAX_NUM_CCs];
#if 0
if (UE_list->head==-1) {
......@@ -462,6 +463,10 @@ schedule_ue_spec(
start_meas(&eNB->schedule_dlsch);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH,VCD_FUNCTION_IN);
/* save DCI_pdu size */
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++)
saved_DCI_pdu[CC_id].Num_dci = eNB->common_channels[CC_id].DCI_pdu.Num_dci;
//weight = get_ue_weight(module_idP,UE_id);
aggregation = 2;
......@@ -496,7 +501,6 @@ schedule_ue_spec(
stop_meas(&eNB->schedule_dlsch_preprocessor);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR,VCD_FUNCTION_OUT);
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
LOG_D(MAC, "doing schedule_ue_spec for CC_id %d\n",CC_id);
......@@ -571,6 +575,18 @@ schedule_ue_spec(
continue;
}
/* add "fake" DCI to have CCE_allocation_infeasible work properly for next allocations */
/* if we don't add it, next allocations may succeed but overall allocations may fail */
/* will be removed at the end of this function */
add_ue_spec_dci(&eNB->common_channels[CC_id].DCI_pdu,
&(char[]){0},
rnti,
1,
aggregation,
1,
format1,
0);
nb_available_rb = ue_sched_ctl->pre_nb_available_rbs[CC_id];
harq_pid = ue_sched_ctl->harq_pid[CC_id];
round = ue_sched_ctl->round[CC_id];
......@@ -632,6 +648,7 @@ schedule_ue_spec(
while((nb_rb_temp > 0) && (j<frame_parms[CC_id]->N_RBG)) {
if(ue_sched_ctl->rballoc_sub_UE[CC_id][j] == 1) {
if (UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j]) printf("WARN: rballoc_subband not free for retrans?\n");
UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = ue_sched_ctl->rballoc_sub_UE[CC_id][j];
if((j == frame_parms[CC_id]->N_RBG-1) &&
......@@ -798,7 +815,7 @@ schedule_ue_spec(
UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1=eNB_UE_stats->dlsch_mcs1;
UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2=eNB_UE_stats->dlsch_mcs1;
} else {
LOG_D(MAC,"[eNB %d] Frame %d CC_id %d : don't schedule UE %d, its retransmission takes more resources than we have\n",
LOG_E(MAC,"[eNB %d] Frame %d CC_id %d : don't schedule UE %d, its retransmission takes more resources than we have\n",
module_idP, frameP, CC_id, UE_id);
}
} else { /* This is a potentially new SDU opportunity */
......@@ -1645,6 +1662,10 @@ schedule_ue_spec(
} // UE_id loop
} // CC_id loop
/* restore DCI_pdu size */
for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++)
eNB->common_channels[CC_id].DCI_pdu.Num_dci = saved_DCI_pdu[CC_id].Num_dci;
stop_meas(&eNB->schedule_dlsch);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SCHEDULE_DLSCH,VCD_FUNCTION_OUT);
......
......@@ -56,6 +56,8 @@
# include "intertask_interface.h"
#endif
#include "T.h"
#define ENABLE_MAC_PAYLOAD_DEBUG
#define DEBUG_eNB_SCHEDULER 1
......@@ -1157,6 +1159,7 @@ boolean_t CCE_allocation_infeasible(int module_idP,
void SR_indication(module_id_t mod_idP, int cc_idP, frame_t frameP, rnti_t rntiP, sub_frame_t subframeP)
{
T(T_ENB_MAC_SCHEDULING_REQUEST, T_INT(mod_idP), T_INT(cc_idP), T_INT(frameP), T_INT(subframeP), T_INT(rntiP));
int UE_id = find_UE_id(mod_idP, rntiP);
UE_list_t *UE_list = &eNB_mac_inst[mod_idP].UE_list;
......
......@@ -670,6 +670,21 @@ void schedule_ulsch(module_id_t module_idP,
}
}
/* TODO: this is a hack to disable scheduling in the PRACH.
* We need to get the information from config/phy/wherever
* as done in the commented code below.
* For the moment, we hardcode for the config used by default.
* Only deals with FDD, PRACH config 0.
*/
LTE_DL_FRAME_PARMS *frame_parms;
frame_parms = mac_xface->get_lte_frame_parms(module_idP,CC_id);
if (frame_parms->frame_type == FDD &&
frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex == 0) {
int frame_ul = (frameP + (subframeP >= 6)) & 1023;
int subframe_ul = (subframeP + 4) % 10;
if ((frame_ul & 1) == 0 && subframe_ul == 1) first_rb[CC_id] = 8;
}
/*
if (mac_xface->is_prach_subframe(&(mac_xface->lte_frame_parms),frameP,subframeP)) {
first_rb[CC_id] = (mac_xface->get_prach_prb_offset(&(mac_xface->lte_frame_parms),
......@@ -677,6 +692,65 @@ void schedule_ulsch(module_id_t module_idP,
}
/* TODO: remove this hack which is to avoid scheduling new uplink where there is a
* retransmission. It increases first_rb to move after the retransmission RBs,
* which can skip a lot of free RBs (say the UE 2 has a retransmission
* in RBs 45..47, we would skip RBs 1..47, but RBs 1..44 are free and
* won't be used for scheduling)
*/
int UE_id;
int rnti;
UE_list_t *UE_list=&eNB->UE_list;
LTE_eNB_UE_stats *eNB_UE_stats = NULL;
int drop_ue=0;
uint8_t harq_pid = 0;
uint8_t round = 0;
int n;
// loop over all UEs
for (UE_id=0; UE_id < NUMBER_OF_UE_MAX; UE_id++) {
rnti = UE_RNTI(module_idP,UE_id);
if (rnti==NOT_A_RNTI) continue;
if (UE_list->UE_template[UE_PCCID(module_idP,UE_id)][UE_id].configured==FALSE) continue;
drop_ue = 0;
for (n=0; n<UE_list->numactiveULCCs[UE_id]; n++) {
CC_id = UE_list->ordered_ULCCids[n][UE_id];
if (mac_xface->get_eNB_UE_stats(module_idP,CC_id,rnti) == NULL) {
drop_ue = 1;
break;
}
}
if (drop_ue == 1) continue;
for (n=0; n<UE_list->numactiveULCCs[UE_id]; n++) {
// This is the actual CC_id in the list
CC_id = UE_list->ordered_ULCCids[n][UE_id];
eNB_UE_stats = mac_xface->get_eNB_UE_stats(module_idP,CC_id,rnti);
if (eNB_UE_stats->mode == PUSCH) { // ue has a ulsch channel
int start_rb;
int nb_rb;
//DCI_pdu = &eNB->common_channels[CC_id].DCI_pdu;
//UE_template = &UE_list->UE_template[CC_id][UE_id];
//UE_sched_ctrl = &UE_list->UE_sched_ctrl[UE_id];
if (mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti,frameP,subframeP,&harq_pid,&round,openair_harq_UL) == -1 ) continue;
int get_ue_rbs(int module_idP, int CC_id, int rnti, int frameP, int subframeP, int *start_rb, int *nb_rb);
if (get_ue_rbs(module_idP,CC_id,rnti,frameP,subframeP,&start_rb,&nb_rb) == -1 ) continue;
if (round > 0)
{
if (start_rb < first_rb[CC_id]) {
LOG_E(MAC, "scheduled retransmission in forbidden RBs\n");
// printf("scheduled retransmission in forbidden RBs\n");
}
if (first_rb[CC_id] < start_rb + nb_rb)
first_rb[CC_id] = start_rb + nb_rb;
}
} // UE is in PUSCH
} // loop over CC
} // loop over UE
schedule_ulsch_rnti(module_idP, cooperation_flag, frameP, subframeP, sched_subframe,first_rb);
#ifdef CBA
......@@ -802,6 +876,13 @@ abort();
module_idP,frameP,subframeP,UE_id,rnti,CC_id, mode_string[eNB_UE_stats->mode], 1<<aggregation);
}
/* be sure that there are some free RBs */
if (first_rb[CC_id] >= frame_parms->N_RB_UL-1) {
LOG_W(MAC,"[eNB %d] frame %d subframe %d, UE %d/%x CC %d mode %s: dropping, not enough RBs\n",
module_idP,frameP,subframeP,UE_id,rnti,CC_id, mode_string[eNB_UE_stats->mode]);
continue;
}
if (eNB_UE_stats->mode == PUSCH) { // ue has a ulsch channel
......@@ -891,9 +972,11 @@ abort();
UE_list->eNB_UE_stats[CC_id][UE_id].ulsch_mcs2=mcs;
// buffer_occupancy = UE_template->ul_total_buffer;
while (((rb_table[rb_table_index]>(frame_parms->N_RB_UL-1-first_rb[CC_id])) ||
(rb_table[rb_table_index]>45)) &&
(rb_table_index>0)) {
while (rb_table_index > 0 &&
(rb_table[rb_table_index] > frame_parms->N_RB_UL-1-first_rb[CC_id] ||
rb_table[rb_table_index]>45 ||
(UE_template->pre_allocated_rb_table_index_ul >= 0 &&
rb_table[rb_table_index] > UE_template->pre_allocated_nb_rb_ul))) {
rb_table_index--;
}
......
......@@ -672,9 +672,12 @@ void dlsch_scheduler_pre_processor (module_id_t Mod_id,
for (ii=0; ii<UE_num_active_CC(UE_list,i); ii++) {
CC_id = UE_list->ordered_CCids[ii][i];
ue_sched_ctl = &UE_list->UE_sched_ctrl[i];
round = ue_sched_ctl->round[CC_id];
// control channel
if (mac_eNB_get_rrc_status(Mod_id,rnti) < RRC_RECONFIGURED) {
// control channel or retransmission
/* TODO: do we have to check for retransmission? */
if (mac_eNB_get_rrc_status(Mod_id,rnti) < RRC_RECONFIGURED || round > 0) {
nb_rbs_required_remaining_1[CC_id][i] = nb_rbs_required[CC_id][i];
} else {
nb_rbs_required_remaining_1[CC_id][i] = cmin(average_rbs_per_user[CC_id],nb_rbs_required[CC_id][i]);
......@@ -696,6 +699,7 @@ void dlsch_scheduler_pre_processor (module_id_t Mod_id,
nb_rbs_required_remaining[CC_id][i] = nb_rbs_required_remaining_1[CC_id][i];
} else { // rb required based only on the buffer - rb allloctaed in the 1st round + extra reaming rb form the 1st round
nb_rbs_required_remaining[CC_id][i] = nb_rbs_required[CC_id][i]-nb_rbs_required_remaining_1[CC_id][i]+nb_rbs_required_remaining[CC_id][i];
if (nb_rbs_required_remaining[CC_id][i]<0) abort();
}
if (nb_rbs_required[CC_id][i]> 0 )
......@@ -901,7 +905,7 @@ void dlsch_scheduler_pre_processor (module_id_t Mod_id,
}
}
#define SF05_LIMIT 1
#define SF0_LIMIT 1
void dlsch_scheduler_pre_processor_reset (int module_idP,
int UE_id,
......@@ -920,10 +924,10 @@ void dlsch_scheduler_pre_processor_reset (int module_idP,
UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
rnti_t rnti = UE_RNTI(module_idP,UE_id);
uint8_t *vrb_map = eNB_mac_inst[module_idP].common_channels[CC_id].vrb_map;
int RBGsize = PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL/N_RBG;
#ifdef SF05_LIMIT
//int subframe05_limit=0;
int sf05_upper=-1,sf05_lower=-1;
int RBGsize;
int RBGsize_last;
#ifdef SF0_LIMIT
int sf0_upper=-1,sf0_lower=-1;
#endif
LTE_eNB_UE_stats *eNB_UE_stats = mac_xface->get_eNB_UE_stats(module_idP,CC_id,rnti);
if (eNB_UE_stats == NULL) return;
......@@ -986,44 +990,60 @@ void dlsch_scheduler_pre_processor_reset (int module_idP,
ue_sched_ctl->dl_pow_off[CC_id] = 2;
nb_rbs_required_remaining[CC_id][UE_id] = 0;
#ifdef SF05_LIMIT
switch (PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL) {
case 6: RBGsize = 1; RBGsize_last = 1; break;
case 15: RBGsize = 2; RBGsize_last = 1; break;
case 25: RBGsize = 2; RBGsize_last = 1; break;
case 50: RBGsize = 3; RBGsize_last = 2; break;
case 75: RBGsize = 4; RBGsize_last = 3; break;
case 100: RBGsize = 4; RBGsize_last = 4; break;
default: printf("unsupported RBs (%d)\n", PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL); fflush(stdout); abort();
}
#ifdef SF0_LIMIT
switch (N_RBG) {
case 6:
sf05_lower=0;
sf05_upper=5;
sf0_lower=0;
sf0_upper=5;
break;
case 8:
sf05_lower=2;
sf05_upper=5;
sf0_lower=2;
sf0_upper=5;
break;
case 13:
sf05_lower=4;
sf05_upper=7;
sf0_lower=4;
sf0_upper=7;
break;
case 17:
sf05_lower=7;
sf05_upper=9;
sf0_lower=7;
sf0_upper=9;
break;
case 25:
sf05_lower=11;
sf05_upper=13;
sf0_lower=11;
sf0_upper=13;
break;
default: printf("unsupported RBs (%d)\n", PHY_vars_eNB_g[module_idP][CC_id]->frame_parms.N_RB_DL); fflush(stdout); abort();
}
#endif
// Initialize Subbands according to VRB map
for (i=0; i<N_RBG; i++) {
int rb_size = i==N_RBG-1 ? RBGsize_last : RBGsize;
ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 0;
rballoc_sub[CC_id][i] = 0;
#ifdef SF05_LIMIT
// for avoiding 6+ PRBs around DC in subframe 0-5 (avoid excessive errors)
if ((subframeP==0 || subframeP==5) &&
(i>=sf05_lower && i<=sf05_upper))
#ifdef SF0_LIMIT
// for avoiding 6+ PRBs around DC in subframe 0 (avoid excessive errors)
/* TODO: make it proper - allocate those RBs, do not "protect" them, but
* compute number of available REs and limit MCS according to the
* TBS table 36.213 7.1.7.2.1-1 (can be done after pre-processor)
*/
if (subframeP==0 &&
i >= sf0_lower && i <= sf0_upper)
rballoc_sub[CC_id][i]=1;
#endif
// for SI-RNTI,RA-RNTI and P-RNTI allocations
for (j=0;j<RBGsize;j++) {
if (vrb_map[j+(i*RBGsize)]!=0) {
for (j = 0; j < rb_size; j++) {
if (vrb_map[j+(i*RBGsize)] != 0) {
rballoc_sub[CC_id][i] = 1;
LOG_D(MAC,"Frame %d, subframe %d : vrb %d allocated\n",frameP,subframeP,j+(i*RBGsize));
break;
......@@ -1063,14 +1083,16 @@ void dlsch_scheduler_pre_processor_allocate (module_id_t Mod_id,
if (ue_sched_ctl->dl_pow_off[CC_id] != 0 ) {
if ((i == N_RBG-1) && ((N_RB_DL == 25) || (N_RB_DL == 50))) {
rballoc_sub[CC_id][i] = 1;
ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1;
MIMO_mode_indicator[CC_id][i] = 1;
if (transmission_mode == 5 ) {
ue_sched_ctl->dl_pow_off[CC_id] = 1;
}
nb_rbs_required_remaining[CC_id][UE_id] = nb_rbs_required_remaining[CC_id][UE_id] - min_rb_unit+1;
ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit - 1;
if (nb_rbs_required_remaining[CC_id][UE_id] >= min_rb_unit-1){
rballoc_sub[CC_id][i] = 1;
ue_sched_ctl->rballoc_sub_UE[CC_id][i] = 1;
MIMO_mode_indicator[CC_id][i] = 1;
if (transmission_mode == 5 ) {
ue_sched_ctl->dl_pow_off[CC_id] = 1;
}
nb_rbs_required_remaining[CC_id][UE_id] = nb_rbs_required_remaining[CC_id][UE_id] - min_rb_unit+1;
ue_sched_ctl->pre_nb_available_rbs[CC_id] = ue_sched_ctl->pre_nb_available_rbs[CC_id] + min_rb_unit - 1;
}
} else {
if (nb_rbs_required_remaining[CC_id][UE_id] >= min_rb_unit){
rballoc_sub[CC_id][i] = 1;
......@@ -1086,7 +1108,6 @@ void dlsch_scheduler_pre_processor_allocate (module_id_t Mod_id,
} // dl_pow_off[CC_id][UE_id] ! = 0
}
}
}
......@@ -1335,6 +1356,8 @@ void assign_max_mcs_min_rb(module_id_t module_idP,int frameP, sub_frame_t subfra
// if this UE has UL traffic
if (UE_template->ul_total_buffer > 0 ) {
/* start with 3 RB => rb_table_index = 2 */
rb_table_index = 2;
tbs = mac_xface->get_TBS_UL(mcs,3); // 1 or 2 PRB with cqi enabled does not work well!
// fixme: set use_srs flag
tx_power= mac_xface->estimate_ue_tx_power(tbs,rb_table[rb_table_index],0,frame_parms->Ncp,0);
......@@ -1378,8 +1401,15 @@ void assign_max_mcs_min_rb(module_id_t module_idP,int frameP, sub_frame_t subfra
UE_template->pre_allocated_nb_rb_ul,
UE_template->phr_info,tx_power);
} else {
UE_template->pre_allocated_rb_table_index_ul=-1;
UE_template->pre_allocated_nb_rb_ul=0;
/* if UE has pending scheduling request then pre-allocate 3 RBs */
//if (UE_template->ul_active == 1 && UE_template->ul_SR == 1) {
if (UE_is_to_be_scheduled(module_idP, CC_id, i)) {
UE_template->pre_allocated_rb_table_index_ul = 2;
UE_template->pre_allocated_nb_rb_ul = 3;
} else {
UE_template->pre_allocated_rb_table_index_ul=-1;
UE_template->pre_allocated_nb_rb_ul=0;
}
}
}
}
......
......@@ -1680,7 +1680,7 @@ do_RRCConnectionSetup(
// SchedulingRequestConfig
physicalConfigDedicated2->schedulingRequestConfig->present = SchedulingRequestConfig_PR_setup;
physicalConfigDedicated2->schedulingRequestConfig->choice.setup.sr_PUCCH_ResourceIndex = 3;//ue_context_pP->local_uid;
physicalConfigDedicated2->schedulingRequestConfig->choice.setup.sr_PUCCH_ResourceIndex = 71 - ue_context_pP->local_uid/10;//ue_context_pP->local_uid;
if (frame_parms->frame_type == 0) { // FDD
physicalConfigDedicated2->schedulingRequestConfig->choice.setup.sr_ConfigIndex = 5+(ue_context_pP->local_uid%10); // Isr = 5 (every 10 subframes, offset=2+UE_id mod3)
......
......@@ -175,16 +175,16 @@ const char* eurecomVariablesNames[] = {
"ue0_SFN5",
"ue0_SFN6",
"ue0_SFN7",
"send_if4_symbol",
"recv_if4_symbol",
"send_if5_pkt_id",
"recv_if5_pkt_id",
"ue_pdcp_flush_size",
"ue_pdcp_flush_err",
"ue0_trx_read_ns",
"ue0_trx_write_ns",
"ue0_trx_read_ns_missing",
"ue0_trx_write_ns_missing"
"send_if4_symbol",
"recv_if4_symbol",
"send_if5_pkt_id",
"recv_if5_pkt_id"
"ue0_trx_write_ns_missing",
};
const char* eurecomFunctionsNames[] = {
......@@ -382,10 +382,10 @@ const char* eurecomFunctionsNames[] = {
"recv_if5",
"compress_if",
"decompress_if"
"decompress_if",
};
struct vcd_module_s vcd_modules[VCD_SIGNAL_DUMPER_MODULE_END] = {
struct vcd_module_s vcd_modules[] = {
{ "variables", VCD_SIGNAL_DUMPER_VARIABLES_END, eurecomVariablesNames, VCD_WIRE, 64 },
{ "functions", VCD_SIGNAL_DUMPER_FUNCTIONS_END, eurecomFunctionsNames, VCD_WIRE, 1 },
// { "ue_procedures_functions", VCD_SIGNAL_DUMPER_UE_PROCEDURES_FUNCTIONS_END, eurecomUEFunctionsNames, VCD_WIRE, 1 },
......@@ -686,7 +686,7 @@ void vcd_signal_dumper_create_header(void)
fprintf(vcd_fd, "$timescale 1 ns $end\n");
/* Initialize each module definition */
for(i = 0; i < VCD_SIGNAL_DUMPER_MODULE_END; i++) {
for(i = 0; i < sizeof(vcd_modules) / sizeof(struct vcd_module_s); i++) {
struct vcd_module_s *module;
module = &vcd_modules[i];
fprintf(vcd_fd, "$scope module %s $end\n", module->name);
......@@ -711,7 +711,7 @@ void vcd_signal_dumper_create_header(void)
/* Init variables and functions to 0 */
fprintf(vcd_fd, "$dumpvars\n");
for(i = 0; i < VCD_SIGNAL_DUMPER_MODULE_END; i++) {
for(i = 0; i < sizeof(vcd_modules) / sizeof(struct vcd_module_s); i++) {
struct vcd_module_s *module;
module = &vcd_modules[i];
......
......@@ -157,8 +157,7 @@ typedef enum {
VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_WRITE_NS,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_READ_NS_MISSING,
VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_WRITE_NS_MISSING,
VCD_SIGNAL_DUMPER_VARIABLES_LAST,
VCD_SIGNAL_DUMPER_VARIABLES_END = VCD_SIGNAL_DUMPER_VARIABLES_LAST,
VCD_SIGNAL_DUMPER_VARIABLES_END
} vcd_signal_dump_variables;
typedef enum {
......@@ -361,8 +360,7 @@ typedef enum {
VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_COMPR_IF,
VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_DECOMPR_IF,
VCD_SIGNAL_DUMPER_FUNCTIONS_LAST,
VCD_SIGNAL_DUMPER_FUNCTIONS_END = VCD_SIGNAL_DUMPER_FUNCTIONS_LAST,
VCD_SIGNAL_DUMPER_FUNCTIONS_END
} vcd_signal_dump_functions;
typedef enum {
......@@ -371,8 +369,6 @@ typedef enum {
VCD_SIGNAL_DUMPER_MODULE_VARIABLES,
VCD_SIGNAL_DUMPER_MODULE_FUNCTIONS,
// VCD_SIGNAL_DUMPER_MODULE_UE_PROCEDURES_FUNCTIONS,
VCD_SIGNAL_DUMPER_MODULE_LAST,
VCD_SIGNAL_DUMPER_MODULE_END = VCD_SIGNAL_DUMPER_MODULE_LAST,
} vcd_signal_dumper_modules;
typedef enum {
......
......@@ -142,7 +142,9 @@ typedef enum {
//! This tells the underlying hardware to use the internal reference
internal=0,
//! This tells the underlying hardware to use the external reference
external=1
external=1,
//! This tells the underlying hardware to use the gpsdo reference
gpsdo=2
} clock_source_t;
/*! \brief RF frontend parameters set by application */
......
/*
* 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.0 (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 <arpa/inet.h>
#include <linux/if_packet.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/ether.h>
#include <unistd.h>
#include <errno.h>
#include <linux/sysctl.h>
#include <sys/sysctl.h>
#include "common_lib.h"
#include "ethernet_lib.h"
#include "mobipass.h"
#include "queues.h"
struct mobipass_header {
uint16_t flags;
uint16_t fifo_status;
unsigned char seqno;
unsigned char ack;
uint32_t word0;
uint32_t timestamp;
} __attribute__((__packed__));
int mobipass_start(openair0_device *device) { init_mobipass(device->priv); return 0; }
int mobipass_request(openair0_device *device, void *msg, ssize_t msg_len) { abort(); return 0; }
int mobipass_reply(openair0_device *device, void *msg, ssize_t msg_len) { abort(); return 0; }
int mobipass_get_stats(openair0_device* device) { return 0; }
int mobipass_reset_stats(openair0_device* device) { return 0; }
void mobipass_end(openair0_device *device) {}
int mobipass_stop(openair0_device *device) { return 0; }
int mobipass_set_freq(openair0_device* device, openair0_config_t *openair0_cfg,int exmimo_dump_config) { return 0; }
int mobipass_set_gains(openair0_device* device, openair0_config_t *openair0_cfg) { return 0; }
int mobipass_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
mobipass_state_t *mobi = device->priv;
struct mobipass_header *mh = (struct mobipass_header *)(((char *)buff[0]) + 14);
mobi->mobipass_write_last_timestamp += 640;
mobi->mobipass_write_last_timestamp %= mobi->samples_per_1024_frames;
mh->timestamp = htonl(ntohl(mh->timestamp) % mobi->samples_per_1024_frames);
if (mobi->mobipass_write_last_timestamp != ntohl(mh->timestamp))
{ printf("mobipass: ERROR: bad timestamp wanted %d got %d\n", mobi->mobipass_write_last_timestamp, ntohl(mh->timestamp)); exit(1); }
//printf("__write nsamps %d timestamps %ld seqno %d (packet timestamp %d)\n", nsamps, timestamp, mh->seqno, ntohl(mh->timestamp));
if (nsamps != 640) abort();
enqueue_to_mobipass(mobi->qstate, buff[0]);
return nsamps;
}
int mobipass_read(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) {
mobipass_state_t *mobi = device->priv;
//printf("__read nsamps %d return timestamp %d\n", nsamps, ts);
*timestamp = htonl(mobi->mobipass_read_ts);
mobi->mobipass_read_ts += nsamps;
mobi->mobipass_read_ts %= mobi->samples_per_1024_frames;
if (nsamps != 640) { printf("mobipass: ERROR: bad nsamps %d, should be 640\n", nsamps); fflush(stdout); abort(); }
dequeue_from_mobipass(mobi->qstate, ntohl(*timestamp), buff[0]);
#if 1
struct mobipass_header *mh = (struct mobipass_header *)(((char *)buff[0]) + 14);
mh->flags = 0;
mh->fifo_status = 0;
mh->seqno = mobi->mobipass_read_seqno++;
mh->ack = 0;
mh->word0 = 0;
mh->timestamp = htonl(mobi->mobipass_read_ts);
#endif
return nsamps;
}
/* this is the only function in the library that is visible from outside
* because in CMakeLists.txt we use -fvisibility=hidden
*/
__attribute__((__visibility__("default")))
int transport_init(openair0_device *device, openair0_config_t *openair0_cfg,
eth_params_t * eth_params )
{
//init_mobipass();
mobipass_state_t *mobi = (mobipass_state_t*)malloc(sizeof(mobipass_state_t));
memset(mobi, 0, sizeof(mobipass_state_t));
if (eth_params->transp_preference != 4) goto err;
if (eth_params->if_compress != 0) goto err;
/* only 50 PRBs handled for the moment */
if (openair0_cfg[0].sample_rate != 15360000) {
printf("mobipass: ERROR: only 50 PRBs supported\n");
exit(1);
}
mobi->eth.flags = ETH_RAW_IF5_MOBIPASS;
mobi->eth.compression = NO_COMPRESS;
device->Mod_id = 0;//num_devices_eth++;
device->transp_type = ETHERNET_TP;
device->trx_start_func = mobipass_start;
device->trx_request_func = mobipass_request;
device->trx_reply_func = mobipass_reply;
device->trx_get_stats_func = mobipass_get_stats;
device->trx_reset_stats_func = mobipass_reset_stats;
device->trx_end_func = mobipass_end;
device->trx_stop_func = mobipass_stop;
device->trx_set_freq_func = mobipass_set_freq;
device->trx_set_gains_func = mobipass_set_gains;
device->trx_write_func = mobipass_write;
device->trx_read_func = mobipass_read;
device->priv = mobi;
mobi->eth.if_name = strdup(eth_params->local_if_name);
if (mobi->eth.if_name == NULL) abort();
if (sscanf(eth_params->my_addr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
&mobi->eth_local[0],
&mobi->eth_local[1],
&mobi->eth_local[2],
&mobi->eth_local[3],
&mobi->eth_local[4],
&mobi->eth_local[5]) != 6) {
printf("mobipass: ERROR: bad local ethernet address '%s', check configuration file\n",
eth_params->my_addr);
exit(1);
}
if (sscanf(eth_params->remote_addr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
&mobi->eth_remote[0],
&mobi->eth_remote[1],
&mobi->eth_remote[2],
&mobi->eth_remote[3],
&mobi->eth_remote[4],
&mobi->eth_remote[5]) != 6) {
printf("mobipass: ERROR: bad remote ethernet address '%s', check configuration file\n",
eth_params->remote_addr);
exit(1);
}
/* note: this only works for 50 PRBs */
mobi->samples_per_1024_frames = 7680*2*10*1024;
/* TX starts at subframe 4, let's pretend we are at the right position */
/* note: this only works for 50 PRBs */
mobi->mobipass_write_last_timestamp = 4*7680*2-640;
/* device specific */
openair0_cfg[0].iq_rxrescale = 15;//rescale iqs
openair0_cfg[0].iq_txshift = eth_params->iq_txshift;// shift
openair0_cfg[0].tx_sample_advance = eth_params->tx_sample_advance;
/* this is useless, I think */
if (device->host_type == BBU_HOST) {
/*Note scheduling advance values valid only for case 7680000 */
switch ((int)openair0_cfg[0].sample_rate) {
case 30720000:
openair0_cfg[0].samples_per_packet = 3840;
break;
case 23040000:
openair0_cfg[0].samples_per_packet = 2880;
break;
case 15360000:
openair0_cfg[0].samples_per_packet = 1920;
break;
case 7680000:
openair0_cfg[0].samples_per_packet = 960;
break;
case 1920000:
openair0_cfg[0].samples_per_packet = 240;
break;
default:
printf("mobipass: ERROR: unknown sampling rate %f\n",openair0_cfg[0].sample_rate);
exit(-1);
break;
}
}
device->openair0_cfg=&openair0_cfg[0];
return 0;
err:
printf("mobipass: ERROR: bad configuration file?\n");
exit(1);
}
/*
* 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.0 (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 <stdlib.h>
#include <string.h>
#include <net/if.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#include <linux/if_packet.h>
#include <netinet/ether.h>
#include <unistd.h>
#include <pthread.h>
#include "queues.h"
#include "mobipass.h"
/******************************************************************/
/* time begin */
/******************************************************************/
#include <time.h>
static void init_time(mobipass_state_t *mobi)
{
struct timespec now;
if (clock_gettime(CLOCK_MONOTONIC_RAW, &now)) abort();
mobi->t0 = (uint64_t)now.tv_sec * (uint64_t)1000000000 + (uint64_t)now.tv_nsec;
}
/* called before sending data to mobipass
* waits if called too early with respect to system clock
* does not wait more than 1ms in any case
*/
static void synch_time(mobipass_state_t *mobi, uint32_t ts)
{
if (ts < mobi->synch_time_last_ts) mobi->synch_time_mega_ts++;
mobi->synch_time_last_ts = ts;
struct timespec now;
if (clock_gettime(CLOCK_MONOTONIC_RAW, &now)) abort();
uint64_t tnow;
tnow = (uint64_t)now.tv_sec * (uint64_t)1000000000 + (uint64_t)now.tv_nsec;
uint64_t cur = tnow - mobi->t0;
/* 15360000 samples/second, in nanoseconds:
* = 15360000 / 1000000000 = 1536 / 100000 = 48 / 3125*/
uint64_t ts_ns = ((uint64_t)ts + mobi->synch_time_mega_ts * (uint64_t)mobi->samples_per_1024_frames) * (uint64_t)3125 / (uint64_t)48;
/* TODO: if cur is way higher than ts_ns, we are very late, log something? */
if (cur >= ts_ns) return;
uint64_t delta = ts_ns - cur;
/* don't sleep more than 1 ms */
if (delta > 1000*1000) delta = 1000*1000;
delta = delta/1000;
if (delta) usleep(delta);
}
/******************************************************************/
/* time end */
/******************************************************************/
struct ethernet_header {
unsigned char dst[6];
unsigned char src[6];
uint16_t packet_type;
} __attribute__((__packed__));
struct mobipass_header {
uint16_t flags;
uint16_t fifo_status;
unsigned char seqno;
unsigned char ack;
uint32_t word0;
uint32_t timestamp;
} __attribute__((__packed__));
static void do_receive(mobipass_state_t *mobi, unsigned char *b)
{
if (recv(mobi->sock, b, 14+14+1280, 0) != 14+14+1280) { perror("recv"); exit(1); }
struct mobipass_header *mh = (struct mobipass_header *)(b+14);
mh->timestamp = htonl((ntohl(mh->timestamp)-45378/*40120*/) % mobi->samples_per_1024_frames);
//printf("recv timestamp %u\n", ntohl(mh->timestamp));
}
/* receiver thread */
static void *receiver(void *_mobi)
{
mobipass_state_t *mobi = _mobi;
unsigned char receive_packet[14 + 14 + 1280];
while (1) {
do_receive(mobi, receive_packet);
enqueue_from_mobipass(mobi->qstate, receive_packet);
}
return 0;
}
static void do_send(mobipass_state_t *mobi, int seqno, uint32_t ts,
unsigned char *packet)
{
struct ethernet_header *eh = (struct ethernet_header *)packet;
struct mobipass_header *mh = (struct mobipass_header *)(packet+14);
ts %= mobi->samples_per_1024_frames;
//printf("SEND seqno %d ts %d\n", seqno, ts);
memcpy(eh->dst, mobi->eth_remote, 6);
memcpy(eh->src, mobi->eth_local, 6);
eh->packet_type = htons(0xbffe);
mh->flags = 0;
mh->fifo_status = 0;
mh->seqno = seqno;
mh->ack = 0;
mh->word0 = 0;
mh->timestamp = htonl(ts);
synch_time(mobi, ts);
if (send(mobi->sock, packet, 14+14+1280, 0) != 14+14+1280) { perror("send"); exit(1); }
}
/* sender thread */
static void *sender(void *_mobi)
{
mobipass_state_t *mobi = _mobi;
unsigned char packet[14 + 14 + 1280];
uint32_t ts = 0;
unsigned char seqno = 0;
while (1) {
dequeue_to_mobipass(mobi->qstate, ts, packet);
do_send(mobi, seqno, ts, packet);
seqno++;
ts += 640;
ts %= mobi->samples_per_1024_frames;
}
return 0;
}
static void new_thread(void *(*f)(void *), void *data)
{
pthread_t t;
pthread_attr_t att;
if (pthread_attr_init(&att))
{ fprintf(stderr, "pthread_attr_init err\n"); exit(1); }
if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED))
{ fprintf(stderr, "pthread_attr_setdetachstate err\n"); exit(1); }
if (pthread_attr_setstacksize(&att, 10000000))
{ fprintf(stderr, "pthread_attr_setstacksize err\n"); exit(1); }
if (pthread_create(&t, &att, f, data))
{ fprintf(stderr, "pthread_create err\n"); exit(1); }
if (pthread_attr_destroy(&att))
{ fprintf(stderr, "pthread_attr_destroy err\n"); exit(1); }
}
void init_mobipass(mobipass_state_t *mobi)
{
int i;
unsigned char data[14+14+640];
memset(data, 0, 14+14+640);
init_time(mobi);
mobi->qstate = init_queues(mobi->samples_per_1024_frames);
for (i = 0; i < 24*4; i++) {
uint32_t timestamp = i*640;
unsigned char seqno = i;
struct mobipass_header *mh = (struct mobipass_header *)(data+14);
mh->seqno = seqno;
mh->timestamp = htonl(timestamp);
enqueue_to_mobipass(mobi->qstate, data);
}
mobi->sock = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW);
if (mobi->sock == -1) { perror("socket"); exit(1); }
/* get if index */
struct ifreq if_index;
memset(&if_index, 0, sizeof(struct ifreq));
strcpy(if_index.ifr_name, mobi->eth.if_name);
if (ioctl(mobi->sock, SIOCGIFINDEX, &if_index)<0) {perror("SIOCGIFINDEX");exit(1);}
struct sockaddr_ll local_addr;
local_addr.sll_family = AF_PACKET;
local_addr.sll_ifindex = if_index.ifr_ifindex;
local_addr.sll_protocol = htons(0xbffe);
local_addr.sll_halen = ETH_ALEN;
local_addr.sll_pkttype = PACKET_OTHERHOST;
if (bind(mobi->sock, (struct sockaddr *)&local_addr, sizeof(struct sockaddr_ll))<0)
{ perror("bind"); exit(1); }
new_thread(receiver, mobi);
new_thread(sender, mobi);
}
/*
* 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.0 (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 _MOBIPASS_H_
#define _MOBIPASS_H_
#include <stdint.h>
#include "ethernet_lib.h"
typedef struct {
/* this has to come first */
eth_state_t eth;
void *qstate;
uint8_t eth_local[6];
uint8_t eth_remote[6];
int samples_per_1024_frames;
/* variables used by the function interface.c:mobipass_read */
uint32_t mobipass_read_ts;
unsigned char mobipass_read_seqno;
/* variables used by the function interface.c:mobipass_write */
uint32_t mobipass_write_last_timestamp;
/* variables used by the function mobipass.c:[init_time|synch_time] */
uint64_t t0;
/* variables used by the function mobipass.c:synch_time */
uint32_t synch_time_last_ts;
uint64_t synch_time_mega_ts;
/* sock is used in mobipass.c */
int sock;
} mobipass_state_t;
void init_mobipass(mobipass_state_t *mobi);
#endif /* _MOBIPASS_H_ */
/*
* 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.0 (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 "queues.h"
#include "mobipass.h"
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <sys/time.h>
#define QSIZE 10000
struct mobipass_header {
uint16_t flags;
uint16_t fifo_status;
unsigned char seqno;
unsigned char ack;
uint32_t word0;
uint32_t timestamp;
} __attribute__((__packed__));
struct queue {
unsigned char buf[QSIZE][14+14+640*2];
volatile int start;
volatile int len;
pthread_mutex_t mutex;
pthread_cond_t cond;
};
typedef struct {
struct queue to_mobipass;
struct queue from_mobipass;
int samples_per_1024_frames;
/* variables used by dequeue_from_mobipass */
int dequeue_from_mobipass_seqno;
/* variables used to manage logging of "missing samples"
* coming from mobipass. (Yes, this can happen, mostly
* at startup.)
* This idea is to print some logs, but not too much to
* flood stdout. (This is already a bad idea to call
* printf in a 'realtime' thread.)
*/
int no_sample_log_running;
uint32_t no_sample_log_start_sample;
uint32_t no_sample_log_next_sample;
} queue_state_t;
static void enqueue(void *data, struct queue *q)
{
int pos;
if (pthread_mutex_lock(&q->mutex)) abort();
if (q->len == QSIZE) {
printf("mobipass: WARNING: enqueue: full\n");
goto done;
}
pos = (q->start + q->len) % QSIZE;
memcpy(q->buf[pos], data, 14+14+640*2);
q->len++;
done:
if (pthread_cond_signal(&q->cond)) abort();
if (pthread_mutex_unlock(&q->mutex)) abort();
}
void enqueue_to_mobipass(void *_qstate, void *data)
{
queue_state_t *qstate = _qstate;
enqueue(data, &qstate->to_mobipass);
}
void dequeue_to_mobipass(void *_qstate, uint32_t timestamp, void *data)
{
queue_state_t *qstate = _qstate;
if (pthread_mutex_lock(&qstate->to_mobipass.mutex)) abort();
while (qstate->to_mobipass.len == 0) {
if (pthread_cond_wait(&qstate->to_mobipass.cond, &qstate->to_mobipass.mutex)) abort();
}
memcpy(data, qstate->to_mobipass.buf[qstate->to_mobipass.start], 14+14+640*2);
qstate->to_mobipass.len--;
qstate->to_mobipass.start = (qstate->to_mobipass.start + 1) % QSIZE;
if (pthread_mutex_unlock(&qstate->to_mobipass.mutex)) abort();
}
void enqueue_from_mobipass(void *_qstate, void *data)
{
queue_state_t *qstate = _qstate;
struct mobipass_header *mh = (struct mobipass_header *)((char*)data+14);
mh->timestamp = htonl(ntohl(mh->timestamp) % qstate->samples_per_1024_frames);
//printf("from mobipass! timestamp %u seqno %d\n", ntohl(mh->timestamp), mh->seqno);
enqueue(data, &qstate->from_mobipass);
}
static int cmp_timestamps(uint32_t a, uint32_t b, int samples_per_1024_frames)
{
if (a == b) return 0;
if (a < b) {
if (b-a > samples_per_1024_frames/2) return 1;
return -1;
}
if (a-b > samples_per_1024_frames/2) return -1;
return 1;
}
/*************************************************/
/* missing samples logging management begin */
/*************************************************/
static void log_flush(queue_state_t *qstate)
{
/* print now if there is something to print */
if (qstate->no_sample_log_running == 0)
return;
qstate->no_sample_log_running = 0;
printf("mobipass: WARNING: missing samples [%u-%u]\n",
qstate->no_sample_log_start_sample,
(uint32_t)(qstate->no_sample_log_next_sample-1));
}
static void log_missed_sample(queue_state_t *qstate, uint32_t timestamp)
{
/* collect data, print if there is a discontinuity */
if (qstate->no_sample_log_running == 0 ||
timestamp != qstate->no_sample_log_next_sample) {
log_flush(qstate);
qstate->no_sample_log_start_sample = timestamp;
}
qstate->no_sample_log_next_sample = timestamp+1;
qstate->no_sample_log_running = 1;
}
static void log_flush_if_old(queue_state_t *qstate, uint32_t timestamp)
{
/* log every second (more or less), if we have to */
/* note that if mobipass stopped, it may take much more
* than one second to log, due to the sleeps done while
* waiting for samples (that never come)
*/
if (qstate->no_sample_log_running == 1 &&
labs(timestamp-qstate->no_sample_log_start_sample) > qstate->samples_per_1024_frames/10)
log_flush(qstate);
}
/*************************************************/
/* missing samples logging management end */
/*************************************************/
/* to be called with lock on */
static void get_sample_from_mobipass(queue_state_t *qstate, char *I, char *Q, uint32_t timestamp)
{
unsigned char *b = NULL;
unsigned char *data = NULL;
struct mobipass_header *mh = NULL;
uint32_t packet_timestamp = 0;
#if 0
uint32_t old_start = qstate->from_mobipass.start;
uint32_t old_len = qstate->from_mobipass.len;
b = qstate->from_mobipass.buf[qstate->from_mobipass.start];
mh = (struct mobipass_header *)(b+14);
uint32_t old_pts = qstate->from_mobipass.len ? ntohl(mh->timestamp) : -1;
b=NULL;
mh=NULL;
#endif
while (qstate->from_mobipass.len) {
b = qstate->from_mobipass.buf[qstate->from_mobipass.start];
mh = (struct mobipass_header *)(b+14);
data = b + 14*2;
packet_timestamp = ntohl(mh->timestamp);
if (cmp_timestamps(timestamp, packet_timestamp, qstate->samples_per_1024_frames) < 0) goto nodata;
if (cmp_timestamps(timestamp, (packet_timestamp+640) % qstate->samples_per_1024_frames, qstate->samples_per_1024_frames) < 0) break;
qstate->from_mobipass.len--;
qstate->from_mobipass.start = (qstate->from_mobipass.start+1) % QSIZE;
}
if (qstate->from_mobipass.len == 0) goto nodata;
if (timestamp == (packet_timestamp + 639) % qstate->samples_per_1024_frames) {
qstate->from_mobipass.len--;
qstate->from_mobipass.start = (qstate->from_mobipass.start+1) % QSIZE;
}
if (timestamp < packet_timestamp) timestamp += qstate->samples_per_1024_frames;
*I = data[(timestamp - packet_timestamp) * 2];
*Q = data[(timestamp - packet_timestamp) * 2 + 1];
return;
nodata:
*I = 0;
*Q = 0;
log_missed_sample(qstate, timestamp);
#if 0
printf("no sample timestamp %u pt %u start %d old_start %d old_pt %u len %d old len %d\n", timestamp, packet_timestamp, qstate->from_mobipass.start, old_start, old_pts, qstate->from_mobipass.len, old_len);
#endif
}
/* doesn't work with delay more than 1s */
static void wait_for_data(pthread_cond_t *cond, pthread_mutex_t *mutex, int delay_us)
{
struct timeval now;
struct timespec target;
gettimeofday(&now, NULL);
target.tv_sec = now.tv_sec;
target.tv_nsec = (now.tv_usec + delay_us) * 1000;
if (target.tv_nsec >= 1000 * 1000 * 1000) { target.tv_nsec -= 1000 * 1000 * 1000; target.tv_sec++; }
int err = pthread_cond_timedwait(cond, mutex, &target);
if (err != 0 && err != ETIMEDOUT) { printf("mobipass: ERROR: pthread_cond_timedwait: err (%d) %s\n", err, strerror(err)); abort(); }
}
/* don't block infinitely when waiting for data
* if waiting for too long, just return some zeros
*/
void dequeue_from_mobipass(void *_qstate, uint32_t timestamp, void *data)
{
queue_state_t *qstate = _qstate;
int i;
// int ts = timestamp;
int waiting_allowed;
if (pthread_mutex_lock(&qstate->from_mobipass.mutex)) abort();
if (qstate->from_mobipass.len == 0) {
//printf("sleep 1\n");
wait_for_data(&qstate->from_mobipass.cond, &qstate->from_mobipass.mutex, 2000); //1000/3);
}
waiting_allowed = qstate->from_mobipass.len != 0;
for (i = 0; i < 640*2; i+=2) {
if (qstate->from_mobipass.len == 0 && waiting_allowed) {
//printf("sleep 2\n");
wait_for_data(&qstate->from_mobipass.cond, &qstate->from_mobipass.mutex, 2000); //1000/3);
waiting_allowed = qstate->from_mobipass.len != 0;
}
get_sample_from_mobipass(qstate, (char*)data + 14*2 + i, (char*)data + 14*2 + i+1, timestamp % qstate->samples_per_1024_frames);
timestamp++;
}
log_flush_if_old(qstate, timestamp);
if (pthread_mutex_unlock(&qstate->from_mobipass.mutex)) abort();
struct mobipass_header *mh = (struct mobipass_header *)(((char *)data) + 14);
mh->flags = 0;
mh->fifo_status = 0;
mh->seqno = qstate->dequeue_from_mobipass_seqno++;
mh->ack = 0;
mh->word0 = 0;
mh->timestamp = htonl(timestamp);
}
void *init_queues(int samples_per_1024_frames)
{
queue_state_t *q;
q = malloc(sizeof(queue_state_t));
if (q == NULL) abort();
memset(q, 0, sizeof(queue_state_t));
if (pthread_mutex_init(&q->to_mobipass.mutex, NULL)) abort();
if (pthread_mutex_init(&q->from_mobipass.mutex, NULL)) abort();
if (pthread_cond_init(&q->to_mobipass.cond, NULL)) abort();
if (pthread_cond_init(&q->from_mobipass.cond, NULL)) abort();
q->samples_per_1024_frames = samples_per_1024_frames;
return q;
}
/*
* 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.0 (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 _QUEUES_H_
#define _QUEUES_H_
#include <stdint.h>
void enqueue_to_mobipass(void *qstate, void *data);
void dequeue_to_mobipass(void *qstate, uint32_t timestamp, void *data);
void enqueue_from_mobipass(void *qstate, void *receive_packet);
void dequeue_from_mobipass(void *qstate, uint32_t timestamp, void *data);
/* returns a queue state type, as opaque data structure */
void *init_queues(int samples_per_1024_frames);
#endif /* _QUEUES_H_ */
Active_eNBs = ( "eNB_Eurecom_LTEBox");
# Asn1_verbosity, choice in: none, info, annoying
Asn1_verbosity = "none";
eNBs =
(
{
////////// 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";
mobile_country_code = "208";
mobile_network_code = "92";
////////// Physical parameters:
component_carriers = (
// second carrier-> for ERCOM
{
node_function = "eNodeB_3GPP_BBU" # should be verified
//node_function = "NGFI_RCC_IF5" # should be verified
node_timing = "synch_to_mobipass_standalone";
//node_timing = "synch_to_ext_device";
node_synch_ref = 0; #should
frame_type = "FDD";
tdd_config = 3;
tdd_config_s = 0;
prefix_type = "NORMAL";
eutra_band = 7;
downlink_frequency = 2660000000L;
uplink_frequency_offset = -120000000;
Nid_cell = 0;
N_RB_DL = 50;
Nid_cell_mbsfn = 0;
nb_antenna_ports = 1;
nb_antennas_tx = 1;
nb_antennas_rx = 1;
tx_gain = 90;
rx_gain = 125;
prach_root = 0;
prach_config_index = 0;
prach_high_speed = "DISABLE";
prach_zero_correlation = 3;
prach_freq_offset = 2;
pucch_delta_shift = 1;
pucch_nRB_CQI = 0;
pucch_nCS_AN = 0;
pucch_n1_AN = 32;
pdsch_referenceSignalPower = -29;
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 = -100;
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;
}
);
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 = "127.0.0.3";
ipv6 = "192:168:30::17";
active = "yes";
preference = "ipv4";
}
);
NETWORK_INTERFACES :
{
ENB_INTERFACE_NAME_FOR_S1_MME = "lo";
ENB_IPV4_ADDRESS_FOR_S1_MME = "127.0.0.2/24";
ENB_INTERFACE_NAME_FOR_S1U = "lo";
ENB_IPV4_ADDRESS_FOR_S1U = "127.0.0.4/24";
ENB_PORT_FOR_S1U = 2152; # Spec 2152
};
rrh_gw_config = (
//second config for Ercom
{
local_if_name = "eth1.300";
remote_address = "00:21:5e:91:5c:7e"; # should be updated with ERCOM's MAC
local_address = "f0:1f:af:db:b9:c8";
local_port = 50000; #for raw option local port must be the same to remote
remote_port = 50000;
rrh_gw_active = "yes";
tr_preference = "raw_if5_mobipass";
rf_preference = "usrp_b200";
iq_txshift = 0;
tx_sample_advance = 80;
tx_scheduling_advance = 9;
if_compression = "None"
}
);
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";
};
}
);
......@@ -48,7 +48,7 @@ eNBs =
prach_zero_correlation = 1;
prach_freq_offset = 2;
pucch_delta_shift = 1;
pucch_nRB_CQI = 1;
pucch_nRB_CQI = 0;
pucch_nCS_AN = 0;
pucch_n1_AN = 32;
pdsch_referenceSignalPower = -29;
......
......@@ -397,6 +397,14 @@ void tx_fh_if5_mobipass(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) {
send_IF5(eNB, proc->timestamp_tx, proc->subframe_tx, &seqno, IF5_MOBIPASS);
}
void tx_fh_if5_mobipass_standalone(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) {
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, proc->timestamp_tx&0xffffffff );
if ((eNB->frame_parms.frame_type==FDD) ||
((eNB->frame_parms.frame_type==TDD) &&
(subframe_select(&eNB->frame_parms,proc->subframe_tx) != SF_UL)))
send_IF5(eNB, proc->timestamp_tx, proc->subframe_tx, &seqno, IF5_MOBIPASS);
}
void tx_fh_if4p5(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) {
if ((eNB->frame_parms.frame_type==FDD) ||
((eNB->frame_parms.frame_type==TDD) &&
......@@ -455,6 +463,10 @@ void proc_tx_full(PHY_VARS_eNB *eNB,
proc_tx_high0(eNB,proc,r_type,rn);
// do OFDM modulation
do_OFDM_mod_rt(proc->subframe_tx,eNB);
T(T_ENB_PHY_OUTPUT_SIGNAL, T_INT(0), T_INT(0), T_INT(proc->frame_tx), T_INT(proc->subframe_tx),
T_INT(0), T_BUFFER(&eNB->common_vars.txdata[0][0][proc->subframe_tx * eNB->frame_parms.samples_per_tti], eNB->frame_parms.samples_per_tti * 4));
// if TX fronthaul go ahead
if (eNB->tx_fh) eNB->tx_fh(eNB,proc);
......@@ -909,7 +921,7 @@ void rx_rf(PHY_VARS_eNB *eNB,int *frame,int *subframe) {
int siglen=fp->samples_per_tti,flags=1;
if (SF_type == SF_S) {
siglen = fp->dl_symbols_in_S_subframe*(fp->ofdm_symbol_size+fp->nb_prefix_samples0);
siglen = (fp->dl_symbols_in_S_subframe+1)*(fp->ofdm_symbol_size+fp->nb_prefix_samples0);
flags=3; // end of burst
}
if ((fp->frame_type == TDD) &&
......@@ -1061,6 +1073,38 @@ void rx_fh_if5(PHY_VARS_eNB *eNB,int *frame, int *subframe) {
}
void rx_fh_if5_mobipass_standalone(PHY_VARS_eNB *eNB,int *frame, int *subframe)
{
LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
eNB_proc_t *proc = &eNB->proc;
recv_IF5(eNB, &proc->timestamp_rx, *subframe, IF5_MOBIPASS);
//printf("in rx_fh_if5_mobipass timestamp from recv_IF5 %ld\n", proc->timestamp_rx);
proc->frame_rx = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023;
proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10;
// T(T_SUBFRAME, T_INT(proc->frame_rx), T_INT(proc->subframe_rx), T_STRING(__FUNCTION__));
if (proc->first_rx == 0) {
if (proc->subframe_rx != *subframe){
LOG_E(PHY,"rx_fh_if5: Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,*subframe);
exit_fun("Exiting");
}
if (proc->frame_rx != *frame) {
LOG_E(PHY,"rx_fh_if5: Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,*frame);
exit_fun("Exiting");
}
} else {
proc->first_rx--;
*frame = proc->frame_rx;
*subframe = proc->subframe_rx;
}
proc->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_tti);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
}
void rx_fh_if4p5(PHY_VARS_eNB *eNB,int *frame,int *subframe) {
......@@ -2099,6 +2143,11 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst
eNB->fh_asynch = fh_if5_asynch_UL;
}
else if (eNB->node_timing == synch_to_mobipass_standalone) {
eNB->tx_fh = tx_fh_if5_mobipass_standalone;
eNB->rx_fh = rx_fh_if5_mobipass_standalone;
eNB->fh_asynch = NULL;
}
else {
eNB->tx_fh = tx_fh_if5;
eNB->rx_fh = rx_fh_if5;
......
......@@ -604,14 +604,11 @@ void *l2l1_task(void *arg) {
static void get_options (int argc, char **argv) {
int c;
// char line[1000];
// int l;
int k,i;//,j,k;
#if defined(OAI_USRP) || defined(CPRIGW)
int clock_src;
#endif
int CC_id;
int c;
// char line[1000];
// int l;
int k,i;//,j,k;
int CC_id;
const Enb_properties_array_t *enb_properties;
......@@ -639,6 +636,7 @@ static void get_options (int argc, char **argv) {
LONG_OPTION_USIMTEST,
LONG_OPTION_MMAPPED_DMA,
LONG_OPTION_EXTERNAL_CLOCK,
LONG_OPTION_GPSDO_CLOCK,
LONG_OPTION_WAIT_FOR_SYNC,
LONG_OPTION_SINGLE_THREAD_DISABLE,
LONG_OPTION_THREADIQ,
......@@ -680,6 +678,7 @@ static void get_options (int argc, char **argv) {
{"usim-test", no_argument, NULL, LONG_OPTION_USIMTEST},
{"mmapped-dma", no_argument, NULL, LONG_OPTION_MMAPPED_DMA},
{"external-clock", no_argument, NULL, LONG_OPTION_EXTERNAL_CLOCK},
{"gpsdo-clock", no_argument, NULL, LONG_OPTION_GPSDO_CLOCK},
{"wait-for-sync", no_argument, NULL, LONG_OPTION_WAIT_FOR_SYNC},
{"single-thread-disable", no_argument, NULL, LONG_OPTION_SINGLE_THREAD_DISABLE},
{"threadIQ", required_argument, NULL, LONG_OPTION_THREADIQ},
......@@ -809,6 +808,10 @@ static void get_options (int argc, char **argv) {
clock_source = external;
break;
case LONG_OPTION_GPSDO_CLOCK:
clock_source = gpsdo;
break;
case LONG_OPTION_WAIT_FOR_SYNC:
wait_for_sync = 1;
break;
......@@ -1001,35 +1004,10 @@ static void get_options (int argc, char **argv) {
break;
case 's':
#if defined(OAI_USRP) || defined(CPRIGW)
clock_src = atoi(optarg);
if (clock_src == 0) {
// char ref[128] = "internal";
//strncpy(uhd_ref, ref, strlen(ref)+1);
} else if (clock_src == 1) {
//char ref[128] = "external";
//strncpy(uhd_ref, ref, strlen(ref)+1);
}
#else
printf("Note: -s not defined for ExpressMIMO2\n");
#endif
break;
case 'S':
exit_missed_slots=0;
printf("Skip exit for missed slots\n");
break;
case 'g':
glog_level=atoi(optarg); // value between 1 - 9
break;
case 'F':
break;
case 'S':
exit_missed_slots=0;
printf("Skip exit for missed slots\n");
break;
case 'G':
glog_verbosity=atoi(optarg);// value from 0, 0x5, 0x15, 0x35, 0x75
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment