From 56ec2c286ede36c64e5616325921ff85a8058d90 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 29 Jan 2021 00:33:51 +0000 Subject: [PATCH] add gtpu test for tunneling --- .../srslte/interfaces/enb_interfaces.h | 34 ++-- lib/include/srslte/upper/gtpu.h | 2 + srsenb/hdr/stack/upper/gtpu.h | 29 ++-- srsenb/hdr/stack/upper/pdcp.h | 2 +- srsenb/src/stack/upper/gtpu.cc | 67 ++++---- srsenb/src/stack/upper/pdcp.cc | 2 +- srsenb/test/common/dummy_classes.h | 8 +- srsenb/test/upper/CMakeLists.txt | 5 + srsenb/test/upper/gtpu_test.cc | 152 ++++++++++++++++++ srsenb/test/upper/test_helpers.h | 2 +- 10 files changed, 241 insertions(+), 62 deletions(-) create mode 100644 srsenb/test/upper/gtpu_test.cc diff --git a/lib/include/srslte/interfaces/enb_interfaces.h b/lib/include/srslte/interfaces/enb_interfaces.h index 9c92b30db..ebf7cedce 100644 --- a/lib/include/srslte/interfaces/enb_interfaces.h +++ b/lib/include/srslte/interfaces/enb_interfaces.h @@ -360,26 +360,26 @@ public: class pdcp_interface_gtpu { public: - virtual void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu, uint32_t pdcp_sn = -1) = 0; - virtual std::map get_buffered_pdus(uint16_t rnti, uint32_t lcid) = 0; + virtual void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu, int pdcp_sn = -1) = 0; + virtual std::map get_buffered_pdus(uint16_t rnti, uint32_t lcid) = 0; }; // PDCP interface for RRC class pdcp_interface_rrc { public: - virtual void reset(uint16_t rnti) = 0; - virtual void add_user(uint16_t rnti) = 0; - virtual void rem_user(uint16_t rnti) = 0; - virtual void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu, uint32_t pdcp_sn = -1) = 0; - virtual void add_bearer(uint16_t rnti, uint32_t lcid, srslte::pdcp_config_t cnfg) = 0; - virtual void del_bearer(uint16_t rnti, uint32_t lcid) = 0; - virtual void config_security(uint16_t rnti, uint32_t lcid, srslte::as_security_config_t sec_cfg) = 0; - virtual void enable_integrity(uint16_t rnti, uint32_t lcid) = 0; - virtual void enable_encryption(uint16_t rnti, uint32_t lcid) = 0; - virtual bool get_bearer_state(uint16_t rnti, uint32_t lcid, srslte::pdcp_lte_state_t* state) = 0; - virtual bool set_bearer_state(uint16_t rnti, uint32_t lcid, const srslte::pdcp_lte_state_t& state) = 0; - virtual void reestablish(uint16_t rnti) = 0; + virtual void reset(uint16_t rnti) = 0; + virtual void add_user(uint16_t rnti) = 0; + virtual void rem_user(uint16_t rnti) = 0; + virtual void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu, int pdcp_sn = -1) = 0; + virtual void add_bearer(uint16_t rnti, uint32_t lcid, srslte::pdcp_config_t cnfg) = 0; + virtual void del_bearer(uint16_t rnti, uint32_t lcid) = 0; + virtual void config_security(uint16_t rnti, uint32_t lcid, srslte::as_security_config_t sec_cfg) = 0; + virtual void enable_integrity(uint16_t rnti, uint32_t lcid) = 0; + virtual void enable_encryption(uint16_t rnti, uint32_t lcid) = 0; + virtual bool get_bearer_state(uint16_t rnti, uint32_t lcid, srslte::pdcp_lte_state_t* state) = 0; + virtual bool set_bearer_state(uint16_t rnti, uint32_t lcid, const srslte::pdcp_lte_state_t& state) = 0; + virtual void reestablish(uint16_t rnti) = 0; }; // PDCP interface for RLC @@ -467,8 +467,10 @@ class gtpu_interface_rrc { public: struct bearer_props { - uint32_t dl_forward_from_teidin = 0; - uint32_t buffer_until_teidin_flush = 0; + bool forward_from_teidin_present = false; + bool flush_before_teidin_present = false; + uint32_t forward_from_teidin = 0; + uint32_t flush_before_teidin = 0; }; virtual uint32_t diff --git a/lib/include/srslte/upper/gtpu.h b/lib/include/srslte/upper/gtpu.h index 39449154b..838845dba 100644 --- a/lib/include/srslte/upper/gtpu.h +++ b/lib/include/srslte/upper/gtpu.h @@ -57,6 +57,8 @@ namespace srslte { #define GTPU_MSG_END_MARKER 254 #define GTPU_MSG_DATA_PDU 255 +#define GTPU_EXT_HEADER_PDCP_PDU_NUMBER 0b11000000 + struct gtpu_header_t { uint8_t flags = 0; uint8_t message_type = 0; diff --git a/srsenb/hdr/stack/upper/gtpu.h b/srsenb/hdr/stack/upper/gtpu.h index 3ac8e4692..27dd39ded 100644 --- a/srsenb/hdr/stack/upper/gtpu.h +++ b/srsenb/hdr/stack/upper/gtpu.h @@ -41,11 +41,14 @@ public: void stop(); // gtpu_interface_rrc - uint32_t - add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out, const bearer_props* props) override; - void rem_bearer(uint16_t rnti, uint32_t lcid) override; - void mod_bearer_rnti(uint16_t old_rnti, uint16_t new_rnti) override; - void rem_user(uint16_t rnti) override; + uint32_t add_bearer(uint16_t rnti, + uint32_t lcid, + uint32_t addr, + uint32_t teid_out, + const bearer_props* props = nullptr) override; + void rem_bearer(uint16_t rnti, uint32_t lcid) override; + void mod_bearer_rnti(uint16_t old_rnti, uint16_t new_rnti) override; + void rem_user(uint16_t rnti) override; // gtpu_interface_pdcp void write_pdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t pdu) override; @@ -103,13 +106,15 @@ private: m1u_handler m1u; struct tunnel { - uint16_t rnti = SRSLTE_INVALID_RNTI; - uint32_t lcid = SRSENB_N_RADIO_BEARERS; - uint32_t teid_in = 0; - uint32_t teid_out = 0; - uint32_t spgw_addr = 0; - uint32_t fwd_teid_in = 0; ///< forward Rx SDUs to this TEID - uint32_t prior_teid_in = 0; ///< buffer bearer SDUs until this TEID receives an End Marker + bool fwd_teid_in_present = false; + bool prior_teid_in_present = false; + uint16_t rnti = SRSLTE_INVALID_RNTI; + uint32_t lcid = SRSENB_N_RADIO_BEARERS; + uint32_t teid_in = 0; + uint32_t teid_out = 0; + uint32_t spgw_addr = 0; + uint32_t fwd_teid_in = 0; ///< forward Rx SDUs to this TEID + uint32_t prior_teid_in = 0; ///< buffer bearer SDUs until this TEID receives an End Marker std::vector buffer; }; std::unordered_map tunnels; diff --git a/srsenb/hdr/stack/upper/pdcp.h b/srsenb/hdr/stack/upper/pdcp.h index 7cbf85f45..c8ac96f3c 100644 --- a/srsenb/hdr/stack/upper/pdcp.h +++ b/srsenb/hdr/stack/upper/pdcp.h @@ -38,7 +38,7 @@ public: void reset(uint16_t rnti) override; void add_user(uint16_t rnti) override; void rem_user(uint16_t rnti) override; - void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu, uint32_t pdcp_sn = -1) override; + void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu, int pdcp_sn = -1) override; void add_bearer(uint16_t rnti, uint32_t lcid, srslte::pdcp_config_t cnfg) override; void del_bearer(uint16_t rnti, uint32_t lcid) override; void config_security(uint16_t rnti, uint32_t lcid, srslte::as_security_config_t cfg_sec) override; diff --git a/srsenb/src/stack/upper/gtpu.cc b/srsenb/src/stack/upper/gtpu.cc index a6e44e2cc..c4ebf39b6 100644 --- a/srsenb/src/stack/upper/gtpu.cc +++ b/srsenb/src/stack/upper/gtpu.cc @@ -153,22 +153,26 @@ void gtpu::send_pdu_to_tunnel(uint16_t rnti, uint32_t gtpu::add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t teid_out, const bearer_props* props) { // Allocate a TEID for the incoming tunnel - uint32_t teid_in = ++next_teid_in; - tunnel& tunnel = tunnels[teid_in]; - tunnel.teid_in = teid_in; - tunnel.rnti = rnti; - tunnel.lcid = lcid; - tunnel.spgw_addr = addr; - tunnel.teid_out = teid_out; + uint32_t teid_in = ++next_teid_in; + tunnel& new_tun = tunnels[teid_in]; + new_tun.teid_in = teid_in; + new_tun.rnti = rnti; + new_tun.lcid = lcid; + new_tun.spgw_addr = addr; + new_tun.teid_out = teid_out; ue_teidin_db[rnti][lcid].push_back(teid_in); if (props != nullptr) { - tunnel.prior_teid_in = props->buffer_until_teidin_flush; + if (props->flush_before_teidin_present) { + tunnel& after_tun = tunnels.at(props->flush_before_teidin); + after_tun.prior_teid_in_present = true; + after_tun.prior_teid_in = teid_in; + } // Connect tunnels if forwarding is activated - if (props->dl_forward_from_teidin > 0) { - if (create_dl_fwd_tunnel(props->dl_forward_from_teidin, teid_in) != SRSLTE_SUCCESS) { + if (props->forward_from_teidin_present) { + if (create_dl_fwd_tunnel(props->forward_from_teidin, teid_in) != SRSLTE_SUCCESS) { rem_tunnel(teid_in); return 0; } @@ -240,10 +244,10 @@ void gtpu::rem_tunnel(uint32_t teidin) logger.warning("Removing GTPU tunnel TEID In=0x%x", teidin); return; } - if (it->second.fwd_teid_in > 0) { + if (it->second.fwd_teid_in_present) { // Forward End Marker to forwarding tunnel, before deleting tunnel end_marker(it->second.fwd_teid_in); - it->second.fwd_teid_in = 0; + it->second.fwd_teid_in_present = false; } auto ue_it = ue_teidin_db.find(it->second.rnti); std::vector& lcid_tunnels = ue_it->second[it->second.lcid]; @@ -288,9 +292,9 @@ void gtpu::handle_gtpu_s1u_rx_packet(srslte::unique_byte_buffer_t pdu, const soc echo_response(addr.sin_addr.s_addr, addr.sin_port, header.seq_number); break; case GTPU_MSG_DATA_PDU: { - auto& tunnel = tunnels.find(header.teid)->second; - uint16_t rnti = tunnel.rnti; - uint16_t lcid = tunnel.lcid; + auto& rx_tun = tunnels.find(header.teid)->second; + uint16_t rnti = rx_tun.rnti; + uint16_t lcid = rx_tun.lcid; if (lcid < SRSENB_N_SRB || lcid >= SRSENB_N_RADIO_BEARERS) { logger.error("Invalid LCID for DL PDU: %d - dropping packet", lcid); @@ -307,22 +311,25 @@ void gtpu::handle_gtpu_s1u_rx_packet(srslte::unique_byte_buffer_t pdu, const soc if (ntohs(ip_pkt->tot_len) != pdu->N_bytes) { logger.error("IP Len and PDU N_bytes mismatch"); } - logger.debug("Rx S1-U PDU -- IP version %d, Total length %d", int(ip_pkt->version), ntohs(ip_pkt->tot_len)); - logger.debug("Rx S1-U PDU -- IP src addr %s", srslte::gtpu_ntoa(ip_pkt->saddr).c_str()); - logger.debug("Rx S1-U PDU -- IP dst addr %s", srslte::gtpu_ntoa(ip_pkt->daddr).c_str()); + logger.debug("Rx S1-U PDU -- IPv%d, src=%s, dst=%s, length=%d", + int(ip_pkt->version), + srslte::gtpu_ntoa(ip_pkt->saddr).c_str(), + srslte::gtpu_ntoa(ip_pkt->daddr).c_str(), + ntohs(ip_pkt->tot_len)); } - if (tunnel.fwd_teid_in > 0) { + if (rx_tun.fwd_teid_in_present) { + tunnel& tx_tun = tunnels.at(rx_tun.fwd_teid_in); logger.info("Forwarding GTPU PDU rnti=0x%x, lcid=%d, n_bytes=%d", rnti, lcid, pdu->N_bytes); - send_pdu_to_tunnel(rnti, lcid, std::move(pdu), tunnel.teid_out, tunnel.spgw_addr); - } else if (tunnel.prior_teid_in > 0) { + send_pdu_to_tunnel(rnti, lcid, std::move(pdu), tx_tun.teid_out, tx_tun.spgw_addr); + } else if (rx_tun.prior_teid_in_present) { logger.info( pdu->msg, pdu->N_bytes, "Buffering RX GTPU PDU rnti=0x%x, lcid=%d, n_bytes=%d", rnti, lcid, pdu->N_bytes); - tunnel.buffer.push_back(std::move(pdu)); + rx_tun.buffer.push_back(std::move(pdu)); } else { logger.info(pdu->msg, pdu->N_bytes, "RX GTPU PDU rnti=0x%x, lcid=%d, n_bytes=%d", rnti, lcid, pdu->N_bytes); uint32_t pdcp_sn = -1; - if (header.flags & GTPU_FLAGS_EXTENDED_HDR and header.next_ext_hdr_type == 0b11000000) { + if (header.flags & GTPU_FLAGS_EXTENDED_HDR and header.next_ext_hdr_type == GTPU_EXT_HEADER_PDCP_PDU_NUMBER) { pdcp_sn = (header.ext_buffer[1] << 8u) + header.ext_buffer[0]; } pdcp->write_sdu(rnti, lcid, std::move(pdu), pdcp_sn); @@ -334,20 +341,21 @@ void gtpu::handle_gtpu_s1u_rx_packet(srslte::unique_byte_buffer_t pdu, const soc logger.info("Received GTPU End Marker for rnti=0x%x.", rnti); // TS 36.300, Sec 10.1.2.2.1 - Path Switch upon handover - if (old_tun.fwd_teid_in > 0) { + if (old_tun.fwd_teid_in_present) { // END MARKER should be forwarded to TeNB if forwarding is activated end_marker(old_tun.fwd_teid_in); - old_tun.fwd_teid_in = 0; + old_tun.fwd_teid_in_present = false; } else { // TeNB switches paths, and flush PDUs that have been buffered std::vector& bearer_tunnels = ue_teidin_db.find(old_tun.rnti)->second[old_tun.lcid]; for (uint32_t new_teidin : bearer_tunnels) { - tunnel& new_tun = tunnels.find(new_teidin)->second; - if (new_teidin != old_tun.teid_in and new_tun.prior_teid_in == old_tun.teid_in) { + tunnel& new_tun = tunnels.at(new_teidin); + if (new_teidin != old_tun.teid_in and new_tun.prior_teid_in_present and + new_tun.prior_teid_in == old_tun.teid_in) { for (srslte::unique_byte_buffer_t& sdu : new_tun.buffer) { pdcp->write_sdu(new_tun.rnti, new_tun.lcid, std::move(sdu)); } - new_tun.prior_teid_in = 0; + new_tun.prior_teid_in_present = false; new_tun.buffer.clear(); } } @@ -375,7 +383,8 @@ int gtpu::create_dl_fwd_tunnel(uint32_t rx_teid_in, uint32_t tx_teid_in) } tunnel &rx_tun = rx_tun_pair->second, &tx_tun = tx_tun_pair->second; - rx_tun.fwd_teid_in = tx_teid_in; + rx_tun.fwd_teid_in_present = true; + rx_tun.fwd_teid_in = tx_teid_in; logger.info("Creating forwarding tunnel for rnti=0x%x, lcid=%d, in={0x%x, 0x%x}->out={0x%x, 0x%x}", rx_tun.rnti, rx_tun.lcid, diff --git a/srsenb/src/stack/upper/pdcp.cc b/srsenb/src/stack/upper/pdcp.cc index 3ae5245a1..d66892cdd 100644 --- a/srsenb/src/stack/upper/pdcp.cc +++ b/srsenb/src/stack/upper/pdcp.cc @@ -139,7 +139,7 @@ void pdcp::write_pdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t } } -void pdcp::write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu, uint32_t pdcp_sn) +void pdcp::write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu, int pdcp_sn) { if (users.count(rnti)) { if (rnti != SRSLTE_MRNTI) { diff --git a/srsenb/test/common/dummy_classes.h b/srsenb/test/common/dummy_classes.h index ac141f8eb..876bdbc66 100644 --- a/srsenb/test/common/dummy_classes.h +++ b/srsenb/test/common/dummy_classes.h @@ -55,13 +55,13 @@ public: void reestablish(uint16_t rnti) override {} }; -class pdcp_dummy : public pdcp_interface_rrc +class pdcp_dummy : public pdcp_interface_rrc, public pdcp_interface_gtpu { public: void reset(uint16_t rnti) override {} void add_user(uint16_t rnti) override {} void rem_user(uint16_t rnti) override {} - void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu, uint32_t pdcp_sn) override {} + void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu, int pdcp_sn) override {} void add_bearer(uint16_t rnti, uint32_t lcid, srslte::pdcp_config_t cnfg) override {} void del_bearer(uint16_t rnti, uint32_t lcid) override {} void config_security(uint16_t rnti, uint32_t lcid, srslte::as_security_config_t sec_cfg_) override {} @@ -70,6 +70,10 @@ public: bool get_bearer_state(uint16_t rnti, uint32_t lcid, srslte::pdcp_lte_state_t* state) override { return true; } bool set_bearer_state(uint16_t rnti, uint32_t lcid, const srslte::pdcp_lte_state_t& state) override { return true; } void reestablish(uint16_t rnti) override {} + std::map get_buffered_pdus(uint16_t rnti, uint32_t lcid) override + { + return {}; + } }; class s1ap_dummy : public s1ap_interface_rrc diff --git a/srsenb/test/upper/CMakeLists.txt b/srsenb/test/upper/CMakeLists.txt index f0ffb9056..c83d58f68 100644 --- a/srsenb/test/upper/CMakeLists.txt +++ b/srsenb/test/upper/CMakeLists.txt @@ -22,7 +22,12 @@ target_link_libraries(erab_setup_test srsenb_rrc rrc_asn1 s1ap_asn1 srslte_commo add_executable(rrc_meascfg_test rrc_meascfg_test.cc) target_link_libraries(rrc_meascfg_test test_helpers) +add_executable(gtpu_test gtpu_test.cc) +target_link_libraries(gtpu_test srslte_common s1ap_asn1 srsenb_upper srslte_upper ${SCTP_LIBRARIES}) + add_test(rrc_mobility_test rrc_mobility_test -i ${CMAKE_CURRENT_SOURCE_DIR}/../..) add_test(erab_setup_test erab_setup_test -i ${CMAKE_CURRENT_SOURCE_DIR}/../..) add_test(rrc_meascfg_test rrc_meascfg_test -i ${CMAKE_CURRENT_SOURCE_DIR}/../..) +add_test(plmn_test plmn_test) +add_test(gtpu_test gtpu_test) diff --git a/srsenb/test/upper/gtpu_test.cc b/srsenb/test/upper/gtpu_test.cc new file mode 100644 index 000000000..e8ddad804 --- /dev/null +++ b/srsenb/test/upper/gtpu_test.cc @@ -0,0 +1,152 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2020 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/asn1/s1ap.h" +#include +#include + +#include "srsenb/hdr/stack/upper/gtpu.h" +#include "srsenb/test/common/dummy_classes.h" +#include "srslte/common/network_utils.h" +#include "srslte/common/test_common.h" +#include "srslte/upper/gtpu.h" + +namespace srsenb { + +class stack_tester : public stack_interface_gtpu_lte +{ +public: + int s1u_fd; + void add_gtpu_s1u_socket_handler(int fd) { s1u_fd = fd; } + void add_gtpu_m1u_socket_handler(int fd) {} +}; + +class pdcp_tester : public pdcp_dummy +{ +public: + void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu, int pdcp_sn) override + { + last_sdu = std::move(sdu); + last_pdcp_sn = pdcp_sn; + last_rnti = rnti; + last_lcid = lcid; + } + + srslte::unique_byte_buffer_t last_sdu; + int last_pdcp_sn = -1; + uint16_t last_rnti = SRSLTE_INVALID_RNTI; + uint32_t last_lcid = 0; +}; + +int GTPU_PORT = 2152; + +srslte::unique_byte_buffer_t encode_gtpu_packet(srslte::span data, + uint32_t teid, + const struct sockaddr_in& src_sockaddr_in, + const struct sockaddr_in& dest_sockaddr_in) +{ + srslte::unique_byte_buffer_t pdu = srslte::allocate_unique_buffer(*srslte::byte_buffer_pool::get_instance()); + + struct iphdr ip_pkt; + ip_pkt.version = 4; + ip_pkt.tot_len = htons(data.size() + sizeof(struct iphdr)); + ip_pkt.saddr = src_sockaddr_in.sin_addr.s_addr; + ip_pkt.daddr = dest_sockaddr_in.sin_addr.s_addr; + memcpy(pdu->msg, &ip_pkt, sizeof(struct iphdr)); + pdu->N_bytes = sizeof(struct iphdr); + memcpy(pdu->msg + pdu->N_bytes, data.data(), data.size()); + pdu->N_bytes += data.size(); + + // header + srslte::gtpu_header_t header; + header.flags = GTPU_FLAGS_VERSION_V1 | GTPU_FLAGS_GTP_PROTOCOL; + header.message_type = GTPU_MSG_DATA_PDU; + header.length = pdu->N_bytes; + header.teid = teid; + + gtpu_write_header(&header, pdu.get(), srslte::log_ref("GTPU")); + return pdu; +} + +srslte::unique_byte_buffer_t read_socket(int fd) +{ + srslte::unique_byte_buffer_t pdu = srslte::allocate_unique_buffer(*srslte::byte_buffer_pool::get_instance()); + pdu->N_bytes = read(fd, pdu->msg, pdu->get_tailroom()); + return pdu; +} + +int test_gtpu_direct_tunneling() +{ + uint16_t rnti = 0x46, rnti2 = 0x50; + uint32_t drb1 = 3; + uint32_t mme_teidout1 = 1, mme_teidout2 = 2; + const char * mme_addr_str = "127.0.0.1", *senb_addr_str = "127.0.1.1", *tenb_addr_str = "127.0.1.2"; + struct sockaddr_in senb_sockaddr, mme_sockaddr, tenb_sockaddr; + srslte::net_utils::set_sockaddr(&senb_sockaddr, senb_addr_str, GTPU_PORT); + srslte::net_utils::set_sockaddr(&mme_sockaddr, mme_addr_str, GTPU_PORT); + srslte::net_utils::set_sockaddr(&tenb_sockaddr, tenb_addr_str, GTPU_PORT); + uint32_t tenb_addr = ntohl(tenb_sockaddr.sin_addr.s_addr), mme_addr = ntohl(mme_sockaddr.sin_addr.s_addr); + + // Initiate layers + srsenb::gtpu senb_gtpu(srslog::fetch_basic_logger("GTPU1")), tenb_gtpu(srslog::fetch_basic_logger("GTPU2")); + stack_tester senb_stack, tenb_stack; + pdcp_tester senb_pdcp, tenb_pdcp; + senb_gtpu.init(senb_addr_str, mme_addr_str, "", "", &senb_pdcp, &senb_stack, false); + tenb_gtpu.init(tenb_addr_str, mme_addr_str, "", "", &tenb_pdcp, &tenb_stack, false); + + // create tunnels MME-SeNB and MME-TeNB + uint32_t senb_teid_in = senb_gtpu.add_bearer(rnti, drb1, mme_addr, mme_teidout1); + uint32_t tenb_teid_in = tenb_gtpu.add_bearer(rnti, drb1, mme_addr, mme_teidout2); + + // create direct tunnel SeNB-TeNB + 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, 0, 0, &props); + props = {}; + props.forward_from_teidin_present = true; + props.forward_from_teidin = senb_teid_in; + senb_gtpu.add_bearer(rnti, drb1, tenb_addr, dl_tenb_teid_in, &props); + + std::vector data_vec(10); + std::iota(data_vec.begin(), data_vec.end(), 0); + + // TEST: verify that incoming DL data is forwarded through SeNB-TeNB tunnel + srslte::unique_byte_buffer_t pdu = encode_gtpu_packet(data_vec, senb_teid_in, mme_sockaddr, senb_sockaddr); + std::vector encoded_data(pdu->msg + 8u, pdu->msg + pdu->N_bytes); + senb_gtpu.handle_gtpu_s1u_rx_packet(std::move(pdu), mme_sockaddr); + tenb_gtpu.handle_gtpu_s1u_rx_packet(read_socket(tenb_stack.s1u_fd), senb_sockaddr); + TESTASSERT(tenb_pdcp.last_sdu != nullptr); + TESTASSERT(tenb_pdcp.last_sdu->N_bytes == encoded_data.size() and + memcmp(tenb_pdcp.last_sdu->msg, encoded_data.data(), encoded_data.size()) == 0); + TESTASSERT(tenb_pdcp.last_rnti == rnti2); + TESTASSERT(tenb_pdcp.last_lcid == drb1); + + return SRSLTE_SUCCESS; +} + +} // namespace srsenb + +int main() +{ + // Setup logging. + srslog::sink& log_sink = srslog::fetch_stdout_sink(); + srslog::log_channel* chan = srslog::create_log_channel("gtpu_test", log_sink); + srslte::srslog_wrapper log_wrapper(*chan); + + // Start the log backend. + srslog::init(); + + srslte::logmap::set_default_log_level(srslte::LOG_LEVEL_DEBUG); + srslte::logmap::set_default_hex_limit(100000); + TESTASSERT(srsenb::test_gtpu_direct_tunneling() == SRSLTE_SUCCESS); +} diff --git a/srsenb/test/upper/test_helpers.h b/srsenb/test/upper/test_helpers.h index a5b65e8a1..26965559b 100644 --- a/srsenb/test/upper/test_helpers.h +++ b/srsenb/test/upper/test_helpers.h @@ -130,7 +130,7 @@ public: }; std::map > bearers; - void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu, uint32_t pdcp_sn) override + void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu, int pdcp_sn) override { last_sdu.rnti = rnti; last_sdu.lcid = lcid;