mirror of https://github.com/PentHertz/srsLTE.git
adding upper layer embms support to the UE
This commit is contained in:
parent
e35672e234
commit
12c9f50ba9
|
@ -58,7 +58,7 @@ public:
|
||||||
bool get_uecrid_successful();
|
bool get_uecrid_successful();
|
||||||
|
|
||||||
void process_pdu(uint8_t *pdu, uint32_t nof_bytes, srslte::pdu_queue::channel_t channel, uint32_t tstamp);
|
void process_pdu(uint8_t *pdu, uint32_t nof_bytes, srslte::pdu_queue::channel_t channel, uint32_t tstamp);
|
||||||
|
void mch_start_rx(uint32_t lcid);
|
||||||
private:
|
private:
|
||||||
const static int MAX_PDU_LEN = 150*1024/8; // ~ 150 Mbps
|
const static int MAX_PDU_LEN = 150*1024/8; // ~ 150 Mbps
|
||||||
const static int NOF_BUFFER_PDUS = 64; // Number of PDU buffers per HARQ pid
|
const static int NOF_BUFFER_PDUS = 64; // Number of PDU buffers per HARQ pid
|
||||||
|
@ -69,9 +69,13 @@ private:
|
||||||
void *uecrid_callback_arg;
|
void *uecrid_callback_arg;
|
||||||
|
|
||||||
srslte::sch_pdu mac_msg;
|
srslte::sch_pdu mac_msg;
|
||||||
|
srslte::mch_pdu mch_mac_msg;
|
||||||
srslte::sch_pdu pending_mac_msg;
|
srslte::sch_pdu pending_mac_msg;
|
||||||
|
uint8_t mch_lcids[SRSLTE_N_MCH_LCIDS];
|
||||||
void process_sch_pdu(srslte::sch_pdu *pdu);
|
void process_sch_pdu(srslte::sch_pdu *pdu);
|
||||||
|
void process_mch_pdu(srslte::mch_pdu *pdu);
|
||||||
|
|
||||||
|
|
||||||
bool process_ce(srslte::sch_subh *subheader);
|
bool process_ce(srslte::sch_subh *subheader);
|
||||||
|
|
||||||
bool is_uecrid_successful;
|
bool is_uecrid_successful;
|
||||||
|
|
|
@ -65,17 +65,23 @@ public:
|
||||||
void new_grant_ul_ack(mac_grant_t grant, bool ack, tb_action_ul_t *action);
|
void new_grant_ul_ack(mac_grant_t grant, bool ack, tb_action_ul_t *action);
|
||||||
void harq_recv(uint32_t tti, bool ack, tb_action_ul_t *action);
|
void harq_recv(uint32_t tti, bool ack, tb_action_ul_t *action);
|
||||||
void new_grant_dl(mac_grant_t grant, tb_action_dl_t *action);
|
void new_grant_dl(mac_grant_t grant, tb_action_dl_t *action);
|
||||||
|
void new_mch_dl(srslte_ra_dl_grant_t phy_grant, tb_action_dl_t *action);
|
||||||
void tb_decoded(bool ack, uint32_t tb_idx, srslte_rnti_type_t rnti_type, uint32_t harq_pid);
|
void tb_decoded(bool ack, uint32_t tb_idx, srslte_rnti_type_t rnti_type, uint32_t harq_pid);
|
||||||
void bch_decoded_ok(uint8_t *payload, uint32_t len);
|
void bch_decoded_ok(uint8_t *payload, uint32_t len);
|
||||||
void pch_decoded_ok(uint32_t len);
|
|
||||||
|
|
||||||
|
void pch_decoded_ok(uint32_t len);
|
||||||
|
void mch_decoded_ok(uint32_t len);
|
||||||
|
void process_mch_pdu(uint32_t len);
|
||||||
|
|
||||||
|
void set_mbsfn_config(uint32_t nof_mbsfn_services);
|
||||||
|
|
||||||
/******** Interface from RLC (RLC -> MAC) ****************/
|
/******** Interface from RRC (RRC -> MAC) ****************/
|
||||||
void bcch_start_rx();
|
void bcch_start_rx();
|
||||||
void bcch_start_rx(int si_window_start, int si_window_length);
|
void bcch_start_rx(int si_window_start, int si_window_length);
|
||||||
void pcch_start_rx();
|
void pcch_start_rx();
|
||||||
void clear_rntis();
|
void clear_rntis();
|
||||||
void setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority, int PBR_x_tti, uint32_t BSD);
|
void setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority, int PBR_x_tti, uint32_t BSD);
|
||||||
|
void mch_start_rx(uint32_t lcid);
|
||||||
void reconfiguration();
|
void reconfiguration();
|
||||||
void reset();
|
void reset();
|
||||||
void wait_uplink();
|
void wait_uplink();
|
||||||
|
@ -119,6 +125,7 @@ private:
|
||||||
rlc_interface_mac *rlc_h;
|
rlc_interface_mac *rlc_h;
|
||||||
rrc_interface_mac *rrc_h;
|
rrc_interface_mac *rrc_h;
|
||||||
srslte::log *log_h;
|
srslte::log *log_h;
|
||||||
|
mac_interface_phy::mac_phy_cfg_mbsfn_t phy_mbsfn_cfg;
|
||||||
|
|
||||||
// MAC configuration
|
// MAC configuration
|
||||||
mac_cfg_t config;
|
mac_cfg_t config;
|
||||||
|
@ -147,6 +154,13 @@ private:
|
||||||
srslte_softbuffer_rx_t pch_softbuffer;
|
srslte_softbuffer_rx_t pch_softbuffer;
|
||||||
uint8_t pch_payload_buffer[pch_payload_buffer_sz];
|
uint8_t pch_payload_buffer[pch_payload_buffer_sz];
|
||||||
|
|
||||||
|
/* Buffers for MCH reception (not included in DL HARQ) */
|
||||||
|
const static uint32_t mch_payload_buffer_sz = SRSLTE_MAX_BUFFER_SIZE_BYTES;
|
||||||
|
srslte_softbuffer_rx_t mch_softbuffer;
|
||||||
|
uint8_t mch_payload_buffer[mch_payload_buffer_sz];
|
||||||
|
srslte::mch_pdu mch_msg;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Functions for MAC Timers */
|
/* Functions for MAC Timers */
|
||||||
uint32_t timer_alignment;
|
uint32_t timer_alignment;
|
||||||
|
|
|
@ -73,6 +73,8 @@ public:
|
||||||
bool deattach();
|
bool deattach();
|
||||||
bool is_attached();
|
bool is_attached();
|
||||||
void start_plot();
|
void start_plot();
|
||||||
|
void print_mbms();
|
||||||
|
void mbms_service_start(uint32_t serv, uint32_t port);
|
||||||
|
|
||||||
void print_pool();
|
void print_pool();
|
||||||
|
|
||||||
|
|
|
@ -165,6 +165,9 @@ public:
|
||||||
virtual void print_pool() = 0;
|
virtual void print_pool() = 0;
|
||||||
|
|
||||||
virtual void radio_overflow() = 0;
|
virtual void radio_overflow() = 0;
|
||||||
|
|
||||||
|
virtual void print_mbms() = 0;
|
||||||
|
virtual void mbms_service_start(uint32_t serv, uint32_t port) = 0;
|
||||||
|
|
||||||
void handle_rf_msg(srslte_rf_error_t error);
|
void handle_rf_msg(srslte_rf_error_t error);
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ namespace srsue {
|
||||||
class gw
|
class gw
|
||||||
:public gw_interface_pdcp
|
:public gw_interface_pdcp
|
||||||
,public gw_interface_nas
|
,public gw_interface_nas
|
||||||
|
,public gw_interface_rrc
|
||||||
,public thread
|
,public thread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -50,14 +51,17 @@ public:
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
void get_metrics(gw_metrics_t &m);
|
void get_metrics(gw_metrics_t &m);
|
||||||
|
void set_netmask(std::string netmask);
|
||||||
|
|
||||||
// PDCP interface
|
// PDCP interface
|
||||||
void write_pdu(uint32_t lcid, srslte::byte_buffer_t *pdu);
|
void write_pdu(uint32_t lcid, srslte::byte_buffer_t *pdu);
|
||||||
|
void write_pdu_mch(uint32_t lcid, srslte::byte_buffer_t *pdu);
|
||||||
|
|
||||||
// NAS interface
|
// NAS interface
|
||||||
srslte::error_t setup_if_addr(uint32_t ip_addr, char *err_str);
|
srslte::error_t setup_if_addr(uint32_t ip_addr, char *err_str);
|
||||||
|
|
||||||
void set_netmask(std::string netmask);
|
// RRC interface
|
||||||
|
void add_mch_port(uint32_t lcid, uint32_t port);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -88,6 +92,12 @@ private:
|
||||||
|
|
||||||
void run_thread();
|
void run_thread();
|
||||||
srslte::error_t init_if(char *err_str);
|
srslte::error_t init_if(char *err_str);
|
||||||
|
|
||||||
|
// MBSFN
|
||||||
|
int mbsfn_sock_fd; // Sink UDP socket file descriptor
|
||||||
|
struct sockaddr_in mbsfn_sock_addr; // Target address
|
||||||
|
uint32_t mbsfn_ports[SRSLTE_N_MCH_LCIDS]; // Target ports for MBSFN data
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace srsue
|
} // namespace srsue
|
||||||
|
|
|
@ -180,6 +180,9 @@ class cell_t
|
||||||
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *sib3ptr() {
|
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT *sib3ptr() {
|
||||||
return &sib3;
|
return &sib3;
|
||||||
}
|
}
|
||||||
|
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13ptr() {
|
||||||
|
return &sib13;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t get_cell_id() {
|
uint32_t get_cell_id() {
|
||||||
return sib1.cell_id;
|
return sib1.cell_id;
|
||||||
|
@ -231,20 +234,23 @@ class cell_t
|
||||||
}
|
}
|
||||||
|
|
||||||
phy_interface_rrc::phy_cell_t phy_cell;
|
phy_interface_rrc::phy_cell_t phy_cell;
|
||||||
bool in_sync;
|
bool in_sync;
|
||||||
|
bool has_mcch;
|
||||||
|
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT sib1;
|
||||||
|
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT sib2;
|
||||||
|
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT sib3;
|
||||||
|
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT sib13;
|
||||||
|
LIBLTE_RRC_MCCH_MSG_STRUCT mcch;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float rsrp;
|
float rsrp;
|
||||||
|
|
||||||
struct timeval last_update;
|
struct timeval last_update;
|
||||||
|
|
||||||
bool has_valid_sib1;
|
bool has_valid_sib1;
|
||||||
bool has_valid_sib2;
|
bool has_valid_sib2;
|
||||||
bool has_valid_sib3;
|
bool has_valid_sib3;
|
||||||
bool has_valid_sib13;
|
bool has_valid_sib13;
|
||||||
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_1_STRUCT sib1;
|
|
||||||
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT sib2;
|
|
||||||
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_3_STRUCT sib3;
|
|
||||||
LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT sib13;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class rrc
|
class rrc
|
||||||
|
@ -266,6 +272,7 @@ public:
|
||||||
pdcp_interface_rrc *pdcp_,
|
pdcp_interface_rrc *pdcp_,
|
||||||
nas_interface_rrc *nas_,
|
nas_interface_rrc *nas_,
|
||||||
usim_interface_rrc *usim_,
|
usim_interface_rrc *usim_,
|
||||||
|
gw_interface_rrc *gw_,
|
||||||
srslte::mac_interface_timers *mac_timers_,
|
srslte::mac_interface_timers *mac_timers_,
|
||||||
srslte::log *rrc_log_);
|
srslte::log *rrc_log_);
|
||||||
|
|
||||||
|
@ -277,6 +284,9 @@ public:
|
||||||
// Timeout callback interface
|
// Timeout callback interface
|
||||||
void timer_expired(uint32_t timeout_id);
|
void timer_expired(uint32_t timeout_id);
|
||||||
void liblte_rrc_log(char *str);
|
void liblte_rrc_log(char *str);
|
||||||
|
|
||||||
|
void print_mbms();
|
||||||
|
void mbms_service_start(uint32_t serv, uint32_t port);
|
||||||
|
|
||||||
// NAS interface
|
// NAS interface
|
||||||
void write_sdu(uint32_t lcid, byte_buffer_t *sdu);
|
void write_sdu(uint32_t lcid, byte_buffer_t *sdu);
|
||||||
|
@ -309,7 +319,7 @@ public:
|
||||||
void write_pdu_bcch_bch(byte_buffer_t *pdu);
|
void write_pdu_bcch_bch(byte_buffer_t *pdu);
|
||||||
void write_pdu_bcch_dlsch(byte_buffer_t *pdu);
|
void write_pdu_bcch_dlsch(byte_buffer_t *pdu);
|
||||||
void write_pdu_pcch(byte_buffer_t *pdu);
|
void write_pdu_pcch(byte_buffer_t *pdu);
|
||||||
|
void write_pdu_mch(uint32_t lcid, srslte::byte_buffer_t *pdu);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -335,7 +345,8 @@ private:
|
||||||
pdcp_interface_rrc *pdcp;
|
pdcp_interface_rrc *pdcp;
|
||||||
nas_interface_rrc *nas;
|
nas_interface_rrc *nas;
|
||||||
usim_interface_rrc *usim;
|
usim_interface_rrc *usim;
|
||||||
|
gw_interface_rrc *gw;
|
||||||
|
|
||||||
LIBLTE_RRC_UL_DCCH_MSG_STRUCT ul_dcch_msg;
|
LIBLTE_RRC_UL_DCCH_MSG_STRUCT ul_dcch_msg;
|
||||||
LIBLTE_RRC_UL_CCCH_MSG_STRUCT ul_ccch_msg;
|
LIBLTE_RRC_UL_CCCH_MSG_STRUCT ul_ccch_msg;
|
||||||
LIBLTE_RRC_DL_CCCH_MSG_STRUCT dl_ccch_msg;
|
LIBLTE_RRC_DL_CCCH_MSG_STRUCT dl_ccch_msg;
|
||||||
|
@ -435,7 +446,7 @@ private:
|
||||||
uint32_t sib_start_tti(uint32_t tti, uint32_t period, uint32_t offset, uint32_t sf);
|
uint32_t sib_start_tti(uint32_t tti, uint32_t period, uint32_t offset, uint32_t sf);
|
||||||
const static int SIB_SEARCH_TIMEOUT_MS = 1000;
|
const static int SIB_SEARCH_TIMEOUT_MS = 1000;
|
||||||
|
|
||||||
const static uint32_t NOF_REQUIRED_SIBS = 3; // SIB1, SIB2 and SIB3
|
const static uint32_t NOF_REQUIRED_SIBS = 13; // SIB1, SIB2 and SIB3
|
||||||
|
|
||||||
bool initiated;
|
bool initiated;
|
||||||
bool ho_start;
|
bool ho_start;
|
||||||
|
@ -618,12 +629,14 @@ private:
|
||||||
void handle_sib13();
|
void handle_sib13();
|
||||||
|
|
||||||
void apply_sib2_configs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2);
|
void apply_sib2_configs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2);
|
||||||
|
void apply_sib13_configs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13);
|
||||||
void handle_con_setup(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *setup);
|
void handle_con_setup(LIBLTE_RRC_CONNECTION_SETUP_STRUCT *setup);
|
||||||
void handle_con_reest(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_STRUCT *setup);
|
void handle_con_reest(LIBLTE_RRC_CONNECTION_REESTABLISHMENT_STRUCT *setup);
|
||||||
void handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *reconfig);
|
void handle_rrc_con_reconfig(uint32_t lcid, LIBLTE_RRC_CONNECTION_RECONFIGURATION_STRUCT *reconfig);
|
||||||
void add_srb(LIBLTE_RRC_SRB_TO_ADD_MOD_STRUCT *srb_cnfg);
|
void add_srb(LIBLTE_RRC_SRB_TO_ADD_MOD_STRUCT *srb_cnfg);
|
||||||
void add_drb(LIBLTE_RRC_DRB_TO_ADD_MOD_STRUCT *drb_cnfg);
|
void add_drb(LIBLTE_RRC_DRB_TO_ADD_MOD_STRUCT *drb_cnfg);
|
||||||
void release_drb(uint8_t lcid);
|
void release_drb(uint8_t lcid);
|
||||||
|
void add_mrb(uint32_t lcid, uint32_t port);
|
||||||
bool apply_rr_config_dedicated(LIBLTE_RRC_RR_CONFIG_DEDICATED_STRUCT *cnfg);
|
bool apply_rr_config_dedicated(LIBLTE_RRC_RR_CONFIG_DEDICATED_STRUCT *cnfg);
|
||||||
void apply_phy_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *phy_cnfg, bool apply_defaults);
|
void apply_phy_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *phy_cnfg, bool apply_defaults);
|
||||||
void apply_mac_config_dedicated(LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT *mac_cfg, bool apply_defaults);
|
void apply_mac_config_dedicated(LIBLTE_RRC_MAC_MAIN_CONFIG_STRUCT *mac_cfg, bool apply_defaults);
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
|
|
||||||
namespace srsue {
|
namespace srsue {
|
||||||
|
|
||||||
demux::demux() : mac_msg(20), pending_mac_msg(20), rlc(NULL)
|
demux::demux() : mac_msg(20), mch_mac_msg(20), pending_mac_msg(20), rlc(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,6 +47,7 @@ void demux::init(phy_interface_mac_common* phy_h_, rlc_interface_mac *rlc_, srsl
|
||||||
rlc = rlc_;
|
rlc = rlc_;
|
||||||
time_alignment_timer = time_alignment_timer_;
|
time_alignment_timer = time_alignment_timer_;
|
||||||
pdus.init(this, log_h);
|
pdus.init(this, log_h);
|
||||||
|
bzero(&mch_lcids, SRSLTE_N_MCH_LCIDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void demux::set_uecrid_callback(bool (*callback)(void*,uint64_t), void *arg) {
|
void demux::set_uecrid_callback(bool (*callback)(void*,uint64_t), void *arg) {
|
||||||
|
@ -129,7 +130,10 @@ void demux::push_pdu_bcch(uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void demux::push_pdu_mch(uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp) {
|
void demux::push_pdu_mch(uint8_t *buff, uint32_t nof_bytes, uint32_t tstamp) {
|
||||||
pdus.push(buff, nof_bytes, srslte::pdu_queue::MCH, tstamp);
|
uint8_t *mch_buffer_ptr = request_buffer(nof_bytes);
|
||||||
|
memcpy(mch_buffer_ptr, buff, nof_bytes);
|
||||||
|
pdus.push(mch_buffer_ptr, nof_bytes, srslte::pdu_queue::MCH, tstamp);
|
||||||
|
mch_buffer_ptr = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool demux::process_pdus()
|
bool demux::process_pdus()
|
||||||
|
@ -145,16 +149,17 @@ void demux::process_pdu(uint8_t *mac_pdu, uint32_t nof_bytes, srslte::pdu_queue:
|
||||||
// Unpack DLSCH MAC PDU
|
// Unpack DLSCH MAC PDU
|
||||||
mac_msg.init_rx(nof_bytes);
|
mac_msg.init_rx(nof_bytes);
|
||||||
mac_msg.parse_packet(mac_pdu);
|
mac_msg.parse_packet(mac_pdu);
|
||||||
|
|
||||||
process_sch_pdu(&mac_msg);
|
process_sch_pdu(&mac_msg);
|
||||||
//srslte_vec_fprint_byte(stdout, mac_pdu, nof_bytes);
|
|
||||||
|
|
||||||
pdus.deallocate(mac_pdu);
|
pdus.deallocate(mac_pdu);
|
||||||
break;
|
break;
|
||||||
case srslte::pdu_queue::BCH:
|
case srslte::pdu_queue::BCH:
|
||||||
rlc->write_pdu_bcch_dlsch(mac_pdu, nof_bytes);
|
rlc->write_pdu_bcch_dlsch(mac_pdu, nof_bytes);
|
||||||
break;
|
break;
|
||||||
case srslte::pdu_queue::MCH:
|
case srslte::pdu_queue::MCH:
|
||||||
|
mch_mac_msg.init_rx(nof_bytes);
|
||||||
|
mch_mac_msg.parse_packet(mac_pdu);
|
||||||
|
deallocate(mac_pdu);
|
||||||
|
process_mch_pdu(&mch_mac_msg);
|
||||||
// Process downlink MCH
|
// Process downlink MCH
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -168,7 +173,7 @@ void demux::process_sch_pdu(srslte::sch_pdu *pdu_msg)
|
||||||
if (pdu_msg->get()->get_sdu_lcid() == 0) {
|
if (pdu_msg->get()->get_sdu_lcid() == 0) {
|
||||||
uint8_t *x = pdu_msg->get()->get_sdu_ptr();
|
uint8_t *x = pdu_msg->get()->get_sdu_ptr();
|
||||||
uint32_t sum = 0;
|
uint32_t sum = 0;
|
||||||
for (int i=0;i<pdu_msg->get()->get_payload_size();i++) {
|
for (uint32_t i=0;i<pdu_msg->get()->get_payload_size();i++) {
|
||||||
sum += x[i];
|
sum += x[i];
|
||||||
}
|
}
|
||||||
if (sum == 0) {
|
if (sum == 0) {
|
||||||
|
@ -196,6 +201,42 @@ void demux::process_sch_pdu(srslte::sch_pdu *pdu_msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void demux::process_mch_pdu(srslte::mch_pdu *mch_msg){
|
||||||
|
|
||||||
|
//disgarding headers that have already been processed
|
||||||
|
//printf("in process cur idx, %d subheaders %d\n",mch_msg->cur_idx,mch_msg->nof_subheaders);
|
||||||
|
while(mch_msg->next()){
|
||||||
|
|
||||||
|
if(srslte::mch_subh::MCH_SCHED_INFO == mch_msg->get()->ce_type()){
|
||||||
|
uint16_t stop;
|
||||||
|
uint8_t lcid;
|
||||||
|
if(mch_msg->get()->get_next_mch_sched_info(&lcid, &stop)) {
|
||||||
|
Info("MCH Sched Info: LCID: %d, Stop: %d, tti is %d \n", lcid, stop, phy_h->get_current_tti());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(mch_msg->get()->is_sdu()) {
|
||||||
|
uint32_t lcid = mch_msg->get()->get_sdu_lcid();
|
||||||
|
if(lcid < 0 || lcid >= SRSLTE_N_MCH_LCIDS) {
|
||||||
|
Error("Radio bearer id must be in [0:%d] - %d\n", SRSLTE_N_MCH_LCIDS, lcid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Info("Wrote MCH LCID=%d to RLC\n", lcid);
|
||||||
|
if(1 == mch_lcids[lcid]) {
|
||||||
|
rlc->write_pdu_mch(lcid, mch_msg->get()->get_sdu_ptr(), mch_msg->get()->get_payload_size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void demux::mch_start_rx(uint32_t lcid)
|
||||||
|
{
|
||||||
|
if(lcid>=0 && lcid<32) {
|
||||||
|
Info("MCH Channel Setup: LCID=%d\n", lcid);
|
||||||
|
mch_lcids[lcid] = 1;
|
||||||
|
} else {
|
||||||
|
Warning("MCH Channel Setup: invalid LCID=%d\n", lcid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool demux::process_ce(srslte::sch_subh *subh) {
|
bool demux::process_ce(srslte::sch_subh *subh) {
|
||||||
switch(subh->ce_type()) {
|
switch(subh->ce_type()) {
|
||||||
|
|
|
@ -43,7 +43,8 @@ namespace srsue {
|
||||||
|
|
||||||
mac::mac() : timers(64),
|
mac::mac() : timers(64),
|
||||||
mux_unit(MAC_NOF_HARQ_PROC),
|
mux_unit(MAC_NOF_HARQ_PROC),
|
||||||
pdu_process_thread(&demux_unit)
|
pdu_process_thread(&demux_unit),
|
||||||
|
mch_msg(10)
|
||||||
{
|
{
|
||||||
pcap = NULL;
|
pcap = NULL;
|
||||||
bzero(&metrics, sizeof(mac_metrics_t));
|
bzero(&metrics, sizeof(mac_metrics_t));
|
||||||
|
@ -58,6 +59,7 @@ bool mac::init(phy_interface_mac *phy, rlc_interface_mac *rlc, rrc_interface_mac
|
||||||
tti = 0;
|
tti = 0;
|
||||||
|
|
||||||
srslte_softbuffer_rx_init(&pch_softbuffer, 100);
|
srslte_softbuffer_rx_init(&pch_softbuffer, 100);
|
||||||
|
srslte_softbuffer_rx_init(&mch_softbuffer, 100);
|
||||||
|
|
||||||
timer_alignment = timers.get_unique_id();
|
timer_alignment = timers.get_unique_id();
|
||||||
contention_resolution_timer = timers.get_unique_id();
|
contention_resolution_timer = timers.get_unique_id();
|
||||||
|
@ -220,6 +222,32 @@ void mac::pch_decoded_ok(uint32_t len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mac::mch_decoded_ok(uint32_t len)
|
||||||
|
{
|
||||||
|
// Parse MAC header
|
||||||
|
mch_msg.init_rx(len);
|
||||||
|
|
||||||
|
mch_msg.parse_packet(mch_payload_buffer);
|
||||||
|
while(mch_msg.next()) {
|
||||||
|
for(uint32_t i = 0; i < phy_mbsfn_cfg.nof_mbsfn_services;i++) {
|
||||||
|
if(srslte::mch_subh::MCH_SCHED_INFO == mch_msg.get()->ce_type()) {
|
||||||
|
uint16_t stop;
|
||||||
|
uint8_t lcid;
|
||||||
|
if(mch_msg.get()->get_next_mch_sched_info(&lcid, &stop)) {
|
||||||
|
phy_h->set_mch_period_stop(stop);
|
||||||
|
Info("MCH Sched Info: LCID: %d, Stop: %d, tti is %d \n", lcid, stop, phy_h->get_current_tti());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
demux_unit.push_pdu_mch(mch_payload_buffer, len, 0);
|
||||||
|
pdu_process_thread.notify();
|
||||||
|
if (pcap) {
|
||||||
|
pcap->write_dl_mch(mch_payload_buffer, len, true, phy_h->get_current_tti());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void mac::tb_decoded(bool ack, uint32_t tb_idx, srslte_rnti_type_t rnti_type, uint32_t harq_pid)
|
void mac::tb_decoded(bool ack, uint32_t tb_idx, srslte_rnti_type_t rnti_type, uint32_t harq_pid)
|
||||||
{
|
{
|
||||||
if (rnti_type == SRSLTE_RNTI_RAR) {
|
if (rnti_type == SRSLTE_RNTI_RAR) {
|
||||||
|
@ -303,6 +331,16 @@ void mac::new_grant_ul_ack(mac_interface_phy::mac_grant_t grant, bool ack, mac_i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mac::new_mch_dl(srslte_ra_dl_grant_t phy_grant, tb_action_dl_t *action)
|
||||||
|
{
|
||||||
|
memcpy(&action->phy_grant, &phy_grant, sizeof(srslte_phy_grant_t));
|
||||||
|
action->generate_ack = false;
|
||||||
|
action->decode_enabled[0] = true;
|
||||||
|
srslte_softbuffer_rx_reset_cb(&mch_softbuffer, 1);
|
||||||
|
action->payload_ptr[0] = mch_payload_buffer;
|
||||||
|
action->softbuffers[0] = &mch_softbuffer;
|
||||||
|
}
|
||||||
|
|
||||||
void mac::harq_recv(uint32_t tti, bool ack, mac_interface_phy::tb_action_ul_t* action)
|
void mac::harq_recv(uint32_t tti, bool ack, mac_interface_phy::tb_action_ul_t* action)
|
||||||
{
|
{
|
||||||
int tbs = ul_harq.get_current_tbs(tti);
|
int tbs = ul_harq.get_current_tbs(tti);
|
||||||
|
@ -378,6 +416,13 @@ void mac::get_config(mac_cfg_t* mac_cfg)
|
||||||
memcpy(mac_cfg, &config, sizeof(mac_cfg_t));
|
memcpy(mac_cfg, &config, sizeof(mac_cfg_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mac::set_mbsfn_config(uint32_t nof_mbsfn_services)
|
||||||
|
{
|
||||||
|
//cfg->nof_mbsfn_services = config.mbsfn.mcch.pmch_infolist_r9[0].mbms_sessioninfolist_r9_size;
|
||||||
|
phy_mbsfn_cfg.nof_mbsfn_services = nof_mbsfn_services;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void mac::set_config(mac_cfg_t* mac_cfg)
|
void mac::set_config(mac_cfg_t* mac_cfg)
|
||||||
{
|
{
|
||||||
memcpy(&config, mac_cfg, sizeof(mac_cfg_t));
|
memcpy(&config, mac_cfg, sizeof(mac_cfg_t));
|
||||||
|
@ -410,6 +455,11 @@ void mac::setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority, int PBR_x_t
|
||||||
bsr_procedure.set_priority(lcid, priority);
|
bsr_procedure.set_priority(lcid, priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mac::mch_start_rx(uint32_t lcid)
|
||||||
|
{
|
||||||
|
demux_unit.mch_start_rx(lcid);
|
||||||
|
}
|
||||||
|
|
||||||
void mac::get_metrics(mac_metrics_t &m)
|
void mac::get_metrics(mac_metrics_t &m)
|
||||||
{
|
{
|
||||||
Info("DL retx: %.2f \%%, perpkt: %.2f, UL retx: %.2f \%% perpkt: %.2f\n",
|
Info("DL retx: %.2f \%%, perpkt: %.2f, UL retx: %.2f \%% perpkt: %.2f\n",
|
||||||
|
|
|
@ -408,6 +408,9 @@ static int sigcnt = 0;
|
||||||
static bool running = true;
|
static bool running = true;
|
||||||
static bool do_metrics = false;
|
static bool do_metrics = false;
|
||||||
metrics_stdout metrics_screen;
|
metrics_stdout metrics_screen;
|
||||||
|
static bool show_mbms = false;
|
||||||
|
static bool mbms_service_start = false;
|
||||||
|
uint32_t serv, port;
|
||||||
|
|
||||||
void sig_int_handler(int signo) {
|
void sig_int_handler(int signo) {
|
||||||
sigcnt++;
|
sigcnt++;
|
||||||
|
@ -419,14 +422,14 @@ void sig_int_handler(int signo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void *input_loop(void *m) {
|
void *input_loop(void *m) {
|
||||||
char key;
|
string key;
|
||||||
while (running) {
|
while (running) {
|
||||||
cin >> key;
|
getline(cin, key);
|
||||||
if (cin.eof() || cin.bad()) {
|
if (cin.eof() || cin.bad()) {
|
||||||
cout << "Closing stdin thread." << endl;
|
cout << "Closing stdin thread." << endl;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
if ('t' == key) {
|
if (0 == key.compare("t")) {
|
||||||
do_metrics = !do_metrics;
|
do_metrics = !do_metrics;
|
||||||
if (do_metrics) {
|
if (do_metrics) {
|
||||||
cout << "Enter t to stop trace." << endl;
|
cout << "Enter t to stop trace." << endl;
|
||||||
|
@ -435,10 +438,31 @@ void *input_loop(void *m) {
|
||||||
}
|
}
|
||||||
metrics_screen.toggle_print(do_metrics);
|
metrics_screen.toggle_print(do_metrics);
|
||||||
} else
|
} else
|
||||||
if ('q' == key) {
|
if (0 == key.compare("q")) {
|
||||||
running = false;
|
running = false;
|
||||||
|
}
|
||||||
|
else if (0 == key.compare("mbms")) {
|
||||||
|
show_mbms = true;
|
||||||
|
} else if (key.find("mbms_service_start") != string::npos) {
|
||||||
|
|
||||||
|
char *dup = strdup(key.c_str());
|
||||||
|
strtok(dup, " ");
|
||||||
|
char *s = strtok(NULL, " ");
|
||||||
|
if(NULL == s) {
|
||||||
|
cout << "Usage: mbms_service_start <service_id> <port_number>" << endl;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
serv = atoi(s);
|
||||||
|
char* p = strtok(NULL, " ");
|
||||||
|
if(NULL == p) {
|
||||||
|
cout << "Usage: mbms_service_start <service_id> <port_number>" << endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
port = atoi(p);
|
||||||
|
mbms_service_start = true;
|
||||||
|
free(dup);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -493,14 +517,26 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
int cnt=0;
|
int cnt=0;
|
||||||
while (running) {
|
while (running) {
|
||||||
|
if(mbms_service_start) {
|
||||||
|
mbms_service_start = false;
|
||||||
|
ue->mbms_service_start(serv, port);
|
||||||
|
}
|
||||||
|
if(show_mbms) {
|
||||||
|
show_mbms = false;
|
||||||
|
ue->print_mbms();
|
||||||
|
}
|
||||||
|
sleep(1);
|
||||||
if (args.expert.print_buffer_state) {
|
if (args.expert.print_buffer_state) {
|
||||||
cnt++;
|
cnt++;
|
||||||
if (cnt==10) {
|
if (cnt==10) {
|
||||||
cnt=0;
|
cnt=0;
|
||||||
ue->print_pool();
|
ue->print_pool();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
while (!ue->attach() && running) {
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sleep(1);
|
|
||||||
}
|
}
|
||||||
pthread_cancel(input);
|
pthread_cancel(input);
|
||||||
metricshub.stop();
|
metricshub.stop();
|
||||||
|
|
|
@ -202,9 +202,8 @@ bool ue::init(all_args_t *args_)
|
||||||
gw.init(&pdcp, &nas, &gw_log, 3 /* RB_ID_DRB1 */);
|
gw.init(&pdcp, &nas, &gw_log, 3 /* RB_ID_DRB1 */);
|
||||||
|
|
||||||
gw.set_netmask(args->expert.ip_netmask);
|
gw.set_netmask(args->expert.ip_netmask);
|
||||||
|
|
||||||
rrc.init(&phy, &mac, &rlc, &pdcp, &nas, &usim, &mac, &rrc_log);
|
rrc.init(&phy, &mac, &rlc, &pdcp, &nas, &usim, &gw, &mac, &rrc_log);
|
||||||
|
|
||||||
// Get current band from provided EARFCN
|
// Get current band from provided EARFCN
|
||||||
args->rrc.supported_bands[0] = srslte_band_get_band(args->rf.dl_earfcn);
|
args->rrc.supported_bands[0] = srslte_band_get_band(args->rf.dl_earfcn);
|
||||||
args->rrc.nof_supported_bands = 1;
|
args->rrc.nof_supported_bands = 1;
|
||||||
|
@ -315,9 +314,19 @@ bool ue::get_metrics(ue_metrics_t &m)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ue::radio_overflow() {
|
void ue::radio_overflow() {
|
||||||
phy.radio_overflow();
|
phy.radio_overflow();
|
||||||
}
|
}
|
||||||
|
void ue::print_mbms()
|
||||||
|
{
|
||||||
|
rrc.print_mbms();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ue::mbms_service_start(uint32_t serv, uint32_t port)
|
||||||
|
{
|
||||||
|
rrc.mbms_service_start(serv, port);
|
||||||
|
}
|
||||||
|
|
||||||
void ue::rf_msg(srslte_rf_error_t error)
|
void ue::rf_msg(srslte_rf_error_t error)
|
||||||
{
|
{
|
||||||
|
|
|
@ -59,6 +59,19 @@ void gw::init(pdcp_interface_gw *pdcp_, nas_interface_gw *nas_, srslte::log *gw_
|
||||||
gettimeofday(&metrics_time[1], NULL);
|
gettimeofday(&metrics_time[1], NULL);
|
||||||
dl_tput_bytes = 0;
|
dl_tput_bytes = 0;
|
||||||
ul_tput_bytes = 0;
|
ul_tput_bytes = 0;
|
||||||
|
// MBSFN
|
||||||
|
mbsfn_sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (mbsfn_sock_fd < 0) {
|
||||||
|
gw_log->error("Failed to create MBSFN sink socket\n");
|
||||||
|
}
|
||||||
|
if (fcntl(mbsfn_sock_fd, F_SETFL, O_NONBLOCK)) {
|
||||||
|
gw_log->error("Failed to set non-blocking MBSFN sink socket\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
mbsfn_sock_addr.sin_family = AF_INET;
|
||||||
|
mbsfn_sock_addr.sin_addr.s_addr =inet_addr("127.0.0.1");
|
||||||
|
|
||||||
|
bzero(mbsfn_ports, SRSLTE_N_MCH_LCIDS*sizeof(uint32_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
void gw::stop()
|
void gw::stop()
|
||||||
|
@ -83,14 +96,15 @@ void gw::stop()
|
||||||
|
|
||||||
current_ip_addr = 0;
|
current_ip_addr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: tear down TUN device?
|
// TODO: tear down TUN device?
|
||||||
}
|
}
|
||||||
|
if (mbsfn_sock_fd) {
|
||||||
|
close(mbsfn_sock_fd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void gw::get_metrics(gw_metrics_t &m)
|
void gw::get_metrics(gw_metrics_t &m)
|
||||||
{
|
{
|
||||||
|
|
||||||
gettimeofday(&metrics_time[2], NULL);
|
gettimeofday(&metrics_time[2], NULL);
|
||||||
get_time_interval(metrics_time);
|
get_time_interval(metrics_time);
|
||||||
double secs = (double) metrics_time[0].tv_sec+metrics_time[0].tv_usec*1e-6;
|
double secs = (double) metrics_time[0].tv_sec+metrics_time[0].tv_usec*1e-6;
|
||||||
|
@ -105,7 +119,8 @@ void gw::get_metrics(gw_metrics_t &m)
|
||||||
ul_tput_bytes = 0;
|
ul_tput_bytes = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gw::set_netmask(std::string netmask) {
|
void gw::set_netmask(std::string netmask)
|
||||||
|
{
|
||||||
default_netmask = false;
|
default_netmask = false;
|
||||||
this->netmask = netmask;
|
this->netmask = netmask;
|
||||||
}
|
}
|
||||||
|
@ -116,8 +131,7 @@ void gw::set_netmask(std::string netmask) {
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
void gw::write_pdu(uint32_t lcid, srslte::byte_buffer_t *pdu)
|
void gw::write_pdu(uint32_t lcid, srslte::byte_buffer_t *pdu)
|
||||||
{
|
{
|
||||||
gw_log->info_hex(pdu->msg, pdu->N_bytes, "RX PDU");
|
gw_log->info_hex(pdu->msg, pdu->N_bytes, "RX PDU. Stack latency: %ld us\n", pdu->get_latency_us());
|
||||||
gw_log->info("RX PDU. Stack latency: %ld us\n", pdu->get_latency_us());
|
|
||||||
dl_tput_bytes += pdu->N_bytes;
|
dl_tput_bytes += pdu->N_bytes;
|
||||||
if(!if_up)
|
if(!if_up)
|
||||||
{
|
{
|
||||||
|
@ -132,6 +146,48 @@ void gw::write_pdu(uint32_t lcid, srslte::byte_buffer_t *pdu)
|
||||||
pool->deallocate(pdu);
|
pool->deallocate(pdu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gw::write_pdu_mch(uint32_t lcid, srslte::byte_buffer_t *pdu)
|
||||||
|
{
|
||||||
|
if(pdu->N_bytes>2)
|
||||||
|
{
|
||||||
|
gw_log->info_hex(pdu->msg, pdu->N_bytes, "RX MCH PDU. Stack latency: %ld us\n", pdu->get_latency_us());
|
||||||
|
dl_tput_bytes += pdu->N_bytes;
|
||||||
|
|
||||||
|
//Hack to drop initial 2 bytes
|
||||||
|
pdu->msg +=2;
|
||||||
|
pdu->N_bytes-=2;
|
||||||
|
struct in_addr dst_addr;
|
||||||
|
memcpy(&dst_addr.s_addr, &pdu->msg[16],4);
|
||||||
|
gw_log->console("gw\n");
|
||||||
|
gw_log->console("Destination IP: %s\n",inet_ntoa(dst_addr));
|
||||||
|
srslte_vec_fprint_b(stdout,&pdu->msg[0], pdu->N_bytes);
|
||||||
|
if(!if_up)
|
||||||
|
{
|
||||||
|
gw_log->warning("TUN/TAP not up - dropping gw RX message\n");
|
||||||
|
}else{
|
||||||
|
int n = write(tun_fd, pdu->msg, pdu->N_bytes);
|
||||||
|
if(n > 0 && (pdu->N_bytes != (uint32_t)n))
|
||||||
|
{
|
||||||
|
gw_log->warning("DL TUN/TAP write failure\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
// Strip IP/UDP header
|
||||||
|
pdu->msg += 28;
|
||||||
|
pdu->N_bytes -= 28;
|
||||||
|
|
||||||
|
if(mbsfn_sock_fd) {
|
||||||
|
if(lcid > 0 && lcid < SRSLTE_N_MCH_LCIDS) {
|
||||||
|
mbsfn_sock_addr.sin_port = htons(mbsfn_ports[lcid]);
|
||||||
|
if(sendto(mbsfn_sock_fd, pdu->msg, pdu->N_bytes, MSG_EOR, (struct sockaddr*)&mbsfn_sock_addr, sizeof(struct sockaddr_in))<0) {
|
||||||
|
gw_log->error("Failed to send MCH PDU to port %d\n", mbsfn_ports[lcid]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
pool->deallocate(pdu);
|
||||||
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
NAS interface
|
NAS interface
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -234,6 +290,19 @@ srslte::error_t gw::init_if(char *err_str)
|
||||||
return(srslte::ERROR_NONE);
|
return(srslte::ERROR_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
RRC interface
|
||||||
|
*******************************************************************************/
|
||||||
|
void gw::add_mch_port(uint32_t lcid, uint32_t port)
|
||||||
|
{
|
||||||
|
if(lcid > 0 && lcid < SRSLTE_N_MCH_LCIDS) {
|
||||||
|
mbsfn_ports[lcid] = port;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/********************/
|
/********************/
|
||||||
/* GW Receive */
|
/* GW Receive */
|
||||||
/********************/
|
/********************/
|
||||||
|
|
|
@ -80,6 +80,63 @@ void rrc::liblte_rrc_log(char *str) {
|
||||||
printf("[ASN]: %s\n", str);
|
printf("[ASN]: %s\n", str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void rrc::print_mbms()
|
||||||
|
{
|
||||||
|
if(rrc_log) {
|
||||||
|
if(serving_cell->has_mcch) {
|
||||||
|
LIBLTE_RRC_MCCH_MSG_STRUCT msg;
|
||||||
|
memcpy(&msg, &serving_cell->mcch, sizeof(LIBLTE_RRC_MCCH_MSG_STRUCT));
|
||||||
|
std::stringstream ss;
|
||||||
|
for(uint32_t i=0;i<msg.pmch_infolist_r9_size; i++){
|
||||||
|
ss << "PMCH: " << i << std::endl;
|
||||||
|
LIBLTE_RRC_PMCH_INFO_R9_STRUCT *pmch = &msg.pmch_infolist_r9[i];
|
||||||
|
for(uint32_t j=0;j<pmch->mbms_sessioninfolist_r9_size; j++) {
|
||||||
|
LIBLTE_RRC_MBMS_SESSION_INFO_R9_STRUCT *sess = &pmch->mbms_sessioninfolist_r9[j];
|
||||||
|
ss << " Service ID: " << sess->tmgi_r9.serviceid_r9;
|
||||||
|
if(sess->sessionid_r9_present) {
|
||||||
|
ss << ", Session ID: " << (uint32_t)sess->sessionid_r9;
|
||||||
|
}
|
||||||
|
if(sess->tmgi_r9.plmn_id_explicit) {
|
||||||
|
std::string tmp;
|
||||||
|
if(mcc_to_string(sess->tmgi_r9.plmn_id_r9.mcc, &tmp)) {
|
||||||
|
ss << ", MCC: " << tmp;
|
||||||
|
}
|
||||||
|
if(mnc_to_string(sess->tmgi_r9.plmn_id_r9.mnc, &tmp)) {
|
||||||
|
ss << ", MNC: " << tmp;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ss << ", PLMN index: " << (uint32_t)sess->tmgi_r9.plmn_index_r9;
|
||||||
|
}
|
||||||
|
ss << ", LCID: " << (uint32_t)sess->logicalchannelid_r9;
|
||||||
|
ss << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//rrc_log->console(ss.str());
|
||||||
|
std::cout << ss.str();
|
||||||
|
} else {
|
||||||
|
rrc_log->console("MCCH not available for current cell\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rrc::mbms_service_start(uint32_t serv, uint32_t port)
|
||||||
|
{
|
||||||
|
rrc_log->console("MBMS service start requested. Service id:%d, port: %d\n", serv, port);
|
||||||
|
if(serving_cell->has_mcch) {
|
||||||
|
LIBLTE_RRC_MCCH_MSG_STRUCT msg;
|
||||||
|
memcpy(&msg, &serving_cell->mcch, sizeof(LIBLTE_RRC_MCCH_MSG_STRUCT));
|
||||||
|
for(uint32_t i=0;i<msg.pmch_infolist_r9_size; i++){
|
||||||
|
LIBLTE_RRC_PMCH_INFO_R9_STRUCT *pmch = &msg.pmch_infolist_r9[i];
|
||||||
|
for(uint32_t j=0;j<pmch->mbms_sessioninfolist_r9_size; j++) {
|
||||||
|
LIBLTE_RRC_MBMS_SESSION_INFO_R9_STRUCT *sess = &pmch->mbms_sessioninfolist_r9[j];
|
||||||
|
if(serv == sess->tmgi_r9.serviceid_r9) {
|
||||||
|
add_mrb(sess->logicalchannelid_r9, port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void rrc::init(phy_interface_rrc *phy_,
|
void rrc::init(phy_interface_rrc *phy_,
|
||||||
mac_interface_rrc *mac_,
|
mac_interface_rrc *mac_,
|
||||||
|
@ -87,6 +144,7 @@ void rrc::init(phy_interface_rrc *phy_,
|
||||||
pdcp_interface_rrc *pdcp_,
|
pdcp_interface_rrc *pdcp_,
|
||||||
nas_interface_rrc *nas_,
|
nas_interface_rrc *nas_,
|
||||||
usim_interface_rrc *usim_,
|
usim_interface_rrc *usim_,
|
||||||
|
gw_interface_rrc *gw_,
|
||||||
mac_interface_timers *mac_timers_,
|
mac_interface_timers *mac_timers_,
|
||||||
srslte::log *rrc_log_) {
|
srslte::log *rrc_log_) {
|
||||||
pool = byte_buffer_pool::get_instance();
|
pool = byte_buffer_pool::get_instance();
|
||||||
|
@ -96,6 +154,7 @@ void rrc::init(phy_interface_rrc *phy_,
|
||||||
pdcp = pdcp_;
|
pdcp = pdcp_;
|
||||||
nas = nas_;
|
nas = nas_;
|
||||||
usim = usim_;
|
usim = usim_;
|
||||||
|
gw = gw_;
|
||||||
rrc_log = rrc_log_;
|
rrc_log = rrc_log_;
|
||||||
|
|
||||||
// Use MAC timers
|
// Use MAC timers
|
||||||
|
@ -474,6 +533,7 @@ bool rrc::configure_serving_cell() {
|
||||||
rrc_log->error("Trying to configure Cell while not camping on it\n");
|
rrc_log->error("Trying to configure Cell while not camping on it\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
serving_cell->has_mcch = false;
|
||||||
// Apply configurations if already retrieved SIB2
|
// Apply configurations if already retrieved SIB2
|
||||||
if (serving_cell->has_sib2()) {
|
if (serving_cell->has_sib2()) {
|
||||||
apply_sib2_configs(serving_cell->sib2ptr());
|
apply_sib2_configs(serving_cell->sib2ptr());
|
||||||
|
@ -490,6 +550,9 @@ bool rrc::configure_serving_cell() {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rrc_log->info("Cell has SIB%d\n", i+1);
|
rrc_log->info("Cell has SIB%d\n", i+1);
|
||||||
|
if(i+1 == 13){
|
||||||
|
apply_sib13_configs(serving_cell->sib13ptr());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -1763,7 +1826,23 @@ void rrc::process_pcch(byte_buffer_t *pdu) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void rrc::write_pdu_mch(uint32_t lcid, srslte::byte_buffer_t *pdu)
|
||||||
|
{
|
||||||
|
if (pdu->N_bytes > 0 && pdu->N_bytes < SRSLTE_MAX_BUFFER_SIZE_BITS) {
|
||||||
|
rrc_log->info_hex(pdu->msg, pdu->N_bytes, "MCH message received %d bytes on lcid:%d\n", pdu->N_bytes, lcid);
|
||||||
|
rrc_log->info("MCH message Stack latency: %ld us\n", pdu->get_latency_us());
|
||||||
|
//TODO: handle MCCH notifications and update MCCH
|
||||||
|
if(0 == lcid && !serving_cell->has_mcch) {
|
||||||
|
srslte_bit_unpack_vector(pdu->msg, bit_buf.msg, pdu->N_bytes * 8);
|
||||||
|
bit_buf.N_bits = pdu->N_bytes * 8;
|
||||||
|
liblte_rrc_unpack_mcch_msg((LIBLTE_BIT_MSG_STRUCT *) &bit_buf, &serving_cell->mcch);
|
||||||
|
serving_cell->has_mcch = true;
|
||||||
|
phy->set_config_mbsfn_mcch(&serving_cell->mcch);
|
||||||
|
}
|
||||||
|
|
||||||
|
pool->deallocate(pdu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -2138,6 +2217,9 @@ void rrc::apply_sib2_configs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2) {
|
||||||
// for(uint8_t i=0;i<sib2->mbsfn_subfr_cnfg_list_size;i++) {
|
// for(uint8_t i=0;i<sib2->mbsfn_subfr_cnfg_list_size;i++) {
|
||||||
// memcpy(&cfg.mbsfn_subfr_cnfg_list[i], &sib2->mbsfn_subfr_cnfg_list[i], sizeof(LIBLTE_RRC_MBSFN_SUBFRAME_CONFIG_STRUCT));
|
// memcpy(&cfg.mbsfn_subfr_cnfg_list[i], &sib2->mbsfn_subfr_cnfg_list[i], sizeof(LIBLTE_RRC_MBSFN_SUBFRAME_CONFIG_STRUCT));
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// Set MBSFN configs
|
||||||
|
phy->set_config_mbsfn_sib2(sib2);
|
||||||
|
|
||||||
mac->set_config(&cfg);
|
mac->set_config(&cfg);
|
||||||
|
|
||||||
|
@ -2202,6 +2284,12 @@ void rrc::apply_sib2_configs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_2_STRUCT *sib2) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rrc::apply_sib13_configs(LIBLTE_RRC_SYS_INFO_BLOCK_TYPE_13_STRUCT *sib13)
|
||||||
|
{
|
||||||
|
phy->set_config_mbsfn_sib13(&serving_cell->sib13);
|
||||||
|
add_mrb(0, 0); // Add MRB0
|
||||||
|
}
|
||||||
|
|
||||||
// Go through all information elements and apply defaults (9.2.4) if not defined
|
// Go through all information elements and apply defaults (9.2.4) if not defined
|
||||||
void rrc::apply_phy_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *phy_cnfg, bool apply_defaults) {
|
void rrc::apply_phy_config_dedicated(LIBLTE_RRC_PHYSICAL_CONFIG_DEDICATED_STRUCT *phy_cnfg, bool apply_defaults) {
|
||||||
// Get current configuration
|
// Get current configuration
|
||||||
|
@ -2589,6 +2677,14 @@ void rrc::release_drb(uint8_t lcid) {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rrc::add_mrb(uint32_t lcid, uint32_t port)
|
||||||
|
{
|
||||||
|
gw->add_mch_port(lcid, port);
|
||||||
|
rlc->add_bearer_mrb(lcid);
|
||||||
|
mac->mch_start_rx(lcid);
|
||||||
|
rrc_log->info("Added MRB bearer for lcid:%d\n", lcid);
|
||||||
|
}
|
||||||
|
|
||||||
// PHY CONFIG DEDICATED Defaults (3GPP 36.331 v10 9.2.4)
|
// PHY CONFIG DEDICATED Defaults (3GPP 36.331 v10 9.2.4)
|
||||||
void rrc::set_phy_default_pucch_srs() {
|
void rrc::set_phy_default_pucch_srs() {
|
||||||
|
|
||||||
|
|
|
@ -418,6 +418,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_pdu_pcch(uint8_t *payload, uint32_t nof_bytes) {}
|
void write_pdu_pcch(uint8_t *payload, uint32_t nof_bytes) {}
|
||||||
|
void write_pdu_mch(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LIBLTE_BIT_MSG_STRUCT bit_msg;
|
LIBLTE_BIT_MSG_STRUCT bit_msg;
|
||||||
|
|
|
@ -74,6 +74,7 @@ public:
|
||||||
void write_pdu_bcch_bch(byte_buffer_t *pdu) {}
|
void write_pdu_bcch_bch(byte_buffer_t *pdu) {}
|
||||||
void write_pdu_bcch_dlsch(byte_buffer_t *pdu) {}
|
void write_pdu_bcch_dlsch(byte_buffer_t *pdu) {}
|
||||||
void write_pdu_pcch(byte_buffer_t *pdu) {}
|
void write_pdu_pcch(byte_buffer_t *pdu) {}
|
||||||
|
void write_pdu_mch(uint32_t lcid, srslte::byte_buffer_t *sdu) {}
|
||||||
std::string get_rb_name(uint32_t lcid) { return std::string("lcid"); }
|
std::string get_rb_name(uint32_t lcid) { return std::string("lcid"); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -123,6 +124,7 @@ class gw_dummy : public gw_interface_nas, public gw_interface_pdcp
|
||||||
{
|
{
|
||||||
error_t setup_if_addr(uint32_t ip_addr, char *err_str) { return ERROR_NONE; }
|
error_t setup_if_addr(uint32_t ip_addr, char *err_str) { return ERROR_NONE; }
|
||||||
void write_pdu(uint32_t lcid, byte_buffer_t *pdu) {}
|
void write_pdu(uint32_t lcid, byte_buffer_t *pdu) {}
|
||||||
|
void write_pdu_mch(uint32_t lcid, srslte::byte_buffer_t *sdu) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue