mirror of https://github.com/PentHertz/srsLTE.git
Mbms fixes (#225)
* fixing the threading structure for mbms in the gtpu fixing some leaks in pmch tests fixing stack overflow caused by radio objext * adding sib.conf.mbsfn.example * creating a different thread_mch object for the gtpu * Make mch_thread an isolated class * excluding mbsfn subframes from noise estimation and cfo estimation * fixing pdsch ue plotting to only show pmch constellation when mbsfn is activated.
This commit is contained in:
parent
0321a967f2
commit
50589108c6
|
@ -67,6 +67,7 @@ pthread_t plot_thread;
|
|||
sem_t plot_sem;
|
||||
uint32_t plot_sf_idx=0;
|
||||
bool plot_track = true;
|
||||
bool enable_mbsfn_plot = false;
|
||||
#endif
|
||||
char *output_file_name;
|
||||
#define PRINT_CHANGE_SCHEDULIGN
|
||||
|
@ -363,6 +364,12 @@ int main(int argc, char **argv) {
|
|||
|
||||
parse_args(&prog_args, argc, argv);
|
||||
|
||||
#ifndef DISABLE_GRAPHICS
|
||||
if(prog_args.mbsfn_area_id > -1) {
|
||||
enable_mbsfn_plot = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (int i = 0; i< SRSLTE_MAX_CODEWORDS; i++) {
|
||||
data[i] = srslte_vec_malloc(sizeof(uint8_t)*1500*8);
|
||||
if (!data[i]) {
|
||||
|
@ -981,13 +988,13 @@ void *plot_thread_run(void *arg) {
|
|||
plot_scatter_addToWindowGrid(&pscatequal, (char*)"pdsch_ue", 0, 0);
|
||||
|
||||
|
||||
|
||||
if(enable_mbsfn_plot) {
|
||||
plot_scatter_init(&pscatequal_pmch);
|
||||
plot_scatter_setTitle(&pscatequal_pmch, "PMCH - Equalized Symbols");
|
||||
plot_scatter_setXAxisScale(&pscatequal_pmch, -4, 4);
|
||||
plot_scatter_setYAxisScale(&pscatequal_pmch, -4, 4);
|
||||
|
||||
plot_scatter_addToWindowGrid(&pscatequal_pmch, (char*)"pdsch_ue", 0, 1);
|
||||
}
|
||||
|
||||
if (!prog_args.disable_plots_except_constellation) {
|
||||
plot_real_init(&pce);
|
||||
|
@ -1004,7 +1011,7 @@ void *plot_thread_run(void *arg) {
|
|||
plot_scatter_setXAxisScale(&pscatequal_pdcch, -4, 4);
|
||||
plot_scatter_setYAxisScale(&pscatequal_pdcch, -4, 4);
|
||||
|
||||
plot_real_addToWindowGrid(&pce, (char*)"pdsch_ue", 0, 2);
|
||||
plot_real_addToWindowGrid(&pce, (char*)"pdsch_ue", 0, (enable_mbsfn_plot)?2:1);
|
||||
plot_real_addToWindowGrid(&pscatequal_pdcch, (char*)"pdsch_ue", 1, 0);
|
||||
plot_real_addToWindowGrid(&p_sync, (char*)"pdsch_ue", 1, 1);
|
||||
}
|
||||
|
@ -1057,7 +1064,10 @@ void *plot_thread_run(void *arg) {
|
|||
|
||||
plot_scatter_setNewData(&pscatequal, ue_dl.pdsch.d[0], nof_symbols);
|
||||
|
||||
if(enable_mbsfn_plot) {
|
||||
plot_scatter_setNewData(&pscatequal_pmch, ue_dl.pmch.d, nof_symbols_pmch);
|
||||
}
|
||||
|
||||
if (plot_sf_idx == 1) {
|
||||
if (prog_args.net_port_signal > 0) {
|
||||
srslte_netsink_write(&net_sink_signal, &sf_buffer[srslte_ue_sync_sf_len(&ue_sync)/7],
|
||||
|
|
|
@ -53,6 +53,7 @@ class radio {
|
|||
radio() : tr_local_time(1024 * 10), tr_usrp_time(1024 * 10), tr_tx_time(1024 * 10), tr_is_eob(1024 * 10) {
|
||||
bzero(&rf_device, sizeof(srslte_rf_t));
|
||||
bzero(&end_of_burst_time, sizeof(srslte_timestamp_t));
|
||||
zeros = (cf_t *) srslte_vec_malloc(burst_preamble_max_samples * sizeof (cf_t));
|
||||
bzero(zeros, burst_preamble_max_samples * sizeof(cf_t));
|
||||
|
||||
burst_preamble_sec = 0;
|
||||
|
@ -145,7 +146,7 @@ class radio {
|
|||
bool is_start_of_burst;
|
||||
uint32_t burst_preamble_samples;
|
||||
double burst_preamble_time_rounded; // preamble time rounded to sample time
|
||||
cf_t zeros[burst_preamble_max_samples];
|
||||
cf_t *zeros;
|
||||
double cur_tx_srate;
|
||||
|
||||
double tx_adv_sec; // Transmission time advance to compensate for antenna->timestamp delay
|
||||
|
|
|
@ -603,12 +603,12 @@ float chest_estimate_cfo(srslte_chest_dl_t *q)
|
|||
}
|
||||
|
||||
void chest_interpolate_noise_est(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx, uint32_t port_id, uint32_t rxant_id, srslte_sf_t ch_mode){
|
||||
if (q->cfo_estimate_enable && ((1<<sf_idx) & q->cfo_estimate_sf_mask)) {
|
||||
if (q->cfo_estimate_enable && ((1<<sf_idx) & q->cfo_estimate_sf_mask) && ch_mode != SRSLTE_SF_MBSFN ) {
|
||||
q->cfo = chest_estimate_cfo(q);
|
||||
}
|
||||
|
||||
/* Estimate noise */
|
||||
if (q->noise_alg == SRSLTE_NOISE_ALG_REFS) {
|
||||
if (q->noise_alg == SRSLTE_NOISE_ALG_REFS && ch_mode != SRSLTE_SF_MBSFN ) {
|
||||
q->noise_estimate[rxant_id][port_id] = estimate_noise_pilots(q, port_id, ch_mode);
|
||||
}
|
||||
|
||||
|
|
|
@ -259,7 +259,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
for (i = 0; i < cell.nof_ports; i++) {
|
||||
tx_sf_symbols[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
|
||||
|
||||
bzero(tx_sf_symbols[i],sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
|
||||
if (srslte_ofdm_tx_init_mbsfn(&ifft_mbsfn[i], SRSLTE_CP_EXT, tx_slot_symbols[i], tx_sf_symbols[i], cell.nof_prb)) {
|
||||
fprintf(stderr, "Error creating iFFT object\n");
|
||||
exit(-1);
|
||||
|
@ -271,7 +271,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
for (i = 0; i < nof_rx_antennas; i++) {
|
||||
rx_sf_symbols[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
|
||||
|
||||
bzero(rx_sf_symbols[i],sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
|
||||
if (srslte_ofdm_rx_init_mbsfn(&fft_mbsfn[i], SRSLTE_CP_EXT, rx_sf_symbols[i], rx_slot_symbols[i], cell.nof_prb)) {
|
||||
fprintf(stderr, "Error creating iFFT object\n");
|
||||
exit(-1);
|
||||
|
|
|
@ -81,6 +81,9 @@ bool radio::is_init() {
|
|||
|
||||
void radio::stop()
|
||||
{
|
||||
if (zeros) {
|
||||
free(zeros);
|
||||
}
|
||||
if (is_initialized) {
|
||||
srslte_rf_close(&rf_device);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ n_prb = 50
|
|||
# eNB configuration files
|
||||
#
|
||||
# sib_config: SIB1, SIB2 and SIB3 configuration file
|
||||
# note: when enabling mbms, use the sib.conf.mbsfn configuration file which includes SIB13
|
||||
# rr_config: Radio Resources configuration file
|
||||
# drb_config: DRB configuration file
|
||||
#####################################################################
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#ifndef SRSENB_GTPU_H
|
||||
#define SRSENB_GTPU_H
|
||||
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -64,6 +65,7 @@ typedef struct{
|
|||
uint32_t teid;
|
||||
}gtpu_header_t;
|
||||
|
||||
|
||||
class gtpu
|
||||
:public gtpu_interface_rrc
|
||||
,public gtpu_interface_pdcp
|
||||
|
@ -71,6 +73,8 @@ class gtpu
|
|||
{
|
||||
public:
|
||||
|
||||
gtpu();
|
||||
|
||||
bool init(std::string gtp_bind_addr_, std::string mme_addr_, pdcp_interface_gtpu *pdcp_, srslte::log *gtpu_log_, bool enable_mbsfn = false);
|
||||
void stop();
|
||||
|
||||
|
@ -82,7 +86,6 @@ public:
|
|||
// gtpu_interface_pdcp
|
||||
void write_pdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t *pdu);
|
||||
|
||||
|
||||
private:
|
||||
static const int THREAD_PRIO = 65;
|
||||
static const int GTPU_PORT = 2152;
|
||||
|
@ -90,14 +93,39 @@ private:
|
|||
bool running;
|
||||
bool run_enable;
|
||||
|
||||
bool mch_running;
|
||||
bool mch_run_enable;
|
||||
bool _enable_mbsfn;
|
||||
|
||||
|
||||
bool enable_mbsfn;
|
||||
std::string gtp_bind_addr;
|
||||
std::string mme_addr;
|
||||
srsenb::pdcp_interface_gtpu *pdcp;
|
||||
srslte::log *gtpu_log;
|
||||
pthread_t mch_thread;
|
||||
|
||||
// Class to create
|
||||
class mch_thread : public thread {
|
||||
public:
|
||||
mch_thread() : initiated(false),running(false),run_enable(false),pool(NULL) {}
|
||||
bool init(pdcp_interface_gtpu *pdcp_, srslte::log *gtpu_log_);
|
||||
void stop();
|
||||
private:
|
||||
void run_thread();
|
||||
|
||||
bool initiated;
|
||||
bool running;
|
||||
bool run_enable;
|
||||
|
||||
static const int MCH_THREAD_PRIO = 65;
|
||||
|
||||
pdcp_interface_gtpu *pdcp;
|
||||
srslte::log *gtpu_log;
|
||||
int m1u_sd;
|
||||
int lcid_counter;
|
||||
|
||||
srslte::byte_buffer_pool *pool;
|
||||
};
|
||||
|
||||
// MCH thread insteance
|
||||
mch_thread mchthread;
|
||||
|
||||
typedef struct{
|
||||
uint32_t teids_in[SRSENB_N_RADIO_BEARERS];
|
||||
|
@ -109,22 +137,10 @@ private:
|
|||
// Socket file descriptors
|
||||
int snk_fd;
|
||||
int src_fd;
|
||||
int m1u_sd;
|
||||
|
||||
//Init functions
|
||||
bool init_m1u(srslte::log *gtpu_log_);
|
||||
|
||||
//Threading
|
||||
void run_thread();
|
||||
void run_mch_thread();
|
||||
|
||||
int mch_lcid_counter;
|
||||
|
||||
static void *mch_thread_routine(void *_this)
|
||||
{
|
||||
((srsenb::gtpu*)_this)->run_mch_thread();
|
||||
return _this;
|
||||
}
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
sib1 =
|
||||
{
|
||||
intra_freq_reselection = "Allowed";
|
||||
q_rx_lev_min = -130;
|
||||
//p_max = 3;
|
||||
cell_barred = "Not Barred"
|
||||
si_window_length = 20;
|
||||
sched_info =
|
||||
(
|
||||
{
|
||||
si_periodicity = 16;
|
||||
si_mapping_info = [13]; // comma-separated array of SIB-indexes (from 3 to 13).
|
||||
// Leave empty or commented to just scheduler sib2
|
||||
}
|
||||
);
|
||||
system_info_value_tag = 0;
|
||||
};
|
||||
|
||||
sib2 =
|
||||
{
|
||||
rr_config_common_sib =
|
||||
{
|
||||
rach_cnfg =
|
||||
{
|
||||
num_ra_preambles = 52;
|
||||
preamble_init_rx_target_pwr = -108;
|
||||
pwr_ramping_step = 6; // in dB
|
||||
preamble_trans_max = 7;
|
||||
ra_resp_win_size = 10; // in ms
|
||||
mac_con_res_timer = 64; // in ms
|
||||
max_harq_msg3_tx = 4;
|
||||
};
|
||||
bcch_cnfg =
|
||||
{
|
||||
modification_period_coeff = 16; // in ms
|
||||
};
|
||||
pcch_cnfg =
|
||||
{
|
||||
default_paging_cycle = 32; // in rf
|
||||
nB = "1";
|
||||
};
|
||||
prach_cnfg =
|
||||
{
|
||||
root_sequence_index = 128;
|
||||
prach_cnfg_info =
|
||||
{
|
||||
high_speed_flag = false;
|
||||
prach_config_index = 3;
|
||||
prach_freq_offset = 0;
|
||||
zero_correlation_zone_config = 11;
|
||||
};
|
||||
};
|
||||
pdsch_cnfg =
|
||||
{
|
||||
p_b = 0;
|
||||
rs_power = -4;
|
||||
};
|
||||
pusch_cnfg =
|
||||
{
|
||||
n_sb = 1;
|
||||
hopping_mode = "inter-subframe";
|
||||
pusch_hopping_offset = 2;
|
||||
enable_64_qam = false;
|
||||
ul_rs =
|
||||
{
|
||||
cyclic_shift = 0;
|
||||
group_assignment_pusch = 0;
|
||||
group_hopping_enabled = false;
|
||||
sequence_hopping_enabled = false;
|
||||
};
|
||||
};
|
||||
pucch_cnfg =
|
||||
{
|
||||
delta_pucch_shift = 1;
|
||||
n_rb_cqi = 1;
|
||||
n_cs_an = 0;
|
||||
n1_pucch_an = 2;
|
||||
};
|
||||
ul_pwr_ctrl =
|
||||
{
|
||||
p0_nominal_pusch = -108;
|
||||
alpha = 1.0;
|
||||
p0_nominal_pucch = -88;
|
||||
delta_flist_pucch =
|
||||
{
|
||||
format_1 = 2;
|
||||
format_1b = 3;
|
||||
format_2 = 0;
|
||||
format_2a = 0;
|
||||
format_2b = 0;
|
||||
};
|
||||
delta_preamble_msg3 = 4;
|
||||
};
|
||||
ul_cp_length = "Normal";
|
||||
};
|
||||
|
||||
ue_timers_and_constants =
|
||||
{
|
||||
t300 = 2000; // in ms
|
||||
t301 = 100; // in ms
|
||||
t310 = 1000; // in ms
|
||||
n310 = 1;
|
||||
t311 = 1000; // in ms
|
||||
n311 = 1;
|
||||
};
|
||||
|
||||
freqInfo =
|
||||
{
|
||||
ul_carrier_freq_present = true;
|
||||
ul_bw_present = true;
|
||||
additional_spectrum_emission = 1;
|
||||
};
|
||||
|
||||
|
||||
|
||||
mbsfnSubframeConfigList =
|
||||
{
|
||||
radioframeAllocationPeriod = "1";
|
||||
subframeAllocationNumFrames = "1";
|
||||
radioframeAllocationOffset = 0;
|
||||
subframeAllocation = 63;
|
||||
|
||||
};
|
||||
|
||||
mbsfnSubframeConfigListLength = 1;
|
||||
|
||||
time_alignment_timer = "INFINITY"; // use "sf500", "sf750", etc.
|
||||
};
|
||||
|
||||
sib13 =
|
||||
{
|
||||
mbsfn_notification_config =
|
||||
{
|
||||
mbsfn_notification_repetition_coeff = "2";
|
||||
mbsfn_notification_offset = 0;
|
||||
mbsfn_notification_sf_index = 1;
|
||||
};
|
||||
mbsfn_area_info_list_size = 1;
|
||||
mbsfn_area_info_list =
|
||||
{
|
||||
non_mbsfn_region_length = "2";
|
||||
mcch_repetition_period = "64";
|
||||
mcch_modification_period = "512";
|
||||
signalling_mcs = "2";
|
||||
mbsfn_area_id = 1;
|
||||
notification_indicator = 0;
|
||||
mcch_offset = 0;
|
||||
sf_alloc_info = 32;
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
|
@ -34,6 +34,10 @@ using namespace srslte;
|
|||
|
||||
namespace srsenb {
|
||||
|
||||
gtpu::gtpu():mchthread()
|
||||
{
|
||||
}
|
||||
|
||||
bool gtpu::init(std::string gtp_bind_addr_, std::string mme_addr_, srsenb::pdcp_interface_gtpu* pdcp_, srslte::log* gtpu_log_, bool enable_mbsfn)
|
||||
{
|
||||
pdcp = pdcp_;
|
||||
|
@ -89,127 +93,26 @@ bool gtpu::init(std::string gtp_bind_addr_, std::string mme_addr_, srsenb::pdcp_
|
|||
return false;
|
||||
}
|
||||
|
||||
//Setup M1-u
|
||||
init_m1u(gtpu_log_);
|
||||
|
||||
_enable_mbsfn = enable_mbsfn;
|
||||
// Setup a thread to receive packets from the src socket
|
||||
start(THREAD_PRIO);
|
||||
if(_enable_mbsfn){
|
||||
mch_lcid_counter = 1;
|
||||
pthread_create(&mch_thread ,NULL ,mch_thread_routine , this);
|
||||
|
||||
// Start MCH thread if enabled
|
||||
this->enable_mbsfn = enable_mbsfn;
|
||||
if(enable_mbsfn) {
|
||||
mchthread.init(pdcp, gtpu_log);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool gtpu::init_m1u(srslte::log* gtpu_log_)
|
||||
{
|
||||
struct sockaddr_in bindaddr;
|
||||
// Set up sink socket
|
||||
m1u_sd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (m1u_sd < 0) {
|
||||
gtpu_log->error("Failed to create M1-U sink socket\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Bind socket */
|
||||
bzero((char *)&bindaddr, sizeof(struct sockaddr_in));
|
||||
bindaddr.sin_family = AF_INET;
|
||||
bindaddr.sin_addr.s_addr = htonl(INADDR_ANY); //Multicast sockets require bind to INADDR_ANY
|
||||
bindaddr.sin_port = htons(GTPU_PORT+1);
|
||||
size_t addrlen = sizeof(bindaddr);
|
||||
|
||||
if (bind(m1u_sd, (struct sockaddr *) &bindaddr, sizeof(bindaddr)) < 0) {
|
||||
gtpu_log->error("Failed to bind multicast socket\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Send an ADD MEMBERSHIP message via setsockopt */
|
||||
struct ip_mreq mreq;
|
||||
mreq.imr_multiaddr.s_addr = inet_addr("239.255.0.1"); //Multicast address of the service
|
||||
mreq.imr_interface.s_addr = inet_addr("127.0.1.200"); //Address of the IF the socket will listen to.
|
||||
if (setsockopt(m1u_sd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
||||
&mreq, sizeof(mreq)) < 0) {
|
||||
gtpu_log->error("Register musticast group for M1-U\n");
|
||||
return false;
|
||||
}
|
||||
gtpu_log->info("M1-U initialized\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
void gtpu::run_mch_thread()
|
||||
{
|
||||
|
||||
byte_buffer_t *pdu;
|
||||
|
||||
mch_run_enable = true;
|
||||
int n;
|
||||
socklen_t addrlen;
|
||||
sockaddr_in src_addr;
|
||||
|
||||
bzero((char *)&src_addr, sizeof(src_addr));
|
||||
src_addr.sin_family = AF_INET;
|
||||
src_addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
src_addr.sin_port = htons(GTPU_PORT+1);
|
||||
addrlen = sizeof(src_addr);
|
||||
|
||||
pdu = pool->allocate();
|
||||
mch_running=true;
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
uint16_t lcid = mch_lcid_counter;
|
||||
mch_lcid_counter++;
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
while(mch_run_enable) {
|
||||
|
||||
pdu->reset();
|
||||
do{
|
||||
n = recvfrom(m1u_sd, pdu->msg, SRSENB_MAX_BUFFER_SIZE_BYTES - SRSENB_BUFFER_HEADER_OFFSET, 0, (struct sockaddr *) &src_addr, &addrlen);
|
||||
} while (n == -1 && errno == EAGAIN);
|
||||
|
||||
pdu->N_bytes = (uint32_t) n;
|
||||
|
||||
|
||||
gtpu_header_t header;
|
||||
gtpu_read_header(pdu, &header);
|
||||
|
||||
uint16_t rnti = 0xFFFD;
|
||||
|
||||
pthread_mutex_lock(&mutex);
|
||||
bool user_exists = (rnti_bearers.count(rnti) > 0);
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
if(!user_exists) {
|
||||
gtpu_log->error("Unrecognized RNTI for DL PDU: 0x%x - dropping packet\n", rnti);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(lcid == 0 || lcid >= SRSENB_N_RADIO_BEARERS) {
|
||||
gtpu_log->error("Invalid LCID for DL PDU: %d - dropping packet\n", lcid);
|
||||
continue;
|
||||
}
|
||||
|
||||
pdcp->write_sdu(rnti, lcid, pdu);
|
||||
do {
|
||||
pdu = pool_allocate;
|
||||
if (!pdu) {
|
||||
gtpu_log->console("GTPU Buffer pool empty. Trying again...\n");
|
||||
usleep(10000);
|
||||
}
|
||||
} while(!pdu);
|
||||
}
|
||||
mch_running=false;
|
||||
}
|
||||
|
||||
void gtpu::stop()
|
||||
{
|
||||
if (run_enable) {
|
||||
run_enable = false;
|
||||
if(mch_run_enable) {
|
||||
mch_run_enable = false;
|
||||
|
||||
if(enable_mbsfn){
|
||||
mchthread.stop();
|
||||
}
|
||||
|
||||
if (run_enable) {
|
||||
run_enable = false;
|
||||
// Wait thread to exit gracefully otherwise might leave a mutex locked
|
||||
int cnt=0;
|
||||
while(running && cnt<100) {
|
||||
|
@ -218,14 +121,8 @@ void gtpu::stop()
|
|||
}
|
||||
if (running) {
|
||||
thread_cancel();
|
||||
if(mch_running) {
|
||||
pthread_cancel(mch_thread);
|
||||
}
|
||||
}
|
||||
wait_thread_finish();
|
||||
if(_enable_mbsfn) {
|
||||
pthread_join(mch_thread, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (snk_fd) {
|
||||
|
@ -332,7 +229,6 @@ void gtpu::run_thread()
|
|||
|
||||
pdu->N_bytes = (uint32_t) n;
|
||||
|
||||
|
||||
gtpu_header_t header;
|
||||
gtpu_read_header(pdu, &header);
|
||||
|
||||
|
@ -446,4 +342,119 @@ void gtpu::rntilcid_to_teidin(uint16_t rnti, uint16_t lcid, uint32_t *teidin)
|
|||
*teidin = (rnti << 16) | lcid;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Class to run the MCH thread
|
||||
***************************************************************************/
|
||||
bool gtpu::mch_thread::init(pdcp_interface_gtpu *pdcp, srslte::log *gtpu_log)
|
||||
{
|
||||
pool = byte_buffer_pool::get_instance();
|
||||
this->pdcp = pdcp;
|
||||
this->gtpu_log = gtpu_log;
|
||||
|
||||
struct sockaddr_in bindaddr;
|
||||
|
||||
// Set up sink socket
|
||||
m1u_sd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (m1u_sd < 0) {
|
||||
gtpu_log->error("Failed to create M1-U sink socket\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Bind socket */
|
||||
bzero((char *)&bindaddr, sizeof(struct sockaddr_in));
|
||||
bindaddr.sin_family = AF_INET;
|
||||
bindaddr.sin_addr.s_addr = htonl(INADDR_ANY); //Multicast sockets require bind to INADDR_ANY
|
||||
bindaddr.sin_port = htons(GTPU_PORT+1);
|
||||
size_t addrlen = sizeof(bindaddr);
|
||||
|
||||
if (bind(m1u_sd, (struct sockaddr *) &bindaddr, sizeof(bindaddr)) < 0) {
|
||||
gtpu_log->error("Failed to bind multicast socket\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Send an ADD MEMBERSHIP message via setsockopt */
|
||||
struct ip_mreq mreq;
|
||||
mreq.imr_multiaddr.s_addr = inet_addr("239.255.0.1"); //Multicast address of the service
|
||||
mreq.imr_interface.s_addr = inet_addr("127.0.1.200"); //Address of the IF the socket will listen to.
|
||||
if (setsockopt(m1u_sd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
|
||||
&mreq, sizeof(mreq)) < 0) {
|
||||
gtpu_log->error("Register musticast group for M1-U\n");
|
||||
return false;
|
||||
}
|
||||
gtpu_log->info("M1-U initialized\n");
|
||||
|
||||
initiated = true;
|
||||
lcid_counter = 1;
|
||||
|
||||
// Start thread
|
||||
start(MCH_THREAD_PRIO);
|
||||
return true;
|
||||
}
|
||||
|
||||
void gtpu::mch_thread::run_thread()
|
||||
{
|
||||
if (!initiated) {
|
||||
fprintf(stderr, "Fatal error running mch_thread without initialization\n");
|
||||
return;
|
||||
}
|
||||
|
||||
byte_buffer_t *pdu;
|
||||
int n;
|
||||
socklen_t addrlen;
|
||||
sockaddr_in src_addr;
|
||||
|
||||
bzero((char *)&src_addr, sizeof(src_addr));
|
||||
src_addr.sin_family = AF_INET;
|
||||
src_addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
src_addr.sin_port = htons(GTPU_PORT+1);
|
||||
addrlen = sizeof(src_addr);
|
||||
|
||||
run_enable = true;
|
||||
running=true;
|
||||
|
||||
pdu = pool->allocate();
|
||||
|
||||
// Warning: Use mutex here if creating multiple services each with a different thread
|
||||
uint16_t lcid = lcid_counter;
|
||||
lcid_counter++;
|
||||
|
||||
while(run_enable) {
|
||||
|
||||
pdu->reset();
|
||||
do{
|
||||
n = recvfrom(m1u_sd, pdu->msg, SRSENB_MAX_BUFFER_SIZE_BYTES - SRSENB_BUFFER_HEADER_OFFSET, 0, (struct sockaddr *) &src_addr, &addrlen);
|
||||
} while (n == -1 && errno == EAGAIN);
|
||||
|
||||
pdu->N_bytes = (uint32_t) n;
|
||||
|
||||
pdcp->write_sdu(SRSLTE_MRNTI, lcid, pdu);
|
||||
do {
|
||||
pdu = pool_allocate;
|
||||
if (!pdu) {
|
||||
gtpu_log->console("GTPU Buffer pool empty. Trying again...\n");
|
||||
usleep(10000);
|
||||
}
|
||||
} while(!pdu);
|
||||
}
|
||||
running = false;
|
||||
}
|
||||
|
||||
void gtpu::mch_thread::stop()
|
||||
{
|
||||
if (run_enable) {
|
||||
run_enable = false;
|
||||
// Wait thread to exit gracefully otherwise might leave a mutex locked
|
||||
int cnt = 0;
|
||||
while(running && cnt < 100) {
|
||||
usleep(10000);
|
||||
cnt++;
|
||||
}
|
||||
if (running) {
|
||||
thread_cancel();
|
||||
}
|
||||
wait_thread_finish();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace srsenb
|
||||
|
|
Loading…
Reference in New Issue