|
|
|
@ -29,35 +29,35 @@ static const size_t PDU_HEADER_SIZE = 20;
|
|
|
|
|
class pdcp_tester : public pdcp_dummy
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu, int pdcp_sn) override
|
|
|
|
|
void write_sdu(uint16_t rnti, uint32_t eps_bearer_id, srsran::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;
|
|
|
|
|
last_sdu = std::move(sdu);
|
|
|
|
|
last_pdcp_sn = pdcp_sn;
|
|
|
|
|
last_rnti = rnti;
|
|
|
|
|
last_eps_bearer_id = eps_bearer_id;
|
|
|
|
|
}
|
|
|
|
|
std::map<uint32_t, srsran::unique_byte_buffer_t> get_buffered_pdus(uint16_t rnti, uint32_t lcid) override
|
|
|
|
|
std::map<uint32_t, srsran::unique_byte_buffer_t> get_buffered_pdus(uint16_t rnti, uint32_t eps_bearer_id) override
|
|
|
|
|
{
|
|
|
|
|
return std::move(buffered_pdus);
|
|
|
|
|
}
|
|
|
|
|
void send_status_report(uint16_t rnti) override {}
|
|
|
|
|
void send_status_report(uint16_t rnti, uint32_t lcid) override {}
|
|
|
|
|
void send_status_report(uint16_t rnti, uint32_t eps_bearer_id) override {}
|
|
|
|
|
|
|
|
|
|
void push_buffered_pdu(uint32_t sn, srsran::unique_byte_buffer_t pdu) { buffered_pdus[sn] = std::move(pdu); }
|
|
|
|
|
|
|
|
|
|
void clear()
|
|
|
|
|
{
|
|
|
|
|
last_sdu = nullptr;
|
|
|
|
|
last_pdcp_sn = -1;
|
|
|
|
|
last_lcid = 0;
|
|
|
|
|
last_rnti = SRSRAN_INVALID_RNTI;
|
|
|
|
|
last_sdu = nullptr;
|
|
|
|
|
last_pdcp_sn = -1;
|
|
|
|
|
last_eps_bearer_id = 0;
|
|
|
|
|
last_rnti = SRSRAN_INVALID_RNTI;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
std::map<uint32_t, srsran::unique_byte_buffer_t> buffered_pdus;
|
|
|
|
|
srsran::unique_byte_buffer_t last_sdu;
|
|
|
|
|
int last_pdcp_sn = -1;
|
|
|
|
|
uint16_t last_rnti = SRSRAN_INVALID_RNTI;
|
|
|
|
|
uint32_t last_lcid = 0;
|
|
|
|
|
int last_pdcp_sn = -1;
|
|
|
|
|
uint16_t last_rnti = SRSRAN_INVALID_RNTI;
|
|
|
|
|
uint32_t last_eps_bearer_id = 0;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct dummy_socket_manager : public srsran::socket_manager_itf {
|
|
|
|
@ -153,44 +153,44 @@ void test_gtpu_tunnel_manager()
|
|
|
|
|
const char* sgw_addr_str = "127.0.0.1";
|
|
|
|
|
struct sockaddr_in sgw_sockaddr = {};
|
|
|
|
|
srsran::net_utils::set_sockaddr(&sgw_sockaddr, sgw_addr_str, GTPU_PORT);
|
|
|
|
|
uint32_t sgw_addr = ntohl(sgw_sockaddr.sin_addr.s_addr);
|
|
|
|
|
const uint32_t drb1_lcid = 3;
|
|
|
|
|
uint32_t sgw_addr = ntohl(sgw_sockaddr.sin_addr.s_addr);
|
|
|
|
|
const uint32_t drb1_eps_bearer_id = 5;
|
|
|
|
|
srsran::task_scheduler task_sched;
|
|
|
|
|
gtpu_args_t gtpu_args = {};
|
|
|
|
|
|
|
|
|
|
gtpu_tunnel_manager tunnels(&task_sched, srslog::fetch_basic_logger("GTPU"));
|
|
|
|
|
tunnels.init(gtpu_args, nullptr);
|
|
|
|
|
TESTASSERT(tunnels.find_tunnel(0) == nullptr);
|
|
|
|
|
TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_lcid).empty());
|
|
|
|
|
TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_eps_bearer_id).empty());
|
|
|
|
|
TESTASSERT(tunnels.find_rnti_tunnels(0x46) == nullptr);
|
|
|
|
|
|
|
|
|
|
// Creation of tunnels for different users and lcids
|
|
|
|
|
const gtpu_tunnel* tun = tunnels.add_tunnel(0x46, drb1_lcid, 5, sgw_addr);
|
|
|
|
|
// Creation of tunnels for different users and bearers
|
|
|
|
|
const gtpu_tunnel* tun = tunnels.add_tunnel(0x46, drb1_eps_bearer_id, 5, sgw_addr);
|
|
|
|
|
TESTASSERT(tun != nullptr);
|
|
|
|
|
TESTASSERT(tunnels.find_tunnel(tun->teid_in) == tun);
|
|
|
|
|
const gtpu_tunnel* tun2 = tunnels.add_tunnel(0x47, drb1_lcid, 6, sgw_addr);
|
|
|
|
|
const gtpu_tunnel* tun2 = tunnels.add_tunnel(0x47, drb1_eps_bearer_id, 6, sgw_addr);
|
|
|
|
|
TESTASSERT(tun2 != nullptr);
|
|
|
|
|
TESTASSERT(tunnels.find_tunnel(tun2->teid_in) == tun2);
|
|
|
|
|
tun2 = tunnels.add_tunnel(0x47, drb1_lcid + 1, 7, sgw_addr);
|
|
|
|
|
tun2 = tunnels.add_tunnel(0x47, drb1_eps_bearer_id + 1, 7, sgw_addr);
|
|
|
|
|
TESTASSERT(tun2 != nullptr);
|
|
|
|
|
TESTASSERT(tunnels.find_tunnel(tun2->teid_in) == tun2);
|
|
|
|
|
TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_lcid).size() == 1);
|
|
|
|
|
TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x47, drb1_lcid).size() == 1);
|
|
|
|
|
TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x47, drb1_lcid + 1).size() == 1);
|
|
|
|
|
TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_eps_bearer_id).size() == 1);
|
|
|
|
|
TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x47, drb1_eps_bearer_id).size() == 1);
|
|
|
|
|
TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x47, drb1_eps_bearer_id + 1).size() == 1);
|
|
|
|
|
|
|
|
|
|
// TEST: Creation/Removal of indirect tunnel
|
|
|
|
|
const gtpu_tunnel* fwd_tun = tunnels.add_tunnel(0x46, drb1_lcid, 8, sgw_addr);
|
|
|
|
|
const gtpu_tunnel* fwd_tun = tunnels.add_tunnel(0x46, drb1_eps_bearer_id, 8, sgw_addr);
|
|
|
|
|
TESTASSERT(fwd_tun != nullptr);
|
|
|
|
|
TESTASSERT(tunnels.find_tunnel(fwd_tun->teid_in) == fwd_tun);
|
|
|
|
|
tunnels.setup_forwarding(tun->teid_in, fwd_tun->teid_in);
|
|
|
|
|
TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_lcid).size() == 2);
|
|
|
|
|
TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_eps_bearer_id).size() == 2);
|
|
|
|
|
// Removing a tunnel also clears any associated forwarding tunnel
|
|
|
|
|
TESTASSERT(tunnels.remove_tunnel(tun->teid_in));
|
|
|
|
|
TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_lcid).empty());
|
|
|
|
|
TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_eps_bearer_id).empty());
|
|
|
|
|
|
|
|
|
|
// TEST: Prioritization of one TEID over another
|
|
|
|
|
const gtpu_tunnel* before_tun = tunnels.add_tunnel(0x46, drb1_lcid, 7, sgw_addr);
|
|
|
|
|
const gtpu_tunnel* after_tun = tunnels.add_tunnel(0x46, drb1_lcid, 8, sgw_addr);
|
|
|
|
|
const gtpu_tunnel* before_tun = tunnels.add_tunnel(0x46, drb1_eps_bearer_id, 7, sgw_addr);
|
|
|
|
|
const gtpu_tunnel* after_tun = tunnels.add_tunnel(0x46, drb1_eps_bearer_id, 8, sgw_addr);
|
|
|
|
|
TESTASSERT(before_tun != nullptr and after_tun != nullptr);
|
|
|
|
|
tunnels.set_tunnel_priority(before_tun->teid_in, after_tun->teid_in);
|
|
|
|
|
for (uint32_t i = 0; i < 1000; ++i) {
|
|
|
|
@ -200,9 +200,9 @@ void test_gtpu_tunnel_manager()
|
|
|
|
|
tunnels.handle_rx_pdcp_sdu(before_tun->teid_in);
|
|
|
|
|
}
|
|
|
|
|
// Removing active TEID, will automatically switch TEID paths
|
|
|
|
|
TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_lcid).size() == 2);
|
|
|
|
|
TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_eps_bearer_id).size() == 2);
|
|
|
|
|
tunnels.remove_tunnel(before_tun->teid_in);
|
|
|
|
|
TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_lcid).size() == 1);
|
|
|
|
|
TESTASSERT(tunnels.find_rnti_bearer_tunnels(0x46, drb1_eps_bearer_id).size() == 1);
|
|
|
|
|
TESTASSERT(after_tun->state == gtpu_tunnel_manager::tunnel_state::pdcp_active);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -215,7 +215,7 @@ int test_gtpu_direct_tunneling(tunnel_test_event event)
|
|
|
|
|
srslog::basic_logger& logger = srslog::fetch_basic_logger("TEST");
|
|
|
|
|
logger.info("\n\n**** Test GTPU Direct Tunneling ****\n");
|
|
|
|
|
uint16_t rnti = 0x46, rnti2 = 0x50;
|
|
|
|
|
uint32_t drb1 = 3;
|
|
|
|
|
uint32_t drb1_bearer_id = 5;
|
|
|
|
|
uint32_t sgw_teidout1 = 1, sgw_teidout2 = 2;
|
|
|
|
|
const char * sgw_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 = {}, sgw_sockaddr = {}, tenb_sockaddr = {};
|
|
|
|
@ -246,8 +246,8 @@ int test_gtpu_direct_tunneling(tunnel_test_event event)
|
|
|
|
|
tenb_gtpu.init(gtpu_args, &tenb_pdcp);
|
|
|
|
|
|
|
|
|
|
// create tunnels MME-SeNB and MME-TeNB
|
|
|
|
|
uint32_t senb_teid_in = senb_gtpu.add_bearer(rnti, drb1, sgw_addr, sgw_teidout1).value();
|
|
|
|
|
uint32_t tenb_teid_in = tenb_gtpu.add_bearer(rnti2, drb1, sgw_addr, sgw_teidout2).value();
|
|
|
|
|
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();
|
|
|
|
|
|
|
|
|
|
// Buffer PDUs in SeNB PDCP
|
|
|
|
|
for (size_t sn = 6; sn < 10; ++sn) {
|
|
|
|
@ -260,11 +260,11 @@ 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, senb_addr, 0, &props).value();
|
|
|
|
|
uint32_t dl_tenb_teid_in = tenb_gtpu.add_bearer(rnti2, drb1_bearer_id, senb_addr, 0, &props).value();
|
|
|
|
|
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);
|
|
|
|
|
senb_gtpu.add_bearer(rnti, drb1_bearer_id, tenb_addr, dl_tenb_teid_in, &props);
|
|
|
|
|
|
|
|
|
|
std::vector<uint8_t> data_vec(10);
|
|
|
|
|
std::iota(data_vec.begin(), data_vec.end(), 0);
|
|
|
|
@ -280,7 +280,7 @@ int test_gtpu_direct_tunneling(tunnel_test_event event)
|
|
|
|
|
pdu_view = srsran::make_span(tenb_pdcp.last_sdu);
|
|
|
|
|
TESTASSERT(std::count(pdu_view.begin() + PDU_HEADER_SIZE, pdu_view.end(), 7) == 10);
|
|
|
|
|
TESTASSERT(tenb_pdcp.last_rnti == rnti2);
|
|
|
|
|
TESTASSERT(tenb_pdcp.last_lcid == drb1);
|
|
|
|
|
TESTASSERT(tenb_pdcp.last_eps_bearer_id == drb1_bearer_id);
|
|
|
|
|
TESTASSERT(tenb_pdcp.last_pdcp_sn == (int)7);
|
|
|
|
|
|
|
|
|
|
// TEST: verify that PDCP buffered SNs have been forwarded through SeNB->TeNB tunnel
|
|
|
|
@ -289,7 +289,7 @@ int test_gtpu_direct_tunneling(tunnel_test_event event)
|
|
|
|
|
pdu_view = srsran::make_span(tenb_pdcp.last_sdu);
|
|
|
|
|
TESTASSERT(std::count(pdu_view.begin() + PDU_HEADER_SIZE, pdu_view.end(), sn) == 10);
|
|
|
|
|
TESTASSERT(tenb_pdcp.last_rnti == rnti2);
|
|
|
|
|
TESTASSERT(tenb_pdcp.last_lcid == drb1);
|
|
|
|
|
TESTASSERT(tenb_pdcp.last_eps_bearer_id == drb1_bearer_id);
|
|
|
|
|
TESTASSERT(tenb_pdcp.last_pdcp_sn == (int)sn);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -302,7 +302,7 @@ int test_gtpu_direct_tunneling(tunnel_test_event event)
|
|
|
|
|
pdu_view = srsran::make_span(tenb_pdcp.last_sdu);
|
|
|
|
|
TESTASSERT(pdu_view.size() == encoded_data.size() and
|
|
|
|
|
std::equal(pdu_view.begin(), pdu_view.end(), encoded_data.begin()));
|
|
|
|
|
TESTASSERT(tenb_pdcp.last_rnti == rnti2 and tenb_pdcp.last_lcid == drb1);
|
|
|
|
|
TESTASSERT(tenb_pdcp.last_rnti == rnti2 and tenb_pdcp.last_eps_bearer_id == drb1_bearer_id);
|
|
|
|
|
|
|
|
|
|
// TEST: verify that MME->TeNB packets are buffered until SeNB->TeNB tunnel is closed
|
|
|
|
|
tenb_pdcp.clear();
|
|
|
|
@ -361,7 +361,7 @@ int test_gtpu_direct_tunneling(tunnel_test_event event)
|
|
|
|
|
if (event != tunnel_test_event::ue_removal_no_marker) {
|
|
|
|
|
// The User is removed in SeNB in case it hasn't and there was no reestablishment
|
|
|
|
|
if (std::uniform_int_distribution<uint32_t>{0, 1}(g) > 0) {
|
|
|
|
|
senb_gtpu.rem_bearer(0x46, 3);
|
|
|
|
|
senb_gtpu.rem_bearer(0x46, drb1_bearer_id);
|
|
|
|
|
}
|
|
|
|
|
senb_gtpu.rem_user(0x46);
|
|
|
|
|
}
|
|
|
|
|