* add RF interface to the rrh gateway
* update the openair0_init for all targets * add a tuning function for the ethernet git-svn-id: http://svn.eurecom.fr/openair4G/trunk@7830 818b1a75-f10b-46b9-bf7c-635c3b92a50f
This commit is contained in:
@@ -392,7 +392,7 @@ elseif (${RF_BOARD} STREQUAL "ETHERNET")
|
|||||||
set(HW_SOURCE ${HW_SOURCE}
|
set(HW_SOURCE ${HW_SOURCE}
|
||||||
${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c
|
${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c
|
||||||
)
|
)
|
||||||
set(LOWLATENCY False)
|
set(LOWLATENCY True)
|
||||||
|
|
||||||
elseif (${RF_BOARD} STREQUAL "CPRIGW")
|
elseif (${RF_BOARD} STREQUAL "CPRIGW")
|
||||||
set(HW_SOURCE ${HW_SOURCE}
|
set(HW_SOURCE ${HW_SOURCE}
|
||||||
@@ -1558,6 +1558,7 @@ add_executable(lte-softmodem
|
|||||||
${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c
|
${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c
|
||||||
${OPENAIR_TARGETS}/SIMU/USER/init_lte.c
|
${OPENAIR_TARGETS}/SIMU/USER/init_lte.c
|
||||||
${OPENAIR_TARGETS}/COMMON/create_tasks.c
|
${OPENAIR_TARGETS}/COMMON/create_tasks.c
|
||||||
|
${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c
|
||||||
${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c
|
${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c
|
||||||
${OPENAIRCN_DIR}/NAS/UE/nas_ue_task.c
|
${OPENAIRCN_DIR}/NAS/UE/nas_ue_task.c
|
||||||
${GTPU_need_ITTI}
|
${GTPU_need_ITTI}
|
||||||
@@ -1591,6 +1592,7 @@ add_executable(lte-softmodem-nos1
|
|||||||
${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c
|
${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c
|
||||||
${OPENAIR_TARGETS}/SIMU/USER/init_lte.c
|
${OPENAIR_TARGETS}/SIMU/USER/init_lte.c
|
||||||
${OPENAIR_TARGETS}/COMMON/create_tasks.c
|
${OPENAIR_TARGETS}/COMMON/create_tasks.c
|
||||||
|
${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c
|
||||||
#${OPENAIR2_DIR}/RRC/NAS/nas_config.c # enable if you want rrc to mount ip interface
|
#${OPENAIR2_DIR}/RRC/NAS/nas_config.c # enable if you want rrc to mount ip interface
|
||||||
#${OPENAIR2_DIR}/RRC/NAS/rb_config.c
|
#${OPENAIR2_DIR}/RRC/NAS/rb_config.c
|
||||||
${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c
|
${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c
|
||||||
@@ -1726,6 +1728,7 @@ add_executable(rrh_gw
|
|||||||
${OPENAIR_TARGETS}/RT/USER/eNB_transport_IQ.c
|
${OPENAIR_TARGETS}/RT/USER/eNB_transport_IQ.c
|
||||||
${OPENAIR_TARGETS}/RT/USER/UE_transport_IQ.c
|
${OPENAIR_TARGETS}/RT/USER/UE_transport_IQ.c
|
||||||
${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c
|
${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c
|
||||||
|
${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c
|
||||||
${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c
|
${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c
|
||||||
${HW_SOURCE}
|
${HW_SOURCE}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -92,6 +92,8 @@ const char* eurecomVariablesNames[] = {
|
|||||||
"diff2",
|
"diff2",
|
||||||
"hw_subframe",
|
"hw_subframe",
|
||||||
"hw_frame",
|
"hw_frame",
|
||||||
|
"hw_subframe_rx",
|
||||||
|
"hw_frame_rx",
|
||||||
"txcnt",
|
"txcnt",
|
||||||
"rxcnt",
|
"rxcnt",
|
||||||
"trx_ts",
|
"trx_ts",
|
||||||
@@ -103,6 +105,8 @@ const char* eurecomVariablesNames[] = {
|
|||||||
"hw_cnt_tx",
|
"hw_cnt_tx",
|
||||||
"lhw_cnt_tx",
|
"lhw_cnt_tx",
|
||||||
"pck_rx",
|
"pck_rx",
|
||||||
|
"pck_tx",
|
||||||
|
"cnt",
|
||||||
"dummy_dump",
|
"dummy_dump",
|
||||||
"itti_send_msg",
|
"itti_send_msg",
|
||||||
"itti_poll_msg",
|
"itti_poll_msg",
|
||||||
@@ -150,6 +154,8 @@ const char* eurecomFunctionsNames[] = {
|
|||||||
"eNB_rx_sleep",
|
"eNB_rx_sleep",
|
||||||
"eNB_tx_sleep",
|
"eNB_tx_sleep",
|
||||||
"eNB_proc_sleep",
|
"eNB_proc_sleep",
|
||||||
|
"trx_read_rf",
|
||||||
|
"trx_write_rf",
|
||||||
|
|
||||||
/* PHY signals */
|
/* PHY signals */
|
||||||
"ue_synch",
|
"ue_synch",
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ typedef enum {
|
|||||||
VCD_SIGNAL_DUMPER_VARIABLES_DIFF,
|
VCD_SIGNAL_DUMPER_VARIABLES_DIFF,
|
||||||
VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME,
|
VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME,
|
||||||
VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME,
|
VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME,
|
||||||
|
VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME_RX,
|
||||||
|
VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME_RX,
|
||||||
VCD_SIGNAL_DUMPER_VARIABLES_TXCNT,
|
VCD_SIGNAL_DUMPER_VARIABLES_TXCNT,
|
||||||
VCD_SIGNAL_DUMPER_VARIABLES_RXCNT,
|
VCD_SIGNAL_DUMPER_VARIABLES_RXCNT,
|
||||||
VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS,
|
VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS,
|
||||||
@@ -75,6 +77,8 @@ typedef enum {
|
|||||||
VCD_SIGNAL_DUMPER_VARIABLES_TX_HWCNT,
|
VCD_SIGNAL_DUMPER_VARIABLES_TX_HWCNT,
|
||||||
VCD_SIGNAL_DUMPER_VARIABLES_TX_LHWCNT,
|
VCD_SIGNAL_DUMPER_VARIABLES_TX_LHWCNT,
|
||||||
VCD_SIGNAL_DUMPER_VARIABLES_RX_PCK,
|
VCD_SIGNAL_DUMPER_VARIABLES_RX_PCK,
|
||||||
|
VCD_SIGNAL_DUMPER_VARIABLES_TX_PCK,
|
||||||
|
VCD_SIGNAL_DUMPER_VARIABLES_CNT,
|
||||||
VCD_SIGNAL_DUMPER_VARIABLES_DUMMY_DUMP,
|
VCD_SIGNAL_DUMPER_VARIABLES_DUMMY_DUMP,
|
||||||
VCD_SIGNAL_DUMPER_VARIABLE_ITTI_SEND_MSG,
|
VCD_SIGNAL_DUMPER_VARIABLE_ITTI_SEND_MSG,
|
||||||
VCD_SIGNAL_DUMPER_VARIABLE_ITTI_POLL_MSG,
|
VCD_SIGNAL_DUMPER_VARIABLE_ITTI_POLL_MSG,
|
||||||
@@ -117,7 +121,6 @@ typedef enum {
|
|||||||
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RX,
|
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RX,
|
||||||
|
|
||||||
/* RRH signals */
|
/* RRH signals */
|
||||||
|
|
||||||
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX,
|
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX,
|
||||||
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX,
|
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX,
|
||||||
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TRX,
|
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TRX,
|
||||||
@@ -125,6 +128,8 @@ typedef enum {
|
|||||||
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX_SLEEP,
|
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX_SLEEP,
|
||||||
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX_SLEEP,
|
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX_SLEEP,
|
||||||
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_SLEEP,
|
VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_SLEEP,
|
||||||
|
VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_RF,
|
||||||
|
VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_RF,
|
||||||
|
|
||||||
/* PHY signals */
|
/* PHY signals */
|
||||||
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SYNCH,
|
VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SYNCH,
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ int trx_brf_set_gains(openair0_device* device) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int openair0_device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
|
int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openair0_cfg) {
|
||||||
|
|
||||||
int status;
|
int status;
|
||||||
int card=0;
|
int card=0;
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
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@eurecom.fr
|
||||||
|
|
||||||
|
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
|
||||||
|
|
||||||
|
*******************************************************************************/
|
||||||
|
/*! \file common_lib.c
|
||||||
|
* \brief common APIs for different RF frontend device
|
||||||
|
* \author HongliangXU, Navid Nikaein
|
||||||
|
* \date 2015
|
||||||
|
* \version 0.2
|
||||||
|
* \company Eurecom
|
||||||
|
* \maintainer: navid.nikaein@eurecom.fr
|
||||||
|
* \note
|
||||||
|
* \warning
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "common_lib.h"
|
||||||
|
|
||||||
|
|
||||||
|
int openair0_device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
|
||||||
|
|
||||||
|
#ifdef ETHERNET
|
||||||
|
device->type=ETH_IF;
|
||||||
|
device->func_type = BBU_FUNC;
|
||||||
|
openair0_dev_init_eth(device, openair0_cfg);
|
||||||
|
printf(" openair0_dev_init_eth ...\n");
|
||||||
|
#elif EXMIMO
|
||||||
|
device->type=EXMIMO_IF;
|
||||||
|
openair0_dev_init_exmimo(device, openair0_cfg);
|
||||||
|
printf("openair0_dev_init_exmimo...\n");
|
||||||
|
#elif OAI_USRP
|
||||||
|
device->type=USRP_IF;
|
||||||
|
openair0_dev_init_usrp(device, openair0_cfg);
|
||||||
|
printf("openair0_dev_init_usrp ...\n");
|
||||||
|
#elif OAI_BLADERF
|
||||||
|
device->type=BLADERF_IF;
|
||||||
|
openair0_dev_init_bladerf(device, openair0_cfg);
|
||||||
|
printf(" openair0_dev_init_bladerf ...\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
@@ -134,7 +134,13 @@ typedef struct {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!\brief device type */
|
/*!\brief interface types that apply to modules (RRH_BBU/RRH_UE) created in RRH (rrh_gw.c)
|
||||||
|
and are defined with respect to the RF device that is present in RRH
|
||||||
|
-RRH_BBU modules have two devices, one is by default ETHERNET (will have ETH_IF) and the other one is a
|
||||||
|
RF device (EXMIMO,USRP,BLADERF) or no device (NONE_IF).
|
||||||
|
-RRH_UE modules have two devices one is by default ETHERNET (will have ETH_IF)
|
||||||
|
and the other one by default not present so it will have NONE_IF
|
||||||
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
MIN_DEV_TYPE = 0,
|
MIN_DEV_TYPE = 0,
|
||||||
/*!\brief device is ETH */
|
/*!\brief device is ETH */
|
||||||
@@ -152,7 +158,7 @@ typedef enum {
|
|||||||
} dev_type_t;
|
} dev_type_t;
|
||||||
|
|
||||||
|
|
||||||
/*!\brief type */
|
/*!\brief openair0 device host type */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
MIN_FUNC_TYPE = 0,
|
MIN_FUNC_TYPE = 0,
|
||||||
/*!\brief device functions within a BBU */
|
/*!\brief device functions within a BBU */
|
||||||
@@ -265,22 +271,19 @@ extern "C"
|
|||||||
|
|
||||||
/*! \brief Initialize Openair RF target. It returns 0 if OK */
|
/*! \brief Initialize Openair RF target. It returns 0 if OK */
|
||||||
int openair0_device_init(openair0_device* device, openair0_config_t *openair0_cfg);
|
int openair0_device_init(openair0_device* device, openair0_config_t *openair0_cfg);
|
||||||
//int openair0_stop(int card);
|
|
||||||
|
|
||||||
//ETHERNET
|
//USRP
|
||||||
/*! \brief Initialize Openair ETHERNET target. It returns 0 if OK */
|
|
||||||
int openair0_dev_init_eth(openair0_device *device, openair0_config_t *openair0_cfg);
|
|
||||||
//int openair0_stop_eth(int card);
|
|
||||||
//int openair0_set_gains_eth(openair0_device* device, openair0_config_t *openair0_cfg);
|
|
||||||
//int openair0_set_frequencies_eth(openair0_device* device, openair0_config_t *openair0_cfg,int exmimo_dump_config);
|
|
||||||
|
|
||||||
//USPRP
|
|
||||||
/*! \brief Get the current timestamp of USRP */
|
/*! \brief Get the current timestamp of USRP */
|
||||||
openair0_timestamp get_usrp_time(openair0_device *device);
|
openair0_timestamp get_usrp_time(openair0_device *device);
|
||||||
|
|
||||||
/*! \brief Set the RX frequency of USRP RF TARGET */
|
/*! \brief Set the RX frequency of USRP RF TARGET */
|
||||||
int openair0_set_rx_frequencies(openair0_device* device, openair0_config_t *openair0_cfg);
|
int openair0_set_rx_frequencies(openair0_device* device, openair0_config_t *openair0_cfg);
|
||||||
|
|
||||||
|
//extern
|
||||||
|
/*! \brief Initialize Openair ETHERNET target. It returns 0 if OK */
|
||||||
|
int openair0_dev_init_eth(openair0_device *device, openair0_config_t *openair0_cfg);
|
||||||
|
int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openair0_cfg);
|
||||||
|
int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_cfg);
|
||||||
|
int openair0_dev_init_exmimo(openair0_device *device, openair0_config_t *openair0_cfg);
|
||||||
/*@}*/
|
/*@}*/
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -52,221 +52,76 @@
|
|||||||
#include "common_lib.h"
|
#include "common_lib.h"
|
||||||
#include "ethernet_lib.h"
|
#include "ethernet_lib.h"
|
||||||
|
|
||||||
|
//#define DEBUG 1
|
||||||
|
|
||||||
int num_devices_eth = 0;
|
int num_devices_eth = 0;
|
||||||
int dest_addr_len[MAX_INST];
|
int dest_addr_len[MAX_INST];
|
||||||
char sendbuf[MAX_INST][BUF_SIZ]; /*TODO*/
|
char sendbuf[MAX_INST][BUF_SIZ]; /*TODO*/
|
||||||
|
|
||||||
|
|
||||||
/* Initialization of UDP Socket to communicate with one destination */
|
/*! \fn static int eth_socket_init(openair0_device *device)
|
||||||
int ethernet_socket_init(openair0_device *device) {
|
* \brief initialization of UDP Socket to communicate with one destination
|
||||||
|
* \param[in] *device openair device for which the socket will be created
|
||||||
|
* \param[out]
|
||||||
|
* \return 0 on success, otherwise -1
|
||||||
|
* \note
|
||||||
|
* @ingroup _oai
|
||||||
|
*/
|
||||||
|
static int eth_socket_init(openair0_device *device);
|
||||||
|
|
||||||
int i = 0;
|
/*! \fn static int eth_set_dev_conf(openair0_device *device)
|
||||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
* \brief
|
||||||
int Mod_id = device->Mod_id;
|
* \param[in] *device openair device
|
||||||
|
* \param[out]
|
||||||
|
* \return 0 on success, otherwise -1
|
||||||
|
* \note
|
||||||
|
* @ingroup _oai
|
||||||
|
*/
|
||||||
|
static int eth_set_dev_conf(openair0_device *device);
|
||||||
|
|
||||||
// struct sockaddr_in *dest = &dest_addr[Mod_id];
|
/*! \fn static int eth_get_dev_conf(openair0_device *device)
|
||||||
char str[INET_ADDRSTRLEN];
|
* \brief
|
||||||
const char *dest_ip;
|
* \param[in] *device openair device
|
||||||
int dest_port;
|
* \param[out]
|
||||||
|
* \return 0 on success, otherwise -1
|
||||||
|
* \note
|
||||||
|
* @ingroup _oai
|
||||||
|
*/
|
||||||
|
static int eth_get_dev_conf(openair0_device *device);
|
||||||
|
|
||||||
if (device->func_type == RRH_FUNC ){
|
|
||||||
dest_ip = device->openair0_cfg.my_ip;
|
|
||||||
dest_port = device->openair0_cfg.my_port;
|
int trx_eth_start(openair0_device *device) {
|
||||||
printf("[RRH] ip addr %s port %d\n",dest_ip, dest_port);
|
|
||||||
|
/* initialize socket */
|
||||||
|
if (eth_socket_init(device)!=0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RRH gets openair0 device configuration BBU sets openair0 device configuration*/
|
||||||
|
if (device->func_type == BBU_FUNC) {
|
||||||
|
return eth_set_dev_conf(device);
|
||||||
} else {
|
} else {
|
||||||
dest_ip = device->openair0_cfg.remote_ip;
|
return eth_get_dev_conf(device);
|
||||||
dest_port = device->openair0_cfg.remote_port;
|
|
||||||
printf("[BBU] ip addr %s port %d\n",dest_ip, dest_port);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Open RAW socket to send on */
|
|
||||||
if ((eth->sockfd[Mod_id] = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
|
|
||||||
perror("ETHERNET: Error opening socket");
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* initialize destination address */
|
|
||||||
for (i=0; i< MAX_INST; i++)
|
|
||||||
bzero((void *)&(eth->dest_addr[i]), sizeof(eth->dest_addr[i]));
|
|
||||||
|
|
||||||
// bzero((void *)dest,sizeof(struct sockaddr_in));
|
|
||||||
eth->dest_addr[Mod_id].sin_family = AF_INET;
|
|
||||||
inet_pton(AF_INET,dest_ip,&(eth->dest_addr[Mod_id].sin_addr.s_addr));
|
|
||||||
eth->dest_addr[Mod_id].sin_port=htons(dest_port);
|
|
||||||
dest_addr_len[Mod_id] = sizeof(struct sockaddr_in);
|
|
||||||
inet_ntop(AF_INET, &(eth->dest_addr[Mod_id].sin_addr), str, INET_ADDRSTRLEN);
|
|
||||||
|
|
||||||
/* if RRH, then I am the server, so bind */
|
|
||||||
if (device->func_type == RRH_FUNC ){
|
|
||||||
if (bind(eth->sockfd[Mod_id],(struct sockaddr *)ð->dest_addr[Mod_id], dest_addr_len[Mod_id])<0) {
|
|
||||||
perror("ETHERNET: Cannot bind to socket");
|
|
||||||
exit(0);
|
|
||||||
}else {
|
|
||||||
printf("[RRH] binding mod_%d to %s:%d\n",Mod_id,str,ntohs(eth->dest_addr[Mod_id].sin_port));
|
|
||||||
}
|
|
||||||
|
|
||||||
}else {
|
|
||||||
printf("[BBU] Connecting to %s:%d\n",str,ntohs(eth->dest_addr[Mod_id].sin_port));
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ethernet_socket_opt (openair0_device *device){
|
|
||||||
|
|
||||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
|
||||||
int Mod_id=device->Mod_id;
|
|
||||||
|
|
||||||
int sndbuf_size=0, rcvbuf_size=0;
|
|
||||||
socklen_t optlen;
|
|
||||||
/* chang the MTU of the eth interface */
|
|
||||||
struct ifreq ifr;
|
|
||||||
|
|
||||||
optlen = sizeof(int);
|
|
||||||
|
|
||||||
if (getsockopt(eth->sockfd[Mod_id],
|
|
||||||
SOL_SOCKET,
|
|
||||||
SO_SNDBUF,
|
|
||||||
&sndbuf_size,&optlen))
|
|
||||||
printf("error:getsockopt()\n");
|
|
||||||
|
|
||||||
if (getsockopt(eth->sockfd[Mod_id],
|
|
||||||
SOL_SOCKET,
|
|
||||||
SO_RCVBUF,
|
|
||||||
&rcvbuf_size,&optlen))
|
|
||||||
printf("error:getsockopt()\n");
|
|
||||||
|
|
||||||
printf( "sndbuf_size= %d bytes rcvbuf_size= %d bytes\n", sndbuf_size,
|
|
||||||
rcvbuf_size);
|
|
||||||
|
|
||||||
ifr.ifr_addr.sa_family = AF_INET;
|
|
||||||
//iap->ifa_name is bond1:xx
|
|
||||||
strncpy(ifr.ifr_name, DEFAULT_IF, sizeof(ifr.ifr_name));
|
|
||||||
ifr.ifr_mtu = device->openair0_cfg.samples_per_packet*5;
|
|
||||||
if (ioctl(eth->sockfd[Mod_id], SIOCSIFMTU, (caddr_t)&ifr) < 0 )
|
|
||||||
perror ("Can't set the MTU");
|
|
||||||
else
|
|
||||||
printf("[ETHERNET] %s MTU size has changed to %d\n",DEFAULT_IF,ifr.ifr_mtu);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int trx_eth_set_dev_conf(openair0_device *device) {
|
|
||||||
|
|
||||||
int Mod_id = device->Mod_id;
|
|
||||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
|
||||||
void *msg;
|
|
||||||
ssize_t msg_len;
|
|
||||||
|
|
||||||
|
|
||||||
/* send to RRH (server) required configuration parameters:
|
|
||||||
-number of downlink RBs (so that frame/packet size can be set accordingly)
|
|
||||||
-rx_num_0channels
|
|
||||||
-tx_num_channels
|
|
||||||
-rx_freq
|
|
||||||
-tx_freq
|
|
||||||
-rxg_mode[4]
|
|
||||||
-rx_gain
|
|
||||||
-tx_gain
|
|
||||||
-rx_bw
|
|
||||||
-tx_bw
|
|
||||||
-autocal */
|
|
||||||
|
|
||||||
msg=malloc(sizeof(openair0_config_t));
|
|
||||||
msg_len=sizeof(openair0_config_t);
|
|
||||||
memcpy(msg,(void*)&device->openair0_cfg,msg_len);
|
|
||||||
|
|
||||||
if (sendto(eth->sockfd[Mod_id],msg,msg_len,0,(struct sockaddr *)ð->dest_addr[Mod_id],dest_addr_len[Mod_id])==-1){
|
|
||||||
perror("ETHERNET: ");
|
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int trx_eth_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags) {
|
||||||
|
|
||||||
int trx_eth_get_dev_conf(openair0_device *device) {
|
int n_written=0,i;
|
||||||
|
|
||||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
|
||||||
int Mod_id = device->Mod_id;
|
|
||||||
char str[INET_ADDRSTRLEN];
|
|
||||||
void *msg;
|
|
||||||
ssize_t msg_len;
|
|
||||||
|
|
||||||
msg=malloc(sizeof(openair0_config_t));
|
|
||||||
msg_len=sizeof(openair0_config_t);
|
|
||||||
|
|
||||||
/* receive from client (lte-softmodem) */
|
|
||||||
if (recvfrom(eth->sockfd[Mod_id],
|
|
||||||
msg,
|
|
||||||
msg_len,
|
|
||||||
0,
|
|
||||||
(struct sockaddr *)ð->dest_addr[Mod_id],
|
|
||||||
(socklen_t *)&dest_addr_len[Mod_id])==-1){
|
|
||||||
perror("ETHERNET: ");
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy((void*)&device->openair0_cfg,msg,msg_len);
|
|
||||||
inet_ntop(AF_INET, &(eth->dest_addr[Mod_id].sin_addr), str, INET_ADDRSTRLEN);
|
|
||||||
device->openair0_cfg.remote_port =ntohs(eth->dest_addr[Mod_id].sin_port);
|
|
||||||
device->openair0_cfg.remote_ip=str;
|
|
||||||
//ethernet_socket_opt (device);
|
|
||||||
// printf("[RRH] write mod_%d %d to %s:%d\n",Mod_id,eth->sockfd[Mod_id],str,ntohs(eth->dest_addr[Mod_id].sin_port));
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int trx_eth_request(openair0_device *device, void *msg, ssize_t msg_len) {
|
|
||||||
|
|
||||||
int Mod_id = device->Mod_id;
|
|
||||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
|
||||||
|
|
||||||
if (sendto(eth->sockfd[Mod_id],msg,msg_len,0,(struct sockaddr *)ð->dest_addr[Mod_id],dest_addr_len[Mod_id])==-1){
|
|
||||||
perror("ETHERNET: ");
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int trx_eth_reply(openair0_device *device, void *msg, ssize_t msg_len) {
|
|
||||||
|
|
||||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
|
||||||
int Mod_id = device->Mod_id;
|
|
||||||
|
|
||||||
/* receive from client (lte-softmodem) */
|
|
||||||
if (recvfrom(eth->sockfd[Mod_id],
|
|
||||||
msg,
|
|
||||||
msg_len,
|
|
||||||
0,
|
|
||||||
(struct sockaddr *)ð->dest_addr[Mod_id],
|
|
||||||
(socklen_t *)&dest_addr_len[Mod_id])==-1){
|
|
||||||
perror("ETHERNET: ");
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int ethernet_write_data(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int antenna_id) {
|
|
||||||
|
|
||||||
int n_written;
|
|
||||||
uint16_t header_size=sizeof(int32_t) + sizeof(openair0_timestamp);
|
uint16_t header_size=sizeof(int32_t) + sizeof(openair0_timestamp);
|
||||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||||
int Mod_id = device->Mod_id;
|
int Mod_id = device->Mod_id;
|
||||||
int sendto_flag =0;
|
int sendto_flag =0;
|
||||||
sendto_flag|=MSG_DONTWAIT;
|
sendto_flag|=MSG_DONTWAIT;
|
||||||
|
|
||||||
/* buff[antenna_id] points to the position in tx buffer where the payload to be sent is
|
for (i=0;i<cc;i++) {
|
||||||
|
/* buff[i] points to the position in tx buffer where the payload to be sent is
|
||||||
buff2 points to the position in tx buffer where the packet header will be placed */
|
buff2 points to the position in tx buffer where the packet header will be placed */
|
||||||
void *buff2 = (void*)(buff[antenna_id]-header_size); // (void*)((unsigned char *)buff[antenna_id]-header_size);
|
void *buff2 = (void*)(buff[i]-header_size);
|
||||||
|
|
||||||
/* we don't want to ovewrite with the header info the previous tx buffer data so we store it*/
|
/* we don't want to ovewrite with the header info the previous tx buffer data so we store it*/
|
||||||
int32_t temp0 = *(int32_t *)buff2;
|
int32_t temp0 = *(int32_t *)buff2;
|
||||||
@@ -274,7 +129,7 @@ int ethernet_write_data(openair0_device *device, openair0_timestamp timestamp, v
|
|||||||
|
|
||||||
n_written = 0;
|
n_written = 0;
|
||||||
|
|
||||||
*(int16_t *)(buff2 + sizeof(int16_t))=1+(antenna_id<<1);
|
*(int16_t *)(buff2 + sizeof(int16_t))=1+(i<<1);
|
||||||
*(openair0_timestamp *)(buff2 + sizeof(int32_t)) = timestamp;
|
*(openair0_timestamp *)(buff2 + sizeof(int32_t)) = timestamp;
|
||||||
|
|
||||||
/* printf("[RRH]write mod_%d %d , len %d, buff %p antenna %d\n",
|
/* printf("[RRH]write mod_%d %d , len %d, buff %p antenna %d\n",
|
||||||
@@ -293,40 +148,44 @@ while(n_written < nsamps) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* printf("Buffer head TX: nu=%d an_id=%d ts%d byte_send=%d \n", *(int16_t *)buff2,
|
#if DEBUG
|
||||||
|
printf("Buffer head TX: nu=%d an_id=%d ts%d samples_send=%d i=%d data=%x\n",
|
||||||
|
*(int16_t *)buff2,
|
||||||
*(int16_t *)(buff2 + sizeof(int16_t)),
|
*(int16_t *)(buff2 + sizeof(int16_t)),
|
||||||
*(openair0_timestamp *)(buff2 + sizeof(int32_t)),
|
*(openair0_timestamp *)(buff2 + sizeof(int32_t)),
|
||||||
n_written>>2);*/
|
n_written>>2,i,*(int32_t *)(buff2 + 20*sizeof(int32_t)));
|
||||||
|
#endif
|
||||||
|
|
||||||
/* tx buffer values restored */
|
/* tx buffer values restored */
|
||||||
*(int32_t *)buff2 = temp0;
|
*(int32_t *)buff2 = temp0;
|
||||||
*(openair0_timestamp *)(buff2 + sizeof(int32_t)) = temp1;
|
*(openair0_timestamp *)(buff2 + sizeof(int32_t)) = temp1;
|
||||||
|
}
|
||||||
return n_written;
|
return n_written;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int trx_eth_read(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) {
|
||||||
|
|
||||||
int ethernet_read_data(openair0_device *device,openair0_timestamp *timestamp,void **buff, int nsamps,int antenna_id) {
|
int bytes_received=0;
|
||||||
|
int block_cnt=0;
|
||||||
int bytes_received;
|
int ret=0,i;
|
||||||
int block_cnt;
|
|
||||||
int ret;
|
|
||||||
uint16_t header_size=sizeof(int32_t) + sizeof(openair0_timestamp);
|
uint16_t header_size=sizeof(int32_t) + sizeof(openair0_timestamp);
|
||||||
|
|
||||||
|
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||||
|
int Mod_id = device->Mod_id;
|
||||||
|
|
||||||
/* buff[antenna_id] points to the position in rx buffer where the payload to be received will be placed
|
for (i=0;i<cc;i++) {
|
||||||
|
/* buff[i] points to the position in rx buffer where the payload to be received will be placed
|
||||||
buff2 points to the position in rx buffer where the packet header will be placed */
|
buff2 points to the position in rx buffer where the packet header will be placed */
|
||||||
void *buff2 = (void*)(buff[antenna_id]-header_size);
|
void *buff2 = (void*)(buff[i]-header_size);
|
||||||
|
|
||||||
/* we don't want to ovewrite with the header info the previous rx buffer data so we store it*/
|
/* we don't want to ovewrite with the header info the previous rx buffer data so we store it*/
|
||||||
int32_t temp0 = *(int32_t *)buff2;
|
int32_t temp0 = *(int32_t *)buff2;
|
||||||
openair0_timestamp temp1 = *(openair0_timestamp *)(buff2 + sizeof(int32_t));
|
openair0_timestamp temp1 = *(openair0_timestamp *)(buff2 + sizeof(int32_t));
|
||||||
|
|
||||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
|
||||||
int Mod_id = device->Mod_id;
|
|
||||||
|
|
||||||
bytes_received=0;
|
bytes_received=0;
|
||||||
block_cnt=0;
|
block_cnt=0;
|
||||||
|
ret=0;
|
||||||
|
|
||||||
/* printf("[RRH] read mod_%d %d,len %d, buff %p antenna %d\n",
|
/* printf("[RRH] read mod_%d %d,len %d, buff %p antenna %d\n",
|
||||||
Mod_id,eth->sockfd[Mod_id],(nsamps<<2)+header_size, buff2, antenna_id);*/
|
Mod_id,eth->sockfd[Mod_id],(nsamps<<2)+header_size, buff2, antenna_id);*/
|
||||||
@@ -353,11 +212,14 @@ int ethernet_read_data(openair0_device *device,openair0_timestamp *timestamp,voi
|
|||||||
bytes_received+=ret;
|
bytes_received+=ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
printf("Buffer head RX: nu=%d an_id=%d ts%d byte_recv=%d\n", *(int16_t *)buff2,
|
#if DEBUG
|
||||||
|
printf("Buffer head RX: nu=%d an_id=%d ts%d samples_recv=%d i=%d data=%x\n",
|
||||||
|
*(int16_t *)buff2,
|
||||||
*(int16_t *)(buff2 + sizeof(int16_t)),
|
*(int16_t *)(buff2 + sizeof(int16_t)),
|
||||||
*(openair0_timestamp *)(buff2 + sizeof(int32_t)),
|
*(openair0_timestamp *)(buff2 + sizeof(int32_t)),
|
||||||
ret>>2);*/
|
ret>>2,i,*(int32_t *)(buff2 + 20*sizeof(int32_t)));
|
||||||
|
#endif
|
||||||
|
|
||||||
/* store the timestamp value from packet's header */
|
/* store the timestamp value from packet's header */
|
||||||
*timestamp = *(openair0_timestamp *)(buff2 + sizeof(int32_t));
|
*timestamp = *(openair0_timestamp *)(buff2 + sizeof(int32_t));
|
||||||
@@ -365,38 +227,122 @@ int ethernet_read_data(openair0_device *device,openair0_timestamp *timestamp,voi
|
|||||||
/* tx buffer values restored */
|
/* tx buffer values restored */
|
||||||
*(int32_t *)buff2 = temp0;
|
*(int32_t *)buff2 = temp0;
|
||||||
*(openair0_timestamp *)(buff2 + sizeof(int32_t)) = temp1;
|
*(openair0_timestamp *)(buff2 + sizeof(int32_t)) = temp1;
|
||||||
// printf("Received %d samples, timestamp = %d\n",bytes_received>>2,*(int32_t*)timestamp);
|
}
|
||||||
|
|
||||||
return nsamps;
|
return nsamps;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int trx_eth_start(openair0_device *device){
|
void trx_eth_end(openair0_device *device) {
|
||||||
|
|
||||||
if (ethernet_socket_init(device)!=0) {
|
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||||
return -1;
|
int Mod_id = device->Mod_id;
|
||||||
|
/*destroys socket only for the processes that call the eth_end fuction-- shutdown() for beaking the pipe */
|
||||||
|
if ( close(eth->sockfd[Mod_id]) <0 ) {
|
||||||
|
perror("ETHERNET: Failed to close socket");
|
||||||
|
exit(0);
|
||||||
|
} else {
|
||||||
|
printf("[RRH] socket for mod_id %d has been successfully closed.\n",Mod_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device->func_type == BBU_FUNC ) {
|
|
||||||
return trx_eth_set_dev_conf(device);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
return trx_eth_get_dev_conf(device);
|
|
||||||
}
|
|
||||||
return(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int trx_eth_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int antenna_id, int flags) {
|
|
||||||
|
|
||||||
return ethernet_write_data(device,timestamp,buff,nsamps,antenna_id);
|
int trx_eth_request(openair0_device *device, void *msg, ssize_t msg_len) {
|
||||||
|
|
||||||
|
int Mod_id = device->Mod_id;
|
||||||
|
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||||
|
|
||||||
|
/* BBU sends a message to RRH */
|
||||||
|
if (sendto(eth->sockfd[Mod_id],msg,msg_len,0,(struct sockaddr *)ð->dest_addr[Mod_id],dest_addr_len[Mod_id])==-1) {
|
||||||
|
perror("ETHERNET: ");
|
||||||
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int trx_eth_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int antenna_id) {
|
return 0;
|
||||||
|
|
||||||
return(ethernet_read_data(device,ptimestamp,buff,nsamps,antenna_id));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int trx_eth_reply(openair0_device *device, void *msg, ssize_t msg_len) {
|
||||||
|
|
||||||
|
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||||
|
int Mod_id = device->Mod_id;
|
||||||
|
|
||||||
|
/* RRH receives from BBU a message */
|
||||||
|
if (recvfrom(eth->sockfd[Mod_id],
|
||||||
|
msg,
|
||||||
|
msg_len,
|
||||||
|
0,
|
||||||
|
(struct sockaddr *)ð->dest_addr[Mod_id],
|
||||||
|
(socklen_t *)&dest_addr_len[Mod_id])==-1) {
|
||||||
|
perror("ETHERNET: ");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int eth_set_dev_conf(openair0_device *device) {
|
||||||
|
|
||||||
|
int Mod_id = device->Mod_id;
|
||||||
|
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||||
|
void *msg;
|
||||||
|
ssize_t msg_len;
|
||||||
|
|
||||||
|
|
||||||
|
/* a BBU client sents to RRH a set of configuration parameters (openair0_config_t)
|
||||||
|
so that RF front end is configured appropriately and
|
||||||
|
frame/packet size etc. can be set */
|
||||||
|
|
||||||
|
msg=malloc(sizeof(openair0_config_t));
|
||||||
|
msg_len=sizeof(openair0_config_t);
|
||||||
|
memcpy(msg,(void*)&device->openair0_cfg,msg_len);
|
||||||
|
|
||||||
|
if (sendto(eth->sockfd[Mod_id],msg,msg_len,0,(struct sockaddr *)ð->dest_addr[Mod_id],dest_addr_len[Mod_id])==-1) {
|
||||||
|
perror("ETHERNET: ");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int eth_get_dev_conf(openair0_device *device) {
|
||||||
|
|
||||||
|
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||||
|
int Mod_id = device->Mod_id;
|
||||||
|
char str[INET_ADDRSTRLEN];
|
||||||
|
void *msg;
|
||||||
|
ssize_t msg_len;
|
||||||
|
|
||||||
|
msg=malloc(sizeof(openair0_config_t));
|
||||||
|
msg_len=sizeof(openair0_config_t);
|
||||||
|
|
||||||
|
/* RRH receives from BBU openair0_config_t */
|
||||||
|
if (recvfrom(eth->sockfd[Mod_id],
|
||||||
|
msg,
|
||||||
|
msg_len,
|
||||||
|
0,
|
||||||
|
(struct sockaddr *)ð->dest_addr[Mod_id],
|
||||||
|
(socklen_t *)&dest_addr_len[Mod_id])==-1) {
|
||||||
|
perror("ETHERNET: ");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy((void*)&device->openair0_cfg,msg,msg_len);
|
||||||
|
inet_ntop(AF_INET, &(eth->dest_addr[Mod_id].sin_addr), str, INET_ADDRSTRLEN);
|
||||||
|
device->openair0_cfg.remote_port =ntohs(eth->dest_addr[Mod_id].sin_port);
|
||||||
|
device->openair0_cfg.remote_ip=str;
|
||||||
|
/*apply additional configuration*/
|
||||||
|
//ethernet_tune (device, RING_PAR);
|
||||||
|
// printf("[RRH] write mod_%d %d to %s:%d\n",Mod_id,eth->sockfd[Mod_id],str,ntohs(eth->dest_addr[Mod_id].sin_port));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int trx_eth_stop(int card) {
|
int trx_eth_stop(int card) {
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
@@ -409,45 +355,170 @@ int trx_eth_set_gains(openair0_device* device, openair0_config_t *openair0_cfg)
|
|||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int trx_eth_get_stats(openair0_device* device) {
|
int trx_eth_get_stats(openair0_device* device) {
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int trx_eth_reset_stats(openair0_device* device) {
|
int trx_eth_reset_stats(openair0_device* device) {
|
||||||
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
int openair0_set_gains(openair0_device* device,
|
|
||||||
openair0_config_t *openair0_cfg) {
|
|
||||||
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int openair0_set_frequencies(openair0_device* device, openair0_config_t *openair0_cfg, int dummy) {
|
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int eth_socket_init(openair0_device *device) {
|
||||||
|
|
||||||
void trx_eth_end(openair0_device *device) {
|
int i = 0;
|
||||||
|
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||||
|
int Mod_id = device->Mod_id;
|
||||||
|
char str[INET_ADDRSTRLEN];
|
||||||
|
const char *dest_ip;
|
||||||
|
int dest_port=0;
|
||||||
|
|
||||||
|
if (device->func_type == RRH_FUNC ) {
|
||||||
|
dest_ip = device->openair0_cfg.my_ip;
|
||||||
|
dest_port = device->openair0_cfg.my_port;
|
||||||
|
printf("[RRH] ip addr %s port %d\n",dest_ip, dest_port);
|
||||||
|
} else {
|
||||||
|
dest_ip = device->openair0_cfg.remote_ip;
|
||||||
|
dest_port = device->openair0_cfg.remote_port;
|
||||||
|
printf("[BBU] ip addr %s port %d\n",dest_ip, dest_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open RAW socket to send on */
|
||||||
|
if ((eth->sockfd[Mod_id] = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
|
||||||
|
perror("ETHERNET: Error opening socket");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initialize destination address */
|
||||||
|
for (i=0; i< MAX_INST; i++) {
|
||||||
|
bzero((void *)&(eth->dest_addr[i]), sizeof(eth->dest_addr[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// bzero((void *)dest,sizeof(struct sockaddr_in));
|
||||||
|
eth->dest_addr[Mod_id].sin_family = AF_INET;
|
||||||
|
inet_pton(AF_INET,dest_ip,&(eth->dest_addr[Mod_id].sin_addr.s_addr));
|
||||||
|
eth->dest_addr[Mod_id].sin_port=htons(dest_port);
|
||||||
|
dest_addr_len[Mod_id] = sizeof(struct sockaddr_in);
|
||||||
|
inet_ntop(AF_INET, &(eth->dest_addr[Mod_id].sin_addr), str, INET_ADDRSTRLEN);
|
||||||
|
|
||||||
|
/* if RRH, then I am the server, so bind */
|
||||||
|
if (device->func_type == RRH_FUNC ) {
|
||||||
|
if (bind(eth->sockfd[Mod_id],(struct sockaddr *)ð->dest_addr[Mod_id], dest_addr_len[Mod_id])<0) {
|
||||||
|
perror("ETHERNET: Cannot bind to socket");
|
||||||
|
exit(0);
|
||||||
|
} else {
|
||||||
|
printf("[RRH] binding mod_%d to %s:%d\n",Mod_id,str,ntohs(eth->dest_addr[Mod_id].sin_port));
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
printf("[BBU] Connecting to %s:%d\n",str,ntohs(eth->dest_addr[Mod_id].sin_port));
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ethernet_tune(openair0_device *device , eth_opt_t option) {
|
||||||
|
|
||||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||||
int Mod_id=device->Mod_id;
|
int Mod_id=device->Mod_id;
|
||||||
/*destroys socket only for the processes that call the eth_end fuction-- shutdown() for beaking the pipe */
|
|
||||||
if ( close(eth->sockfd[Mod_id]) <0 ) {
|
unsigned int sndbuf_size=0, rcvbuf_size=0;
|
||||||
perror("ETHERNET: Failed to close socket");
|
struct timeval snd_timeout, rcv_timeout;
|
||||||
exit(0);
|
struct ifreq ifr;
|
||||||
|
char system_cmd[256];
|
||||||
|
char* if_name=DEFAULT_IF;
|
||||||
|
|
||||||
|
/****************** socket level options ************************/
|
||||||
|
if (option== SND_BUF_SIZE) { /* transmit socket buffer size */
|
||||||
|
if (setsockopt(eth->sockfd[Mod_id],
|
||||||
|
SOL_SOCKET,
|
||||||
|
SO_SNDBUF,
|
||||||
|
&sndbuf_size,sizeof(sndbuf_size))) {
|
||||||
|
perror("[ETHERNET] setsockopt()");
|
||||||
} else {
|
} else {
|
||||||
printf("[RRH] socket for mod_id %d has been successfully closed.",Mod_id);
|
printf( "sndbuf_size= %d bytes\n", sndbuf_size);
|
||||||
|
}
|
||||||
|
} else if (option== RCV_BUF_SIZE) { /* receive socket buffer size */
|
||||||
|
if (setsockopt(eth->sockfd[Mod_id],
|
||||||
|
SOL_SOCKET,
|
||||||
|
SO_RCVBUF,
|
||||||
|
&rcvbuf_size,sizeof(rcvbuf_size))) {
|
||||||
|
perror("[ETHERNET] setsockopt()");
|
||||||
|
} else {
|
||||||
|
printf( "rcvbuf_size= %d bytes\n", rcvbuf_size);
|
||||||
|
}
|
||||||
|
} else if (option==RCV_TIMEOUT) {
|
||||||
|
rcv_timeout.tv_sec = 0;
|
||||||
|
rcv_timeout.tv_usec = 180;//less than rt_period
|
||||||
|
if (setsockopt(eth->sockfd[Mod_id],
|
||||||
|
SOL_SOCKET,
|
||||||
|
SO_RCVTIMEO,
|
||||||
|
(char *)&rcv_timeout,sizeof(rcv_timeout))) {
|
||||||
|
perror("[ETHERNET] setsockopt()");
|
||||||
|
} else {
|
||||||
|
printf( "rcv_timeout= %d usecs\n", rcv_timeout.tv_usec);
|
||||||
|
}
|
||||||
|
} else if (option==SND_TIMEOUT) {
|
||||||
|
snd_timeout.tv_sec = 0;
|
||||||
|
snd_timeout.tv_usec = 180;//less than rt_period
|
||||||
|
if (setsockopt(eth->sockfd[Mod_id],
|
||||||
|
SOL_SOCKET,
|
||||||
|
SO_SNDTIMEO,
|
||||||
|
(char *)&snd_timeout,sizeof(snd_timeout))) {
|
||||||
|
perror("[ETHERNET] setsockopt()");
|
||||||
|
} else {
|
||||||
|
printf( "snd_timeout= %d usecs\n", snd_timeout.tv_usec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************* interface level options *************************/
|
||||||
|
else if (option==MTU_SIZE) { /* change MTU of the eth interface */
|
||||||
|
ifr.ifr_addr.sa_family = AF_INET;
|
||||||
|
strncpy(ifr.ifr_name,if_name, sizeof(ifr.ifr_name));
|
||||||
|
ifr.ifr_mtu =8960;
|
||||||
|
if (ioctl(eth->sockfd[Mod_id],SIOCSIFMTU,(caddr_t)&ifr) < 0 )
|
||||||
|
perror ("[ETHERNET] Can't set the MTU");
|
||||||
|
else
|
||||||
|
printf("[ETHERNET] %s MTU size has changed to %d\n",DEFAULT_IF,ifr.ifr_mtu);
|
||||||
|
} else if (option==TX_Q_LEN) { /* change TX queue length of eth interface */
|
||||||
|
ifr.ifr_addr.sa_family = AF_INET;
|
||||||
|
strncpy(ifr.ifr_name,if_name, sizeof(ifr.ifr_name));
|
||||||
|
ifr.ifr_qlen =3000 ;
|
||||||
|
if (ioctl(eth->sockfd[Mod_id],SIOCSIFTXQLEN,(caddr_t)&ifr) < 0 )
|
||||||
|
perror ("[ETHERNET] Can't set the txqueuelen");
|
||||||
|
else
|
||||||
|
printf("[ETHERNET] %s txqueuelen size has changed to %d\n",DEFAULT_IF,ifr.ifr_qlen);
|
||||||
|
|
||||||
|
|
||||||
|
/******************* device level options *************************/
|
||||||
|
} else if (option==COALESCE_PAR) {
|
||||||
|
if (snprintf(system_cmd,sizeof(system_cmd),"ethtool -C %s rx-usecs 3",DEFAULT_IF) > 0) {
|
||||||
|
system(system_cmd);
|
||||||
|
printf("[ETHERNET] Coalesce parameters %s\n",system_cmd);
|
||||||
|
} else {
|
||||||
|
perror("[ETHERNET] Can't set coalesce parameters\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (option==PAUSE_PAR ) {
|
||||||
|
if (snprintf(system_cmd,sizeof(system_cmd),"ethtool -A %s autoneg off rx off tx off",DEFAULT_IF) > 0) {
|
||||||
|
system(system_cmd);
|
||||||
|
printf("[ETHERNET] Pause parameters %s\n",system_cmd);
|
||||||
|
} else {
|
||||||
|
perror("[ETHERNET] Can't set pause parameters\n");
|
||||||
|
}
|
||||||
|
} else if (option==RING_PAR ) {
|
||||||
|
if (snprintf(system_cmd,sizeof(system_cmd),"ethtool -G %s rx 4096 tx 4096",DEFAULT_IF) > 0) {
|
||||||
|
system(system_cmd);
|
||||||
|
printf("[ETHERNET] Ring parameters %s\n",system_cmd);
|
||||||
|
} else {
|
||||||
|
perror("[ETHERNET] Can't set ring parameters\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int openair0_dev_init_eth(openair0_device *device, openair0_config_t *openair0_cfg) {
|
int openair0_dev_init_eth(openair0_device *device, openair0_config_t *openair0_cfg) {
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
#include <netinet/ether.h>
|
#include <netinet/ether.h>
|
||||||
|
|
||||||
#define MAX_INST 4
|
#define MAX_INST 4
|
||||||
#define DEFAULT_IF "eth0"
|
#define DEFAULT_IF "lo"
|
||||||
#define BUF_SIZ 8960 /*Jumbo frame size*/
|
#define BUF_SIZ 8960 /*Jumbo frame size*/
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -103,21 +103,51 @@ struct eth_meta_data{
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!\brief packet header */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* packet's timestamp */
|
/*!\brief packet's timestamp */
|
||||||
openair0_timestamp timestamp;
|
openair0_timestamp timestamp;
|
||||||
/* variable declared for alignment purposes (sample size=32 bit) */
|
/*!\brief variable declared for alignment purposes (sample size=32 bit) */
|
||||||
int16_t not_used;
|
int16_t not_used;
|
||||||
/* antenna port used to resynchronize*/
|
/*!\brief antenna port used to resynchronize */
|
||||||
int16_t antenna_id;
|
int16_t antenna_id;
|
||||||
} header_t;
|
} header_t;
|
||||||
|
|
||||||
|
/*!\brief different options for ethernet tuning in socket and driver level */
|
||||||
|
typedef enum {
|
||||||
|
MIN_OPT = 0,
|
||||||
|
/*!\brief socket send buffer size in bytes */
|
||||||
|
SND_BUF_SIZE,
|
||||||
|
/*!\brief socket receive buffer size in bytes */
|
||||||
|
RCV_BUF_SIZE,
|
||||||
|
/*!\brief receiving timeout */
|
||||||
|
RCV_TIMEOUT,
|
||||||
|
/*!\brief sending timeout */
|
||||||
|
SND_TIMEOUT,
|
||||||
|
/*!\brief maximun transmission unit size in bytes */
|
||||||
|
MTU_SIZE,
|
||||||
|
/*!\brief TX queue length */
|
||||||
|
TX_Q_LEN,
|
||||||
|
/*!\brief RX/TX ring parameters of ethernet device */
|
||||||
|
RING_PAR,
|
||||||
|
/*!\brief interruptions coalesence mechanism of ethernet device */
|
||||||
|
COALESCE_PAR,
|
||||||
|
/*!\brief pause parameters of ethernet device */
|
||||||
|
PAUSE_PAR,
|
||||||
|
MAX_OPT
|
||||||
|
} eth_opt_t;
|
||||||
|
|
||||||
|
|
||||||
int ethernet_socket_init(openair0_device *device);
|
|
||||||
|
|
||||||
int ethernet_write_data(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int antenna_id);
|
/*! \fn int ethernet_tune (openair0_device *device, eth_opt_t option)
|
||||||
|
* \brief this function allows you to configure certain ethernet parameters in socket or device level
|
||||||
int ethernet_read_data(openair0_device *device,openair0_timestamp *timestamp,void **buff, int nsamps,int antenna_id);
|
* \param[in] openair0 device which bears the socket
|
||||||
|
* \param[in] name of parameter to configure
|
||||||
void ethernet_socket_opt (openair0_device *device);
|
* \return 0 on success, otherwise -1
|
||||||
|
* \note
|
||||||
|
* @ingroup _oai
|
||||||
|
*/
|
||||||
|
int ethernet_tune (openair0_device *device, eth_opt_t option);
|
||||||
|
int ethernet_write_data(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc) ;
|
||||||
|
int ethernet_read_data(openair0_device *device,openair0_timestamp *timestamp,void **buff, int nsamps,int cc);
|
||||||
|
|||||||
@@ -247,7 +247,7 @@ int openair0_stop_without_reset(int card)
|
|||||||
#define MY_RF_MODE (RXEN + TXEN + TXLPFNORM + TXLPFEN + TXLPF25 + RXLPFNORM + RXLPFEN + RXLPF25 + LNA1ON +LNAMax + RFBBNORM + DMAMODE_RX + DMAMODE_TX)
|
#define MY_RF_MODE (RXEN + TXEN + TXLPFNORM + TXLPFEN + TXLPF25 + RXLPFNORM + RXLPFEN + RXLPF25 + LNA1ON +LNAMax + RFBBNORM + DMAMODE_RX + DMAMODE_TX)
|
||||||
#define RF_MODE_BASE (LNA1ON + RFBBNORM)
|
#define RF_MODE_BASE (LNA1ON + RFBBNORM)
|
||||||
|
|
||||||
int openair0_device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
|
int openair0_dev_init_exmimo(openair0_device *device, openair0_config_t *openair0_cfg) {
|
||||||
|
|
||||||
// Initialize card
|
// Initialize card
|
||||||
// exmimo_config_t *p_exmimo_config;
|
// exmimo_config_t *p_exmimo_config;
|
||||||
|
|||||||
@@ -154,7 +154,6 @@ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp,
|
|||||||
|
|
||||||
static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc)
|
static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc)
|
||||||
{
|
{
|
||||||
|
|
||||||
usrp_state_t *s = (usrp_state_t*)device->priv;
|
usrp_state_t *s = (usrp_state_t*)device->priv;
|
||||||
int samples_received=0,i,j;
|
int samples_received=0,i,j;
|
||||||
int nsamps2; // aligned to upper 32 or 16 byte boundary
|
int nsamps2; // aligned to upper 32 or 16 byte boundary
|
||||||
@@ -188,25 +187,20 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
|
|||||||
for (int j=0; j<nsamps2; j++) {
|
for (int j=0; j<nsamps2; j++) {
|
||||||
#if defined(__x86_64__) || defined(__i386__)
|
#if defined(__x86_64__) || defined(__i386__)
|
||||||
#ifdef __AVX2__
|
#ifdef __AVX2__
|
||||||
|
|
||||||
((__m256i *)buff[i])[j] = _mm256_srai_epi16(buff_tmp[i][j],4);
|
((__m256i *)buff[i])[j] = _mm256_srai_epi16(buff_tmp[i][j],4);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
((__m128i *)buff[i])[j] = _mm_srai_epi16(buff_tmp[i][j],4);
|
((__m128i *)buff[i])[j] = _mm_srai_epi16(buff_tmp[i][j],4);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#elif defined(__arm__)
|
#elif defined(__arm__)
|
||||||
|
|
||||||
((int16x8_t*)buff[i])[j] = vshrq_n_s16(buff_tmp[i][j],4);
|
((int16x8_t*)buff[i])[j] = vshrq_n_s16(buff_tmp[i][j],4);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (samples_received < nsamps) {
|
if (samples_received < nsamps) {
|
||||||
printf("[recv] received %d samples out of %d\n",samples_received,nsamps);
|
printf("[recv] received %d samples out of %d\n",samples_received,nsamps);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//handle the error code
|
//handle the error code
|
||||||
switch(s->rx_md.error_code){
|
switch(s->rx_md.error_code){
|
||||||
case uhd::rx_metadata_t::ERROR_CODE_NONE:
|
case uhd::rx_metadata_t::ERROR_CODE_NONE:
|
||||||
@@ -225,6 +219,7 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
|
|||||||
s->rx_count += nsamps;
|
s->rx_count += nsamps;
|
||||||
s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate);
|
s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate);
|
||||||
*ptimestamp = s->rx_timestamp;
|
*ptimestamp = s->rx_timestamp;
|
||||||
|
|
||||||
return samples_received;
|
return samples_received;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,7 +329,7 @@ int trx_usrp_reset_stats(openair0_device* device) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int openair0_device_init(openair0_device* device, openair0_config_t *openair0_cfg)
|
int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_cfg)
|
||||||
{
|
{
|
||||||
uhd::set_thread_priority_safe(1.0);
|
uhd::set_thread_priority_safe(1.0);
|
||||||
usrp_state_t *s = (usrp_state_t*)malloc(sizeof(usrp_state_t));
|
usrp_state_t *s = (usrp_state_t*)malloc(sizeof(usrp_state_t));
|
||||||
@@ -499,6 +494,5 @@ int openair0_device_init(openair0_device* device, openair0_config_t *openair0_cf
|
|||||||
s->tx_forward_nsamps = 90;
|
s->tx_forward_nsamps = 90;
|
||||||
if(is_equal(s->sample_rate, (double)7.68e6))
|
if(is_equal(s->sample_rate, (double)7.68e6))
|
||||||
s->tx_forward_nsamps = 50;
|
s->tx_forward_nsamps = 50;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,15 +89,8 @@ void *rrh_UE_thread_status;
|
|||||||
void *rx_ue[2]; // FIXME hard coded array size; indexed by lte_frame_parms.nb_antennas_rx
|
void *rx_ue[2]; // FIXME hard coded array size; indexed by lte_frame_parms.nb_antennas_rx
|
||||||
void *tx_ue[2]; // FIXME hard coded array size; indexed by lte_frame_parms.nb_antennas_tx
|
void *tx_ue[2]; // FIXME hard coded array size; indexed by lte_frame_parms.nb_antennas_tx
|
||||||
|
|
||||||
/*! \fn void create_UE_trx_threads( openair0_device *dev_ue, uint8_t RT_flag,uint8_t NRT_flag)
|
|
||||||
* \brief this function
|
void config_UE_mod( rrh_module_t *dev_ue, uint8_t RT_flag,uint8_t NRT_flag) {
|
||||||
* \param[in]
|
|
||||||
* \param[out]
|
|
||||||
* \return
|
|
||||||
* \note
|
|
||||||
* @ingroup _oai
|
|
||||||
*/
|
|
||||||
void create_UE_trx_threads( rrh_module_t *dev_ue, uint8_t RT_flag,uint8_t NRT_flag) {
|
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
int error_code_UE, error_code_proc_UE;
|
int error_code_UE, error_code_proc_UE;
|
||||||
|
|||||||
+328
-186
@@ -28,7 +28,7 @@
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
|
||||||
/*! \file eNB_transport_IQ.c
|
/*! \file eNB_transport_IQ.c
|
||||||
* \brief eNB transport IQ sampels
|
* \brief eNB transport IQ samples
|
||||||
* \author Katerina Trilyraki, Navid Nikaein, Raymond Knopp
|
* \author Katerina Trilyraki, Navid Nikaein, Raymond Knopp
|
||||||
* \date 2015
|
* \date 2015
|
||||||
* \version 0.1
|
* \version 0.1
|
||||||
@@ -53,75 +53,103 @@
|
|||||||
|
|
||||||
#define PRINTF_PERIOD 3750
|
#define PRINTF_PERIOD 3750
|
||||||
#define HEADER_SIZE ((sizeof(int32_t) + sizeof(openair0_timestamp))>>2)
|
#define HEADER_SIZE ((sizeof(int32_t) + sizeof(openair0_timestamp))>>2)
|
||||||
//#undef LOWLATENCY
|
|
||||||
/******************************************************************************
|
|
||||||
** FUNCTION PROTOTYPES **
|
|
||||||
******************************************************************************/
|
|
||||||
void *rrh_eNB_rx_thread(void *);
|
|
||||||
void *rrh_eNB_tx_thread(void *);
|
|
||||||
void *rrh_proc_eNB_thread(void *);
|
|
||||||
void *rrh_eNB_thread(void *);
|
|
||||||
void set_rt_period( openair0_config_t openair0_cfg);
|
|
||||||
void check_dev_config( rrh_module_t *mod_enb);
|
|
||||||
|
|
||||||
|
|
||||||
pthread_t main_rrh_eNB_thread;
|
|
||||||
pthread_attr_t attr, attr_proc;
|
|
||||||
struct sched_param sched_param_rrh;
|
|
||||||
|
|
||||||
pthread_cond_t sync_eNB_cond[4];
|
pthread_cond_t sync_eNB_cond[4];
|
||||||
pthread_mutex_t sync_eNB_mutex[4];
|
pthread_mutex_t sync_eNB_mutex[4];
|
||||||
|
pthread_mutex_t sync_trx_mutex=PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
pthread_cond_t sync_trx_cond=PTHREAD_COND_INITIALIZER;
|
||||||
|
|
||||||
openair0_timestamp nrt_eNB_counter[4]= {0,0,0,0};
|
openair0_timestamp nrt_eNB_counter[4]= {0,0,0,0};
|
||||||
int32_t overflow_rx_buffer_eNB[4]= {0,0,0,0};
|
int32_t overflow_rx_buffer_eNB[4]= {0,0,0,0};
|
||||||
int32_t nsamps_eNB[4]= {0,0,0,0};
|
int32_t nsamps_eNB[4]= {0,0,0,0};
|
||||||
int32_t eNB_tx_started=0,eNB_rx_started=0;
|
int32_t eNB_tx_started=0,eNB_rx_started=0;
|
||||||
int32_t counter_eNB_rx[4]= {0,0,0,0};
|
int32_t counter_eNB_rx[4]= {0,0,0,0};
|
||||||
int32_t counter_eNB_tx[4]= {0,0,0,0};
|
int32_t counter_eNB_tx[4]= {0,0,0,0};
|
||||||
|
|
||||||
uint8_t RT_flag_eNB,NRT_flag_eNB;
|
uint8_t RT_flag_eNB,NRT_flag_eNB;
|
||||||
int32_t **tx_buffer_eNB, **rx_buffer_eNB;
|
|
||||||
void *rrh_eNB_thread_status;
|
void *rrh_eNB_thread_status;
|
||||||
|
int sync_eNB_rx[4]= {-1,-1,-1,-1};
|
||||||
|
unsigned int sync_trx=0;
|
||||||
|
|
||||||
|
int32_t **tx_buffer_eNB;
|
||||||
|
int32_t **rx_buffer_eNB;
|
||||||
void **rx_eNB; //was fixed to 2 ant
|
void **rx_eNB; //was fixed to 2 ant
|
||||||
void **tx_eNB; //was fixed to 2 ant
|
void **tx_eNB; //was fixed to 2 ant
|
||||||
|
|
||||||
int sync_eNB_rx[4]= {-1,-1,-1,-1};
|
openair0_timestamp timestamp_eNB_tx[4]= {0,0,0,0};// all antennas must have the same ts
|
||||||
openair0_timestamp timestamp_eNB_tx[4]= {0,0,0,0},timestamp_eNB_rx[4]= {0,0,0,0};
|
openair0_timestamp timestamp_eNB_rx[4]= {0,0,0,0};
|
||||||
|
openair0_timestamp timestamp_rx=0,timestamp_tx=0;
|
||||||
|
|
||||||
unsigned int rx_pos=0, next_rx_pos=0;
|
unsigned int rx_pos=0, next_rx_pos=0;
|
||||||
unsigned int tx_pos=0, prev_tx_pos=0;
|
unsigned int tx_pos=0, tx_pos_rf=0, prev_tx_pos=0;
|
||||||
|
unsigned int rt_period=0;
|
||||||
|
|
||||||
|
struct itimerspec timerspec;
|
||||||
|
pthread_mutex_t timer_mutex;
|
||||||
|
|
||||||
|
|
||||||
/*! \fn void create_eNB_trx_threads( rrh_module_t *dev_enb, uint8_t RT_flag,uint8_t NRT_flag)
|
|
||||||
|
/*! \fn void *rrh_eNB_rx_thread(void *arg)
|
||||||
* \brief this function
|
* \brief this function
|
||||||
* \param[in]
|
* \param[in]
|
||||||
* \param[out]
|
* \return none
|
||||||
* \return
|
|
||||||
* \note
|
* \note
|
||||||
* @ingroup _oai
|
* @ingroup _oai
|
||||||
*/
|
*/
|
||||||
void create_eNB_trx_threads( rrh_module_t *mod_enb, uint8_t RT_flag, uint8_t NRT_flag){
|
void *rrh_eNB_rx_thread(void *);
|
||||||
|
/*! \fn void *rrh_eNB_tx_thread(void *arg)
|
||||||
|
* \brief this function
|
||||||
|
* \param[in]
|
||||||
|
* \return none
|
||||||
|
* \note
|
||||||
|
* @ingroup _oai
|
||||||
|
*/
|
||||||
|
void *rrh_eNB_tx_thread(void *);
|
||||||
|
/*! \fn void *rrh_eNB_thread(void *arg)
|
||||||
|
* \brief this function
|
||||||
|
* \param[in]
|
||||||
|
* \return none
|
||||||
|
* \note
|
||||||
|
* @ingroup _oai
|
||||||
|
*/
|
||||||
|
void *rrh_eNB_thread(void *);
|
||||||
|
/*! \fn void check_dev_config( rrh_module_t *mod_enb)
|
||||||
|
* \brief this function
|
||||||
|
* \param[in] *mod_enb
|
||||||
|
* \return none
|
||||||
|
* \note
|
||||||
|
* @ingroup _oai
|
||||||
|
*/
|
||||||
|
static void check_dev_config( rrh_module_t *mod_enb);
|
||||||
|
/*! \fn void calc_rt_period_ns( openair0_config_t openair0_cfg)
|
||||||
|
* \brief this function
|
||||||
|
* \param[in] openair0_cfg
|
||||||
|
* \return none
|
||||||
|
* \note
|
||||||
|
* @ingroup _oai
|
||||||
|
*/
|
||||||
|
static void calc_rt_period_ns( openair0_config_t openair0_cfg);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void config_BBU_mod( rrh_module_t *mod_enb, uint8_t RT_flag, uint8_t NRT_flag) {
|
||||||
|
|
||||||
//int i;
|
|
||||||
int error_code_eNB;
|
int error_code_eNB;
|
||||||
|
pthread_t main_rrh_eNB_thread;
|
||||||
|
pthread_attr_t attr;
|
||||||
|
struct sched_param sched_param_rrh;
|
||||||
|
|
||||||
RT_flag_eNB=RT_flag;
|
RT_flag_eNB=RT_flag;
|
||||||
NRT_flag_eNB=NRT_flag;
|
NRT_flag_eNB=NRT_flag;
|
||||||
|
|
||||||
pthread_attr_init(&attr);
|
|
||||||
sched_param_rrh.sched_priority = sched_get_priority_max(SCHED_FIFO);
|
|
||||||
pthread_attr_setschedparam(&attr,&sched_param_rrh);
|
|
||||||
pthread_attr_setschedpolicy(&attr,SCHED_FIFO);
|
|
||||||
/*for (i=0; i<4; i++) {
|
|
||||||
pthread_mutex_init(&sync_eNB_mutex[i],NULL);
|
|
||||||
pthread_cond_init(&sync_eNB_cond[i],NULL);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/* handshake with client to exchange parameters */
|
/* handshake with client to exchange parameters */
|
||||||
mod_enb->eth_dev.trx_start_func(&mod_enb->eth_dev);//change port make it plus_id
|
mod_enb->eth_dev.trx_start_func(&mod_enb->eth_dev);//change port make it plus_id
|
||||||
|
|
||||||
|
/* if a RF iterface is added to RRH module get the configuration parameters sent from eNB */
|
||||||
|
if (mod_enb->devs->type != NONE_IF ) {
|
||||||
|
|
||||||
memcpy((void*)&mod_enb->devs->openair0_cfg,(void *)&mod_enb->eth_dev.openair0_cfg,sizeof(openair0_config_t));
|
memcpy((void*)&mod_enb->devs->openair0_cfg,(void *)&mod_enb->eth_dev.openair0_cfg,sizeof(openair0_config_t));
|
||||||
|
|
||||||
/* update certain parameters */
|
/* certain parameters have to be updated (calibration related)*/
|
||||||
if ( mod_enb->devs->type == EXMIMO_IF ) {
|
if ( mod_enb->devs->type == EXMIMO_IF ) {
|
||||||
if ( mod_enb->devs->openair0_cfg.num_rb_dl == 100 ) {
|
if ( mod_enb->devs->openair0_cfg.num_rb_dl == 100 ) {
|
||||||
mod_enb->devs->openair0_cfg.samples_per_packet = 2048;
|
mod_enb->devs->openair0_cfg.samples_per_packet = 2048;
|
||||||
@@ -189,11 +217,10 @@ void create_eNB_trx_threads( rrh_module_t *mod_enb, uint8_t RT_flag, uint8_t NRT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check sanity of received configuration parameters and print */
|
/* check sanity of configuration parameters and print */
|
||||||
check_dev_config(mod_enb);
|
check_dev_config(mod_enb);
|
||||||
|
|
||||||
#ifndef ETHERNET
|
/* initialize and configure the RF device */
|
||||||
/* initialize and apply configuration to associated RF device */
|
|
||||||
if (openair0_device_init(mod_enb->devs, &mod_enb->devs->openair0_cfg)<0){
|
if (openair0_device_init(mod_enb->devs, &mod_enb->devs->openair0_cfg)<0){
|
||||||
LOG_E(RRH,"Exiting, cannot initialize RF device.\n");
|
LOG_E(RRH,"Exiting, cannot initialize RF device.\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
@@ -202,9 +229,26 @@ void create_eNB_trx_threads( rrh_module_t *mod_enb, uint8_t RT_flag, uint8_t NRT
|
|||||||
LOG_I(RRH,"RF device has been successfully initialized.\n");
|
LOG_I(RRH,"RF device has been successfully initialized.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
/* start RF device */
|
||||||
|
if (mod_enb->devs->type == EXMIMO_IF ) {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (mod_enb->devs->trx_start_func(mod_enb->devs)!=0)
|
||||||
|
LOG_E(RRH,"Unable to initiate RF device.\n");
|
||||||
|
}
|
||||||
|
LOG_I(RRH,"RF device has been initiated.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create main eNB module thread
|
||||||
|
main_rrh_eNB_thread allocates memory
|
||||||
|
for TX/RX buffers and creates TX/RX
|
||||||
|
threads for every eNB module */
|
||||||
|
pthread_attr_init(&attr);
|
||||||
|
sched_param_rrh.sched_priority = sched_get_priority_max(SCHED_FIFO);
|
||||||
|
pthread_attr_setschedparam(&attr,&sched_param_rrh);
|
||||||
|
pthread_attr_setschedpolicy(&attr,SCHED_FIFO);
|
||||||
error_code_eNB = pthread_create(&main_rrh_eNB_thread, &attr, rrh_eNB_thread, (void *)mod_enb);
|
error_code_eNB = pthread_create(&main_rrh_eNB_thread, &attr, rrh_eNB_thread, (void *)mod_enb);
|
||||||
|
|
||||||
if (error_code_eNB) {
|
if (error_code_eNB) {
|
||||||
LOG_E(RRH,"Error while creating eNB thread\n");
|
LOG_E(RRH,"Error while creating eNB thread\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
@@ -212,16 +256,9 @@ void create_eNB_trx_threads( rrh_module_t *mod_enb, uint8_t RT_flag, uint8_t NRT
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \fn void *rrh_eNB_thread(void *arg)
|
|
||||||
* \brief this function
|
void *rrh_eNB_thread(void *arg) {
|
||||||
* \param[in]
|
|
||||||
* \param[out]
|
|
||||||
* \return
|
|
||||||
* \note
|
|
||||||
* @ingroup _oai
|
|
||||||
*/
|
|
||||||
void *rrh_eNB_thread(void *arg)
|
|
||||||
{
|
|
||||||
rrh_module_t *dev=(rrh_module_t *)arg;
|
rrh_module_t *dev=(rrh_module_t *)arg;
|
||||||
pthread_t eNB_rx_thread, eNB_tx_thread;
|
pthread_t eNB_rx_thread, eNB_tx_thread;
|
||||||
int error_code_eNB_rx, error_code_eNB_tx;
|
int error_code_eNB_rx, error_code_eNB_tx;
|
||||||
@@ -229,42 +266,35 @@ void *rrh_eNB_thread(void *arg)
|
|||||||
void *tmp;
|
void *tmp;
|
||||||
unsigned int samples_per_frame=0;
|
unsigned int samples_per_frame=0;
|
||||||
|
|
||||||
|
samples_per_frame = dev->eth_dev.openair0_cfg.samples_per_frame;
|
||||||
|
|
||||||
while (rrh_exit==0) {
|
while (rrh_exit==0) {
|
||||||
|
|
||||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TRX, 1 );
|
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TRX, 1 );
|
||||||
|
|
||||||
|
/* calculate packet period */
|
||||||
if (dev->devs->type != NONE_IF) {
|
calc_rt_period_ns(dev->eth_dev.openair0_cfg);
|
||||||
set_rt_period(dev->eth_dev.openair0_cfg);
|
|
||||||
}
|
|
||||||
samples_per_frame = dev->eth_dev.openair0_cfg.samples_per_frame;
|
|
||||||
|
|
||||||
/* allocate memory for TX/RX buffers
|
/* allocate memory for TX/RX buffers
|
||||||
each antenna port has a TX and a RX buffer
|
each antenna port has a TX and a RX buffer
|
||||||
each TX and RX buffer is of (samples_per_frame + HEADER_SIZE) samples (size of samples is 4 bytes) */
|
each TX and RX buffer is of (samples_per_frame + HEADER_SIZE) samples (size of samples is 4 bytes) */
|
||||||
rx_buffer_eNB = (int32_t**)malloc16(dev->eth_dev.openair0_cfg.rx_num_channels*sizeof(int32_t*));
|
rx_buffer_eNB = (int32_t**)malloc16(dev->eth_dev.openair0_cfg.rx_num_channels*sizeof(int32_t*));
|
||||||
tx_buffer_eNB = (int32_t**)malloc16(dev->eth_dev.openair0_cfg.tx_num_channels*sizeof(int32_t*));
|
tx_buffer_eNB = (int32_t**)malloc16(dev->eth_dev.openair0_cfg.tx_num_channels*sizeof(int32_t*));
|
||||||
|
LOG_D(RRH,"rx_buffer_eNB address =%p tx_buffer_eNB address =%p \n",rx_buffer_eNB,tx_buffer_eNB);
|
||||||
LOG_I(RRH,"rx ch %d %p and tx ch %d %p\n",
|
|
||||||
dev->eth_dev.openair0_cfg.rx_num_channels,
|
|
||||||
rx_buffer_eNB,
|
|
||||||
dev->eth_dev.openair0_cfg.tx_num_channels,
|
|
||||||
tx_buffer_eNB);
|
|
||||||
|
|
||||||
/* rx_buffer_eNB points to the beginning of data */
|
/* rx_buffer_eNB points to the beginning of data */
|
||||||
for (i=0; i<dev->eth_dev.openair0_cfg.rx_num_channels; i++) {
|
for (i=0; i<dev->eth_dev.openair0_cfg.rx_num_channels; i++) {
|
||||||
tmp=(void *)malloc(sizeof(int32_t)*(samples_per_frame + HEADER_SIZE));
|
tmp=(void *)malloc16(sizeof(int32_t)*(samples_per_frame + 32));
|
||||||
memset(tmp,0,sizeof(int32_t)*(samples_per_frame + HEADER_SIZE));
|
memset(tmp,0,sizeof(int32_t)*(samples_per_frame + 32));
|
||||||
rx_buffer_eNB[i]=( tmp + (HEADER_SIZE*sizeof(int32_t)) );
|
rx_buffer_eNB[i]=( tmp + (32*sizeof(int32_t)) );
|
||||||
LOG_I(RRH," rx ch %d %p |%p\n",i,rx_buffer_eNB[i],tmp);
|
LOG_D(RRH,"i=%d rx_buffer_eNB[i]=%p tmp= %p\n",i,rx_buffer_eNB[i],tmp);
|
||||||
}
|
}
|
||||||
/* tx_buffer_eNB points to the beginning of data */
|
/* tx_buffer_eNB points to the beginning of data */
|
||||||
for (i=0; i<dev->eth_dev.openair0_cfg.tx_num_channels; i++) {
|
for (i=0; i<dev->eth_dev.openair0_cfg.tx_num_channels; i++) {
|
||||||
tmp=(void *)malloc(sizeof(int32_t)*(samples_per_frame + HEADER_SIZE));
|
tmp=(void *)malloc16(sizeof(int32_t)*(samples_per_frame + 32));
|
||||||
memset(tmp,0,sizeof(int32_t)*(samples_per_frame + HEADER_SIZE));
|
memset(tmp,0,sizeof(int32_t)*(samples_per_frame + 32));
|
||||||
tx_buffer_eNB[i]=( tmp + (HEADER_SIZE*sizeof(int32_t)) );
|
tx_buffer_eNB[i]=( tmp + (32*sizeof(int32_t)) );
|
||||||
LOG_I(RRH," tx ch %d %p| %p \n", i,tx_buffer_eNB[i],tmp);
|
LOG_D(RRH,"i= %d tx_buffer_eNB[i]=%p tmp= %p \n",i,tx_buffer_eNB[i],tmp);
|
||||||
}
|
}
|
||||||
/* dummy initialization for TX/RX buffers */
|
/* dummy initialization for TX/RX buffers */
|
||||||
for (i=0; i<dev->eth_dev.openair0_cfg.rx_num_channels; i++) {
|
for (i=0; i<dev->eth_dev.openair0_cfg.rx_num_channels; i++) {
|
||||||
@@ -278,12 +308,19 @@ void *rrh_eNB_thread(void *arg)
|
|||||||
tx_buffer_eNB[i][j]=12+i;
|
tx_buffer_eNB[i][j]=12+i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate TX/RX buffers pointers used in write/read operations */
|
/* allocate TX/RX buffers pointers used in write/read operations */
|
||||||
rx_eNB = (void**)malloc16(dev->eth_dev.openair0_cfg.rx_num_channels*sizeof(int32_t*));
|
rx_eNB = (void**)malloc16(dev->eth_dev.openair0_cfg.rx_num_channels*sizeof(int32_t*));
|
||||||
tx_eNB = (void**)malloc16(dev->eth_dev.openair0_cfg.tx_num_channels*sizeof(int32_t*));
|
tx_eNB = (void**)malloc16(dev->eth_dev.openair0_cfg.tx_num_channels*sizeof(int32_t*));
|
||||||
|
|
||||||
|
/* init mutexes */
|
||||||
|
for (i=0; i<dev->eth_dev.openair0_cfg.tx_num_channels; i++) {
|
||||||
|
pthread_mutex_init(&sync_eNB_mutex[i],NULL);
|
||||||
|
pthread_cond_init(&sync_eNB_cond[i],NULL);
|
||||||
|
}
|
||||||
|
/* init mutexes */
|
||||||
|
pthread_mutex_init(&sync_trx_mutex,NULL);
|
||||||
|
|
||||||
|
/* create eNB module's TX/RX threads */
|
||||||
#ifdef LOWLATENCY
|
#ifdef LOWLATENCY
|
||||||
error_code_eNB_rx = pthread_create(&eNB_rx_thread, NULL, rrh_eNB_rx_thread, (void *)dev);
|
error_code_eNB_rx = pthread_create(&eNB_rx_thread, NULL, rrh_eNB_rx_thread, (void *)dev);
|
||||||
error_code_eNB_tx = pthread_create(&eNB_tx_thread, NULL, rrh_eNB_tx_thread, (void *)dev);
|
error_code_eNB_tx = pthread_create(&eNB_tx_thread, NULL, rrh_eNB_tx_thread, (void *)dev);
|
||||||
@@ -291,6 +328,7 @@ void *rrh_eNB_thread(void *arg)
|
|||||||
#else
|
#else
|
||||||
pthread_attr_t attr_eNB_rx, attr_eNB_tx;
|
pthread_attr_t attr_eNB_rx, attr_eNB_tx;
|
||||||
struct sched_param sched_param_eNB_rx, sched_param_eNB_tx;
|
struct sched_param sched_param_eNB_rx, sched_param_eNB_tx;
|
||||||
|
|
||||||
pthread_attr_init(&attr_eNB_rx);
|
pthread_attr_init(&attr_eNB_rx);
|
||||||
pthread_attr_init(&attr_eNB_tx);
|
pthread_attr_init(&attr_eNB_tx);
|
||||||
sched_param_eNB_rx.sched_priority = sched_get_priority_max(SCHED_FIFO);
|
sched_param_eNB_rx.sched_priority = sched_get_priority_max(SCHED_FIFO);
|
||||||
@@ -314,11 +352,53 @@ void *rrh_eNB_thread(void *arg)
|
|||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* create timer thread; when no RF device is present a software clock is generated */
|
||||||
|
if (dev->devs->type == NONE_IF) {
|
||||||
|
|
||||||
|
int error_code_timer;
|
||||||
|
pthread_t main_timer_proc_thread;
|
||||||
|
|
||||||
|
LOG_I(RRH,"Creating timer thread with rt period %d ns.\n",rt_period);
|
||||||
|
|
||||||
|
/* setup the timer to generate an interrupt:
|
||||||
|
-for the first time in (sample_per_packet/sample_rate) ns
|
||||||
|
-and then every (sample_per_packet/sample_rate) ns */
|
||||||
|
timerspec.it_value.tv_sec = rt_period/1000000000;
|
||||||
|
timerspec.it_value.tv_nsec = rt_period%1000000000;
|
||||||
|
timerspec.it_interval.tv_sec = rt_period/1000000000;
|
||||||
|
timerspec.it_interval.tv_nsec = rt_period%1000000000;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef LOWLATENCY
|
||||||
|
error_code_timer = pthread_create(&main_timer_proc_thread, NULL, timer_proc, (void *)&timerspec);
|
||||||
|
LOG_I(RRH,"[eNB][SCHED] deadline scheduling applied to timer thread \n");
|
||||||
|
#else
|
||||||
|
pthread_attr_t attr_timer;
|
||||||
|
struct sched_param sched_param_timer;
|
||||||
|
|
||||||
|
pthread_attr_init(&attr_timer);
|
||||||
|
sched_param_timer.sched_priority = sched_get_priority_max(SCHED_FIFO-1);
|
||||||
|
pthread_attr_setschedparam(&attr_timer,&sched_param_timer);
|
||||||
|
pthread_attr_setschedpolicy(&attr_timer,SCHED_FIFO-1);
|
||||||
|
|
||||||
|
pthread_mutex_init(&timer_mutex,NULL);
|
||||||
|
|
||||||
|
error_code_timer = pthread_create(&main_timer_proc_thread, &attr_timer, timer_proc, (void *)&timerspec);
|
||||||
|
LOG_I(RRH,"[eNB][SCHED] FIFO scheduling applied to timer thread \n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (error_code_timer) {
|
||||||
|
LOG_E(RRH,"Error while creating timer proc thread\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
while (rrh_exit==0)
|
while (rrh_exit==0)
|
||||||
sleep(1);
|
sleep(1);
|
||||||
|
|
||||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TRX,0 );
|
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TRX,0 );
|
||||||
} //while (eNB_exit==0)
|
}
|
||||||
|
|
||||||
rrh_eNB_thread_status = 0;
|
rrh_eNB_thread_status = 0;
|
||||||
pthread_exit(&rrh_eNB_thread_status);
|
pthread_exit(&rrh_eNB_thread_status);
|
||||||
@@ -326,15 +406,6 @@ void *rrh_eNB_thread(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*! \fn void *rrh_eNB_rx_thread(void *arg)
|
|
||||||
* \brief this function
|
|
||||||
* \param[in]
|
|
||||||
* \param[out]
|
|
||||||
* \return
|
|
||||||
* \note
|
|
||||||
* @ingroup _oai
|
|
||||||
*/
|
|
||||||
void *rrh_eNB_rx_thread(void *arg) {
|
void *rrh_eNB_rx_thread(void *arg) {
|
||||||
|
|
||||||
/* measuremnt related vars */
|
/* measuremnt related vars */
|
||||||
@@ -345,19 +416,23 @@ void *rrh_eNB_rx_thread(void *arg){
|
|||||||
struct timespec time_req_1us, time_rem_1us;
|
struct timespec time_req_1us, time_rem_1us;
|
||||||
rrh_module_t *dev = (rrh_module_t *)arg;
|
rrh_module_t *dev = (rrh_module_t *)arg;
|
||||||
ssize_t bytes_sent;
|
ssize_t bytes_sent;
|
||||||
int i, spp ,pck_rx=0;
|
int i=0 ,pck_rx=0, s_cnt=0;
|
||||||
openair0_vtimestamp last_hw_counter=0; //volatile int64_t
|
openair0_timestamp last_hw_counter=0; //volatile int64_t
|
||||||
unsigned int samples_per_frame=0;
|
unsigned int samples_per_frame=0,samples_per_subframe=0, spp_rf=0, spp_eth=0;
|
||||||
uint8_t loopback=0,measurements=0;
|
uint8_t loopback=0,measurements=0;
|
||||||
|
unsigned int subframe=0;
|
||||||
|
unsigned int frame=0;
|
||||||
|
|
||||||
//RTIME sleep_ns=1000;
|
|
||||||
time_req_1us.tv_sec = 0;
|
time_req_1us.tv_sec = 0;
|
||||||
time_req_1us.tv_nsec =1000; //time_req_1us.tv_nsec = (int)rt_period/2;--->granularity issue
|
time_req_1us.tv_nsec =1000; //time_req_1us.tv_nsec = (int)rt_period/2;--->granularity issue
|
||||||
spp = dev->eth_dev.openair0_cfg.samples_per_packet;
|
spp_eth = dev->eth_dev.openair0_cfg.samples_per_packet;
|
||||||
|
spp_rf = dev->devs->openair0_cfg.samples_per_packet;
|
||||||
|
|
||||||
samples_per_frame = dev->eth_dev.openair0_cfg.samples_per_frame;
|
samples_per_frame = dev->eth_dev.openair0_cfg.samples_per_frame;
|
||||||
|
samples_per_subframe = (unsigned int)samples_per_frame/10;
|
||||||
loopback = dev->loopback;
|
loopback = dev->loopback;
|
||||||
measurements = dev->measurements;
|
measurements = dev->measurements;
|
||||||
next_rx_pos = spp;
|
next_rx_pos = spp_eth;
|
||||||
|
|
||||||
#ifdef LOWLATENCY
|
#ifdef LOWLATENCY
|
||||||
struct sched_attr attr;
|
struct sched_attr attr;
|
||||||
@@ -369,9 +444,9 @@ void *rrh_eNB_rx_thread(void *arg){
|
|||||||
attr.sched_priority = 0;
|
attr.sched_priority = 0;
|
||||||
|
|
||||||
attr.sched_policy = SCHED_DEADLINE;
|
attr.sched_policy = SCHED_DEADLINE;
|
||||||
attr.sched_runtime = (0.1 * 100) * 10000; //
|
attr.sched_runtime = (0.8 * 100) * 10000;//4 * 10000;
|
||||||
attr.sched_deadline = rt_period;// 0.1 * 1000000; //
|
attr.sched_deadline = (0.9 * 100) * 10000;//rt_period-2000;
|
||||||
attr.sched_period = rt_period; //0.1 * 1000000; // each TX/RX thread has
|
attr.sched_period = 1 * 1000000;//rt_period;
|
||||||
|
|
||||||
if (sched_setattr(0, &attr, flags) < 0 ) {
|
if (sched_setattr(0, &attr, flags) < 0 ) {
|
||||||
perror("[SCHED] eNB RX thread: sched_setattr failed (run with sudo)\n");
|
perror("[SCHED] eNB RX thread: sched_setattr failed (run with sudo)\n");
|
||||||
@@ -380,84 +455,88 @@ void *rrh_eNB_rx_thread(void *arg){
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (rrh_exit == 0) {
|
while (rrh_exit == 0) {
|
||||||
|
while (rx_pos <(1 + subframe)*samples_per_subframe) {
|
||||||
|
LOG_D(RRH,"starting a new send:%d %d\n",sync_trx,frame);
|
||||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX, 1 );
|
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX, 1 );
|
||||||
|
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME_RX, frame);
|
||||||
|
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME_RX, subframe );
|
||||||
|
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_PCK, pck_rx );
|
||||||
|
LOG_D(RRH,"pack=%d rx_pos=%d subframe=%d frame=%d\n ",pck_rx, rx_pos, subframe,frame);
|
||||||
|
|
||||||
|
if (dev->devs->type == NONE_IF) {
|
||||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_HWCNT, hw_counter );
|
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_HWCNT, hw_counter );
|
||||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_LHWCNT, last_hw_counter );
|
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_LHWCNT, last_hw_counter );
|
||||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_PCK, pck_rx );
|
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_CNT, s_cnt );
|
||||||
|
|
||||||
for (i=0; i<dev->eth_dev.openair0_cfg.rx_num_channels; i++){
|
|
||||||
if (!eNB_rx_started) {
|
if (!eNB_rx_started) {
|
||||||
eNB_rx_started=1; // set this flag to 1 to indicate that eNB started
|
eNB_rx_started=1; // set this flag to 1 to indicate that eNB started
|
||||||
if (RT_flag_eNB==1) {
|
if (RT_flag_eNB==1) {
|
||||||
last_hw_counter=hw_counter;
|
last_hw_counter=hw_counter;//get current counter
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (RT_flag_eNB==1) {
|
if (RT_flag_eNB==1) {
|
||||||
if (hw_counter > last_hw_counter+1) {
|
if (hw_counter > last_hw_counter+1) {
|
||||||
printf("LR");
|
printf("LR");
|
||||||
} else {
|
} else {
|
||||||
while (hw_counter < last_hw_counter+1){
|
while ((hw_counter < last_hw_counter+1)) {
|
||||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX_SLEEP, 1 );
|
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX_SLEEP, 1 );
|
||||||
nanosleep(&time_req_1us,&time_rem_1us);
|
nanosleep(&time_req_1us,&time_rem_1us); //rt_sleep_ns(sleep_ns);
|
||||||
//rt_sleep_ns(sleep_ns);
|
s_cnt++;
|
||||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX_SLEEP, 0 );
|
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX_SLEEP, 0 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (measurements == 1 )
|
|
||||||
clock_gettime(CLOCK_MONOTONIC,&time1);
|
|
||||||
|
|
||||||
/* LOG_I(RRH,"send for%d at %d with %d |%d|%d| \n",i,rx_pos,timestamp_eNB_rx[i],((timestamp_eNB_rx[i]+spp)%samples_per_frame),next_rx_pos );
|
|
||||||
|
|
||||||
if ((timestamp_UE_tx[i]%samples_per_frame < next_rx_pos) && (UE_tx_started==1)) {
|
|
||||||
printf("eNB underflow\n");
|
|
||||||
if (NRT_flag_eNB==1) {
|
|
||||||
while ((timestamp_UE_tx[i]%samples_per_frame) < spp)
|
|
||||||
nanosleep(&time_req_1us,&time_rem_1us);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (((rx_pos)< timestamp_UE_tx[i]%samples_per_frame) && (next_rx_pos > (timestamp_UE_tx[i]%samples_per_frame)) && (UE_tx_started==1)) {
|
|
||||||
printf("eNB underflow\n");
|
if (measurements == 1 ) clock_gettime(CLOCK_MONOTONIC,&time1);
|
||||||
if (NRT_flag_eNB==1) {
|
|
||||||
while (next_rx_pos > (timestamp_UE_tx[i]%samples_per_frame))
|
|
||||||
nanosleep(&time_req_1us,&time_rem_1us);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
if (loopback == 1 ) {
|
if (loopback == 1 ) {
|
||||||
if (sync_eNB_rx[i]==0) {
|
if (sync_eNB_rx[i]==0) {
|
||||||
rx_eNB[i] = (void*)&tx_buffer_eNB[i][tx_pos];
|
rx_eNB[i] = (void*)&tx_buffer_eNB[i][tx_pos];
|
||||||
LOG_I(RRH,"tx_buffer_eNB[i][tx_pos]=%d ,tx_pos=%d\n",tx_buffer_eNB[i][tx_pos],tx_pos);
|
LOG_I(RRH,"tx_buffer_eNB[i][tx_pos]=%d ,tx_pos=%d\n",tx_buffer_eNB[i][tx_pos],tx_pos);
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
rx_eNB[i] = (void*)&rx_buffer_eNB[i][rx_pos];
|
rx_eNB[i] = (void*)&rx_buffer_eNB[i][rx_pos];
|
||||||
LOG_I(RRH,"rx_buffer_eNB[i][rx_pos]=%d ,rx_pos=%d\n",rx_buffer_eNB[i][rx_pos],rx_pos);
|
LOG_I(RRH,"rx_buffer_eNB[i][rx_pos]=%d ,rx_pos=%d\n",rx_buffer_eNB[i][rx_pos],rx_pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i=0; i<dev->eth_dev.openair0_cfg.rx_num_channels; i++) {
|
||||||
rx_eNB[i] = (void*)&rx_buffer_eNB[i][rx_pos];
|
rx_eNB[i] = (void*)&rx_buffer_eNB[i][rx_pos];
|
||||||
|
LOG_D(RRH," rx_eNB[i]=%p rx_buffer_eNB[i][rx_pos]=%p ,rx_pos=%d, i=%d ts=%d\n",rx_eNB[i],&rx_buffer_eNB[i][rx_pos],rx_pos,i,timestamp_rx);
|
||||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RXCNT, rx_pos );
|
|
||||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_TS, timestamp_eNB_rx[i]&0xffffffff );
|
|
||||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
|
|
||||||
|
|
||||||
//LOG_D(RRH," rx_eNB[i]=%p rx_buffer_eNB[i][rx_pos]=%p ,rx_pos=%d, i=%d ts=%d\n",rx_eNB[i],&rx_buffer_eNB[i][rx_pos],rx_pos,i,timestamp_eNB_rx[i]);
|
|
||||||
if ((bytes_sent = dev->eth_dev.trx_write_func (&dev->eth_dev,
|
|
||||||
timestamp_eNB_rx[i],
|
|
||||||
rx_eNB,
|
|
||||||
spp,
|
|
||||||
i,
|
|
||||||
0))<0){
|
|
||||||
perror("RRH eNB : sendto for RX");
|
|
||||||
}
|
}
|
||||||
|
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RXCNT, rx_pos );
|
||||||
|
if (dev->devs->type != NONE_IF) {
|
||||||
|
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_RF, 1 );
|
||||||
|
/* Read operation to RF device (RX)*/
|
||||||
|
if ( dev->devs->trx_read_func (dev->devs,
|
||||||
|
×tamp_rx,
|
||||||
|
rx_eNB,
|
||||||
|
spp_rf,
|
||||||
|
dev->devs->openair0_cfg.rx_num_channels
|
||||||
|
)<0) {
|
||||||
|
perror("RRH eNB : USRP read");
|
||||||
|
}
|
||||||
|
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_RF, 0 );
|
||||||
|
}
|
||||||
|
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_TS, timestamp_rx&0xffffffff );
|
||||||
|
|
||||||
|
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
|
||||||
|
if ((bytes_sent = dev->eth_dev.trx_write_func (&dev->eth_dev,
|
||||||
|
timestamp_rx,
|
||||||
|
rx_eNB,
|
||||||
|
spp_eth,
|
||||||
|
dev->eth_dev.openair0_cfg.rx_num_channels,
|
||||||
|
0))<0) {
|
||||||
|
perror("RRH eNB : ETHERNET write");
|
||||||
|
}
|
||||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
|
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
|
||||||
|
|
||||||
timestamp_eNB_rx[i]+=spp;
|
/* when there is no RF timestamp is updated by number of samples */
|
||||||
|
if (dev->devs->type == NONE_IF) {
|
||||||
|
timestamp_rx+=spp_eth;
|
||||||
last_hw_counter=hw_counter;
|
last_hw_counter=hw_counter;
|
||||||
|
}
|
||||||
|
|
||||||
if (measurements == 1 ) {
|
if (measurements == 1 ) {
|
||||||
|
|
||||||
@@ -474,7 +553,7 @@ void *rrh_eNB_rx_thread(void *arg){
|
|||||||
min_rx_time = total_rx_time;
|
min_rx_time = total_rx_time;
|
||||||
if (total_rx_time > max_rx_time){
|
if (total_rx_time > max_rx_time){
|
||||||
max_rx_time = total_rx_time;
|
max_rx_time = total_rx_time;
|
||||||
LOG_I(RRH,"Max value %d update at rx_position %d \n",total_rx_time,timestamp_eNB_rx[i]);
|
LOG_I(RRH,"Max value %d update at rx_position %d \n",total_rx_time,timestamp_rx);
|
||||||
}
|
}
|
||||||
average_rx_time = (long long unsigned int)((average_rx_time*trial)+total_rx_time)/(trial+1);
|
average_rx_time = (long long unsigned int)((average_rx_time*trial)+total_rx_time)/(trial+1);
|
||||||
}
|
}
|
||||||
@@ -493,31 +572,44 @@ void *rrh_eNB_rx_thread(void *arg){
|
|||||||
pthread_mutex_unlock(&sync_eNB_mutex[i]);
|
pthread_mutex_unlock(&sync_eNB_mutex[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}//for each antenna
|
rx_pos += spp_eth;
|
||||||
|
|
||||||
rx_pos += spp;
|
|
||||||
pck_rx++;
|
pck_rx++;
|
||||||
next_rx_pos=(rx_pos+spp);
|
next_rx_pos=(rx_pos+spp_eth);
|
||||||
|
|
||||||
|
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX, 0 );
|
||||||
|
/**/
|
||||||
|
if (frame>50) {
|
||||||
|
pthread_mutex_lock(&sync_trx_mutex);
|
||||||
|
while (sync_trx) {
|
||||||
|
pthread_cond_wait(&sync_trx_cond,&sync_trx_mutex);
|
||||||
|
}
|
||||||
|
sync_trx=1;
|
||||||
|
LOG_D(RRH,"out of while send:%d %d\n",sync_trx,frame);
|
||||||
|
pthread_cond_signal(&sync_trx_cond);
|
||||||
|
pthread_mutex_unlock(&sync_trx_mutex);
|
||||||
|
}
|
||||||
|
} // while
|
||||||
|
|
||||||
|
subframe++;
|
||||||
|
s_cnt=0;
|
||||||
|
|
||||||
|
/* wrap around rx buffer index */
|
||||||
if (next_rx_pos >= samples_per_frame)
|
if (next_rx_pos >= samples_per_frame)
|
||||||
next_rx_pos -= samples_per_frame;
|
next_rx_pos -= samples_per_frame;
|
||||||
if (rx_pos >= samples_per_frame)
|
if (rx_pos >= samples_per_frame)
|
||||||
rx_pos -= samples_per_frame;
|
rx_pos -= samples_per_frame;
|
||||||
|
/* wrap around subframe number */
|
||||||
|
if (subframe == 10 ) {
|
||||||
|
subframe = 0;
|
||||||
|
frame++;
|
||||||
|
}
|
||||||
|
|
||||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX, 0 );
|
|
||||||
} //while (eNB_exit==0)
|
} //while (eNB_exit==0)
|
||||||
return(0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! \fn void *rrh_eNB_tx_thread(void *arg)
|
|
||||||
* \brief this function
|
|
||||||
* \param[in]
|
|
||||||
* \param[out]
|
|
||||||
* \return
|
|
||||||
* \note
|
|
||||||
* @ingroup _oai
|
|
||||||
*/
|
|
||||||
void *rrh_eNB_tx_thread(void *arg) {
|
void *rrh_eNB_tx_thread(void *arg) {
|
||||||
|
|
||||||
struct timespec time0a,time0,time1,time2;
|
struct timespec time0a,time0,time1,time2;
|
||||||
@@ -525,10 +617,13 @@ void *rrh_eNB_tx_thread(void *arg){
|
|||||||
rrh_module_t *dev = (rrh_module_t *)arg;
|
rrh_module_t *dev = (rrh_module_t *)arg;
|
||||||
struct timespec time_req_1us, time_rem_1us;
|
struct timespec time_req_1us, time_rem_1us;
|
||||||
ssize_t bytes_received;
|
ssize_t bytes_received;
|
||||||
int spp,i;
|
int i;
|
||||||
openair0_timestamp last_hw_counter=0;
|
openair0_timestamp last_hw_counter=0;
|
||||||
unsigned int samples_per_frame=0;
|
unsigned int samples_per_frame=0,samples_per_subframe=0;
|
||||||
|
unsigned int spp_rf=0, spp_eth=0;
|
||||||
uint8_t loopback=0,measurements=0;
|
uint8_t loopback=0,measurements=0;
|
||||||
|
unsigned int subframe=0,frame=0;
|
||||||
|
unsigned int pck_tx=0;
|
||||||
|
|
||||||
#ifdef LOWLATENCY
|
#ifdef LOWLATENCY
|
||||||
struct sched_attr attr;
|
struct sched_attr attr;
|
||||||
@@ -540,9 +635,9 @@ void *rrh_eNB_tx_thread(void *arg){
|
|||||||
attr.sched_priority = 0;
|
attr.sched_priority = 0;
|
||||||
|
|
||||||
attr.sched_policy = SCHED_DEADLINE;
|
attr.sched_policy = SCHED_DEADLINE;
|
||||||
attr.sched_runtime = (0.1 * 100) * 10000; //
|
attr.sched_runtime = (0.8 * 100) * 10000;
|
||||||
attr.sched_deadline = rt_period;//0.1 * 1000000; //
|
attr.sched_deadline = (0.9 * 100) * 10000;
|
||||||
attr.sched_period = rt_period;//0.1 * 1000000; // each TX/RX thread has
|
attr.sched_period = 1 * 1000000;
|
||||||
|
|
||||||
if (sched_setattr(0, &attr, flags) < 0 ) {
|
if (sched_setattr(0, &attr, flags) < 0 ) {
|
||||||
perror("[SCHED] eNB TX thread: sched_setattr failed\n");
|
perror("[SCHED] eNB TX thread: sched_setattr failed\n");
|
||||||
@@ -550,24 +645,40 @@ void *rrh_eNB_tx_thread(void *arg){
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
tx_pos=0;
|
time_req_1us.tv_sec = 1;
|
||||||
time_req_1us.tv_sec = 0;
|
time_req_1us.tv_nsec = 0;
|
||||||
time_req_1us.tv_nsec = 1000;
|
spp_eth = dev->eth_dev.openair0_cfg.samples_per_packet;
|
||||||
spp = dev->eth_dev.openair0_cfg.samples_per_packet;
|
spp_rf = dev->devs->openair0_cfg.samples_per_packet;
|
||||||
samples_per_frame = dev->eth_dev.openair0_cfg.samples_per_frame;
|
samples_per_frame = dev->eth_dev.openair0_cfg.samples_per_frame;
|
||||||
|
samples_per_subframe = (unsigned int)samples_per_frame/10;
|
||||||
|
tx_pos=0;
|
||||||
|
//tx_pos_rf=spp_rf*dev->devs->openair0_cfg.tx_delay;
|
||||||
|
|
||||||
loopback = dev->loopback;
|
loopback = dev->loopback;
|
||||||
measurements = dev->measurements;
|
measurements = dev->measurements;
|
||||||
|
|
||||||
while (rrh_exit == 0) {
|
while (rrh_exit == 0) {
|
||||||
|
while (tx_pos < (1 + subframe)*samples_per_subframe) {
|
||||||
|
|
||||||
|
LOG_D(RRH,"bef lock read:%d %d\n",sync_trx,frame);
|
||||||
|
pthread_mutex_lock(&sync_trx_mutex);
|
||||||
|
|
||||||
|
while (!sync_trx) {
|
||||||
|
LOG_D(RRH,"in sync read:%d %d\n",sync_trx,frame);
|
||||||
|
pthread_cond_wait(&sync_trx_cond,&sync_trx_mutex);
|
||||||
|
}
|
||||||
|
LOG_D(RRH,"out of while read:%d %d\n",sync_trx,frame);
|
||||||
|
|
||||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX, 1 );
|
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX, 1 );
|
||||||
|
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME, frame);
|
||||||
|
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME, subframe );
|
||||||
|
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_PCK, pck_tx );
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (dev->devs->type == NONE_IF) {
|
||||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_HWCNT, hw_counter );
|
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_HWCNT, hw_counter );
|
||||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_LHWCNT, last_hw_counter );
|
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_LHWCNT, last_hw_counter );
|
||||||
|
|
||||||
if (measurements == 1 )
|
|
||||||
clock_gettime(CLOCK_MONOTONIC,&time0a);
|
|
||||||
|
|
||||||
for (i=0; i<dev->eth_dev.openair0_cfg.tx_num_channels; i++){
|
|
||||||
if (!eNB_tx_started) {
|
if (!eNB_tx_started) {
|
||||||
eNB_tx_started=1; // set this flag to 1 to indicate that eNB started
|
eNB_tx_started=1; // set this flag to 1 to indicate that eNB started
|
||||||
if (RT_flag_eNB==1) {
|
if (RT_flag_eNB==1) {
|
||||||
@@ -578,7 +689,7 @@ void *rrh_eNB_tx_thread(void *arg){
|
|||||||
if (hw_counter > last_hw_counter+1) {
|
if (hw_counter > last_hw_counter+1) {
|
||||||
printf("LT");
|
printf("LT");
|
||||||
} else {
|
} else {
|
||||||
while (hw_counter < last_hw_counter+1){
|
while ((hw_counter < last_hw_counter+1)) {
|
||||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX_SLEEP, 1 );
|
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX_SLEEP, 1 );
|
||||||
nanosleep(&time_req_1us,&time_rem_1us);
|
nanosleep(&time_req_1us,&time_rem_1us);
|
||||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX_SLEEP, 0 );
|
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX_SLEEP, 0 );
|
||||||
@@ -586,30 +697,44 @@ void *rrh_eNB_tx_thread(void *arg){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
if (measurements == 1 )
|
if (measurements == 1 ) clock_gettime(CLOCK_MONOTONIC,&time1);
|
||||||
clock_gettime(CLOCK_MONOTONIC,&time1);
|
for (i=0; i<dev->eth_dev.openair0_cfg.tx_num_channels; i++) tx_eNB[i] = (void*)&tx_buffer_eNB[i][tx_pos]; //RF!!!!!
|
||||||
|
|
||||||
tx_eNB[i] = (void*)&tx_buffer_eNB[i][tx_pos];
|
|
||||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TXCNT, tx_pos );
|
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TXCNT, tx_pos );
|
||||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 );
|
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 );
|
||||||
bytes_received = dev->eth_dev.trx_read_func(&dev->eth_dev,
|
|
||||||
×tamp_eNB_tx[i],
|
/* Read operation to ETHERNET device */
|
||||||
|
if (( bytes_received = dev->eth_dev.trx_read_func(&dev->eth_dev,
|
||||||
|
×tamp_tx,
|
||||||
tx_eNB,
|
tx_eNB,
|
||||||
spp,
|
spp_eth,
|
||||||
i);
|
dev->eth_dev.openair0_cfg.tx_num_channels))<0) {
|
||||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
|
perror("RRH eNB : ETHERNET read");
|
||||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_TS, timestamp_eNB_tx[i]&0xffffffff );
|
|
||||||
if (NRT_flag_eNB==1) {
|
|
||||||
nrt_eNB_counter[i]++;
|
|
||||||
}
|
}
|
||||||
prev_tx_pos=tx_pos;
|
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
|
||||||
tx_pos += spp;
|
|
||||||
|
|
||||||
if (tx_pos >= samples_per_frame)
|
if (dev->devs->type != NONE_IF) {
|
||||||
tx_pos -= samples_per_frame;
|
LOG_D(RRH," tx_buffer_eNB[i][tx_pos]=%x t_buffer_eNB[i][tx_pos+1]=%x t_buffer_eNB[i][tx_pos+2]=%x \n",tx_buffer_eNB[0][tx_pos],tx_buffer_eNB[0][tx_pos+1],tx_buffer_eNB[0][tx_pos+2]);
|
||||||
|
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_RF, 1 );
|
||||||
|
/* Write operation to RF device (TX)*/
|
||||||
|
if ( dev->devs->trx_write_func (dev->devs,
|
||||||
|
timestamp_tx,
|
||||||
|
tx_eNB,
|
||||||
|
spp_rf,
|
||||||
|
dev->devs->openair0_cfg.tx_num_channels,
|
||||||
|
0)<0){
|
||||||
|
perror("RRH eNB : USRP write");
|
||||||
|
}
|
||||||
|
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_RF, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_TS, timestamp_tx&0xffffffff );
|
||||||
|
|
||||||
|
|
||||||
|
if (dev->devs->type == NONE_IF) last_hw_counter=hw_counter;
|
||||||
|
|
||||||
last_hw_counter=hw_counter;
|
|
||||||
|
|
||||||
if (loopback ==1 ) {
|
if (loopback ==1 ) {
|
||||||
while (sync_eNB_rx[i]==0)
|
while (sync_eNB_rx[i]==0)
|
||||||
@@ -620,28 +745,45 @@ void *rrh_eNB_tx_thread(void *arg){
|
|||||||
pthread_mutex_unlock(&sync_eNB_mutex[i]);
|
pthread_mutex_unlock(&sync_eNB_mutex[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
if (measurements == 1 ) {
|
if (measurements == 1 ) {
|
||||||
clock_gettime(CLOCK_MONOTONIC,&time2);
|
clock_gettime(CLOCK_MONOTONIC,&time2);
|
||||||
memcpy(&time0,&time2,sizeof(struct timespec));
|
memcpy(&time0,&time2,sizeof(struct timespec));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prev_tx_pos=tx_pos;
|
||||||
|
tx_pos += spp_eth;
|
||||||
|
pck_tx++;
|
||||||
|
|
||||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX, 0 );
|
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX, 0 );
|
||||||
}
|
sync_trx=0;
|
||||||
return(0);
|
pthread_cond_signal(&sync_trx_cond);
|
||||||
|
pthread_mutex_unlock(&sync_trx_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
//needs to be fixed
|
/* wrap around tx buffer index */
|
||||||
void set_rt_period( openair0_config_t openair0_cfg){
|
if (tx_pos >= samples_per_frame)
|
||||||
|
tx_pos -= samples_per_frame;
|
||||||
|
/* wrap around subframe number */
|
||||||
|
subframe++;
|
||||||
|
if (subframe == 10 ) {
|
||||||
|
subframe = 0; // the radio frame is complete, start over
|
||||||
|
frame++;
|
||||||
|
}
|
||||||
|
|
||||||
|
} //while (eNB_exit==0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void calc_rt_period_ns( openair0_config_t openair0_cfg) {
|
||||||
|
|
||||||
rt_period= (double)(openair0_cfg.samples_per_packet/(openair0_cfg.samples_per_frame/10.0)*1000000);
|
rt_period= (double)(openair0_cfg.samples_per_packet/(openair0_cfg.samples_per_frame/10.0)*1000000);
|
||||||
AssertFatal(rt_period > 0, "Invalid rt period !%u\n", rt_period);
|
AssertFatal(rt_period > 0, "Invalid rt period !%u\n", rt_period);
|
||||||
//only in case of NRT with emulated UE
|
LOG_I(RRH,"[eNB] Real time period is set to %u ns\n", rt_period);
|
||||||
//create_timer_thread();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void check_dev_config( rrh_module_t *mod_enb) {
|
static void check_dev_config( rrh_module_t *mod_enb) {
|
||||||
|
|
||||||
|
|
||||||
AssertFatal( (mod_enb->devs->openair0_cfg.num_rb_dl==100 || mod_enb->devs->openair0_cfg.num_rb_dl==50 || mod_enb->devs->openair0_cfg.num_rb_dl==25 || mod_enb->devs->openair0_cfg.num_rb_dl==6) , "Invalid number of resource blocks! %d\n", mod_enb->devs->openair0_cfg.num_rb_dl);
|
AssertFatal( (mod_enb->devs->openair0_cfg.num_rb_dl==100 || mod_enb->devs->openair0_cfg.num_rb_dl==50 || mod_enb->devs->openair0_cfg.num_rb_dl==25 || mod_enb->devs->openair0_cfg.num_rb_dl==6) , "Invalid number of resource blocks! %d\n", mod_enb->devs->openair0_cfg.num_rb_dl);
|
||||||
@@ -656,7 +798,7 @@ void check_dev_config( rrh_module_t *mod_enb) {
|
|||||||
AssertFatal( mod_enb->devs->openair0_cfg.tx_gain[0] > 0.0 ,"Invalid TX gain! %f\n", mod_enb->devs->openair0_cfg.tx_gain[0]);
|
AssertFatal( mod_enb->devs->openair0_cfg.tx_gain[0] > 0.0 ,"Invalid TX gain! %f\n", mod_enb->devs->openair0_cfg.tx_gain[0]);
|
||||||
AssertFatal( mod_enb->devs->openair0_cfg.rx_bw > 0.0 ,"Invalid RX bw! %f\n", mod_enb->devs->openair0_cfg.rx_bw);
|
AssertFatal( mod_enb->devs->openair0_cfg.rx_bw > 0.0 ,"Invalid RX bw! %f\n", mod_enb->devs->openair0_cfg.rx_bw);
|
||||||
AssertFatal( mod_enb->devs->openair0_cfg.tx_bw > 0.0 ,"Invalid RX bw! %f\n", mod_enb->devs->openair0_cfg.tx_bw);
|
AssertFatal( mod_enb->devs->openair0_cfg.tx_bw > 0.0 ,"Invalid RX bw! %f\n", mod_enb->devs->openair0_cfg.tx_bw);
|
||||||
// AssertFatal( mod_enb->devs->openair0_cfg.autocal[0] > 0 , "Invalid auto calibration choice! %d\n", mod_enb->devs->openair0_cfg.autocal[0]);
|
AssertFatal( mod_enb->devs->openair0_cfg.autocal[0] > 0 , "Invalid auto calibration choice! %d\n", mod_enb->devs->openair0_cfg.autocal[0]);
|
||||||
|
|
||||||
printf("\n---------------------RF device configuration parameters---------------------\n");
|
printf("\n---------------------RF device configuration parameters---------------------\n");
|
||||||
|
|
||||||
|
|||||||
@@ -2992,22 +2992,6 @@ openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL;
|
|||||||
openair0.func_type = BBU_FUNC;
|
openair0.func_type = BBU_FUNC;
|
||||||
openair0_cfg[0].log_level = glog_level;
|
openair0_cfg[0].log_level = glog_level;
|
||||||
|
|
||||||
#ifdef ETHERNET
|
|
||||||
openair0.type=ETH_IF; // not used for the moment
|
|
||||||
openair0.func_type = BBU_FUNC;
|
|
||||||
openair0_dev_init_eth(&openair0, &openair0_cfg[0]);
|
|
||||||
#else
|
|
||||||
#ifdef EXMIMO
|
|
||||||
openair0.type=EXMIMO_IF;
|
|
||||||
printf("Setting the HW to EXMIMO and initializing openair0 ...\n");
|
|
||||||
#elif OAI_USRP
|
|
||||||
openair0.type=USRP_IF;
|
|
||||||
printf("Setting the HW to USRP and initializing openair0 ...\n");
|
|
||||||
#elif OAI_BLADERF
|
|
||||||
openair0.type=BLADERF_IF;
|
|
||||||
printf("Setting the HW to BLADERF and initializing openair0 ...\n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ((mode!=loop_through_memory) &&
|
if ((mode!=loop_through_memory) &&
|
||||||
(openair0_device_init(&openair0, &openair0_cfg[0]) <0)) {
|
(openair0_device_init(&openair0, &openair0_cfg[0]) <0)) {
|
||||||
printf("Exiting, cannot initialize device\n");
|
printf("Exiting, cannot initialize device\n");
|
||||||
@@ -3015,7 +2999,6 @@ openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL;
|
|||||||
}
|
}
|
||||||
else if (mode==loop_through_memory) {
|
else if (mode==loop_through_memory) {
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
printf("Done\n");
|
printf("Done\n");
|
||||||
|
|
||||||
|
|||||||
@@ -58,8 +58,8 @@
|
|||||||
#define RRH_UE_PORT 51000
|
#define RRH_UE_PORT 51000
|
||||||
#define RRH_UE_DEST_IP "127.0.0.1"
|
#define RRH_UE_DEST_IP "127.0.0.1"
|
||||||
|
|
||||||
#define FRAME_MAX_SIZE 307200
|
#define FRAME_MAX_SIZE 307200//76800
|
||||||
#define DEFAULT_PERIOD_NS 133333
|
#define DEFAULT_PERIOD_NS 133333//200000
|
||||||
|
|
||||||
#define START_CMD 1
|
#define START_CMD 1
|
||||||
#define PRINTF_PERIOD 3750
|
#define PRINTF_PERIOD 3750
|
||||||
|
|||||||
+24
-16
@@ -1,25 +1,29 @@
|
|||||||
[*]
|
[*]
|
||||||
[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI
|
[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI
|
||||||
[*] Thu Jul 9 09:53:25 2015
|
[*] Thu Sep 17 14:23:43 2015
|
||||||
[*]
|
[*]
|
||||||
[dumpfile] "/tmp/openair_dump_rrh.vcd"
|
[dumpfile] "/tmp/openair_dump_rrh.vcd"
|
||||||
[dumpfile_mtime] "Thu Jul 9 09:52:29 2015"
|
[dumpfile_mtime] "Thu Sep 17 14:21:43 2015"
|
||||||
[dumpfile_size] 170586112
|
[dumpfile_size] 636509125
|
||||||
[savefile] "/home/sud/openair4G/targets/RT/USER/eNB2.gtkw"
|
[savefile] "/home/guepe/openair4G/targets/RT/USER/rrh.gtkw"
|
||||||
[timestart] 16177999000
|
[timestart] 17746655400
|
||||||
[size] 1535 876
|
[size] 1855 1056
|
||||||
[pos] -1 -1
|
[pos] -1 -1
|
||||||
*-17.749426 16178576148 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
|
*-15.826077 17746846200 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
|
||||||
[sst_width] 224
|
[sst_width] 224
|
||||||
[signals_width] 230
|
[signals_width] 230
|
||||||
[sst_expanded] 1
|
[sst_expanded] 1
|
||||||
[sst_vpaned_height] 230
|
[sst_vpaned_height] 287
|
||||||
|
@24
|
||||||
|
[color] 1
|
||||||
|
variables.hw_frame_rx[63:0]
|
||||||
|
[color] 1
|
||||||
|
variables.hw_subframe_rx[63:0]
|
||||||
@28
|
@28
|
||||||
[color] 1
|
[color] 1
|
||||||
functions.eNB_rx
|
functions.eNB_rx
|
||||||
functions.eNB_rx_sleep
|
functions.eNB_rx_sleep
|
||||||
[color] 7
|
functions.trx_write_rf
|
||||||
functions.trx_write
|
|
||||||
@c00024
|
@c00024
|
||||||
variables.rxcnt[63:0]
|
variables.rxcnt[63:0]
|
||||||
@28
|
@28
|
||||||
@@ -89,23 +93,27 @@ variables.rxcnt[63:0]
|
|||||||
(63)variables.rxcnt[63:0]
|
(63)variables.rxcnt[63:0]
|
||||||
@1401200
|
@1401200
|
||||||
-group_end
|
-group_end
|
||||||
|
@24
|
||||||
|
variables.pck_rx[63:0]
|
||||||
|
variables.hw_frame[63:0]
|
||||||
|
variables.hw_subframe[63:0]
|
||||||
@28
|
@28
|
||||||
[color] 1
|
[color] 1
|
||||||
functions.eNB_tx
|
functions.eNB_tx
|
||||||
functions.eNB_tx_sleep
|
functions.eNB_tx_sleep
|
||||||
|
functions.trx_read_rf
|
||||||
|
[color] 7
|
||||||
|
functions.trx_write
|
||||||
[color] 7
|
[color] 7
|
||||||
functions.trx_read
|
functions.trx_read
|
||||||
@24
|
@24
|
||||||
variables.txcnt[63:0]
|
variables.txcnt[63:0]
|
||||||
variables.rx_ts[63:0]
|
variables.rx_ts[63:0]
|
||||||
variables.tx_ts[63:0]
|
variables.tx_ts[63:0]
|
||||||
variables.pck_rx[63:0]
|
|
||||||
variables.hw_cnt_rx[63:0]
|
variables.hw_cnt_rx[63:0]
|
||||||
variables.lhw_cnt_rx[63:0]
|
variables.lhw_cnt_rx[63:0]
|
||||||
variables.hw_frame[63:0]
|
@25
|
||||||
@28
|
[color] 3
|
||||||
functions.eNB_tm
|
variables.cnt[63:0]
|
||||||
@29
|
|
||||||
functions.eNB_trx
|
|
||||||
[pattern_trace] 1
|
[pattern_trace] 1
|
||||||
[pattern_trace] 0
|
[pattern_trace] 0
|
||||||
|
|||||||
+137
-287
@@ -60,17 +60,17 @@
|
|||||||
#include "log_extern.h"
|
#include "log_extern.h"
|
||||||
#include "vcd_signal_dumper.h"
|
#include "vcd_signal_dumper.h"
|
||||||
|
|
||||||
//#undef LOWLATENCY
|
/*****************************************************************************************
|
||||||
|
* ---------- *
|
||||||
|
* ------- RRH_BBU_IF ------- RRH_RF_IF -------USRP - COTS_UE- *
|
||||||
|
* - BBU - --------------- - RRH - ------------- -------BLADERF ---------- *
|
||||||
|
* ------- ------- -------EXMIMO *
|
||||||
|
* --------- *
|
||||||
|
* -------ETH_IF - EMU_UE- *
|
||||||
|
* --------- *
|
||||||
|
*****************************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
** FUNCTION PROTOTYPES **
|
|
||||||
******************************************************************************/
|
|
||||||
static void debug_init(void);
|
|
||||||
static void get_options(int argc, char *argv[]);
|
|
||||||
static void print_help(void);
|
|
||||||
static void get_RFinterfaces(void);
|
|
||||||
static rrh_module_t new_module(unsigned int id);
|
|
||||||
int get_ip_address(char* if_name);
|
|
||||||
|
|
||||||
char rrh_ip[20] = "192.168.12.242"; // there is code to detect the my ip address
|
char rrh_ip[20] = "192.168.12.242"; // there is code to detect the my ip address
|
||||||
int rrh_port = 50000; // has to be an option
|
int rrh_port = 50000; // has to be an option
|
||||||
@@ -98,22 +98,48 @@ uint8_t measurements_flag=0;
|
|||||||
|
|
||||||
/* Default operation as RRH:
|
/* Default operation as RRH:
|
||||||
- there are neither eNB nor UE modules
|
- there are neither eNB nor UE modules
|
||||||
- no RF device is asscociated with RRH */
|
- no RF hardware is specified (NONE_IF)
|
||||||
|
- default ethernet interface is local */
|
||||||
uint8_t num_eNB_mod=0;
|
uint8_t num_eNB_mod=0;
|
||||||
uint8_t num_UE_mod=0;
|
uint8_t num_UE_mod=0;
|
||||||
uint8_t num_EXMIMO_mod=0;
|
uint8_t num_EXMIMO_mod=0;
|
||||||
uint8_t num_USRP_mod=0;
|
uint8_t num_USRP_mod=0;
|
||||||
uint8_t hardware_target=NONE_IF;
|
uint8_t hardware_target=NONE_IF;
|
||||||
|
char* if_name="lo";
|
||||||
|
|
||||||
rrh_module_t *enb_array;
|
rrh_module_t *enb_array;
|
||||||
rrh_module_t *ue_array;
|
rrh_module_t *ue_array;
|
||||||
|
|
||||||
pthread_mutex_t timer_mutex;
|
|
||||||
openair0_vtimestamp hw_counter=0;
|
openair0_vtimestamp hw_counter=0;
|
||||||
unsigned int rt_period=0;
|
|
||||||
struct itimerspec timerspec;
|
|
||||||
|
|
||||||
char* if_name="lo";
|
|
||||||
|
|
||||||
|
|
||||||
|
static void debug_init(void);
|
||||||
|
static void get_options(int argc, char *argv[]);
|
||||||
|
static void print_help(void);
|
||||||
|
|
||||||
|
/*!\fn static rrh_module_t new_module(unsigned int id);
|
||||||
|
* \brief creation of a eNB/UE module
|
||||||
|
* \param[in] module id
|
||||||
|
* \return module
|
||||||
|
* \note
|
||||||
|
* @ingroup _oai
|
||||||
|
*/
|
||||||
|
static rrh_module_t new_module(unsigned int id);
|
||||||
|
|
||||||
|
/*!\fn static int get_ip_address(char* if_name)
|
||||||
|
* \brief retrieves IP address from the specified network interface
|
||||||
|
* \param[in] name of network interface
|
||||||
|
* \return 0
|
||||||
|
* \note
|
||||||
|
* @ingroup _oai
|
||||||
|
*/
|
||||||
|
static int get_ip_address(char* if_name);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
|
|
||||||
@@ -128,55 +154,13 @@ int main(int argc, char **argv) {
|
|||||||
/* make a graceful exit when ctrl-c is pressed */
|
/* make a graceful exit when ctrl-c is pressed */
|
||||||
signal(SIGSEGV, signal_handler);
|
signal(SIGSEGV, signal_handler);
|
||||||
signal(SIGINT, signal_handler);
|
signal(SIGINT, signal_handler);
|
||||||
/*probe RF front end devices interfaced to RRH */
|
|
||||||
// get_RFinterfaces();
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef ETHERNET
|
|
||||||
int error_code_timer;
|
|
||||||
pthread_t main_timer_proc_thread;
|
|
||||||
|
|
||||||
LOG_I(RRH,"Creating timer thread with rt period %d ns.\n",rt_period);
|
|
||||||
|
|
||||||
/* setup the timer to generate an interrupt:
|
|
||||||
-for the first time in (sample_per_packet/sample_rate) ns
|
|
||||||
-and then every (sample_per_packet/sample_rate) ns */
|
|
||||||
timerspec.it_value.tv_sec = rt_period/1000000000;
|
|
||||||
timerspec.it_value.tv_nsec = rt_period%1000000000;
|
|
||||||
timerspec.it_interval.tv_sec = rt_period/1000000000;
|
|
||||||
timerspec.it_interval.tv_nsec = rt_period%1000000000;
|
|
||||||
|
|
||||||
|
|
||||||
//#ifndef LOWLATENCY
|
|
||||||
pthread_attr_t attr_timer;
|
|
||||||
struct sched_param sched_param_timer;
|
|
||||||
|
|
||||||
pthread_attr_init(&attr_timer);
|
|
||||||
sched_param_timer.sched_priority = sched_get_priority_max(SCHED_FIFO);
|
|
||||||
pthread_attr_setschedparam(&attr_timer,&sched_param_timer);
|
|
||||||
pthread_attr_setschedpolicy(&attr_timer,SCHED_FIFO);
|
|
||||||
|
|
||||||
pthread_mutex_init(&timer_mutex,NULL);
|
|
||||||
|
|
||||||
error_code_timer = pthread_create(&main_timer_proc_thread, &attr_timer, timer_proc, (void *)&timerspec);
|
|
||||||
LOG_I(RRH,"[SCHED] FIFO scheduling applied to timer thread \n");
|
|
||||||
/*#else
|
|
||||||
error_code_timer = pthread_create(&main_timer_proc_thread, NULL, timer_proc, (void *)&timerspec);
|
|
||||||
LOG_I(RRH,"[SCHED] deadline scheduling applied to timer thread \n");
|
|
||||||
#endif*/
|
|
||||||
|
|
||||||
if (error_code_timer) {
|
|
||||||
LOG_E(RRH,"Error while creating timer proc thread\n");
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* create modules based on input arguments */
|
/* create modules based on input arguments */
|
||||||
if (eNB_flag==1){
|
if (eNB_flag==1){
|
||||||
enb_array=(rrh_module_t*)malloc(num_eNB_mod*sizeof(rrh_module_t));
|
enb_array=(rrh_module_t*)malloc(num_eNB_mod*sizeof(rrh_module_t));
|
||||||
for(i=0;i<num_eNB_mod;i++){
|
for(i=0;i<num_eNB_mod;i++){
|
||||||
enb_array[i]=new_module(i);//enb_array[i]=new_module(i, get_RF_interfaces(&hardware_target));
|
enb_array[i]=new_module(i);//enb_array[i]=new_module(i, get_RF_interfaces(&hardware_target));
|
||||||
create_eNB_trx_threads(&enb_array[i],RT_flag,NRT_flag);
|
config_BBU_mod(&enb_array[i],RT_flag,NRT_flag);
|
||||||
LOG_I(RRH,"[eNB %d] module(s) created (out of %u) \n",i,num_eNB_mod);
|
LOG_I(RRH,"[eNB %d] module(s) created (out of %u) \n",i,num_eNB_mod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -184,7 +168,7 @@ int main(int argc, char **argv) {
|
|||||||
ue_array=(rrh_module_t*)malloc(num_UE_mod*sizeof(rrh_module_t));
|
ue_array=(rrh_module_t*)malloc(num_UE_mod*sizeof(rrh_module_t));
|
||||||
for(i=0;i<num_UE_mod;i++){
|
for(i=0;i<num_UE_mod;i++){
|
||||||
ue_array[i]=new_module(i);
|
ue_array[i]=new_module(i);
|
||||||
create_UE_trx_threads(&ue_array[i],RT_flag,NRT_flag);
|
config_UE_mod(&ue_array[i],RT_flag,NRT_flag);
|
||||||
LOG_I(RRH,"[UE %d] module(s) created (out of %u)\n",i, num_UE_mod);
|
LOG_I(RRH,"[UE %d] module(s) created (out of %u)\n",i, num_UE_mod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -194,22 +178,10 @@ int main(int argc, char **argv) {
|
|||||||
while (rrh_exit==0)
|
while (rrh_exit==0)
|
||||||
sleep(1);
|
sleep(1);
|
||||||
|
|
||||||
//close sockets
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!\fn openair0_device new_module (unsigned int id, dev_type_t type)
|
|
||||||
* \brief this function
|
|
||||||
* \param[in]
|
|
||||||
* \param[out]
|
|
||||||
* \return
|
|
||||||
* \note
|
|
||||||
* @ingroup _oai
|
|
||||||
*/
|
|
||||||
static rrh_module_t new_module (unsigned int id) {
|
static rrh_module_t new_module (unsigned int id) {
|
||||||
|
|
||||||
rrh_module_t rrh_mod;
|
rrh_module_t rrh_mod;
|
||||||
@@ -221,7 +193,9 @@ static rrh_module_t new_module (unsigned int id) {
|
|||||||
|
|
||||||
/* each module is associated with an ethernet device */
|
/* each module is associated with an ethernet device */
|
||||||
rrh_mod.eth_dev.type=ETH_IF;
|
rrh_mod.eth_dev.type=ETH_IF;
|
||||||
|
/* ethernet device is functioning within RRH */
|
||||||
rrh_mod.eth_dev.func_type=RRH_FUNC;
|
rrh_mod.eth_dev.func_type=RRH_FUNC;
|
||||||
|
/* specify IP address */
|
||||||
get_ip_address(if_name);
|
get_ip_address(if_name);
|
||||||
openair0_cfg.my_ip=&rrh_ip[0];
|
openair0_cfg.my_ip=&rrh_ip[0];
|
||||||
openair0_cfg.my_port=rrh_port;
|
openair0_cfg.my_port=rrh_port;
|
||||||
@@ -232,7 +206,7 @@ static rrh_module_t new_module (unsigned int id) {
|
|||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* specify associated RF device */
|
/* allocate space and specify associated RF device */
|
||||||
openair0_device *oai_dv = (openair0_device *)malloc(sizeof(openair0_device));
|
openair0_device *oai_dv = (openair0_device *)malloc(sizeof(openair0_device));
|
||||||
memset(oai_dv,0, sizeof(openair0_device));
|
memset(oai_dv,0, sizeof(openair0_device));
|
||||||
|
|
||||||
@@ -257,119 +231,6 @@ static rrh_module_t new_module (unsigned int id) {
|
|||||||
return rrh_mod;
|
return rrh_mod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*! \fn void *timer_proc(void *arg)
|
|
||||||
* \brief this function
|
|
||||||
* \param[in]
|
|
||||||
* \param[out]
|
|
||||||
* \return
|
|
||||||
* \note
|
|
||||||
* @ingroup _oai
|
|
||||||
*/
|
|
||||||
void *timer_proc(void *arg) {
|
|
||||||
|
|
||||||
timer_t timerid;
|
|
||||||
struct itimerspec *timer= (struct itimerspec *)arg ; // the timer data structure
|
|
||||||
struct itimerspec *old_value;
|
|
||||||
|
|
||||||
/*
|
|
||||||
#ifdef LOWLATENCY
|
|
||||||
struct sched_attr attr;
|
|
||||||
unsigned int flags = 0;
|
|
||||||
|
|
||||||
attr.size = sizeof(attr);
|
|
||||||
attr.sched_flags = 0;
|
|
||||||
attr.sched_nice = 0;
|
|
||||||
attr.sched_priority = 0;
|
|
||||||
|
|
||||||
attr.sched_policy = SCHED_DEADLINE;
|
|
||||||
attr.sched_runtime = (0.1 * 100) * 10000; //
|
|
||||||
attr.sched_deadline = rt_period-30000;//(0.1 * 100) * 10000; //
|
|
||||||
attr.sched_period = rt_period;//(0.1 * 100) * 10000; // each TX/RX thread has, as a function of RT PERIOD ??
|
|
||||||
|
|
||||||
if (sched_setattr(0, &attr, flags) < 0 ) {
|
|
||||||
perror("[SCHED] timer thread: sched_setattr failed\n");
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
*/
|
|
||||||
if (timer_create (CLOCK_REALTIME, NULL, &timerid) == -1) {
|
|
||||||
fprintf (stderr, "couldn't create a timer\n");
|
|
||||||
perror (NULL);
|
|
||||||
exit (EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
signal(SIGALRM, timer_signal_handler);
|
|
||||||
LOG_I(RRH,"Timer has started!\n");
|
|
||||||
timer_settime (timerid, 0, timer, old_value);
|
|
||||||
|
|
||||||
while (!rrh_exit) {
|
|
||||||
sleep(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
timer_delete(timerid);
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*! \fn void timer_signal_handler(int sig)
|
|
||||||
* \brief this function
|
|
||||||
* \param[in]
|
|
||||||
* \param[out]
|
|
||||||
* \return
|
|
||||||
* \note
|
|
||||||
* @ingroup _oai
|
|
||||||
*/
|
|
||||||
void timer_signal_handler(int sig) {
|
|
||||||
|
|
||||||
if (sig == SIGALRM) {
|
|
||||||
pthread_mutex_lock(&timer_mutex);
|
|
||||||
hw_counter ++;
|
|
||||||
pthread_mutex_unlock(&timer_mutex);
|
|
||||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME, hw_counter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*! \fn void signal_handler(int sig)
|
|
||||||
* \brief this function
|
|
||||||
* \param[in]
|
|
||||||
* \param[out]
|
|
||||||
* \return
|
|
||||||
* \note
|
|
||||||
* @ingroup _oai
|
|
||||||
*/
|
|
||||||
void signal_handler(int sig) {
|
|
||||||
|
|
||||||
void *array[10];
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
if (sig==SIGSEGV) {
|
|
||||||
// get void*'s for all entries on the stack
|
|
||||||
size = backtrace(array, 10);
|
|
||||||
|
|
||||||
// print out all the frames to stderr
|
|
||||||
fprintf(stderr, "Error: signal %d:\n", sig);
|
|
||||||
backtrace_symbols_fd(array, size, 2);
|
|
||||||
exit(-1);
|
|
||||||
} else {
|
|
||||||
printf("trying to exit gracefully...\n");
|
|
||||||
rrh_exit = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*! \fn void debug_init(void)
|
|
||||||
* \brief this function
|
|
||||||
* \param[in]
|
|
||||||
* \param[out]
|
|
||||||
* \return
|
|
||||||
* \note
|
|
||||||
* @ingroup _oai
|
|
||||||
*/
|
|
||||||
static void debug_init(void) {
|
static void debug_init(void) {
|
||||||
|
|
||||||
// log initialization
|
// log initialization
|
||||||
@@ -387,14 +248,7 @@ static void debug_init(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!\fn void get_options(int argc, char *argv[])
|
|
||||||
* \brief this function
|
|
||||||
* \param[in]
|
|
||||||
* \param[out]
|
|
||||||
* \return
|
|
||||||
* \note
|
|
||||||
* @ingroup _oai
|
|
||||||
*/
|
|
||||||
static void get_options(int argc, char *argv[]) {
|
static void get_options(int argc, char *argv[]) {
|
||||||
|
|
||||||
int opt;
|
int opt;
|
||||||
@@ -457,45 +311,35 @@ static void get_options(int argc, char *argv[]) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!\fn void print_help(void)
|
static int get_ip_address(char* if_name) {
|
||||||
* \brief this function
|
|
||||||
* \param[in]
|
|
||||||
* \param[out]
|
|
||||||
* \return
|
|
||||||
* \note
|
|
||||||
* @ingroup _oai
|
|
||||||
*/
|
|
||||||
int get_ip_address(char* if_name) {
|
|
||||||
|
|
||||||
int fd;
|
int fd;
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
|
|
||||||
|
|
||||||
fd = socket(AF_INET, SOCK_DGRAM, 0);
|
fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
|
||||||
/* I want to get an IPv4 IP address */
|
/* I want to get an IPv4 IP address */
|
||||||
ifr.ifr_addr.sa_family = AF_INET;
|
ifr.ifr_addr.sa_family = AF_INET;
|
||||||
|
|
||||||
/* I want IP address attached to "eth0" */
|
/* I want IP address attached to "if_name" */
|
||||||
strncpy(ifr.ifr_name, if_name, IFNAMSIZ-1);
|
strncpy(ifr.ifr_name, if_name, IFNAMSIZ-1);
|
||||||
|
|
||||||
ioctl(fd, SIOCGIFADDR, &ifr);
|
if ( ioctl(fd, SIOCGIFADDR, &ifr)<0 ) {
|
||||||
|
perror("IOCTL:");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
/* display result */
|
/* display result */
|
||||||
snprintf(&rrh_ip[0],20,"%s", inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
|
snprintf(&rrh_ip[0],20,"%s", inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
|
||||||
printf("Got IP address %s from interface %s\n", rrh_ip,if_name);
|
LOG_I(RRH,"Got IP address %s from interface %s\n", rrh_ip,if_name);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!\fn void print_help(void)
|
|
||||||
* \brief this function
|
|
||||||
* \param[in]
|
|
||||||
* \param[out]
|
|
||||||
* \return
|
|
||||||
* \note
|
|
||||||
* @ingroup _oai
|
|
||||||
*/
|
|
||||||
static void print_help(void) {
|
static void print_help(void) {
|
||||||
|
|
||||||
puts("Usage: \n");
|
puts("Usage: \n");
|
||||||
@@ -504,7 +348,7 @@ static void print_help(void) {
|
|||||||
puts("\t -n create eNB module\n");
|
puts("\t -n create eNB module\n");
|
||||||
puts("\t -u create UE module\n");
|
puts("\t -u create UE module\n");
|
||||||
puts("\t -g define global log level\n");
|
puts("\t -g define global log level\n");
|
||||||
puts("\t -i set the RRH interface (default eth0)\n");
|
puts("\t -i set the RRH interface (default lo)\n");
|
||||||
puts("\t -r define rrh log level\n");
|
puts("\t -r define rrh log level\n");
|
||||||
puts("\t -e define eNB log level\n");
|
puts("\t -e define eNB log level\n");
|
||||||
puts("\t -x enable real time bahaviour\n");
|
puts("\t -x enable real time bahaviour\n");
|
||||||
@@ -516,16 +360,85 @@ static void print_help(void) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \fn void exit_fun(const char* s)
|
|
||||||
* \brief this function
|
void *timer_proc(void *arg) {
|
||||||
* \param[in]
|
|
||||||
* \param[out]
|
timer_t timerid;
|
||||||
* \return
|
struct itimerspec *timer= (struct itimerspec *)arg ; // the timer data structure
|
||||||
* \note
|
struct itimerspec *old_value;
|
||||||
* @ingroup _oai
|
|
||||||
*/
|
|
||||||
void exit_fun(const char* s)
|
#ifdef LOWLATENCY
|
||||||
{
|
struct sched_attr attr;
|
||||||
|
unsigned int flags = 0;
|
||||||
|
|
||||||
|
attr.size = sizeof(attr);
|
||||||
|
attr.sched_flags = 0;
|
||||||
|
attr.sched_nice = 0;
|
||||||
|
attr.sched_priority = 0;
|
||||||
|
|
||||||
|
attr.sched_policy = SCHED_DEADLINE;
|
||||||
|
attr.sched_runtime = (0.1 * 100) * 10000; //
|
||||||
|
attr.sched_deadline = rt_period-30000;//(0.1 * 100) * 10000;
|
||||||
|
attr.sched_period = rt_period;//(0.1 * 100) * 10000; // each TX/RX thread has, as a function of RT PERIOD ??
|
||||||
|
|
||||||
|
if (sched_setattr(0, &attr, flags) < 0 ) {
|
||||||
|
perror("[SCHED] timer thread: sched_setattr failed\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (timer_create (CLOCK_REALTIME, NULL, &timerid) == -1) {
|
||||||
|
fprintf (stderr, "couldn't create a timer\n");
|
||||||
|
perror (NULL);
|
||||||
|
exit (EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
signal(SIGALRM, timer_signal_handler);
|
||||||
|
LOG_I(RRH,"Timer has started!\n");
|
||||||
|
timer_settime (timerid, 0, timer, old_value);
|
||||||
|
|
||||||
|
while (!rrh_exit) {
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
timer_delete(timerid);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void timer_signal_handler(int sig) {
|
||||||
|
|
||||||
|
if (sig == SIGALRM) {
|
||||||
|
pthread_mutex_lock(&timer_mutex);
|
||||||
|
hw_counter ++;
|
||||||
|
pthread_mutex_unlock(&timer_mutex);
|
||||||
|
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_CNT, hw_counter);//USED ELSEWHERE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void signal_handler(int sig) {
|
||||||
|
|
||||||
|
void *array[10];
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
if (sig==SIGSEGV) {
|
||||||
|
// get void*'s for all entries on the stack
|
||||||
|
size = backtrace(array, 10);
|
||||||
|
|
||||||
|
// print out all the frames to stderr
|
||||||
|
fprintf(stderr, "Error: signal %d:\n", sig);
|
||||||
|
backtrace_symbols_fd(array, size, 2);
|
||||||
|
exit(-1);
|
||||||
|
} else {
|
||||||
|
printf("trying to exit gracefully...\n");
|
||||||
|
rrh_exit = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void exit_fun(const char* s) {
|
||||||
if (s != NULL) {
|
if (s != NULL) {
|
||||||
printf("%s %s() Exiting RRH: %s\n",__FILE__, __FUNCTION__, s);
|
printf("%s %s() Exiting RRH: %s\n",__FILE__, __FUNCTION__, s);
|
||||||
}
|
}
|
||||||
@@ -534,66 +447,3 @@ void exit_fun(const char* s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! \fn static void get_RFinterfaces(void)
|
|
||||||
* \brief this function
|
|
||||||
* \param[in]
|
|
||||||
* \param[out]
|
|
||||||
* \return
|
|
||||||
* \note
|
|
||||||
* @ingroup _oai
|
|
||||||
*/
|
|
||||||
static void get_RFinterfaces(void) {
|
|
||||||
|
|
||||||
EXMIMO_flag=1;
|
|
||||||
USRP_flag=1;
|
|
||||||
num_EXMIMO_mod=1;
|
|
||||||
num_USRP_mod=1;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*!\fn void create_timer_thread(void)
|
|
||||||
* \brief this function
|
|
||||||
* \param[in]
|
|
||||||
* \param[out]
|
|
||||||
* \return
|
|
||||||
* \note
|
|
||||||
* @ingroup _oai
|
|
||||||
*/
|
|
||||||
void create_timer_thread() {
|
|
||||||
|
|
||||||
int error_code_timer;
|
|
||||||
pthread_t main_timer_proc_thread;
|
|
||||||
|
|
||||||
LOG_I(RRH,"Creating timer thread with rt period %d ns.\n",rt_period);
|
|
||||||
|
|
||||||
/* setup the timer to generate an interrupt:
|
|
||||||
-for the first time in (sample_per_packet/sample_rate) ns
|
|
||||||
-and then every (sample_per_packet/sample_rate) ns */
|
|
||||||
timerspec.it_value.tv_sec = rt_period/1000000000;
|
|
||||||
timerspec.it_value.tv_nsec = rt_period%1000000000;
|
|
||||||
timerspec.it_interval.tv_sec = rt_period/1000000000;
|
|
||||||
timerspec.it_interval.tv_nsec = rt_period%1000000000;
|
|
||||||
|
|
||||||
pthread_mutex_init(&timer_mutex,NULL);
|
|
||||||
|
|
||||||
#ifndef LOWLATENCY
|
|
||||||
pthread_attr_t attr_timer;
|
|
||||||
struct sched_param sched_param_timer;
|
|
||||||
|
|
||||||
pthread_attr_init(&attr_timer);
|
|
||||||
sched_param_timer.sched_priority = sched_get_priority_max(SCHED_FIFO-1);
|
|
||||||
pthread_attr_setschedparam(&attr_timer,&sched_param_timer);
|
|
||||||
pthread_attr_setschedpolicy(&attr_timer,SCHED_FIFO-1);
|
|
||||||
error_code_timer = pthread_create(&main_timer_proc_thread, &attr_timer, timer_proc, (void *)&timerspec);
|
|
||||||
LOG_I(RRH,"[SCHED] FIFO scheduling applied to timer thread \n");
|
|
||||||
#else
|
|
||||||
error_code_timer = pthread_create(&main_timer_proc_thread, NULL, timer_proc, (void *)&timerspec);
|
|
||||||
LOG_I(RRH,"[SCHED] deadline scheduling applied to timer thread \n");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (error_code_timer) {
|
|
||||||
LOG_E(RRH,"Error while creating timer proc thread\n");
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+47
-20
@@ -45,41 +45,68 @@
|
|||||||
#include "vcd_signal_dumper.h"
|
#include "vcd_signal_dumper.h"
|
||||||
#include "assertions.h"
|
#include "assertions.h"
|
||||||
|
|
||||||
#define DEFAULT_PERIOD_NS 200000
|
#define DEFAULT_PERIOD_NS 200000 /* default value is calculated for 25 PRB */
|
||||||
#define RRH_UE_PORT 51000
|
#define RRH_UE_PORT 51000
|
||||||
#define RRH_UE_DEST_IP "127.0.0.1"
|
#define RRH_UE_DEST_IP "127.0.0.1"
|
||||||
|
|
||||||
/*! \brief RRH supports two types of modules: eNB and UE
|
/*! \brief RRH supports two types of modules: eNB and UE
|
||||||
each module is associated a device of type ETH_IF
|
each module is associated with an ethernet device (device of ETH_IF)
|
||||||
and optionally with an RF device (USRP/BLADERF/EXMIMO) */
|
and optionally with a RF device (device type can be USRP_IF/BLADERF_IF/EXMIMO_IF/NONE_IF)
|
||||||
|
UE modules will always have RF device type NONE_IF */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
//! module id
|
/*! \brief module id */
|
||||||
uint8_t id;
|
uint8_t id;
|
||||||
//! loopback flag
|
/*! \brief! loopback flag */
|
||||||
uint8_t loopback;
|
uint8_t loopback;
|
||||||
//! measurement flag
|
/*! \brief measurement flag */
|
||||||
uint8_t measurements;
|
uint8_t measurements;
|
||||||
//! module's ethernet device
|
/*! \brief module's ethernet device */
|
||||||
openair0_device eth_dev;
|
openair0_device eth_dev;
|
||||||
//! pointer to RF module's device (pointer->since its optional)
|
/*! \brief pointer to RF module's device (pointer->since it's optional) */
|
||||||
openair0_device *devs;
|
openair0_device *devs;
|
||||||
|
|
||||||
}rrh_module_t;
|
}rrh_module_t;
|
||||||
|
|
||||||
|
/*! \fn void timer_signal_handler(int sig)
|
||||||
/******************************************************************************
|
* \brief this function
|
||||||
** FUNCTION PROTOTYPES **
|
* \param[in] signal type
|
||||||
******************************************************************************/
|
* \return none
|
||||||
void signal_handler(int sig);
|
* \note
|
||||||
|
* @ingroup _oai
|
||||||
|
*/
|
||||||
void timer_signal_handler(int);
|
void timer_signal_handler(int);
|
||||||
|
|
||||||
|
/*! \fn void *timer_proc(void *arg)
|
||||||
|
* \brief this function
|
||||||
|
* \param[in]
|
||||||
|
* \param[out]
|
||||||
|
* \return
|
||||||
|
* \note
|
||||||
|
* @ingroup _oai
|
||||||
|
*/
|
||||||
void *timer_proc(void *);
|
void *timer_proc(void *);
|
||||||
void create_timer_thread(void);
|
|
||||||
|
/*! \fn void config_BBU_mod( rrh_module_t *mod_enb, uint8_t RT_flag,uint8_t NRT_flag)
|
||||||
|
* \brief receive and apply configuration to modules' optional device
|
||||||
|
* \param[in] *mod_enb pointer to module
|
||||||
|
* \param[in] RT_flag real time flag
|
||||||
|
* \return none
|
||||||
|
* \note
|
||||||
|
* @ingroup _oai
|
||||||
|
*/
|
||||||
|
void config_BBU_mod( rrh_module_t *mod_enb, uint8_t RT_flag, uint8_t NRT_flag);
|
||||||
|
|
||||||
|
/*! \fn void config_UE_mod( rrh_module_t *dev_ue, uint8_t RT_flag,uint8_t NRT_flag)
|
||||||
|
* \brief this function
|
||||||
|
* \param[in] *mod_ue pointer to module
|
||||||
|
* \param[in]
|
||||||
|
* \return none
|
||||||
|
* \note
|
||||||
|
* @ingroup _oai
|
||||||
|
*/
|
||||||
|
void config_UE_mod( rrh_module_t *dev_ue, uint8_t RT_flag, uint8_t NRT_flag);
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
** FUNCTION PROTOTYPES **
|
void signal_handler(int sig);
|
||||||
******************************************************************************/
|
|
||||||
void create_UE_trx_threads( rrh_module_t *dev_ue, uint8_t RT_flag, uint8_t NRT_flag);
|
|
||||||
void create_eNB_trx_threads( rrh_module_t *mod_enb, uint8_t RT_flag, uint8_t NRT_flag);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user