adding mbms-gw and mch generation tables
This commit is contained in:
parent
12c9f50ba9
commit
e4c3f0bc30
|
@ -82,7 +82,7 @@ uint32_t multiplex_nof_layers = 1;
|
||||||
|
|
||||||
int mbsfn_area_id = -1;
|
int mbsfn_area_id = -1;
|
||||||
char *rf_args = "";
|
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;
|
float output_file_snr = +INFINITY;
|
||||||
|
|
||||||
|
@ -302,7 +302,7 @@ void base_init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (net_port > 0) {
|
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);
|
fprintf(stderr, "Error creating input UDP socket at port %d\n", net_port);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
@ -869,13 +869,13 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Transmit PDCCH + PDSCH only when there is data to send */
|
/* 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;
|
send_data = net_packet_ready;
|
||||||
if (net_packet_ready) {
|
if (net_packet_ready) {
|
||||||
INFO("Transmitting packet\n");
|
INFO("Transmitting packet\n");
|
||||||
}
|
}
|
||||||
} else {
|
} 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++) {
|
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
|
||||||
if (pdsch_cfg.grant.tb_en[tb]) {
|
if (pdsch_cfg.grant.tb_en[tb]) {
|
||||||
for (i = 0; i < pdsch_cfg.grant.mcs[tb].tbs / 8; i++) {
|
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;
|
send_data = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (send_data) {
|
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;
|
srslte_dci_format_t dci_format;
|
||||||
switch(pdsch_cfg.mimo_type) {
|
switch(pdsch_cfg.mimo_type) {
|
||||||
case SRSLTE_MIMO_TYPE_SINGLE_ANTENNA:
|
case SRSLTE_MIMO_TYPE_SINGLE_ANTENNA:
|
||||||
|
@ -1024,10 +1023,13 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
usleep(1000);
|
usleep(1000);
|
||||||
} else {
|
} else {
|
||||||
#ifndef DISABLE_RF
|
#ifndef DISABLE_RF
|
||||||
float norm_factor = (float) cell.nof_prb/15/sqrtf(pdsch_cfg.grant.nof_prb);
|
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++) {
|
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);
|
srslte_rf_send_multi(&rf, (void**) output_buffer, sf_n_samples, true, start_of_burst, false);
|
||||||
start_of_burst=false;
|
start_of_burst=false;
|
||||||
|
|
|
@ -385,7 +385,7 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prog_args.net_port > 0) {
|
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);
|
fprintf(stderr, "Error initiating UDP socket to %s:%d\n", prog_args.net_address, prog_args.net_port);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 <pthread.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <vector>
|
||||||
|
#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
|
|
@ -147,10 +147,11 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<SubH> subheaders;
|
std::vector<SubH> subheaders;
|
||||||
uint32_t pdu_len;
|
uint32_t pdu_len;
|
||||||
uint32_t rem_len;
|
uint32_t rem_len;
|
||||||
int cur_idx;
|
int cur_idx;
|
||||||
int nof_subheaders;
|
int nof_subheaders;
|
||||||
uint32_t max_subheaders;
|
uint32_t max_subheaders;
|
||||||
|
|
|
@ -494,8 +494,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** PHY interface
|
/** PHY interface
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -566,12 +564,12 @@ public:
|
||||||
class phy_interface_mac : public phy_interface_mac_common
|
class phy_interface_mac : public phy_interface_mac_common
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/* Configure PRACH using parameters written by RRC */
|
/* Configure PRACH using parameters written by RRC */
|
||||||
virtual void configure_prach_params() = 0;
|
virtual void configure_prach_params() = 0;
|
||||||
|
|
||||||
virtual void prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm) = 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 */
|
/* Indicates the transmission of a SR signal in the next opportunity */
|
||||||
virtual void sr_send() = 0;
|
virtual void sr_send() = 0;
|
||||||
virtual int sr_last_tx_tti() = 0;
|
virtual int sr_last_tx_tti() = 0;
|
||||||
|
|
|
@ -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
|
|
@ -112,7 +112,8 @@ uint8_t* sch_pdu::write_packet(srslte::log *log_h)
|
||||||
onetwo_padding = rem_len;
|
onetwo_padding = rem_len;
|
||||||
rem_len = 0;
|
rem_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Determine the header size and CE payload size */
|
/* Determine the header size and CE payload size */
|
||||||
uint32_t header_sz = 0;
|
uint32_t header_sz = 0;
|
||||||
uint32_t ce_payload_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);
|
subheaders[i].write_payload(&ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set padding to zeros (if any)
|
// Set padding to zeros (if any)
|
||||||
if (rem_len > 0) {
|
if (rem_len > 0) {
|
||||||
bzero(&pdu_start_ptr[pdu_len-rem_len], rem_len*sizeof(uint8_t));
|
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];
|
return (uint16_t) w_payload_ce[0]<<8 | w_payload_ce[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t sch_subh::get_con_res_id()
|
uint64_t sch_subh::get_con_res_id()
|
||||||
{
|
{
|
||||||
if (payload) {
|
if (payload) {
|
||||||
|
@ -395,6 +396,7 @@ uint64_t sch_subh::get_con_res_id()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float sch_subh::get_phr()
|
float sch_subh::get_phr()
|
||||||
{
|
{
|
||||||
if (payload) {
|
if (payload) {
|
||||||
|
@ -786,12 +788,6 @@ uint8_t sch_subh::phr_report_table(float phr_value)
|
||||||
return (uint8_t) floor(phr_value+23);
|
return (uint8_t) floor(phr_value+23);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void rar_pdu::fprint(FILE* stream)
|
void rar_pdu::fprint(FILE* stream)
|
||||||
{
|
{
|
||||||
fprintf(stream, "MAC PDU for RAR. ");
|
fprintf(stream, "MAC PDU for RAR. ");
|
||||||
|
@ -861,38 +857,47 @@ void rar_subh::init()
|
||||||
ta = 0;
|
ta = 0;
|
||||||
temp_rnti = 0;
|
temp_rnti = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t rar_subh::get_rapid()
|
uint32_t rar_subh::get_rapid()
|
||||||
{
|
{
|
||||||
return preamble;
|
return preamble;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rar_subh::get_sched_grant(uint8_t grant_[RAR_GRANT_LEN])
|
void rar_subh::get_sched_grant(uint8_t grant_[RAR_GRANT_LEN])
|
||||||
{
|
{
|
||||||
memcpy(grant_, grant, sizeof(uint8_t)*RAR_GRANT_LEN);
|
memcpy(grant_, grant, sizeof(uint8_t)*RAR_GRANT_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t rar_subh::get_ta_cmd()
|
uint32_t rar_subh::get_ta_cmd()
|
||||||
{
|
{
|
||||||
return ta;
|
return ta;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t rar_subh::get_temp_crnti()
|
uint16_t rar_subh::get_temp_crnti()
|
||||||
{
|
{
|
||||||
return temp_rnti;
|
return temp_rnti;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rar_subh::set_rapid(uint32_t rapid)
|
void rar_subh::set_rapid(uint32_t rapid)
|
||||||
{
|
{
|
||||||
preamble = rapid;
|
preamble = rapid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rar_subh::set_sched_grant(uint8_t grant_[RAR_GRANT_LEN])
|
void rar_subh::set_sched_grant(uint8_t grant_[RAR_GRANT_LEN])
|
||||||
{
|
{
|
||||||
memcpy(grant, grant_, sizeof(uint8_t)*RAR_GRANT_LEN);
|
memcpy(grant, grant_, sizeof(uint8_t)*RAR_GRANT_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rar_subh::set_ta_cmd(uint32_t ta_)
|
void rar_subh::set_ta_cmd(uint32_t ta_)
|
||||||
{
|
{
|
||||||
ta = ta_;
|
ta = ta_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rar_subh::set_temp_crnti(uint16_t temp_rnti_)
|
void rar_subh::set_temp_crnti(uint16_t temp_rnti_)
|
||||||
{
|
{
|
||||||
temp_rnti = temp_rnti_;
|
temp_rnti = temp_rnti_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Section 6.2.2
|
// Section 6.2.2
|
||||||
void rar_subh::write_subheader(uint8_t** ptr, bool is_last)
|
void rar_subh::write_subheader(uint8_t** ptr, bool is_last)
|
||||||
{
|
{
|
||||||
|
|
|
@ -124,7 +124,7 @@ int srslte_chest_dl_init(srslte_chest_dl_t *q, uint32_t max_prb)
|
||||||
perror("malloc");
|
perror("malloc");
|
||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
q->pilot_recv_signal = srslte_vec_malloc(sizeof(cf_t) * pilot_vec_size);
|
q->pilot_recv_signal = srslte_vec_malloc(sizeof(cf_t) * pilot_vec_size);
|
||||||
if (!q->pilot_recv_signal) {
|
if (!q->pilot_recv_signal) {
|
||||||
perror("malloc");
|
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->noise_alg = SRSLTE_NOISE_ALG_REFS;
|
||||||
|
|
||||||
q->rsrp_neighbour = false;
|
q->rsrp_neighbour = false;
|
||||||
|
q->average_subframe = false;
|
||||||
q->smooth_filter_auto = false;
|
q->smooth_filter_auto = false;
|
||||||
q->smooth_filter_len = 3;
|
q->smooth_filter_len = 3;
|
||||||
srslte_chest_dl_set_smooth_filter3_coeff(q, 0.1);
|
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 */
|
/* Get PSS from received signal */
|
||||||
srslte_pss_get_slot(input, q->tmp_pss, q->cell.nof_prb, q->cell.cp);
|
srslte_pss_get_slot(input, q->tmp_pss, q->cell.nof_prb, q->cell.cp);
|
||||||
|
|
||||||
/* Get channel estimates for PSS position */
|
/* Get channel estimates for PSS position */
|
||||||
srslte_pss_get_slot(ce, q->tmp_pss_noisy, q->cell.nof_prb, q->cell.cp);
|
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 */
|
/* Substract received signal */
|
||||||
srslte_vec_sub_ccc(q->tmp_pss_noisy, q->tmp_pss, q->tmp_pss_noisy, SRSLTE_PSS_LEN);
|
srslte_vec_sub_ccc(q->tmp_pss_noisy, q->tmp_pss, q->tmp_pss_noisy, SRSLTE_PSS_LEN);
|
||||||
|
|
||||||
/* Compute average power */
|
/* Compute average power */
|
||||||
float power = q->cell.nof_ports*srslte_vec_avg_power_cf(q->tmp_pss_noisy, SRSLTE_PSS_LEN)/sqrt(2);
|
float power = q->cell.nof_ports*srslte_vec_avg_power_cf(q->tmp_pss_noisy, SRSLTE_PSS_LEN)/sqrt(2);
|
||||||
return power;
|
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 */
|
/* 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) {
|
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;
|
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-5], 5); // 5 empty SC before SSS
|
||||||
noise_power += srslte_vec_avg_power_cf(&input[k_sss+62], 5); // 5 empty SC after 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;
|
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-5], 5); // 5 empty SC before PSS
|
||||||
noise_power += srslte_vec_avg_power_cf(&input[k_pss+62], 5); // 5 empty SC after 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)]
|
#define cesymb(i) ce[SRSLTE_RE_IDX(q->cell.nof_prb,i,0)]
|
||||||
|
|
|
@ -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);
|
return 1+l*SRSLTE_CP_NSYMB(cp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32_t srslte_refsignal_mbsfn_nsymbol(uint32_t l)
|
inline uint32_t srslte_refsignal_mbsfn_nsymbol(uint32_t l)
|
||||||
{
|
{
|
||||||
uint32_t ret = 0;
|
uint32_t ret = 0;
|
||||||
|
|
|
@ -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)
|
void srslte_ofdm_tx_slot_mbsfn(srslte_ofdm_t *q, cf_t *input, cf_t *output)
|
||||||
{
|
{
|
||||||
uint32_t i, cp_len;
|
uint32_t i, cp_len;
|
||||||
|
|
||||||
for(i=0;i<q->nof_symbols_mbsfn;i++) {
|
for(i=0;i<q->nof_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);
|
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));
|
memcpy(&q->tmp[q->nof_guards], input, q->nof_re * sizeof(cf_t));
|
||||||
|
|
|
@ -364,7 +364,6 @@ int srslte_pmch_decode_multi(srslte_pmch_t *q,
|
||||||
data != NULL &&
|
data != NULL &&
|
||||||
cfg != 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",
|
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->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);
|
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 */
|
/* extract symbols */
|
||||||
n = srslte_pmch_get(q, sf_symbols[j], q->symbols[j], cfg->nbits[0].lstart);
|
n = srslte_pmch_get(q, sf_symbols[j], q->symbols[j], cfg->nbits[0].lstart);
|
||||||
if (n != cfg->nbits[0].nof_re) {
|
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);
|
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;
|
return SRSLTE_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -433,7 +433,6 @@ int srslte_pmch_encode(srslte_pmch_t *q,
|
||||||
/* Set pointers for layermapping & precoding */
|
/* Set pointers for layermapping & precoding */
|
||||||
cf_t *x[SRSLTE_MAX_LAYERS];
|
cf_t *x[SRSLTE_MAX_LAYERS];
|
||||||
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
int ret = SRSLTE_ERROR_INVALID_INPUTS;
|
||||||
|
|
||||||
if (q != NULL && cfg != NULL)
|
if (q != NULL && cfg != NULL)
|
||||||
{
|
{
|
||||||
for (i=0;i<q->cell.nof_ports;i++) {
|
for (i=0;i<q->cell.nof_ports;i++) {
|
||||||
|
|
|
@ -658,6 +658,7 @@ int srslte_ue_dl_decode_mbsfn(srslte_ue_dl_t * q,
|
||||||
noise_estimate,
|
noise_estimate,
|
||||||
q->current_mbsfn_area_id, data);
|
q->current_mbsfn_area_id, data);
|
||||||
|
|
||||||
|
|
||||||
if (ret == SRSLTE_ERROR) {
|
if (ret == SRSLTE_ERROR) {
|
||||||
q->pmch_pkt_errors++;
|
q->pmch_pkt_errors++;
|
||||||
} else if (ret == SRSLTE_ERROR_INVALID_INPUTS) {
|
} else if (ret == SRSLTE_ERROR_INVALID_INPUTS) {
|
||||||
|
|
|
@ -139,7 +139,7 @@ void srslte_vec_fprint_c(FILE *stream, cf_t *x, const uint32_t len) {
|
||||||
int i;
|
int i;
|
||||||
fprintf(stream, "[");
|
fprintf(stream, "[");
|
||||||
for (i=0;i<len;i++) {
|
for (i=0;i<len;i++) {
|
||||||
fprintf(stream, "%+2.2f%+2.2fi, ", __real__ x[i], __imag__ x[i]);
|
fprintf(stream, "%+2.5f%+2.5fi, ", __real__ x[i], __imag__ x[i]);
|
||||||
}
|
}
|
||||||
fprintf(stream, "];\n");
|
fprintf(stream, "];\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ rlc_um::rlc_um() : tx_sdu_queue(32)
|
||||||
bzero(&cfg, sizeof(srslte_rlc_um_config_t));
|
bzero(&cfg, sizeof(srslte_rlc_um_config_t));
|
||||||
|
|
||||||
tx_sdu = NULL;
|
tx_sdu = NULL;
|
||||||
|
|
||||||
rx_sdu = NULL;
|
rx_sdu = NULL;
|
||||||
pool = byte_buffer_pool::get_instance();
|
pool = byte_buffer_pool::get_instance();
|
||||||
|
|
||||||
|
@ -480,6 +481,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",
|
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());
|
rrc->get_rb_name(lcid).c_str(), tx_sdu->get_latency_us());
|
||||||
|
|
||||||
pool->deallocate(tx_sdu);
|
pool->deallocate(tx_sdu);
|
||||||
tx_sdu = NULL;
|
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",
|
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());
|
rrc->get_rb_name(lcid).c_str(), tx_sdu->get_latency_us());
|
||||||
|
|
||||||
pool->deallocate(tx_sdu);
|
pool->deallocate(tx_sdu);
|
||||||
tx_sdu = NULL;
|
tx_sdu = NULL;
|
||||||
}
|
}
|
||||||
|
@ -717,6 +720,7 @@ void rlc_um::reassemble_rx_sdus()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle last segment
|
// Handle last segment
|
||||||
|
|
||||||
if (rx_sdu->N_bytes > 0 || rlc_um_start_aligned(rx_window[vr_ur].header.fi)) {
|
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",
|
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);
|
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 ext;
|
||||||
uint8_t *ptr = payload;
|
uint8_t *ptr = payload;
|
||||||
|
|
||||||
// Fixed part
|
// Fixed part
|
||||||
if(RLC_UMD_SN_SIZE_5_BITS == sn_size)
|
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;
|
uint32_t i;
|
||||||
uint8_t ext = (header->N_li > 0) ? 1 : 0;
|
uint8_t ext = (header->N_li > 0) ? 1 : 0;
|
||||||
|
|
||||||
// Make room for the header
|
// Make room for the header
|
||||||
uint32_t len = rlc_um_packed_length(header);
|
uint32_t len = rlc_um_packed_length(header);
|
||||||
pdu->msg -= len;
|
pdu->msg -= len;
|
||||||
|
|
|
@ -545,3 +545,4 @@ int main(int argc, char **argv) {
|
||||||
reassmble_test2();
|
reassmble_test2();
|
||||||
byte_buffer_pool::get_instance()->cleanup();
|
byte_buffer_pool::get_instance()->cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,7 @@ typedef struct {
|
||||||
LIBLTE_RRC_SRS_UL_CONFIG_COMMON_STRUCT srs_ul_cnfg;
|
LIBLTE_RRC_SRS_UL_CONFIG_COMMON_STRUCT srs_ul_cnfg;
|
||||||
} phy_cfg_t;
|
} phy_cfg_t;
|
||||||
|
|
||||||
|
|
||||||
class phy : public phy_interface_mac,
|
class phy : public phy_interface_mac,
|
||||||
public phy_interface_rrc
|
public phy_interface_rrc
|
||||||
{
|
{
|
||||||
|
|
|
@ -78,6 +78,7 @@ typedef struct {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_STRUCT sibs[LIBLTE_RRC_MAX_SIB];
|
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_STRUCT sibs[LIBLTE_RRC_MAX_SIB];
|
||||||
LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT mac_cnfg;
|
LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT mac_cnfg;
|
||||||
|
|
||||||
LIBLTE_RRC_PUSCH_CONFIG_DEDICATED_STRUCT pusch_cfg;
|
LIBLTE_RRC_PUSCH_CONFIG_DEDICATED_STRUCT pusch_cfg;
|
||||||
LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT antenna_info;
|
LIBLTE_RRC_ANTENNA_INFO_DEDICATED_STRUCT antenna_info;
|
||||||
LIBLTE_RRC_PDSCH_CONFIG_P_A_ENUM pdsch_cfg;
|
LIBLTE_RRC_PDSCH_CONFIG_P_A_ENUM pdsch_cfg;
|
||||||
|
|
|
@ -735,6 +735,7 @@ uint32_t HexToBytes(const std::string& str, uint8_t *char_value, uint32_t buff_l
|
||||||
return i/2;
|
return i/2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int enb::parse_sib9(std::string filename, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_9_STRUCT *data)
|
int enb::parse_sib9(std::string filename, LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_9_STRUCT *data)
|
||||||
{
|
{
|
||||||
parser::section sib9("sib9");
|
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)) {
|
if (parse_sib2(args->enb_files.sib_config, sib2)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SRS not yet supported
|
// SRS not yet supported
|
||||||
sib2->rr_config_common_sib.srs_ul_cnfg.present = false;
|
sib2->rr_config_common_sib.srs_ul_cnfg.present = false;
|
||||||
if (sib2->ul_bw.present) {
|
if (sib2->ul_bw.present) {
|
||||||
|
|
|
@ -449,7 +449,6 @@ int mac::rach_detected(uint32_t tti, uint32_t preamble_idx, uint32_t time_adv)
|
||||||
|
|
||||||
// Register new user in RRC
|
// Register new user in RRC
|
||||||
rrc_h->add_user(last_rnti);
|
rrc_h->add_user(last_rnti);
|
||||||
|
|
||||||
// Trigger scheduler RACH
|
// Trigger scheduler RACH
|
||||||
scheduler.dl_rach_info(tti, ra_id, last_rnti, 7);
|
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)
|
uint8_t* mac::assemble_si(uint32_t index)
|
||||||
{
|
{
|
||||||
rlc_h->read_pdu_bcch_dlsch(index, bcch_dlsch_payload);
|
rlc_h->read_pdu_bcch_dlsch(index, bcch_dlsch_payload);
|
||||||
return bcch_dlsch_payload;
|
return bcch_dlsch_payload;
|
||||||
}
|
}
|
||||||
|
@ -774,9 +773,6 @@ void mac::tti_clock()
|
||||||
timers_thread.tti_clock();
|
timers_thread.tti_clock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/********************************************************
|
/********************************************************
|
||||||
*
|
*
|
||||||
* Interface for upper layer timers
|
* 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
|
* Class to run timers with normal priority
|
||||||
|
|
|
@ -775,10 +775,10 @@ int sched::dl_sched(uint32_t tti, sched_interface::dl_sched_res_t* sched_result)
|
||||||
|
|
||||||
/* Schedule Broadcast data */
|
/* Schedule Broadcast data */
|
||||||
sched_result->nof_bc_elems += dl_sched_bc(sched_result->bc);
|
sched_result->nof_bc_elems += dl_sched_bc(sched_result->bc);
|
||||||
|
|
||||||
/* Schedule RAR */
|
/* Schedule RAR */
|
||||||
sched_result->nof_rar_elems += dl_sched_rar(sched_result->rar);
|
sched_result->nof_rar_elems += dl_sched_rar(sched_result->rar);
|
||||||
|
|
||||||
/* Schedule pending RLC data */
|
/* Schedule pending RLC data */
|
||||||
sched_result->nof_data_elems += dl_sched_data(sched_result->data);
|
sched_result->nof_data_elems += dl_sched_data(sched_result->data);
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
while(sdu_len > 3 && n > 0) {
|
||||||
if (pdu->new_subh()) { // there is space for a new subheader
|
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);
|
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
|
if (n > 0) { // new SDU could be added
|
||||||
sdu_len -= n;
|
sdu_len -= n;
|
||||||
log_h->debug("SDU: rnti=0x%x, lcid=%d, nbytes=%d, rem_len=%d\n",
|
log_h->debug("SDU: rnti=0x%x, lcid=%d, nbytes=%d, rem_len=%d\n",
|
||||||
|
|
|
@ -57,6 +57,8 @@ bool phch_common::init(srslte_cell_t *cell_, srslte::radio* radio_h_, mac_interf
|
||||||
mac = mac_;
|
mac = mac_;
|
||||||
memcpy(&cell, cell_, sizeof(srslte_cell_t));
|
memcpy(&cell, cell_, sizeof(srslte_cell_t));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
is_first_of_burst = true;
|
is_first_of_burst = true;
|
||||||
is_first_tx = true;
|
is_first_tx = true;
|
||||||
for (uint32_t i=0;i<max_mutex;i++) {
|
for (uint32_t i=0;i<max_mutex;i++) {
|
||||||
|
|
|
@ -1056,18 +1056,6 @@ void phch_worker::ue::metrics_ul(uint32_t mcs, float rssi, float sinr, uint32_t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void phch_worker::start_plot() {
|
void phch_worker::start_plot() {
|
||||||
#ifdef ENABLE_GUI
|
#ifdef ENABLE_GUI
|
||||||
|
|
|
@ -131,6 +131,7 @@ void pdcp::user_interface_gtpu::write_pdu(uint32_t lcid, srslte::byte_buffer_t *
|
||||||
|
|
||||||
void pdcp::user_interface_rlc::write_sdu(uint32_t lcid, srslte::byte_buffer_t* sdu)
|
void pdcp::user_interface_rlc::write_sdu(uint32_t lcid, srslte::byte_buffer_t* sdu)
|
||||||
{
|
{
|
||||||
|
|
||||||
rlc->write_sdu(rnti, lcid, sdu);
|
rlc->write_sdu(rnti, lcid, sdu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "srslte/srslte.h"
|
#include "srslte/srslte.h"
|
||||||
#include "srslte/asn1/liblte_mme.h"
|
#include "srslte/asn1/liblte_mme.h"
|
||||||
|
|
||||||
|
|
||||||
using srslte::byte_buffer_t;
|
using srslte::byte_buffer_t;
|
||||||
using srslte::bit_buffer_t;
|
using srslte::bit_buffer_t;
|
||||||
|
|
||||||
|
@ -273,6 +274,7 @@ void rrc::add_user(uint16_t rnti)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&user_mutex);
|
pthread_mutex_lock(&user_mutex);
|
||||||
if (users.count(rnti) == 0) {
|
if (users.count(rnti) == 0) {
|
||||||
|
|
||||||
users[rnti].parent = this;
|
users[rnti].parent = this;
|
||||||
users[rnti].rnti = rnti;
|
users[rnti].rnti = rnti;
|
||||||
rlc->add_user(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_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.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;
|
sched_cfg.pucch_cfg.n1_pucch_an = parent->sib2.rr_config_common_sib.pucch_cnfg.n1_pucch_an;
|
||||||
|
|
||||||
// Configure MAC
|
// Configure MAC
|
||||||
parent->mac->ue_cfg(rnti, &sched_cfg);
|
parent->mac->ue_cfg(rnti, &sched_cfg);
|
||||||
|
|
||||||
|
|
|
@ -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 <cstddef>
|
||||||
|
#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
|
|
@ -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
|
|
@ -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(mme)
|
||||||
add_subdirectory(hss)
|
add_subdirectory(hss)
|
||||||
add_subdirectory(spgw)
|
add_subdirectory(spgw)
|
||||||
|
add_subdirectory(mbms-gw)
|
||||||
|
|
||||||
# Link libstdc++ and libgcc
|
# Link libstdc++ and libgcc
|
||||||
if(BUILD_STATIC)
|
if(BUILD_STATIC)
|
||||||
|
@ -26,11 +46,22 @@ target_link_libraries(srsepc srsepc_mme
|
||||||
${LIBCONFIGPP_LIBRARIES}
|
${LIBCONFIGPP_LIBRARIES}
|
||||||
${SCTP_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)
|
if (RPATH)
|
||||||
set_target_properties(srsepc PROPERTIES INSTALL_RPATH ".")
|
set_target_properties(srsepc PROPERTIES INSTALL_RPATH ".")
|
||||||
|
set_target_properties(srsmbms PROPERTIES INSTALL_RPATH ".")
|
||||||
endif (RPATH)
|
endif (RPATH)
|
||||||
|
|
||||||
install(TARGETS srsepc DESTINATION ${RUNTIME_DIR})
|
install(TARGETS srsepc DESTINATION ${RUNTIME_DIR})
|
||||||
|
install(TARGETS srsmbms DESTINATION ${RUNTIME_DIR})
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
# Option to run command after build (useful for remote builds)
|
# Option to run command after build (useful for remote builds)
|
||||||
|
|
|
@ -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})
|
|
@ -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 <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <boost/program_options.hpp>
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
#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<string>(&mbms_gw_name)->default_value("srsmbmsgw01"), "MBMS-GW Name")
|
||||||
|
("mbms_gw.sgi_mb_if_addr", bpo::value<string>(&mbms_gw_sgi_mb_if_addr)->default_value("172.16.1.1"), "SGi-mb TUN interface Address")
|
||||||
|
("mbms_gw.m1u_multi_addr", bpo::value<string>(&mbms_gw_m1u_multi_addr)->default_value("239.255.0.1"), "M1-u GTPu destination multicast address")
|
||||||
|
|
||||||
|
("log.all_level", bpo::value<string>(&args->log_args.all_level)->default_value("info"), "ALL log level")
|
||||||
|
("log.all_hex_limit", bpo::value<int>(&args->log_args.all_hex_limit)->default_value(32), "ALL log hex dump limit")
|
||||||
|
|
||||||
|
("log.filename", bpo::value<string>(&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;
|
||||||
|
}
|
|
@ -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 <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <linux/if.h>
|
||||||
|
#include <linux/if_tun.h>
|
||||||
|
#include <linux/ip.h>
|
||||||
|
#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
|
|
@ -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_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_ul_search_reset();
|
||||||
void pdcch_dl_search_reset();
|
void pdcch_dl_search_reset();
|
||||||
|
|
||||||
/* Get/Set PHY parameters interface from RRC */
|
/* Get/Set PHY parameters interface from RRC */
|
||||||
void get_config(phy_cfg_t *phy_cfg);
|
void get_config(phy_cfg_t *phy_cfg);
|
||||||
void set_config(phy_cfg_t *phy_cfg);
|
void set_config(phy_cfg_t *phy_cfg);
|
||||||
|
|
|
@ -74,9 +74,10 @@ private:
|
||||||
nas_interface_gw *nas;
|
nas_interface_gw *nas;
|
||||||
|
|
||||||
srslte::byte_buffer_pool *pool;
|
srslte::byte_buffer_pool *pool;
|
||||||
|
|
||||||
srslte::log *gw_log;
|
srslte::log *gw_log;
|
||||||
|
|
||||||
srslte::srslte_gw_config_t cfg;
|
srslte::srslte_gw_config_t cfg;
|
||||||
|
|
||||||
bool running;
|
bool running;
|
||||||
bool run_enable;
|
bool run_enable;
|
||||||
int32 tun_fd;
|
int32 tun_fd;
|
||||||
|
|
|
@ -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;
|
bsr_proc::bsr_t bsr;
|
||||||
bool regular_bsr = bsr_procedure->need_to_send_bsr_on_ul_grant(pdu_msg.rem_size(), &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;
|
// MAC control element for BSR, with exception of BSR included for padding;
|
||||||
if (regular_bsr) {
|
if (regular_bsr) {
|
||||||
|
|
|
@ -271,8 +271,9 @@ void ra_proc::step_preamble_transmission() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ra_proc::step_pdcch_setup() {
|
void ra_proc::step_pdcch_setup() {
|
||||||
|
|
||||||
int ra_tti = phy_h->prach_tx_tti();
|
int ra_tti = phy_h->prach_tx_tti();
|
||||||
if (ra_tti > 0) {
|
if (ra_tti > 0) {
|
||||||
ra_rnti = 1+ra_tti%10;
|
ra_rnti = 1+ra_tti%10;
|
||||||
rInfo("seq=%d, ra-rnti=0x%x, ra-tti=%d\n", sel_preamble, ra_rnti, ra_tti);
|
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);
|
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) {
|
if (ra_tti >= 0 && !rar_received) {
|
||||||
uint32_t interval = srslte_tti_interval(phy_h->get_current_tti(), ra_tti+3+responseWindowSize);
|
uint32_t interval = srslte_tti_interval(phy_h->get_current_tti(), ra_tti+3+responseWindowSize);
|
||||||
if (interval > 1 && interval < 100) {
|
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;
|
state = RESPONSE_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 (file.is_open() && ue != NULL) {
|
||||||
if(n_reports == 0) {
|
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 << (metrics_report_period*n_reports) << ";";
|
||||||
file << float_to_string(metrics.phy.dl.rsrp, 2);
|
file << float_to_string(metrics.phy.dl.rsrp, 2);
|
||||||
|
|
|
@ -51,7 +51,8 @@ phch_common::phch_common(uint32_t max_mutex_) : tx_mutex(max_mutex_)
|
||||||
rx_gain_offset = 0;
|
rx_gain_offset = 0;
|
||||||
last_ri = 0;
|
last_ri = 0;
|
||||||
last_pmi = 0;
|
last_pmi = 0;
|
||||||
|
//have_mtch_stop = false;
|
||||||
|
|
||||||
bzero(&dl_metrics, sizeof(dl_metrics_t));
|
bzero(&dl_metrics, sizeof(dl_metrics_t));
|
||||||
dl_metrics_read = true;
|
dl_metrics_read = true;
|
||||||
dl_metrics_count = 0;
|
dl_metrics_count = 0;
|
||||||
|
|
|
@ -392,6 +392,7 @@ void phch_recv::run_thread()
|
||||||
phy_state.state_exit();
|
phy_state.state_exit();
|
||||||
break;
|
break;
|
||||||
case sync_state::SFN_SYNC:
|
case sync_state::SFN_SYNC:
|
||||||
|
|
||||||
/* SFN synchronization using MIB. run_subframe() receives and processes 1 subframe
|
/* SFN synchronization using MIB. run_subframe() receives and processes 1 subframe
|
||||||
* and returns
|
* and returns
|
||||||
*/
|
*/
|
||||||
|
@ -473,6 +474,7 @@ void phch_recv::run_thread()
|
||||||
|
|
||||||
is_end_of_burst = true;
|
is_end_of_burst = true;
|
||||||
|
|
||||||
|
|
||||||
// Start worker
|
// Start worker
|
||||||
workers_pool->start_worker(worker);
|
workers_pool->start_worker(worker);
|
||||||
|
|
||||||
|
@ -500,6 +502,7 @@ void phch_recv::run_thread()
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case sync_state::IDLE:
|
case sync_state::IDLE:
|
||||||
|
|
||||||
if (radio_h->is_init()) {
|
if (radio_h->is_init()) {
|
||||||
uint32_t nsamples = 1920;
|
uint32_t nsamples = 1920;
|
||||||
if (current_srate > 0) {
|
if (current_srate > 0) {
|
||||||
|
|
|
@ -133,6 +133,7 @@ bool phch_worker::init(uint32_t max_prb, srslte::log *log_h, srslte::log *log_ph
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
srslte_chest_dl_set_rsrp_neighbour(&ue_dl.chest, true);
|
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_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);
|
srslte_chest_dl_cfo_estimate_enable(&ue_dl.chest, phy->args->cfo_ref_mask!=0, phy->args->cfo_ref_mask);
|
||||||
|
|
|
@ -354,6 +354,7 @@ uint32_t phy::get_current_tti()
|
||||||
return sf_recv.get_current_tti();
|
return sf_recv.get_current_tti();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void phy::sr_send()
|
void phy::sr_send()
|
||||||
{
|
{
|
||||||
workers_common.sr_enabled = true;
|
workers_common.sr_enabled = true;
|
||||||
|
|
Loading…
Reference in New Issue