Added GTPU bind address as output parameter

master
David Rupprecht 3 years ago committed by David Rupprecht
parent bd0e641633
commit 611255aa5f

@ -49,6 +49,7 @@ public:
uint32_t eps_bearer_id, uint32_t eps_bearer_id,
uint32_t addr, uint32_t addr,
uint32_t teid_out, uint32_t teid_out,
uint32_t& addr_in,
const bearer_props* props = nullptr) = 0; const bearer_props* props = nullptr) = 0;
virtual void set_tunnel_status(uint32_t teidin, bool dl_active) = 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; virtual void rem_bearer(uint16_t rnti, uint32_t eps_bearer_id) = 0;

@ -42,8 +42,8 @@ public:
bool send_initial_ctxt_setup_failure(asn1::ngap_nr::cause_c cause); 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 // 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, bool send_pdu_session_resource_setup_response(uint16_t pdu_session_id,
uint32_t teid_out, uint32_t teid_in,
asn1::bounded_bitstring<1, 160, true, true> transport_layer_address); asn1::bounded_bitstring<1, 160, true, true> addr_in);
// TS 38.413 - Section 9.2.2.1 - Initial Context Setup Request // 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); 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 // TS 38.413 - Section 9.2.2.5 - UE Context Release Command

@ -32,7 +32,8 @@ public:
struct gtpu_tunnel { struct gtpu_tunnel {
uint32_t teid_out = 0; uint32_t teid_out = 0;
uint32_t teid_in = 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 id = 0;
uint8_t lcid = 0; uint8_t lcid = 0;
@ -48,6 +49,9 @@ public:
const asn1::ngap_nr::qos_flow_level_qos_params_s& qos, 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,
uint32_t teid_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); asn1::ngap_nr::cause_c& cause);
private: private:

@ -145,6 +145,7 @@ public:
uint32_t eps_bearer_id, uint32_t eps_bearer_id,
uint32_t addr, uint32_t addr,
uint32_t teid_out, uint32_t teid_out,
uint32_t& addr_in,
const bearer_props* props = nullptr) override; const bearer_props* props = nullptr) override;
void set_tunnel_status(uint32_t teidin, bool dl_active) override; void set_tunnel_status(uint32_t teidin, bool dl_active) override;
void rem_bearer(uint16_t rnti, uint32_t eps_bearer_id) override; void rem_bearer(uint16_t rnti, uint32_t eps_bearer_id) override;

@ -184,10 +184,9 @@ bool ngap::ue::send_initial_ctxt_setup_failure(cause_c cause)
return true; return true;
} }
bool ngap::ue::send_pdu_session_resource_setup_response( bool ngap::ue::send_pdu_session_resource_setup_response(uint16_t pdu_session_id,
uint16_t pdu_session_id, uint32_t teid_in,
uint32_t teid_out, asn1::bounded_bitstring<1, 160, true, true> addr_in)
asn1::bounded_bitstring<1, 160, true, true> transport_layer_address)
{ {
if (not ngap_ptr->amf_connected) { if (not ngap_ptr->amf_connected) {
logger.warning("AMF not 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_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.gtp_teid.from_number(teid_in);
gtp_tunnel.transport_layer_address = transport_layer_address; gtp_tunnel.transport_layer_address = addr_in;
asn1::ngap_nr::associated_qos_flow_list_l qos_flow_list; asn1::ngap_nr::associated_qos_flow_list_l qos_flow_list;
asn1::ngap_nr::associated_qos_flow_item_s qos_flow_item; asn1::ngap_nr::associated_qos_flow_item_s qos_flow_item;
qos_flow_item.qos_flow_id = 1; qos_flow_item.qos_flow_id = 1;

@ -23,25 +23,27 @@ ngap_ue_bearer_manager::~ngap_ue_bearer_manager(){};
int ngap_ue_bearer_manager::add_pdu_session(uint16_t rnti, int ngap_ue_bearer_manager::add_pdu_session(uint16_t rnti,
uint8_t pdu_session_id, uint8_t pdu_session_id,
const asn1::ngap_nr::qos_flow_level_qos_params_s& qos, 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, 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) asn1::ngap_nr::cause_c& cause)
{ {
// RRC call for QoS parameter and lcid <-> ID mapping // 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 // Only add session if gtpu was successful
pdu_session_t::gtpu_tunnel tunnel; 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"); 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; cause.set_radio_network().value = asn1::ngap_nr::cause_radio_network_opts::invalid_qos_combination;
return SRSRAN_ERROR; return SRSRAN_ERROR;
} }
// TODO long term remove lcid and just use pdu_session_id and rnti as id for GTP 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);
int rtn = add_gtpu_bearer(rnti, lcid, pdu_session_id, teid_out, addr, tunnel);
if (rtn != SRSRAN_SUCCESS) { if (rtn != SRSRAN_SUCCESS) {
logger.error("Adding PDU Session ID=%d to GTPU", pdu_session_id); logger.error("Adding PDU Session ID=%d to GTPU", pdu_session_id);
return SRSRAN_ERROR; 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].lcid = lcid;
pdu_session_list[pdu_session_id].qos_params = qos; pdu_session_list[pdu_session_id].qos_params = qos;
pdu_session_list[pdu_session_id].tunnels.push_back(tunnel); 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; return SRSRAN_SUCCESS;
} }
@ -58,25 +65,35 @@ int ngap_ue_bearer_manager::add_gtpu_bearer(uint16_t
uint32_t lcid, uint32_t lcid,
uint32_t pdu_session_id, uint32_t pdu_session_id,
uint32_t teid_out, 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, pdu_session_t::gtpu_tunnel& tunnel,
const gtpu_interface_rrc::bearer_props* props) const gtpu_interface_rrc::bearer_props* props)
{ {
// Initialize ERAB tunnel in GTPU right-away. DRBs are only created during RRC setup/reconf // Initialize ERAB tunnel in GTPU right-away. DRBs are only created during RRC setup/reconf
srsran::expected<uint32_t> rtn = gtpu->add_bearer(rnti, lcid, address.to_number(), teid_out, props); uint32_t addr_in;
srsran::expected<uint32_t> rtn = gtpu->add_bearer(rnti, lcid, address_out.to_number(), teid_out, addr_in, props);
if (rtn.is_error()) { if (rtn.is_error()) {
logger.error("Failed adding pdu_session_id=%d to GTPU", pdu_session_id); logger.error("Failed adding pdu_session_id=%d to GTPU", pdu_session_id);
return SRSRAN_ERROR; 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, rnti,
lcid, lcid,
pdu_session_id, 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; return SRSRAN_SUCCESS;
} }

@ -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 = 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]; pdu_ses_res_setup_req_trans.protocol_ies.qos_flow_setup_request_list.value[0];
srsran::const_span<uint8_t> nas_pdu_dummy; srsran::const_span<uint8_t> nas_pdu_dummy;
asn1::ngap_nr::cause_c cause;
uint32_t teid_out = 0; 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[0] << 24u;
teid_out |= pdu_ses_res_setup_req_trans.protocol_ies.ul_ngu_up_tnl_info.value.gtp_tunnel().gtp_teid[1] << 16u; 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]; teid_out |= pdu_ses_res_setup_req_trans.protocol_ies.ul_ngu_up_tnl_info.value.gtp_tunnel().gtp_teid[3];
// TODO: Check cause // 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( if (bearer_manager->add_pdu_session(
ue_ctxt->rnti, 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, 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, pdu_ses_res_setup_req_trans.protocol_ies.ul_ngu_up_tnl_info.value.gtp_tunnel().transport_layer_address,
teid_out, teid_out,
lcid,
addr_in,
teid_in,
cause) != SRSRAN_SUCCESS) { cause) != SRSRAN_SUCCESS) {
logger.warning("Failed to add pdu session\n"); logger.warning("Failed to add pdu session\n");
return proc_outcome_t::error; 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 // 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) { 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) == if (rrc->establish_rrc_bearer(ue_ctxt->rnti, su_req.pdu_session_id, su_req.pdu_session_nas_pdu, lcid) ==
SRSRAN_SUCCESS) { 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; return proc_outcome_t::success;
} }
} }

@ -237,12 +237,12 @@ int rrc::add_user(uint16_t rnti, const sched_interface::ue_cfg_t& sched_ue_cfg)
if (rnti == SRSRAN_MRNTI) { 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) { 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 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) // adding UE object to MAC for MRNTI without scheduling configuration (broadcast not part of regular scheduling)
mac->ue_cfg(SRSRAN_MRNTI, NULL); mac->ue_cfg(SRSRAN_MRNTI, NULL);
rlc->add_bearer_mrb(SRSRAN_MRNTI, lcid); rlc->add_bearer_mrb(SRSRAN_MRNTI, lcid);
pdcp->add_bearer(SRSRAN_MRNTI, lcid, srsran::make_drb_pdcp_config_t(1, false)); 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; return SRSRAN_SUCCESS;

@ -385,9 +385,10 @@ srsran::expected<uint32_t> bearer_cfg_handler::add_gtpu_bearer(uint32_t
// Initialize ERAB tunnel in GTPU right-away. DRBs are only created during RRC setup/reconf // Initialize ERAB tunnel in GTPU right-away. DRBs are only created during RRC setup/reconf
erab_t& erab = it->second; erab_t& erab = it->second;
erab_t::gtpu_tunnel bearer; erab_t::gtpu_tunnel bearer;
uint32_t addr_in;
bearer.teid_out = teid_out; bearer.teid_out = teid_out;
bearer.addr = addr; bearer.addr = addr;
srsran::expected<uint32_t> teidin = gtpu->add_bearer(rnti, erab.id, addr, teid_out, props); srsran::expected<uint32_t> teidin = gtpu->add_bearer(rnti, erab.id, addr, teid_out, addr_in, props);
if (teidin.is_error()) { if (teidin.is_error()) {
logger->error("Adding erab_id=%d to GTPU", erab_id); logger->error("Adding erab_id=%d to GTPU", erab_id);
return srsran::default_error_t(); return srsran::default_error_t();

@ -476,11 +476,15 @@ void gtpu::send_pdu_to_tunnel(const gtpu_tunnel& tx_tun, srsran::unique_byte_buf
} }
} }
srsran::expected<uint32_t> srsran::expected<uint32_t> gtpu::add_bearer(uint16_t rnti,
gtpu::add_bearer(uint16_t rnti, uint32_t eps_bearer_id, uint32_t addr, uint32_t teid_out, const bearer_props* props) 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 // 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) { if (new_tun == nullptr) {
return default_error_t(); 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; return teid_in;
} }

@ -109,8 +109,12 @@ public:
class gtpu_dummy : public srsenb::gtpu_interface_rrc class gtpu_dummy : public srsenb::gtpu_interface_rrc
{ {
public: public:
srsran::expected<uint32_t> srsran::expected<uint32_t> add_bearer(uint16_t rnti,
add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out, const bearer_props* props) override uint32_t lcid,
uint32_t addr,
uint32_t teid_out,
uint32_t& addr_in,
const bearer_props* props) override
{ {
return 1; return 1;
} }

@ -244,10 +244,11 @@ int test_gtpu_direct_tunneling(tunnel_test_event event)
senb_gtpu.init(gtpu_args, &senb_pdcp); senb_gtpu.init(gtpu_args, &senb_pdcp);
gtpu_args.gtp_bind_addr = tenb_addr_str; gtpu_args.gtp_bind_addr = tenb_addr_str;
tenb_gtpu.init(gtpu_args, &tenb_pdcp); tenb_gtpu.init(gtpu_args, &tenb_pdcp);
uint32_t addr_in1;
uint32_t addr_in2;
// create tunnels MME-SeNB and MME-TeNB // 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 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).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 // Buffer PDUs in SeNB PDCP
for (size_t sn = 6; sn < 10; ++sn) { 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; gtpu::bearer_props props;
props.flush_before_teidin_present = true; props.flush_before_teidin_present = true;
props.flush_before_teidin = tenb_teid_in; 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 = {};
props.forward_from_teidin_present = true; props.forward_from_teidin_present = true;
props.forward_from_teidin = senb_teid_in; 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<uint8_t> data_vec(10); std::vector<uint8_t> data_vec(10);
std::iota(data_vec.begin(), data_vec.end(), 0); std::iota(data_vec.begin(), data_vec.end(), 0);

Loading…
Cancel
Save