|
|
|
@ -35,6 +35,7 @@
|
|
|
|
|
#include <linux/if_tun.h>
|
|
|
|
|
#include "spgw/spgw.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace srsepc{
|
|
|
|
|
|
|
|
|
|
spgw* spgw::m_instance = NULL;
|
|
|
|
@ -128,61 +129,6 @@ spgw::stop()
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
spgw::run_thread()
|
|
|
|
|
{
|
|
|
|
|
//Mark the thread as running
|
|
|
|
|
m_running=true;
|
|
|
|
|
srslte::byte_buffer_t *msg;
|
|
|
|
|
msg = m_pool->allocate();
|
|
|
|
|
|
|
|
|
|
struct sockaddr src_addr;
|
|
|
|
|
socklen_t addrlen;
|
|
|
|
|
|
|
|
|
|
int sgi = m_sgi_if;
|
|
|
|
|
|
|
|
|
|
fd_set set;
|
|
|
|
|
//struct timeval to;
|
|
|
|
|
int max_fd = std::max(m_s1u,sgi);
|
|
|
|
|
while (m_running)
|
|
|
|
|
{
|
|
|
|
|
msg->reset();
|
|
|
|
|
FD_ZERO(&set);
|
|
|
|
|
FD_SET(m_s1u, &set);
|
|
|
|
|
FD_SET(sgi, &set);
|
|
|
|
|
|
|
|
|
|
m_spgw_log->info("Waiting for S1-U or SGi packets.\n");
|
|
|
|
|
int n = select(max_fd+1, &set, NULL, NULL, NULL);
|
|
|
|
|
if (n == -1)
|
|
|
|
|
{
|
|
|
|
|
m_spgw_log->error("Error from select\n");
|
|
|
|
|
}
|
|
|
|
|
else if (n)
|
|
|
|
|
{
|
|
|
|
|
m_spgw_log->info("Data is available now.\n");
|
|
|
|
|
if (FD_ISSET(m_s1u, &set))
|
|
|
|
|
{
|
|
|
|
|
msg->N_bytes = recvfrom(m_s1u, msg->msg, SRSLTE_MAX_BUFFER_SIZE_BYTES, 0, &src_addr, &addrlen );
|
|
|
|
|
m_spgw_log->console("Received PDU from S1-U. Bytes %d\n", msg->N_bytes);
|
|
|
|
|
m_spgw_log->debug("Received PDU from S1-U. Bytes %d\n", msg->N_bytes);
|
|
|
|
|
}
|
|
|
|
|
if (FD_ISSET(m_sgi_if, &set))
|
|
|
|
|
{
|
|
|
|
|
m_spgw_log->console("Received PDU from SGi\n");
|
|
|
|
|
msg->N_bytes = read(sgi, msg->msg, SRSLTE_MAX_BUFFER_SIZE_BYTES);
|
|
|
|
|
m_spgw_log->console("Received PDU from SGi. Bytes %d\n", msg->N_bytes);
|
|
|
|
|
m_spgw_log->debug("Received PDU from SGi. Bytes %d\n", msg->N_bytes);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
m_spgw_log->debug("No data from select.\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
m_pool->deallocate(msg);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
srslte::error_t
|
|
|
|
|
spgw::init_sgi_if(spgw_args_t *args)
|
|
|
|
|
{
|
|
|
|
@ -283,4 +229,97 @@ spgw::init_s1u(spgw_args_t *args)
|
|
|
|
|
return srslte::ERROR_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
spgw::run_thread()
|
|
|
|
|
{
|
|
|
|
|
//Mark the thread as running
|
|
|
|
|
m_running=true;
|
|
|
|
|
srslte::byte_buffer_t *msg;
|
|
|
|
|
msg = m_pool->allocate();
|
|
|
|
|
|
|
|
|
|
struct sockaddr src_addr;
|
|
|
|
|
socklen_t addrlen;
|
|
|
|
|
|
|
|
|
|
int sgi = m_sgi_if;
|
|
|
|
|
|
|
|
|
|
fd_set set;
|
|
|
|
|
//struct timeval to;
|
|
|
|
|
int max_fd = std::max(m_s1u,sgi);
|
|
|
|
|
while (m_running)
|
|
|
|
|
{
|
|
|
|
|
msg->reset();
|
|
|
|
|
FD_ZERO(&set);
|
|
|
|
|
FD_SET(m_s1u, &set);
|
|
|
|
|
FD_SET(sgi, &set);
|
|
|
|
|
|
|
|
|
|
m_spgw_log->info("Waiting for S1-U or SGi packets.\n");
|
|
|
|
|
int n = select(max_fd+1, &set, NULL, NULL, NULL);
|
|
|
|
|
if (n == -1)
|
|
|
|
|
{
|
|
|
|
|
m_spgw_log->error("Error from select\n");
|
|
|
|
|
}
|
|
|
|
|
else if (n)
|
|
|
|
|
{
|
|
|
|
|
m_spgw_log->info("Data is available now.\n");
|
|
|
|
|
if (FD_ISSET(m_s1u, &set))
|
|
|
|
|
{
|
|
|
|
|
msg->N_bytes = recvfrom(m_s1u, msg->msg, SRSLTE_MAX_BUFFER_SIZE_BYTES, 0, &src_addr, &addrlen );
|
|
|
|
|
m_spgw_log->console("Received PDU from S1-U. Bytes %d\n", msg->N_bytes);
|
|
|
|
|
m_spgw_log->debug("Received PDU from S1-U. Bytes %d\n", msg->N_bytes);
|
|
|
|
|
}
|
|
|
|
|
if (FD_ISSET(m_sgi_if, &set))
|
|
|
|
|
{
|
|
|
|
|
m_spgw_log->console("Received PDU from SGi\n");
|
|
|
|
|
msg->N_bytes = read(sgi, msg->msg, SRSLTE_MAX_BUFFER_SIZE_BYTES);
|
|
|
|
|
m_spgw_log->console("Received PDU from SGi. Bytes %d\n", msg->N_bytes);
|
|
|
|
|
m_spgw_log->debug("Received PDU from SGi. Bytes %d\n", msg->N_bytes);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
m_spgw_log->debug("No data from select.\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
m_pool->deallocate(msg);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
spgw::handle_create_session_request(struct srslte::gtpc_create_session_request *cs_req, struct srslte::gtpc_create_session_response *cs_resp)
|
|
|
|
|
{
|
|
|
|
|
//Setup uplink control TEID
|
|
|
|
|
uint64_t spgw_uplink_ctrl_teid = get_new_ctrl_teid();
|
|
|
|
|
//Setup uplink user TEID
|
|
|
|
|
uint64_t spgw_uplink_user_teid = get_new_user_teid();
|
|
|
|
|
//Allocate UE IP
|
|
|
|
|
in_addr_t ue_ip = get_new_ue_ipv4();
|
|
|
|
|
|
|
|
|
|
//Save the UE context //TODO!!!
|
|
|
|
|
|
|
|
|
|
//Create session response message
|
|
|
|
|
//Initialize to zero\\
|
|
|
|
|
bzero(cs_resp,sizeof(struct srslte::gtpc_create_session_response));
|
|
|
|
|
//Setup Cause\\
|
|
|
|
|
cs_resp->cause = ;
|
|
|
|
|
//Setup sender F-TEID (ctrl)\\
|
|
|
|
|
cs_resp->sender_f_teid.teid_present = true;
|
|
|
|
|
cs_resp->sender_f_teid.teid = spgw_uplink_ctrl_teid;
|
|
|
|
|
cs_resp->sender_f_teid.ipv4 = m_gtpu_bind_addr;//FIXME This is not relevant, as the GTP-C is not transmitted over sockets yet.
|
|
|
|
|
//Bearer context created\\
|
|
|
|
|
cs_resp->eps_bearer_context_created.ebi = 5;
|
|
|
|
|
cs_resp->eps_bearer_context_created.cause = ;
|
|
|
|
|
cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid_present=true;
|
|
|
|
|
cs_resp->eps_bearer_context_created.s1_u_sgw_f_teid.teid = spgw_uplink_user_teid;
|
|
|
|
|
//Fill in the PDA\\
|
|
|
|
|
cs_resp->pda_present = true;
|
|
|
|
|
cs_resp->pda.pdn_type = srslte::GTPC_IPV4;
|
|
|
|
|
cs_resp->ipv4_present = true;
|
|
|
|
|
cs_resp->ipv4 = ue_ip;
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} //namespace srsepc
|
|
|
|
|