/******************************************************************************* OpenAirInterface Copyright(c) 1999 - 2014 Eurecom OpenAirInterface is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenAirInterface 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 General Public License for more details. You should have received a copy of the GNU General Public License along with OpenAirInterface.The full GNU General Public License is included in this distribution in the file called "COPYING". If not, see <http://www.gnu.org/licenses/>. Contact Information OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France. *******************************************************************************/ /*! \file sgw_lite_handlers.c * \brief * \author Lionel Gauthier * \company Eurecom * \email: lionel.gauthier@eurecom.fr */ #define SGW_LITE #define SGW_LITE_HANDLERS_C #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <string.h> #include <netinet/in.h> #include "assertions.h" #include "conversions.h" #include "common_types.h" #include "intertask_interface.h" #include "mme_config.h" #include "sgw_lite_defs.h" #include "sgw_lite_handlers.h" #include "sgw_lite_context_manager.h" #include "sgw_lite.h" #include "pgw_lite_paa.h" extern sgw_app_t sgw_app; int sgw_lite_handle_create_session_request( const SgwCreateSessionRequest * const session_req_pP) { mme_sgw_tunnel_t* new_endpoint_p = NULL; s_plus_p_gw_eps_bearer_context_information_t* s_plus_p_gw_eps_bearer_ctxt_info_p = NULL; sgw_eps_bearer_entry_t* eps_bearer_entry_p = NULL; MessageDef* message_p = NULL; /* Upon reception of create session request from MME, * S-GW should create UE, eNB and MME contexts and forward message to P-GW. */ if (session_req_pP->rat_type != RAT_EUTRAN) { SPGW_APP_WARN("Received session request with RAT != RAT_TYPE_EUTRAN: type %d\n", session_req_pP->rat_type); } /* As we are abstracting GTP-C transport, FTeid ip address is useless. * We just use the teid to identify MME tunnel. Normally we received either: * - ipv4 address if ipv4 flag is set * - ipv6 address if ipv6 flag is set * - ipv4 and ipv6 if both flags are set * Communication between MME and S-GW involves S11 interface so we are expecting * S11_MME_GTP_C (11) as interface_type. */ if ((session_req_pP->sender_fteid_for_cp.teid == 0) && (session_req_pP->sender_fteid_for_cp.interface_type != S11_MME_GTP_C)) { /* MME sent request with teid = 0. This is not valid... */ SPGW_APP_WARN("F-TEID parameter mismatch\n"); return -1; } new_endpoint_p = sgw_lite_cm_create_s11_tunnel( session_req_pP->sender_fteid_for_cp.teid, sgw_lite_get_new_S11_tunnel_id()); if (new_endpoint_p == NULL) { SPGW_APP_WARN("Could not create new tunnel endpoint between S-GW and MME " "for S11 abstraction\n"); return -1; } SPGW_APP_DEBUG("Rx CREATE-SESSION-REQUEST MME S11 teid %u S-GW S11 teid %u APN %s EPS bearer Id %d\n", new_endpoint_p->remote_teid, new_endpoint_p->local_teid, session_req_pP->apn, session_req_pP->bearer_to_create.eps_bearer_id); SPGW_APP_DEBUG(" IMSI %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", IMSI(&session_req_pP->imsi)); s_plus_p_gw_eps_bearer_ctxt_info_p = sgw_lite_cm_create_bearer_context_information_in_collection(new_endpoint_p->local_teid); if (s_plus_p_gw_eps_bearer_ctxt_info_p != NULL) { /* We try to create endpoint for S11 interface. A NULL endpoint means that * either the teid is already in list of known teid or ENOMEM error has been * raised during malloc. */ //-------------------------------------------------- // copy informations from create session request to bearer context information //-------------------------------------------------- memcpy(s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.imsi.digit, session_req_pP->imsi.digit, IMSI_DIGITS_MAX); memcpy(s_plus_p_gw_eps_bearer_ctxt_info_p->pgw_eps_bearer_context_information.imsi.digit, session_req_pP->imsi.digit, IMSI_DIGITS_MAX); s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.imsi_unauthenticated_indicator = 1; s_plus_p_gw_eps_bearer_ctxt_info_p->pgw_eps_bearer_context_information.imsi_unauthenticated_indicator = 1; s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.mme_teid_for_S11 = session_req_pP->sender_fteid_for_cp.teid; s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.s_gw_teid_for_S11_S4 = new_endpoint_p->local_teid; s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.trxn = session_req_pP->trxn; s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.peer_ip = session_req_pP->peer_ip; // may use ntohl or reverse, will see FTEID_T_2_IP_ADDRESS_T( (&session_req_pP->sender_fteid_for_cp) , (&s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.mme_ip_address_for_S11)); //-------------------------------------- // PDN connection //-------------------------------------- /*pdn_connection = sgw_lite_cm_create_pdn_connection(); if (pdn_connection == NULL) { // Malloc failed, may be ENOMEM error SPGW_APP_ERROR("Failed to create new PDN connection\n"); return -1; }*/ memset(&s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.pdn_connection, 0, sizeof(sgw_pdn_connection_t)); s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers = hashtable_create(12, NULL, NULL); if ( s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers == NULL) { SPGW_APP_ERROR("Failed to create eps bearers collection object\n"); DevMessage("Failed to create eps bearers collection object\n"); return -1; } if (session_req_pP->apn) { s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.pdn_connection.apn_in_use = strdup(session_req_pP->apn); } else { s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.pdn_connection.apn_in_use = "NO APN"; } s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.pdn_connection.default_bearer = session_req_pP->bearer_to_create.eps_bearer_id; //obj_hashtable_insert(s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.pdn_connections, pdn_connection->apn_in_use, strlen(pdn_connection->apn_in_use), pdn_connection); //-------------------------------------- // EPS bearer entry //-------------------------------------- eps_bearer_entry_p = sgw_lite_cm_create_eps_bearer_entry_in_collection( s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers, session_req_pP->bearer_to_create.eps_bearer_id); sgw_lite_display_s11teid2mme_mappings(); sgw_lite_display_s11_bearer_context_information_mapping(); if (eps_bearer_entry_p == NULL) { SPGW_APP_ERROR("Failed to create new EPS bearer entry\n"); // TO DO FREE new_bearer_ctxt_info_p and by cascade... return -1; } eps_bearer_entry_p->eps_bearer_qos = session_req_pP->bearer_to_create.bearer_level_qos; //s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_informationteid = teid; /* Trying to insert the new tunnel into the tree. * If collision_p is not NULL (0), it means tunnel is already present. */ //s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_informations_gw_ip_address_for_S11_S4 = memcpy(&s_plus_p_gw_eps_bearer_ctxt_info_p->sgw_eps_bearer_context_information.saved_message, session_req_pP, sizeof(SgwCreateSessionRequest)); /* Establishing EPS bearer. Requesting S1-U (GTPV1-U) task to create a * tunnel for S1 user plane interface. If status in response is successfull (0), * the tunnel endpoint is locally ready. */ message_p = itti_alloc_new_message(TASK_SPGW_APP, GTPV1U_CREATE_TUNNEL_REQ); if (message_p == NULL) { sgw_lite_cm_remove_s11_tunnel(new_endpoint_p->remote_teid); return -1; } message_p->ittiMsg.gtpv1uCreateTunnelReq.context_teid = new_endpoint_p->local_teid; message_p->ittiMsg.gtpv1uCreateTunnelReq.eps_bearer_id = session_req_pP->bearer_to_create.eps_bearer_id; SPGW_APP_DEBUG("Tx GTPV1U_CREATE_TUNNEL_REQ -> TASK_GTPV1_U, Context: S-GW S11 teid %u eps bearer id %d (from session req)\n", message_p->ittiMsg.gtpv1uCreateTunnelReq.context_teid, message_p->ittiMsg.gtpv1uCreateTunnelReq.eps_bearer_id); return itti_send_msg_to_task(TASK_GTPV1_U, INSTANCE_DEFAULT, message_p); } else { SPGW_APP_WARN("Could not create new transaction for SESSION_CREATE message\n"); free(new_endpoint_p); new_endpoint_p = NULL; return -1; } } int sgw_lite_handle_sgi_endpoint_created( const SGICreateEndpointResp * const resp_pP) { task_id_t to_task; SgwCreateSessionResponse *create_session_response_p = NULL; s_plus_p_gw_eps_bearer_context_information_t *new_bearer_ctxt_info_p = NULL; MessageDef *message_p = NULL; hashtable_rc_t hash_rc; SPGW_APP_DEBUG("Rx SGI_CREATE_ENDPOINT_RESPONSE,Context: S11 teid %u, SGW S1U teid %u EPS bearer id %u\n", resp_pP->context_teid, resp_pP->sgw_S1u_teid, resp_pP->eps_bearer_id); hash_rc = hashtable_get(sgw_app.s11_bearer_context_information_hashtable, resp_pP->context_teid, (void**)&new_bearer_ctxt_info_p); #if defined(ENABLE_STANDALONE_EPC) to_task = TASK_MME_APP; #else to_task = TASK_S11; #endif message_p = itti_alloc_new_message(TASK_SPGW_APP, SGW_CREATE_SESSION_RESPONSE); if (message_p == NULL) { return -1; } create_session_response_p = &message_p->ittiMsg.sgwCreateSessionResponse; memset(create_session_response_p, 0, sizeof(SgwCreateSessionResponse)); if (hash_rc == HASH_TABLE_OK) { create_session_response_p->teid = new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.mme_teid_for_S11; /* Preparing to send create session response on S11 abstraction interface. * we set the cause value regarding the S1-U bearer establishment result status. */ if (resp_pP->status == 0) { uint32_t address = sgw_app.sgw_ip_address_for_S1u_S12_S4_up; create_session_response_p->bearer_context_created.s1u_sgw_fteid.teid = resp_pP->sgw_S1u_teid; create_session_response_p->bearer_context_created.s1u_sgw_fteid.interface_type = S1_U_SGW_GTP_U; create_session_response_p->bearer_context_created.s1u_sgw_fteid.ipv4 = 1; /* Should be filled in with S-GW S1-U local address. Running everything on localhost for now */ create_session_response_p->bearer_context_created.s1u_sgw_fteid.ipv4_address = address; memcpy(&create_session_response_p->paa, &resp_pP->paa, sizeof(PAA_t)); /* Set the Cause information from bearer context created. * "Request accepted" is returned when the GTPv2 entity has accepted a control plane request. */ create_session_response_p->cause = REQUEST_ACCEPTED; create_session_response_p->bearer_context_created.cause = REQUEST_ACCEPTED; } else { create_session_response_p->cause = M_PDN_APN_NOT_ALLOWED; create_session_response_p->bearer_context_created.cause = M_PDN_APN_NOT_ALLOWED; } create_session_response_p->s11_sgw_teid.teid = resp_pP->context_teid; create_session_response_p->bearer_context_created.eps_bearer_id = resp_pP->eps_bearer_id; create_session_response_p->trxn = new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.trxn; create_session_response_p->peer_ip = new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.peer_ip; } else { create_session_response_p->cause = CONTEXT_NOT_FOUND; create_session_response_p->bearer_context_created.cause = CONTEXT_NOT_FOUND; } SPGW_APP_DEBUG("Tx CREATE-SESSION-RESPONSE MME -> %s, S11 MME teid %u S11 S-GW teid %u S1U teid %u S1U addr 0x%x EPS bearer id %u status %d\n", to_task == TASK_MME_APP ? "TASK_MME_APP" : "TASK_S11", create_session_response_p->teid, create_session_response_p->s11_sgw_teid.teid, create_session_response_p->bearer_context_created.s1u_sgw_fteid.teid, create_session_response_p->bearer_context_created.s1u_sgw_fteid.ipv4_address, create_session_response_p->bearer_context_created.eps_bearer_id, create_session_response_p->bearer_context_created.cause); return itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p); } int sgw_lite_handle_gtpv1uCreateTunnelResp( const Gtpv1uCreateTunnelResp * const endpoint_created_pP) { task_id_t to_task; SgwCreateSessionResponse *create_session_response_p = NULL; s_plus_p_gw_eps_bearer_context_information_t *new_bearer_ctxt_info_p = NULL; SGICreateEndpointReq *sgi_create_endpoint_req_p = NULL; MessageDef *message_p = NULL; sgw_eps_bearer_entry_t *eps_bearer_entry_p = NULL; hashtable_rc_t hash_rc; struct in_addr inaddr ; struct in6_addr in6addr = IN6ADDR_ANY_INIT; #if defined(ENABLE_STANDALONE_EPC) to_task = TASK_MME_APP; #else to_task = TASK_S11; #endif SPGW_APP_DEBUG("Rx GTPV1U_CREATE_TUNNEL_RESP, Context S-GW S11 teid %u, S-GW S1U teid %u EPS bearer id %u status %d\n", endpoint_created_pP->context_teid, endpoint_created_pP->S1u_teid, endpoint_created_pP->eps_bearer_id, endpoint_created_pP->status); hash_rc = hashtable_get( sgw_app.s11_bearer_context_information_hashtable, endpoint_created_pP->context_teid, (void**)&new_bearer_ctxt_info_p); if (hash_rc == HASH_TABLE_OK) { hash_rc = hashtable_get ( new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers, endpoint_created_pP->eps_bearer_id, (void**)&eps_bearer_entry_p); DevAssert(hash_rc == HASH_TABLE_OK); SPGW_APP_DEBUG("Updated eps_bearer_entry_p eps_b_id %u with SGW S1U teid %u\n", endpoint_created_pP->eps_bearer_id, endpoint_created_pP->S1u_teid); eps_bearer_entry_p->s_gw_teid_for_S1u_S12_S4_up = endpoint_created_pP->S1u_teid; sgw_lite_display_s11_bearer_context_information_mapping(); /* SEND IP_FW_CREATE_IP_ENDPOINT_REQUEST to FW_IP task */ message_p = itti_alloc_new_message(TASK_SPGW_APP, SGI_CREATE_ENDPOINT_REQUEST); if (message_p == NULL) { return -1; } sgi_create_endpoint_req_p = &message_p->ittiMsg.sgiCreateEndpointReq; memset(sgi_create_endpoint_req_p, 0, sizeof(SGICreateEndpointReq)); // IP forward will forward packets to this teid sgi_create_endpoint_req_p->context_teid = endpoint_created_pP->context_teid; sgi_create_endpoint_req_p->sgw_S1u_teid = endpoint_created_pP->S1u_teid; sgi_create_endpoint_req_p->eps_bearer_id = endpoint_created_pP->eps_bearer_id; // TO DO NOW sgi_create_endpoint_req_p->paa.pdn_type = new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.saved_message.pdn_type; switch (sgi_create_endpoint_req_p->paa.pdn_type) { case IPv4_OR_v6: if (pgw_lite_get_free_ipv4_paa_address(&inaddr) == 0) { IN_ADDR_TO_BUFFER(inaddr, sgi_create_endpoint_req_p->paa.ipv4_address); } else { SPGW_APP_WARN("Failed to allocate IPv4 PAA for PDN type IPv4_OR_v6\n"); if (pgw_lite_get_free_ipv6_paa_prefix(&in6addr) == 0) { IN6_ADDR_TO_BUFFER(in6addr, sgi_create_endpoint_req_p->paa.ipv6_address); } else { SPGW_APP_ERROR("Failed to allocate IPv6 PAA for PDN type IPv4_OR_v6\n"); } } break; case IPv4: if (pgw_lite_get_free_ipv4_paa_address(&inaddr) == 0) { IN_ADDR_TO_BUFFER(inaddr, sgi_create_endpoint_req_p->paa.ipv4_address); } else { SPGW_APP_ERROR("Failed to allocate IPv4 PAA for PDN type IPv4\n"); } break; case IPv6: if (pgw_lite_get_free_ipv6_paa_prefix(&in6addr) == 0) { IN6_ADDR_TO_BUFFER(in6addr, sgi_create_endpoint_req_p->paa.ipv6_address); } else { SPGW_APP_ERROR("Failed to allocate IPv6 PAA for PDN type IPv6\n"); } break; case IPv4_AND_v6: if (pgw_lite_get_free_ipv4_paa_address(&inaddr) == 0) { IN_ADDR_TO_BUFFER(inaddr, sgi_create_endpoint_req_p->paa.ipv4_address); } else { SPGW_APP_ERROR("Failed to allocate IPv4 PAA for PDN type IPv4_AND_v6\n"); } if (pgw_lite_get_free_ipv6_paa_prefix(&in6addr) == 0) { IN6_ADDR_TO_BUFFER(in6addr, sgi_create_endpoint_req_p->paa.ipv6_address); } else { SPGW_APP_ERROR("Failed to allocate IPv6 PAA for PDN type IPv4_AND_v6\n"); } break; default: AssertFatal(0,"BAD paa.pdn_type %d", sgi_create_endpoint_req_p->paa.pdn_type); break; } // TO DO TFT, QOS return itti_send_msg_to_task(TASK_FW_IP, INSTANCE_DEFAULT, message_p); } else { SPGW_APP_DEBUG("Rx SGW_S1U_ENDPOINT_CREATED, Context: teid %u NOT FOUND\n", endpoint_created_pP->context_teid); message_p = itti_alloc_new_message(TASK_SPGW_APP, SGW_CREATE_SESSION_RESPONSE); if (message_p == NULL) { return -1; } create_session_response_p = &message_p->ittiMsg.sgwCreateSessionResponse; memset(create_session_response_p, 0, sizeof(SgwCreateSessionResponse)); create_session_response_p->cause = CONTEXT_NOT_FOUND; create_session_response_p->bearer_context_created.cause = CONTEXT_NOT_FOUND; return itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p); } } int sgw_lite_handle_gtpv1uUpdateTunnelResp( const Gtpv1uUpdateTunnelResp * const endpoint_updated_pP) { SgwModifyBearerResponse *modify_response_p = NULL; SGIUpdateEndpointReq *update_request_p = NULL; s_plus_p_gw_eps_bearer_context_information_t *new_bearer_ctxt_info_p = NULL; MessageDef *message_p = NULL; sgw_eps_bearer_entry_t *eps_bearer_entry_p = NULL; hashtable_rc_t hash_rc; task_id_t to_task; #if defined(ENABLE_STANDALONE_EPC) to_task = TASK_MME_APP; #else to_task = TASK_S11; #endif SPGW_APP_DEBUG("Rx GTPV1U_UPDATE_TUNNEL_RESP, Context teid %u, SGW S1U teid %u, eNB S1U teid %u, EPS bearer id %u, status %d\n", endpoint_updated_pP->context_teid, endpoint_updated_pP->sgw_S1u_teid, endpoint_updated_pP->enb_S1u_teid, endpoint_updated_pP->eps_bearer_id, endpoint_updated_pP->status); hash_rc = hashtable_get(sgw_app.s11_bearer_context_information_hashtable, endpoint_updated_pP->context_teid, (void**)&new_bearer_ctxt_info_p); if (hash_rc == HASH_TABLE_OK) { hash_rc = hashtable_get (new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers, endpoint_updated_pP->eps_bearer_id, (void**)&eps_bearer_entry_p); if ((hash_rc == HASH_TABLE_KEY_NOT_EXISTS) || (hash_rc == HASH_TABLE_BAD_PARAMETER_HASHTABLE)) { SPGW_APP_DEBUG("Sending SGW_MODIFY_BEARER_RESPONSE trxn %p bearer %u CONTEXT_NOT_FOUND (sgw_eps_bearers)\n", new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.trxn, endpoint_updated_pP->eps_bearer_id); message_p = itti_alloc_new_message(TASK_SPGW_APP, SGW_MODIFY_BEARER_RESPONSE); if (message_p == NULL) { return -1; } modify_response_p = &message_p->ittiMsg.sgwModifyBearerResponse; memset(modify_response_p, 0, sizeof(SgwModifyBearerResponse)); modify_response_p->bearer_present = MODIFY_BEARER_RESPONSE_REM; modify_response_p->bearer_choice.bearer_for_removal.eps_bearer_id = endpoint_updated_pP->eps_bearer_id; modify_response_p->bearer_choice.bearer_for_removal.cause = CONTEXT_NOT_FOUND; modify_response_p->cause = CONTEXT_NOT_FOUND; modify_response_p->trxn = new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.trxn; return itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p); } else if (hash_rc == HASH_TABLE_OK) { message_p = itti_alloc_new_message(TASK_SPGW_APP, SGI_UPDATE_ENDPOINT_REQUEST); if (message_p == NULL) { return -1; } update_request_p = &message_p->ittiMsg.sgiUpdateEndpointReq; memset(update_request_p, 0, sizeof(SGIUpdateEndpointReq)); update_request_p->context_teid = endpoint_updated_pP->context_teid; update_request_p->sgw_S1u_teid = endpoint_updated_pP->sgw_S1u_teid; update_request_p->enb_S1u_teid = endpoint_updated_pP->enb_S1u_teid; update_request_p->eps_bearer_id = endpoint_updated_pP->eps_bearer_id; return itti_send_msg_to_task(TASK_FW_IP, INSTANCE_DEFAULT, message_p); } } else { SPGW_APP_DEBUG("Sending SGW_MODIFY_BEARER_RESPONSE trxn %p bearer %u CONTEXT_NOT_FOUND (s11_bearer_context_information_hashtable)\n", new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.trxn, endpoint_updated_pP->eps_bearer_id); message_p = itti_alloc_new_message(TASK_SPGW_APP, SGW_MODIFY_BEARER_RESPONSE); if (message_p == NULL) { return -1; } modify_response_p = &message_p->ittiMsg.sgwModifyBearerResponse; memset(modify_response_p, 0, sizeof(SgwModifyBearerResponse)); modify_response_p->bearer_present = MODIFY_BEARER_RESPONSE_REM; modify_response_p->bearer_choice.bearer_for_removal.eps_bearer_id = endpoint_updated_pP->eps_bearer_id; modify_response_p->bearer_choice.bearer_for_removal.cause = CONTEXT_NOT_FOUND; modify_response_p->cause = CONTEXT_NOT_FOUND; modify_response_p->trxn = new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.trxn; return itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p); } return -1; } int sgw_lite_handle_sgi_endpoint_updated( const SGIUpdateEndpointResp * const resp_pP) { SgwModifyBearerResponse *modify_response_p = NULL; s_plus_p_gw_eps_bearer_context_information_t *new_bearer_ctxt_info_p = NULL; MessageDef *message_p = NULL; sgw_eps_bearer_entry_t *eps_bearer_entry_p = NULL; hashtable_rc_t hash_rc; task_id_t to_task; #if defined(ENABLE_STANDALONE_EPC) to_task = TASK_MME_APP; #else to_task = TASK_S11; #endif SPGW_APP_DEBUG("Rx SGI_UPDATE_ENDPOINT_RESPONSE, Context teid %u, SGW S1U teid %u, eNB S1U teid %u, EPS bearer id %u, status %d\n", resp_pP->context_teid, resp_pP->sgw_S1u_teid, resp_pP->enb_S1u_teid, resp_pP->eps_bearer_id, resp_pP->status); message_p = itti_alloc_new_message(TASK_SPGW_APP, SGW_MODIFY_BEARER_RESPONSE); if (message_p == NULL) { return -1; } modify_response_p = &message_p->ittiMsg.sgwModifyBearerResponse; memset(modify_response_p, 0, sizeof(SgwModifyBearerResponse)); hash_rc = hashtable_get(sgw_app.s11_bearer_context_information_hashtable, resp_pP->context_teid, (void**)&new_bearer_ctxt_info_p); if (hash_rc == HASH_TABLE_OK) { hash_rc = hashtable_get (new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers, resp_pP->eps_bearer_id, (void**)&eps_bearer_entry_p); if ((hash_rc == HASH_TABLE_KEY_NOT_EXISTS) || (hash_rc == HASH_TABLE_BAD_PARAMETER_HASHTABLE)) { SPGW_APP_DEBUG("Rx SGI_UPDATE_ENDPOINT_RESPONSE: CONTEXT_NOT_FOUND (pdn_connection.sgw_eps_bearers context)\n"); modify_response_p->teid = resp_pP->context_teid; // TO BE CHECKED IF IT IS THIS TEID modify_response_p->bearer_present = MODIFY_BEARER_RESPONSE_REM; modify_response_p->bearer_choice.bearer_for_removal.eps_bearer_id = resp_pP->eps_bearer_id; modify_response_p->bearer_choice.bearer_for_removal.cause = CONTEXT_NOT_FOUND; modify_response_p->cause = CONTEXT_NOT_FOUND; modify_response_p->trxn = 0; return itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p); } else if (hash_rc == HASH_TABLE_OK) { SPGW_APP_DEBUG("Rx SGI_UPDATE_ENDPOINT_RESPONSE: REQUEST_ACCEPTED\n"); // accept anyway modify_response_p->teid = resp_pP->context_teid; // TO BE CHECKED IF IT IS THIS TEID modify_response_p->bearer_present = MODIFY_BEARER_RESPONSE_MOD; modify_response_p->bearer_choice.bearer_contexts_modified.eps_bearer_id = resp_pP->eps_bearer_id; modify_response_p->bearer_choice.bearer_contexts_modified.cause = REQUEST_ACCEPTED; modify_response_p->cause = REQUEST_ACCEPTED; modify_response_p->trxn = new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.trxn; } return itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p); } else { SPGW_APP_DEBUG("Rx SGI_UPDATE_ENDPOINT_RESPONSE: CONTEXT_NOT_FOUND (S11 context)\n"); modify_response_p->teid = resp_pP->context_teid; // TO BE CHECKED IF IT IS THIS TEID modify_response_p->bearer_present = MODIFY_BEARER_RESPONSE_REM; modify_response_p->bearer_choice.bearer_for_removal.eps_bearer_id = resp_pP->eps_bearer_id; modify_response_p->bearer_choice.bearer_for_removal.cause = CONTEXT_NOT_FOUND; modify_response_p->cause = CONTEXT_NOT_FOUND; modify_response_p->trxn = 0; return itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p); } } int sgw_lite_handle_modify_bearer_request( const SgwModifyBearerRequest * const modify_bearer_pP) { SgwModifyBearerResponse *modify_response_p = NULL; Gtpv1uUpdateTunnelReq *gtpv1u_update_tunnel_req_p = NULL; s_plus_p_gw_eps_bearer_context_information_t *new_bearer_ctxt_info_p = NULL; MessageDef *message_p = NULL; sgw_eps_bearer_entry_t *eps_bearer_entry_p = NULL; hashtable_rc_t hash_rc; task_id_t to_task; #if defined(ENABLE_STANDALONE_EPC) to_task = TASK_MME_APP; #else to_task = TASK_S11; #endif SPGW_APP_DEBUG("Rx MODIFY_BEARER_REQUEST, teid %u, EPS bearer id %u\n", modify_bearer_pP->teid, modify_bearer_pP->bearer_context_to_modify.eps_bearer_id); sgw_lite_display_s11teid2mme_mappings(); sgw_lite_display_s11_bearer_context_information_mapping(); hash_rc = hashtable_get( sgw_app.s11_bearer_context_information_hashtable, modify_bearer_pP->teid, (void**)&new_bearer_ctxt_info_p); if (hash_rc == HASH_TABLE_OK) { new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.pdn_connection.default_bearer = modify_bearer_pP->bearer_context_to_modify.eps_bearer_id; new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.trxn = modify_bearer_pP->trxn; hash_rc = hashtable_is_key_exists ( new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers, modify_bearer_pP->bearer_context_to_modify.eps_bearer_id); if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) { message_p = itti_alloc_new_message(TASK_SPGW_APP, SGW_MODIFY_BEARER_RESPONSE); if (message_p == NULL) { return -1; } modify_response_p = &message_p->ittiMsg.sgwModifyBearerResponse; memset(modify_response_p, 0, sizeof(SgwModifyBearerResponse)); modify_response_p->bearer_present = MODIFY_BEARER_RESPONSE_REM; modify_response_p->bearer_choice.bearer_for_removal.eps_bearer_id = modify_bearer_pP->bearer_context_to_modify.eps_bearer_id; modify_response_p->bearer_choice.bearer_for_removal.cause = CONTEXT_NOT_FOUND; modify_response_p->cause = CONTEXT_NOT_FOUND; modify_response_p->trxn = modify_bearer_pP->trxn; SPGW_APP_DEBUG("Rx MODIFY_BEARER_REQUEST, eps_bearer_id %u CONTEXT_NOT_FOUND\n", modify_bearer_pP->bearer_context_to_modify.eps_bearer_id); return itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p); } else if (hash_rc == HASH_TABLE_OK) { // TO DO hash_rc = hashtable_get ( new_bearer_ctxt_info_p->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers, modify_bearer_pP->bearer_context_to_modify.eps_bearer_id, (void**)&eps_bearer_entry_p); FTEID_T_2_IP_ADDRESS_T( (&modify_bearer_pP->bearer_context_to_modify.s1_eNB_fteid) , (&eps_bearer_entry_p->enb_ip_address_for_S1u) ); eps_bearer_entry_p->enb_teid_for_S1u = modify_bearer_pP->bearer_context_to_modify.s1_eNB_fteid.teid; // UPDATE GTPV1U mapping tables with eNB references (teid, addresses) message_p = itti_alloc_new_message(TASK_SPGW_APP, GTPV1U_UPDATE_TUNNEL_REQ); if (message_p == NULL) { return -1; } gtpv1u_update_tunnel_req_p = &message_p->ittiMsg.gtpv1uUpdateTunnelReq; memset(gtpv1u_update_tunnel_req_p, 0, sizeof(Gtpv1uUpdateTunnelReq)); gtpv1u_update_tunnel_req_p->context_teid = modify_bearer_pP->teid; gtpv1u_update_tunnel_req_p->sgw_S1u_teid = eps_bearer_entry_p->s_gw_teid_for_S1u_S12_S4_up; ///< SGW S1U local Tunnel Endpoint Identifier gtpv1u_update_tunnel_req_p->enb_S1u_teid = eps_bearer_entry_p->enb_teid_for_S1u; ///< eNB S1U Tunnel Endpoint Identifier gtpv1u_update_tunnel_req_p->enb_ip_address_for_S1u = eps_bearer_entry_p->enb_ip_address_for_S1u; gtpv1u_update_tunnel_req_p->eps_bearer_id = eps_bearer_entry_p->eps_bearer_id; SPGW_APP_DEBUG("Rx MODIFY_BEARER_REQUEST, gtpv1u_update_tunnel_req_p->context_teid = %u\n",modify_bearer_pP->teid); SPGW_APP_DEBUG("Rx MODIFY_BEARER_REQUEST, gtpv1u_update_tunnel_req_p->sgw_S1u_teid = %u\n",gtpv1u_update_tunnel_req_p->sgw_S1u_teid); SPGW_APP_DEBUG("Rx MODIFY_BEARER_REQUEST, gtpv1u_update_tunnel_req_p->enb_S1u_teid = %u\n",gtpv1u_update_tunnel_req_p->enb_S1u_teid); //SPGW_APP_DEBUG("Rx MODIFY_BEARER_REQUEST, gtpv1u_update_tunnel_req_p->enb_ip_address_for_S1u = %u\n",modify_bearer_pP->enb_ip_address_for_S1u); SPGW_APP_DEBUG("Rx MODIFY_BEARER_REQUEST, gtpv1u_update_tunnel_req_p->eps_bearer_id = %u\n",gtpv1u_update_tunnel_req_p->eps_bearer_id); return itti_send_msg_to_task(TASK_GTPV1_U, INSTANCE_DEFAULT, message_p); } } else { message_p = itti_alloc_new_message(TASK_SPGW_APP, SGW_MODIFY_BEARER_RESPONSE); if (message_p == NULL) { return -1; } modify_response_p = &message_p->ittiMsg.sgwModifyBearerResponse; modify_response_p->bearer_present = MODIFY_BEARER_RESPONSE_REM; modify_response_p->bearer_choice.bearer_for_removal.eps_bearer_id = modify_bearer_pP->bearer_context_to_modify.eps_bearer_id; modify_response_p->bearer_choice.bearer_for_removal.cause = CONTEXT_NOT_FOUND; modify_response_p->cause = CONTEXT_NOT_FOUND; modify_response_p->trxn = modify_bearer_pP->trxn; SPGW_APP_DEBUG("Rx MODIFY_BEARER_REQUEST, teid %u CONTEXT_NOT_FOUND\n", modify_bearer_pP->teid); return itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p); } return -1; } int sgw_lite_handle_delete_session_request( const SgwDeleteSessionRequest * const delete_session_req_pP) { task_id_t to_task; hashtable_rc_t hash_rc; SgwDeleteSessionResponse *delete_session_resp_p = NULL; MessageDef *message_p = NULL; s_plus_p_gw_eps_bearer_context_information_t *ctx_p = NULL; #if defined(ENABLE_STANDALONE_EPC) to_task = TASK_MME_APP; #else to_task = TASK_S11; #endif message_p = itti_alloc_new_message(TASK_SPGW_APP, SGW_DELETE_SESSION_RESPONSE); if (message_p == NULL) { return -1; } delete_session_resp_p = &message_p->ittiMsg.sgwDeleteSessionResponse; SPGW_APP_WARN("Delete session handler needs to be completed...\n"); if (delete_session_req_pP->indication_flags & OI_FLAG) { SPGW_APP_DEBUG("OI flag is set for this message indicating the request" "should be forwarded to P-GW entity\n"); } hash_rc = hashtable_get(sgw_app.s11_bearer_context_information_hashtable, delete_session_req_pP->teid, (void**)&ctx_p); if (hash_rc == HASH_TABLE_OK) { if ((delete_session_req_pP->sender_fteid_for_cp.ipv4 != 0) && (delete_session_req_pP->sender_fteid_for_cp.ipv6 != 0)) { /* Sender F-TEID IE present */ if (delete_session_resp_p->teid != ctx_p->sgw_eps_bearer_context_information.mme_teid_for_S11) { delete_session_resp_p->teid = ctx_p->sgw_eps_bearer_context_information.mme_teid_for_S11; delete_session_resp_p->cause = INVALID_PEER; SPGW_APP_DEBUG("Mismatch in MME Teid for CP\n"); } else { delete_session_resp_p->teid = delete_session_req_pP->sender_fteid_for_cp.teid; } } else { delete_session_resp_p->cause = REQUEST_ACCEPTED; delete_session_resp_p->teid = ctx_p->sgw_eps_bearer_context_information.mme_teid_for_S11; } delete_session_resp_p->trxn = delete_session_req_pP->trxn; delete_session_resp_p->peer_ip = delete_session_req_pP->peer_ip; return itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p); } else { /* Context not found... set the cause to CONTEXT_NOT_FOUND * 3GPP TS 29.274 #7.2.10.1 */ message_p = itti_alloc_new_message(TASK_SPGW_APP, SGW_DELETE_SESSION_RESPONSE); if (message_p == NULL) { return -1; } delete_session_resp_p = &message_p->ittiMsg.sgwDeleteSessionResponse; if ((delete_session_req_pP->sender_fteid_for_cp.ipv4 == 0) && (delete_session_req_pP->sender_fteid_for_cp.ipv6 == 0)) { delete_session_resp_p->teid = 0; } else { delete_session_resp_p->teid = delete_session_req_pP->sender_fteid_for_cp.teid; } delete_session_resp_p->cause = CONTEXT_NOT_FOUND; delete_session_resp_p->trxn = delete_session_req_pP->trxn; delete_session_resp_p->peer_ip = delete_session_req_pP->peer_ip; return itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p); } return -1; }