diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index c1ee594dc..07fb695c9 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -78,7 +78,12 @@ public: class gw_interface_nas { public: - virtual int setup_if_addr(uint32_t lcid, uint8_t pdn_type, uint32_t ip_addr, uint8_t* ipv6_if_id, char* err_str) = 0; + virtual int setup_if_addr(uint32_t eps_bearer_id, + uint32_t lcid, + uint8_t pdn_type, + uint32_t ip_addr, + uint8_t* ipv6_if_id, + char* err_str) = 0; virtual int apply_traffic_flow_template(const uint8_t& eps_bearer_id, const uint8_t& lcid, const LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft) = 0; @@ -102,7 +107,8 @@ public: class gw_interface_rrc { public: - virtual void add_mch_port(uint32_t lcid, uint32_t port) = 0; + virtual void add_mch_port(uint32_t lcid, uint32_t port) = 0; + virtual int update_lcid(uint32_t eps_bearer_id, uint32_t new_lcid) = 0; }; // GW interface for PDCP diff --git a/srsenb/src/stack/gnb_stack_nr.cc b/srsenb/src/stack/gnb_stack_nr.cc index d98c7c31a..684655a1b 100644 --- a/srsenb/src/stack/gnb_stack_nr.cc +++ b/srsenb/src/stack/gnb_stack_nr.cc @@ -86,7 +86,8 @@ int gnb_stack_nr::init(const srsenb::stack_args_t& args_, const rrc_nr_cfg_t& rr m_gw->init(args.coreless.gw_args, logger, this); char* err_str = nullptr; - if (m_gw->setup_if_addr(args.coreless.drb_lcid, + if (m_gw->setup_if_addr(5, + args.coreless.drb_lcid, LIBLTE_MME_PDN_TYPE_IPV4, htonl(inet_addr(args.coreless.ip_addr.c_str())), nullptr, diff --git a/srsue/hdr/stack/upper/gw.h b/srsue/hdr/stack/upper/gw.h index 0d0f65d7e..4cbfc2542 100644 --- a/srsue/hdr/stack/upper/gw.h +++ b/srsue/hdr/stack/upper/gw.h @@ -51,7 +51,12 @@ public: void write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t pdu); // NAS interface - int setup_if_addr(uint32_t lcid, uint8_t pdn_type, uint32_t ip_addr, uint8_t* ipv6_if_addr, char* err_str); + int setup_if_addr(uint32_t eps_bearer_id, + uint32_t lcid, + uint8_t pdn_type, + uint32_t ip_addr, + uint8_t* ipv6_if_addr, + char* err_str); int apply_traffic_flow_template(const uint8_t& eps_bearer_id, const uint8_t& lcid, const LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft); @@ -59,6 +64,7 @@ public: // RRC interface void add_mch_port(uint32_t lcid, uint32_t port); + int update_lcid(uint32_t eps_bearer_id, uint32_t new_lcid); private: static const int GW_THREAD_PRIO = -1; @@ -79,6 +85,8 @@ private: uint32_t default_lcid = 0; srslog::basic_logger& logger; + + std::map eps_lcid; // Mapping between eps bearer ID and LCID uint32_t current_ip_addr = 0; uint8_t current_if_id[8]; diff --git a/srsue/src/stack/rrc/rrc_nr.cc b/srsue/src/stack/rrc/rrc_nr.cc index be1e3c13a..0667da500 100644 --- a/srsue/src/stack/rrc/rrc_nr.cc +++ b/srsue/src/stack/rrc/rrc_nr.cc @@ -604,8 +604,8 @@ bool rrc_nr::apply_drb_add_mod(const drb_to_add_mod_s& drb_cfg) log_h->error("CN associtaion type not supported %s ", drb_cfg.cn_assoc.type().to_string().c_str()); return false; } - - drb_eps_bearer_id[drb_cfg.drb_id] = drb_cfg.cn_assoc.eps_bearer_id(); + uint32_t eps_bearer_id = drb_cfg.cn_assoc.eps_bearer_id(); + drb_eps_bearer_id[drb_cfg.drb_id] = eps_bearer_id; if (drb_cfg.pdcp_cfg.drb.pdcp_sn_size_dl_present && drb_cfg.pdcp_cfg.drb.pdcp_sn_size_ul_present && (drb_cfg.pdcp_cfg.drb.pdcp_sn_size_ul.to_number() != drb_cfg.pdcp_cfg.drb.pdcp_sn_size_dl.to_number())) { @@ -615,7 +615,7 @@ bool rrc_nr::apply_drb_add_mod(const drb_to_add_mod_s& drb_cfg) srslte::pdcp_config_t pdcp_cfg = make_drb_pdcp_config_t(drb_cfg.drb_id, true, drb_cfg.pdcp_cfg); pdcp->add_bearer(lcid, pdcp_cfg); - + gw->update_lcid(eps_bearer_id, lcid); return true; } diff --git a/srsue/src/stack/ue_stack_nr.cc b/srsue/src/stack/ue_stack_nr.cc index 80381b9c2..8f8e57fbf 100644 --- a/srsue/src/stack/ue_stack_nr.cc +++ b/srsue/src/stack/ue_stack_nr.cc @@ -109,7 +109,7 @@ bool ue_stack_nr::switch_on() { // statically setup TUN (will be done through RRC later) char* err_str = nullptr; - if (gw->setup_if_addr(4, LIBLTE_MME_PDN_TYPE_IPV4, htonl(inet_addr("192.168.1.3")), nullptr, err_str)) { + if (gw->setup_if_addr(5, 4, LIBLTE_MME_PDN_TYPE_IPV4, htonl(inet_addr("192.168.1.3")), nullptr, err_str)) { printf("Error configuring TUN interface\n"); } return true; diff --git a/srsue/src/stack/upper/gw.cc b/srsue/src/stack/upper/gw.cc index 29ca5c2bd..23b9c4ca1 100644 --- a/srsue/src/stack/upper/gw.cc +++ b/srsue/src/stack/upper/gw.cc @@ -167,7 +167,12 @@ void gw::write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t pdu) /******************************************************************************* NAS interface *******************************************************************************/ -int gw::setup_if_addr(uint32_t lcid, uint8_t pdn_type, uint32_t ip_addr, uint8_t* ipv6_if_addr, char* err_str) +int gw::setup_if_addr(uint32_t eps_bearer_id, + uint32_t lcid, + uint8_t pdn_type, + uint32_t ip_addr, + uint8_t* ipv6_if_addr, + char* err_str) { int err; if (pdn_type == LIBLTE_MME_PDN_TYPE_IPV4 || pdn_type == LIBLTE_MME_PDN_TYPE_IPV4V6) { @@ -183,6 +188,7 @@ int gw::setup_if_addr(uint32_t lcid, uint8_t pdn_type, uint32_t ip_addr, uint8_t } } + eps_lcid[eps_bearer_id] = lcid; default_lcid = lcid; tft_matcher.set_default_lcid(lcid); @@ -191,6 +197,26 @@ int gw::setup_if_addr(uint32_t lcid, uint8_t pdn_type, uint32_t ip_addr, uint8_t return SRSLTE_SUCCESS; } +int gw::update_lcid(uint32_t eps_bearer_id, uint32_t new_lcid) +{ + auto it = eps_lcid.find(eps_bearer_id); + if (it != eps_lcid.end()) { + uint32_t old_lcid = eps_lcid[eps_bearer_id]; + logger.debug("Found EPS bearer %d. Update old lcid %d to new lcid %d", eps_bearer_id, old_lcid, new_lcid); + eps_lcid[eps_bearer_id] = new_lcid; + if (old_lcid == default_lcid) { + logger.debug("Defaulting new lcid %d", new_lcid); + default_lcid = new_lcid; + tft_matcher.set_default_lcid(new_lcid); + } + // TODO: update need filters if not the default lcid + } else { + logger.error("Did not found EPS bearer %d for updating LCID.", eps_bearer_id); + return SRSLTE_ERROR; + } + return SRSLTE_SUCCESS; +} + int gw::apply_traffic_flow_template(const uint8_t& erab_id, const uint8_t& lcid, const LIBLTE_MME_TRAFFIC_FLOW_TEMPLATE_STRUCT* tft) diff --git a/srsue/src/stack/upper/nas.cc b/srsue/src/stack/upper/nas.cc index 05fa67c5b..c944c4f35 100644 --- a/srsue/src/stack/upper/nas.cc +++ b/srsue/src/stack/upper/nas.cc @@ -1031,7 +1031,8 @@ void nas::parse_attach_accept(uint32_t lcid, unique_byte_buffer_t pdu) // Setup GW char* err_str = nullptr; - if (gw->setup_if_addr(rrc->get_lcid_for_eps_bearer(act_def_eps_bearer_context_req.eps_bearer_id), + if (gw->setup_if_addr(act_def_eps_bearer_context_req.eps_bearer_id, + rrc->get_lcid_for_eps_bearer(act_def_eps_bearer_context_req.eps_bearer_id), LIBLTE_MME_PDN_TYPE_IPV4, ip_addr, nullptr, @@ -1063,7 +1064,8 @@ void nas::parse_attach_accept(uint32_t lcid, unique_byte_buffer_t pdu) act_def_eps_bearer_context_req.pdn_addr.addr[7]); // Setup GW char* err_str = nullptr; - if (gw->setup_if_addr(rrc->get_lcid_for_eps_bearer(act_def_eps_bearer_context_req.eps_bearer_id), + if (gw->setup_if_addr(act_def_eps_bearer_context_req.eps_bearer_id, + rrc->get_lcid_for_eps_bearer(act_def_eps_bearer_context_req.eps_bearer_id), LIBLTE_MME_PDN_TYPE_IPV6, 0, ipv6_if_id, @@ -1113,7 +1115,8 @@ void nas::parse_attach_accept(uint32_t lcid, unique_byte_buffer_t pdu) act_def_eps_bearer_context_req.pdn_addr.addr[11]); char* err_str = nullptr; - if (gw->setup_if_addr(rrc->get_lcid_for_eps_bearer(act_def_eps_bearer_context_req.eps_bearer_id), + if (gw->setup_if_addr(act_def_eps_bearer_context_req.eps_bearer_id, + rrc->get_lcid_for_eps_bearer(act_def_eps_bearer_context_req.eps_bearer_id), LIBLTE_MME_PDN_TYPE_IPV4V6, ip_addr, ipv6_if_id, diff --git a/srsue/test/ttcn3/hdr/ttcn3_ue.h b/srsue/test/ttcn3/hdr/ttcn3_ue.h index 5565b42f6..e997e534a 100644 --- a/srsue/test/ttcn3/hdr/ttcn3_ue.h +++ b/srsue/test/ttcn3/hdr/ttcn3_ue.h @@ -51,7 +51,13 @@ public: void add_mch_port(uint32_t lcid, uint32_t port); void write_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu); void write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t pdu); - int setup_if_addr(uint32_t lcid, uint8_t pdn_type, uint32_t ip_addr, uint8_t* ipv6_if_id, char* err_str); + int setup_if_addr(uint32_t eps_bearer_id, + uint32_t lcid, + uint8_t pdn_type, + uint32_t ip_addr, + uint8_t* ipv6_if_id, + char* err_str); + int update_lcid(uint32_t eps_bearer_id, uint32_t new_lcid); int apply_traffic_flow_template(const uint8_t& eps_bearer_id, const uint8_t& lcid, diff --git a/srsue/test/ttcn3/src/ttcn3_ue.cc b/srsue/test/ttcn3/src/ttcn3_ue.cc index cd46c6923..a7f70b4aa 100644 --- a/srsue/test/ttcn3/src/ttcn3_ue.cc +++ b/srsue/test/ttcn3/src/ttcn3_ue.cc @@ -181,10 +181,19 @@ void ttcn3_ue::write_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu) } } void ttcn3_ue::write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t pdu) {} -int ttcn3_ue::setup_if_addr(uint32_t lcid, uint8_t pdn_type, uint32_t ip_addr, uint8_t* ipv6_if_id, char* err_str) +int ttcn3_ue::setup_if_addr(uint32_t eps_bearer_id, + uint32_t lcid, + uint8_t pdn_type, + uint32_t ip_addr, + uint8_t* ipv6_if_id, + char* err_str) { return 0; } +int ttcn3_ue::update_lcid(uint32_t eps_bearer_id, uint32_t new_lcid) +{ + return SRSLTE_SUCCESS; +} int ttcn3_ue::apply_traffic_flow_template(const uint8_t& eps_bearer_id, const uint8_t& lcid, diff --git a/srsue/test/upper/CMakeLists.txt b/srsue/test/upper/CMakeLists.txt index 04093a152..cd84fa988 100644 --- a/srsue/test/upper/CMakeLists.txt +++ b/srsue/test/upper/CMakeLists.txt @@ -31,6 +31,10 @@ add_executable(nas_test nas_test.cc) target_link_libraries(nas_test srsue_upper srslte_upper srslte_phy rrc_asn1) add_test(nas_test nas_test) +add_executable(gw_test gw_test.cc) +target_link_libraries(gw_test srsue_upper srslte_upper srslte_phy) +add_test(gw_test gw_test) + add_executable(tft_test tft_test.cc) target_link_libraries(tft_test srsue_upper srslte_upper srslte_phy) add_test(tft_test tft_test) diff --git a/srsue/test/upper/gw_test.cc b/srsue/test/upper/gw_test.cc new file mode 100644 index 000000000..573b46a23 --- /dev/null +++ b/srsue/test/upper/gw_test.cc @@ -0,0 +1,88 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "srslte/common/common.h" +#include "srslte/common/log.h" +#include "srslte/common/logger_srslog_wrapper.h" +#include "srslte/common/test_common.h" +#include "srslte/interfaces/ue_interfaces.h" +#include "srslte/srslog/srslog.h" +#include "srslte/srslte.h" +#include "srsue/hdr/stack/upper/gw.h" + +class test_stack_dummy : public srsue::stack_interface_gw +{ +public: + bool is_registered() { return true; } + bool start_service_request() { return true; }; + void write_sdu(uint32_t lcid, srslte::unique_byte_buffer_t sdu) { return; } + bool is_lcid_enabled(uint32_t lcid) { return true; } +}; + +int gw_change_lcid_test() +{ + + // Setup logging. + srslog::sink* log_sink = srslog::create_stdout_sink(); + if (!log_sink) { + return SRSLTE_ERROR; + } + + srslog::log_channel* chan = srslog::create_log_channel("main_channel", *log_sink); + if (!chan) { + return SRSLTE_ERROR; + } + + srslte::srslog_wrapper log_wrapper(*chan); + + srslte::log_filter log; + log.init("TEST ", &log_wrapper); + log.set_level("debug"); + log.set_hex_limit(10000); + + srslog::init(); + + srsue::gw_args_t gw_args; + gw_args.tun_dev_name = "tun1"; + gw_args.log.gw_level = "debug"; + gw_args.log.gw_hex_limit = 100000; + test_stack_dummy stack; + srsue::gw gw; + gw.init(gw_args, &log_wrapper, &stack); + + uint32_t eps_bearer_id = 5; + uint32_t non_existing_eps_bearer_id = 23; + uint32_t old_lcid = 3; + uint32_t new_lcid = 4; + char* err_str = nullptr; + int rtn = 0; + + rtn = gw.setup_if_addr( + eps_bearer_id, old_lcid, LIBLTE_MME_PDN_TYPE_IPV4, htonl(inet_addr("192.168.56.32")), nullptr, err_str); + + if (rtn != SRSLTE_SUCCESS) { + log.error("Failed to setup GW interface. Not possible to test function. Try to execute with sudo rights."); + gw.stop(); + return SRSLTE_SUCCESS; + } + + TESTASSERT(gw.update_lcid(eps_bearer_id, new_lcid) == SRSLTE_SUCCESS); + TESTASSERT(gw.update_lcid(non_existing_eps_bearer_id, new_lcid) == SRSLTE_ERROR); + gw.stop(); + return SRSLTE_SUCCESS; +} + +int main(int argc, char** argv) +{ + TESTASSERT(gw_change_lcid_test() == SRSLTE_SUCCESS); + return SRSLTE_SUCCESS; +} diff --git a/srsue/test/upper/nas_test.cc b/srsue/test/upper/nas_test.cc index 1753e4b16..d3d22d13a 100644 --- a/srsue/test/upper/nas_test.cc +++ b/srsue/test/upper/nas_test.cc @@ -176,7 +176,12 @@ public: class gw_dummy : public gw_interface_nas, public gw_interface_pdcp { - int setup_if_addr(uint32_t lcid, uint8_t pdn_type, uint32_t ip_addr, uint8_t* ipv6_if_id, char* err_str) + int setup_if_addr(uint32_t eps_bearer_id, + uint32_t lcid, + uint8_t pdn_type, + uint32_t ip_addr, + uint8_t* ipv6_if_id, + char* err_str) { return SRSLTE_SUCCESS; }