diff --git a/srsepc/epc.conf.example b/srsepc/epc.conf.example index 16434ceee..e530a6dc4 100644 --- a/srsepc/epc.conf.example +++ b/srsepc/epc.conf.example @@ -21,5 +21,6 @@ mcc = 001 mnc = 01 mme_bind_addr = 127.0.0.0/24 - +[spgw] +s1u_bind_addr=127.0.0.1 diff --git a/srsepc/hdr/spgw/spgw.h b/srsepc/hdr/spgw/spgw.h index ffd854b38..1e4795019 100644 --- a/srsepc/hdr/spgw/spgw.h +++ b/srsepc/hdr/spgw/spgw.h @@ -42,8 +42,10 @@ namespace srsepc{ +const uint16_t GTPU_RX_PORT = 2152; + typedef struct { - std::string gtpc_bind_addr; + std::string gtpu_bind_addr; } spgw_args_t; @@ -63,14 +65,19 @@ private: virtual ~spgw(); static spgw *m_instance; - srslte::error_t init_sgi_if(); + srslte::error_t init_sgi_if(spgw_args_t *args); + srslte::error_t init_s1u(spgw_args_t *args); bool m_running; srslte::byte_buffer_pool *m_pool; - bool m_if_up; + bool m_sgi_up; int m_sgi_if; int m_sgi_sock; + + bool m_s1u_up; + int m_s1u; + /*Logs*/ srslte::log_filter *m_spgw_log; diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index edceda337..15820a12a 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -41,7 +41,8 @@ boost::mutex spgw_instance_mutex; spgw::spgw(): m_running(false), - m_if_up(false) + m_sgi_up(false), + m_s1u_up(false) { m_pool = srslte::byte_buffer_pool::get_instance(); return; @@ -75,11 +76,26 @@ spgw::cleanup(void) int spgw::init(spgw_args_t* args, srslte::log_filter *spgw_log) { + srslte::error_t err; + //Init log m_spgw_log = spgw_log; - //Init Si interface - init_sgi_if(); + //Init SGi interface + err = init_sgi_if(args); + if (err != srslte::ERROR_NONE) + { + m_spgw_log->console("Could not initialize the SGi interface.\n"); + return -1; + } + + //Init S1-U + err = init_s1u(args); + if (err != srslte::ERROR_NONE) + { + m_spgw_log->console("Could not initialize the S1-U interface.\n"); + return -1; + } m_spgw_log->info("SP-GW Initialized.\n"); m_spgw_log->console("SP-GW Initialized.\n"); return 0; @@ -94,12 +110,17 @@ spgw::stop() thread_cancel(); wait_thread_finish(); - //Clean up interface - if(m_if_up) + //Clean up SGi interface + if(m_sgi_up) { close(m_sgi_if); close(m_sgi_sock); } + //Clean up S1-U socket + if(m_s1u_up) + { + close(m_s1u); + } } return; } @@ -117,12 +138,12 @@ spgw::run_thread() } srslte::error_t -spgw::init_sgi_if() +spgw::init_sgi_if(spgw_args_t *args) { char dev[IFNAMSIZ] = "srs_spgw_sgi"; struct ifreq ifr; - if(m_if_up) + if(m_sgi_up) { return(srslte::ERROR_ALREADY_STARTED); } @@ -133,7 +154,7 @@ spgw::init_sgi_if() m_spgw_log->info("TUN file descriptor = %d\n", m_sgi_if); if(m_sgi_if < 0) { - m_spgw_log->debug("Failed to open TUN device: %s\n", strerror(errno)); + m_spgw_log->error("Failed to open TUN device: %s\n", strerror(errno)); return(srslte::ERROR_CANT_START); } @@ -142,7 +163,7 @@ spgw::init_sgi_if() strncpy(ifr.ifr_ifrn.ifrn_name, dev, IFNAMSIZ); if(ioctl(m_sgi_if, TUNSETIFF, &ifr) < 0) { - m_spgw_log->debug("Failed to set TUN device name: %s\n", strerror(errno)); + m_spgw_log->error("Failed to set TUN device name: %s\n", strerror(errno)); close(m_sgi_if); return(srslte::ERROR_CANT_START); } @@ -151,20 +172,45 @@ spgw::init_sgi_if() m_sgi_sock = socket(AF_INET, SOCK_DGRAM, 0); if(ioctl(m_sgi_sock, SIOCGIFFLAGS, &ifr) < 0) { - m_spgw_log->debug("Failed to bring up socket: %s\n", strerror(errno)); + m_spgw_log->error("Failed to bring up socket: %s\n", strerror(errno)); close(m_sgi_if); return(srslte::ERROR_CANT_START); } ifr.ifr_flags |= IFF_UP | IFF_RUNNING; if(ioctl(m_sgi_sock, SIOCSIFFLAGS, &ifr) < 0) { - m_spgw_log->debug("Failed to set socket flags: %s\n", strerror(errno)); + m_spgw_log->error("Failed to set socket flags: %s\n", strerror(errno)); close(m_sgi_if); return(srslte::ERROR_CANT_START); } - m_if_up = true; + m_sgi_up = true; return(srslte::ERROR_NONE); } +srslte::error_t +spgw::init_s1u(spgw_args_t *args) +{ + //Open S1-U socket + m_s1u = socket(AF_INET,SOCK_DGRAM,0); + if (m_s1u == -1) + { + m_spgw_log->error("Failed to open socket: %s\n", strerror(errno)); + return srslte::ERROR_CANT_START; + } + m_s1u_up = true; + + //Bind the socket + struct sockaddr_in servaddr; + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr=inet_addr(args->gtpu_bind_addr.c_str()); + servaddr.sin_port=htons(GTPU_RX_PORT); + + if (bind(m_s1u,(struct sockaddr *)&servaddr,sizeof(struct sockaddr_in))) { + m_spgw_log->error("Failed to bind socket: %s\n", strerror(errno)); + return srslte::ERROR_CANT_START; + } + return srslte::ERROR_NONE; +} + } //namespace srsepc