diff --git a/srsepc/hdr/mme/mme.h b/srsepc/hdr/mme/mme.h index 053887d54..2ce0f65eb 100644 --- a/srsepc/hdr/mme/mme.h +++ b/srsepc/hdr/mme/mme.h @@ -72,6 +72,7 @@ private: bool m_running; srslte::byte_buffer_pool* m_pool; + fd_set m_set; /*Logs*/ srslte::log_filter* m_nas_log; diff --git a/srsepc/hdr/mme/mme_gtpc.h b/srsepc/hdr/mme/mme_gtpc.h index bb0e2a55b..f3ffe9500 100644 --- a/srsepc/hdr/mme/mme_gtpc.h +++ b/srsepc/hdr/mme/mme_gtpc.h @@ -51,7 +51,8 @@ public: static void cleanup(void); bool init(srslte::log_filter* mme_gtpc_log); - void handle_s11_pdu(srslte::gtpc_pdu* msg); + bool send_s11_pdu(const srslte::gtpc_pdu& pdu); + void handle_s11_pdu(srslte::byte_buffer_t* msg); virtual bool send_create_session_request(uint64_t imsi); bool handle_create_session_response(srslte::gtpc_pdu* cs_resp_pdu); @@ -60,6 +61,8 @@ public: void send_release_access_bearers_request(uint64_t imsi); virtual bool send_delete_session_request(uint64_t imsi); + int get_s11(); + private: mme_gtpc(); virtual ~mme_gtpc(); @@ -88,5 +91,10 @@ inline uint32_t mme_gtpc::get_new_ctrl_teid() return m_next_ctrl_teid++; } +inline int mme_gtpc::get_s11() +{ + return m_s11; +} + } // namespace srsepc #endif // SRSEPC_MME_GTPC_H diff --git a/srsepc/hdr/spgw/gtpc.h b/srsepc/hdr/spgw/gtpc.h index 53f064254..5bf2334af 100644 --- a/srsepc/hdr/spgw/gtpc.h +++ b/srsepc/hdr/spgw/gtpc.h @@ -50,18 +50,16 @@ public: uint64_t get_new_user_teid(); in_addr_t get_new_ue_ipv4(); - void handle_s11_pdu(srslte::gtpc_pdu* msg, srslte::gtpc_pdu* reply_msg); + void handle_s11_pdu(srslte::byte_buffer_t* msg); + bool send_s11_pdu(const srslte::gtpc_pdu& pdu); - void handle_create_session_request(const srslte::gtpc_create_session_request& cs_req, srslte::gtpc_pdu* gtpc_pdu); + void handle_create_session_request(const srslte::gtpc_create_session_request& cs_req); void handle_modify_bearer_request(const srslte::gtpc_header& mb_req_hdr, - const srslte::gtpc_modify_bearer_request& mb_req, - srslte::gtpc_pdu* mb_resp_pdu); + const srslte::gtpc_modify_bearer_request& mb_req); void handle_delete_session_request(const srslte::gtpc_header& header, - const srslte::gtpc_delete_session_request& del_req, - srslte::gtpc_pdu* del_resp_pdu); + const srslte::gtpc_delete_session_request& del_req); void handle_release_access_bearers_request(const srslte::gtpc_header& header, - const srslte::gtpc_release_access_bearers_request& rel_req, - srslte::gtpc_pdu* rel_resp_pdu); + const srslte::gtpc_release_access_bearers_request& rel_req); spgw_tunnel_ctx_t* create_gtpc_ctx(const srslte::gtpc_create_session_request& cs_req); bool delete_gtpc_ctx(uint32_t ctrl_teid); diff --git a/srsepc/hdr/spgw/spgw.h b/srsepc/hdr/spgw/spgw.h index f7e17d1ca..8ecf2e18b 100644 --- a/srsepc/hdr/spgw/spgw.h +++ b/srsepc/hdr/spgw/spgw.h @@ -75,10 +75,6 @@ public: void stop(); void run_thread(); - void handle_sgi_pdu(srslte::byte_buffer_t* msg); - void handle_s1u_pdu(srslte::byte_buffer_t* msg); - void handle_s11_pdu(srslte::gtpc_pdu* pdu, srslte::gtpc_pdu* reply_pdu); - private: spgw(); virtual ~spgw(); diff --git a/srsepc/src/mme/mme.cc b/srsepc/src/mme/mme.cc index 5d64a2e27..729ebbc23 100644 --- a/srsepc/src/mme/mme.cc +++ b/srsepc/src/mme/mme.cc @@ -124,32 +124,55 @@ void mme::run_thread() // Mark the thread as running m_running = true; - // Get S1-MME socket + // Get S1-MME and S11 sockets int s1mme = m_s1ap->get_s1_mme(); + int s11 = m_mme_gtpc->get_s11(); + while (m_running) { - m_s1ap_log->debug("Waiting for SCTP Msg\n"); pdu->reset(); - rd_sz = sctp_recvmsg(s1mme, pdu->msg, sz, (struct sockaddr*)&enb_addr, &fromlen, &sri, &msg_flags); - if (rd_sz == -1 && errno != EAGAIN) { - m_s1ap_log->error("Error reading from SCTP socket: %s", strerror(errno)); - } else if (rd_sz == -1 && errno == EAGAIN) { - m_s1ap_log->debug("Socket timeout reached"); - } else { - if (msg_flags & MSG_NOTIFICATION) { - // Received notification - union sctp_notification* notification = (union sctp_notification*)pdu->msg; - m_s1ap_log->debug("SCTP Notification %d\n", notification->sn_header.sn_type); - if (notification->sn_header.sn_type == SCTP_SHUTDOWN_EVENT) { - m_s1ap_log->info("SCTP Association Shutdown. Association: %d\n", sri.sinfo_assoc_id); - m_s1ap_log->console("SCTP Association Shutdown. Association: %d\n", sri.sinfo_assoc_id); - m_s1ap->delete_enb_ctx(sri.sinfo_assoc_id); + int max_fd = std::max(s1mme, s11); + + FD_ZERO(&m_set); + FD_SET(s1mme, &m_set); + FD_SET(s11, &m_set); + + m_s1ap_log->debug("Waiting for S1-MME or S11 Message\n"); + int n = select(max_fd + 1, &m_set, NULL, NULL, NULL); + if (n == -1) { + m_s1ap_log->error("Error from select\n"); + } else if (n) { + // Handle S1-MME + if (FD_ISSET(s1mme, &m_set)) { + rd_sz = sctp_recvmsg(s1mme, pdu->msg, sz, (struct sockaddr*)&enb_addr, &fromlen, &sri, &msg_flags); + if (rd_sz == -1 && errno != EAGAIN) { + m_s1ap_log->error("Error reading from SCTP socket: %s", strerror(errno)); + } else if (rd_sz == -1 && errno == EAGAIN) { + m_s1ap_log->debug("Socket timeout reached"); + } else { + if (msg_flags & MSG_NOTIFICATION) { + // Received notification + union sctp_notification* notification = (union sctp_notification*)pdu->msg; + m_s1ap_log->debug("SCTP Notification %d\n", notification->sn_header.sn_type); + if (notification->sn_header.sn_type == SCTP_SHUTDOWN_EVENT) { + m_s1ap_log->info("SCTP Association Shutdown. Association: %d\n", sri.sinfo_assoc_id); + m_s1ap_log->console("SCTP Association Shutdown. Association: %d\n", sri.sinfo_assoc_id); + m_s1ap->delete_enb_ctx(sri.sinfo_assoc_id); + } + } else { + // Received data + pdu->N_bytes = rd_sz; + m_s1ap_log->info("Received S1AP msg. Size: %d\n", pdu->N_bytes); + m_s1ap->handle_s1ap_rx_pdu(pdu, &sri); + } } - } else { - // Received data - pdu->N_bytes = rd_sz; - m_s1ap_log->info("Received S1AP msg. Size: %d\n", pdu->N_bytes); - m_s1ap->handle_s1ap_rx_pdu(pdu, &sri); } + // Handle S11 + if (FD_ISSET(s11, &m_set)) { + pdu->N_bytes = recvfrom(s11, pdu->msg, SRSLTE_MAX_BUFFER_SIZE_BYTES, 0, NULL, NULL); + m_mme_gtpc->handle_s11_pdu(pdu); + } + } else { + m_s1ap_log->debug("No data from select.\n"); } } return; diff --git a/srsepc/src/mme/mme_gtpc.cc b/srsepc/src/mme/mme_gtpc.cc index 1de0d87c6..51127e001 100644 --- a/srsepc/src/mme/mme_gtpc.cc +++ b/srsepc/src/mme/mme_gtpc.cc @@ -126,8 +126,30 @@ bool mme_gtpc::init_s11() return true; } -void mme_gtpc::handle_s11_pdu(srslte::gtpc_pdu *pdu) +bool mme_gtpc::send_s11_pdu(const srslte::gtpc_pdu& pdu) { + int n; + m_mme_gtpc_log->debug("Sending S-11 GTP-C PDU\n"); + + // FIXME Add GTP-C serialization code + // Send S11 message to SPGW + n = sendto(m_s11, &pdu, sizeof(pdu), 0, (const sockaddr*)&m_spgw_addr, sizeof(m_spgw_addr)); + if (n < 0) { + m_mme_gtpc_log->error("Error sending to socket. Error %s\n", strerror(errno)); + m_mme_gtpc_log->console("Error sending to socket. Error %s\n", strerror(errno)); + return false; + } else { + m_mme_gtpc_log->debug("MME S11 Sent %d Bytes.\n", n); + } + return true; +} + +void mme_gtpc::handle_s11_pdu(srslte::byte_buffer_t *msg) +{ + m_mme_gtpc_log->debug("Received S11 message\n"); + + srslte::gtpc_pdu *pdu; + pdu = (srslte::gtpc_pdu *) msg->msg; m_mme_gtpc_log->debug("MME Received GTP-C PDU. Message type %s\n",srslte::gtpc_msg_type_to_str(pdu->header.type)); switch(pdu->header.type){ case srslte::GTPC_MSG_TYPE_CREATE_SESSION_RESPONSE: @@ -208,9 +230,7 @@ bool mme_gtpc::send_create_session_request(uint64_t imsi) m_imsi_to_gtpc_ctx.insert(std::pair(imsi, gtpc_ctx)); // Send msg to SPGW - srslte::gtpc_pdu mb_resp_pdu; - m_spgw->handle_s11_pdu(&cs_req_pdu, &cs_resp_pdu); - handle_s11_pdu(&cs_resp_pdu); + send_s11_pdu(cs_req_pdu); return true; } @@ -328,9 +348,7 @@ bool mme_gtpc::send_modify_bearer_request(uint64_t imsi, uint16_t erab_to_modify m_mme_gtpc_log->info("GTP-C Modify bearer request -- S1-U TEID 0x%x, IP %s\n", enb_fteid->teid, inet_ntoa(addr)); // Send msg to SPGW - srslte::gtpc_pdu mb_resp_pdu; - m_spgw->handle_s11_pdu(&mb_req_pdu, &mb_resp_pdu); - handle_s11_pdu(&mb_resp_pdu); + send_s11_pdu(mb_req_pdu); return true; } @@ -376,8 +394,7 @@ bool mme_gtpc::send_delete_session_request(uint64_t imsi) m_mme_gtpc_log->info("GTP-C Delete Session Request -- S-GW Control TEID %d\n", sgw_ctr_fteid.teid); // Send msg to SPGW - srslte::gtpc_pdu del_resp_pdu; - m_spgw->handle_s11_pdu(&del_req_pdu, &del_resp_pdu); + send_s11_pdu(del_req_pdu); // Delete GTP-C context std::map::iterator it_imsi = m_mme_ctr_teid_to_imsi.find(mme_ctr_fteid.teid); @@ -392,6 +409,7 @@ bool mme_gtpc::send_delete_session_request(uint64_t imsi) void mme_gtpc::send_release_access_bearers_request(uint64_t imsi) { + // The GTP-C connection will not be torn down, just the user plane bearers. m_mme_gtpc_log->info("Sending GTP-C Delete Access Bearers Request\n"); srslte::gtpc_pdu rel_req_pdu; srslte::gtp_fteid_t sgw_ctr_fteid; @@ -414,10 +432,8 @@ void mme_gtpc::send_release_access_bearers_request(uint64_t imsi) m_mme_gtpc_log->info("GTP-C Release Access Berarers Request -- S-GW Control TEID %d\n", sgw_ctr_fteid.teid); // Send msg to SPGW - srslte::gtpc_pdu rel_resp_pdu; - m_spgw->handle_s11_pdu(&rel_req_pdu, &rel_resp_pdu); + send_s11_pdu(rel_req_pdu); - // The GTP-C connection will not be torn down, just the user plane bearers. return; } diff --git a/srsepc/src/mme/s1ap_nas_transport.cc b/srsepc/src/mme/s1ap_nas_transport.cc index 97d90eb61..a2fb1d468 100644 --- a/srsepc/src/mme/s1ap_nas_transport.cc +++ b/srsepc/src/mme/s1ap_nas_transport.cc @@ -197,7 +197,7 @@ bool s1ap_nas_transport::handle_uplink_nas_transport(LIBLTE_S1AP_MESSAGE_UPLINKN mac_valid = nas_ctx->integrity_check(nas_msg); if (mac_valid == false) { m_s1ap_log->warning("Invalid MAC message. Even if security header indicates integrity protection (Maybe: " - "Identity Response or Authenticatio Response)\n"); + "Identity Response or Authentication Response)\n"); } } diff --git a/srsepc/src/spgw/gtpc.cc b/srsepc/src/spgw/gtpc.cc index c21b751d9..ebf1d93c4 100644 --- a/srsepc/src/spgw/gtpc.cc +++ b/srsepc/src/spgw/gtpc.cc @@ -133,22 +133,40 @@ srslte::error_t spgw::gtpc::init_s11(spgw_args_t* args) return srslte::ERROR_NONE; } -void spgw::gtpc::handle_s11_pdu(srslte::gtpc_pdu* pdu, srslte::gtpc_pdu* reply_pdu) +bool spgw::gtpc::send_s11_pdu(const srslte::gtpc_pdu& pdu) { + m_gtpc_log->debug("SPGW Sending S11 PDU! N_Bytes: %lu\n", sizeof(pdu)); + + // FIXME add serialization code here + // Send S11 message to MME + int n = sendto(m_s11, &pdu, sizeof(pdu), 0, (const sockaddr*)&m_mme_addr, sizeof(m_mme_addr)); + if (n < 0) { + m_gtpc_log->error("Error sending to socket. Error %s", strerror(errno)); + return false; + } else { + m_gtpc_log->debug("SPGW S11 Sent %d Bytes.\n", n); + } + return true; +} + +void spgw::gtpc::handle_s11_pdu(srslte::byte_buffer_t* msg) +{ + //FIXME add deserialization code here + srslte::gtpc_pdu *pdu = (srslte::gtpc_pdu*) msg->msg; m_gtpc_log->console("Received GTP-C PDU. Message type: %s\n", srslte::gtpc_msg_type_to_str(pdu->header.type)); m_gtpc_log->debug("Received GTP-C PDU. Message type: %s\n", srslte::gtpc_msg_type_to_str(pdu->header.type)); switch (pdu->header.type) { case srslte::GTPC_MSG_TYPE_CREATE_SESSION_REQUEST: - handle_create_session_request(pdu->choice.create_session_request, reply_pdu); + handle_create_session_request(pdu->choice.create_session_request); break; case srslte::GTPC_MSG_TYPE_MODIFY_BEARER_REQUEST: - handle_modify_bearer_request(pdu->header, pdu->choice.modify_bearer_request, reply_pdu); + handle_modify_bearer_request(pdu->header, pdu->choice.modify_bearer_request); break; case srslte::GTPC_MSG_TYPE_DELETE_SESSION_REQUEST: - handle_delete_session_request(pdu->header, pdu->choice.delete_session_request, reply_pdu); + handle_delete_session_request(pdu->header, pdu->choice.delete_session_request); break; case srslte::GTPC_MSG_TYPE_RELEASE_ACCESS_BEARERS_REQUEST: - handle_release_access_bearers_request(pdu->header, pdu->choice.release_access_bearers_request, reply_pdu); + handle_release_access_bearers_request(pdu->header, pdu->choice.release_access_bearers_request); break; default: m_gtpc_log->error("Unhandled GTP-C message type\n"); @@ -156,7 +174,7 @@ void spgw::gtpc::handle_s11_pdu(srslte::gtpc_pdu* pdu, srslte::gtpc_pdu* reply_p return; } -void spgw::gtpc::handle_create_session_request(const struct srslte::gtpc_create_session_request& cs_req, srslte::gtpc_pdu *cs_resp_pdu) +void spgw::gtpc::handle_create_session_request(const struct srslte::gtpc_create_session_request& cs_req) { m_gtpc_log->info("SPGW Received Create Session Request\n"); spgw_tunnel_ctx_t* tunnel_ctx; @@ -173,8 +191,9 @@ void spgw::gtpc::handle_create_session_request(const struct srslte::gtpc_create_ tunnel_ctx = create_gtpc_ctx(cs_req); // Create session response message - srslte::gtpc_header* header = &cs_resp_pdu->header; - srslte::gtpc_create_session_response* cs_resp = &cs_resp_pdu->choice.create_session_response; + srslte::gtpc_pdu cs_resp_pdu; + srslte::gtpc_header* header = &cs_resp_pdu.header; + srslte::gtpc_create_session_response* cs_resp = &cs_resp_pdu.choice.create_session_response; // Setup GTP-C header header->piggyback = false; @@ -204,12 +223,12 @@ void spgw::gtpc::handle_create_session_request(const struct srslte::gtpc_create_ m_gtpc_log->info("Sending Create Session Response\n"); // Send Create session response to MME + send_s11_pdu(cs_resp_pdu); return; } void spgw::gtpc::handle_modify_bearer_request(const struct srslte::gtpc_header& mb_req_hdr, - const struct srslte::gtpc_modify_bearer_request& mb_req, - srslte::gtpc_pdu* mb_resp_pdu) + const struct srslte::gtpc_modify_bearer_request& mb_req) { m_gtpc_log->info("Received Modified Bearer Request\n"); @@ -247,25 +266,25 @@ void spgw::gtpc::handle_modify_bearer_request(const struct srslte::gtpc_header& // Setting up Modify bearer response PDU // Header - srslte::gtpc_header* header = &mb_resp_pdu->header; + srslte::gtpc_pdu mb_resp_pdu; + srslte::gtpc_header* header = &mb_resp_pdu.header; header->piggyback = false; header->teid_present = true; header->teid = tunnel_ctx->dw_ctrl_fteid.teid; header->type = srslte::GTPC_MSG_TYPE_MODIFY_BEARER_RESPONSE; // PDU - srslte::gtpc_modify_bearer_response* mb_resp = &mb_resp_pdu->choice.modify_bearer_response; + srslte::gtpc_modify_bearer_response* mb_resp = &mb_resp_pdu.choice.modify_bearer_response; mb_resp->cause.cause_value = srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED; mb_resp->eps_bearer_context_modified.ebi = tunnel_ctx->ebi; mb_resp->eps_bearer_context_modified.cause.cause_value = srslte::GTPC_CAUSE_VALUE_REQUEST_ACCEPTED; - + //Send Modify Bearer Response PDU return; } void spgw::gtpc::handle_delete_session_request(const srslte::gtpc_header& header, - const srslte::gtpc_delete_session_request& del_req_pdu, - srslte::gtpc_pdu* del_resp_pdu) + const srslte::gtpc_delete_session_request& del_req_pdu) { uint32_t ctrl_teid = header.teid; std::map::iterator tunnel_it = m_teid_to_tunnel_ctx.find(ctrl_teid); @@ -281,8 +300,7 @@ void spgw::gtpc::handle_delete_session_request(const srslte::gtpc_header& } void spgw::gtpc::handle_release_access_bearers_request(const srslte::gtpc_header& header, - const srslte::gtpc_release_access_bearers_request& rel_req, - srslte::gtpc_pdu* rel_resp_pdu) + const srslte::gtpc_release_access_bearers_request& rel_req) { // Find tunel ctxt uint32_t ctrl_teid = header.teid; diff --git a/srsepc/src/spgw/spgw.cc b/srsepc/src/spgw/spgw.cc index 9dcc369ea..5b447a6e0 100644 --- a/srsepc/src/spgw/spgw.cc +++ b/srsepc/src/spgw/spgw.cc @@ -121,32 +121,44 @@ void spgw::run_thread() srslte::byte_buffer_t* msg; msg = m_pool->allocate(); - struct sockaddr src_addr; + struct sockaddr_in src_addr_in; + struct sockaddr_un src_addr_un; socklen_t addrlen; struct iphdr* ip_pkt; - int sgi = m_gtpu->get_sgi(); - int s1u = m_gtpu->get_s1u(); + + int sgi = m_gtpu->get_sgi(); + int s1u = m_gtpu->get_s1u(); + int s11 = m_gtpc->get_s11(); + + size_t buf_len = SRSLTE_MAX_BUFFER_SIZE_BYTES - SRSLTE_BUFFER_HEADER_OFFSET; fd_set set; int max_fd = std::max(s1u, sgi); + max_fd = std::max(max_fd, s11); while (m_running) { msg->reset(); FD_ZERO(&set); FD_SET(s1u, &set); FD_SET(sgi, &set); + FD_SET(s11, &set); int n = select(max_fd + 1, &set, NULL, NULL, NULL); if (n == -1) { m_spgw_log->error("Error from select\n"); } else if (n) { if (FD_ISSET(s1u, &set)) { - msg->N_bytes = recvfrom(s1u, msg->msg, SRSLTE_MAX_BUFFER_SIZE_BYTES, 0, &src_addr, &addrlen); + msg->N_bytes = recvfrom(s1u, msg->msg, buf_len, 0, (struct sockaddr*)&src_addr_in, &addrlen); m_gtpu->handle_s1u_pdu(msg); } if (FD_ISSET(sgi, &set)) { - msg->N_bytes = read(sgi, msg->msg, SRSLTE_MAX_BUFFER_SIZE_BYTES); + msg->N_bytes = read(sgi, msg->msg, buf_len); m_gtpu->handle_sgi_pdu(msg); } + if (FD_ISSET(s11, &set)) { + m_spgw_log->debug("Message received at SPGW: S11 Message\n"); + msg->N_bytes = recvfrom(s11, msg->msg, buf_len, 0, (struct sockaddr*)&src_addr_un, &addrlen); + m_gtpc->handle_s11_pdu(msg); + } } else { m_spgw_log->debug("No data from select.\n"); } @@ -155,7 +167,4 @@ void spgw::run_thread() return; } -void spgw::handle_s11_pdu(srslte::gtpc_pdu *pdu, srslte::gtpc_pdu *reply_pdu){ - m_gtpc->handle_s11_pdu(pdu, reply_pdu); -} } // namespace srsepc