diff --git a/srsepc/hdr/mme/mme.h b/srsepc/hdr/mme/mme.h index d46dfdd40..d9a985b19 100644 --- a/srsepc/hdr/mme/mme.h +++ b/srsepc/hdr/mme/mme.h @@ -34,22 +34,34 @@ #define MME_H #include +#include "s1ap.h" + namespace srsepc{ +typedef struct{ + s1ap_args_t s1ap_args; +} all_args_t; + + class mme { public: static mme* get_instance(void); static void cleanup(void); + + int init(all_args_t* args); + + int get_s1_mme(); private: - static mme *instance; mme(); virtual ~mme(); - + static mme *m_instance; + s1ap m_s1ap; + }; } // namespace srsepc diff --git a/srsepc/hdr/mme/s1ap.h b/srsepc/hdr/mme/s1ap.h index 2e93db2d4..3a50cc80f 100644 --- a/srsepc/hdr/mme/s1ap.h +++ b/srsepc/hdr/mme/s1ap.h @@ -26,12 +26,39 @@ namespace srsepc{ +const uint16_t S1MME_PORT = 36412; + +typedef struct{ + uint8_t mme_code; + uint16_t mme_group; + uint16_t tac; // 16-bit tac + uint16_t mcc; // BCD-coded with 0xF filler + uint16_t mnc; // BCD-coded with 0xF filler + std::string mme_bindx_addr; + std::string mme_name; +} s1ap_args_t; + class s1ap { public: s1ap(); virtual ~s1ap(); int enb_listen(); + + int init(s1ap_args_t s1ap_args); + + int get_s1_mme(); + +private: + uint8_t m_mme_code; + uint16_t m_mme_group; + uint16_t m_tac; // 16-bit tac + uint16_t m_mcc; // BCD-coded with 0xF filler + uint16_t m_mnc; // BCD-coded with 0xF filler + std::string m_mme_bindx_addr; + std::string m_mme_name; + + int m_s1mme; }; } //namespace srsepc diff --git a/srsepc/src/main.cc b/srsepc/src/main.cc index f77a1cc18..48c252da1 100644 --- a/srsepc/src/main.cc +++ b/srsepc/src/main.cc @@ -8,12 +8,12 @@ * * This file is part of srsLTE. * - * srsUE is free software: you can redistribute it and/or modify + * srsLTE is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * - * srsUE is distributed in the hope that it will be useful, + * srsLTE is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. @@ -24,20 +24,103 @@ * */ #include +#include +#include +#include +#include #include #include "mme/mme.h" - using namespace std; using namespace srsepc; namespace bpo = boost::program_options; +bool running = true; + +/* +void +parse_args(all_args_t *args, int argc, char* argv[]) { + + string mme_code; + string mme_group; + string tac; + string mcc; + string mnc; + + // Command line only options + bpo::options_description general("General options"); + general.add_options() + ("help,h", "Produce help message") + ("version,v", "Print version information and exit") + ; + + // Command line or config file options + bpo::options_description common("Configuration options"); + common.add_options() + + ("mme.enb_id", bpo::value(&enb_id)->default_value("0x0"), "eNodeB ID") + ("mme.name", bpo::value(&args->enb.s1ap.enb_name)->default_value("srsenb01"), "eNodeB Name") + ("mme.cell_id", bpo::value(&cell_id)->default_value("0x0"), "Cell ID") + ("mme.tac", bpo::value(&tac)->default_value("0x0"), "Tracking Area Code") + ("mme.mcc", bpo::value(&mcc)->default_value("001"), "Mobile Country Code") + ("mme.mnc", bpo::value(&mnc)->default_value("01"), "Mobile Network Code") + ("mme.mme_bindx_addr", bpo::value(&args->enb.s1ap.mme_addr)->default_value("127.0.0.1"),"IP address of MME for S1 connnection") + ; + + // Positional options - config file location + bpo::options_description position("Positional options"); + position.add_options() + ("config_file", bpo::value< string >(&config_file), "eNodeB configuration file") + ; + bpo::positional_options_description p; + p.add("config_file", -1) + + return; +} +*/ + int main (int argc,char * argv[] ) -{ - //signal(SIGINT, sig_int_handler); - mme *mme = mme::get_instance(); - +{ cout << "--- Software Radio Systems EPC MME ---" << endl << endl; + + //signal(SIGINT, sig_int_handler); + + //TODO these should be passed from config files + all_args_t args; + args.s1ap_args.mme_code = 0x01; + args.s1ap_args.mme_group = 0x0001; + args.s1ap_args.tac = 0x0001; + args.s1ap_args.mcc = 0x01; + args.s1ap_args.mnc = 0x01; + args.s1ap_args.mme_bindx_addr="127.0.0.0/24"; + + struct sockaddr_in enb_addr; + char readbuf[1000]; + struct sctp_sndrcvinfo sri; + socklen_t fromlen; + int rd_sz; + int msg_flags; + + mme *mme = mme::get_instance(); + if (mme->init(&args)) { + cout << "Error initializing MME" << endl; + exit(1); + } + + //Initalize S1-MME scoket + int s1mme = mme->get_s1_mme(); + while(running) + { + cout << "Waiting for SCTP Msg" << endl; + rd_sz = sctp_recvmsg(s1mme, (void*) readbuf, sizeof(readbuf),(struct sockaddr*) &enb_addr, &fromlen, &sri, &msg_flags); + if (rd_sz == -1){ + cout<< "Error reading from SCTP socket"< //TODO Remove #include #include "mme/mme.h" namespace srsepc{ -mme* mme::instance = NULL; +mme* mme::m_instance = NULL; boost::mutex mme_instance_mutex; mme::mme() @@ -46,21 +47,36 @@ mme* mme::get_instance(void) { boost::mutex::scoped_lock lock(mme_instance_mutex); - if(NULL == instance) { - instance = new mme(); + if(NULL == m_instance) { + m_instance = new mme(); } - return(instance); + return(m_instance); } void mme::cleanup(void) { boost::mutex::scoped_lock lock(mme_instance_mutex); - if(NULL != instance) { - delete instance; - instance = NULL; + if(NULL != m_instance) { + delete m_instance; + m_instance = NULL; } } +int +mme::init(all_args_t* args) +{ + if(m_s1ap.init(args->s1ap_args)){ + std::cout << "Error initializing MME S1APP" << std::endl; + exit(-1); + } + return 0; +} + +int +mme::get_s1_mme() +{ + return m_s1ap.get_s1_mme(); +} } //namespace srsepc diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 514060178..b53fe0479 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -43,11 +43,26 @@ s1ap::~s1ap() { } +int +s1ap::init(s1ap_args_t s1ap_args) +{ + m_mme_code = s1ap_args.mme_code ; + m_mme_group = s1ap_args.mme_group; + m_tac = s1ap_args.tac; + m_mcc = s1ap_args.mcc; + m_mnc = s1ap_args.mnc; + m_mme_bindx_addr = s1ap_args.mme_bindx_addr; + m_mme_name = std::string("SRS MME"); + + m_s1mme = enb_listen(); + return 0; +} + int s1ap::enb_listen() { /*This function sets up the SCTP socket for eNBs to connect to*/ - int sock_fd; + int sock_fd, err; struct sockaddr_in s1mme_addr;//TODO make this a configurable class memeber. sock_fd = socket (AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); @@ -59,13 +74,26 @@ s1ap::enb_listen() //S1-MME bind bzero(&s1mme_addr, sizeof(s1mme_addr)); s1mme_addr.sin_family = AF_INET; - s1mme_addr.sin_addr.s_addr = htonl(INADDR_ANY); - s1mme_addr.sin_port = htons(18000); //TODO define S1MME_PORT + s1mme_addr.sin_addr.s_addr = htonl(INADDR_ANY); //TODO this should use the bindx information + s1mme_addr.sin_port = htons(S1MME_PORT); + err = bind(sock_fd, (struct sockaddr*) &s1mme_addr, sizeof (s1mme_addr)); + if (err != 0){ + std::cout << "Error binding SCTP socket" << std::endl; + } //Listen for connections - listen(sock_fd,SOMAXCONN); + err = listen(sock_fd,SOMAXCONN); + if (err != 0){ + std::cout << "Error in SCTP socket listen" << std::endl; + } return sock_fd; } +int +s1ap::get_s1_mme() +{ + return m_s1mme; +} + }//namespace srsepc