mirror of https://github.com/PentHertz/srsLTE.git
add gtpu test for tunneling
This commit is contained in:
parent
13649e4e19
commit
56ec2c286e
|
@ -360,26 +360,26 @@ public:
|
||||||
class pdcp_interface_gtpu
|
class pdcp_interface_gtpu
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu, uint32_t pdcp_sn = -1) = 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<uint32_t, srslte::unique_byte_buffer_t> get_buffered_pdus(uint16_t rnti, uint32_t lcid) = 0;
|
virtual std::map<uint32_t, srslte::unique_byte_buffer_t> get_buffered_pdus(uint16_t rnti, uint32_t lcid) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// PDCP interface for RRC
|
// PDCP interface for RRC
|
||||||
class pdcp_interface_rrc
|
class pdcp_interface_rrc
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void reset(uint16_t rnti) = 0;
|
virtual void reset(uint16_t rnti) = 0;
|
||||||
virtual void add_user(uint16_t rnti) = 0;
|
virtual void add_user(uint16_t rnti) = 0;
|
||||||
virtual void rem_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 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 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 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 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_integrity(uint16_t rnti, uint32_t lcid) = 0;
|
||||||
virtual void enable_encryption(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 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 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 reestablish(uint16_t rnti) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// PDCP interface for RLC
|
// PDCP interface for RLC
|
||||||
|
@ -467,8 +467,10 @@ class gtpu_interface_rrc
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
struct bearer_props {
|
struct bearer_props {
|
||||||
uint32_t dl_forward_from_teidin = 0;
|
bool forward_from_teidin_present = false;
|
||||||
uint32_t buffer_until_teidin_flush = 0;
|
bool flush_before_teidin_present = false;
|
||||||
|
uint32_t forward_from_teidin = 0;
|
||||||
|
uint32_t flush_before_teidin = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual uint32_t
|
virtual uint32_t
|
||||||
|
|
|
@ -57,6 +57,8 @@ namespace srslte {
|
||||||
#define GTPU_MSG_END_MARKER 254
|
#define GTPU_MSG_END_MARKER 254
|
||||||
#define GTPU_MSG_DATA_PDU 255
|
#define GTPU_MSG_DATA_PDU 255
|
||||||
|
|
||||||
|
#define GTPU_EXT_HEADER_PDCP_PDU_NUMBER 0b11000000
|
||||||
|
|
||||||
struct gtpu_header_t {
|
struct gtpu_header_t {
|
||||||
uint8_t flags = 0;
|
uint8_t flags = 0;
|
||||||
uint8_t message_type = 0;
|
uint8_t message_type = 0;
|
||||||
|
|
|
@ -41,11 +41,14 @@ public:
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
// gtpu_interface_rrc
|
// gtpu_interface_rrc
|
||||||
uint32_t
|
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,
|
||||||
void rem_bearer(uint16_t rnti, uint32_t lcid) override;
|
uint32_t addr,
|
||||||
void mod_bearer_rnti(uint16_t old_rnti, uint16_t new_rnti) override;
|
uint32_t teid_out,
|
||||||
void rem_user(uint16_t rnti) override;
|
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
|
// gtpu_interface_pdcp
|
||||||
void write_pdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t pdu) override;
|
void write_pdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t pdu) override;
|
||||||
|
@ -103,13 +106,15 @@ private:
|
||||||
m1u_handler m1u;
|
m1u_handler m1u;
|
||||||
|
|
||||||
struct tunnel {
|
struct tunnel {
|
||||||
uint16_t rnti = SRSLTE_INVALID_RNTI;
|
bool fwd_teid_in_present = false;
|
||||||
uint32_t lcid = SRSENB_N_RADIO_BEARERS;
|
bool prior_teid_in_present = false;
|
||||||
uint32_t teid_in = 0;
|
uint16_t rnti = SRSLTE_INVALID_RNTI;
|
||||||
uint32_t teid_out = 0;
|
uint32_t lcid = SRSENB_N_RADIO_BEARERS;
|
||||||
uint32_t spgw_addr = 0;
|
uint32_t teid_in = 0;
|
||||||
uint32_t fwd_teid_in = 0; ///< forward Rx SDUs to this TEID
|
uint32_t teid_out = 0;
|
||||||
uint32_t prior_teid_in = 0; ///< buffer bearer SDUs until this TEID receives an End Marker
|
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<srslte::unique_byte_buffer_t> buffer;
|
std::vector<srslte::unique_byte_buffer_t> buffer;
|
||||||
};
|
};
|
||||||
std::unordered_map<uint32_t, tunnel> tunnels;
|
std::unordered_map<uint32_t, tunnel> tunnels;
|
||||||
|
|
|
@ -38,7 +38,7 @@ public:
|
||||||
void reset(uint16_t rnti) override;
|
void reset(uint16_t rnti) override;
|
||||||
void add_user(uint16_t rnti) override;
|
void add_user(uint16_t rnti) override;
|
||||||
void rem_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 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 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;
|
void config_security(uint16_t rnti, uint32_t lcid, srslte::as_security_config_t cfg_sec) override;
|
||||||
|
|
|
@ -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)
|
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
|
// Allocate a TEID for the incoming tunnel
|
||||||
uint32_t teid_in = ++next_teid_in;
|
uint32_t teid_in = ++next_teid_in;
|
||||||
tunnel& tunnel = tunnels[teid_in];
|
tunnel& new_tun = tunnels[teid_in];
|
||||||
tunnel.teid_in = teid_in;
|
new_tun.teid_in = teid_in;
|
||||||
tunnel.rnti = rnti;
|
new_tun.rnti = rnti;
|
||||||
tunnel.lcid = lcid;
|
new_tun.lcid = lcid;
|
||||||
tunnel.spgw_addr = addr;
|
new_tun.spgw_addr = addr;
|
||||||
tunnel.teid_out = teid_out;
|
new_tun.teid_out = teid_out;
|
||||||
|
|
||||||
ue_teidin_db[rnti][lcid].push_back(teid_in);
|
ue_teidin_db[rnti][lcid].push_back(teid_in);
|
||||||
|
|
||||||
if (props != nullptr) {
|
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
|
// Connect tunnels if forwarding is activated
|
||||||
if (props->dl_forward_from_teidin > 0) {
|
if (props->forward_from_teidin_present) {
|
||||||
if (create_dl_fwd_tunnel(props->dl_forward_from_teidin, teid_in) != SRSLTE_SUCCESS) {
|
if (create_dl_fwd_tunnel(props->forward_from_teidin, teid_in) != SRSLTE_SUCCESS) {
|
||||||
rem_tunnel(teid_in);
|
rem_tunnel(teid_in);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -240,10 +244,10 @@ void gtpu::rem_tunnel(uint32_t teidin)
|
||||||
logger.warning("Removing GTPU tunnel TEID In=0x%x", teidin);
|
logger.warning("Removing GTPU tunnel TEID In=0x%x", teidin);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (it->second.fwd_teid_in > 0) {
|
if (it->second.fwd_teid_in_present) {
|
||||||
// Forward End Marker to forwarding tunnel, before deleting tunnel
|
// Forward End Marker to forwarding tunnel, before deleting tunnel
|
||||||
end_marker(it->second.fwd_teid_in);
|
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);
|
auto ue_it = ue_teidin_db.find(it->second.rnti);
|
||||||
std::vector<uint32_t>& lcid_tunnels = ue_it->second[it->second.lcid];
|
std::vector<uint32_t>& 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);
|
echo_response(addr.sin_addr.s_addr, addr.sin_port, header.seq_number);
|
||||||
break;
|
break;
|
||||||
case GTPU_MSG_DATA_PDU: {
|
case GTPU_MSG_DATA_PDU: {
|
||||||
auto& tunnel = tunnels.find(header.teid)->second;
|
auto& rx_tun = tunnels.find(header.teid)->second;
|
||||||
uint16_t rnti = tunnel.rnti;
|
uint16_t rnti = rx_tun.rnti;
|
||||||
uint16_t lcid = tunnel.lcid;
|
uint16_t lcid = rx_tun.lcid;
|
||||||
|
|
||||||
if (lcid < SRSENB_N_SRB || lcid >= SRSENB_N_RADIO_BEARERS) {
|
if (lcid < SRSENB_N_SRB || lcid >= SRSENB_N_RADIO_BEARERS) {
|
||||||
logger.error("Invalid LCID for DL PDU: %d - dropping packet", lcid);
|
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) {
|
if (ntohs(ip_pkt->tot_len) != pdu->N_bytes) {
|
||||||
logger.error("IP Len and PDU N_bytes mismatch");
|
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 -- IPv%d, src=%s, dst=%s, length=%d",
|
||||||
logger.debug("Rx S1-U PDU -- IP src addr %s", srslte::gtpu_ntoa(ip_pkt->saddr).c_str());
|
int(ip_pkt->version),
|
||||||
logger.debug("Rx S1-U PDU -- IP dst addr %s", srslte::gtpu_ntoa(ip_pkt->daddr).c_str());
|
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);
|
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);
|
send_pdu_to_tunnel(rnti, lcid, std::move(pdu), tx_tun.teid_out, tx_tun.spgw_addr);
|
||||||
} else if (tunnel.prior_teid_in > 0) {
|
} else if (rx_tun.prior_teid_in_present) {
|
||||||
logger.info(
|
logger.info(
|
||||||
pdu->msg, pdu->N_bytes, "Buffering RX GTPU PDU rnti=0x%x, lcid=%d, n_bytes=%d", rnti, lcid, pdu->N_bytes);
|
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 {
|
} else {
|
||||||
logger.info(pdu->msg, pdu->N_bytes, "RX GTPU PDU rnti=0x%x, lcid=%d, n_bytes=%d", rnti, lcid, pdu->N_bytes);
|
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;
|
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_sn = (header.ext_buffer[1] << 8u) + header.ext_buffer[0];
|
||||||
}
|
}
|
||||||
pdcp->write_sdu(rnti, lcid, std::move(pdu), pdcp_sn);
|
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);
|
logger.info("Received GTPU End Marker for rnti=0x%x.", rnti);
|
||||||
|
|
||||||
// TS 36.300, Sec 10.1.2.2.1 - Path Switch upon handover
|
// 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 should be forwarded to TeNB if forwarding is activated
|
||||||
end_marker(old_tun.fwd_teid_in);
|
end_marker(old_tun.fwd_teid_in);
|
||||||
old_tun.fwd_teid_in = 0;
|
old_tun.fwd_teid_in_present = false;
|
||||||
} else {
|
} else {
|
||||||
// TeNB switches paths, and flush PDUs that have been buffered
|
// TeNB switches paths, and flush PDUs that have been buffered
|
||||||
std::vector<uint32_t>& bearer_tunnels = ue_teidin_db.find(old_tun.rnti)->second[old_tun.lcid];
|
std::vector<uint32_t>& bearer_tunnels = ue_teidin_db.find(old_tun.rnti)->second[old_tun.lcid];
|
||||||
for (uint32_t new_teidin : bearer_tunnels) {
|
for (uint32_t new_teidin : bearer_tunnels) {
|
||||||
tunnel& new_tun = tunnels.find(new_teidin)->second;
|
tunnel& new_tun = tunnels.at(new_teidin);
|
||||||
if (new_teidin != old_tun.teid_in and new_tun.prior_teid_in == old_tun.teid_in) {
|
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) {
|
for (srslte::unique_byte_buffer_t& sdu : new_tun.buffer) {
|
||||||
pdcp->write_sdu(new_tun.rnti, new_tun.lcid, std::move(sdu));
|
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();
|
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;
|
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}",
|
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.rnti,
|
||||||
rx_tun.lcid,
|
rx_tun.lcid,
|
||||||
|
|
|
@ -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 (users.count(rnti)) {
|
||||||
if (rnti != SRSLTE_MRNTI) {
|
if (rnti != SRSLTE_MRNTI) {
|
||||||
|
|
|
@ -55,13 +55,13 @@ public:
|
||||||
void reestablish(uint16_t rnti) override {}
|
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:
|
public:
|
||||||
void reset(uint16_t rnti) override {}
|
void reset(uint16_t rnti) override {}
|
||||||
void add_user(uint16_t rnti) override {}
|
void add_user(uint16_t rnti) override {}
|
||||||
void rem_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 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 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 {}
|
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 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; }
|
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 {}
|
void reestablish(uint16_t rnti) override {}
|
||||||
|
std::map<uint32_t, srslte::unique_byte_buffer_t> get_buffered_pdus(uint16_t rnti, uint32_t lcid) override
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class s1ap_dummy : public s1ap_interface_rrc
|
class s1ap_dummy : public s1ap_interface_rrc
|
||||||
|
|
|
@ -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)
|
add_executable(rrc_meascfg_test rrc_meascfg_test.cc)
|
||||||
target_link_libraries(rrc_meascfg_test test_helpers)
|
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(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(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(rrc_meascfg_test rrc_meascfg_test -i ${CMAKE_CURRENT_SOURCE_DIR}/../..)
|
||||||
|
add_test(plmn_test plmn_test)
|
||||||
|
add_test(gtpu_test gtpu_test)
|
||||||
|
|
||||||
|
|
|
@ -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 <linux/ip.h>
|
||||||
|
#include <numeric>
|
||||||
|
|
||||||
|
#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<uint8_t> 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<uint8_t> 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<uint8_t> 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);
|
||||||
|
}
|
|
@ -130,7 +130,7 @@ public:
|
||||||
};
|
};
|
||||||
std::map<uint16_t, std::map<uint32_t, lcid_cfg_t> > bearers;
|
std::map<uint16_t, std::map<uint32_t, lcid_cfg_t> > 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.rnti = rnti;
|
||||||
last_sdu.lcid = lcid;
|
last_sdu.lcid = lcid;
|
||||||
|
|
Loading…
Reference in New Issue