From 5e33fa70faea5e7be116318209fda68bbf778072 Mon Sep 17 00:00:00 2001 From: rashmi Date: Tue, 2 Mar 2021 06:44:24 +0530 Subject: [PATCH 1/8] Added SGW_S8 contexts Signed-off-by: rashmi --- .../c/oai/include/sgw_context_manager.h | 71 ++++++++++++ lte/gateway/c/oai/include/sgw_s8_state.h | 93 +++++++++++++++ lte/gateway/c/oai/include/spgw_config.h | 1 + lte/gateway/c/oai/include/spgw_state.h | 2 +- lte/gateway/c/oai/include/spgw_types.h | 8 ++ lte/gateway/c/oai/oai_mme/CMakeLists.txt | 3 +- lte/gateway/c/oai/oai_mme/oai_mme.c | 2 +- lte/gateway/c/oai/tasks/CMakeLists.txt | 2 +- .../c/oai/tasks/gtpv1-u/CMakeLists.txt | 2 +- .../c/oai/tasks/sgw/sgw_context_manager.c | 2 +- lte/gateway/c/oai/tasks/sgw/spgw_state.cpp | 2 +- .../c/oai/tasks/sgw/spgw_state_manager.cpp | 2 +- lte/gateway/c/oai/tasks/sgw_s8/CMakeLists.txt | 29 ++++- .../c/oai/tasks/sgw_s8/sgw_s11_handlers.h | 32 ++++++ lte/gateway/c/oai/tasks/sgw_s8/sgw_s8_defs.h | 3 +- .../c/oai/tasks/sgw_s8/sgw_s8_handlers.c | 75 +++++++++++++ lte/gateway/c/oai/tasks/sgw_s8/sgw_s8_task.c | 16 ++- lte/gateway/c/oai/tasks/sgw_s8/sgw_state.cpp | 61 ++++++++++ .../oai/tasks/sgw_s8/sgw_state_converter.cpp | 52 +++++++++ .../c/oai/tasks/sgw_s8/sgw_state_converter.h | 73 ++++++++++++ .../c/oai/tasks/sgw_s8/sgw_state_manager.cpp | 106 ++++++++++++++++++ .../c/oai/tasks/sgw_s8/sgw_state_manager.h | 88 +++++++++++++++ 22 files changed, 713 insertions(+), 12 deletions(-) create mode 100644 lte/gateway/c/oai/include/sgw_context_manager.h create mode 100644 lte/gateway/c/oai/include/sgw_s8_state.h create mode 100644 lte/gateway/c/oai/tasks/sgw_s8/sgw_s11_handlers.h create mode 100644 lte/gateway/c/oai/tasks/sgw_s8/sgw_s8_handlers.c create mode 100644 lte/gateway/c/oai/tasks/sgw_s8/sgw_state.cpp create mode 100644 lte/gateway/c/oai/tasks/sgw_s8/sgw_state_converter.cpp create mode 100644 lte/gateway/c/oai/tasks/sgw_s8/sgw_state_converter.h create mode 100644 lte/gateway/c/oai/tasks/sgw_s8/sgw_state_manager.cpp create mode 100644 lte/gateway/c/oai/tasks/sgw_s8/sgw_state_manager.h diff --git a/lte/gateway/c/oai/include/sgw_context_manager.h b/lte/gateway/c/oai/include/sgw_context_manager.h new file mode 100644 index 000000000000..c1b250d73638 --- /dev/null +++ b/lte/gateway/c/oai/include/sgw_context_manager.h @@ -0,0 +1,71 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the terms found in the LICENSE file in the root of this source tree. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file sgw_context_manager.h + * \brief + * \author Lionel Gauthier + * \company Eurecom + * \email: lionel.gauthier@eurecom.fr + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include "3gpp_24.007.h" + +#include "spgw_state.h" + +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( + s_plus_p_gw_eps_bearer_context_information_t* sp_context_information); +void pgw_lite_cm_free_apn(pgw_apn_t** apnP); + +teid_t sgw_get_new_S11_tunnel_id(spgw_state_t* state); +mme_sgw_tunnel_t* sgw_cm_create_s11_tunnel( + teid_t remote_teid, teid_t local_teid); +s_plus_p_gw_eps_bearer_context_information_t* +sgw_cm_create_bearer_context_information_in_collection( + spgw_state_t* spgw_state, teid_t teid, imsi64_t imsi64); +int sgw_cm_remove_bearer_context_information( + spgw_state_t* state, teid_t teid, imsi64_t imsi64); +sgw_eps_bearer_ctxt_t* sgw_cm_create_eps_bearer_ctxt_in_collection( + sgw_pdn_connection_t* const sgw_pdn_connection, const ebi_t eps_bearer_idP); +sgw_eps_bearer_ctxt_t* sgw_cm_insert_eps_bearer_ctxt_in_collection( + sgw_pdn_connection_t* const sgw_pdn_connection, + sgw_eps_bearer_ctxt_t* const sgw_eps_bearer_ctxt); +sgw_eps_bearer_ctxt_t* sgw_cm_get_eps_bearer_entry( + sgw_pdn_connection_t* const sgw_pdn_connection, ebi_t ebi); +int sgw_cm_remove_eps_bearer_entry( + sgw_pdn_connection_t* const sgw_pdn_connection, ebi_t eps_bearer_idP); +// Returns SPGW state pointer for given UE indexed by IMSI +s_plus_p_gw_eps_bearer_context_information_t* sgw_cm_get_spgw_context( + teid_t teid); +spgw_ue_context_t* spgw_create_or_get_ue_context( + spgw_state_t* spgw_state, imsi64_t imsi64); + +int spgw_update_teid_in_ue_context( + spgw_state_t* spgw_state, imsi64_t imsi64, teid_t teid); + +#ifdef __cplusplus +} +#endif diff --git a/lte/gateway/c/oai/include/sgw_s8_state.h b/lte/gateway/c/oai/include/sgw_s8_state.h new file mode 100644 index 000000000000..31862b5bfe6b --- /dev/null +++ b/lte/gateway/c/oai/include/sgw_s8_state.h @@ -0,0 +1,93 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the terms found in the LICENSE file in the root of this source tree. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "hashtable.h" +#include "spgw_types.h" +#include "sgw_config.h" + +// Initializes SGW state struct when task process starts. +int sgw_state_init(bool persist_state, const sgw_config_t* config); + +// Function that frees sgw_state. +void sgw_state_exit(void); + +// Function that returns a pointer to sgw_state. +sgw_state_t* get_sgw_state(bool read_from_db); + +// Function that writes the sgw_state struct into db. +void put_sgw_state(void); + +/** + * Returns pointer to SGW UE state + * @return hashtable_ts_t struct with SGW UE context structs as data + */ +hash_table_ts_t* get_sgw_ue_state(void); + +/** + * Populates SGW UE hashtable from db + * @return response code + */ +int read_sgw_ue_state_db(void); + +/** + * Saves an UE context state to db + * @param pointer to SGW's state + * @param imsi64 + */ +void put_sgw_ue_state(sgw_state_t* sgw_state, imsi64_t imsi64); + +/** + * Removes entry for SGW UE state in db + * @param imsi64 + */ +void delete_sgw_ue_state(imsi64_t imsi64); + +/** + * Callback function for s11_bearer_context_information hashtable freefunc + * @param context_p sgw eps bearer context entry on hashtable + */ +void sgw_free_s11_bearer_context_information( + sgw_eps_bearer_context_information_t** context_p); + +/** + * Frees pdn connection and its contained objects + * @param pdn_connection_p + */ +void sgw_free_pdn_connection(sgw_pdn_connection_t* pdn_connection_p); + +/** + * Frees sgw_eps_bearer_ctxt entry + * @param sgw_eps_bearer_ctxt + */ +void sgw_free_eps_bearer_context(sgw_eps_bearer_ctxt_t** sgw_eps_bearer_ctxt); + +/** + * Callback function for imsi_ue_context hashtable's freefunc + * @param spgw_ue_context_t + */ +void sgw_free_ue_context(spgw_ue_context_t** ue_context_p); + +#ifdef __cplusplus +} +#endif diff --git a/lte/gateway/c/oai/include/spgw_config.h b/lte/gateway/c/oai/include/spgw_config.h index 4ea88b18f525..3eb09fd45a7d 100644 --- a/lte/gateway/c/oai/include/spgw_config.h +++ b/lte/gateway/c/oai/include/spgw_config.h @@ -43,6 +43,7 @@ typedef struct spgw_config_s { #ifndef SGW extern spgw_config_t spgw_config; +extern sgw_config_t sgw_config; #endif void spgw_config_init(spgw_config_t*); diff --git a/lte/gateway/c/oai/include/spgw_state.h b/lte/gateway/c/oai/include/spgw_state.h index 561cde4913cd..0f575e3e8c0f 100644 --- a/lte/gateway/c/oai/include/spgw_state.h +++ b/lte/gateway/c/oai/include/spgw_state.h @@ -67,7 +67,7 @@ void delete_spgw_ue_state(imsi64_t imsi64); * Callback function for s11_bearer_context_information hashtable freefunc * @param context_p spgw eps bearer context entry on hashtable */ -void sgw_free_s11_bearer_context_information( +void spgw_free_s11_bearer_context_information( s_plus_p_gw_eps_bearer_context_information_t** context_p); /** * Frees pdn connection and its contained objects diff --git a/lte/gateway/c/oai/include/spgw_types.h b/lte/gateway/c/oai/include/spgw_types.h index 26a8436ce579..de757a98f681 100644 --- a/lte/gateway/c/oai/include/spgw_types.h +++ b/lte/gateway/c/oai/include/spgw_types.h @@ -80,6 +80,14 @@ typedef struct mme_sgw_tunnel_s { uint32_t remote_teid; ///< Remote tunnel endpoint Identifier } mme_sgw_tunnel_t; +// AGW-wide state for SGW task +typedef struct sgw_state_s { + teid_t tunnel_id; + uint32_t gtpv1u_teid; + struct in_addr sgw_ip_address_S1u_S12_S4_up; + hash_table_ts_t* imsi_ue_context_htbl; +} sgw_state_t; + // AGW-wide state for SPGW task typedef struct spgw_state_s { STAILQ_HEAD(ipv4_list_allocated_s, ipv4_list_elm_s) ipv4_list_allocated; diff --git a/lte/gateway/c/oai/oai_mme/CMakeLists.txt b/lte/gateway/c/oai/oai_mme/CMakeLists.txt index 592a319df270..4edcf67200b7 100644 --- a/lte/gateway/c/oai/oai_mme/CMakeLists.txt +++ b/lte/gateway/c/oai/oai_mme/CMakeLists.txt @@ -45,7 +45,7 @@ target_link_libraries(mme LIB_HASHTABLE LIB_S6A_PROXY TASK_S1AP TASK_SCTP_SERVER TASK_SGS TASK_SMS_ORC8R TASK_S6A TASK_MME_APP TASK_GRPC_SERVICE TASK_NAS TASK_HA - TASK_SGW_S8 ${ITTI_LIB} ${GCOV_LIB} + ${ITTI_LIB} ${GCOV_LIB} -Wl,--end-group ${LFDS} pthread m sctp rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES} gnutls ${SERVICE303_LIB} @@ -57,6 +57,7 @@ if ( NOT EMBEDDED_SGW ) LIB_GTPV2C TASK_UDP) else ( EMBEDDED_SGW ) target_link_libraries(mme TASK_SGW) +target_link_libraries(mme TASK_SGW_S8) endif ( NOT EMBEDDED_SGW ) if ( NOT S6A_OVER_GRPC ) diff --git a/lte/gateway/c/oai/oai_mme/oai_mme.c b/lte/gateway/c/oai/oai_mme/oai_mme.c index 25a324a33228..eee4b92f31df 100644 --- a/lte/gateway/c/oai/oai_mme/oai_mme.c +++ b/lte/gateway/c/oai/oai_mme/oai_mme.c @@ -127,6 +127,7 @@ int main(int argc, char* argv[]) { CHECK_INIT_RETURN(sctp_init(&mme_config)); #if EMBEDDED_SGW CHECK_INIT_RETURN(spgw_app_init(&spgw_config, mme_config.use_stateless)); + CHECK_INIT_RETURN(sgw_s8_init(&sgw_config)); #else CHECK_INIT_RETURN(udp_init()); CHECK_INIT_RETURN(s11_mme_init(&mme_config)); @@ -134,7 +135,6 @@ int main(int argc, char* argv[]) { CHECK_INIT_RETURN(s1ap_mme_init(&mme_config)); CHECK_INIT_RETURN(s6a_init(&mme_config)); - CHECK_INIT_RETURN(sgw_s8_init()); // Create SGS Task only if non_eps_service_control is not set to OFF char* non_eps_service_control = bdata(mme_config.non_eps_service_control); if (!(strcmp(non_eps_service_control, "SMS")) || diff --git a/lte/gateway/c/oai/tasks/CMakeLists.txt b/lte/gateway/c/oai/tasks/CMakeLists.txt index 76b14296fb4c..82663d6cb2b6 100644 --- a/lte/gateway/c/oai/tasks/CMakeLists.txt +++ b/lte/gateway/c/oai/tasks/CMakeLists.txt @@ -8,11 +8,11 @@ add_subdirectory(sgs) # TASK_SGS add_subdirectory(sms_orc8r) # TASK_SMS_ORC8R add_subdirectory(grpc_service) # TASK_GRPC_SERVICE add_subdirectory(ha) # TASK_HA -add_subdirectory(sgw_s8) # TASK_SGW_S8 if (EMBEDDED_SGW) add_subdirectory(gtpv1-u) # TASK_GTPV1U add_subdirectory(sgw) # TASK_SGW +add_subdirectory(sgw_s8) # TASK_SGW_S8 else (EMBEDDED_SGW) add_subdirectory(s11) # TASK_S11 add_subdirectory(udp) #TASK_UDP diff --git a/lte/gateway/c/oai/tasks/gtpv1-u/CMakeLists.txt b/lte/gateway/c/oai/tasks/gtpv1-u/CMakeLists.txt index e619c689aee1..341f308d64d2 100644 --- a/lte/gateway/c/oai/tasks/gtpv1-u/CMakeLists.txt +++ b/lte/gateway/c/oai/tasks/gtpv1-u/CMakeLists.txt @@ -20,5 +20,5 @@ target_include_directories(TASK_GTPV1U PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(TASK_GTPV1U COMMON LIB_BSTR LIB_HASHTABLE LIB_OPENFLOW_CONTROLLER LIB_MOBILITY_CLIENT - TASK_NAS TASK_MME_APP TASK_SERVICE303 TASK_SGW + TASK_NAS TASK_MME_APP TASK_SERVICE303 TASK_SGW TASK_SGW_S8 ) 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 a501bc156df9..70f87d83acf2 100644 --- a/lte/gateway/c/oai/tasks/sgw/sgw_context_manager.c +++ b/lte/gateway/c/oai/tasks/sgw/sgw_context_manager.c @@ -195,7 +195,7 @@ sgw_cm_create_bearer_context_information_in_collection( "Failed to create APN collection object entry for EPS bearer S11 " "teid " TEID_FMT "\n", teid); - sgw_free_s11_bearer_context_information(&new_bearer_context_information); + spgw_free_s11_bearer_context_information(&new_bearer_context_information); return NULL; } diff --git a/lte/gateway/c/oai/tasks/sgw/spgw_state.cpp b/lte/gateway/c/oai/tasks/sgw/spgw_state.cpp index bf9755ad9201..9c1a4b78a0ab 100644 --- a/lte/gateway/c/oai/tasks/sgw/spgw_state.cpp +++ b/lte/gateway/c/oai/tasks/sgw/spgw_state.cpp @@ -77,7 +77,7 @@ void delete_spgw_ue_state(imsi64_t imsi64) { SpgwStateManager::getInstance().clear_ue_state_db(imsi_str); } -void sgw_free_s11_bearer_context_information( +void spgw_free_s11_bearer_context_information( s_plus_p_gw_eps_bearer_context_information_t** context_p) { if (*context_p) { sgw_free_pdn_connection( diff --git a/lte/gateway/c/oai/tasks/sgw/spgw_state_manager.cpp b/lte/gateway/c/oai/tasks/sgw/spgw_state_manager.cpp index 31cb6d4b1990..0433d0f8d061 100644 --- a/lte/gateway/c/oai/tasks/sgw/spgw_state_manager.cpp +++ b/lte/gateway/c/oai/tasks/sgw/spgw_state_manager.cpp @@ -55,7 +55,7 @@ void SpgwStateManager::create_state() { bstring b = bfromcstr(S11_BEARER_CONTEXT_INFO_HT_NAME); state_ue_ht = hashtable_ts_create( SGW_STATE_CONTEXT_HT_MAX_SIZE, nullptr, - (void (*)(void**)) sgw_free_s11_bearer_context_information, b); + (void (*)(void**)) spgw_free_s11_bearer_context_information, b); state_cache_p->sgw_ip_address_S1u_S12_S4_up.s_addr = config_->sgw_config.ipv4.S1u_S12_S4_up.s_addr; diff --git a/lte/gateway/c/oai/tasks/sgw_s8/CMakeLists.txt b/lte/gateway/c/oai/tasks/sgw_s8/CMakeLists.txt index 65d50309ce26..a76353a57a97 100644 --- a/lte/gateway/c/oai/tasks/sgw_s8/CMakeLists.txt +++ b/lte/gateway/c/oai/tasks/sgw_s8/CMakeLists.txt @@ -1,10 +1,35 @@ +# compile required protos +set(SGW_LTE_CPP_PROTOS spgw_state sgw_state common_types std_3gpp_types) +list(APPEND PROTO_SRCS "") +list(APPEND PROTO_HDRS "") + +set(STATE_OUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/lte/protos/oai") +generate_cpp_protos("${SGW_LTE_CPP_PROTOS}" "${PROTO_SRCS}" "${PROTO_HDRS}" + "${STATE_PROTO_DIR}" "${STATE_OUT_DIR}") + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) +include_directories(${STATE_OUT_DIR}) + +message("s8 Proto_srcs are ${PROTO_SRCS}") +message("s8 Proto_includes are ${PROTO_HDRS}") set (SGW_S8_SRC sgw_s8_task.c + sgw_s8_handlers.c + sgw_state.cpp + sgw_state_manager.cpp + sgw_state_converter.cpp + ${PROTO_SRCS} + ${PROTO_HDRS} ) - add_library(TASK_SGW_S8 ${SGW_S8_SRC}) -target_link_libraries(TASK_SGW_S8 COMMON LIB_BSTR LIB_HASHTABLE) + +target_link_libraries(TASK_SGW_S8 + COMMON + LIB_BSTR LIB_HASHTABLE + LIB_OPENFLOW_CONTROLLER TASK_SERVICE303 + cpp_redis tacopie protobuf +) target_include_directories(TASK_SGW_S8 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} diff --git a/lte/gateway/c/oai/tasks/sgw_s8/sgw_s11_handlers.h b/lte/gateway/c/oai/tasks/sgw_s8/sgw_s11_handlers.h new file mode 100644 index 000000000000..8d890a78f627 --- /dev/null +++ b/lte/gateway/c/oai/tasks/sgw_s8/sgw_s11_handlers.h @@ -0,0 +1,32 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the terms found in the LICENSE file in the root of this source tree. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file sgw_s11_handlers.h + * \brief + * \author + * \company + * \email + */ + +#pragma once +#include "common_types.h" +#include "s11_messages_types.h" +#include "intertask_interface.h" + +int sgw_s8_handle_s11_create_session_request( + const itti_s11_create_session_request_t* const session_req_p, + imsi64_t imsi64); diff --git a/lte/gateway/c/oai/tasks/sgw_s8/sgw_s8_defs.h b/lte/gateway/c/oai/tasks/sgw_s8/sgw_s8_defs.h index 51005c5cde57..bf1b48f6b740 100644 --- a/lte/gateway/c/oai/tasks/sgw_s8/sgw_s8_defs.h +++ b/lte/gateway/c/oai/tasks/sgw_s8/sgw_s8_defs.h @@ -14,7 +14,8 @@ limitations under the License. #pragma once #include "intertask_interface.h" +#include "sgw_config.h" extern task_zmq_ctx_t sgw_s8_task_zmq_ctx; -int sgw_s8_init(void); +int sgw_s8_init(sgw_config_t* sgw_config_p); 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 new file mode 100644 index 000000000000..34ded2b31517 --- /dev/null +++ b/lte/gateway/c/oai/tasks/sgw_s8/sgw_s8_handlers.c @@ -0,0 +1,75 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the terms found in the LICENSE file in the root of this source tree. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file sgw_s8_handlers.c + \brief + \author + \company + \email: +*/ +#include +#include +#include "log.h" +#include "common_defs.h" +#include "intertask_interface.h" +#include "common_types.h" +#include "sgw_context_manager.h" + +int sgw_s8_handle_s11_create_session_request( + const itti_s11_create_session_request_t* const session_req_pP, + imsi64_t imsi64) { + OAILOG_FUNC_IN(LOG_SGW_S8); + OAILOG_INFO_UE( + LOG_SGW_S8, imsi64, "Received S11 CREATE SESSION REQUEST from MME_APP\n"); +#if 0 + sgw_eps_bearer_context_information_t* sgw_eps_bearer_ctxt_info_p = NULL; + mme_sgw_tunnel_t sgw_s11_tunnel = {0}; + + increment_counter("spgw_create_session", 1, NO_LABELS); + if (session_req_pP->rat_type != RAT_EUTRAN) { + OAILOG_WARNING_UE( + LOG_SGW_S8, imsi64, + "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... + OAILOG_ERROR_UE(LOG_SGW_S8, imsi64, "Received invalid teid \n"); + increment_counter( + "spgw_create_session", 1, 2, "result", "failure", "cause", + "sender_fteid_incorrect_parameters"); + OAILOG_FUNC_RETURN(LOG_SGW_S8, RETURNerror); + } + sgw_s11_tunnel.local_teid = 1; + sgw_s11_tunnel.remote_teid = session_req_pP->sender_fteid_for_cp.teid; + mme_sgw_tunnel_t* new_endpoint_p = NULL; + new_endpoint_p = + sgw_cm_create_s11_tunnel(session_req_pP->sender_fteid_for_cp.teid, 1); +#endif + + OAILOG_FUNC_RETURN(LOG_SGW_S8, RETURNok); +} 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 eb86c4531315..b0d1d78d012e 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 @@ -30,9 +30,13 @@ #include "common_defs.h" #include "itti_free_defined_msg.h" #include "sgw_s8_defs.h" +#include "sgw_s11_handlers.h" +#include "sgw_s8_state.h" static int handle_message(zloop_t* loop, zsock_t* reader, void* arg); static void sgw_s8_exit(void); + +sgw_config_t sgw_config; task_zmq_ctx_t sgw_s8_task_zmq_ctx; static void* sgw_s8_thread(void* args) { @@ -46,8 +50,12 @@ static void* sgw_s8_thread(void* args) { return NULL; } -int sgw_s8_init(void) { +int sgw_s8_init(sgw_config_t* sgw_config_p) { OAILOG_DEBUG(LOG_SGW_S8, "Initializing SGW-S8 interface\n"); + if (sgw_state_init(false, sgw_config_p) < 0) { + OAILOG_CRITICAL(LOG_SGW_S8, "Error while initializing SGW_S8 state\n"); + return RETURNerror; + } if (itti_create_task(TASK_SGW_S8, &sgw_s8_thread, NULL) < 0) { OAILOG_ERROR(LOG_SGW_S8, "Failed to create sgw_s8 task\n"); @@ -62,6 +70,8 @@ static int handle_message(zloop_t* loop, zsock_t* reader, void* arg) { assert(msg_frame); MessageDef* received_message_p = (MessageDef*) zframe_data(msg_frame); + imsi64_t imsi64 = itti_get_associated_imsi(received_message_p); + switch (ITTI_MSG_ID(received_message_p)) { case MESSAGE_TEST: { OAI_FPRINTF_INFO("TASK_SGW_S8 received MESSAGE_TEST\n"); @@ -73,6 +83,10 @@ static int handle_message(zloop_t* loop, zsock_t* reader, void* arg) { sgw_s8_exit(); } break; + case S11_CREATE_SESSION_REQUEST: { + sgw_s8_handle_s11_create_session_request( + &received_message_p->ittiMsg.s11_create_session_request, imsi64); + } break; default: { OAILOG_DEBUG( LOG_SGW_S8, "Unkwnon message ID %d: %s\n", diff --git a/lte/gateway/c/oai/tasks/sgw_s8/sgw_state.cpp b/lte/gateway/c/oai/tasks/sgw_s8/sgw_state.cpp new file mode 100644 index 000000000000..00f358e41138 --- /dev/null +++ b/lte/gateway/c/oai/tasks/sgw_s8/sgw_state.cpp @@ -0,0 +1,61 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the terms found in the LICENSE file in the root of this source tree. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------ + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "sgw_s8_state.h" + +#include +#include + +extern "C" { +#include "assertions.h" +#include "bstrlib.h" +#include "dynamic_memory_check.h" +#include "sgw_context_manager.h" +} + +#include "sgw_state_manager.h" + +using magma::lte::SgwStateManager; + +int sgw_state_init(bool persist_state, const sgw_config_t* config) { + SgwStateManager::getInstance().init(persist_state, config); + return RETURNok; +} + +sgw_state_t* get_sgw_state(bool read_from_db) { + return SgwStateManager::getInstance().get_state(read_from_db); +} + +hash_table_ts_t* get_sgw_ue_state() { + return SgwStateManager::getInstance().get_ue_state_ht(); +} + +int read_sgw_ue_state_db() { + return SgwStateManager::getInstance().read_ue_state_from_db(); +} + +void sgw_state_exit() { + SgwStateManager::getInstance().free_state(); +} + +void put_sgw_state() { + SgwStateManager::getInstance().write_state_to_db(); +} + +void put_sgw_ue_state(sgw_state_t* sgw_state, imsi64_t imsi64) {} + +void delete_sgw_ue_state(imsi64_t imsi64) {} diff --git a/lte/gateway/c/oai/tasks/sgw_s8/sgw_state_converter.cpp b/lte/gateway/c/oai/tasks/sgw_s8/sgw_state_converter.cpp new file mode 100644 index 000000000000..d3d58885c06f --- /dev/null +++ b/lte/gateway/c/oai/tasks/sgw_s8/sgw_state_converter.cpp @@ -0,0 +1,52 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the terms found in the LICENSE file in the root of this source tree. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------ + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +extern "C" { +#include "dynamic_memory_check.h" +#include "sgw_context_manager.h" +} + +#include "sgw_state_converter.h" + +using magma::lte::oai::SgwState; +using magma::lte::oai::SgwUeContext; + +namespace magma { +namespace lte { + +SgwStateConverter::SgwStateConverter() = default; +SgwStateConverter::~SgwStateConverter() = default; + +void SgwStateConverter::state_to_proto( + const sgw_state_t* sgw_state, SgwState* proto) { + proto->Clear(); +} + +void SgwStateConverter::proto_to_state( + const SgwState& proto, sgw_state_t* sgw_state) {} + +void SgwStateConverter::ue_to_proto( + const spgw_ue_context_t* ue_state, oai::SgwUeContext* ue_proto) {} + +void SgwStateConverter::proto_to_ue( + const oai::SgwUeContext& ue_proto, spgw_ue_context_t* ue_context_p) { + OAILOG_FUNC_IN(LOG_SGW_S8); + OAILOG_FUNC_OUT(LOG_SGW_S8); +} + +} // namespace lte +} // namespace magma diff --git a/lte/gateway/c/oai/tasks/sgw_s8/sgw_state_converter.h b/lte/gateway/c/oai/tasks/sgw_s8/sgw_state_converter.h new file mode 100644 index 000000000000..82ded7a098ab --- /dev/null +++ b/lte/gateway/c/oai/tasks/sgw_s8/sgw_state_converter.h @@ -0,0 +1,73 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the terms found in the LICENSE file in the root of this source tree. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------ + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "assertions.h" +#include "common_types.h" +#include "hashtable.h" + +#ifdef __cplusplus +} +#endif + +#include "state_converter.h" +#include "lte/protos/oai/sgw_state.pb.h" +#include "spgw_types.h" + +namespace magma { +namespace lte { + +/** + * Class for SGW_S8 tasks state conversion helper functions. + */ +class SgwStateConverter : StateConverter { + public: + /** + * Main function to convert SPGW state to proto definition + * @param sgw_state const pointer to sgw_state struct + * @param sgw_proto SgwState proto object to be written to + * Memory is owned by the caller + */ + static void state_to_proto( + const sgw_state_t* pgw_state, oai::SgwState* sgw_proto); + + /** + * Main function to convert SPGW proto to state definition + * @param sgw_proto SgwState proto object to be written to + * @param sgw_state const pointer to sgw_state struct + * Memory is owned by the caller + */ + static void proto_to_state( + const oai::SgwState& proto, sgw_state_t* sgw_state); + + static void ue_to_proto( + const spgw_ue_context_t* ue_state, oai::SgwUeContext* ue_proto); + + static void proto_to_ue( + const oai::SgwUeContext& ue_proto, spgw_ue_context_t* ue_context_p); + + private: + SgwStateConverter(); + ~SgwStateConverter(); +}; +} // namespace lte +} // namespace magma diff --git a/lte/gateway/c/oai/tasks/sgw_s8/sgw_state_manager.cpp b/lte/gateway/c/oai/tasks/sgw_s8/sgw_state_manager.cpp new file mode 100644 index 000000000000..095bff03e1a2 --- /dev/null +++ b/lte/gateway/c/oai/tasks/sgw_s8/sgw_state_manager.cpp @@ -0,0 +1,106 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the terms found in the LICENSE file in the root of this source tree. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------ + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +extern "C" { +#include +#include "backtrace.h" +} + +#include "sgw_state_manager.h" + +namespace magma { +namespace lte { + +SgwStateManager::SgwStateManager() : config_(nullptr) {} + +SgwStateManager::~SgwStateManager() { + free_state(); +} + +SgwStateManager& SgwStateManager::getInstance() { + static SgwStateManager instance; + return instance; +} + +void SgwStateManager::init(bool persist_state, const sgw_config_t* config) { + log_task = LOG_SGW_S8; + task_name = SGW_TASK_NAME; + table_key = SGW_STATE_TABLE_NAME; + persist_state_enabled = persist_state; + config_ = config; + create_state(); + if (read_state_from_db() != RETURNok) { + OAILOG_ERROR(LOG_SGW_S8, "Failed to read state from redis"); + } + is_initialized = true; +} + +void SgwStateManager::create_state() { + // Allocating sgw_state_p + state_cache_p = (sgw_state_t*) calloc(1, sizeof(sgw_state_t)); + display_backtrace(); + + OAILOG_INFO(LOG_SGW_S8, "Creating SGW_S8 state "); + bstring b = bfromcstr(S11_BEARER_CONTEXT_INFO_HT_NAME); + state_ue_ht = hashtable_ts_create( + SGW_STATE_CONTEXT_HT_MAX_SIZE, nullptr, + /*Rashmi TODO (void (*)(void**)) sgw_free_s11_bearer_context_information + */ + nullptr, b); + + state_cache_p->sgw_ip_address_S1u_S12_S4_up.s_addr = + config_->ipv4.S1u_S12_S4_up.s_addr; + + state_cache_p->imsi_ue_context_htbl = hashtable_ts_create( + SGW_STATE_CONTEXT_HT_MAX_SIZE, nullptr, + /* Rashmi TODO (void (*)(void**)) spgw_free_ue_context*/ nullptr, + nullptr); + + state_cache_p->tunnel_id = 0; + + state_cache_p->gtpv1u_teid = 0; + + bdestroy_wrapper(&b); +} + +void SgwStateManager::free_state() { + AssertFatal( + is_initialized, + "SgwStateManager init() function should be called to initialize state."); + + if (state_cache_p == nullptr) { + return; + } + + if (hashtable_ts_destroy(state_ue_ht) != HASH_TABLE_OK) { + OAI_FPRINTF_ERR( + "An error occurred while destroying SGW s11_bearer_context_information " + "hashtable"); + } + + hashtable_ts_destroy(state_cache_p->imsi_ue_context_htbl); + + free_wrapper((void**) &state_cache_p); +} + +int SgwStateManager::read_ue_state_from_db() { + /*TODO handle stateless */ + return RETURNok; +} + +} // namespace lte +} // namespace magma diff --git a/lte/gateway/c/oai/tasks/sgw_s8/sgw_state_manager.h b/lte/gateway/c/oai/tasks/sgw_s8/sgw_state_manager.h new file mode 100644 index 000000000000..bf56fd01d1ae --- /dev/null +++ b/lte/gateway/c/oai/tasks/sgw_s8/sgw_state_manager.h @@ -0,0 +1,88 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the terms found in the LICENSE file in the root of this source tree. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------ + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#pragma once + +#include +#include "sgw_s8_state.h" +#include "lte/protos/oai/sgw_state.pb.h" +#include "sgw_state_converter.h" + +namespace { +constexpr int SGW_STATE_CONTEXT_HT_MAX_SIZE = 512; +constexpr int MAX_PREDEFINED_PCC_RULES_HT_SIZE = 32; +constexpr char S11_BEARER_CONTEXT_INFO_HT_NAME[] = + "s11_bearer_context_information_htbl"; +constexpr char SGW_STATE_TABLE_NAME[] = "sgw_state"; +constexpr char SGW_TASK_NAME[] = "SGW"; +} // namespace + +namespace magma { +namespace lte { + +/** + * SgwStateManager is a singleton (thread-safe, destruction guaranteed) + * that contains functions to maintain SGW and PGW state, allocating and + * freeing state structs, and writing / reading state to db. + */ +class SgwStateManager : public StateManager< + sgw_state_t, spgw_ue_context_t, oai::SgwState, + oai::SgwUeContext, SgwStateConverter> { + public: + /** + * Returns an instance of SgwStateManager, guaranteed to be thread safe and + * initialized only once. + * @return SgwStateManager instance. + */ + static SgwStateManager& getInstance(); + /** + * Initialization function to initialize member variables. + * @param persist_state should read and write state from db + * @param config SPGW config struct + */ + void init(bool persist_state, const sgw_config_t* config); + + /** + * Singleton class, copy constructor and assignment operator are marked + * as deleted functions. + */ + // Making them public for better debugging logging. + SgwStateManager(SgwStateManager const&) = delete; + SgwStateManager& operator=(SgwStateManager const&) = delete; + + /** + * Frees all memory allocated on sgw_state_t. + */ + void free_state() override; + + int read_ue_state_from_db() override; + + private: + SgwStateManager(); + ~SgwStateManager(); + + /** + * Allocates a new sgw_state_t struct, and inits hashtables and state + * structs to default values. + */ + void create_state() override; + + const sgw_config_t* config_; +}; + +} // namespace lte +} // namespace magma From 790162fe02315c3909d331615353c14afc56280e Mon Sep 17 00:00:00 2001 From: rsarwad <30685618+rsarwad@users.noreply.github.com> Date: Tue, 2 Mar 2021 11:39:31 +0530 Subject: [PATCH 2/8] Added code to create SGW_S8 task (#5092) * Created new task i.e SGW_S8 Signed-off-by: rashmi --- lte/gateway/c/oai/common/log.c | 3 + lte/gateway/c/oai/common/log.h | 1 + lte/gateway/c/oai/include/tasks_def.h | 2 + lte/gateway/c/oai/oai_mme/CMakeLists.txt | 4 +- lte/gateway/c/oai/oai_mme/oai_mme.c | 2 + lte/gateway/c/oai/tasks/CMakeLists.txt | 1 + .../c/oai/tasks/mme_app/mme_app_main.c | 4 +- lte/gateway/c/oai/tasks/sgw_s8/CMakeLists.txt | 11 +++ lte/gateway/c/oai/tasks/sgw_s8/sgw_s8_defs.h | 20 +++++ lte/gateway/c/oai/tasks/sgw_s8/sgw_s8_task.c | 90 +++++++++++++++++++ 10 files changed, 134 insertions(+), 4 deletions(-) create mode 100644 lte/gateway/c/oai/tasks/sgw_s8/CMakeLists.txt create mode 100644 lte/gateway/c/oai/tasks/sgw_s8/sgw_s8_defs.h create mode 100644 lte/gateway/c/oai/tasks/sgw_s8/sgw_s8_task.c diff --git a/lte/gateway/c/oai/common/log.c b/lte/gateway/c/oai/common/log.c index 2257a437d899..617c1c416d89 100644 --- a/lte/gateway/c/oai/common/log.c +++ b/lte/gateway/c/oai/common/log.c @@ -656,6 +656,9 @@ int log_init( &g_oai_log.log_proto2str[LOG_S11][0], LOG_MAX_PROTO_NAME_LENGTH, "S11"); snprintf( &g_oai_log.log_proto2str[LOG_S6A][0], LOG_MAX_PROTO_NAME_LENGTH, "S6A"); + snprintf( + &g_oai_log.log_proto2str[LOG_SGW_S8][0], LOG_MAX_PROTO_NAME_LENGTH, + "SGW_S8"); snprintf( &g_oai_log.log_proto2str[LOG_SECU][0], LOG_MAX_PROTO_NAME_LENGTH, "SECU"); snprintf( diff --git a/lte/gateway/c/oai/common/log.h b/lte/gateway/c/oai/common/log.h index 0c2d4a301091..f2e6cf4781ca 100644 --- a/lte/gateway/c/oai/common/log.h +++ b/lte/gateway/c/oai/common/log.h @@ -167,6 +167,7 @@ typedef enum { LOG_ASYNC_SYSTEM, LOG_ASSERT, LOG_COMMON, + LOG_SGW_S8, MAX_LOG_PROTOS, } log_proto_t; diff --git a/lte/gateway/c/oai/include/tasks_def.h b/lte/gateway/c/oai/include/tasks_def.h index c351f00ab6ee..23f190530ccb 100644 --- a/lte/gateway/c/oai/include/tasks_def.h +++ b/lte/gateway/c/oai/include/tasks_def.h @@ -71,3 +71,5 @@ TASK_DEF(TASK_HA) TASK_DEF(TASK_NGAP) /// AMF Application task TASK_DEF(TASK_AMF_APP) +/// SGW_S8 task +TASK_DEF(TASK_SGW_S8) diff --git a/lte/gateway/c/oai/oai_mme/CMakeLists.txt b/lte/gateway/c/oai/oai_mme/CMakeLists.txt index 2fef261645c8..63260162160e 100644 --- a/lte/gateway/c/oai/oai_mme/CMakeLists.txt +++ b/lte/gateway/c/oai/oai_mme/CMakeLists.txt @@ -45,7 +45,7 @@ target_link_libraries(mme LIB_HASHTABLE LIB_S6A_PROXY TASK_S1AP TASK_SCTP_SERVER TASK_SGS TASK_SMS_ORC8R TASK_S6A TASK_MME_APP TASK_GRPC_SERVICE TASK_NAS TASK_HA - ${ITTI_LIB} ${GCOV_LIB} + ${ITTI_LIB} ${GCOV_LIB} -Wl,--end-group ${LFDS} pthread m sctp rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${CONFIG_LIBRARIES} gnutls ${SERVICE303_LIB} @@ -56,7 +56,7 @@ if ( NOT EMBEDDED_SGW ) target_link_libraries(mme LIB_GTPV2C TASK_UDP) else ( EMBEDDED_SGW ) -target_link_libraries(mme TASK_SGW) +target_link_libraries(mme TASK_SGW TASK_SGW_S8) endif ( NOT EMBEDDED_SGW ) if ( NOT S6A_OVER_GRPC ) diff --git a/lte/gateway/c/oai/oai_mme/oai_mme.c b/lte/gateway/c/oai/oai_mme/oai_mme.c index b80899b4a1a0..90aef56c0894 100644 --- a/lte/gateway/c/oai/oai_mme/oai_mme.c +++ b/lte/gateway/c/oai/oai_mme/oai_mme.c @@ -43,6 +43,7 @@ #include "sgs_defs.h" #include "sms_orc8r_defs.h" #include "ha_defs.h" +#include "sgw_s8_defs.h" #include "oai_mme.h" #include "pid_file.h" #include "service303_message_utils.h" @@ -126,6 +127,7 @@ int main(int argc, char* argv[]) { CHECK_INIT_RETURN(sctp_init(&mme_config)); #if EMBEDDED_SGW CHECK_INIT_RETURN(spgw_app_init(&spgw_config, mme_config.use_stateless)); + CHECK_INIT_RETURN(sgw_s8_init()); #else CHECK_INIT_RETURN(udp_init()); CHECK_INIT_RETURN(s11_mme_init(&mme_config)); diff --git a/lte/gateway/c/oai/tasks/CMakeLists.txt b/lte/gateway/c/oai/tasks/CMakeLists.txt index 286392697891..f2bbf97f5d69 100644 --- a/lte/gateway/c/oai/tasks/CMakeLists.txt +++ b/lte/gateway/c/oai/tasks/CMakeLists.txt @@ -13,6 +13,7 @@ add_subdirectory(ha) # TASK_HA if (EMBEDDED_SGW) add_subdirectory(gtpv1-u) # TASK_GTPV1U add_subdirectory(sgw) # TASK_SGW +add_subdirectory(sgw_s8) # TASK_SGW_S8 else (EMBEDDED_SGW) add_subdirectory(s11) # TASK_S11 add_subdirectory(udp) #TASK_UDP diff --git a/lte/gateway/c/oai/tasks/mme_app/mme_app_main.c b/lte/gateway/c/oai/tasks/mme_app/mme_app_main.c index 521fd44566cb..4365bab0e07f 100644 --- a/lte/gateway/c/oai/tasks/mme_app/mme_app_main.c +++ b/lte/gateway/c/oai/tasks/mme_app/mme_app_main.c @@ -456,8 +456,8 @@ static void* mme_app_thread(__attribute__((unused)) void* args) { init_task_context( TASK_MME_APP, (task_id_t[]){TASK_SPGW_APP, TASK_SGS, TASK_SMS_ORC8R, TASK_S11, TASK_S6A, - TASK_S1AP, TASK_SERVICE303, TASK_HA}, - 8, handle_message, &mme_app_task_zmq_ctx); + TASK_S1AP, TASK_SERVICE303, TASK_HA, TASK_SGW_S8}, + 9, handle_message, &mme_app_task_zmq_ctx); // Service started, but not healthy yet send_app_health_to_service303(&mme_app_task_zmq_ctx, TASK_MME_APP, false); diff --git a/lte/gateway/c/oai/tasks/sgw_s8/CMakeLists.txt b/lte/gateway/c/oai/tasks/sgw_s8/CMakeLists.txt new file mode 100644 index 000000000000..65d50309ce26 --- /dev/null +++ b/lte/gateway/c/oai/tasks/sgw_s8/CMakeLists.txt @@ -0,0 +1,11 @@ +set (SGW_S8_SRC + sgw_s8_task.c + ) + +add_library(TASK_SGW_S8 ${SGW_S8_SRC}) + +target_link_libraries(TASK_SGW_S8 COMMON LIB_BSTR LIB_HASHTABLE) + +target_include_directories(TASK_SGW_S8 PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} +) diff --git a/lte/gateway/c/oai/tasks/sgw_s8/sgw_s8_defs.h b/lte/gateway/c/oai/tasks/sgw_s8/sgw_s8_defs.h new file mode 100644 index 000000000000..51005c5cde57 --- /dev/null +++ b/lte/gateway/c/oai/tasks/sgw_s8/sgw_s8_defs.h @@ -0,0 +1,20 @@ +/* +Copyright 2020 The Magma Authors. + +This source code is licensed under the BSD-style license found in the +LICENSE file in the root directory of this source tree. + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#pragma once + +#include "intertask_interface.h" + +extern task_zmq_ctx_t sgw_s8_task_zmq_ctx; + +int sgw_s8_init(void); 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 new file mode 100644 index 000000000000..f735f95fb499 --- /dev/null +++ b/lte/gateway/c/oai/tasks/sgw_s8/sgw_s8_task.c @@ -0,0 +1,90 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the terms found in the LICENSE file in the root of this source tree. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file sgw_s8_task.c + \brief + \author + \company + \email: +*/ +#define SGW_S8 +#define SGW_S8_TASK_C + +#include +#include "log.h" +#include "assertions.h" +#include "common_defs.h" +#include "itti_free_defined_msg.h" +#include "sgw_s8_defs.h" + +static int handle_message(zloop_t* loop, zsock_t* reader, void* arg); +static void sgw_s8_exit(void); +task_zmq_ctx_t sgw_s8_task_zmq_ctx; + +static void* sgw_s8_thread(void* args) { + itti_mark_task_ready(TASK_SGW_S8); + init_task_context( + TASK_SGW_S8, (task_id_t[]){TASK_MME_APP}, 1, handle_message, + &sgw_s8_task_zmq_ctx); + + zloop_start(sgw_s8_task_zmq_ctx.event_loop); + sgw_s8_exit(); + return NULL; +} + +int sgw_s8_init(void) { + OAILOG_DEBUG(LOG_SGW_S8, "Initializing SGW-S8 interface\n"); + + if (itti_create_task(TASK_SGW_S8, &sgw_s8_thread, NULL) < 0) { + OAILOG_ERROR(LOG_SGW_S8, "Failed to create sgw_s8 task\n"); + return RETURNerror; + } + OAILOG_DEBUG(LOG_SGW_S8, "Done initialization of SGW_S8 interface\n"); + return RETURNok; +} + +static int handle_message(zloop_t* loop, zsock_t* reader, void* arg) { + zframe_t* msg_frame = zframe_recv(reader); + assert(msg_frame); + MessageDef* received_message_p = (MessageDef*) zframe_data(msg_frame); + + switch (ITTI_MSG_ID(received_message_p)) { + case TERMINATE_MESSAGE: { + itti_free_msg_content(received_message_p); + zframe_destroy(&msg_frame); + sgw_s8_exit(); + } break; + + default: { + OAILOG_DEBUG( + LOG_SGW_S8, "Unkwnon message ID %d: %s\n", + ITTI_MSG_ID(received_message_p), ITTI_MSG_NAME(received_message_p)); + } break; + } + + itti_free_msg_content(received_message_p); + zframe_destroy(&msg_frame); + return 0; +} + +//------------------------------------------------------------------------------ +static void sgw_s8_exit(void) { + destroy_task_context(&sgw_s8_task_zmq_ctx); + OAILOG_DEBUG(LOG_SGW_S8, "Finished cleaning up SGW_S8 task \n"); + OAI_FPRINTF_INFO("TASK_SGW_S8 terminated\n"); + pthread_exit(NULL); +} From 3bb03b679abfc06268ea19bc811f23797f1b33b8 Mon Sep 17 00:00:00 2001 From: Marie <37634144+themarwhal@users.noreply.github.com> Date: Tue, 2 Mar 2021 08:15:41 -0600 Subject: [PATCH 3/8] Add additional formats for sctp (#5252) Signed-off-by: Marie Bremner --- lte/gateway/c/sctpd/sctp_assoc.cpp | 25 +++-- lte/gateway/c/sctpd/sctp_assoc.h | 18 ++-- lte/gateway/c/sctpd/sctp_connection.cpp | 96 +++++++++---------- lte/gateway/c/sctpd/sctp_connection.h | 31 +++--- lte/gateway/c/sctpd/sctp_desc.cpp | 32 +++---- lte/gateway/c/sctpd/sctp_desc.h | 8 +- lte/gateway/c/sctpd/sctpd.cpp | 14 +-- lte/gateway/c/sctpd/sctpd_downlink_impl.cpp | 93 ++++++++---------- lte/gateway/c/sctpd/sctpd_downlink_impl.h | 25 ++--- lte/gateway/c/sctpd/sctpd_event_handler.cpp | 20 ++-- lte/gateway/c/sctpd/sctpd_event_handler.h | 6 +- lte/gateway/c/sctpd/sctpd_uplink_client.cpp | 17 ++-- lte/gateway/c/sctpd/sctpd_uplink_client.h | 10 +- .../c/sctpd/test/test_event_handler.cpp | 65 ++++++------- lte/gateway/c/sctpd/test/test_sctp_desc.cpp | 28 +++--- lte/gateway/c/sctpd/util.cpp | 81 +++++++--------- 16 files changed, 253 insertions(+), 316 deletions(-) diff --git a/lte/gateway/c/sctpd/sctp_assoc.cpp b/lte/gateway/c/sctpd/sctp_assoc.cpp index c745b167778c..b576346ab06a 100644 --- a/lte/gateway/c/sctpd/sctp_assoc.cpp +++ b/lte/gateway/c/sctpd/sctp_assoc.cpp @@ -20,22 +20,19 @@ namespace magma { namespace sctpd { -SctpAssoc::SctpAssoc(): - sd(0), - ppid(0), - instreams(0), - outstreams(0), - assoc_id(0), - messages_recv(0), - messages_sent(0) -{ -} +SctpAssoc::SctpAssoc() + : sd(0), + ppid(0), + instreams(0), + outstreams(0), + assoc_id(0), + messages_recv(0), + messages_sent(0) {} -void SctpAssoc::dump() const -{ +void SctpAssoc::dump() const { MLOG(MDEBUG) << "SctpAssocassoc_id) << ">" << std::endl; } -} // namespace sctpd -} // namespace magma +} // namespace sctpd +} // namespace magma diff --git a/lte/gateway/c/sctpd/sctp_assoc.h b/lte/gateway/c/sctpd/sctp_assoc.h index 326aeea674d3..a3128c01d3cc 100644 --- a/lte/gateway/c/sctpd/sctp_assoc.h +++ b/lte/gateway/c/sctpd/sctp_assoc.h @@ -21,13 +21,13 @@ namespace sctpd { // Models the state of an SCTP association class SctpAssoc { public: - int sd; ///< Socket descriptor - uint32_t ppid; ///< Payload protocol Identifier - uint16_t instreams; ///< Number of input streams negotiated - uint16_t outstreams; ///< Number of output strams negotiated - uint32_t assoc_id; ///< SCTP association id - uint32_t messages_recv; ///< Number of messages received - uint32_t messages_sent; ///< Number of messages sent + int sd; ///< Socket descriptor + uint32_t ppid; ///< Payload protocol Identifier + uint16_t instreams; ///< Number of input streams negotiated + uint16_t outstreams; ///< Number of output strams negotiated + uint32_t assoc_id; ///< SCTP association id + uint32_t messages_recv; ///< Number of messages received + uint32_t messages_sent; ///< Number of messages sent SctpAssoc(); @@ -35,5 +35,5 @@ class SctpAssoc { void dump() const; }; -} // namespace sctpd -} // namespace magma +} // namespace sctpd +} // namespace magma diff --git a/lte/gateway/c/sctpd/sctp_connection.cpp b/lte/gateway/c/sctpd/sctp_connection.cpp index 19e718f79ff8..bbaa078b4786 100644 --- a/lte/gateway/c/sctpd/sctp_connection.cpp +++ b/lte/gateway/c/sctpd/sctp_connection.cpp @@ -32,30 +32,26 @@ namespace sctpd { const int NUM_EPOLL_EVENTS = 10; -SctpConnection::SctpConnection(const InitReq &req, SctpEventHandler &handler): - _done(false), - _handler(handler), - _ppid(req.ppid()), - _sctp_desc(0), - _thread(nullptr) -{ - +SctpConnection::SctpConnection(const InitReq& req, SctpEventHandler& handler) + : _done(false), + _handler(handler), + _ppid(req.ppid()), + _sctp_desc(0), + _thread(nullptr) { int sock = create_sctp_sock(req); if (sock < 0) throw std::exception(); _sctp_desc = SctpDesc(sock); } -void SctpConnection::Start() -{ +void SctpConnection::Start() { assert(_done == false); assert(_thread == nullptr); _thread = std::make_unique(&SctpConnection::Listen, this); } -void SctpConnection::Close() -{ +void SctpConnection::Close() { assert(_done == false); assert(_thread != nullptr); @@ -71,19 +67,16 @@ void SctpConnection::Close() } void SctpConnection::Send( - uint32_t assoc_id, - uint32_t stream, - const std::string &msg) -{ + uint32_t assoc_id, uint32_t stream, const std::string& msg) { assert(_thread != nullptr); auto assoc = _sctp_desc.getAssoc(assoc_id); assert(assoc.sd >= 0); auto buf = msg.c_str(); - auto n = msg.size(); - auto rc = - sctp_sendmsg(assoc.sd, buf, n, NULL, 0, htonl(assoc.ppid), 0, stream, 0, 0); + auto n = msg.size(); + auto rc = sctp_sendmsg( + assoc.sd, buf, n, NULL, 0, htonl(assoc.ppid), 0, stream, 0, 0); if (rc < 0) { MLOG_perror("sctp_sendmsg"); @@ -91,8 +84,7 @@ void SctpConnection::Send( } } -void SctpConnection::Listen() -{ +void SctpConnection::Listen() { int server_fd = _sctp_desc.sd(); MLOG(MINFO) << "starting sctp connection listener sd = " << std::to_string(server_fd); @@ -104,7 +96,7 @@ void SctpConnection::Listen() } struct epoll_event event; - event.events = EPOLLIN; + event.events = EPOLLIN; event.data.fd = server_fd; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &event) < 0) { @@ -115,21 +107,19 @@ void SctpConnection::Listen() struct epoll_event events[NUM_EPOLL_EVENTS]; while (!_done) { - int timeout = 100; // milliseconds = .1s + int timeout = 100; // milliseconds = .1s int num_events = epoll_wait(epoll_fd, events, NUM_EPOLL_EVENTS, timeout); switch (num_events) { - case -1: { // errored + case -1: { // errored if (errno == EINTR) continue; MLOG_perror("epoll_wait"); std::terminate(); } - case 0: { // timed out + case 0: { // timed out continue; } - default: { - break; - } + default: { break; } } for (int i = 0; i < num_events; i++) { @@ -143,7 +133,7 @@ void SctpConnection::Listen() } struct epoll_event event; - event.events = EPOLLIN; + event.events = EPOLLIN; event.data.fd = client_sd; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_sd, &event) < 0) { @@ -166,8 +156,7 @@ void SctpConnection::Listen() } } -SctpStatus SctpConnection::HandleClientSock(int sd) -{ +SctpStatus SctpConnection::HandleClientSock(int sd) { assert(sd >= 0); MLOG(MDEBUG) << "HandleClientSock sd = " << std::to_string(sd); @@ -184,7 +173,7 @@ SctpStatus SctpConnection::HandleClientSock(int sd) } if (flags & MSG_NOTIFICATION) { - auto notif = (union sctp_notification *) msg; + auto notif = (union sctp_notification*) msg; switch (notif->sn_header.sn_type) { case SCTP_SHUTDOWN_EVENT: { @@ -197,17 +186,18 @@ SctpStatus SctpConnection::HandleClientSock(int sd) } default: { MLOG(MWARNING) << "Unhandled notification type " - << std::to_string(notif->sn_header.sn_type); + << std::to_string(notif->sn_header.sn_type); return SctpStatus::OK; } } } else { // Data payload received - SctpAssoc &&assoc = SctpAssoc(); + SctpAssoc&& assoc = SctpAssoc(); try { assoc = _sctp_desc.getAssoc(sinfo.sinfo_assoc_id); } catch (std::out_of_range) { - MLOG(MERROR) << "Received sctp msg for untracked assoc: " << std::to_string(sinfo.sinfo_assoc_id); + MLOG(MERROR) << "Received sctp msg for untracked assoc: " + << std::to_string(sinfo.sinfo_assoc_id); // TODO: handle this case return SctpStatus::FAILURE; } @@ -227,16 +217,16 @@ SctpStatus SctpConnection::HandleClientSock(int sd) << std::to_string(sinfo.sinfo_assoc_id) << ":" << std::to_string(sinfo.sinfo_stream); - _handler.HandleRecv(ntohl(sinfo.sinfo_ppid), sinfo.sinfo_assoc_id, sinfo.sinfo_stream, std::string(msg, n)); + _handler.HandleRecv( + ntohl(sinfo.sinfo_ppid), sinfo.sinfo_assoc_id, sinfo.sinfo_stream, + std::string(msg, n)); return SctpStatus::OK; } } SctpStatus SctpConnection::HandleAssocChange( - int sd, - struct sctp_assoc_change *change) -{ + int sd, struct sctp_assoc_change* change) { switch (change->sac_state) { case SCTP_COMM_UP: { return HandleComUp(sd, change); @@ -250,19 +240,20 @@ SctpStatus SctpConnection::HandleAssocChange( return HandleComDown(change->sac_assoc_id); } default: - MLOG(MWARNING) << "Unhandled sctp message " << std::to_string(change->sac_state); + MLOG(MWARNING) << "Unhandled sctp message " + << std::to_string(change->sac_state); return SctpStatus::FAILURE; } } -SctpStatus SctpConnection::HandleComUp(int sd, struct sctp_assoc_change *change) -{ +SctpStatus SctpConnection::HandleComUp( + int sd, struct sctp_assoc_change* change) { SctpAssoc assoc; - assoc.sd = sd; - assoc.ppid = _ppid; - assoc.assoc_id = change->sac_assoc_id; - assoc.instreams = change->sac_inbound_streams; + assoc.sd = sd; + assoc.ppid = _ppid; + assoc.assoc_id = change->sac_assoc_id; + assoc.instreams = change->sac_inbound_streams; assoc.outstreams = change->sac_outbound_streams; _sctp_desc.addAssoc(assoc); @@ -277,9 +268,9 @@ SctpStatus SctpConnection::HandleComUp(int sd, struct sctp_assoc_change *change) return SctpStatus::OK; } -SctpStatus SctpConnection::HandleComDown(uint32_t assoc_id) -{ - MLOG(MDEBUG) << "Sending close connection for assoc_id " << std::to_string(assoc_id); +SctpStatus SctpConnection::HandleComDown(uint32_t assoc_id) { + MLOG(MDEBUG) << "Sending close connection for assoc_id " + << std::to_string(assoc_id); _sctp_desc.delAssoc(assoc_id); @@ -288,8 +279,7 @@ SctpStatus SctpConnection::HandleComDown(uint32_t assoc_id) return SctpStatus::DISCONNECT; } -SctpStatus SctpConnection::HandleReset(uint32_t assoc_id) -{ +SctpStatus SctpConnection::HandleReset(uint32_t assoc_id) { MLOG(MDEBUG) << "Handling sctp reset"; _handler.HandleCloseAssoc(_ppid, assoc_id, true); @@ -297,5 +287,5 @@ SctpStatus SctpConnection::HandleReset(uint32_t assoc_id) return SctpStatus::OK; } -} // namespace sctpd -} // namespace magma +} // namespace sctpd +} // namespace magma diff --git a/lte/gateway/c/sctpd/sctp_connection.h b/lte/gateway/c/sctpd/sctp_connection.h index efb64565fc8d..de2a96913544 100644 --- a/lte/gateway/c/sctpd/sctp_connection.h +++ b/lte/gateway/c/sctpd/sctp_connection.h @@ -29,9 +29,9 @@ namespace sctpd { // Describes status of Sctp event (up or down stream) enum class SctpStatus { - OK, // Sctp event was ok - FAILURE, // General failure - nonfatal - DISCONNECT, // Sctp assoc disconnected + OK, // Sctp event was ok + FAILURE, // General failure - nonfatal + DISCONNECT, // Sctp assoc disconnected }; // Interface for upstream Sctp event handling @@ -39,25 +39,24 @@ class SctpEventHandler { public: // Specification for NewAssoc handler function virtual void HandleNewAssoc( - uint32_t ppid, uint32_t assoc_id, uint32_t instreams, uint32_t outstreams, + uint32_t ppid, uint32_t assoc_id, uint32_t instreams, uint32_t outstreams, std::string& ran_cp_ipaddr) = 0; // Specification for CloseAssoc handler function - virtual void HandleCloseAssoc(uint32_t ppid, uint32_t assoc_id, bool reset) = 0; + virtual void HandleCloseAssoc( + uint32_t ppid, uint32_t assoc_id, bool reset) = 0; // Specification for Recv handler function virtual void HandleRecv( - uint32_t ppid, - uint32_t assoc_id, - uint32_t stream, - const std::string &payload) = 0; + uint32_t ppid, uint32_t assoc_id, uint32_t stream, + const std::string& payload) = 0; }; // Manages Sctp connection including setup/teardown and send/recv class SctpConnection { public: // Construct as per the InitReq and sending upstream events to handler - SctpConnection(const InitReq &req, SctpEventHandler &handler); + SctpConnection(const InitReq& req, SctpEventHandler& handler); // Start SCTP connection and begin listening/relaying events to handler void Start(); @@ -65,7 +64,7 @@ class SctpConnection { void Close(); // Send a message on the Sctp connection to (assoc_id, stream) - void Send(uint32_t assoc_id, uint32_t stream, const std::string &msg); + void Send(uint32_t assoc_id, uint32_t stream, const std::string& msg); private: // Listener loop run in separate thread by Start @@ -73,9 +72,9 @@ class SctpConnection { // Handle an event on a client socket SctpStatus HandleClientSock(int sd); // Handle an association change event for an association sd/change - SctpStatus HandleAssocChange(int sd, struct sctp_assoc_change *change); + SctpStatus HandleAssocChange(int sd, struct sctp_assoc_change* change); // Handle a comup event on an association sd/change - SctpStatus HandleComUp(int sd, struct sctp_assoc_change *change); + SctpStatus HandleComUp(int sd, struct sctp_assoc_change* change); // Handle a comdown event on an association keyed by assoc_id SctpStatus HandleComDown(uint32_t assoc_id); // Handle a reset event on an association keyed by assoc_id @@ -84,7 +83,7 @@ class SctpConnection { // Flag is set to true when the connection is closing std::atomic _done; // Concrete handler instance to handle upstream events - SctpEventHandler &_handler; + SctpEventHandler& _handler; // PPID to use with Sctp connections int _ppid; // Keeps track of sctp and assocation info @@ -93,5 +92,5 @@ class SctpConnection { std::unique_ptr _thread; }; -} // namespace sctpd -}; // namespace magma +} // namespace sctpd +}; // namespace magma diff --git a/lte/gateway/c/sctpd/sctp_desc.cpp b/lte/gateway/c/sctpd/sctp_desc.cpp index dbd84653d0b8..efa331fd68f0 100644 --- a/lte/gateway/c/sctpd/sctp_desc.cpp +++ b/lte/gateway/c/sctpd/sctp_desc.cpp @@ -18,49 +18,41 @@ namespace magma { namespace sctpd { -SctpDesc::SctpDesc(int sd): _sd(sd) -{ +SctpDesc::SctpDesc(int sd) : _sd(sd) { assert(sd >= 0); } -void SctpDesc::addAssoc(const SctpAssoc &assoc) -{ +void SctpDesc::addAssoc(const SctpAssoc& assoc) { _assocs[assoc.assoc_id] = assoc; } -SctpAssoc &SctpDesc::getAssoc(uint32_t assoc_id) -{ - return _assocs.at(assoc_id); // throws std::out_of_range +SctpAssoc& SctpDesc::getAssoc(uint32_t assoc_id) { + return _assocs.at(assoc_id); // throws std::out_of_range } -int SctpDesc::delAssoc(uint32_t assoc_id) -{ +int SctpDesc::delAssoc(uint32_t assoc_id) { auto num_removed = _assocs.erase(assoc_id); return num_removed == 1 ? 0 : -1; } -AssocMap::const_iterator SctpDesc::begin() const -{ +AssocMap::const_iterator SctpDesc::begin() const { return _assocs.cbegin(); } -AssocMap::const_iterator SctpDesc::end() const -{ +AssocMap::const_iterator SctpDesc::end() const { return _assocs.cend(); } -int SctpDesc::sd() const -{ +int SctpDesc::sd() const { return _sd; } -void SctpDesc::dump() const -{ - for (auto const &kv : _assocs) { +void SctpDesc::dump() const { + for (auto const& kv : _assocs) { auto assoc = kv.second; assoc.dump(); } } -} // namespace sctpd -} // namespace magma +} // namespace sctpd +} // namespace magma diff --git a/lte/gateway/c/sctpd/sctp_desc.h b/lte/gateway/c/sctpd/sctp_desc.h index e9f8d303038b..fa2d663763be 100644 --- a/lte/gateway/c/sctpd/sctp_desc.h +++ b/lte/gateway/c/sctpd/sctp_desc.h @@ -31,9 +31,9 @@ class SctpDesc { SctpDesc(int sd); // Add assocation, assoc, to the list of assocations - keyed by assoc_id - void addAssoc(const SctpAssoc &assoc); + void addAssoc(const SctpAssoc& assoc); // Get association keyed by assoc_id, throw std::out_of_range otherwise - SctpAssoc &getAssoc(uint32_t assoc_id); + SctpAssoc& getAssoc(uint32_t assoc_id); // Remove assoc keyed by assoc_id from assoc list, returns 0/-1 on ok/fail int delAssoc(uint32_t assoc_id); @@ -55,5 +55,5 @@ class SctpDesc { int _sd; }; -} // namespace sctpd -} // namespace magma +} // namespace sctpd +} // namespace magma diff --git a/lte/gateway/c/sctpd/sctpd.cpp b/lte/gateway/c/sctpd/sctpd.cpp index ea29f894b017..98574174a3e7 100644 --- a/lte/gateway/c/sctpd/sctpd.cpp +++ b/lte/gateway/c/sctpd/sctpd.cpp @@ -28,9 +28,7 @@ using magma::sctpd::SctpdDownlinkImpl; using magma::sctpd::SctpdEventHandler; using magma::sctpd::SctpdUplinkClient; - -int signalMask(void) -{ +int signalMask(void) { sigset_t set; sigemptyset(&set); sigaddset(&set, SIGSEGV); @@ -44,10 +42,7 @@ int signalMask(void) } int signalHandler( - int *end, - std::unique_ptr &server, - SctpdDownlinkImpl &downLink) -{ + int* end, std::unique_ptr& server, SctpdDownlinkImpl& downLink) { int ret; siginfo_t info; sigset_t set; @@ -79,15 +74,14 @@ int signalHandler( return 0; } -int main() -{ +int main() { signalMask(); magma::init_logging("sctpd"); magma::set_verbosity(MDEBUG); auto channel = - grpc::CreateChannel(UPSTREAM_SOCK, grpc::InsecureChannelCredentials()); + grpc::CreateChannel(UPSTREAM_SOCK, grpc::InsecureChannelCredentials()); SctpdUplinkClient client(channel); SctpdEventHandler handler(client); diff --git a/lte/gateway/c/sctpd/sctpd_downlink_impl.cpp b/lte/gateway/c/sctpd/sctpd_downlink_impl.cpp index 07a11cc3c843..3d25e92868bd 100644 --- a/lte/gateway/c/sctpd/sctpd_downlink_impl.cpp +++ b/lte/gateway/c/sctpd/sctpd_downlink_impl.cpp @@ -23,73 +23,63 @@ namespace magma { namespace sctpd { -SctpdDownlinkImpl::SctpdDownlinkImpl(SctpEventHandler &uplink_handler): - _uplink_handler(uplink_handler), - _sctp_4G_connection(nullptr), - _sctp_5G_connection(nullptr) -{ -} +SctpdDownlinkImpl::SctpdDownlinkImpl(SctpEventHandler& uplink_handler) + : _uplink_handler(uplink_handler), + _sctp_4G_connection(nullptr), + _sctp_5G_connection(nullptr) {} Status SctpdDownlinkImpl::create_sctp_connection( - std::unique_ptr& sctp_connection, - const InitReq *req, -InitRes *res) -{ + std::unique_ptr& sctp_connection, const InitReq* req, + InitRes* res) { if (sctp_connection != nullptr && !req->force_restart()) { - MLOG(MERROR) << "SctpdDownlinkImpl::Init reusing existing connection"; - res->set_result(InitRes::INIT_OK); - return Status::OK; + MLOG(MERROR) << "SctpdDownlinkImpl::Init reusing existing connection"; + res->set_result(InitRes::INIT_OK); + return Status::OK; } if (sctp_connection != nullptr) { - MLOG(MINFO)<< "SctpdDownlinkImpl::Init cleaning up sctp_desc and listener"; - auto conn = std::move(sctp_connection); - conn->Close(); + MLOG(MINFO) << "SctpdDownlinkImpl::Init cleaning up sctp_desc and listener"; + auto conn = std::move(sctp_connection); + conn->Close(); } MLOG(MINFO) << "SctpdDownlinkImpl::Init creating new socket and listener"; try { - sctp_connection = std::make_unique(*req, _uplink_handler); + sctp_connection = std::make_unique(*req, _uplink_handler); } catch (...) { - res->set_result(InitRes::INIT_FAIL); - return Status::OK; + res->set_result(InitRes::INIT_FAIL); + return Status::OK; } sctp_connection->Start(); return Status::OK; } Status SctpdDownlinkImpl::Init( - ServerContext *context, - const InitReq *req, - InitRes *res) -{ - MLOG(MINFO) << "SctpdDownlinkImpl::req->ppid()=" << std::to_string(req->ppid()); - MLOG(MINFO) << "SctpdDownlinkImpl::req->port()=" << std::to_string(req->port()); + ServerContext* context, const InitReq* req, InitRes* res) { + MLOG(MINFO) << "SctpdDownlinkImpl::req->ppid()=" + << std::to_string(req->ppid()); + MLOG(MINFO) << "SctpdDownlinkImpl::req->port()=" + << std::to_string(req->port()); - Status rc; + Status rc; if (req->ppid() == S1AP) { - rc = create_sctp_connection(_sctp_4G_connection, req, res); - -} - else if (req->ppid() == NGAP) { - rc = create_sctp_connection(_sctp_5G_connection, req, res); + rc = create_sctp_connection(_sctp_4G_connection, req, res); -} - res->set_result(InitRes::INIT_OK); - return Status::OK; + } else if (req->ppid() == NGAP) { + rc = create_sctp_connection(_sctp_5G_connection, req, res); + } + res->set_result(InitRes::INIT_OK); + return Status::OK; } Status SctpdDownlinkImpl::SendDl( - ServerContext *context, - const SendDlReq *req, - SendDlRes *res) -{ + ServerContext* context, const SendDlReq* req, SendDlRes* res) { MLOG(MDEBUG) << "SctpdDownlinkImpl::SendDl starting"; try { - if (req->ppid() == S1AP ) - _sctp_4G_connection->Send(req->assoc_id(), req->stream(), req->payload()); - else - _sctp_5G_connection->Send(req->assoc_id(), req->stream(), req->payload()); + if (req->ppid() == S1AP) + _sctp_4G_connection->Send(req->assoc_id(), req->stream(), req->payload()); + else + _sctp_5G_connection->Send(req->assoc_id(), req->stream(), req->payload()); } catch (...) { res->set_result(SendDlRes::SEND_DL_FAIL); @@ -100,15 +90,14 @@ Status SctpdDownlinkImpl::SendDl( return Status::OK; } -void SctpdDownlinkImpl::stop() -{ - if (_sctp_4G_connection != nullptr) { - _sctp_4G_connection->Close(); - } - if (_sctp_5G_connection != nullptr) { - _sctp_5G_connection->Close(); - } +void SctpdDownlinkImpl::stop() { + if (_sctp_4G_connection != nullptr) { + _sctp_4G_connection->Close(); + } + if (_sctp_5G_connection != nullptr) { + _sctp_5G_connection->Close(); + } } -} // namespace sctpd -} // namespace magma +} // namespace sctpd +} // namespace magma diff --git a/lte/gateway/c/sctpd/sctpd_downlink_impl.h b/lte/gateway/c/sctpd/sctpd_downlink_impl.h index de4c0bccd4dc..5366abe54146 100644 --- a/lte/gateway/c/sctpd/sctpd_downlink_impl.h +++ b/lte/gateway/c/sctpd/sctpd_downlink_impl.h @@ -36,29 +36,32 @@ using grpc::Status; class SctpdDownlinkImpl final : public SctpdDownlink::Service { public: // Construct a new SctpdDownlinkImpl service - SctpdDownlinkImpl(SctpEventHandler &uplink_handler); + SctpdDownlinkImpl(SctpEventHandler& uplink_handler); // Implementation of SctpdDownlink.Init method (see sctpd.proto for more info) - Status Init(ServerContext *context, const InitReq *request, InitRes *response) - override; + Status Init(ServerContext* context, const InitReq* request, InitRes* response) + override; - // Implementation of SctpdDownlink.SendDl method (see sctpd.proto for more info) - Status SendDl( ServerContext *context, const SendDlReq *request, SendDlRes *response) - override; + // Implementation of SctpdDownlink.SendDl method (see sctpd.proto for more + // info) + Status SendDl( + ServerContext* context, const SendDlReq* request, + SendDlRes* response) override; // Implementation of SctpdDownlink.create_sctp_connection method //(creates 4G/5G sctp connection) - Status create_sctp_connection(std::unique_ptr& sctp_connection, - const InitReq *request, InitRes *response); + Status create_sctp_connection( + std::unique_ptr& sctp_connection, const InitReq* request, + InitRes* response); // Close SCTP connection for this SctpdDownlink. void stop(); private: - SctpEventHandler &_uplink_handler; + SctpEventHandler& _uplink_handler; std::unique_ptr _sctp_4G_connection; std::unique_ptr _sctp_5G_connection; }; -} // namespace sctpd -} // namespace magma +} // namespace sctpd +} // namespace magma diff --git a/lte/gateway/c/sctpd/sctpd_event_handler.cpp b/lte/gateway/c/sctpd/sctpd_event_handler.cpp index 6f6c27f09d1a..6ed58709ee68 100644 --- a/lte/gateway/c/sctpd/sctpd_event_handler.cpp +++ b/lte/gateway/c/sctpd/sctpd_event_handler.cpp @@ -18,9 +18,8 @@ namespace magma { namespace sctpd { -SctpdEventHandler::SctpdEventHandler(SctpdUplinkClient &client): _client(client) -{ -} +SctpdEventHandler::SctpdEventHandler(SctpdUplinkClient& client) + : _client(client) {} void SctpdEventHandler::HandleNewAssoc( uint32_t ppid, uint32_t assoc_id, uint32_t instreams, uint32_t outstreams, @@ -37,8 +36,8 @@ void SctpdEventHandler::HandleNewAssoc( _client.newAssoc(req, &res); } -void SctpdEventHandler::HandleCloseAssoc(uint32_t ppid, uint32_t assoc_id, bool reset) -{ +void SctpdEventHandler::HandleCloseAssoc( + uint32_t ppid, uint32_t assoc_id, bool reset) { CloseAssocReq req; CloseAssocRes res; @@ -50,11 +49,8 @@ void SctpdEventHandler::HandleCloseAssoc(uint32_t ppid, uint32_t assoc_id, bool } void SctpdEventHandler::HandleRecv( - uint32_t ppid, - uint32_t assoc_id, - uint32_t stream, - const std::string &payload) -{ + uint32_t ppid, uint32_t assoc_id, uint32_t stream, + const std::string& payload) { SendUlReq req; SendUlRes res; @@ -66,5 +62,5 @@ void SctpdEventHandler::HandleRecv( _client.sendUl(req, &res); } -} // namespace sctpd -} // namespace magma +} // namespace sctpd +} // namespace magma diff --git a/lte/gateway/c/sctpd/sctpd_event_handler.h b/lte/gateway/c/sctpd/sctpd_event_handler.h index b45a3589f524..2e7587c06823 100644 --- a/lte/gateway/c/sctpd/sctpd_event_handler.h +++ b/lte/gateway/c/sctpd/sctpd_event_handler.h @@ -28,7 +28,7 @@ class SctpdEventHandler : public SctpEventHandler { // Relay new assocation to MME/AMF over GRPC void HandleNewAssoc( - uint32_t ppid, uint32_t assoc_id, uint32_t instreams, uint32_t outstreams, + uint32_t ppid, uint32_t assoc_id, uint32_t instreams, uint32_t outstreams, std::string& ran_cp_ipaddr) override; // Relay close assocation to MME/AMF over GRPC @@ -36,7 +36,9 @@ class SctpdEventHandler : public SctpEventHandler { // Relay new message to MME over GRPC void HandleRecv( - uint32_t ppid, uint32_t assoc_id, uint32_t stream, const std::string& payload) override; + uint32_t ppid, uint32_t assoc_id, uint32_t stream, + const std::string& payload) override; + private: SctpdUplinkClient& _client; }; diff --git a/lte/gateway/c/sctpd/sctpd_uplink_client.cpp b/lte/gateway/c/sctpd/sctpd_uplink_client.cpp index 9a61b8e85d05..2419ba69fb96 100644 --- a/lte/gateway/c/sctpd/sctpd_uplink_client.cpp +++ b/lte/gateway/c/sctpd/sctpd_uplink_client.cpp @@ -20,13 +20,11 @@ namespace sctpd { using grpc::ClientContext; -SctpdUplinkClient::SctpdUplinkClient(std::shared_ptr channel) -{ +SctpdUplinkClient::SctpdUplinkClient(std::shared_ptr channel) { _stub = SctpdUplink::NewStub(channel); } -int SctpdUplinkClient::sendUl(const SendUlReq &req, SendUlRes *res) -{ +int SctpdUplinkClient::sendUl(const SendUlReq& req, SendUlRes* res) { assert(res != nullptr); ClientContext context; @@ -41,8 +39,7 @@ int SctpdUplinkClient::sendUl(const SendUlReq &req, SendUlRes *res) return status.ok() ? 0 : -1; } -int SctpdUplinkClient::newAssoc(const NewAssocReq &req, NewAssocRes *res) -{ +int SctpdUplinkClient::newAssoc(const NewAssocReq& req, NewAssocRes* res) { assert(res != nullptr); ClientContext context; @@ -57,8 +54,8 @@ int SctpdUplinkClient::newAssoc(const NewAssocReq &req, NewAssocRes *res) return status.ok() ? 0 : -1; } -int SctpdUplinkClient::closeAssoc(const CloseAssocReq &req, CloseAssocRes *res) -{ +int SctpdUplinkClient::closeAssoc( + const CloseAssocReq& req, CloseAssocRes* res) { assert(res != nullptr); ClientContext context; @@ -73,5 +70,5 @@ int SctpdUplinkClient::closeAssoc(const CloseAssocReq &req, CloseAssocRes *res) return status.ok() ? 0 : -1; } -} // namespace sctpd -} // namespace magma +} // namespace sctpd +} // namespace magma diff --git a/lte/gateway/c/sctpd/sctpd_uplink_client.h b/lte/gateway/c/sctpd/sctpd_uplink_client.h index 947c97bf5516..c324c4486384 100644 --- a/lte/gateway/c/sctpd/sctpd_uplink_client.h +++ b/lte/gateway/c/sctpd/sctpd_uplink_client.h @@ -31,16 +31,16 @@ class SctpdUplinkClient { explicit SctpdUplinkClient(std::shared_ptr channel); // Send an uplink packet to MME (see sctpd.proto for more info) - virtual int sendUl(const SendUlReq &req, SendUlRes *res); + virtual int sendUl(const SendUlReq& req, SendUlRes* res); // Notify MME of new association (see sctpd.proto for more info) - virtual int newAssoc(const NewAssocReq &req, NewAssocRes *res); + virtual int newAssoc(const NewAssocReq& req, NewAssocRes* res); // Notify MME of closing/reseting association (see sctpd.proto for more info) - virtual int closeAssoc(const CloseAssocReq &req, CloseAssocRes *res); + virtual int closeAssoc(const CloseAssocReq& req, CloseAssocRes* res); private: // Stub used for client to communicate with server std::unique_ptr _stub; }; -} // namespace sctpd -} // namespace magma +} // namespace sctpd +} // namespace magma diff --git a/lte/gateway/c/sctpd/test/test_event_handler.cpp b/lte/gateway/c/sctpd/test/test_event_handler.cpp index b3aa13fc4739..526113585954 100644 --- a/lte/gateway/c/sctpd/test/test_event_handler.cpp +++ b/lte/gateway/c/sctpd/test/test_event_handler.cpp @@ -36,23 +36,21 @@ namespace sctpd { class MockSctpdUplinkClient final : public SctpdUplinkClient { public: - MockSctpdUplinkClient(std::shared_ptr channel): - SctpdUplinkClient(channel) - { + MockSctpdUplinkClient(std::shared_ptr channel) + : SctpdUplinkClient(channel) { ON_CALL(*this, sendUl(_, _)).WillByDefault(Return(0)); ON_CALL(*this, newAssoc(_, _)).WillByDefault(Return(0)); ON_CALL(*this, closeAssoc(_, _)).WillByDefault(Return(0)); } - MOCK_METHOD2(sendUl, int(const SendUlReq &, SendUlRes *)); - MOCK_METHOD2(newAssoc, int(const NewAssocReq &, NewAssocRes *)); - MOCK_METHOD2(closeAssoc, int(const CloseAssocReq &, CloseAssocRes *)); + MOCK_METHOD2(sendUl, int(const SendUlReq&, SendUlRes*)); + MOCK_METHOD2(newAssoc, int(const NewAssocReq&, NewAssocRes*)); + MOCK_METHOD2(closeAssoc, int(const CloseAssocReq&, CloseAssocRes*)); }; class EventHandlerTest : public ::testing::Test { protected: - virtual void SetUp() - { + virtual void SetUp() { send_ul_req.set_assoc_id(123); send_ul_req.set_stream(321); send_ul_req.set_payload("testtest"); @@ -67,7 +65,7 @@ class EventHandlerTest : public ::testing::Test { auto channel = grpc::CreateChannel("", grpc::InsecureChannelCredentials()); _uplink_client = std::make_unique(channel); - _handler = std::make_unique(*_uplink_client); + _handler = std::make_unique(*_uplink_client); } SendUlReq send_ul_req; @@ -78,64 +76,59 @@ class EventHandlerTest : public ::testing::Test { std::unique_ptr _handler; }; -TEST_F(EventHandlerTest, test_event_handler_new_assoc) -{ +TEST_F(EventHandlerTest, test_event_handler_new_assoc) { auto correct_assoc_id = - Property(&NewAssocReq::assoc_id, Eq(new_assoc_req.assoc_id())); + Property(&NewAssocReq::assoc_id, Eq(new_assoc_req.assoc_id())); auto correct_instreams = - Property(&NewAssocReq::instreams, Eq(new_assoc_req.instreams())); + Property(&NewAssocReq::instreams, Eq(new_assoc_req.instreams())); auto correct_outstreams = - Property(&NewAssocReq::outstreams, Eq(new_assoc_req.outstreams())); + Property(&NewAssocReq::outstreams, Eq(new_assoc_req.outstreams())); auto correct_new_assoc_req = - AllOf(correct_assoc_id, correct_instreams, correct_outstreams); + AllOf(correct_assoc_id, correct_instreams, correct_outstreams); EXPECT_CALL(*_uplink_client, newAssoc(correct_new_assoc_req, NotNull())) - .Times(1); + .Times(1); _handler->HandleNewAssoc( - new_assoc_req.assoc_id(), - new_assoc_req.instreams(), - new_assoc_req.outstreams()); + new_assoc_req.assoc_id(), new_assoc_req.instreams(), + new_assoc_req.outstreams()); } -TEST_F(EventHandlerTest, test_event_handler_close_assoc) -{ +TEST_F(EventHandlerTest, test_event_handler_close_assoc) { auto correct_assoc_id = - Property(&CloseAssocReq::assoc_id, Eq(close_assoc_req.assoc_id())); + Property(&CloseAssocReq::assoc_id, Eq(close_assoc_req.assoc_id())); auto correct_reset = - Property(&CloseAssocReq::is_reset, Eq(close_assoc_req.is_reset())); + Property(&CloseAssocReq::is_reset, Eq(close_assoc_req.is_reset())); auto correct_close_assoc_req = AllOf(correct_assoc_id, correct_reset); EXPECT_CALL(*_uplink_client, closeAssoc(correct_close_assoc_req, NotNull())) - .Times(1); + .Times(1); _handler->HandleCloseAssoc( - close_assoc_req.assoc_id(), close_assoc_req.is_reset()); + close_assoc_req.assoc_id(), close_assoc_req.is_reset()); } -TEST_F(EventHandlerTest, test_event_handler_send_ul) -{ +TEST_F(EventHandlerTest, test_event_handler_send_ul) { auto correct_assoc_id = - Property(&SendUlReq::assoc_id, Eq(send_ul_req.assoc_id())); + Property(&SendUlReq::assoc_id, Eq(send_ul_req.assoc_id())); auto correct_stream = Property(&SendUlReq::stream, Eq(send_ul_req.stream())); auto correct_payload = - Property(&SendUlReq::payload, Eq(send_ul_req.payload())); + Property(&SendUlReq::payload, Eq(send_ul_req.payload())); auto correct_send_ul_req = - AllOf(correct_assoc_id, correct_stream, correct_payload); + AllOf(correct_assoc_id, correct_stream, correct_payload); EXPECT_CALL(*_uplink_client, sendUl(correct_send_ul_req, NotNull())).Times(1); _handler->HandleRecv( - send_ul_req.assoc_id(), send_ul_req.stream(), send_ul_req.payload()); + send_ul_req.assoc_id(), send_ul_req.stream(), send_ul_req.payload()); } -} // namespace sctpd -} // namespace magma +} // namespace sctpd +} // namespace magma -int main(int argc, char **argv) -{ +int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); FLAGS_logtostderr = 1; - FLAGS_v = 10; + FLAGS_v = 10; return RUN_ALL_TESTS(); } diff --git a/lte/gateway/c/sctpd/test/test_sctp_desc.cpp b/lte/gateway/c/sctpd/test/test_sctp_desc.cpp index 495eb3becfdf..f2270cdacf3a 100644 --- a/lte/gateway/c/sctpd/test/test_sctp_desc.cpp +++ b/lte/gateway/c/sctpd/test/test_sctp_desc.cpp @@ -25,22 +25,20 @@ namespace sctpd { const int DESC_SD = 3; const int ASSOC_1_ASSOC_ID = 1; -const int ASSOC_1_SD = 4; +const int ASSOC_1_SD = 4; const int ASSOC_2_ASSOC_ID = 2; -const int ASSOC_2_SD = 5; +const int ASSOC_2_SD = 5; class SctpdDescTest : public ::testing::Test { protected: - virtual void SetUp() - { + virtual void SetUp() { assoc_1.assoc_id = ASSOC_1_ASSOC_ID; - assoc_1.sd = ASSOC_1_SD; + assoc_1.sd = ASSOC_1_SD; assoc_2.assoc_id = ASSOC_2_ASSOC_ID; - assoc_2.sd = ASSOC_2_SD; + assoc_2.sd = ASSOC_2_SD; } - void check_assoc(int assoc_id, int sd, const SctpAssoc &assoc) - { + void check_assoc(int assoc_id, int sd, const SctpAssoc& assoc) { EXPECT_EQ(assoc_id, assoc.assoc_id); EXPECT_EQ(sd, assoc.sd); } @@ -49,8 +47,7 @@ class SctpdDescTest : public ::testing::Test { SctpAssoc assoc_2; }; -TEST_F(SctpdDescTest, test_sctpd_desc) -{ +TEST_F(SctpdDescTest, test_sctpd_desc) { SctpDesc desc(DESC_SD); EXPECT_EQ(DESC_SD, desc.sd()); @@ -74,7 +71,7 @@ TEST_F(SctpdDescTest, test_sctpd_desc) bool found_2 = false; for (auto kv : desc) { auto assoc_id = kv.first; - auto assoc = kv.second; + auto assoc = kv.second; EXPECT_EQ(assoc_id, assoc.assoc_id); if (assoc_id == ASSOC_1_ASSOC_ID) { @@ -102,13 +99,12 @@ TEST_F(SctpdDescTest, test_sctpd_desc) EXPECT_THROW(desc.getAssoc(ASSOC_2_ASSOC_ID), std::out_of_range); } -} // namespace sctpd -} // namespace magma +} // namespace sctpd +} // namespace magma -int main(int argc, char **argv) -{ +int main(int argc, char** argv) { ::testing::InitGoogleTest(&argc, argv); FLAGS_logtostderr = 1; - FLAGS_v = 10; + FLAGS_v = 10; return RUN_ALL_TESTS(); } diff --git a/lte/gateway/c/sctpd/util.cpp b/lte/gateway/c/sctpd/util.cpp index 512e91740881..92a51a53815b 100644 --- a/lte/gateway/c/sctpd/util.cpp +++ b/lte/gateway/c/sctpd/util.cpp @@ -23,19 +23,15 @@ namespace sctpd { // Set up basic sctp options of socket "sd" int set_sctp_opts( - const int sd, - const uint16_t instreams, - const uint16_t outstreams, - const uint16_t max_attempts, - const uint16_t init_timeout); + const int sd, const uint16_t instreams, const uint16_t outstreams, + const uint16_t max_attempts, const uint16_t init_timeout); // Convert address specified in InitReq into struct sockaddr for sctp setup -int convert_addrs(const InitReq *req, struct sockaddr **addrs, int *num_addrs); +int convert_addrs(const InitReq* req, struct sockaddr** addrs, int* num_addrs); -int create_sctp_sock(const InitReq &req) -{ +int create_sctp_sock(const InitReq& req) { int num_addrs; - struct sockaddr *addrs; + struct sockaddr* addrs; int sd; if (!req.use_ipv4() && !req.use_ipv6()) return -1; @@ -78,16 +74,12 @@ int create_sctp_sock(const InitReq &req) } int set_sctp_opts( - const int sd, - const uint16_t instreams, - const uint16_t outstreams, - const uint16_t max_attempts, - const uint16_t init_timeout) -{ + const int sd, const uint16_t instreams, const uint16_t outstreams, + const uint16_t max_attempts, const uint16_t init_timeout) { struct sctp_initmsg init; - init.sinit_num_ostreams = outstreams; - init.sinit_max_instreams = instreams; - init.sinit_max_attempts = max_attempts; + init.sinit_num_ostreams = outstreams; + init.sinit_max_instreams = instreams; + init.sinit_max_attempts = max_attempts; init.sinit_max_init_timeo = init_timeout; if (setsockopt(sd, IPPROTO_SCTP, SCTP_INITMSG, &init, sizeof(init)) < 0) { @@ -98,19 +90,18 @@ int set_sctp_opts( int on = 1; struct linger sctp_linger; - sctp_linger.l_onoff = on; + sctp_linger.l_onoff = on; sctp_linger.l_linger = 0; // send an ABORT - if ( - setsockopt(sd, SOL_SOCKET, SO_LINGER, &sctp_linger, sizeof(sctp_linger)) < 0 - ) { + if (setsockopt(sd, SOL_SOCKET, SO_LINGER, &sctp_linger, sizeof(sctp_linger)) < + 0) { MLOG_perror("setsockopt linger"); return -1; } struct sctp_event_subscribe event; event.sctp_association_event = on; - event.sctp_shutdown_event = on; - event.sctp_data_io_event = on; + event.sctp_shutdown_event = on; + event.sctp_data_io_event = on; if (setsockopt(sd, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(event)) < 0) { MLOG_perror("setsockopt"); @@ -120,37 +111,35 @@ int set_sctp_opts( return 0; } -int convert_addrs(const InitReq *req, struct sockaddr **addrs, int *num_addrs) -{ +int convert_addrs(const InitReq* req, struct sockaddr** addrs, int* num_addrs) { int i; - struct sockaddr_in *ipv4_addr; - struct sockaddr_in6 *ipv6_addr; + struct sockaddr_in* ipv4_addr; + struct sockaddr_in6* ipv6_addr; auto num_ipv4_addrs = req->ipv4_addrs_size(); auto num_ipv6_addrs = req->ipv6_addrs_size(); - *num_addrs = num_ipv4_addrs + num_ipv6_addrs; + *num_addrs = num_ipv4_addrs + num_ipv6_addrs; - *addrs = (struct sockaddr *) calloc(*num_addrs, sizeof(struct sockaddr *)); + *addrs = (struct sockaddr*) calloc(*num_addrs, sizeof(struct sockaddr*)); if (*addrs == NULL) return -1; for (i = 0; i < num_ipv4_addrs; i++) { - ipv4_addr = (struct sockaddr_in *) &(*addrs)[i]; + ipv4_addr = (struct sockaddr_in*) &(*addrs)[i]; ipv4_addr->sin_family = AF_INET; - ipv4_addr->sin_port = htons(req->port()); + ipv4_addr->sin_port = htons(req->port()); if (inet_aton(req->ipv4_addrs(i).c_str(), &ipv4_addr->sin_addr) < 0) { return -1; } } for (i = 0; i < num_ipv6_addrs; i++) { - ipv6_addr = (struct sockaddr_in6 *) &(*addrs)[i + num_ipv4_addrs]; + ipv6_addr = (struct sockaddr_in6*) &(*addrs)[i + num_ipv4_addrs]; ipv6_addr->sin6_family = AF_INET6; - ipv6_addr->sin6_port = htons(req->port()); - if ( - inet_pton(AF_INET6, req->ipv6_addrs(i).c_str(), &ipv6_addr->sin6_addr) < - 0) { + ipv6_addr->sin6_port = htons(req->port()); + if (inet_pton(AF_INET6, req->ipv6_addrs(i).c_str(), &ipv6_addr->sin6_addr) < + 0) { return -1; } } @@ -158,15 +147,16 @@ int convert_addrs(const InitReq *req, struct sockaddr **addrs, int *num_addrs) return 0; } -int pull_peer_ipaddr(const int sd, const uint32_t assoc_id, std::string& ran_cp_ipaddr) { +int pull_peer_ipaddr( + const int sd, const uint32_t assoc_id, std::string& ran_cp_ipaddr) { int n_remote_addr = -1; struct sockaddr* remote_addrs = NULL; - n_remote_addr = sctp_getpaddrs(sd, assoc_id, &remote_addrs); + n_remote_addr = sctp_getpaddrs(sd, assoc_id, &remote_addrs); // Since socket is opened as AF_INET6, remote address comes as IPv6 formatted // for both IPv4 and IPv6 end points - const uint8_t *remote_addr_ipv6_bytes = - ((const struct sockaddr_in6*) &remote_addrs[0])->sin6_addr.s6_addr; + const uint8_t* remote_addr_ipv6_bytes = + ((const struct sockaddr_in6*) &remote_addrs[0])->sin6_addr.s6_addr; const char* fromaddr = NULL; if (n_remote_addr >= 1) { // Picking the first address only. @@ -174,18 +164,17 @@ int pull_peer_ipaddr(const int sd, const uint32_t assoc_id, std::string& ran_cp_ if (IN6_IS_ADDR_V4MAPPED( &((struct sockaddr_in6*) &remote_addrs[0])->sin6_addr)) { // First 12 bytes are ::FFFF for IPv4-mapped-IPv6 - fromaddr = (const char *) remote_addr_ipv6_bytes + 12; + fromaddr = (const char*) remote_addr_ipv6_bytes + 12; ran_cp_ipaddr = std::string(fromaddr, 4); } else { - fromaddr = (const char *) remote_addr_ipv6_bytes; + fromaddr = (const char*) remote_addr_ipv6_bytes; ran_cp_ipaddr = std::string(fromaddr, 16); } } - sctp_freepaddrs(remote_addrs); return 0; } -} // namespace sctpd -} // namespace magma +} // namespace sctpd +} // namespace magma From a94f0f65451033526adb33914a4b2673d941dea3 Mon Sep 17 00:00:00 2001 From: rsarwad <30685618+rsarwad@users.noreply.github.com> Date: Tue, 2 Mar 2021 22:38:45 +0530 Subject: [PATCH 4/8] Fixed the compilation issue occurring in OAI build (#5251) Signed-off-by: rashmi --- lte/gateway/c/oai/oai_mme/oai_mme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lte/gateway/c/oai/oai_mme/oai_mme.c b/lte/gateway/c/oai/oai_mme/oai_mme.c index 90aef56c0894..13cea753941b 100644 --- a/lte/gateway/c/oai/oai_mme/oai_mme.c +++ b/lte/gateway/c/oai/oai_mme/oai_mme.c @@ -43,7 +43,6 @@ #include "sgs_defs.h" #include "sms_orc8r_defs.h" #include "ha_defs.h" -#include "sgw_s8_defs.h" #include "oai_mme.h" #include "pid_file.h" #include "service303_message_utils.h" @@ -54,6 +53,7 @@ #include "mme_app_embedded_spgw.h" #include "spgw_config.h" #include "sgw_defs.h" +#include "sgw_s8_defs.h" #endif #include "udp_primitives_server.h" #include "s11_mme.h" From b39f568136179bdc2279fa9fab072eb75d412f42 Mon Sep 17 00:00:00 2001 From: prabinakpattnaik <69528542+prabinakpattnaik@users.noreply.github.com> Date: Wed, 3 Mar 2021 01:00:46 +0530 Subject: [PATCH 5/8] pipelined: classifier test failure #5239 (#5255) Signed-off-by: prabina pattnaik --- lte/gateway/python/magma/pipelined/app/classifier.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lte/gateway/python/magma/pipelined/app/classifier.py b/lte/gateway/python/magma/pipelined/app/classifier.py index 72aed50d7f05..b277cae9da0f 100644 --- a/lte/gateway/python/magma/pipelined/app/classifier.py +++ b/lte/gateway/python/magma/pipelined/app/classifier.py @@ -12,6 +12,7 @@ """ import subprocess import ipaddress +import socket from collections import namedtuple from ryu.ofproto.ofproto_v1_4 import OFPP_LOCAL @@ -87,7 +88,7 @@ def _ovs_multi_tunnel_init(self): self.ovs_gtp_type = "gtp" def _ip_addr_to_gtp_port_name(self, enodeb_ip_addr:str): - ip_no = hex(int(ipaddress.ip_address(enodeb_ip_addr))) + ip_no = hex(socket.htonl(int(ipaddress.ip_address(enodeb_ip_addr)))) buf = "g_{}".format(ip_no[2:]) return buf @@ -97,7 +98,7 @@ def _get_ofport(self, port_name): return None try: - return ovs.get_ofport(port_name) + port_no = ovs.get_ofport(port_name) except AssertionError as error: self.logger.debug('Cannot get port number for %s: %s', @@ -109,6 +110,8 @@ def _get_ofport(self, port_name): port_name, e) return None + return port_no + def _add_gtp_port(self, gnb_ip): if not self.config.multi_tunnel_flag: return self.config.gtp_port From 10202bf0b9b9ce3d95d89d61ba340ea70b03b3e8 Mon Sep 17 00:00:00 2001 From: Alex Rodriguez Date: Tue, 2 Mar 2021 15:22:45 -0800 Subject: [PATCH 6/8] Adding @ardzoht to `lte/gateway/c/oai` folder (#5265) Signed-off-by: Alex Rodriguez --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index 82ce3b488351..d8ffac7a78b0 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -20,7 +20,7 @@ openwrt/ @emakeev @uri200 # More specific mappings for lte/gateway will override this top-level one lte/gateway @ardzoht @pshelar lte/gateway/c/session_manager @themarwhal @uri200 -lte/gateway/c/oai @ssanadhya @ulaskozat @lionelgo +lte/gateway/c/oai @ssanadhya @ulaskozat @lionelgo @ardzoht lte/gateway/c/sctpd @ssanadhya @ulaskozat lte/gateway/c/connection_tracker @koolzz lte/gateway/docker @rdefosse @tmdzk From 20da8d626bb8ce960b5f488cde202bb0339bb189 Mon Sep 17 00:00:00 2001 From: Oriol Batalla Date: Tue, 2 Mar 2021 17:15:17 -0800 Subject: [PATCH 7/8] [feg] s6a_proxy modify Regional Zone Code from String to []byte (#5242) --- feg/cloud/go/protos/s6a_proxy.pb.go | 79 ++++++++++--------- .../s6a_proxy/servicers/s6a_definitions.go | 2 +- .../s6a_proxy/servicers/s6a_proxy_test.go | 5 +- .../servicers/test/test_s6a_server.go | 4 +- .../services/s6a_proxy/servicers/ul.go | 4 +- feg/protos/s6a_proxy.proto | 2 +- 6 files changed, 50 insertions(+), 46 deletions(-) diff --git a/feg/cloud/go/protos/s6a_proxy.pb.go b/feg/cloud/go/protos/s6a_proxy.pb.go index 0ce2c66464bc..8a3d13322d1e 100644 --- a/feg/cloud/go/protos/s6a_proxy.pb.go +++ b/feg/cloud/go/protos/s6a_proxy.pb.go @@ -671,7 +671,7 @@ type UpdateLocationAnswer struct { DefaultChargingCharacteristics string `protobuf:"bytes,6,opt,name=default_charging_characteristics,json=defaultChargingCharacteristics,proto3" json:"default_charging_characteristics,omitempty"` Msisdn []byte `protobuf:"bytes,7,opt,name=msisdn,proto3" json:"msisdn,omitempty"` NetworkAccessMode UpdateLocationAnswer_NetworkAccessMode `protobuf:"varint,8,opt,name=network_access_mode,json=networkAccessMode,proto3,enum=magma.feg.UpdateLocationAnswer_NetworkAccessMode" json:"network_access_mode,omitempty"` - RegionalSubscriptionZoneCode []string `protobuf:"bytes,9,rep,name=regional_subscription_zone_code,json=regionalSubscriptionZoneCode,proto3" json:"regional_subscription_zone_code,omitempty"` + RegionalSubscriptionZoneCode [][]byte `protobuf:"bytes,9,rep,name=regional_subscription_zone_code,json=regionalSubscriptionZoneCode,proto3" json:"regional_subscription_zone_code,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -758,7 +758,7 @@ func (m *UpdateLocationAnswer) GetNetworkAccessMode() UpdateLocationAnswer_Netwo return UpdateLocationAnswer_PACKET_AND_CIRCUIT } -func (m *UpdateLocationAnswer) GetRegionalSubscriptionZoneCode() []string { +func (m *UpdateLocationAnswer) GetRegionalSubscriptionZoneCode() [][]byte { if m != nil { return m.RegionalSubscriptionZoneCode } @@ -1250,7 +1250,7 @@ func init() { func init() { proto.RegisterFile("feg/protos/s6a_proxy.proto", fileDescriptor_f32b2af5087a8858) } var fileDescriptor_f32b2af5087a8858 = []byte{ - // 1903 bytes of a gzipped FileDescriptorProto + // 1905 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x58, 0xeb, 0x6e, 0xdb, 0xc8, 0x15, 0xb6, 0x7c, 0x89, 0xad, 0x63, 0xc9, 0xa1, 0x67, 0x9d, 0x48, 0x56, 0x92, 0xda, 0xab, 0xb6, 0x88, 0xe1, 0x6d, 0xed, 0x6d, 0xd2, 0xba, 0x97, 0xfd, 0xd1, 0xa5, 0xc5, 0x49, 0xcc, 0x58, 0xa2, @@ -1304,7 +1304,7 @@ var fileDescriptor_f32b2af5087a8858 = []byte{ 0x21, 0x06, 0x6f, 0x05, 0x3c, 0x79, 0x1a, 0x46, 0x8f, 0x29, 0x73, 0x1c, 0x1e, 0xc7, 0x74, 0x20, 0xda, 0xb2, 0x24, 0xdb, 0xf2, 0x95, 0x57, 0xa1, 0x36, 0x52, 0x57, 0x55, 0x7a, 0x76, 0x44, 0xcf, 0x56, 0x83, 0x69, 0x11, 0xc2, 0xb0, 0x11, 0xf1, 0xbe, 0x17, 0x06, 0xcc, 0xcf, 0x69, 0x36, 0x14, - 0x31, 0xe8, 0xf7, 0xc3, 0x80, 0xa7, 0x2c, 0x28, 0x6f, 0xce, 0x6d, 0x95, 0xc9, 0xcd, 0xdc, 0xcc, + 0x31, 0xe8, 0xf7, 0xc3, 0x80, 0xa7, 0x2c, 0x28, 0x6f, 0xce, 0x6d, 0x55, 0xc8, 0xcd, 0xdc, 0xcc, 0x2c, 0x58, 0x3d, 0x0c, 0x03, 0x2e, 0x28, 0xd0, 0xf8, 0xe9, 0x02, 0x28, 0xd3, 0x55, 0x42, 0xb7, 0x00, 0x0a, 0x7c, 0x28, 0x49, 0x3e, 0x94, 0x9d, 0x31, 0x11, 0xde, 0x81, 0xd5, 0x98, 0x47, 0x67, 0x9e, 0xc3, 0x69, 0xcc, 0x7d, 0xee, 0x08, 0x1f, 0xc9, 0x9a, 0x32, 0x51, 0x32, 0x85, 0x99, 0xcb, @@ -1335,41 +1335,42 @@ var fileDescriptor_f32b2af5087a8858 = []byte{ 0xa1, 0x9b, 0x50, 0xd7, 0x0d, 0xdd, 0xd2, 0xd5, 0x36, 0x55, 0x2d, 0x4b, 0x6d, 0x1d, 0x14, 0x82, 0xce, 0x37, 0x0f, 0x61, 0x6d, 0xf2, 0x6a, 0x97, 0x78, 0xa7, 0x35, 0xbf, 0x0c, 0x2b, 0xbd, 0x51, 0xd4, 0xe7, 0x36, 0x7e, 0x9d, 0xd2, 0x37, 0x35, 0xa8, 0x66, 0xe6, 0x97, 0x49, 0x7a, 0x1b, 0x2a, - 0x84, 0xc7, 0x3c, 0xc9, 0x53, 0xd6, 0x60, 0x51, 0xa6, 0x94, 0x13, 0x2b, 0x96, 0xf0, 0x15, 0xf1, - 0xa8, 0xbb, 0xcd, 0x7d, 0x58, 0x96, 0x86, 0x97, 0x48, 0xb6, 0xfd, 0xbf, 0x79, 0x28, 0x8f, 0x15, - 0xa8, 0x0a, 0x65, 0xdb, 0xd0, 0xf0, 0x3d, 0xdd, 0xc0, 0x9a, 0x32, 0x83, 0xae, 0x81, 0xd2, 0xb1, - 0xdb, 0x96, 0x4e, 0x49, 0xd7, 0x36, 0x34, 0xaa, 0xda, 0xd6, 0x81, 0xf2, 0xdf, 0x45, 0x54, 0x81, - 0x45, 0xd3, 0x6e, 0xb5, 0xb0, 0x69, 0x2a, 0xff, 0xba, 0x8a, 0xd6, 0xe0, 0x6a, 0x5b, 0xef, 0xe8, - 0x16, 0xd6, 0x68, 0x2e, 0xfd, 0xf7, 0x55, 0x54, 0x03, 0xd4, 0xea, 0x76, 0x3a, 0x82, 0xf0, 0xb6, - 0x61, 0xda, 0xbd, 0x2e, 0xb1, 0xb0, 0xa6, 0xfc, 0xa9, 0x86, 0xae, 0xc3, 0xaa, 0x6d, 0xa8, 0xfb, - 0x6d, 0x4c, 0xad, 0x2e, 0xd5, 0x70, 0x5b, 0x3f, 0xc2, 0x44, 0xf9, 0x73, 0x4d, 0xe4, 0x22, 0x58, - 0x6d, 0x77, 0xa8, 0xd1, 0xb5, 0x68, 0x36, 0x14, 0x9f, 0xd4, 0x50, 0x15, 0x96, 0xac, 0x6e, 0x97, - 0xee, 0xdb, 0xe6, 0x87, 0xca, 0x5f, 0x6a, 0x08, 0x41, 0xb5, 0xdd, 0xed, 0xf6, 0xa8, 0x86, 0x2d, - 0xdc, 0x12, 0x11, 0xff, 0x5a, 0x43, 0x75, 0x78, 0x8b, 0x60, 0x4d, 0x27, 0xb8, 0x65, 0x51, 0xdd, - 0xd0, 0xf4, 0x96, 0x2a, 0xd8, 0xa4, 0x7c, 0x5a, 0x43, 0x37, 0xa1, 0xa6, 0xf6, 0x7a, 0xed, 0x4c, - 0x92, 0x02, 0xc9, 0x90, 0xfc, 0x4d, 0x66, 0xd4, 0x8d, 0x23, 0xb5, 0xad, 0x6b, 0x07, 0x54, 0x23, - 0x74, 0x5f, 0xb7, 0x4c, 0xe5, 0xef, 0x45, 0x31, 0x55, 0x8f, 0x7a, 0xa9, 0xf8, 0x1f, 0x35, 0xb4, - 0x0a, 0x15, 0xdb, 0x38, 0x34, 0xba, 0xc7, 0x06, 0xed, 0x61, 0x4c, 0x94, 0x7f, 0xa6, 0xe1, 0x6d, - 0xeb, 0x00, 0x1b, 0x56, 0x9e, 0x81, 0xe0, 0x07, 0x29, 0xac, 0x5f, 0x6c, 0x08, 0x87, 0xae, 0x6d, - 0xd1, 0xee, 0x3d, 0x6a, 0xf6, 0xd4, 0x16, 0x56, 0x7e, 0xb9, 0x21, 0xd0, 0xe3, 0x36, 0x6e, 0x49, - 0xd3, 0x76, 0xd7, 0xb4, 0x94, 0x5f, 0x6d, 0xa0, 0x1b, 0x70, 0x5d, 0x04, 0xe9, 0x12, 0xfd, 0xe1, - 0x54, 0x8c, 0x1f, 0xdf, 0x96, 0x49, 0x4d, 0x4c, 0x68, 0x96, 0x59, 0xf9, 0xe1, 0x6d, 0x51, 0xd8, - 0x1c, 0x87, 0x89, 0x4d, 0x53, 0x78, 0xe8, 0x9a, 0xf2, 0xa3, 0xdb, 0xe8, 0x16, 0xd4, 0x73, 0x05, - 0xee, 0x99, 0xb4, 0x38, 0x59, 0xca, 0x6f, 0xb6, 0x45, 0x9b, 0x88, 0x6a, 0xc9, 0xea, 0xaa, 0xed, - 0x76, 0xf7, 0x18, 0x6b, 0xca, 0x6f, 0xb7, 0x65, 0xed, 0xba, 0x6a, 0x47, 0x37, 0xee, 0x4f, 0x68, - 0x7e, 0x72, 0x5b, 0xf4, 0x09, 0x7f, 0x60, 0xeb, 0xbd, 0x0e, 0x36, 0xac, 0x71, 0xfe, 0xdf, 0x49, - 0x0f, 0xdb, 0x38, 0x4c, 0xd3, 0x93, 0xa3, 0xd4, 0x51, 0xc3, 0xca, 0xef, 0xb7, 0xd1, 0x17, 0x60, - 0x63, 0xaa, 0x1c, 0x9a, 0x6a, 0xa9, 0xd4, 0x36, 0xd4, 0x23, 0x55, 0x6f, 0x8b, 0x96, 0x2b, 0xff, - 0xd9, 0xbc, 0xf3, 0xb3, 0x59, 0x58, 0x32, 0xf7, 0x58, 0x4f, 0x7c, 0x8d, 0xa3, 0x33, 0x58, 0x7f, - 0xe9, 0xc7, 0x0b, 0x7a, 0xe7, 0x75, 0x3e, 0x71, 0xb2, 0x21, 0x69, 0x6c, 0xbf, 0xfe, 0xf7, 0x50, - 0x73, 0x06, 0xd9, 0xb0, 0x32, 0xf9, 0x16, 0x46, 0x9b, 0x2f, 0x7d, 0x41, 0xe7, 0x19, 0x36, 0x5e, - 0xf1, 0x0a, 0x6f, 0xce, 0xa0, 0xf7, 0x61, 0x31, 0x9b, 0x7f, 0xb4, 0x5e, 0xb0, 0x9e, 0x5c, 0x21, - 0x8d, 0xfa, 0xf3, 0xaa, 0x3c, 0xc2, 0x9d, 0x5f, 0x97, 0x60, 0xd5, 0xdc, 0x63, 0xf7, 0x59, 0xc2, - 0x9f, 0xb2, 0x0b, 0x33, 0xfd, 0xff, 0x47, 0xc0, 0x9d, 0xdc, 0x69, 0x13, 0x70, 0x5f, 0xb8, 0xc9, - 0x27, 0xe0, 0xbe, 0x68, 0x21, 0x36, 0x67, 0xd0, 0xb7, 0x60, 0x41, 0xee, 0x0f, 0x54, 0x2b, 0xd8, - 0x16, 0x57, 0x4f, 0xe3, 0xfa, 0xb4, 0x22, 0xf7, 0xdd, 0xbf, 0xf1, 0x70, 0x5d, 0xaa, 0x76, 0x4f, - 0x79, 0x7f, 0xd7, 0xf1, 0xc3, 0x91, 0xbb, 0xdb, 0x0f, 0xb3, 0x9f, 0x5b, 0x4e, 0xae, 0xc8, 0xbf, - 0x77, 0xff, 0x1f, 0x00, 0x00, 0xff, 0xff, 0xb5, 0x0d, 0x0a, 0x5b, 0x83, 0x11, 0x00, 0x00, + 0x84, 0xc7, 0x3c, 0xc9, 0x53, 0xd6, 0x60, 0x51, 0xa6, 0x94, 0x13, 0x3b, 0xb7, 0x55, 0x26, 0x57, + 0xc4, 0xa3, 0xee, 0x36, 0xf7, 0x61, 0x59, 0x1a, 0x5e, 0x22, 0xd9, 0xf6, 0xff, 0xe6, 0xa1, 0x3c, + 0x56, 0xa0, 0x2a, 0x94, 0x6d, 0x43, 0xc3, 0xf7, 0x74, 0x03, 0x6b, 0xca, 0x0c, 0xba, 0x06, 0x4a, + 0xc7, 0x6e, 0x5b, 0x3a, 0x25, 0x5d, 0xdb, 0xd0, 0xa8, 0x6a, 0x5b, 0x07, 0xca, 0x7f, 0x17, 0x51, + 0x05, 0x16, 0x4d, 0xbb, 0xd5, 0xc2, 0xa6, 0xa9, 0xfc, 0xeb, 0x2a, 0x5a, 0x83, 0xab, 0x6d, 0xbd, + 0xa3, 0x5b, 0x58, 0xa3, 0xb9, 0xf4, 0xdf, 0x57, 0x51, 0x0d, 0x50, 0xab, 0xdb, 0xe9, 0x08, 0xc2, + 0xdb, 0x86, 0x69, 0xf7, 0xba, 0xc4, 0xc2, 0x9a, 0xf2, 0xa7, 0x1a, 0xba, 0x0e, 0xab, 0xb6, 0xa1, + 0xee, 0xb7, 0x31, 0xb5, 0xba, 0x54, 0xc3, 0x6d, 0xfd, 0x08, 0x13, 0xe5, 0xcf, 0x35, 0x91, 0x8b, + 0x60, 0xb5, 0xdd, 0xa1, 0x46, 0xd7, 0xa2, 0xd9, 0x50, 0x7c, 0x52, 0x43, 0x55, 0x58, 0xb2, 0xba, + 0x5d, 0xba, 0x6f, 0x9b, 0x1f, 0x2a, 0x7f, 0xa9, 0x21, 0x04, 0xd5, 0x76, 0xb7, 0xdb, 0xa3, 0x1a, + 0xb6, 0x70, 0x4b, 0x44, 0xfc, 0x6b, 0x0d, 0xd5, 0xe1, 0x2d, 0x82, 0x35, 0x9d, 0xe0, 0x96, 0x45, + 0x75, 0x43, 0xd3, 0x5b, 0xaa, 0x60, 0x93, 0xf2, 0x69, 0x0d, 0xdd, 0x84, 0x9a, 0xda, 0xeb, 0xb5, + 0x33, 0x49, 0x0a, 0x24, 0x43, 0xf2, 0x37, 0x99, 0x51, 0x37, 0x8e, 0xd4, 0xb6, 0xae, 0x1d, 0x50, + 0x8d, 0xd0, 0x7d, 0xdd, 0x32, 0x95, 0xbf, 0x17, 0xc5, 0x54, 0x3d, 0xea, 0xa5, 0xe2, 0x7f, 0xd4, + 0xd0, 0x2a, 0x54, 0x6c, 0xe3, 0xd0, 0xe8, 0x1e, 0x1b, 0xb4, 0x87, 0x31, 0x51, 0xfe, 0x99, 0x86, + 0xb7, 0xad, 0x03, 0x6c, 0x58, 0x79, 0x06, 0x82, 0x1f, 0xa4, 0xb0, 0x7e, 0xb1, 0x21, 0x1c, 0xba, + 0xb6, 0x45, 0xbb, 0xf7, 0xa8, 0xd9, 0x53, 0x5b, 0x58, 0xf9, 0xe5, 0x86, 0x40, 0x8f, 0xdb, 0xb8, + 0x25, 0x4d, 0xdb, 0x5d, 0xd3, 0x52, 0x7e, 0xb5, 0x81, 0x6e, 0xc0, 0x75, 0x11, 0xa4, 0x4b, 0xf4, + 0x87, 0x53, 0x31, 0x7e, 0x7c, 0x5b, 0x26, 0x35, 0x31, 0xa1, 0x59, 0x66, 0xe5, 0x87, 0xb7, 0x45, + 0x61, 0x73, 0x1c, 0x26, 0x36, 0x4d, 0xe1, 0xa1, 0x6b, 0xca, 0x8f, 0x6e, 0xa3, 0x5b, 0x50, 0xcf, + 0x15, 0xb8, 0x67, 0xd2, 0xe2, 0x64, 0x29, 0xbf, 0xd9, 0x16, 0x6d, 0x22, 0xaa, 0x25, 0xab, 0xab, + 0xb6, 0xdb, 0xdd, 0x63, 0xac, 0x29, 0xbf, 0xdd, 0x96, 0xb5, 0xeb, 0xaa, 0x1d, 0xdd, 0xb8, 0x3f, + 0xa1, 0xf9, 0xc9, 0x6d, 0xd1, 0x27, 0xfc, 0x81, 0xad, 0xf7, 0x3a, 0xd8, 0xb0, 0xc6, 0xf9, 0x7f, + 0x27, 0x3d, 0x6c, 0xe3, 0x30, 0x4d, 0x4f, 0x8e, 0x52, 0x47, 0x0d, 0x2b, 0xbf, 0xdf, 0x46, 0x5f, + 0x80, 0x8d, 0xa9, 0x72, 0x68, 0xaa, 0xa5, 0x52, 0xdb, 0x50, 0x8f, 0x54, 0xbd, 0x2d, 0x5a, 0xae, + 0xfc, 0x67, 0xf3, 0xce, 0xcf, 0x66, 0x61, 0xc9, 0xdc, 0x63, 0x3d, 0xf1, 0x35, 0x8e, 0xce, 0x60, + 0xfd, 0xa5, 0x1f, 0x2f, 0xe8, 0x9d, 0xd7, 0xf9, 0xc4, 0xc9, 0x86, 0xa4, 0xb1, 0xfd, 0xfa, 0xdf, + 0x43, 0xcd, 0x19, 0x64, 0xc3, 0xca, 0xe4, 0x5b, 0x18, 0x6d, 0xbe, 0xf4, 0x05, 0x9d, 0x67, 0xd8, + 0x78, 0xc5, 0x2b, 0xbc, 0x39, 0x83, 0xde, 0x87, 0xc5, 0x6c, 0xfe, 0xd1, 0x7a, 0xc1, 0x7a, 0x72, + 0x85, 0x34, 0xea, 0xcf, 0xab, 0xf2, 0x08, 0x77, 0x7e, 0x5d, 0x82, 0x55, 0x73, 0x8f, 0xdd, 0x67, + 0x09, 0x7f, 0xca, 0x2e, 0xcc, 0xf4, 0xff, 0x1f, 0x01, 0x77, 0x72, 0xa7, 0x4d, 0xc0, 0x7d, 0xe1, + 0x26, 0x9f, 0x80, 0xfb, 0xa2, 0x85, 0xd8, 0x9c, 0x41, 0xdf, 0x82, 0x05, 0xb9, 0x3f, 0x50, 0xad, + 0x60, 0x5b, 0x5c, 0x3d, 0x8d, 0xeb, 0xd3, 0x8a, 0xdc, 0x77, 0xff, 0xc6, 0xc3, 0x75, 0xa9, 0xda, + 0x3d, 0xe5, 0xfd, 0x5d, 0xc7, 0x0f, 0x47, 0xee, 0x6e, 0x3f, 0xcc, 0x7e, 0x6e, 0x39, 0xb9, 0x22, + 0xff, 0xde, 0xfd, 0x7f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xb4, 0xb4, 0x95, 0x86, 0x83, 0x11, 0x00, + 0x00, } // Reference imports to suppress errors if they are not otherwise used. diff --git a/feg/gateway/services/s6a_proxy/servicers/s6a_definitions.go b/feg/gateway/services/s6a_proxy/servicers/s6a_definitions.go index 8f76b69a79bd..19990635429c 100644 --- a/feg/gateway/services/s6a_proxy/servicers/s6a_definitions.go +++ b/feg/gateway/services/s6a_proxy/servicers/s6a_definitions.go @@ -188,7 +188,7 @@ type SubscriptionData struct { APNConfigurationProfile APNConfigurationProfile `avp:"APN-Configuration-Profile"` SubscribedPeriodicRauTauTimer uint32 `avp:"Subscribed-Periodic-RAU-TAU-Timer"` TgppChargingCharacteristics string `avp:"TGPP-Charging-Characteristics"` - RegionalSubscriptionZoneCode []datatype.OctetString `avp:"Regional-Subscription-Zone-Code"` + RegionalSubscriptionZoneCode []datatype.OctetString `avp:"Regional-Subscription-Zone-Code"` } type ULA struct { diff --git a/feg/gateway/services/s6a_proxy/servicers/s6a_proxy_test.go b/feg/gateway/services/s6a_proxy/servicers/s6a_proxy_test.go index 034096ae0a4f..14fec1908645 100644 --- a/feg/gateway/services/s6a_proxy/servicers/s6a_proxy_test.go +++ b/feg/gateway/services/s6a_proxy/servicers/s6a_proxy_test.go @@ -14,6 +14,7 @@ limitations under the License. package servicers_test import ( + "bytes" "fmt" "math/rand" "net" @@ -107,8 +108,10 @@ func TestS6aProxyService(t *testing.T) { if ulResp.ErrorCode != protos.ErrorCode_UNDEFINED { t.Errorf("Unexpected ULA Error Code: %d", ulResp.ErrorCode) } + assert.NoError(t, err) if len(ulResp.RegionalSubscriptionZoneCode) != 2 || - (ulResp.RegionalSubscriptionZoneCode[0] != "112233" || ulResp.RegionalSubscriptionZoneCode[1]!= "445566") { + !bytes.Equal(ulResp.RegionalSubscriptionZoneCode[0], []byte{155, 36, 12, 2, 227, 43, 246, 254}) || + !bytes.Equal(ulResp.RegionalSubscriptionZoneCode[1], []byte{1, 1, 0, 1}) { t.Errorf("There should be 2 Regional Subscription Zone Codes : %+v", ulResp.RegionalSubscriptionZoneCode) } diff --git a/feg/gateway/services/s6a_proxy/servicers/test/test_s6a_server.go b/feg/gateway/services/s6a_proxy/servicers/test/test_s6a_server.go index a382e674be38..1e41e202fd2c 100644 --- a/feg/gateway/services/s6a_proxy/servicers/test/test_s6a_server.go +++ b/feg/gateway/services/s6a_proxy/servicers/test/test_s6a_server.go @@ -321,8 +321,8 @@ func testSendULA(settings *sm.Settings, w io.Writer, m *diam.Message) (n int64, diam.NewAVP(avp.AccessRestrictionData, avp.Mbit|avp.Vbit, VENDOR_3GPP, datatype.Unsigned32(47)), diam.NewAVP(avp.SubscriberStatus, avp.Mbit|avp.Vbit, VENDOR_3GPP, datatype.Unsigned32(0)), diam.NewAVP(avp.NetworkAccessMode, avp.Mbit|avp.Vbit, VENDOR_3GPP, datatype.Unsigned32(2)), - diam.NewAVP(avp.RegionalSubscriptionZoneCode, avp.Mbit|avp.Vbit, VENDOR_3GPP, datatype.OctetString("112233")), - diam.NewAVP(avp.RegionalSubscriptionZoneCode, avp.Mbit|avp.Vbit, VENDOR_3GPP, datatype.OctetString("445566")), + diam.NewAVP(avp.RegionalSubscriptionZoneCode, avp.Mbit|avp.Vbit, VENDOR_3GPP, datatype.OctetString([]byte{155, 36, 12, 2, 227, 43, 246, 254})), + diam.NewAVP(avp.RegionalSubscriptionZoneCode, avp.Mbit|avp.Vbit, VENDOR_3GPP, datatype.OctetString([]byte{1, 1, 0, 1})), diam.NewAVP(avp.AMBR, avp.Mbit|avp.Vbit, VENDOR_3GPP, &diam.GroupedAVP{ AVP: []*diam.AVP{ diam.NewAVP( diff --git a/feg/gateway/services/s6a_proxy/servicers/ul.go b/feg/gateway/services/s6a_proxy/servicers/ul.go index fe4945d386a6..13cbf929bc5b 100644 --- a/feg/gateway/services/s6a_proxy/servicers/ul.go +++ b/feg/gateway/services/s6a_proxy/servicers/ul.go @@ -119,9 +119,9 @@ func (s *s6aProxy) UpdateLocationImpl(req *protos.UpdateLocationRequest) (*proto res.AllApnsIncluded = ula.SubscriptionData.APNConfigurationProfile.AllAPNConfigurationsIncludedIndicator == 0 res.NetworkAccessMode = protos.UpdateLocationAnswer_NetworkAccessMode(ula.SubscriptionData.NetworkAccessMode) - res.RegionalSubscriptionZoneCode = make([]string, len(ula.SubscriptionData.RegionalSubscriptionZoneCode)) + res.RegionalSubscriptionZoneCode = make([][]byte, len(ula.SubscriptionData.RegionalSubscriptionZoneCode)) for i, code := range ula.SubscriptionData.RegionalSubscriptionZoneCode { - res.RegionalSubscriptionZoneCode[i] = string(code) + res.RegionalSubscriptionZoneCode[i] = code.Serialize() } for _, apnCfg := range ula.SubscriptionData.APNConfigurationProfile.APNConfigs { res.Apn = append( diff --git a/feg/protos/s6a_proxy.proto b/feg/protos/s6a_proxy.proto index 5dfe21600b7a..f14c2f73bb47 100644 --- a/feg/protos/s6a_proxy.proto +++ b/feg/protos/s6a_proxy.proto @@ -168,7 +168,7 @@ message UpdateLocationAnswer { NetworkAccessMode network_access_mode = 8; - repeated string regional_subscription_zone_code = 9; + repeated bytes regional_subscription_zone_code = 9; message APNConfiguration { // APN identifier From 161d672a674703604d263bc2b97aca40a225063e Mon Sep 17 00:00:00 2001 From: Pravin Shelar Date: Tue, 2 Mar 2021 18:54:01 -0800 Subject: [PATCH 8/8] AGW: pipelined: use pyroute2 to manage TC queue and filters (#5240) Following commit adds second implementation for executing TC commands. This is using netlink socket rather than executing `tc` commands. I have seen good improvement over current master. following numbers are using `pipelined_cli.py enforcement stress_test_grpc` With pyroute2 ------------ Starting attaches Finished 600 attaches in 9.850383 seconds Actual attach rate = 61 UEs per sec Starting detaches Finished 600 detaches in 6.381709 seconds with current master ------------------- Starting attaches Finished 600 attaches in 22.11333 seconds Actual attach rate = 27 UEs per sec Starting detaches Finished 600 detaches in 6.360227 seconds Signed-off-by: Pravin B Shelar --- lte/gateway/configs/pipelined.yml | 1 + lte/gateway/configs/pipelined.yml_prod | 1 + .../python/magma/pipelined/bridge_util.py | 2 + .../python/magma/pipelined/qos/qos_tc_impl.py | 25 ++- .../python/magma/pipelined/qos/tc_ops_cmd.py | 4 +- .../magma/pipelined/qos/tc_ops_pyroute2.py | 145 +++++++++++++++ .../python/magma/pipelined/tests/test_qos.py | 47 +++-- .../pipelined/tests/test_qos_pyroute2.py | 173 ++++++++++++++++++ lte/gateway/python/setup.py | 3 +- 9 files changed, 372 insertions(+), 29 deletions(-) create mode 100644 lte/gateway/python/magma/pipelined/qos/tc_ops_pyroute2.py create mode 100755 lte/gateway/python/magma/pipelined/tests/test_qos_pyroute2.py diff --git a/lte/gateway/configs/pipelined.yml b/lte/gateway/configs/pipelined.yml index 22afdf4914b1..029b2eaf5994 100644 --- a/lte/gateway/configs/pipelined.yml +++ b/lte/gateway/configs/pipelined.yml @@ -109,6 +109,7 @@ ipv6_router_addr: 'd88d:aba4:472f:fc95:7e7d:8457:5301:ebce' qos: enable: true impl: linux_tc + enable_pyroute2: true max_rate: 1000000000 linux_tc: min_idx: 2 diff --git a/lte/gateway/configs/pipelined.yml_prod b/lte/gateway/configs/pipelined.yml_prod index 8af7ae262002..1a75befb18f8 100644 --- a/lte/gateway/configs/pipelined.yml_prod +++ b/lte/gateway/configs/pipelined.yml_prod @@ -107,6 +107,7 @@ ipv6_router_addr: 'd88d:aba4:472f:fc95:7e7d:8457:5301:ebce' qos: enable: true impl: linux_tc + enable_pyroute2: True max_rate: 1000000000 linux_tc: min_idx: 2 diff --git a/lte/gateway/python/magma/pipelined/bridge_util.py b/lte/gateway/python/magma/pipelined/bridge_util.py index a44565ee345b..7d96ad5b21ab 100644 --- a/lte/gateway/python/magma/pipelined/bridge_util.py +++ b/lte/gateway/python/magma/pipelined/bridge_util.py @@ -86,6 +86,8 @@ def create_internal_iface(bridge_name, iface_name, ip): if ip is not None: subprocess.Popen(["ifconfig", iface_name, ip]).wait() + subprocess.Popen(["ifconfig", iface_name, "up"]).wait() + @staticmethod def add_ovs_port(bridge_name: str, iface_name: str, ofp_port: str): """ diff --git a/lte/gateway/python/magma/pipelined/qos/qos_tc_impl.py b/lte/gateway/python/magma/pipelined/qos/qos_tc_impl.py index 02d199914cb7..8f8235140783 100644 --- a/lte/gateway/python/magma/pipelined/qos/qos_tc_impl.py +++ b/lte/gateway/python/magma/pipelined/qos/qos_tc_impl.py @@ -17,6 +17,7 @@ from .types import QosInfo from .utils import IdManager from .tc_ops_cmd import run_cmd, TcOpsCmd, argSplit +from .tc_ops_pyroute2 import TcOpsPyRoute2 LOG = logging.getLogger('pipelined.qos.qos_tc_impl') # LOG.setLevel(logging.DEBUG) @@ -32,16 +33,16 @@ class TrafficClass: Creates/Deletes queues in linux. Using Qdiscs for flow based rate limiting(traffic shaping) of user traffic. """ - tc_cmd = TcOpsCmd() + tc_ops = None @staticmethod def delete_class(intf: str, qid: int, skip_filter=False) -> int: qid_hex = hex(qid) if not skip_filter: - TrafficClass.tc_cmd.del_filter(intf, qid_hex, qid_hex) + TrafficClass.tc_ops.del_filter(intf, qid_hex, qid_hex) - return TrafficClass.tc_cmd.del_htb(intf, qid_hex) + return TrafficClass.tc_ops.del_htb(intf, qid_hex) @staticmethod def create_class(intf: str, qid: int, max_bw: int, rate=None, @@ -60,15 +61,22 @@ def create_class(intf: str, qid: int, max_bw: int, rate=None, qid_hex = hex(qid) parent_qid_hex = '1:' + hex(parent_qid) - err = TrafficClass.tc_cmd.create_htb(intf, qid_hex, max_bw, rate, parent_qid_hex) + err = TrafficClass.tc_ops.create_htb(intf, qid_hex, max_bw, rate, parent_qid_hex) if err < 0 or skip_filter: return err # add filter - return TrafficClass.tc_cmd.create_filter(intf, qid_hex, qid_hex) + return TrafficClass.tc_ops.create_filter(intf, qid_hex, qid_hex) @staticmethod - def init_qdisc(intf: str, show_error=False) -> int: + def init_qdisc(intf: str, show_error=False, enable_pyroute2=False) -> int: + # TODO: Convert this class into an object. + if TrafficClass.tc_ops is None: + if enable_pyroute2: + TrafficClass.tc_ops = TcOpsPyRoute2() + else: + TrafficClass.tc_ops = TcOpsCmd() + cmd_list = [] speed = DEFAULT_INTF_SPEED qid_hex = hex(ROOT_QID) @@ -203,6 +211,7 @@ def __init__(self, self._uplink = config['nat_iface'] self._downlink = config['enodeb_iface'] self._max_rate = config["qos"]["max_rate"] + self._enable_pyroute2 = config["qos"].get('enable_pyroute2', False) self._start_idx, self._max_idx = (config['qos']['linux_tc']['min_idx'], config['qos']['linux_tc']['max_idx']) self._id_manager = IdManager(self._start_idx, self._max_idx) @@ -227,8 +236,8 @@ def destroy(self, ): def setup(self, ): # initialize new qdisc - TrafficClass.init_qdisc(self._uplink) - TrafficClass.init_qdisc(self._downlink) + TrafficClass.init_qdisc(self._uplink, enable_pyroute2=self._enable_pyroute2) + TrafficClass.init_qdisc(self._downlink, enable_pyroute2=self._enable_pyroute2) def get_action_instruction(self, qid: int): # return an action and an instruction corresponding to this qid diff --git a/lte/gateway/python/magma/pipelined/qos/tc_ops_cmd.py b/lte/gateway/python/magma/pipelined/qos/tc_ops_cmd.py index a08b72376547..f2ffc1f9ec6e 100644 --- a/lte/gateway/python/magma/pipelined/qos/tc_ops_cmd.py +++ b/lte/gateway/python/magma/pipelined/qos/tc_ops_cmd.py @@ -75,6 +75,6 @@ def create_filter(self, iface: str, mark: str, qid: str, proto: int = 3) -> int: def del_filter(self, iface: str, mark: str, qid: str, proto: int = 3) -> int: filter_cmd = "tc filter del dev {intf} protocol ip parent 1: prio 1 " - filter_cmd += "handle {qid} fw flowid 1:{qid}" - filter_cmd = filter_cmd.format(intf=iface, qid=qid) + filter_cmd += "handle {mark} fw flowid 1:{qid}" + filter_cmd = filter_cmd.format(intf=iface, mark=mark, qid=qid) return run_cmd([filter_cmd], True) diff --git a/lte/gateway/python/magma/pipelined/qos/tc_ops_pyroute2.py b/lte/gateway/python/magma/pipelined/qos/tc_ops_pyroute2.py new file mode 100644 index 000000000000..8ad170da32d8 --- /dev/null +++ b/lte/gateway/python/magma/pipelined/qos/tc_ops_pyroute2.py @@ -0,0 +1,145 @@ +""" +Copyright 2021 The Magma Authors. + +This source code is licensed under the BSD-style license found in the +LICENSE file in the root directory of this source tree. + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +""" + + +from .tc_ops import TcOpsBase +import logging +from pyroute2 import IPRoute, NetlinkError +import pprint + +LOG = logging.getLogger('pipelined.qos.tc_pyroute2') + +QUEUE_PREFIX = '1:' +PROTOCOL = 0x0800 +PARENT_ID = 0x10000 + + +class TcOpsPyRoute2(TcOpsBase): + """ + Create TC scheduler and corresponding filter + """ + def __init__(self): + self._ipr = IPRoute() + self._iface_if_index = {} + LOG.info("initialized") + + def create_htb(self, iface: str, qid: str, max_bw: int, rate: str, + parent_qid: str = None) -> int: + LOG.debug("Create HTB iface %s qid %s", iface, qid) + + try: + if_index = self._get_if_index(iface) + htb_queue = QUEUE_PREFIX + qid + ret = self._ipr.tc("add-class", "htb", if_index, + htb_queue, parent=parent_qid, + rate=str(rate).lower(), ceil=max_bw, prio=1) + LOG.debug("Return: %s", ret) + except (ValueError, NetlinkError) as ex: + LOG.error("create-htb error : %s", ex.code) + LOG.debug(ex, exc_info=True) + return ex.code + return 0 + + def del_htb(self, iface: str, qid: str) -> int: + LOG.debug("Delete HTB iface %s qid %s", iface, qid) + + try: + if_index = self._get_if_index(iface) + htb_queue = QUEUE_PREFIX + qid + + ret = self._ipr.tc("del-class", "htb", if_index, htb_queue) + LOG.debug("Return: %s", ret) + except (ValueError, NetlinkError) as ex: + LOG.error("del-htb error error : %s", ex.code) + LOG.debug(ex, exc_info=True) + return ex.code + return 0 + + def create_filter(self, iface: str, mark: str, qid: str, proto: int = PROTOCOL) -> int: + LOG.debug("Create Filter iface %s qid %s", iface, qid) + + try: + if_index = self._get_if_index(iface) + + class_id = int(PARENT_ID) | int(qid, 16) + ret = self._ipr.tc("add-filter", "fw", if_index, int(mark, 16), + parent=PARENT_ID, + prio=1, + protocol=proto, + classid=class_id) + LOG.debug("Return: %s", ret) + + except (ValueError, NetlinkError) as ex: + LOG.error("create-filter error : %s", ex.code) + LOG.debug(ex, exc_info=True) + return ex.code + return 0 + + def del_filter(self, iface: str, mark: str, qid: str, proto: int = PROTOCOL) -> int: + LOG.debug("Del Filter iface %s qid %s", iface, qid) + + try: + if_index = self._get_if_index(iface) + + class_id = int(PARENT_ID) | int(qid, 16) + + ret = self._ipr.tc("del-filter", "fw", if_index, int(mark, 16), + parent=PARENT_ID, + prio=1, + protocol=proto, + classid=class_id) + LOG.debug("Return: %s", ret) + except (ValueError, NetlinkError) as ex: + LOG.error("del-filter error : %s", ex.code) + LOG.debug(ex, exc_info=True) + return ex.code + return 0 + + def create(self, iface: str, qid: str, max_bw: int, rate=None, + parent_qid: str = None, proto=PROTOCOL) -> int: + err = self.create_htb(iface, qid, max_bw, rate, parent_qid) + if err: + return err + err = self.create_filter(iface, qid, qid, proto) + if err: + return err + return 0 + + def delete(self, iface: str, qid: str, proto=PROTOCOL) -> int: + err = self.del_filter(iface, qid, qid, proto) + if err: + return err + + err = self.del_htb(iface, qid) + if err: + return err + + return 0 + + def _get_if_index(self, iface: str): + if_index = self._iface_if_index.get(iface, -1) + if if_index == -1: + if_index = self._ipr.link_lookup(ifname=iface) + self._iface_if_index[iface] = if_index + + return if_index + + def _print_classes(self, iface): + if_index = self._get_if_index(iface) + + pprint.pprint(self._ipr.get_classes(if_index)) + + def _print_filters(self, iface): + if_index = self._get_if_index(iface) + + pprint.pprint(self._ipr.get_filters(if_index)) diff --git a/lte/gateway/python/magma/pipelined/tests/test_qos.py b/lte/gateway/python/magma/pipelined/tests/test_qos.py index 9fc5730f3db6..310f79989f2e 100644 --- a/lte/gateway/python/magma/pipelined/tests/test_qos.py +++ b/lte/gateway/python/magma/pipelined/tests/test_qos.py @@ -15,6 +15,7 @@ import unittest from collections import namedtuple from unittest.mock import MagicMock, call, patch +from magma.pipelined.bridge_util import BridgeTools from magma.pipelined.qos.common import QosImplType, QosManager, SubscriberState from magma.pipelined.qos.qos_meter_impl import MeterManager @@ -107,8 +108,8 @@ def verifyTcAddQos(self, mock_get_action_inst, mock_traffic_cls, d, qid, qos_inf parent_qid=0, skip_filter=False): intf = self.ul_intf if d == FlowMatch.UPLINK else self.dl_intf mock_get_action_inst.assert_any_call(qid) - mock_traffic_cls.init_qdisc.assert_any_call(self.ul_intf) - mock_traffic_cls.init_qdisc.assert_any_call(self.dl_intf) + mock_traffic_cls.init_qdisc.assert_any_call(self.ul_intf, enable_pyroute2=False) + mock_traffic_cls.init_qdisc.assert_any_call(self.dl_intf, enable_pyroute2=False) mock_traffic_cls.create_class.assert_any_call(intf, qid, qos_info.mbr, rate=qos_info.gbr, parent_qid=parent_qid, skip_filter=skip_filter) @@ -837,12 +838,18 @@ def testBrokenMeter(self, meter_cls): class TestTrafficClass(unittest.TestCase): + @patch("subprocess.check_call") @patch("os.geteuid", return_value=1) def testSudoUser(self, _, mock_check_call): - TrafficClass.init_qdisc("eth0") + intf = 'qt' + BRIDGE = 'qtbr0' + BridgeTools.create_bridge(BRIDGE, BRIDGE) + BridgeTools.create_internal_iface(BRIDGE, intf, None) + + TrafficClass.init_qdisc(intf) mock_check_call.assert_any_call( - ["sudo", "tc", "qdisc", "add", "dev", "eth0", "root", "handle", "1:", "htb"] + ["sudo", "tc", "qdisc", "add", "dev", intf, "root", "handle", "1:", "htb"] ) @patch("subprocess.check_call") @@ -853,10 +860,14 @@ def dummy_check_call(*args): mock_check_call.side_effect = dummy_check_call with self.assertLogs("pipelined.qos.tc_cmd", level="ERROR") as cm: TrafficClass.init_qdisc("eth0", show_error=True) - self.assertTrue("error: 1 running: tc qdisc add dev eth" in cm.output[0]) + self.assertTrue("error: 1 running: tc qdisc add dev " in cm.output[0]) def testSanityTrafficClass(self, ): - intf = 'eth0' + intf = 'qt' + BRIDGE = 'qtbr0' + BridgeTools.create_bridge(BRIDGE, BRIDGE) + BridgeTools.create_internal_iface(BRIDGE, intf, None) + parent_qid = 2 qid = 3 apn_ambr = 1000000 @@ -872,14 +883,14 @@ def testSanityTrafficClass(self, ): parent_qid=parent_qid) # check if the filters installed for leaf class only - filter_output = subprocess.check_output(['tc', 'filter', 'show', 'dev', 'eth0']) + filter_output = subprocess.check_output(['tc', 'filter', 'show', 'dev', intf]) filter_list = filter_output.decode('utf-8').split("\n") filter_list = [ln for ln in filter_list if 'classid' in ln] assert('classid 1:{qid}'.format(qid=parent_qid) in filter_list[0]) assert('classid 1:{qid}'.format(qid=qid) in filter_list[1]) # check if classes are installed with appropriate bandwidth limits - class_output = subprocess.check_output(['tc', 'class', 'show', 'dev', 'eth0']) + class_output = subprocess.check_output(['tc', 'class', 'show', 'dev', intf]) class_list = class_output.decode('utf-8').split("\n") for info in class_list: if 'class htb 1:{qid}'.format(qid=qid) in info: @@ -892,40 +903,40 @@ def testSanityTrafficClass(self, ): assert(child_class and 'rate 250Kbit ceil 500Kbit' in child_class) # check if fq_codel is associated only with the leaf class - qdisc_output = subprocess.check_output(['tc', 'qdisc', 'show', 'dev', 'eth0']) + qdisc_output = subprocess.check_output(['tc', 'qdisc', 'show', 'dev', intf]) # check if read_all_classes work - qid_list = TrafficClass.read_all_classes('eth0') - assert( (qid, parent_qid) in qid_list) + qid_list = TrafficClass.read_all_classes(intf) + assert((qid, parent_qid) in qid_list) # delete leaf class - TrafficClass.delete_class('eth0', 3) + TrafficClass.delete_class(intf, 3) # check class for qid 3 removed - class_output = subprocess.check_output(['tc', 'class', 'show', 'dev', 'eth0']) + class_output = subprocess.check_output(['tc', 'class', 'show', 'dev', intf]) class_list = class_output.decode('utf-8').split("\n") assert( not [info for info in class_list if 'class htb 1:{qid}'.format( qid=qid) in info]) # delete APN AMBR class - TrafficClass.delete_class('eth0', 2) + TrafficClass.delete_class(intf, 2) # verify that parent class is removed - class_output = subprocess.check_output(['tc', 'class', 'show', 'dev', 'eth0']) + class_output = subprocess.check_output(['tc', 'class', 'show', 'dev', intf]) class_list = class_output.decode('utf-8').split("\n") assert( not [info for info in class_list if 'class htb 1:{qid}'.format( qid=parent_qid) in info]) # check if no fq_codel nor filter exists - qdisc_output = subprocess.check_output(['tc', 'qdisc', 'show', 'dev', 'eth0']) - filter_output = subprocess.check_output(['tc', 'filter', 'show', 'dev', 'eth0']) + qdisc_output = subprocess.check_output(['tc', 'qdisc', 'show', 'dev', intf]) + filter_output = subprocess.check_output(['tc', 'filter', 'show', 'dev', intf]) filter_list = filter_output.decode('utf-8').split("\n") filter_list = [ln for ln in filter_list if 'classid' in ln] qdisc_list = qdisc_output.decode('utf-8').split("\n") qdisc_list = [ln for ln in qdisc_list if 'fq_codel' in ln] assert(not filter_list and not qdisc_list) - # destroy all qos on eth0 + # destroy all qos on intf run_cmd(['tc qdisc del dev {intf} root'.format(intf=intf)]) diff --git a/lte/gateway/python/magma/pipelined/tests/test_qos_pyroute2.py b/lte/gateway/python/magma/pipelined/tests/test_qos_pyroute2.py new file mode 100755 index 000000000000..366ebb76773d --- /dev/null +++ b/lte/gateway/python/magma/pipelined/tests/test_qos_pyroute2.py @@ -0,0 +1,173 @@ +from pyroute2 import IPRoute +from pyroute2 import NetlinkError +from pyroute2 import protocols + +import unittest +import socket +import logging +import traceback +import time +import pprint +import subprocess +from magma.pipelined.bridge_util import BridgeTools +from magma.pipelined.qos.qos_tc_impl import TrafficClass +from magma.pipelined.qos.tc_ops_pyroute2 import TcOpsPyRoute2 +from magma.pipelined.qos.tc_ops_cmd import TcOpsCmd + +LOG = logging.getLogger('pipelined.qos.tc_rtnl') + +QUEUE_PREFIX = '1:' +PROTOCOL = 3 + + +class TcSetypTest(unittest.TestCase): + BRIDGE = 'testing_qos' + IFACE = 'dev_qos' + + @classmethod + def setUpClass(cls): + BridgeTools.create_bridge(cls.BRIDGE, cls.BRIDGE) + BridgeTools.create_internal_iface(cls.BRIDGE, cls.IFACE, None) + TrafficClass.init_qdisc(cls.IFACE, True) + + @classmethod + def tearDownClass(cls): + BridgeTools.destroy_bridge(cls.BRIDGE) + pass + + def check_qid_in_tc(self, qid): + cmd = "tc filter show dev dev_qos" + exe_cmd = cmd.split(" ") + output = subprocess.check_output(exe_cmd) + found = False + for ln in output.decode('utf-8').split("\n"): + ln = ln.strip() + if not ln: + continue + #print(ln) + tokens = ln.split(" ") + + if len(tokens) > 10 and tokens[9] == qid: + found = True + + return found + + def test_basic(self): + cls = self.__class__ + t1 = TcOpsPyRoute2() + iface = cls.IFACE + qid = "0xae" + max_bw = 10000 + rate = 1000 + parent_qid = '1:fffe' + + err1 = t1.create(iface, qid, max_bw, rate, parent_qid) + self.assertTrue(self.check_qid_in_tc(qid)) + err = t1.delete(iface, qid) + self.assertFalse(self.check_qid_in_tc(qid)) + self.assertEqual(err, 0) + self.assertEqual(err1, 0) + + def test_basic6(self): + cls = self.__class__ + t1 = TcOpsPyRoute2() + iface = cls.IFACE + qid = "0xae" + max_bw = 10000 + rate = 1000 + parent_qid = '1:fffe' + + err1 = t1.create(iface, qid, max_bw, rate, parent_qid, proto=0x86DD) + self.assertTrue(self.check_qid_in_tc(qid)) + err = t1.delete(iface, qid, proto=0x86DD) + self.assertFalse(self.check_qid_in_tc(qid)) + self.assertEqual(err, 0) + self.assertEqual(err1, 0) + + def test_hierarchy(self): + cls = self.__class__ + t1 = TcOpsPyRoute2() + # First queue + + iface1 = cls.IFACE + qid1 = "0xae" + max_bw = 10000 + rate = 1000 + parent_qid1 = '1:fffe' + + err1 = t1.create(iface1, qid1, max_bw, rate, parent_qid1) + self.assertTrue(self.check_qid_in_tc(qid1)) + + # Second queue + + qid2 = "0x1ae" + max_bw = 10000 + rate = 1000 + parent_qid2 = '1:' + qid1 + + err1 = t1.create(iface1, qid2, max_bw, rate, parent_qid2) + self.assertTrue(self.check_qid_in_tc(qid2)) + # t1._print_classes(iface1) + # t1._print_filters(iface1) + + err = t1.delete(iface1, qid2) + self.assertEqual(err, 0) + self.assertFalse(self.check_qid_in_tc(qid2)) + + err = t1.delete(iface1, qid1) + self.assertFalse(self.check_qid_in_tc(qid1)) + + self.assertEqual(err, 0) + self.assertEqual(err1, 0) + + def test_mix1(self): + cls = self.__class__ + t1 = TcOpsPyRoute2() + t2 = TcOpsCmd() + iface = cls.IFACE + qid = "0xae" + max_bw = 10000 + rate = 1000 + parent_qid = '1:fffe' + + err1 = t1.create(iface, qid, max_bw, rate, parent_qid) + self.assertTrue(self.check_qid_in_tc(qid)) + + err = t2.del_filter(iface, qid, qid) + self.assertEqual(err, 0) + err = t2.del_htb(iface, qid) + self.assertEqual(err, 0) + + self.assertFalse(self.check_qid_in_tc(qid)) + self.assertEqual(err, 0) + self.assertEqual(err1, 0) + + def test_mix2(self): + cls = self.__class__ + t1 = TcOpsPyRoute2() + t2 = TcOpsCmd() + iface = cls.IFACE + qid = "0xae" + max_bw = 10000 + rate = 1000 + parent_qid = '1:fffe' + + err1 = t2.create_htb(iface, qid, max_bw, rate, parent_qid) + self.assertEqual(err1, 0) + err1 = t2.create_filter(iface, qid, qid) + self.assertEqual(err1, 0) + + self.assertTrue(self.check_qid_in_tc(qid)) + + err = t1.del_filter(iface, qid, qid) + self.assertEqual(err, 0) + err = t1.del_htb(iface, qid) + self.assertEqual(err, 0) + + self.assertFalse(self.check_qid_in_tc(qid)) + self.assertEqual(err, 0) + self.assertEqual(err1, 0) + + +if __name__ == "__main__": + unittest.main() diff --git a/lte/gateway/python/setup.py b/lte/gateway/python/setup.py index e1dbd151ea9d..f873247dcba6 100644 --- a/lte/gateway/python/setup.py +++ b/lte/gateway/python/setup.py @@ -113,7 +113,8 @@ 'h2>=3.2.0', 'hpack>=3.0', 'freezegun>=0.3.15', - 'pycryptodome>=3.9.9' + 'pycryptodome>=3.9.9', + 'pyroute2' ], extras_require={ 'dev': [