From 611255aa5f953597071240fa4e2e9041b1a0314a Mon Sep 17 00:00:00 2001 From: David Rupprecht Date: Fri, 10 Sep 2021 13:04:00 +0200 Subject: [PATCH] Added GTPU bind address as output parameter --- .../srsran/interfaces/enb_gtpu_interfaces.h | 1 + srsenb/hdr/stack/ngap/ngap_ue.h | 4 +- .../hdr/stack/ngap/ngap_ue_bearer_manager.h | 6 ++- srsenb/hdr/stack/upper/gtpu.h | 1 + srsenb/src/stack/ngap/ngap_ue.cc | 11 +++-- .../src/stack/ngap/ngap_ue_bearer_manager.cc | 43 +++++++++++++------ srsenb/src/stack/ngap/ngap_ue_proc.cc | 22 ++++++---- srsenb/src/stack/rrc/rrc.cc | 4 +- srsenb/src/stack/rrc/rrc_bearer_cfg.cc | 3 +- srsenb/src/stack/upper/gtpu.cc | 17 ++++++-- srsenb/test/common/dummy_classes.h | 8 +++- srsenb/test/upper/gtpu_test.cc | 13 +++--- 12 files changed, 90 insertions(+), 43 deletions(-) diff --git a/lib/include/srsran/interfaces/enb_gtpu_interfaces.h b/lib/include/srsran/interfaces/enb_gtpu_interfaces.h index bc6aebda0..b9ec2f364 100644 --- a/lib/include/srsran/interfaces/enb_gtpu_interfaces.h +++ b/lib/include/srsran/interfaces/enb_gtpu_interfaces.h @@ -49,6 +49,7 @@ public: uint32_t eps_bearer_id, uint32_t addr, uint32_t teid_out, + uint32_t& addr_in, const bearer_props* props = nullptr) = 0; virtual void set_tunnel_status(uint32_t teidin, bool dl_active) = 0; virtual void rem_bearer(uint16_t rnti, uint32_t eps_bearer_id) = 0; diff --git a/srsenb/hdr/stack/ngap/ngap_ue.h b/srsenb/hdr/stack/ngap/ngap_ue.h index 3cf651b91..77004fdc0 100644 --- a/srsenb/hdr/stack/ngap/ngap_ue.h +++ b/srsenb/hdr/stack/ngap/ngap_ue.h @@ -42,8 +42,8 @@ public: bool send_initial_ctxt_setup_failure(asn1::ngap_nr::cause_c cause); // TS 38.413 - Section 9.2.1.2 - PDU Session Resource Setup Response bool send_pdu_session_resource_setup_response(uint16_t pdu_session_id, - uint32_t teid_out, - asn1::bounded_bitstring<1, 160, true, true> transport_layer_address); + uint32_t teid_in, + asn1::bounded_bitstring<1, 160, true, true> addr_in); // TS 38.413 - Section 9.2.2.1 - Initial Context Setup Request bool handle_initial_ctxt_setup_request(const asn1::ngap_nr::init_context_setup_request_s& msg); // TS 38.413 - Section 9.2.2.5 - UE Context Release Command diff --git a/srsenb/hdr/stack/ngap/ngap_ue_bearer_manager.h b/srsenb/hdr/stack/ngap/ngap_ue_bearer_manager.h index 94031deae..ed4c3bdeb 100644 --- a/srsenb/hdr/stack/ngap/ngap_ue_bearer_manager.h +++ b/srsenb/hdr/stack/ngap/ngap_ue_bearer_manager.h @@ -32,7 +32,8 @@ public: struct gtpu_tunnel { uint32_t teid_out = 0; uint32_t teid_in = 0; - asn1::bounded_bitstring<1, 160, true, true> address; + asn1::bounded_bitstring<1, 160, true, true> address_out; + asn1::bounded_bitstring<1, 160, true, true> address_in; }; uint8_t id = 0; uint8_t lcid = 0; @@ -48,6 +49,9 @@ public: const asn1::ngap_nr::qos_flow_level_qos_params_s& qos, const asn1::bounded_bitstring<1, 160, true, true>& addr, uint32_t teid_out, + uint16_t& lcid, + asn1::bounded_bitstring<1, 160, true, true>& addr_in, + uint32_t& teid_in, asn1::ngap_nr::cause_c& cause); private: diff --git a/srsenb/hdr/stack/upper/gtpu.h b/srsenb/hdr/stack/upper/gtpu.h index eff0e747d..3fdb9e0a3 100644 --- a/srsenb/hdr/stack/upper/gtpu.h +++ b/srsenb/hdr/stack/upper/gtpu.h @@ -145,6 +145,7 @@ public: uint32_t eps_bearer_id, uint32_t addr, uint32_t teid_out, + uint32_t& addr_in, const bearer_props* props = nullptr) override; void set_tunnel_status(uint32_t teidin, bool dl_active) override; void rem_bearer(uint16_t rnti, uint32_t eps_bearer_id) override; diff --git a/srsenb/src/stack/ngap/ngap_ue.cc b/srsenb/src/stack/ngap/ngap_ue.cc index 01ee89c5e..5fc7f5e86 100644 --- a/srsenb/src/stack/ngap/ngap_ue.cc +++ b/srsenb/src/stack/ngap/ngap_ue.cc @@ -184,10 +184,9 @@ bool ngap::ue::send_initial_ctxt_setup_failure(cause_c cause) return true; } -bool ngap::ue::send_pdu_session_resource_setup_response( - uint16_t pdu_session_id, - uint32_t teid_out, - asn1::bounded_bitstring<1, 160, true, true> transport_layer_address) +bool ngap::ue::send_pdu_session_resource_setup_response(uint16_t pdu_session_id, + uint32_t teid_in, + asn1::bounded_bitstring<1, 160, true, true> addr_in) { if (not ngap_ptr->amf_connected) { logger.warning("AMF not connected"); @@ -207,8 +206,8 @@ bool ngap::ue::send_pdu_session_resource_setup_response( gtp_tunnel_s& gtp_tunnel = resp_transfer.dlqos_flow_per_tnl_info.uptransport_layer_info.set_gtp_tunnel(); - gtp_tunnel.gtp_teid.from_number(teid_out); - gtp_tunnel.transport_layer_address = transport_layer_address; + gtp_tunnel.gtp_teid.from_number(teid_in); + gtp_tunnel.transport_layer_address = addr_in; asn1::ngap_nr::associated_qos_flow_list_l qos_flow_list; asn1::ngap_nr::associated_qos_flow_item_s qos_flow_item; qos_flow_item.qos_flow_id = 1; diff --git a/srsenb/src/stack/ngap/ngap_ue_bearer_manager.cc b/srsenb/src/stack/ngap/ngap_ue_bearer_manager.cc index 040ff341d..19c71526f 100644 --- a/srsenb/src/stack/ngap/ngap_ue_bearer_manager.cc +++ b/srsenb/src/stack/ngap/ngap_ue_bearer_manager.cc @@ -23,25 +23,27 @@ ngap_ue_bearer_manager::~ngap_ue_bearer_manager(){}; int ngap_ue_bearer_manager::add_pdu_session(uint16_t rnti, uint8_t pdu_session_id, const asn1::ngap_nr::qos_flow_level_qos_params_s& qos, - const asn1::bounded_bitstring<1, 160, true, true>& addr, + const asn1::bounded_bitstring<1, 160, true, true>& addr_out, uint32_t teid_out, + uint16_t& lcid, + asn1::bounded_bitstring<1, 160, true, true>& addr_in, + uint32_t& teid_in, asn1::ngap_nr::cause_c& cause) { // RRC call for QoS parameter and lcid <-> ID mapping - int lcid = rrc->allocate_lcid(rnti); + lcid = rrc->allocate_lcid(rnti); // Only add session if gtpu was successful pdu_session_t::gtpu_tunnel tunnel; - if (addr.length() > 32) { + if (addr_out.length() > 32) { logger.error("Only addresses with length <= 32 (IPv4) are supported"); cause.set_radio_network().value = asn1::ngap_nr::cause_radio_network_opts::invalid_qos_combination; return SRSRAN_ERROR; } - // TODO long term remove lcid and just use pdu_session_id and rnti as id for GTP tunnel - - int rtn = add_gtpu_bearer(rnti, lcid, pdu_session_id, teid_out, addr, tunnel); + // TODO: remove lcid and just use pdu_session_id and rnti as id for GTP tunnel + int rtn = add_gtpu_bearer(rnti, lcid, pdu_session_id, teid_out, addr_out, tunnel); if (rtn != SRSRAN_SUCCESS) { logger.error("Adding PDU Session ID=%d to GTPU", pdu_session_id); return SRSRAN_ERROR; @@ -51,6 +53,11 @@ int ngap_ue_bearer_manager::add_pdu_session(uint16_t pdu_session_list[pdu_session_id].lcid = lcid; pdu_session_list[pdu_session_id].qos_params = qos; pdu_session_list[pdu_session_id].tunnels.push_back(tunnel); + + // return values + teid_in = tunnel.teid_in; + addr_in = tunnel.address_in; + return SRSRAN_SUCCESS; } @@ -58,25 +65,35 @@ int ngap_ue_bearer_manager::add_gtpu_bearer(uint16_t uint32_t lcid, uint32_t pdu_session_id, uint32_t teid_out, - asn1::bounded_bitstring<1, 160, true, true> address, + asn1::bounded_bitstring<1, 160, true, true> address_out, pdu_session_t::gtpu_tunnel& tunnel, const gtpu_interface_rrc::bearer_props* props) { // Initialize ERAB tunnel in GTPU right-away. DRBs are only created during RRC setup/reconf - srsran::expected rtn = gtpu->add_bearer(rnti, lcid, address.to_number(), teid_out, props); + uint32_t addr_in; + srsran::expected rtn = gtpu->add_bearer(rnti, lcid, address_out.to_number(), teid_out, addr_in, props); if (rtn.is_error()) { logger.error("Failed adding pdu_session_id=%d to GTPU", pdu_session_id); return SRSRAN_ERROR; } - tunnel.teid_out = teid_out; - tunnel.address = address; - tunnel.teid_in = rtn.value(); - logger.info("Added GTPU tunnel for rnti %x, lcid %d, pdu_session_id=%d, address %s", + tunnel.teid_out = teid_out; + tunnel.address_out = address_out; + + logger.info("Addr in %x", addr_in); + + tunnel.address_in.from_number(addr_in); + tunnel.teid_in = rtn.value(); + + logger.info("Added GTPU tunnel rnti 0x%04x, lcid %d, pdu_session_id=%d, teid_out %d, teid_in %d, address out 0x%x, " + "address in 0x%x", rnti, lcid, pdu_session_id, - address.to_string()); + tunnel.teid_out, + tunnel.teid_in, + tunnel.address_out.to_number(), + tunnel.address_in.to_number()); return SRSRAN_SUCCESS; } diff --git a/srsenb/src/stack/ngap/ngap_ue_proc.cc b/srsenb/src/stack/ngap/ngap_ue_proc.cc index bf9aeac2e..ad61f8c6c 100644 --- a/srsenb/src/stack/ngap/ngap_ue_proc.cc +++ b/srsenb/src/stack/ngap/ngap_ue_proc.cc @@ -128,9 +128,7 @@ proc_outcome_t ngap_ue_pdu_session_res_setup_proc::init(const asn1::ngap_nr::pdu asn1::ngap_nr::qos_flow_setup_request_item_s qos_flow_setup = pdu_ses_res_setup_req_trans.protocol_ies.qos_flow_setup_request_list.value[0]; srsran::const_span nas_pdu_dummy; - asn1::ngap_nr::cause_c cause; uint32_t teid_out = 0; - int lcid; teid_out |= pdu_ses_res_setup_req_trans.protocol_ies.ul_ngu_up_tnl_info.value.gtp_tunnel().gtp_teid[0] << 24u; teid_out |= pdu_ses_res_setup_req_trans.protocol_ies.ul_ngu_up_tnl_info.value.gtp_tunnel().gtp_teid[1] << 16u; @@ -138,6 +136,10 @@ proc_outcome_t ngap_ue_pdu_session_res_setup_proc::init(const asn1::ngap_nr::pdu teid_out |= pdu_ses_res_setup_req_trans.protocol_ies.ul_ngu_up_tnl_info.value.gtp_tunnel().gtp_teid[3]; // TODO: Check cause + asn1::ngap_nr::cause_c cause; + uint32_t teid_in; + uint16_t lcid; + asn1::bounded_bitstring<1, 160, true, true> addr_in; if (bearer_manager->add_pdu_session( ue_ctxt->rnti, @@ -145,21 +147,25 @@ proc_outcome_t ngap_ue_pdu_session_res_setup_proc::init(const asn1::ngap_nr::pdu qos_flow_setup.qos_flow_level_qos_params, pdu_ses_res_setup_req_trans.protocol_ies.ul_ngu_up_tnl_info.value.gtp_tunnel().transport_layer_address, teid_out, + lcid, + addr_in, + teid_in, cause) != SRSRAN_SUCCESS) { logger.warning("Failed to add pdu session\n"); return proc_outcome_t::error; } + logger.info("Added PDU Session with LCID %d, teid_out %d, teid_in %d, addr_in %s", + lcid, + teid_out, + teid_in, + addr_in.to_string()); + // QoS parameter mapping in config in LTE enb - // Transport Layer Address required by the procedure for the reponse - asn1::bounded_bitstring<1, 160, true, true> transport_layer_address; - transport_layer_address = - pdu_ses_res_setup_req_trans.protocol_ies.ul_ngu_up_tnl_info.value.gtp_tunnel().transport_layer_address; if (su_req.pdu_session_nas_pdu_present) { - lcid = rrc->allocate_lcid(ue_ctxt->rnti); if (rrc->establish_rrc_bearer(ue_ctxt->rnti, su_req.pdu_session_id, su_req.pdu_session_nas_pdu, lcid) == SRSRAN_SUCCESS) { - parent->send_pdu_session_resource_setup_response(su_req.pdu_session_id, teid_out, transport_layer_address); + parent->send_pdu_session_resource_setup_response(su_req.pdu_session_id, teid_in, addr_in); return proc_outcome_t::success; } } diff --git a/srsenb/src/stack/rrc/rrc.cc b/srsenb/src/stack/rrc/rrc.cc index 0097f8aca..a9eff4db2 100644 --- a/srsenb/src/stack/rrc/rrc.cc +++ b/srsenb/src/stack/rrc/rrc.cc @@ -237,12 +237,12 @@ int rrc::add_user(uint16_t rnti, const sched_interface::ue_cfg_t& sched_ue_cfg) if (rnti == SRSRAN_MRNTI) { for (auto& mbms_item : mcch.msg.c1().mbsfn_area_cfg_r9().pmch_info_list_r9[0].mbms_session_info_list_r9) { uint32_t lcid = mbms_item.lc_ch_id_r9; - + uint32_t addr_in; // adding UE object to MAC for MRNTI without scheduling configuration (broadcast not part of regular scheduling) mac->ue_cfg(SRSRAN_MRNTI, NULL); rlc->add_bearer_mrb(SRSRAN_MRNTI, lcid); pdcp->add_bearer(SRSRAN_MRNTI, lcid, srsran::make_drb_pdcp_config_t(1, false)); - gtpu->add_bearer(SRSRAN_MRNTI, lcid, 1, 1); + gtpu->add_bearer(SRSRAN_MRNTI, lcid, 1, 1, addr_in); } } return SRSRAN_SUCCESS; diff --git a/srsenb/src/stack/rrc/rrc_bearer_cfg.cc b/srsenb/src/stack/rrc/rrc_bearer_cfg.cc index 6870d22f0..59db1a763 100644 --- a/srsenb/src/stack/rrc/rrc_bearer_cfg.cc +++ b/srsenb/src/stack/rrc/rrc_bearer_cfg.cc @@ -385,9 +385,10 @@ srsran::expected bearer_cfg_handler::add_gtpu_bearer(uint32_t // Initialize ERAB tunnel in GTPU right-away. DRBs are only created during RRC setup/reconf erab_t& erab = it->second; erab_t::gtpu_tunnel bearer; + uint32_t addr_in; bearer.teid_out = teid_out; bearer.addr = addr; - srsran::expected teidin = gtpu->add_bearer(rnti, erab.id, addr, teid_out, props); + srsran::expected teidin = gtpu->add_bearer(rnti, erab.id, addr, teid_out, addr_in, props); if (teidin.is_error()) { logger->error("Adding erab_id=%d to GTPU", erab_id); return srsran::default_error_t(); diff --git a/srsenb/src/stack/upper/gtpu.cc b/srsenb/src/stack/upper/gtpu.cc index f2d42c808..658a4933e 100644 --- a/srsenb/src/stack/upper/gtpu.cc +++ b/srsenb/src/stack/upper/gtpu.cc @@ -476,11 +476,15 @@ void gtpu::send_pdu_to_tunnel(const gtpu_tunnel& tx_tun, srsran::unique_byte_buf } } -srsran::expected -gtpu::add_bearer(uint16_t rnti, uint32_t eps_bearer_id, uint32_t addr, uint32_t teid_out, const bearer_props* props) +srsran::expected gtpu::add_bearer(uint16_t rnti, + uint32_t eps_bearer_id, + uint32_t addr_out, + uint32_t teid_out, + uint32_t& addr_in, + const bearer_props* props) { // Allocate a TEID for the incoming tunnel - const gtpu_tunnel* new_tun = tunnels.add_tunnel(rnti, eps_bearer_id, teid_out, addr); + const gtpu_tunnel* new_tun = tunnels.add_tunnel(rnti, eps_bearer_id, teid_out, addr_out); if (new_tun == nullptr) { return default_error_t(); } @@ -504,6 +508,13 @@ gtpu::add_bearer(uint16_t rnti, uint32_t eps_bearer_id, uint32_t addr, uint32_t } } + // Return bind address for S1AP and NGAP setup + struct in_addr inaddr; + if ((inet_pton(AF_INET, gtp_bind_addr.c_str(), &inaddr)) < 1) { + logger.error("Invalid address or failure during conversion: %s\n", gtp_bind_addr.c_str()); + } + addr_in = ntohl(inaddr.s_addr); + return teid_in; } diff --git a/srsenb/test/common/dummy_classes.h b/srsenb/test/common/dummy_classes.h index e27f57dad..c3fb2598a 100644 --- a/srsenb/test/common/dummy_classes.h +++ b/srsenb/test/common/dummy_classes.h @@ -109,8 +109,12 @@ public: class gtpu_dummy : public srsenb::gtpu_interface_rrc { public: - srsran::expected - add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out, const bearer_props* props) override + srsran::expected add_bearer(uint16_t rnti, + uint32_t lcid, + uint32_t addr, + uint32_t teid_out, + uint32_t& addr_in, + const bearer_props* props) override { return 1; } diff --git a/srsenb/test/upper/gtpu_test.cc b/srsenb/test/upper/gtpu_test.cc index 4220de0a6..caa4fdfc8 100644 --- a/srsenb/test/upper/gtpu_test.cc +++ b/srsenb/test/upper/gtpu_test.cc @@ -244,10 +244,11 @@ int test_gtpu_direct_tunneling(tunnel_test_event event) senb_gtpu.init(gtpu_args, &senb_pdcp); gtpu_args.gtp_bind_addr = tenb_addr_str; tenb_gtpu.init(gtpu_args, &tenb_pdcp); - + uint32_t addr_in1; + uint32_t addr_in2; // create tunnels MME-SeNB and MME-TeNB - uint32_t senb_teid_in = senb_gtpu.add_bearer(rnti, drb1_bearer_id, sgw_addr, sgw_teidout1).value(); - uint32_t tenb_teid_in = tenb_gtpu.add_bearer(rnti2, drb1_bearer_id, sgw_addr, sgw_teidout2).value(); + uint32_t senb_teid_in = senb_gtpu.add_bearer(rnti, drb1_bearer_id, sgw_addr, sgw_teidout1, addr_in1).value(); + uint32_t tenb_teid_in = tenb_gtpu.add_bearer(rnti2, drb1_bearer_id, sgw_addr, sgw_teidout2, addr_in2).value(); // Buffer PDUs in SeNB PDCP for (size_t sn = 6; sn < 10; ++sn) { @@ -260,11 +261,13 @@ int test_gtpu_direct_tunneling(tunnel_test_event event) gtpu::bearer_props props; props.flush_before_teidin_present = true; props.flush_before_teidin = tenb_teid_in; - uint32_t dl_tenb_teid_in = tenb_gtpu.add_bearer(rnti2, drb1_bearer_id, senb_addr, 0, &props).value(); + uint32_t addr_in3; + uint32_t dl_tenb_teid_in = tenb_gtpu.add_bearer(rnti2, drb1_bearer_id, senb_addr, 0, addr_in3, &props).value(); props = {}; props.forward_from_teidin_present = true; props.forward_from_teidin = senb_teid_in; - senb_gtpu.add_bearer(rnti, drb1_bearer_id, tenb_addr, dl_tenb_teid_in, &props); + uint32_t addr_in4; + senb_gtpu.add_bearer(rnti, drb1_bearer_id, tenb_addr, dl_tenb_teid_in, addr_in4, &props); std::vector data_vec(10); std::iota(data_vec.begin(), data_vec.end(), 0);