From e4c3f0bc30b40e358da1a76975ffd95a59933a7a Mon Sep 17 00:00:00 2001 From: yagoda Date: Tue, 15 May 2018 17:27:10 +0200 Subject: [PATCH] adding mbms-gw and mch generation tables --- lib/examples/pdsch_enodeb.c | 18 +- lib/examples/pdsch_ue.c | 2 +- lib/include/srslte/common/gen_mch_tables.h | 52 +++ lib/include/srslte/common/pdu.h | 3 +- lib/include/srslte/interfaces/ue_interfaces.h | 6 +- lib/src/common/gen_mch_tables.cc | 65 ++++ lib/src/common/pdu.cc | 21 +- lib/src/phy/ch_estimation/chest_dl.c | 14 +- lib/src/phy/ch_estimation/refsignal_dl.c | 1 + lib/src/phy/dft/ofdm.c | 1 - lib/src/phy/phch/pmch.c | 3 +- lib/src/phy/ue/ue_dl.c | 1 + lib/src/phy/utils/vector.c | 2 +- lib/src/upper/rlc_um.cc | 6 +- lib/test/upper/rlc_um_test.cc | 1 + srsenb/hdr/phy/phy.h | 1 + srsenb/hdr/upper/rrc.h | 1 + srsenb/src/enb_cfg_parser.cc | 3 +- srsenb/src/mac/mac.cc | 7 +- srsenb/src/mac/scheduler.cc | 4 +- srsenb/src/mac/ue.cc | 2 +- srsenb/src/phy/phch_common.cc | 2 + srsenb/src/phy/phch_worker.cc | 12 - srsenb/src/upper/pdcp.cc | 1 + srsenb/src/upper/rrc.cc | 4 +- srsepc/hdr/mbms-gw/mbms-gw.h | 93 +++++ srsepc/mbms.conf.example | 39 +++ srsepc/src/CMakeLists.txt | 31 ++ srsepc/src/mbms-gw/CMakeLists.txt | 23 ++ srsepc/src/mbms-gw/main.cc | 216 ++++++++++++ srsepc/src/mbms-gw/mbms-gw.cc | 326 ++++++++++++++++++ srsue/hdr/phy/phy.h | 2 +- srsue/hdr/upper/gw.h | 3 +- srsue/src/mac/mux.cc | 2 +- srsue/src/mac/proc_ra.cc | 5 +- srsue/src/metrics_csv.cc | 2 +- srsue/src/phy/phch_common.cc | 3 +- srsue/src/phy/phch_recv.cc | 3 + srsue/src/phy/phch_worker.cc | 1 + srsue/src/phy/phy.cc | 1 + 40 files changed, 918 insertions(+), 65 deletions(-) create mode 100644 lib/include/srslte/common/gen_mch_tables.h create mode 100644 lib/src/common/gen_mch_tables.cc create mode 100644 srsepc/hdr/mbms-gw/mbms-gw.h create mode 100644 srsepc/mbms.conf.example create mode 100644 srsepc/src/mbms-gw/CMakeLists.txt create mode 100644 srsepc/src/mbms-gw/main.cc create mode 100644 srsepc/src/mbms-gw/mbms-gw.cc diff --git a/lib/examples/pdsch_enodeb.c b/lib/examples/pdsch_enodeb.c index a75deded6..78c693bda 100644 --- a/lib/examples/pdsch_enodeb.c +++ b/lib/examples/pdsch_enodeb.c @@ -82,7 +82,7 @@ uint32_t multiplex_nof_layers = 1; int mbsfn_area_id = -1; char *rf_args = ""; -float rf_amp = 0.8, rf_gain = 70.0, rf_freq = 2400000000; +float rf_amp = 0.8, rf_gain = 60.0, rf_freq = 2400000000; float output_file_snr = +INFINITY; @@ -302,7 +302,7 @@ void base_init() { } if (net_port > 0) { - if (srslte_netsource_init(&net_source, "0.0.0.0", net_port, SRSLTE_NETSOURCE_TCP)) { + if (srslte_netsource_init(&net_source, "127.0.0.1", net_port, SRSLTE_NETSOURCE_UDP)) { fprintf(stderr, "Error creating input UDP socket at port %d\n", net_port); exit(-1); } @@ -869,13 +869,13 @@ int main(int argc, char **argv) { } /* Transmit PDCCH + PDSCH only when there is data to send */ - if (net_port > 0) { + if ((net_port > 0) && (sf_idx == 1 || mbsfn_area_id < 0)) { send_data = net_packet_ready; if (net_packet_ready) { INFO("Transmitting packet\n"); } } else { - INFO("SF: %d, Generating %d random bits\n", sf_idx, pdsch_cfg.grant.mcs[0].tbs + pdsch_cfg.grant.mcs[1].tbs); + printf("SF: %d, Generating %d random bits\n", sf_idx, pdsch_cfg.grant.mcs[0].tbs + pdsch_cfg.grant.mcs[1].tbs); for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) { if (pdsch_cfg.grant.tb_en[tb]) { for (i = 0; i < pdsch_cfg.grant.mcs[tb].tbs / 8; i++) { @@ -890,9 +890,8 @@ int main(int argc, char **argv) { send_data = false; } } - if (send_data) { - if(sf_idx != 1 || mbsfn_area_id < 0) { // PDCCH + PDSCH + if(sf_idx != 2 || mbsfn_area_id < 0) { // PDCCH + PDSCH srslte_dci_format_t dci_format; switch(pdsch_cfg.mimo_type) { case SRSLTE_MIMO_TYPE_SINGLE_ANTENNA: @@ -1024,10 +1023,13 @@ int main(int argc, char **argv) { } usleep(1000); } else { -#ifndef DISABLE_RF +#ifndef DISABLE_RF float norm_factor = (float) cell.nof_prb/15/sqrtf(pdsch_cfg.grant.nof_prb); + //norm_factor = 0.066667; + //rf_amp = 0.8; + printf("power adj is %f\n",rf_amp * norm_factor); for (i = 0; i < cell.nof_ports; i++) { - srslte_vec_sc_prod_cfc(output_buffer[i], rf_amp * norm_factor, output_buffer[i], SRSLTE_SF_LEN_PRB(cell.nof_prb)); + srslte_vec_sc_prod_cfc(output_buffer[i], 0.01, output_buffer[i], SRSLTE_SF_LEN_PRB(cell.nof_prb)); } srslte_rf_send_multi(&rf, (void**) output_buffer, sf_n_samples, true, start_of_burst, false); start_of_burst=false; diff --git a/lib/examples/pdsch_ue.c b/lib/examples/pdsch_ue.c index c4334cd66..8b4abd102 100644 --- a/lib/examples/pdsch_ue.c +++ b/lib/examples/pdsch_ue.c @@ -385,7 +385,7 @@ int main(int argc, char **argv) { } if (prog_args.net_port > 0) { - if (srslte_netsink_init(&net_sink, prog_args.net_address, prog_args.net_port, SRSLTE_NETSINK_TCP)) { + if (srslte_netsink_init(&net_sink, prog_args.net_address, prog_args.net_port, SRSLTE_NETSINK_UDP)) { fprintf(stderr, "Error initiating UDP socket to %s:%d\n", prog_args.net_address, prog_args.net_port); exit(-1); } diff --git a/lib/include/srslte/common/gen_mch_tables.h b/lib/include/srslte/common/gen_mch_tables.h new file mode 100644 index 000000000..da3c0e0fb --- /dev/null +++ b/lib/include/srslte/common/gen_mch_tables.h @@ -0,0 +1,52 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2015 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of the srsUE library. + * + * srsUE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsUE 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 Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#ifndef GEN_MCH_TALBES_H +#define GEN_MCH_TALBES_H + +/****************************************************************************** + * Common mch table generation - used in phch_common of UE and ENB for MBMS + *****************************************************************************/ +#include +#include +#include +#include "srslte/common/common.h" + + + +namespace srslte { + + + +void generate_frame_mch_table(uint8_t *table, uint8_t alloc); +void generate_mch_table(uint8_t *table, uint32_t sf_alloc, uint8_t num_frames); +void generate_mcch_table(uint8_t *table, uint32_t sf_alloc); + + + +} // namespace srsue + +#endif // SECURITY_H diff --git a/lib/include/srslte/common/pdu.h b/lib/include/srslte/common/pdu.h index 17a20a047..428ee1dca 100644 --- a/lib/include/srslte/common/pdu.h +++ b/lib/include/srslte/common/pdu.h @@ -147,10 +147,11 @@ public: } } + protected: std::vector subheaders; uint32_t pdu_len; - uint32_t rem_len; + uint32_t rem_len; int cur_idx; int nof_subheaders; uint32_t max_subheaders; diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index de6155a66..601a13b37 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -494,8 +494,6 @@ public: }; - - /** PHY interface * */ @@ -566,12 +564,12 @@ public: class phy_interface_mac : public phy_interface_mac_common { public: + /* Configure PRACH using parameters written by RRC */ virtual void configure_prach_params() = 0; virtual void prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm) = 0; - virtual int prach_tx_tti() = 0; - + virtual int prach_tx_tti() = 0; /* Indicates the transmission of a SR signal in the next opportunity */ virtual void sr_send() = 0; virtual int sr_last_tx_tti() = 0; diff --git a/lib/src/common/gen_mch_tables.cc b/lib/src/common/gen_mch_tables.cc new file mode 100644 index 000000000..c8ecc35a2 --- /dev/null +++ b/lib/src/common/gen_mch_tables.cc @@ -0,0 +1,65 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2015 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of the srsUE library. + * + * srsUE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsUE 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 Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + + +#include "srslte/common/gen_mch_tables.h" + +namespace srslte { + +/****************************************************************************** + * Key Generation + *****************************************************************************/ + +void generate_frame_table(uint8_t *table, uint8_t alloc) +{ + table[1] = (alloc >> 5) & 0x01; + table[2] = (alloc >> 4) & 0x01; + table[3] = (alloc >> 3) & 0x01; + table[6] = (alloc >> 2) & 0x01; + table[7] = (alloc >> 1) & 0x01; + table[8] = (alloc >> 0) & 0x01; +} + +void generate_mch_table(uint8_t *table, uint32_t sf_alloc, uint8_t num_frames) +{ + if(num_frames == 1){ + uint8_t alloc = (sf_alloc) & 0x3F; + generate_frame_table(table, alloc); + } else if(num_frames == 4){ + for(uint32_t j=0; j<4; j++){ + uint8_t alloc = (sf_alloc >> 6*(3-j)) & 0x3F; + generate_frame_table(&table[j*10], alloc); + } + } +} + +void generate_mcch_table(uint8_t *table, uint32_t sf_alloc) +{ + uint8_t alloc = (sf_alloc) & 0x3F; + generate_frame_table(table, alloc); +} + +} // namespace srsue diff --git a/lib/src/common/pdu.cc b/lib/src/common/pdu.cc index 604fb6c54..836e1716c 100644 --- a/lib/src/common/pdu.cc +++ b/lib/src/common/pdu.cc @@ -112,7 +112,8 @@ uint8_t* sch_pdu::write_packet(srslte::log *log_h) onetwo_padding = rem_len; rem_len = 0; } - + + /* Determine the header size and CE payload size */ uint32_t header_sz = 0; uint32_t ce_payload_sz = 0; @@ -168,7 +169,6 @@ uint8_t* sch_pdu::write_packet(srslte::log *log_h) subheaders[i].write_payload(&ptr); } } - // Set padding to zeros (if any) if (rem_len > 0) { bzero(&pdu_start_ptr[pdu_len-rem_len], rem_len*sizeof(uint8_t)); @@ -384,6 +384,7 @@ uint16_t sch_subh::get_c_rnti() return (uint16_t) w_payload_ce[0]<<8 | w_payload_ce[1]; } } + uint64_t sch_subh::get_con_res_id() { if (payload) { @@ -395,6 +396,7 @@ uint64_t sch_subh::get_con_res_id() return 0; } } + float sch_subh::get_phr() { if (payload) { @@ -786,12 +788,6 @@ uint8_t sch_subh::phr_report_table(float phr_value) return (uint8_t) floor(phr_value+23); } - - - - - - void rar_pdu::fprint(FILE* stream) { fprintf(stream, "MAC PDU for RAR. "); @@ -861,38 +857,47 @@ void rar_subh::init() ta = 0; temp_rnti = 0; } + uint32_t rar_subh::get_rapid() { return preamble; } + void rar_subh::get_sched_grant(uint8_t grant_[RAR_GRANT_LEN]) { memcpy(grant_, grant, sizeof(uint8_t)*RAR_GRANT_LEN); } + uint32_t rar_subh::get_ta_cmd() { return ta; } + uint16_t rar_subh::get_temp_crnti() { return temp_rnti; } + void rar_subh::set_rapid(uint32_t rapid) { preamble = rapid; } + void rar_subh::set_sched_grant(uint8_t grant_[RAR_GRANT_LEN]) { memcpy(grant, grant_, sizeof(uint8_t)*RAR_GRANT_LEN); } + void rar_subh::set_ta_cmd(uint32_t ta_) { ta = ta_; } + void rar_subh::set_temp_crnti(uint16_t temp_rnti_) { temp_rnti = temp_rnti_; } + // Section 6.2.2 void rar_subh::write_subheader(uint8_t** ptr, bool is_last) { diff --git a/lib/src/phy/ch_estimation/chest_dl.c b/lib/src/phy/ch_estimation/chest_dl.c index 0222357bb..cb291b449 100644 --- a/lib/src/phy/ch_estimation/chest_dl.c +++ b/lib/src/phy/ch_estimation/chest_dl.c @@ -124,7 +124,7 @@ int srslte_chest_dl_init(srslte_chest_dl_t *q, uint32_t max_prb) perror("malloc"); goto clean_exit; } - + q->pilot_recv_signal = srslte_vec_malloc(sizeof(cf_t) * pilot_vec_size); if (!q->pilot_recv_signal) { perror("malloc"); @@ -154,7 +154,7 @@ int srslte_chest_dl_init(srslte_chest_dl_t *q, uint32_t max_prb) q->noise_alg = SRSLTE_NOISE_ALG_REFS; q->rsrp_neighbour = false; - + q->average_subframe = false; q->smooth_filter_auto = false; q->smooth_filter_len = 3; srslte_chest_dl_set_smooth_filter3_coeff(q, 0.1); @@ -333,7 +333,7 @@ static float estimate_noise_pss(srslte_chest_dl_t *q, cf_t *input, cf_t *ce) { /* Get PSS from received signal */ srslte_pss_get_slot(input, q->tmp_pss, q->cell.nof_prb, q->cell.cp); - + /* Get channel estimates for PSS position */ srslte_pss_get_slot(ce, q->tmp_pss_noisy, q->cell.nof_prb, q->cell.cp); @@ -342,7 +342,7 @@ static float estimate_noise_pss(srslte_chest_dl_t *q, cf_t *input, cf_t *ce) /* Substract received signal */ srslte_vec_sub_ccc(q->tmp_pss_noisy, q->tmp_pss, q->tmp_pss_noisy, SRSLTE_PSS_LEN); - + /* Compute average power */ float power = q->cell.nof_ports*srslte_vec_avg_power_cf(q->tmp_pss_noisy, SRSLTE_PSS_LEN)/sqrt(2); return power; @@ -351,14 +351,14 @@ static float estimate_noise_pss(srslte_chest_dl_t *q, cf_t *input, cf_t *ce) /* Uses the 5 empty transmitted SC before and after the SSS and PSS sequences for noise estimation */ static float estimate_noise_empty_sc(srslte_chest_dl_t *q, cf_t *input) { int k_sss = (SRSLTE_CP_NSYMB(q->cell.cp) - 2) * q->cell.nof_prb * SRSLTE_NRE + q->cell.nof_prb * SRSLTE_NRE / 2 - 31; - float noise_power = 0; + float noise_power = 0; noise_power += srslte_vec_avg_power_cf(&input[k_sss-5], 5); // 5 empty SC before SSS noise_power += srslte_vec_avg_power_cf(&input[k_sss+62], 5); // 5 empty SC after SSS int k_pss = (SRSLTE_CP_NSYMB(q->cell.cp) - 1) * q->cell.nof_prb * SRSLTE_NRE + q->cell.nof_prb * SRSLTE_NRE / 2 - 31; noise_power += srslte_vec_avg_power_cf(&input[k_pss-5], 5); // 5 empty SC before PSS noise_power += srslte_vec_avg_power_cf(&input[k_pss+62], 5); // 5 empty SC after PSS - - return noise_power; + + return noise_power; } #define cesymb(i) ce[SRSLTE_RE_IDX(q->cell.nof_prb,i,0)] diff --git a/lib/src/phy/ch_estimation/refsignal_dl.c b/lib/src/phy/ch_estimation/refsignal_dl.c index 316f84476..14e078aed 100644 --- a/lib/src/phy/ch_estimation/refsignal_dl.c +++ b/lib/src/phy/ch_estimation/refsignal_dl.c @@ -120,6 +120,7 @@ inline uint32_t srslte_refsignal_cs_nsymbol(uint32_t l, srslte_cp_t cp, uint32_t return 1+l*SRSLTE_CP_NSYMB(cp); } } + inline uint32_t srslte_refsignal_mbsfn_nsymbol(uint32_t l) { uint32_t ret = 0; diff --git a/lib/src/phy/dft/ofdm.c b/lib/src/phy/dft/ofdm.c index adea1f5e5..06da6b41a 100644 --- a/lib/src/phy/dft/ofdm.c +++ b/lib/src/phy/dft/ofdm.c @@ -561,7 +561,6 @@ void srslte_ofdm_tx_slot(srslte_ofdm_t *q, int slot_in_sf) { void srslte_ofdm_tx_slot_mbsfn(srslte_ofdm_t *q, cf_t *input, cf_t *output) { uint32_t i, cp_len; - for(i=0;inof_symbols_mbsfn;i++) { cp_len = ( i>(q->non_mbsfn_region-1) )?SRSLTE_CP_LEN_EXT(q->symbol_sz):SRSLTE_CP_LEN_NORM(i, q->symbol_sz); memcpy(&q->tmp[q->nof_guards], input, q->nof_re * sizeof(cf_t)); diff --git a/lib/src/phy/phch/pmch.c b/lib/src/phy/phch/pmch.c index b1560c7b1..c5d4ad24c 100644 --- a/lib/src/phy/phch/pmch.c +++ b/lib/src/phy/phch/pmch.c @@ -364,7 +364,6 @@ int srslte_pmch_decode_multi(srslte_pmch_t *q, data != NULL && cfg != NULL) { - INFO("Decoding PMCH SF: %d, MBSFN area ID: 0x%x, Mod %s, TBS: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d, C_prb=%d, cfi=%d\n", cfg->sf_idx, area_id, srslte_mod_string(cfg->grant.mcs[0].mod), cfg->grant.mcs[0].tbs, cfg->nbits[0].nof_re, cfg->nbits[0].nof_bits, 0, cfg->grant.nof_prb, cfg->nbits[0].lstart-1); @@ -379,6 +378,7 @@ int srslte_pmch_decode_multi(srslte_pmch_t *q, /* extract symbols */ n = srslte_pmch_get(q, sf_symbols[j], q->symbols[j], cfg->nbits[0].lstart); if (n != cfg->nbits[0].nof_re) { + fprintf(stderr, "PMCH 1 extract symbols error expecting %d symbols but got %d, lstart %d\n", cfg->nbits[0].nof_re, n, cfg->nbits[0].lstart); return SRSLTE_ERROR; } @@ -433,7 +433,6 @@ int srslte_pmch_encode(srslte_pmch_t *q, /* Set pointers for layermapping & precoding */ cf_t *x[SRSLTE_MAX_LAYERS]; int ret = SRSLTE_ERROR_INVALID_INPUTS; - if (q != NULL && cfg != NULL) { for (i=0;icell.nof_ports;i++) { diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index dc9fdc806..7bcbbf578 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -658,6 +658,7 @@ int srslte_ue_dl_decode_mbsfn(srslte_ue_dl_t * q, noise_estimate, q->current_mbsfn_area_id, data); + if (ret == SRSLTE_ERROR) { q->pmch_pkt_errors++; } else if (ret == SRSLTE_ERROR_INVALID_INPUTS) { diff --git a/lib/src/phy/utils/vector.c b/lib/src/phy/utils/vector.c index d3d836b21..6c55ddefb 100644 --- a/lib/src/phy/utils/vector.c +++ b/lib/src/phy/utils/vector.c @@ -139,7 +139,7 @@ void srslte_vec_fprint_c(FILE *stream, cf_t *x, const uint32_t len) { int i; fprintf(stream, "["); for (i=0;idebug("%s Complete SDU scheduled for tx. Stack latency: %ld us\n", rrc->get_rb_name(lcid).c_str(), tx_sdu->get_latency_us()); + pool->deallocate(tx_sdu); tx_sdu = NULL; } @@ -509,6 +511,7 @@ int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) { log->debug("%s Complete SDU scheduled for tx. Stack latency: %ld us\n", rrc->get_rb_name(lcid).c_str(), tx_sdu->get_latency_us()); + pool->deallocate(tx_sdu); tx_sdu = NULL; } @@ -717,6 +720,7 @@ void rlc_um::reassemble_rx_sdus() } // Handle last segment + if (rx_sdu->N_bytes > 0 || rlc_um_start_aligned(rx_window[vr_ur].header.fi)) { log->debug("Writing last segment in SDU buffer. Lower edge vr_ur=%d, Buffer size=%d, segment size=%d\n", vr_ur, rx_sdu->N_bytes, rx_window[vr_ur].buf->N_bytes); @@ -886,7 +890,6 @@ void rlc_um_read_data_pdu_header(uint8_t *payload, uint32_t nof_bytes, rlc_umd_s { uint8_t ext; uint8_t *ptr = payload; - // Fixed part if(RLC_UMD_SN_SIZE_5_BITS == sn_size) { @@ -933,7 +936,6 @@ void rlc_um_write_data_pdu_header(rlc_umd_pdu_header_t *header, byte_buffer_t *p { uint32_t i; uint8_t ext = (header->N_li > 0) ? 1 : 0; - // Make room for the header uint32_t len = rlc_um_packed_length(header); pdu->msg -= len; diff --git a/lib/test/upper/rlc_um_test.cc b/lib/test/upper/rlc_um_test.cc index 5e2ae0910..c0ad46e7b 100644 --- a/lib/test/upper/rlc_um_test.cc +++ b/lib/test/upper/rlc_um_test.cc @@ -545,3 +545,4 @@ int main(int argc, char **argv) { reassmble_test2(); byte_buffer_pool::get_instance()->cleanup(); } + diff --git a/srsenb/hdr/phy/phy.h b/srsenb/hdr/phy/phy.h index a6240b8b3..d20079135 100644 --- a/srsenb/hdr/phy/phy.h +++ b/srsenb/hdr/phy/phy.h @@ -49,6 +49,7 @@ typedef struct { LIBLTE_RRC_SRS_UL_CONFIG_COMMON_STRUCT srs_ul_cnfg; } phy_cfg_t; + class phy : public phy_interface_mac, public phy_interface_rrc { diff --git a/srsenb/hdr/upper/rrc.h b/srsenb/hdr/upper/rrc.h index 5b0f488e2..b2b0b37b8 100644 --- a/srsenb/hdr/upper/rrc.h +++ b/srsenb/hdr/upper/rrc.h @@ -78,6 +78,7 @@ typedef struct { typedef struct { LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_STRUCT sibs[LIBLTE_RRC_MAX_SIB]; LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT mac_cnfg; + LIBLTE_RRC_PUSCH_CONFIG_DEDICATED_STRUCT pusch_cfg; LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT antenna_info; LIBLTE_RRC_PDSCH_CONFIG_P_A_ENUM pdsch_cfg; diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index c26b7a741..bca482c08 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -735,6 +735,7 @@ uint32_t HexToBytes(const std::string& str, uint8_t *char_value, uint32_t buff_l return i/2; } + int enb::parse_sib9(std::string filename, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_9_STRUCT *data) { parser::section sib9("sib9"); @@ -880,7 +881,7 @@ int enb::parse_sibs(all_args_t *args, rrc_cfg_t *rrc_cfg, phy_cfg_t *phy_config_ if (parse_sib2(args->enb_files.sib_config, sib2)) { return -1; } - + // SRS not yet supported sib2->rr_config_common_sib.srs_ul_cnfg.present = false; if (sib2->ul_bw.present) { diff --git a/srsenb/src/mac/mac.cc b/srsenb/src/mac/mac.cc index ccccfc78f..5c9656df2 100644 --- a/srsenb/src/mac/mac.cc +++ b/srsenb/src/mac/mac.cc @@ -449,7 +449,6 @@ int mac::rach_detected(uint32_t tti, uint32_t preamble_idx, uint32_t time_adv) // Register new user in RRC rrc_h->add_user(last_rnti); - // Trigger scheduler RACH scheduler.dl_rach_info(tti, ra_id, last_rnti, 7); @@ -704,7 +703,7 @@ uint8_t* mac::assemble_rar(sched_interface::dl_sched_rar_grant_t* grants, uint32 } uint8_t* mac::assemble_si(uint32_t index) -{ +{ rlc_h->read_pdu_bcch_dlsch(index, bcch_dlsch_payload); return bcch_dlsch_payload; } @@ -774,9 +773,6 @@ void mac::tti_clock() timers_thread.tti_clock(); } - - - /******************************************************** * * Interface for upper layer timers @@ -799,7 +795,6 @@ srslte::timers::timer* mac::timer_get(uint32_t timer_id) } - /******************************************************** * * Class to run timers with normal priority diff --git a/srsenb/src/mac/scheduler.cc b/srsenb/src/mac/scheduler.cc index 7cfbb5e81..b752eb7ee 100644 --- a/srsenb/src/mac/scheduler.cc +++ b/srsenb/src/mac/scheduler.cc @@ -775,10 +775,10 @@ int sched::dl_sched(uint32_t tti, sched_interface::dl_sched_res_t* sched_result) /* Schedule Broadcast data */ sched_result->nof_bc_elems += dl_sched_bc(sched_result->bc); - + /* Schedule RAR */ sched_result->nof_rar_elems += dl_sched_rar(sched_result->rar); - + /* Schedule pending RLC data */ sched_result->nof_data_elems += dl_sched_data(sched_result->data); diff --git a/srsenb/src/mac/ue.cc b/srsenb/src/mac/ue.cc index 09221d58f..7335e0b12 100644 --- a/srsenb/src/mac/ue.cc +++ b/srsenb/src/mac/ue.cc @@ -329,7 +329,7 @@ void ue::allocate_sdu(srslte::sch_pdu *pdu, uint32_t lcid, uint32_t total_sdu_le while(sdu_len > 3 && n > 0) { if (pdu->new_subh()) { // there is space for a new subheader log_h->debug("SDU: set_sdu(), lcid=%d, sdu_len=%d, sdu_space=%d\n", lcid, sdu_len, sdu_space); - n = pdu->get()->set_sdu(lcid, sdu_len, this); + n = pdu->get()->set_sdu(lcid, sdu_len, this); if (n > 0) { // new SDU could be added sdu_len -= n; log_h->debug("SDU: rnti=0x%x, lcid=%d, nbytes=%d, rem_len=%d\n", diff --git a/srsenb/src/phy/phch_common.cc b/srsenb/src/phy/phch_common.cc index b284c1036..1a29af3cd 100644 --- a/srsenb/src/phy/phch_common.cc +++ b/srsenb/src/phy/phch_common.cc @@ -57,6 +57,8 @@ bool phch_common::init(srslte_cell_t *cell_, srslte::radio* radio_h_, mac_interf mac = mac_; memcpy(&cell, cell_, sizeof(srslte_cell_t)); + + is_first_of_burst = true; is_first_tx = true; for (uint32_t i=0;iwrite_sdu(rnti, lcid, sdu); } diff --git a/srsenb/src/upper/rrc.cc b/srsenb/src/upper/rrc.cc index 65b721f8b..19a8dc073 100644 --- a/srsenb/src/upper/rrc.cc +++ b/srsenb/src/upper/rrc.cc @@ -30,6 +30,7 @@ #include "srslte/srslte.h" #include "srslte/asn1/liblte_mme.h" + using srslte::byte_buffer_t; using srslte::bit_buffer_t; @@ -273,6 +274,7 @@ void rrc::add_user(uint16_t rnti) { pthread_mutex_lock(&user_mutex); if (users.count(rnti) == 0) { + users[rnti].parent = this; users[rnti].rnti = rnti; rlc->add_user(rnti); @@ -1314,7 +1316,7 @@ void rrc::ue::send_connection_setup(bool is_setup) sched_cfg.pucch_cfg.N_cs = parent->sib2.rr_config_common_sib.pucch_cnfg.n_cs_an; sched_cfg.pucch_cfg.n_rb_2 = parent->sib2.rr_config_common_sib.pucch_cnfg.n_rb_cqi; sched_cfg.pucch_cfg.n1_pucch_an = parent->sib2.rr_config_common_sib.pucch_cnfg.n1_pucch_an; - + // Configure MAC parent->mac->ue_cfg(rnti, &sched_cfg); diff --git a/srsepc/hdr/mbms-gw/mbms-gw.h b/srsepc/hdr/mbms-gw/mbms-gw.h new file mode 100644 index 000000000..2b7daacbf --- /dev/null +++ b/srsepc/hdr/mbms-gw/mbms-gw.h @@ -0,0 +1,93 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2017 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE 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 Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +/****************************************************************************** + * File: mbms-gw.h + * Description: Top-level MBMS-GW class. Creates and links all + * interfaces and helpers. + *****************************************************************************/ + +#ifndef MBMS_GW_H +#define MBMS_GW_H + +#include +#include "srslte/common/log.h" +#include "srslte/common/logger_file.h" +#include "srslte/common/log_filter.h" +#include "srslte/common/buffer_pool.h" +#include "srslte/common/threads.h" +#include "srslte/asn1/gtpc.h" + +namespace srsepc{ + + +const uint16_t GTPU_RX_PORT = 2152; + +typedef struct { + std::string name; + std::string sgi_mb_if_addr; + std::string m1u_multi_addr; +} mbms_gw_args_t; + + + +class mbms_gw: + public thread +{ +public: + static mbms_gw* get_instance(void); + static void cleanup(void); + int init(mbms_gw_args_t* args, srslte::log_filter *mbms_gw_log); + void stop(); + void run_thread(); + +private: + + /* Methods */ + mbms_gw(); + virtual ~mbms_gw(); + static mbms_gw *m_instance; + + srslte::error_t init_sgi_mb_if(mbms_gw_args_t *args); + srslte::error_t init_m1_u(mbms_gw_args_t *args); + + void handle_sgi_md_pdu(srslte::byte_buffer_t *msg); + /* Members */ + bool m_running; + srslte::byte_buffer_pool *m_pool; + srslte::log_filter *m_mbms_gw_log; + + bool m_sgi_mb_up; + int m_sgi_mb_if; + + bool m_m1u_up; + int m_m1u; + struct sockaddr_in m_m1u_multi_addr; +}; + +} // namespace srsepc + +#endif // SGW_H diff --git a/srsepc/mbms.conf.example b/srsepc/mbms.conf.example new file mode 100644 index 000000000..a7f1a9fa3 --- /dev/null +++ b/srsepc/mbms.conf.example @@ -0,0 +1,39 @@ +##################################################################### +# srsEPC configuration file +##################################################################### + +##################################################################### +# MBMS-GW configuration +# +# name: MBMS-GW name +# sgi_mb_if_addr: SGi-mb interface IP address +# m1u_addr: Multicast group for eNBs (FIXME this should be setup with M2/M3) +# +##################################################################### +[mbms_gw] +name = srsmbmsgw01 +sgi_mb_if_addr = 172.16.0.254 +m1u_multi_addr = 239.255.0.1 + +#################################################################### +# Log configuration +# +# Log levels can be set for individual layers. "all_level" sets log +# level for all layers unless otherwise configured. +# Format: e.g. s1ap_level = info +# +# In the same way, packet hex dumps can be limited for each level. +# "all_hex_limit" sets the hex limit for all layers unless otherwise +# configured. +# Format: e.g. s1ap_hex_limit = 32 +# +# Logging layers: mbms_gw, all +# Logging levels: debug, info, warning, error, none +# +# filename: File path to use for log output. Can be set to stdout +# to print logs to standard output +##################################################################### +[log] +all_level = debug +all_hex_limit = 32 +filename = /tmp/mbms.log diff --git a/srsepc/src/CMakeLists.txt b/srsepc/src/CMakeLists.txt index e6f4c2538..9fb56ce30 100644 --- a/srsepc/src/CMakeLists.txt +++ b/srsepc/src/CMakeLists.txt @@ -1,7 +1,27 @@ +# +# Copyright 2013-2017 Software Radio Systems Limited +# +# This file is part of srsLTE +# +# srsLTE is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# srsLTE 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 Affero General Public License for more details. +# +# A copy of the GNU Affero General Public License can be found in +# the LICENSE file in the top-level directory of this distribution +# and at http://www.gnu.org/licenses/. +# add_subdirectory(mme) add_subdirectory(hss) add_subdirectory(spgw) +add_subdirectory(mbms-gw) # Link libstdc++ and libgcc if(BUILD_STATIC) @@ -26,11 +46,22 @@ target_link_libraries(srsepc srsepc_mme ${LIBCONFIGPP_LIBRARIES} ${SCTP_LIBRARIES}) +add_executable(srsmbms mbms-gw/main.cc ) +target_link_libraries(srsmbms srsepc_mbms_gw + srslte_upper + srslte_common + ${CMAKE_THREAD_LIBS_INIT} + ${Boost_LIBRARIES} + ${SEC_LIBRARIES} + ${LIBCONFIGPP_LIBRARIES} + ${SCTP_LIBRARIES}) if (RPATH) set_target_properties(srsepc PROPERTIES INSTALL_RPATH ".") + set_target_properties(srsmbms PROPERTIES INSTALL_RPATH ".") endif (RPATH) install(TARGETS srsepc DESTINATION ${RUNTIME_DIR}) +install(TARGETS srsmbms DESTINATION ${RUNTIME_DIR}) ######################################################################## # Option to run command after build (useful for remote builds) diff --git a/srsepc/src/mbms-gw/CMakeLists.txt b/srsepc/src/mbms-gw/CMakeLists.txt new file mode 100644 index 000000000..412753b57 --- /dev/null +++ b/srsepc/src/mbms-gw/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright 2013-2017 Software Radio Systems Limited +# +# This file is part of srsLTE +# +# srsLTE is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of +# the License, or (at your option) any later version. +# +# srsLTE 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 Affero General Public License for more details. +# +# A copy of the GNU Affero General Public License can be found in +# the LICENSE file in the top-level directory of this distribution +# and at http://www.gnu.org/licenses/. +# + +file(GLOB SOURCES "*.cc") +add_library(srsepc_mbms_gw STATIC ${SOURCES}) +install(TARGETS srsepc_mbms_gw DESTINATION ${LIBRARY_DIR}) diff --git a/srsepc/src/mbms-gw/main.cc b/srsepc/src/mbms-gw/main.cc new file mode 100644 index 000000000..379d56a36 --- /dev/null +++ b/srsepc/src/mbms-gw/main.cc @@ -0,0 +1,216 @@ +/** + * + * \section COPYRIGHT + * + * \section LICENSE + * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE 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 Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ +#include +#include +#include +#include +#include +#include +#include "srsepc/hdr/mbms-gw/mbms-gw.h" + +using namespace std; +using namespace srsepc; +namespace bpo = boost::program_options; + +bool running = true; + +void +sig_int_handler(int signo){ + running = false; +} + +typedef struct { + std::string mbms_gw_level; + int mbms_gw_hex_limit; + std::string all_level; + int all_hex_limit; + std::string filename; +}log_args_t; + +typedef struct { + mbms_gw_args_t mbms_gw_args; + log_args_t log_args; +}all_args_t; + +srslte::LOG_LEVEL_ENUM +level(std::string l) +{ + boost::to_upper(l); + if("NONE" == l){ + return srslte::LOG_LEVEL_NONE; + }else if("ERROR" == l){ + return srslte::LOG_LEVEL_ERROR; + }else if("WARNING" == l){ + return srslte::LOG_LEVEL_WARNING; + }else if("INFO" == l){ + return srslte::LOG_LEVEL_INFO; + }else if("DEBUG" == l){ + return srslte::LOG_LEVEL_DEBUG; + }else{ + return srslte::LOG_LEVEL_NONE; + } +} + +/********************************************************************** + * Program arguments processing + ***********************************************************************/ +string config_file; + +void +parse_args(all_args_t *args, int argc, char* argv[]) { + + string mbms_gw_name; + string mbms_gw_sgi_mb_if_addr; + string mbms_gw_m1u_multi_addr; + + string log_filename; + + // Command line only options + bpo::options_description general("General options"); + general.add_options() + ("help,h", "Produce help message") + ("version,v", "Print version information and exit") + ; + + // Command line or config file options + bpo::options_description common("Configuration options"); + common.add_options() + + ("mbms_gw.name", bpo::value(&mbms_gw_name)->default_value("srsmbmsgw01"), "MBMS-GW Name") + ("mbms_gw.sgi_mb_if_addr", bpo::value(&mbms_gw_sgi_mb_if_addr)->default_value("172.16.1.1"), "SGi-mb TUN interface Address") + ("mbms_gw.m1u_multi_addr", bpo::value(&mbms_gw_m1u_multi_addr)->default_value("239.255.0.1"), "M1-u GTPu destination multicast address") + + ("log.all_level", bpo::value(&args->log_args.all_level)->default_value("info"), "ALL log level") + ("log.all_hex_limit", bpo::value(&args->log_args.all_hex_limit)->default_value(32), "ALL log hex dump limit") + + ("log.filename", bpo::value(&args->log_args.filename)->default_value("/tmp/mbms.log"),"Log filename") + ; + + // Positional options - config file location + bpo::options_description position("Positional options"); + position.add_options() + ("config_file", bpo::value< string >(&config_file), "MBMS-GW configuration file") + ; + bpo::positional_options_description p; + p.add("config_file", -1); + + // these options are allowed on the command line + bpo::options_description cmdline_options; + cmdline_options.add(common).add(position).add(general); + + // parse the command line and store result in vm + bpo::variables_map vm; + bpo::store(bpo::command_line_parser(argc, argv).options(cmdline_options).positional(p).run(), vm); + bpo::notify(vm); + + // help option was given - print usage and exit + if (vm.count("help")) { + cout << "Usage: " << argv[0] << " [OPTIONS] config_file" << endl << endl; + cout << common << endl << general << endl; + exit(0); + } + + //Parsing Config File + if (!vm.count("config_file")) { + cout << "Error: Configuration file not provided" << endl; + cout << "Usage: " << argv[0] << " [OPTIONS] config_file" << endl << endl; + exit(0); + } else { + cout << "Reading configuration file " << config_file << "..." << endl; + ifstream conf(config_file.c_str(), ios::in); + if(conf.fail()) { + cout << "Failed to read configuration file " << config_file << " - exiting" << endl; + exit(1); + } + bpo::store(bpo::parse_config_file(conf, common), vm); + bpo::notify(vm); + } + + args->mbms_gw_args.name = mbms_gw_name; + args->mbms_gw_args.sgi_mb_if_addr = mbms_gw_sgi_mb_if_addr; + args->mbms_gw_args.m1u_multi_addr = mbms_gw_m1u_multi_addr; + // Apply all_level to any unset layers + if (vm.count("log.all_level")) { + if(!vm.count("log.mbms_gw_level")) { + args->log_args.mbms_gw_level = args->log_args.all_level; + } + } + + // Apply all_hex_limit to any unset layers + if (vm.count("log.all_hex_limit")) { + if(!vm.count("log.mbms_gw_hex_limit")) { + args->log_args.mbms_gw_hex_limit = args->log_args.all_hex_limit; + } + } + return; +} + + + +int +main (int argc,char * argv[] ) +{ + cout << endl <<"--- Software Radio Systems MBMS ---" << endl << endl; + signal(SIGINT, sig_int_handler); + signal(SIGTERM, sig_int_handler); + signal(SIGKILL, sig_int_handler); + + all_args_t args; + parse_args(&args, argc, argv); + + srslte::logger_stdout logger_stdout; + srslte::logger_file logger_file; + srslte::logger *logger; + + /*Init logger*/ + if (!args.log_args.filename.compare("stdout")) { + logger = &logger_stdout; + } else { + logger_file.init(args.log_args.filename); + logger_file.log("\n--- Software Radio Systems MBMS log ---\n\n"); + logger = &logger_file; + } + + srslte::log_filter mbms_gw_log; + mbms_gw_log.init("MBMS",logger); + mbms_gw_log.set_level(level(args.log_args.mbms_gw_level)); + mbms_gw_log.set_hex_limit(args.log_args.mbms_gw_hex_limit); + + mbms_gw *mbms_gw = mbms_gw::get_instance(); + if(mbms_gw->init(&args.mbms_gw_args,&mbms_gw_log)) { + cout << "Error initializing MBMS-GW" << endl; + exit(1); + } + + mbms_gw->start(); + while(running) { + sleep(1); + } + + mbms_gw->stop(); + mbms_gw->cleanup(); + + cout << std::endl <<"--- exiting ---" << endl; + return 0; +} diff --git a/srsepc/src/mbms-gw/mbms-gw.cc b/srsepc/src/mbms-gw/mbms-gw.cc new file mode 100644 index 000000000..81cd8225e --- /dev/null +++ b/srsepc/src/mbms-gw/mbms-gw.cc @@ -0,0 +1,326 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2017 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of srsLTE. + * + * srsLTE is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of + * the License, or (at your option) any later version. + * + * srsLTE 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 Affero General Public License for more details. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "srsepc/hdr/mbms-gw/mbms-gw.h" +#include "srslte/upper/gtpu.h" + +namespace srsepc{ + +mbms_gw* mbms_gw::m_instance = NULL; +pthread_mutex_t mbms_gw_instance_mutex = PTHREAD_MUTEX_INITIALIZER; + +const uint16_t MBMS_GW_BUFFER_SIZE = 2500; + +mbms_gw::mbms_gw(): + m_running(false), + m_sgi_mb_up(false) +{ + return; +} + +mbms_gw::~mbms_gw() +{ + return; +} + +mbms_gw* +mbms_gw::get_instance(void) +{ + pthread_mutex_lock(&mbms_gw_instance_mutex); + if(NULL == m_instance) { + m_instance = new mbms_gw(); + } + pthread_mutex_unlock(&mbms_gw_instance_mutex); + return(m_instance); +} + +void +mbms_gw::cleanup(void) +{ + pthread_mutex_lock(&mbms_gw_instance_mutex); + if(NULL != m_instance) { + delete m_instance; + m_instance = NULL; + } + pthread_mutex_unlock(&mbms_gw_instance_mutex); +} + +int +mbms_gw::init(mbms_gw_args_t* args, srslte::log_filter *mbms_gw_log) +{ + srslte::error_t err; + m_pool = srslte::byte_buffer_pool::get_instance(); + + //Init log + m_mbms_gw_log = mbms_gw_log; + + err = init_sgi_mb_if(args); + if (err != srslte::ERROR_NONE) + { + m_mbms_gw_log->console("Error initializing SGi-MB.\n"); + m_mbms_gw_log->error("Error initializing SGi-MB.\n"); + return -1; + } + err = init_m1_u(args); + if (err != srslte::ERROR_NONE) + { + m_mbms_gw_log->console("Error initializing SGi-MB.\n"); + m_mbms_gw_log->error("Error initializing SGi-MB.\n"); + return -1; + } + m_mbms_gw_log->info("MBMS GW Initiated\n"); + m_mbms_gw_log->console("MBMS GW Initiated\n"); + return 0; +} + +void +mbms_gw::stop() +{ + if(m_running) + { + if(m_sgi_mb_up) + { + close(m_sgi_mb_if); + m_mbms_gw_log->info("Closed SGi-MB interface\n"); + } + m_running = false; + thread_cancel(); + wait_thread_finish(); + } + return; +} + +srslte::error_t +mbms_gw::init_sgi_mb_if(mbms_gw_args_t *args) +{ + char dev[IFNAMSIZ] = "sgi_mb"; + struct ifreq ifr; + + if(m_sgi_mb_up) + { + return(srslte::ERROR_ALREADY_STARTED); + } + + + // Construct the TUN device + m_sgi_mb_if = open("/dev/net/tun", O_RDWR); + m_mbms_gw_log->info("TUN file descriptor = %d\n", m_sgi_mb_if); + if(m_sgi_mb_if < 0) + { + m_mbms_gw_log->error("Failed to open TUN device: %s\n", strerror(errno)); + return(srslte::ERROR_CANT_START); + } + + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_flags = IFF_TUN | IFF_NO_PI; + strncpy(ifr.ifr_ifrn.ifrn_name, dev, IFNAMSIZ-1); + ifr.ifr_ifrn.ifrn_name[IFNAMSIZ-1]='\0'; + + if(ioctl(m_sgi_mb_if, TUNSETIFF, &ifr) < 0) + { + m_mbms_gw_log->error("Failed to set TUN device name: %s\n", strerror(errno)); + close(m_sgi_mb_if); + return(srslte::ERROR_CANT_START); + } + + // Bring up the interface + int sgi_mb_sock = socket(AF_INET, SOCK_DGRAM, 0); + if(sgi_mb_sock<0) + { + m_mbms_gw_log->error("Failed to bring up socket: %s\n", strerror(errno)); + close(m_sgi_mb_if); + return(srslte::ERROR_CANT_START); + } + + if(ioctl(sgi_mb_sock, SIOCGIFFLAGS, &ifr) < 0) + { + m_mbms_gw_log->error("Failed to bring up interface: %s\n", strerror(errno)); + close(m_sgi_mb_if); + close(sgi_mb_sock); + return(srslte::ERROR_CANT_START); + } + + ifr.ifr_flags |= IFF_UP | IFF_RUNNING; + if(ioctl(sgi_mb_sock, SIOCSIFFLAGS, &ifr) < 0) + { + m_mbms_gw_log->error("Failed to set socket flags: %s\n", strerror(errno)); + close(sgi_mb_sock); + close(m_sgi_mb_if); + return(srslte::ERROR_CANT_START); + } + + //Set IP of the interface + struct sockaddr_in *addr = (struct sockaddr_in*)&ifr.ifr_addr; + addr->sin_family = AF_INET; + addr->sin_addr.s_addr = inet_addr(args->sgi_mb_if_addr.c_str()); + addr->sin_port = 0; + + if (ioctl(sgi_mb_sock, SIOCSIFADDR, &ifr) < 0) { + m_mbms_gw_log->error("Failed to set TUN interface IP. Address: %s, Error: %s\n", args->sgi_mb_if_addr.c_str(), strerror(errno)); + close(m_sgi_mb_if); + close(sgi_mb_sock); + return srslte::ERROR_CANT_START; + } + + ifr.ifr_netmask.sa_family = AF_INET; + ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr("255.255.255.255"); + if (ioctl(sgi_mb_sock, SIOCSIFNETMASK, &ifr) < 0) { + m_mbms_gw_log->error("Failed to set TUN interface Netmask. Error: %s\n", strerror(errno)); + close(m_sgi_mb_if); + close(sgi_mb_sock); + return srslte::ERROR_CANT_START; + } + + m_sgi_mb_up = true; + close(sgi_mb_sock); + return(srslte::ERROR_NONE); +} + +srslte::error_t +mbms_gw::init_m1_u(mbms_gw_args_t *args) +{ + int addrlen; + struct sockaddr_in addr; + m_m1u = socket(AF_INET, SOCK_DGRAM, 0); + if(m_m1u<0) + { + m_mbms_gw_log->error("Failed to open socket: %s\n", strerror(errno)); + return srslte::ERROR_CANT_START; + } + m_m1u_up = true; + + /* set no loopback */ + char loopch = 0; + if(setsockopt(m_m1u, IPPROTO_IP, IP_MULTICAST_LOOP, (char*)&loopch, sizeof(char))<0){ + m_mbms_gw_log->error("Failed to disable loopback: %s\n", strerror(errno)); + return srslte::ERROR_CANT_START; + } else { + m_mbms_gw_log->debug("Loopback disabled\n"); + } + + /* Set local interface for outbound multicast packets*/ + /* The IP must be associated with a local multicast capable interface */ + struct in_addr local_if; + local_if.s_addr = inet_addr("127.0.1.200"); + if(setsockopt(m_m1u, IPPROTO_IP, IP_MULTICAST_IF, (char*)&local_if, sizeof(struct in_addr))<0){ + perror("Error setting multicast interface.\n"); + } else { + printf("Multicast interface specified.\n"); + } + + bzero(&m_m1u_multi_addr,sizeof(m_m1u_multi_addr)); + m_m1u_multi_addr.sin_family = AF_INET; + m_m1u_multi_addr.sin_port = htons(GTPU_RX_PORT+1); + m_m1u_multi_addr.sin_addr.s_addr = inet_addr(args->m1u_multi_addr.c_str()); + m_mbms_gw_log->info("Initialized M1-U\n"); + + return srslte::ERROR_NONE; +} + +void +mbms_gw::run_thread() +{ + //Mark the thread as running + m_running=true; + srslte::byte_buffer_t *msg; + msg = m_pool->allocate(); + + + uint8_t seq = 0; + while(m_running) + { + msg->reset(); + int n; + do{ + n = read(m_sgi_mb_if, msg->msg, SRSLTE_MAX_BUFFER_SIZE_BYTES); + }while(n == -1 && errno == EAGAIN); + + if(n<0){ + m_mbms_gw_log->error("Error reading from TUN interface. Error: %s\n", strerror(errno)); + } + else{ + msg->N_bytes = n; + handle_sgi_md_pdu(msg); + } + } + m_pool->deallocate(msg); + return; +} + +void +mbms_gw::handle_sgi_md_pdu(srslte::byte_buffer_t *msg) +{ + uint8_t version; + srslte::gtpu_header_t header; + in_addr_t baddr = inet_addr("172.16.0.255"); + + //Setup GTP-U header + header.flags = 0x30; + header.message_type = 0xFF; + header.length = msg->N_bytes; + header.teid = 0xAAAA; //FIXME Harcoded TEID for now + + //Sanity Check IP packet + if(msg->N_bytes < 20) + { + m_mbms_gw_log->error("IPv4 min len: %d, drop msg len %d\n", 20, msg->N_bytes); + return; + } + version = msg->msg[0]>>4; + if(version !=4) + { + m_mbms_gw_log->warning("IPv6 not supported yet.\n"); + return; + } + //Replace Destination IP with broadcast address + memcpy(&msg->msg[16],&baddr,4); + + //Write GTP-U header into packet + if(!srslte::gtpu_write_header(&header, msg)) + { + m_mbms_gw_log->console("Error writing GTP-U header on PDU\n"); + } + + int n = sendto(m_m1u, msg->msg, msg->N_bytes, 0, + (sockaddr *) &m_m1u_multi_addr, sizeof(struct sockaddr)); + if(n<0){ + m_mbms_gw_log->console("Error writting to M1-U socket.\n"); + } + else{ + m_mbms_gw_log->console("Sent %d Bytes\n", msg->N_bytes); + } + +} +} //namespace srsepc diff --git a/srsue/hdr/phy/phy.h b/srsue/hdr/phy/phy.h index e7661908b..38bcb6d8b 100644 --- a/srsue/hdr/phy/phy.h +++ b/srsue/hdr/phy/phy.h @@ -120,7 +120,7 @@ public: void pdcch_dl_search(srslte_rnti_type_t rnti_type, uint16_t rnti, int tti_start = -1, int tti_end = -1); void pdcch_ul_search_reset(); void pdcch_dl_search_reset(); - + /* Get/Set PHY parameters interface from RRC */ void get_config(phy_cfg_t *phy_cfg); void set_config(phy_cfg_t *phy_cfg); diff --git a/srsue/hdr/upper/gw.h b/srsue/hdr/upper/gw.h index 457832cff..46059b517 100644 --- a/srsue/hdr/upper/gw.h +++ b/srsue/hdr/upper/gw.h @@ -74,9 +74,10 @@ private: nas_interface_gw *nas; srslte::byte_buffer_pool *pool; - srslte::log *gw_log; + srslte::srslte_gw_config_t cfg; + bool running; bool run_enable; int32 tun_fd; diff --git a/srsue/src/mac/mux.cc b/srsue/src/mac/mux.cc index 6d1edbebf..361c0bea4 100644 --- a/srsue/src/mac/mux.cc +++ b/srsue/src/mac/mux.cc @@ -188,7 +188,7 @@ uint8_t* mux::pdu_get(uint8_t *payload, uint32_t pdu_sz, uint32_t tx_tti, uint32 bsr_proc::bsr_t bsr; bool regular_bsr = bsr_procedure->need_to_send_bsr_on_ul_grant(pdu_msg.rem_size(), &bsr); - bool bsr_is_inserted = false; + bool bsr_is_inserted = false; // MAC control element for BSR, with exception of BSR included for padding; if (regular_bsr) { diff --git a/srsue/src/mac/proc_ra.cc b/srsue/src/mac/proc_ra.cc index d5efbea4f..5b5b56ee7 100644 --- a/srsue/src/mac/proc_ra.cc +++ b/srsue/src/mac/proc_ra.cc @@ -271,8 +271,9 @@ void ra_proc::step_preamble_transmission() { } void ra_proc::step_pdcch_setup() { + int ra_tti = phy_h->prach_tx_tti(); - if (ra_tti > 0) { + if (ra_tti > 0) { ra_rnti = 1+ra_tti%10; rInfo("seq=%d, ra-rnti=0x%x, ra-tti=%d\n", sel_preamble, ra_rnti, ra_tti); log_h->console("Random Access Transmission: seq=%d, ra-rnti=0x%x\n", sel_preamble, ra_rnti); @@ -387,7 +388,7 @@ void ra_proc::step_response_reception() { if (ra_tti >= 0 && !rar_received) { uint32_t interval = srslte_tti_interval(phy_h->get_current_tti(), ra_tti+3+responseWindowSize); if (interval > 1 && interval < 100) { - rDebug("RA response not received within the response window\n"); + Error("RA response not received within the response window\n"); state = RESPONSE_ERROR; } } diff --git a/srsue/src/metrics_csv.cc b/srsue/src/metrics_csv.cc index fa8760f37..ef660761c 100644 --- a/srsue/src/metrics_csv.cc +++ b/srsue/src/metrics_csv.cc @@ -72,7 +72,7 @@ void metrics_csv::set_metrics(ue_metrics_t &metrics, const uint32_t period_usec) { if (file.is_open() && ue != NULL) { if(n_reports == 0) { - file << "time;rsrp;pl;cfo;dl_mcs;dl_snr;dl_turbo;dl_brate;dl_bler;ul_ta;ul_mcs;ul_buff;ul_brate;ul_bler;rf_o;rf_u;rf_l;is_attached\n"; + file << "time;rsrp;pl;cfo;dl_mcs;dl_snr;dl_turbo;dl_brate;dl_bler;ul_ta,ul_mcs;ul_buff;ul_brate;ul_bler;rf_o;rf_u;rf_l;is_attached\n"; } file << (metrics_report_period*n_reports) << ";"; file << float_to_string(metrics.phy.dl.rsrp, 2); diff --git a/srsue/src/phy/phch_common.cc b/srsue/src/phy/phch_common.cc index 161d93244..88352e6dd 100644 --- a/srsue/src/phy/phch_common.cc +++ b/srsue/src/phy/phch_common.cc @@ -51,7 +51,8 @@ phch_common::phch_common(uint32_t max_mutex_) : tx_mutex(max_mutex_) rx_gain_offset = 0; last_ri = 0; last_pmi = 0; - + //have_mtch_stop = false; + bzero(&dl_metrics, sizeof(dl_metrics_t)); dl_metrics_read = true; dl_metrics_count = 0; diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index f2ef205c9..cbbf5c18c 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -392,6 +392,7 @@ void phch_recv::run_thread() phy_state.state_exit(); break; case sync_state::SFN_SYNC: + /* SFN synchronization using MIB. run_subframe() receives and processes 1 subframe * and returns */ @@ -473,6 +474,7 @@ void phch_recv::run_thread() is_end_of_burst = true; + // Start worker workers_pool->start_worker(worker); @@ -500,6 +502,7 @@ void phch_recv::run_thread() } break; case sync_state::IDLE: + if (radio_h->is_init()) { uint32_t nsamples = 1920; if (current_srate > 0) { diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 94f8b7158..1b75c9ddf 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -133,6 +133,7 @@ bool phch_worker::init(uint32_t max_prb, srslte::log *log_h, srslte::log *log_ph return false; } + srslte_chest_dl_set_rsrp_neighbour(&ue_dl.chest, true); srslte_chest_dl_average_subframe(&ue_dl.chest, phy->args->average_subframe_enabled); srslte_chest_dl_cfo_estimate_enable(&ue_dl.chest, phy->args->cfo_ref_mask!=0, phy->args->cfo_ref_mask); diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index 3cdfcd8da..20f40f4b6 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -354,6 +354,7 @@ uint32_t phy::get_current_tti() return sf_recv.get_current_tti(); } + void phy::sr_send() { workers_common.sr_enabled = true;