diff --git a/srsenb/hdr/stack/upper/pdcp_nr.h b/srsenb/hdr/stack/upper/pdcp_nr.h new file mode 100644 index 000000000..dd6a92ed7 --- /dev/null +++ b/srsenb/hdr/stack/upper/pdcp_nr.h @@ -0,0 +1,124 @@ +/* + * Copyright 2013-2020 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/. + * + */ + +#include "srslte/common/log.h" +#include "srslte/common/log_filter.h" +#include "srslte/common/logger.h" +#include "srslte/interfaces/gnb_interfaces.h" +#include "srslte/upper/pdcp.h" +#include + +#ifndef SRSENB_PDCP_NR_H +#define SRSENB_PDCP_NR_H + +namespace srsenb { + +struct pdcp_nr_args_t { + std::string log_level; + uint32_t log_hex_limit; +}; + +class pdcp_nr : public pdcp_interface_rlc_nr, public pdcp_interface_sdap_nr, public pdcp_interface_rrc_nr +{ +public: + explicit pdcp_nr(srslte::task_handler_interface* task_executor_, const char* logname); + virtual ~pdcp_nr() = default; + void init(const pdcp_nr_args_t& args_, + rlc_interface_pdcp_nr* rlc_, + rrc_interface_pdcp_nr* rrc_, + sdap_interface_pdcp_nr* gtpu_); + void stop(); + + // pdcp_interface_rlc_nr + void write_pdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu); + void write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t sdu) {} + + // pdcp_interface_rrc_nr + void reset(uint16_t rnti) final; + void add_user(uint16_t rnti) final; + void rem_user(uint16_t rnti) final; + void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu) final; + void add_bearer(uint16_t rnti, uint32_t lcid, srslte::pdcp_config_t cnfg) final; + void config_security(uint16_t rnti, uint32_t lcid, srslte::as_security_config_t sec_cfg) final; + void enable_integrity(uint16_t rnti, uint32_t lcid) final; + void enable_encryption(uint16_t rnti, uint32_t lcid) final; + +private: + class user_interface_rlc final : public srsue::rlc_interface_pdcp + { + public: + uint16_t rnti; + srsenb::rlc_interface_pdcp_nr* rlc; + // rlc_interface_pdcp_nr + void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking) final; + void discard_sdu(uint32_t lcid, uint32_t discard_sn) final; + bool rb_is_um(uint32_t lcid) final; + }; + + class user_interface_sdap : public srsue::gw_interface_pdcp + { + public: + uint16_t rnti; + srsenb::sdap_interface_pdcp_nr* sdap; + // gw_interface_pdcp + void write_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu) final; + void write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t sdu) final {} + }; + + class user_interface_rrc : public srsue::rrc_interface_pdcp + { + public: + uint16_t rnti; + srsenb::rrc_interface_pdcp_nr* rrc; + // rrc_interface_pdcp_nr + void write_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu) final; + void write_pdu_bcch_bch(srslte::unique_byte_buffer_t pdu) final; + void write_pdu_bcch_dlsch(srslte::unique_byte_buffer_t pdu) final; + void write_pdu_pcch(srslte::unique_byte_buffer_t pdu) final; + void write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t pdu) final {} + std::string get_rb_name(uint32_t lcid) final; + }; + + class user_interface + { + public: + user_interface_rlc rlc_itf; + user_interface_sdap sdap_itf; + user_interface_rrc rrc_itf; + std::unique_ptr pdcp; + }; + + // args + pdcp_nr_args_t m_args = {}; + srslte::byte_buffer_pool* pool = nullptr; + srslte::log_ref m_log; + rlc_interface_pdcp_nr* m_rlc = nullptr; + rrc_interface_pdcp_nr* m_rrc = nullptr; + sdap_interface_pdcp_nr* m_sdap = nullptr; + + std::map users; + + srslte::task_handler_interface* task_executor; +}; + +} // namespace srsenb + +#endif // SRSENB_PDCP_NR_H \ No newline at end of file diff --git a/srsenb/src/stack/upper/CMakeLists.txt b/srsenb/src/stack/upper/CMakeLists.txt index aa06a063b..0bbb6ce37 100644 --- a/srsenb/src/stack/upper/CMakeLists.txt +++ b/srsenb/src/stack/upper/CMakeLists.txt @@ -18,5 +18,11 @@ # and at http://www.gnu.org/licenses/. # -file(GLOB SOURCES "*.cc") -add_library(srsenb_upper STATIC ${SOURCES}) \ No newline at end of file +set(SOURCES gtpu.cc pdcp.cc rlc.cc s1ap.cc) +add_library(srsenb_upper STATIC ${SOURCES}) + +if (ENABLE_5GNR) +set(SOURCES pdcp_nr.cc) +add_library(srsgnb_upper STATIC ${SOURCES}) +endif (ENABLE_5GNR) + diff --git a/srsenb/src/stack/upper/pdcp_nr.cc b/srsenb/src/stack/upper/pdcp_nr.cc new file mode 100644 index 000000000..3846691ef --- /dev/null +++ b/srsenb/src/stack/upper/pdcp_nr.cc @@ -0,0 +1,165 @@ +/* + * Copyright 2013-2020 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/. + * + */ + +#include "srsenb/hdr/stack/upper/pdcp_nr.h" +#include "lib/include/srslte/interfaces/nr_common_interface_types.h" + +namespace srsenb { + +pdcp_nr::pdcp_nr(srslte::task_handler_interface* task_executor_, const char* logname) : + task_executor(task_executor_), + m_log(logname), + pool(srslte::byte_buffer_pool::get_instance()) +{} + +void pdcp_nr::init(const pdcp_nr_args_t& args_, + rlc_interface_pdcp_nr* rlc_, + rrc_interface_pdcp_nr* rrc_, + sdap_interface_pdcp_nr* sdap_) +{ + m_args = args_; + m_rlc = rlc_; + m_rrc = rrc_; + m_sdap = sdap_; +} + +void pdcp_nr::stop() +{ + for (auto& user : users) { + user.second.pdcp->stop(); + } + users.clear(); +} + +void pdcp_nr::add_user(uint16_t rnti) +{ + if (users.count(rnti) == 0) { + users[rnti].pdcp.reset(new srslte::pdcp(task_executor, "PDCP")); + users[rnti].rlc_itf.rnti = rnti; + users[rnti].sdap_itf.rnti = rnti; + users[rnti].rrc_itf.rnti = rnti; + users[rnti].rlc_itf.rlc = m_rlc; + users[rnti].rrc_itf.rrc = m_rrc; + users[rnti].sdap_itf.sdap = m_sdap; + users[rnti].pdcp->init(&users[rnti].rlc_itf, &users[rnti].rrc_itf, &users[rnti].sdap_itf); + } +} + +void pdcp_nr::rem_user(uint16_t rnti) +{ + users.erase(rnti); +} + +void pdcp_nr::add_bearer(uint16_t rnti, uint32_t lcid, srslte::pdcp_config_t cfg) +{ + if (users.count(rnti)) { + users[rnti].pdcp->add_bearer(lcid, cfg); + } +} + +void pdcp_nr::reset(uint16_t rnti) +{ + if (users.count(rnti)) { + users[rnti].pdcp->reset(); + } +} + +void pdcp_nr::config_security(uint16_t rnti, uint32_t lcid, srslte::as_security_config_t sec_cfg) +{ + if (users.count(rnti)) { + users[rnti].pdcp->config_security(lcid, sec_cfg); + } +} + +void pdcp_nr::enable_integrity(uint16_t rnti, uint32_t lcid) +{ + users[rnti].pdcp->enable_integrity(lcid, srslte::DIRECTION_TXRX); +} + +void pdcp_nr::enable_encryption(uint16_t rnti, uint32_t lcid) +{ + users[rnti].pdcp->enable_encryption(lcid, srslte::DIRECTION_TXRX); +} + +void pdcp_nr::write_pdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu) +{ + if (users.count(rnti)) { + users[rnti].pdcp->write_pdu(lcid, std::move(sdu)); + } else { + m_log->error("Can't write PDU. RNTI=0x%X doesn't exist.\n", rnti); + } +} + +void pdcp_nr::write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu) +{ + if (users.count(rnti)) { + users[rnti].pdcp->write_sdu(lcid, std::move(sdu), false); + } else { + m_log->error("Can't write SDU. RNTI=0x%X doesn't exist.\n", rnti); + } +} + +void pdcp_nr::user_interface_sdap::write_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu) +{ + sdap->write_pdu(rnti, lcid, std::move(pdu)); +} + +void pdcp_nr::user_interface_rlc::write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu, bool blocking) +{ + rlc->write_sdu(rnti, lcid, std::move(sdu)); +} + +void pdcp_nr::user_interface_rlc::discard_sdu(uint32_t lcid, uint32_t discard_sn) +{ + fprintf(stderr, "discard_sdu method not implemented.\n"); +} + +bool pdcp_nr::user_interface_rlc::rb_is_um(uint32_t lcid) +{ + return rlc->rb_is_um(rnti, lcid); +} + +void pdcp_nr::user_interface_rrc::write_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu) +{ + rrc->write_pdu(rnti, lcid, std::move(pdu)); +} + +void pdcp_nr::user_interface_rrc::write_pdu_bcch_bch(srslte::unique_byte_buffer_t pdu) +{ + ERROR("Error: Received BCCH from ue=%d\n", rnti); +} + +void pdcp_nr::user_interface_rrc::write_pdu_bcch_dlsch(srslte::unique_byte_buffer_t pdu) +{ + ERROR("Error: Received BCCH from ue=%d\n", rnti); +} + +void pdcp_nr::user_interface_rrc::write_pdu_pcch(srslte::unique_byte_buffer_t pdu) +{ + ERROR("Error: Received PCCH from ue=%d\n", rnti); +} + +std::string pdcp_nr::user_interface_rrc::get_rb_name(uint32_t lcid) +{ + return srslte::to_string(static_cast(lcid)); +} + +} // namespace srsenb \ No newline at end of file