diff --git a/lte/gateway/c/oai/include/ip_forward_messages_types.h b/lte/gateway/c/oai/include/ip_forward_messages_types.h index d15d93e6d9e9..45d2f7919508 100644 --- a/lte/gateway/c/oai/include/ip_forward_messages_types.h +++ b/lte/gateway/c/oai/include/ip_forward_messages_types.h @@ -80,8 +80,6 @@ typedef struct { typedef struct { teid_t context_teid; ///< Tunnel Endpoint Identifier S11 - SGIStatus_t status; ///< Status of endpoint creation (Failed = 0xFF or - ///< Success = 0x0) uint8_t num_bearers_modified; bearer_cxt_t bearer_contexts_to_be_modified[BEARERS_PER_UE]; uint8_t num_bearers_removed; diff --git a/lte/gateway/c/oai/include/sgw_context_manager.h b/lte/gateway/c/oai/include/sgw_context_manager.h index 969a2cf3dcaf..c7680e8cf184 100644 --- a/lte/gateway/c/oai/include/sgw_context_manager.h +++ b/lte/gateway/c/oai/include/sgw_context_manager.h @@ -38,6 +38,7 @@ void sgw_display_sgw_eps_bearer_context( const sgw_eps_bearer_ctxt_t* eps_bearer_ctxt); void sgw_display_s11teid2mme(mme_sgw_tunnel_t* mme_sgw_tunnel); void sgw_display_s11_bearer_context_information( + log_proto_t module, sgw_eps_bearer_context_information_t* sgw_context_information); void pgw_lite_cm_free_apn(pgw_apn_t** apnP); diff --git a/lte/gateway/c/oai/lib/s8_proxy/s8_client_api.cpp b/lte/gateway/c/oai/lib/s8_proxy/s8_client_api.cpp index 3d64ea391e37..1dd4093c4b2f 100644 --- a/lte/gateway/c/oai/lib/s8_proxy/s8_client_api.cpp +++ b/lte/gateway/c/oai/lib/s8_proxy/s8_client_api.cpp @@ -49,14 +49,16 @@ static void get_fteid_from_proto_msg( OAILOG_FUNC_IN(LOG_SGW_S8); pgw_fteid->teid = proto_fteid.teid(); if (proto_fteid.ipv4_address().c_str()) { - struct in_addr addr = {0}; - memcpy(&addr, proto_fteid.ipv4_address().c_str(), sizeof(in_addr)); - pgw_fteid->ipv4_address = addr; + pgw_fteid->ipv4 = true; + inet_pton( + AF_INET, proto_fteid.ipv4_address().c_str(), + &(pgw_fteid->ipv4_address)); } if (proto_fteid.ipv6_address().c_str()) { - struct in6_addr ip6_addr; - memcpy(&ip6_addr, proto_fteid.ipv6_address().c_str(), sizeof(in6_addr)); - pgw_fteid->ipv6_address = ip6_addr; + pgw_fteid->ipv6 = true; + inet_pton( + AF_INET6, proto_fteid.ipv6_address().c_str(), + &(pgw_fteid->ipv6_address)); } OAILOG_FUNC_OUT(LOG_SGW_S8); } @@ -69,22 +71,22 @@ static void get_paa_from_proto_msg( case magma::feg::PDNType::IPV4: { paa->pdn_type = IPv4; auto ip = proto_paa.ipv4_address(); - memcpy(&paa->ipv4_address, ip.c_str(), sizeof(ip.c_str())); + inet_pton(AF_INET, ip.c_str(), &(paa->ipv4_address)); break; } case magma::feg::PDNType::IPV6: { paa->pdn_type = IPv6; auto ip = proto_paa.ipv6_address(); - memcpy(&paa->ipv6_address, ip.c_str(), sizeof(ip.c_str())); + inet_pton(AF_INET6, ip.c_str(), &(paa->ipv6_address)); paa->ipv6_prefix_length = IPV6_PREFIX_LEN; break; } case magma::feg::PDNType::IPV4V6: { paa->pdn_type = IPv4_AND_v6; auto ip = proto_paa.ipv4_address(); - memcpy(&paa->ipv4_address, ip.c_str(), sizeof(ip.c_str())); + inet_pton(AF_INET, ip.c_str(), &(paa->ipv4_address)); auto ipv6 = proto_paa.ipv6_address(); - memcpy(&paa->ipv6_address, ipv6.c_str(), sizeof(ipv6.c_str())); + inet_pton(AF_INET6, ipv6.c_str(), &(paa->ipv6_address)); paa->ipv6_prefix_length = IPV6_PREFIX_LEN; break; } @@ -371,6 +373,10 @@ static void convert_proto_msg_to_itti_csr( get_qos_from_proto_msg(response.bearer_context().qos(), &s8_bc->qos); get_fteid_from_proto_msg( response.bearer_context().user_plane_fteid(), &s8_bc->pgw_s8_up); - s5_response->cause = response.mutable_gtp_error()->cause(); + if (response.has_gtp_error()) { + s5_response->cause = response.mutable_gtp_error()->cause(); + } else { + s5_response->cause = REQUEST_ACCEPTED; + } OAILOG_FUNC_OUT(LOG_SGW_S8); } diff --git a/lte/gateway/c/oai/tasks/gtpv1-u/gtpv1u.h b/lte/gateway/c/oai/tasks/gtpv1-u/gtpv1u.h index ca01b53b0d6d..2fe4745ef102 100644 --- a/lte/gateway/c/oai/tasks/gtpv1-u/gtpv1u.h +++ b/lte/gateway/c/oai/tasks/gtpv1-u/gtpv1u.h @@ -178,4 +178,10 @@ int gtpv1u_add_s8_tunnel( struct in_addr ue, struct in6_addr* ue_ipv6, int vlan, struct in_addr enb, struct in_addr pgw, uint32_t i_tei, uint32_t o_tei, Imsi_t imsi, struct ip_flow_dl* flow_dl, uint32_t flow_precedence_dl); + +int gtpv1u_del_s8_tunnel( + struct in_addr enb, struct in_addr pgw, struct in_addr ue, + struct in6_addr* ue_ipv6, uint32_t i_tei, uint32_t o_tei, + struct ip_flow_dl* flow_dl); + #endif /* FILE_GTPV1_U_SEEN */ diff --git a/lte/gateway/c/oai/tasks/sgw/sgw_context_manager.c b/lte/gateway/c/oai/tasks/sgw/sgw_context_manager.c index 518d53c49439..49ae8700d9ac 100644 --- a/lte/gateway/c/oai/tasks/sgw/sgw_context_manager.c +++ b/lte/gateway/c/oai/tasks/sgw/sgw_context_manager.c @@ -65,41 +65,41 @@ void sgw_display_sgw_eps_bearer_context( //----------------------------------------------------------------------------- void sgw_display_s11_bearer_context_information( + log_proto_t module, sgw_eps_bearer_context_information_t* sgw_context_information) //----------------------------------------------------------------------------- { OAILOG_DEBUG( - LOG_SPGW_APP, "| KEY %" PRId64 ": \n", - sgw_context_information->imsi64); - OAILOG_DEBUG(LOG_SPGW_APP, "|\tsgw_eps_bearer_context_information: |\n"); + module, "| KEY %" PRId64 ": \n", sgw_context_information->imsi64); + OAILOG_DEBUG(module, "|\tsgw_eps_bearer_context_information: |\n"); // Imsi_t imsi; ///< IMSI // (International Mobile Subscriber Identity) is the subscriber permanent // identity. OAILOG_DEBUG( - LOG_SPGW_APP, "|\t\timsi_unauthenticated_indicator:\t%u\n", + module, "|\t\timsi_unauthenticated_indicator:\t%u\n", sgw_context_information->imsi_unauthenticated_indicator); // char msisdn[MSISDN_LENGTH]; ///< The basic MSISDN // of the UE. The presence is dictated by its storage in the HSS. OAILOG_DEBUG( - LOG_SPGW_APP, "|\t\tmme_teid_ S11: \t" TEID_FMT "\n", + module, "|\t\tmme_teid_ S11: \t" TEID_FMT "\n", sgw_context_information->mme_teid_S11); // ip_address_t mme_ip_address_for_S11; ///< MME IP address // the S11 interface. OAILOG_DEBUG( - LOG_SPGW_APP, "|\t\ts_gw_teid_S11_S4: \t" TEID_FMT "\n", + module, "|\t\ts_gw_teid_S11_S4: \t" TEID_FMT "\n", sgw_context_information->s_gw_teid_S11_S4); // ip_address_t s_gw_ip_address_for_S11_S4; ///< S-GW IP address // for the S11 interface and the S4 Interface (control plane). cgi_t // last_known_cell_Id; ///< This is the last location of the UE // known by the network - OAILOG_DEBUG(LOG_SPGW_APP, "|\t\tpdn_connection:\n"); + OAILOG_DEBUG(module, "|\t\tpdn_connection:\n"); OAILOG_DEBUG( - LOG_SPGW_APP, "|\t\t\tapn_in_use: %s\n", + module, "|\t\t\tapn_in_use: %s\n", sgw_context_information->pdn_connection.apn_in_use); OAILOG_DEBUG( - LOG_SPGW_APP, "|\t\t\tdefault_bearer: %u\n", + module, "|\t\t\tdefault_bearer: %u\n", sgw_context_information->pdn_connection.default_bearer); - OAILOG_DEBUG(LOG_SPGW_APP, "|\t\t\teps_bearers:\n"); + OAILOG_DEBUG(module, "|\t\t\teps_bearers:\n"); for (int ebix = 0; ebix < BEARERS_PER_UE; ebix++) { sgw_display_sgw_eps_bearer_context( sgw_context_information->pdn_connection.sgw_eps_bearers_array[ebix]); diff --git a/lte/gateway/c/oai/tasks/sgw/sgw_handlers.c b/lte/gateway/c/oai/tasks/sgw/sgw_handlers.c index d22d90b8a102..fffebbd5954a 100644 --- a/lte/gateway/c/oai/tasks/sgw/sgw_handlers.c +++ b/lte/gateway/c/oai/tasks/sgw/sgw_handlers.c @@ -78,9 +78,6 @@ static void _generate_dl_flow( packet_filter_contents_t* packet_filter, in_addr_t ipv4_s_addr, struct in6_addr* ue_ipv6, struct ip_flow_dl* dlflow); -static bool does_bearer_context_hold_valid_enb_ip( - ip_address_t enb_ip_address_S1u); - static void _add_tunnel_helper( s_plus_p_gw_eps_bearer_context_information_t* spgw_context, sgw_eps_bearer_ctxt_t* eps_bearer_ctxt_entry_p, imsi64_t imsi64); @@ -255,8 +252,8 @@ int sgw_handle_s11_create_session_request( session_req_pP->bearer_contexts_to_be_created.bearer_contexts[0] .eps_bearer_id); sgw_display_s11_bearer_context_information( - &s_plus_p_gw_eps_bearer_ctxt_info_p - ->sgw_eps_bearer_context_information); + LOG_SPGW_APP, &s_plus_p_gw_eps_bearer_ctxt_info_p + ->sgw_eps_bearer_context_information); if (eps_bearer_ctxt_p == NULL) { OAILOG_ERROR_UE( @@ -439,10 +436,11 @@ int sgw_handle_sgi_endpoint_created( /* Populates bearer contexts marked for removal structure in * modify bearer rsp message. */ -static void sgw_populate_mbr_bearer_contexts_not_found( +void sgw_populate_mbr_bearer_contexts_not_found( + log_proto_t module, const itti_sgi_update_end_point_response_t* const resp_pP, itti_s11_modify_bearer_response_t* modify_response_p) { - OAILOG_FUNC_IN(LOG_SPGW_APP); + OAILOG_FUNC_IN(module); uint8_t rsp_idx = 0; for (uint8_t idx = 0; idx < resp_pP->num_bearers_not_found; idx++) { modify_response_p->bearer_contexts_marked_for_removal @@ -453,23 +451,22 @@ static void sgw_populate_mbr_bearer_contexts_not_found( .cause.cause_value = CONTEXT_NOT_FOUND; modify_response_p->bearer_contexts_marked_for_removal.num_bearer_context++; } - OAILOG_FUNC_OUT(LOG_SPGW_APP); + OAILOG_FUNC_OUT(module); } //------------------------------------------------------------------------------ /* Populates bearer contexts marked for removal structure in * modify bearer rsp message */ -static void sgw_populate_mbr_bearer_contexts_removed( +void sgw_populate_mbr_bearer_contexts_removed( const itti_sgi_update_end_point_response_t* const resp_pP, imsi64_t imsi64, - s_plus_p_gw_eps_bearer_context_information_t* new_bearer_ctxt_info_p, + sgw_eps_bearer_context_information_t* sgw_context_p, itti_s11_modify_bearer_response_t* modify_response_p) { OAILOG_FUNC_IN(LOG_SPGW_APP); uint8_t rsp_idx = 0; sgw_eps_bearer_ctxt_t* eps_bearer_ctxt_p = NULL; for (uint8_t idx = 0; idx < resp_pP->num_bearers_removed; idx++) { eps_bearer_ctxt_p = sgw_cm_get_eps_bearer_entry( - &new_bearer_ctxt_info_p->sgw_eps_bearer_context_information - .pdn_connection, + &(sgw_context_p->pdn_connection), resp_pP->bearer_contexts_to_be_removed[idx]); /* If context is found, delete the context and set cause as * REQUEST_ACCEPTED. If context is not found set the cause as @@ -478,9 +475,8 @@ static void sgw_populate_mbr_bearer_contexts_removed( */ if (NULL != eps_bearer_ctxt_p) { sgw_free_eps_bearer_context( - &new_bearer_ctxt_info_p->sgw_eps_bearer_context_information - .pdn_connection.sgw_eps_bearers_array[EBI_TO_INDEX( - eps_bearer_ctxt_p->eps_bearer_id)]); + &(sgw_context_p->pdn_connection.sgw_eps_bearers_array[EBI_TO_INDEX( + eps_bearer_ctxt_p->eps_bearer_id)])); modify_response_p->bearer_contexts_marked_for_removal .bearer_contexts[rsp_idx] .cause.cause_value = REQUEST_ACCEPTED; @@ -672,8 +668,8 @@ void sgw_handle_sgi_endpoint_updated( OAILOG_DEBUG_UE( LOG_SPGW_APP, imsi64, - "Rx SGI_UPDATE_ENDPOINT_RESPONSE, Context teid " TEID_FMT " status %d\n", - resp_pP->context_teid, resp_pP->status); + "Rx SGI_UPDATE_ENDPOINT_RESPONSE, Context teid " TEID_FMT "\n", + resp_pP->context_teid); message_p = itti_alloc_new_message(TASK_SPGW_APP, S11_MODIFY_BEARER_RESPONSE); if (!message_p) { @@ -698,8 +694,11 @@ void sgw_handle_sgi_endpoint_updated( sgw_populate_mbr_bearer_contexts_modified( resp_pP, imsi64, new_bearer_ctxt_info_p, modify_response_p); sgw_populate_mbr_bearer_contexts_removed( - resp_pP, imsi64, new_bearer_ctxt_info_p, modify_response_p); - sgw_populate_mbr_bearer_contexts_not_found(resp_pP, modify_response_p); + resp_pP, imsi64, + &new_bearer_ctxt_info_p->sgw_eps_bearer_context_information, + modify_response_p); + sgw_populate_mbr_bearer_contexts_not_found( + LOG_SPGW_APP, resp_pP, modify_response_p); send_msg_to_task(&spgw_app_task_zmq_ctx, TASK_MME, message_p); } OAILOG_FUNC_OUT(LOG_SPGW_APP); @@ -860,7 +859,7 @@ int sgw_handle_sgi_endpoint_deleted( //------------------------------------------------------------------------------ // This function populates itti_sgi_update_end_point_response_t message -static void populate_sgi_end_point_update( +void populate_sgi_end_point_update( uint8_t sgi_rsp_idx, uint8_t idx, const itti_s11_modify_bearer_request_t* const modify_bearer_pP, sgw_eps_bearer_ctxt_t* eps_bearer_ctxt_p, @@ -887,18 +886,19 @@ static void populate_sgi_end_point_update( //------------------------------------------------------------------------------ // This function populates and sends MBR failure message to MME APP -static int send_mbr_failure( +int send_mbr_failure( + log_proto_t module, const itti_s11_modify_bearer_request_t* const modify_bearer_pP, imsi64_t imsi64) { int rv = RETURNok; - OAILOG_FUNC_IN(LOG_SPGW_APP); + OAILOG_FUNC_IN(module); MessageDef* message_p = itti_alloc_new_message(TASK_SPGW_APP, S11_MODIFY_BEARER_RESPONSE); if (!message_p) { OAILOG_ERROR( - LOG_SPGW_APP, "S11_MODIFY_BEARER_RESPONSE memory allocation failed\n"); - OAILOG_FUNC_RETURN(LOG_SPGW_APP, RETURNerror); + module, "S11_MODIFY_BEARER_RESPONSE memory allocation failed\n"); + OAILOG_FUNC_RETURN(module, RETURNerror); } itti_s11_modify_bearer_response_t* modify_response_p = @@ -921,13 +921,13 @@ static int send_mbr_failure( modify_response_p->cause.cause_value = CONTEXT_NOT_FOUND; modify_response_p->trxn = modify_bearer_pP->trxn; OAILOG_DEBUG_UE( - LOG_SPGW_APP, imsi64, + module, imsi64, "Rx MODIFY_BEARER_REQUEST, teid " TEID_FMT " CONTEXT_NOT_FOUND\n", modify_bearer_pP->teid); message_p->ittiMsgHeader.imsi = imsi64; rv = send_msg_to_task(&spgw_app_task_zmq_ctx, TASK_MME, message_p); - OAILOG_FUNC_RETURN(LOG_SPGW_APP, rv); + OAILOG_FUNC_RETURN(module, rv); } //------------------------------------------------------------------------------ @@ -956,7 +956,6 @@ int sgw_handle_modify_bearer_request( modify_bearer_pP->trxn; sgi_update_end_point_resp.context_teid = modify_bearer_pP->teid; - sgi_update_end_point_resp.status = 0; uint8_t sgi_rsp_idx = 0; for (idx = 0; idx < @@ -1031,7 +1030,7 @@ int sgw_handle_modify_bearer_request( } sgw_handle_sgi_endpoint_updated(&sgi_update_end_point_resp, imsi64); } else { // bearer_ctxt_info_p not found - rv = send_mbr_failure(modify_bearer_pP, imsi64); + rv = send_mbr_failure(LOG_SPGW_APP, modify_bearer_pP, imsi64); if (rv != RETURNok) { OAILOG_ERROR( LOG_SPGW_APP, @@ -2227,8 +2226,7 @@ static void _add_tunnel_helper( } } } -static bool does_bearer_context_hold_valid_enb_ip( - ip_address_t enb_ip_address_S1u) { +bool does_bearer_context_hold_valid_enb_ip(ip_address_t enb_ip_address_S1u) { OAILOG_FUNC_IN(LOG_SPGW_APP); static struct in6_addr ipv6_address = {0}; switch (enb_ip_address_S1u.pdn_type) { diff --git a/lte/gateway/c/oai/tasks/sgw/sgw_handlers.h b/lte/gateway/c/oai/tasks/sgw/sgw_handlers.h index 21f40af3d490..658164070882 100644 --- a/lte/gateway/c/oai/tasks/sgw/sgw_handlers.h +++ b/lte/gateway/c/oai/tasks/sgw/sgw_handlers.h @@ -69,4 +69,28 @@ int sgw_handle_ip_allocation_rsp( const itti_ip_allocation_response_t* ip_allocation_rsp, imsi64_t imsi64); bool is_enb_ip_address_same(const fteid_t* fte_p, ip_address_t* ip_p); uint32_t spgw_get_new_s1u_teid(spgw_state_t* state); +int send_mbr_failure( + log_proto_t module, + const itti_s11_modify_bearer_request_t* const modify_bearer_pP, + imsi64_t imsi64); +void sgw_populate_mbr_bearer_contexts_removed( + const itti_sgi_update_end_point_response_t* const resp_pP, imsi64_t imsi64, + sgw_eps_bearer_context_information_t* sgw_context_p, + itti_s11_modify_bearer_response_t* modify_response_p); +void sgw_populate_mbr_bearer_contexts_not_found( + log_proto_t module, + const itti_sgi_update_end_point_response_t* const resp_pP, + itti_s11_modify_bearer_response_t* modify_response_p); +void populate_sgi_end_point_update( + uint8_t sgi_rsp_idx, uint8_t idx, + const itti_s11_modify_bearer_request_t* const modify_bearer_pP, + sgw_eps_bearer_ctxt_t* eps_bearer_ctxt_p, + itti_sgi_update_end_point_response_t* sgi_update_end_point_resp); +bool does_bearer_context_hold_valid_enb_ip(ip_address_t enb_ip_address_S1u); +void populate_sgi_end_point_update( + uint8_t sgi_rsp_idx, uint8_t idx, + const itti_s11_modify_bearer_request_t* const modify_bearer_pP, + sgw_eps_bearer_ctxt_t* eps_bearer_ctxt_p, + itti_sgi_update_end_point_response_t* sgi_update_end_point_resp); + #endif /* FILE_SGW_HANDLERS_SEEN */ diff --git a/lte/gateway/c/oai/tasks/sgw_s8/sgw_s8_handlers.c b/lte/gateway/c/oai/tasks/sgw_s8/sgw_s8_handlers.c index 765a6d9a58ce..763e5e84da21 100644 --- a/lte/gateway/c/oai/tasks/sgw_s8/sgw_s8_handlers.c +++ b/lte/gateway/c/oai/tasks/sgw_s8/sgw_s8_handlers.c @@ -24,6 +24,7 @@ limitations under the License. #include "s8_client_api.h" #include "gtpv1u.h" #include "dynamic_memory_check.h" +#include "sgw_handlers.h" extern task_zmq_ctx_t sgw_s8_task_zmq_ctx; extern struct gtp_tunnel_ops* gtp_tunnel_ops; @@ -32,6 +33,14 @@ static int sgw_s8_add_gtp_tunnel( sgw_eps_bearer_ctxt_t* eps_bearer_ctxt_p, sgw_eps_bearer_context_information_t* sgw_context_p); +static int sgw_s8_add_gtp_s8_tunnel( + sgw_eps_bearer_ctxt_t* eps_bearer_ctxt_p, + sgw_eps_bearer_context_information_t* sgw_context_p); + +static void sgw_send_modify_bearer_response( + sgw_eps_bearer_context_information_t* sgw_context_p, + const itti_sgi_update_end_point_response_t* const resp_pP, imsi64_t imsi64); + uint32_t sgw_get_new_s1u_teid(sgw_state_t* state) { if (state->s1u_teid == 0) { state->s1u_teid = INITIAL_SGW_S8_S1U_TEID; @@ -44,6 +53,10 @@ uint32_t sgw_get_new_s5s8u_teid(sgw_state_t* state) { __sync_fetch_and_add(&state->s5s8u_teid, 1); return (state->s5s8u_teid); } +static void sgw_s8_populate_mbr_bearer_contexts_modified( + const itti_sgi_update_end_point_response_t* const resp_pP, imsi64_t imsi64, + sgw_eps_bearer_context_information_t* sgw_context_p, + itti_s11_modify_bearer_response_t* modify_response_p); void sgw_remove_sgw_bearer_context_information( sgw_state_t* sgw_state, teid_t teid, imsi64_t imsi64) { @@ -300,7 +313,7 @@ void sgw_s8_handle_s11_create_session_request( send_s8_create_session_request( sgw_s11_tunnel.local_teid, session_req_pP, imsi64); - sgw_display_s11_bearer_context_information(new_sgw_eps_context); + sgw_display_s11_bearer_context_information(LOG_SGW_S8, new_sgw_eps_context); OAILOG_FUNC_OUT(LOG_SGW_S8); } @@ -338,7 +351,6 @@ static int update_bearer_context_info( memcpy( &default_bearer_ctx_p->eps_bearer_qos, &s5s8_bearer_context.qos, sizeof(bearer_qos_t)); - sgw_s8_add_gtp_tunnel(default_bearer_ctx_p, sgw_context_p); OAILOG_FUNC_RETURN(LOG_SGW_S8, RETURNok); } @@ -533,8 +545,13 @@ static int sgw_s8_add_gtp_tunnel( } else { OAILOG_DEBUG_UE( LOG_SGW_S8, sgw_context_p->imsi64, - "Adding tunnel for bearer %u ue addr %x\n", - eps_bearer_ctxt_p->eps_bearer_id, ue_ipv4.s_addr); + "Adding tunnel for bearer %u ue addr %x enb " + "%x,s_gw_teid_S1u_S12_S4_up %x, enb_teid_S1u %x pgw_up_ip %x " + "pgw_up_teid %x \n", + eps_bearer_ctxt_p->eps_bearer_id, ue_ipv4.s_addr, enb.s_addr, + eps_bearer_ctxt_p->s_gw_teid_S1u_S12_S4_up, + eps_bearer_ctxt_p->enb_teid_S1u, pgw.s_addr, + eps_bearer_ctxt_p->p_gw_teid_S5_S8_up); if (eps_bearer_ctxt_p->eps_bearer_id == sgw_context_p->pdn_connection.default_bearer) { // Set default precedence and tft for default bearer @@ -561,3 +578,267 @@ static int sgw_s8_add_gtp_tunnel( } OAILOG_FUNC_RETURN(LOG_SGW_S8, rv); } + +void sgw_s8_handle_modify_bearer_request( + sgw_state_t* state, + const itti_s11_modify_bearer_request_t* const modify_bearer_pP, + imsi64_t imsi64) { + OAILOG_FUNC_IN(LOG_SGW_S8); + + uint8_t idx = 0; + uint8_t sgi_rsp_idx = 0; + itti_sgi_update_end_point_response_t sgi_update_end_point_resp = {0}; + struct in_addr enb = {.s_addr = 0}; + struct in_addr pgw = {.s_addr = 0}; + sgw_eps_bearer_ctxt_t* bearer_ctx_p = NULL; + + OAILOG_INFO_UE( + LOG_SGW_S8, imsi64, "Rx MODIFY_BEARER_REQUEST, teid " TEID_FMT "\n", + modify_bearer_pP->teid); + + sgw_eps_bearer_context_information_t* sgw_context_p = + sgw_get_sgw_eps_bearer_context(modify_bearer_pP->teid); + if (!sgw_context_p) { + OAILOG_ERROR_UE( + LOG_SGW_S8, imsi64, + "Failed to fetch sgw_eps_bearer_context_info from " + "context_teid " TEID_FMT " \n", + modify_bearer_pP->teid); + if ((send_mbr_failure(LOG_SGW_S8, modify_bearer_pP, imsi64) != RETURNok)) { + OAILOG_ERROR( + LOG_SGW_S8, + "Error in sending modify bearer response to MME App for context " + "teid " TEID_FMT "\n", + modify_bearer_pP->teid); + } + OAILOG_FUNC_OUT(LOG_SGW_S8); + } + sgw_context_p->trxn = modify_bearer_pP->trxn; + sgi_update_end_point_resp.context_teid = modify_bearer_pP->teid; + // Traversing through the list of bearers to be modified + for (; idx < + modify_bearer_pP->bearer_contexts_to_be_modified.num_bearer_context; + idx++) { + bearer_context_to_be_modified_t mbr_bearer_ctxt_p = + modify_bearer_pP->bearer_contexts_to_be_modified.bearer_contexts[idx]; + bearer_ctx_p = sgw_cm_get_eps_bearer_entry( + &sgw_context_p->pdn_connection, mbr_bearer_ctxt_p.eps_bearer_id); + if (!bearer_ctx_p) { + OAILOG_ERROR_UE( + LOG_SGW_S8, imsi64, + "Failed to get eps bearer context for context teid " TEID_FMT + "and bearer_id :%u \n", + modify_bearer_pP->teid, mbr_bearer_ctxt_p.eps_bearer_id); + sgi_update_end_point_resp.bearer_contexts_not_found[sgi_rsp_idx++] = + mbr_bearer_ctxt_p.eps_bearer_id; + sgi_update_end_point_resp.num_bearers_not_found++; + } else { + enb.s_addr = bearer_ctx_p->enb_ip_address_S1u.address.ipv4_address.s_addr; + pgw.s_addr = + bearer_ctx_p->p_gw_address_in_use_up.address.ipv4_address.s_addr; + + // Send end marker to eNB and then delete the tunnel if enb_ip is + // different + if (does_bearer_context_hold_valid_enb_ip( + bearer_ctx_p->enb_ip_address_S1u) && + is_enb_ip_address_same( + &mbr_bearer_ctxt_p.s1_eNB_fteid, + &bearer_ctx_p->enb_ip_address_S1u) == false) { + struct in_addr ue_ipv4 = bearer_ctx_p->paa.ipv4_address; + struct in6_addr* ue_ipv6 = NULL; + if ((bearer_ctx_p->paa.pdn_type == IPv6) || + (bearer_ctx_p->paa.pdn_type == IPv4_AND_v6)) { + ue_ipv6 = &bearer_ctx_p->paa.ipv6_address; + } + + OAILOG_DEBUG_UE( + LOG_SGW_S8, imsi64, + "Delete GTPv1-U tunnel for sgw_teid:" TEID_FMT "for bearer %u\n", + bearer_ctx_p->s_gw_teid_S1u_S12_S4_up, bearer_ctx_p->eps_bearer_id); + // This is best effort, ignore return code. + gtp_tunnel_ops->send_end_marker(enb, modify_bearer_pP->teid); + // delete GTPv1-U tunnel + gtpv1u_del_s8_tunnel( + enb, pgw, ue_ipv4, ue_ipv6, bearer_ctx_p->s_gw_teid_S1u_S12_S4_up, + bearer_ctx_p->enb_teid_S1u, NULL); + } + populate_sgi_end_point_update( + sgi_rsp_idx, idx, modify_bearer_pP, bearer_ctx_p, + &sgi_update_end_point_resp); + sgi_rsp_idx++; + } + } // for loop + + sgi_rsp_idx = 0; + for (idx = 0; + idx < modify_bearer_pP->bearer_contexts_to_be_removed.num_bearer_context; + idx++) { + bearer_ctx_p = sgw_cm_get_eps_bearer_entry( + &sgw_context_p->pdn_connection, + modify_bearer_pP->bearer_contexts_to_be_removed.bearer_contexts[idx] + .eps_bearer_id); + if (bearer_ctx_p) { + sgi_update_end_point_resp.bearer_contexts_to_be_removed[sgi_rsp_idx++] = + bearer_ctx_p->eps_bearer_id; + sgi_update_end_point_resp.num_bearers_removed++; + } + } + sgw_send_modify_bearer_response( + sgw_context_p, &sgi_update_end_point_resp, imsi64); + OAILOG_FUNC_OUT(LOG_SGW_S8); +} + +static void sgw_send_modify_bearer_response( + sgw_eps_bearer_context_information_t* sgw_context_p, + const itti_sgi_update_end_point_response_t* const resp_pP, + imsi64_t imsi64) { + OAILOG_FUNC_IN(LOG_SGW_S8); + itti_s11_modify_bearer_response_t* modify_response_p = NULL; + MessageDef* message_p = NULL; + + OAILOG_DEBUG_UE( + LOG_SGW_S8, imsi64, + "send modify bearer response for Context teid " TEID_FMT "\n", + resp_pP->context_teid); + message_p = itti_alloc_new_message(TASK_SGW_S8, S11_MODIFY_BEARER_RESPONSE); + + if (!message_p) { + OAILOG_ERROR_UE( + LOG_SGW_S8, imsi64, + "Failed to allocate memory for S11_MODIFY_BEARER_RESPONSE\n"); + OAILOG_FUNC_OUT(LOG_SGW_S8); + } + + modify_response_p = &message_p->ittiMsg.s11_modify_bearer_response; + + if (sgw_context_p) { + modify_response_p->teid = sgw_context_p->mme_teid_S11; + modify_response_p->cause.cause_value = REQUEST_ACCEPTED; + modify_response_p->trxn = sgw_context_p->trxn; + message_p->ittiMsgHeader.imsi = imsi64; + + sgw_s8_populate_mbr_bearer_contexts_modified( + resp_pP, imsi64, sgw_context_p, modify_response_p); + sgw_populate_mbr_bearer_contexts_removed( + resp_pP, imsi64, sgw_context_p, modify_response_p); + sgw_populate_mbr_bearer_contexts_not_found( + LOG_SGW_S8, resp_pP, modify_response_p); + send_msg_to_task(&sgw_s8_task_zmq_ctx, TASK_MME_APP, message_p); + } + OAILOG_FUNC_OUT(LOG_SGW_S8); +} + +static void sgw_s8_populate_mbr_bearer_contexts_modified( + const itti_sgi_update_end_point_response_t* const resp_pP, imsi64_t imsi64, + sgw_eps_bearer_context_information_t* sgw_context_p, + itti_s11_modify_bearer_response_t* modify_response_p) { + OAILOG_FUNC_IN(LOG_SGW_S8); + uint8_t rsp_idx = 0; + sgw_eps_bearer_ctxt_t* eps_bearer_ctxt_p = NULL; + + for (uint8_t idx = 0; idx < resp_pP->num_bearers_modified; idx++) { + eps_bearer_ctxt_p = sgw_cm_get_eps_bearer_entry( + &sgw_context_p->pdn_connection, + resp_pP->bearer_contexts_to_be_modified[idx].eps_bearer_id); + + if (NULL != eps_bearer_ctxt_p) { + OAILOG_DEBUG_UE( + LOG_SGW_S8, imsi64, + "Modify bearer request is accepted for bearer_id :%u\n", + resp_pP->bearer_contexts_to_be_modified[idx].eps_bearer_id); + modify_response_p->bearer_contexts_modified.bearer_contexts[rsp_idx] + .eps_bearer_id = + resp_pP->bearer_contexts_to_be_modified[idx].eps_bearer_id; + modify_response_p->bearer_contexts_modified.bearer_contexts[rsp_idx++] + .cause.cause_value = REQUEST_ACCEPTED; + modify_response_p->bearer_contexts_modified.num_bearer_context++; + + // setup GTPv1-U tunnel + sgw_s8_add_gtp_tunnel(eps_bearer_ctxt_p, sgw_context_p); + sgw_s8_add_gtp_s8_tunnel(eps_bearer_ctxt_p, sgw_context_p); + // may be removed TODO rashmi remove after testing + if (TRAFFIC_FLOW_TEMPLATE_NB_PACKET_FILTERS_MAX > + eps_bearer_ctxt_p->num_sdf) { + int i = 0; + while ((i < eps_bearer_ctxt_p->num_sdf) && + (SDF_ID_NGBR_DEFAULT != eps_bearer_ctxt_p->sdf_id[i])) + i++; + if (i >= eps_bearer_ctxt_p->num_sdf) { + eps_bearer_ctxt_p->sdf_id[eps_bearer_ctxt_p->num_sdf] = + SDF_ID_NGBR_DEFAULT; + eps_bearer_ctxt_p->num_sdf += 1; + } + } + } + } + OAILOG_FUNC_OUT(LOG_SGW_S8); +} + +// Helper function to add gtp tunnels for default bearers +static int sgw_s8_add_gtp_s8_tunnel( + sgw_eps_bearer_ctxt_t* eps_bearer_ctxt_p, + sgw_eps_bearer_context_information_t* sgw_context_p) { + int rv = RETURNok; + struct in_addr enb = {.s_addr = 0}; + struct in_addr pgw = {.s_addr = 0}; + pgw.s_addr = + eps_bearer_ctxt_p->p_gw_address_in_use_up.address.ipv4_address.s_addr; + if ((pgw.s_addr == 0) && (eps_bearer_ctxt_p->p_gw_teid_S5_S8_up == 0)) { + OAILOG_ERROR_UE( + LOG_SGW_S8, sgw_context_p->imsi64, + "bearer context has invalid pgw_s8_teid " TEID_FMT + "pgw_ip address :%x \n", + eps_bearer_ctxt_p->p_gw_teid_S5_S8_up, pgw.s_addr); + OAILOG_FUNC_RETURN(LOG_SGW_S8, RETURNerror); + } + enb.s_addr = + eps_bearer_ctxt_p->enb_ip_address_S1u.address.ipv4_address.s_addr; + + struct in_addr ue_ipv4 = {.s_addr = 0}; + struct in6_addr* ue_ipv6 = NULL; + ue_ipv4.s_addr = eps_bearer_ctxt_p->paa.ipv4_address.s_addr; + if ((eps_bearer_ctxt_p->paa.pdn_type == IPv6) || + (eps_bearer_ctxt_p->paa.pdn_type == IPv4_AND_v6)) { + ue_ipv6 = &eps_bearer_ctxt_p->paa.ipv6_address; + } + + int vlan = eps_bearer_ctxt_p->paa.vlan; + Imsi_t imsi = sgw_context_p->imsi; + + char ip6_str[INET6_ADDRSTRLEN]; + if (ue_ipv6) { + inet_ntop(AF_INET6, ue_ipv6, ip6_str, INET6_ADDRSTRLEN); + } + OAILOG_DEBUG_UE( + LOG_SGW_S8, sgw_context_p->imsi64, + "Adding tunnel for bearer_id %u ue addr %x enb %x s_gw_teid_S5_S8_up %x, " + "s_gw_ip_address_S5_S8_up %x pgw_up_ip %x pgw_up_teid %x \n", + eps_bearer_ctxt_p->eps_bearer_id, ue_ipv4.s_addr, enb.s_addr, + eps_bearer_ctxt_p->s_gw_teid_S5_S8_up, + eps_bearer_ctxt_p->s_gw_ip_address_S5_S8_up.address.ipv4_address.s_addr, + pgw.s_addr, eps_bearer_ctxt_p->p_gw_teid_S5_S8_up); + if (eps_bearer_ctxt_p->eps_bearer_id == + sgw_context_p->pdn_connection.default_bearer) { + // Set default precedence and tft for default bearer + if (ue_ipv6) { + OAILOG_INFO_UE( + LOG_SGW_S8, sgw_context_p->imsi64, + "Adding tunnel for ipv6 ue addr %s, enb %x, " + "s_gw_teid_S5_S8_up %x, s_gw_ip_address_S5_S8_up %x pgw_up_ip %x " + "pgw_up_teid %x \n", + ip6_str, enb.s_addr, eps_bearer_ctxt_p->s_gw_teid_S5_S8_up, + eps_bearer_ctxt_p->s_gw_ip_address_S5_S8_up.address.ipv4_address + .s_addr, + pgw.s_addr, eps_bearer_ctxt_p->p_gw_teid_S5_S8_up); + } + rv = gtpv1u_add_s8_tunnel( + ue_ipv4, ue_ipv6, vlan, enb, pgw, eps_bearer_ctxt_p->s_gw_teid_S5_S8_up, + eps_bearer_ctxt_p->p_gw_teid_S5_S8_up, imsi, NULL, DEFAULT_PRECEDENCE); + if (rv < 0) { + OAILOG_ERROR_UE( + LOG_SGW_S8, sgw_context_p->imsi64, + "ERROR in setting up TUNNEL err=%d\n", rv); + } + } + OAILOG_FUNC_RETURN(LOG_SGW_S8, rv); +} diff --git a/lte/gateway/c/oai/tasks/sgw_s8/sgw_s8_s11_handlers.h b/lte/gateway/c/oai/tasks/sgw_s8/sgw_s8_s11_handlers.h index 059f69b5064e..e6e13379c403 100644 --- a/lte/gateway/c/oai/tasks/sgw_s8/sgw_s8_s11_handlers.h +++ b/lte/gateway/c/oai/tasks/sgw_s8/sgw_s8_s11_handlers.h @@ -24,3 +24,8 @@ void sgw_s8_handle_s11_create_session_request( void sgw_s8_handle_create_session_response( sgw_state_t* sgw_state, s8_create_session_response_t* session_rsp_p, imsi64_t imsi64); + +void sgw_s8_handle_modify_bearer_request( + sgw_state_t* state, + const itti_s11_modify_bearer_request_t* const modify_bearer_pP, + imsi64_t imsi64); diff --git a/lte/gateway/c/oai/tasks/sgw_s8/sgw_s8_task.c b/lte/gateway/c/oai/tasks/sgw_s8/sgw_s8_task.c index d48e6780b42b..3a4c8787e438 100644 --- a/lte/gateway/c/oai/tasks/sgw_s8/sgw_s8_task.c +++ b/lte/gateway/c/oai/tasks/sgw_s8/sgw_s8_task.c @@ -76,6 +76,11 @@ static int handle_message(zloop_t* loop, zsock_t* reader, void* arg) { sgw_state, &received_message_p->ittiMsg.s8_create_session_rsp, imsi64); } break; + case S11_MODIFY_BEARER_REQUEST: { + sgw_s8_handle_modify_bearer_request( + sgw_state, &received_message_p->ittiMsg.s11_modify_bearer_request, + imsi64); + } break; default: { OAILOG_DEBUG(