diff --git a/srsepc/epc.conf.example b/srsepc/epc.conf.example index e530a6dc4..053915a1d 100644 --- a/srsepc/epc.conf.example +++ b/srsepc/epc.conf.example @@ -22,5 +22,5 @@ mnc = 01 mme_bind_addr = 127.0.0.0/24 [spgw] -s1u_bind_addr=127.0.0.1 - +gtpu_bind_addr=127.0.0.1 +sgi_if_addr=172.0.0.1 diff --git a/srsepc/hdr/spgw/spgw.h b/srsepc/hdr/spgw/spgw.h index 1e4795019..eb75ed57d 100644 --- a/srsepc/hdr/spgw/spgw.h +++ b/srsepc/hdr/spgw/spgw.h @@ -46,6 +46,7 @@ const uint16_t GTPU_RX_PORT = 2152; typedef struct { std::string gtpu_bind_addr; + std::string sgi_if_addr; } spgw_args_t; diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index eae1ab45b..b0a4b1432 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -71,6 +71,8 @@ parse_args(all_args_t *args, int argc, char* argv[]) { string mcc; string mnc; string mme_bind_addr; + string spgw_bind_addr; + string sgi_if_addr; // Command line only options bpo::options_description general("General options"); @@ -90,6 +92,8 @@ parse_args(all_args_t *args, int argc, char* argv[]) { ("mme.mcc", bpo::value(&mcc)->default_value("001"), "Mobile Country Code") ("mme.mnc", bpo::value(&mnc)->default_value("01"), "Mobile Network Code") ("mme.mme_bind_addr", bpo::value(&mme_bind_addr)->default_value("127.0.0.1"),"IP address of MME for S1 connnection") + ("spgw.gtpu_bind_addr", bpo::value(&spgw_bind_addr)->default_value("127.0.0.1"),"IP address of SP-GW for the S1-U connection") + ("spgw.sgi_if_addr", bpo::value(&sgi_if_addr)->default_value("176.16.0.1"),"IP address of TUN interface for the SGi connection") ; @@ -162,6 +166,8 @@ parse_args(all_args_t *args, int argc, char* argv[]) { } args->mme_args.s1ap_args.mme_bind_addr = mme_bind_addr; + args->spgw_args.gtpu_bind_addr = spgw_bind_addr; + args->spgw_args.sgi_if_addr = sgi_if_addr; return; } diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index 15820a12a..1d2169a9a 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -25,6 +25,7 @@ */ #include +#include #include #include #include @@ -39,6 +40,8 @@ namespace srsepc{ spgw* spgw::m_instance = NULL; boost::mutex spgw_instance_mutex; +const uint16_t SPGW_BUFFER_SIZE = 2500; + spgw::spgw(): m_running(false), m_sgi_up(false), @@ -130,10 +133,53 @@ 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) { - sleep(1); + 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; } @@ -170,6 +216,7 @@ spgw::init_sgi_if(spgw_args_t *args) // Bring up the interface m_sgi_sock = socket(AF_INET, SOCK_DGRAM, 0); + if(ioctl(m_sgi_sock, SIOCGIFFLAGS, &ifr) < 0) { m_spgw_log->error("Failed to bring up socket: %s\n", strerror(errno)); @@ -184,6 +231,28 @@ spgw::init_sgi_if(spgw_args_t *args) return(srslte::ERROR_CANT_START); } + //Set IP of the interface + struct sockaddr_in *addr = (struct sockaddr_in*)&ifr.ifr_addr; + addr->sin_family = AF_INET; + addr->sin_addr.s_addr = inet_addr(args->sgi_if_addr.c_str()); + addr->sin_port = 0; + + if (ioctl(m_sgi_sock, SIOCSIFADDR, &ifr) < 0) { + m_spgw_log->error("Failed to set TUN interface IP. Address: %s, Error: %s\n", args->sgi_if_addr.c_str(), strerror(errno)); + close(m_sgi_if); + close(m_sgi_sock); + return srslte::ERROR_CANT_START; + } + + ifr.ifr_netmask.sa_family = AF_INET; + ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr("255.255.255.0"); + if (ioctl(m_sgi_sock, SIOCSIFNETMASK, &ifr) < 0) { + m_spgw_log->error("Failed to set TUN interface Netmask. Error: %s\n", strerror(errno)); + close(m_sgi_if); + close(m_sgi_sock); + return srslte::ERROR_CANT_START; + } + m_sgi_up = true; return(srslte::ERROR_NONE); } @@ -210,6 +279,7 @@ spgw::init_s1u(spgw_args_t *args) m_spgw_log->error("Failed to bind socket: %s\n", strerror(errno)); return srslte::ERROR_CANT_START; } + m_spgw_log->info("S1-U socket = %d\n", m_s1u); return srslte::ERROR_NONE; }