diff --git a/lib/include/srsran/common/network_utils.h b/lib/include/srsran/common/network_utils.h index f8c9e8a26..1c581b019 100644 --- a/lib/include/srsran/common/network_utils.h +++ b/lib/include/srsran/common/network_utils.h @@ -83,10 +83,14 @@ public: std::string get_ip() const { return net_utils::get_ip(addr); } net_utils::socket_type get_family() const { return net_utils::get_addr_family(sockfd); } + bool open_socket(net_utils::addr_family ip, net_utils::socket_type socket_type, net_utils::protocol_type protocol); bool bind_addr(const char* bind_addr_str, int port); bool connect_to(const char* dest_addr_str, int dest_port, sockaddr_in* dest_sockaddr = nullptr); bool start_listen(); - bool open_socket(net_utils::addr_family ip, net_utils::socket_type socket_type, net_utils::protocol_type protocol); + bool reuse_addr(); + bool sctp_subscribe_to_events(); + bool sctp_set_rto_opts(int rto_max); + bool sctp_set_init_msg_opts(int max_init_attempts, int max_init_timeo); int get_socket() const { return sockfd; }; protected: diff --git a/lib/include/srsran/interfaces/enb_s1ap_interfaces.h b/lib/include/srsran/interfaces/enb_s1ap_interfaces.h index 3f250fa4a..62a25a4b9 100644 --- a/lib/include/srsran/interfaces/enb_s1ap_interfaces.h +++ b/lib/include/srsran/interfaces/enb_s1ap_interfaces.h @@ -42,6 +42,10 @@ struct s1ap_args_t { uint32_t ts1_reloc_prep_timeout; uint32_t ts1_reloc_overall_timeout; int32_t max_s1_setup_retries; + bool sctp_reuse_addr; + int32_t sctp_rto_max; + int32_t sctp_init_max_attempts; + int32_t sctp_max_init_timeo; }; // S1AP interface for RRC diff --git a/lib/src/common/network_utils.cc b/lib/src/common/network_utils.cc index a84689113..a77b5061a 100644 --- a/lib/src/common/network_utils.cc +++ b/lib/src/common/network_utils.cc @@ -118,75 +118,7 @@ int open_socket(net_utils::addr_family ip_type, net_utils::socket_type socket_ty perror("Could not create socket\n"); return -1; } - - if (protocol == protocol_type::SCTP) { - // Sets the data_io_event to be able to use sendrecv_info - // Subscribes to the SCTP_SHUTDOWN event, to handle graceful shutdown - // Also subscribes to SCTP_PEER_ADDR_CHANGE, to handle ungraceful shutdown of the link. - struct sctp_event_subscribe evnts = {}; - evnts.sctp_data_io_event = 1; - evnts.sctp_shutdown_event = 1; - evnts.sctp_address_event = 1; - if (setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof(evnts)) != 0) { - srslog::fetch_basic_logger(LOGSERVICE).error("Failed to subscribe to SCTP_SHUTDOWN event: %s", strerror(errno)); - perror("Could not register socket to SCTP events\n"); - close(fd); - return -1; - } - - /* - * Modify SCTP default parameters for quicker detection of broken links. - * This includes changes to the SCTP_INITMSG parameters (to control the timeout of the connect() syscall) - * And changes to the maximum re-transmission timeout (rto_max), for quicker detection of broken links. - */ - // Set RTO_MAX to quickly detect broken links. - sctp_rtoinfo rto_opts; - socklen_t rto_sz = sizeof(sctp_rtoinfo); - rto_opts.srto_assoc_id = 0; - if (getsockopt(fd, SOL_SCTP, SCTP_RTOINFO, &rto_opts, &rto_sz) < 0) { - printf("Error getting RTO_INFO sockopts\n"); - close(fd); - return -1; - } - - rto_opts.srto_max = 6000; // 6 seconds - - srslog::fetch_basic_logger(LOGSERVICE) - .debug( - "Setting RTO_INFO options on SCTP socket. Association %d, Initial RTO %d, Minimum RTO %d, Maximum RTO %d", - rto_opts.srto_assoc_id, - rto_opts.srto_initial, - rto_opts.srto_min, - rto_opts.srto_max); - - if (setsockopt(fd, SOL_SCTP, SCTP_RTOINFO, &rto_opts, rto_sz) < 0) { - perror("Error setting RTO_INFO sockopts\n"); - close(fd); - return -1; - } - - // Set SCTP INITMSG options to reduce blocking timeout of connect() - sctp_initmsg init_opts; - socklen_t init_sz = sizeof(sctp_initmsg); - if (getsockopt(fd, SOL_SCTP, SCTP_INITMSG, &init_opts, &init_sz) < 0) { - printf("Error getting sockopts\n"); - close(fd); - return -1; - } - - init_opts.sinit_max_attempts = 3; - init_opts.sinit_max_init_timeo = 5000; // 5 seconds - - srslog::fetch_basic_logger(LOGSERVICE) - .debug("Setting SCTP_INITMSG options on SCTP socket. Max attempts %d, Max init attempts timeout %d", - init_opts.sinit_max_attempts, - init_opts.sinit_max_init_timeo); - if (setsockopt(fd, SOL_SCTP, SCTP_INITMSG, &init_opts, init_sz) < 0) { - perror("Error setting SCTP_INITMSG sockopts\n"); - close(fd); - return -1; - } - } + srslog::fetch_basic_logger(LOGSERVICE).debug("Opened %s socket=%d", net_utils::protocol_to_string(protocol), fd); return fd; } @@ -200,7 +132,12 @@ bool bind_addr(int fd, const sockaddr_in& addr_in) if (bind(fd, (struct sockaddr*)&addr_in, sizeof(addr_in)) != 0) { srslog::fetch_basic_logger(LOGSERVICE) - .error("Failed to bind on address %s: %s errno %d", get_ip(addr_in).c_str(), strerror(errno), errno); + .error("Failed to bind on address %s:%d. Socket=%d, strerror=%s, errno=%d", + get_ip(addr_in).c_str(), + get_port(addr_in), + fd, + strerror(errno), + errno); perror("bind()"); return false; } @@ -267,6 +204,107 @@ bool start_listen(int fd) return true; } +bool reuse_addr(int fd) +{ + if (fd < 0) { + srslog::fetch_basic_logger(LOGSERVICE).error("Trying reuse_addr a closed socket. Socket=%d", fd); + return false; + } + + int enable = 1; + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0) { + srslog::fetch_basic_logger(LOGSERVICE).error("Failed to set SO_REUSEADDR. Socket=%d", fd); + return false; + } + srslog::fetch_basic_logger(LOGSERVICE).debug("Successfully set SO_REUSEADDR. Socket=%d", fd); + return true; +} + +bool sctp_subscribe_to_events(int fd) +{ + if (fd < 0) { + srslog::fetch_basic_logger(LOGSERVICE).error("Trying subscribe to SCTP events on a closed socket. Socket=%d", fd); + return false; + } + + // Sets the data_io_event to be able to use sendrecv_info + // Subscribes to the SCTP_SHUTDOWN event, to handle graceful shutdown + // Also subscribes to SCTP_PEER_ADDR_CHANGE, to handle ungraceful shutdown of the link. + struct sctp_event_subscribe evnts = {}; + evnts.sctp_data_io_event = 1; + evnts.sctp_shutdown_event = 1; + evnts.sctp_address_event = 1; + if (setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof(evnts)) != 0) { + srslog::fetch_basic_logger(LOGSERVICE).error("Failed to subscribe to SCTP_SHUTDOWN event: %s", strerror(errno)); + perror("Could not register socket to SCTP events\n"); + close(fd); + return false; + } + return true; +} + +/* + * Modify SCTP default parameters for quicker detection of broken links. + * Changes to the maximum re-transmission timeout (rto_max). + */ +bool sctp_set_rto_opts(int fd, int rto_max) +{ + // Set RTO_MAX to quickly detect broken links. + sctp_rtoinfo rto_opts; + socklen_t rto_sz = sizeof(sctp_rtoinfo); + rto_opts.srto_assoc_id = 0; + if (getsockopt(fd, SOL_SCTP, SCTP_RTOINFO, &rto_opts, &rto_sz) < 0) { + printf("Error getting RTO_INFO sockopts\n"); + close(fd); + return false; + } + + rto_opts.srto_max = rto_max; + + srslog::fetch_basic_logger(LOGSERVICE) + .debug("Setting RTO_INFO options on SCTP socket. Association %d, Initial RTO %d, Minimum RTO %d, Maximum RTO %d", + rto_opts.srto_assoc_id, + rto_opts.srto_initial, + rto_opts.srto_min, + rto_opts.srto_max); + + if (setsockopt(fd, SOL_SCTP, SCTP_RTOINFO, &rto_opts, rto_sz) < 0) { + perror("Error setting RTO_INFO sockopts\n"); + close(fd); + return false; + } + return true; +} + +/* + * Modify SCTP default parameters for quicker detection of broken links. + * Changes to the SCTP_INITMSG parameters (to control the timeout of the connect() syscall) + */ +bool sctp_set_init_msg_opts(int fd, int init_max_attempts, int max_init_timeo) +{ + // Set SCTP INITMSG options to reduce blocking timeout of connect() + sctp_initmsg init_opts; + socklen_t init_sz = sizeof(sctp_initmsg); + if (getsockopt(fd, SOL_SCTP, SCTP_INITMSG, &init_opts, &init_sz) < 0) { + printf("Error getting sockopts\n"); + close(fd); + return false; + } + + init_opts.sinit_max_attempts = init_max_attempts; + init_opts.sinit_max_init_timeo = max_init_timeo; + + srslog::fetch_basic_logger(LOGSERVICE) + .debug("Setting SCTP_INITMSG options on SCTP socket. Max attempts %d, Max init attempts timeout %d", + init_opts.sinit_max_attempts, + init_opts.sinit_max_init_timeo); + if (setsockopt(fd, SOL_SCTP, SCTP_INITMSG, &init_opts, init_sz) < 0) { + perror("Error setting SCTP_INITMSG sockopts\n"); + close(fd); + return false; + } + return true; +} } // namespace net_utils /******************************************** @@ -306,9 +344,15 @@ bool unique_socket::open_socket(net_utils::addr_family ip_type, void unique_socket::close() { if (sockfd >= 0) { - ::close(sockfd); + if (::close(sockfd) == -1) { + srslog::fetch_basic_logger(LOGSERVICE).error("Socket=%d could not be closed.", sockfd); + } else { + srslog::fetch_basic_logger(LOGSERVICE).debug("Socket=%d was closed.", sockfd); + } sockfd = -1; addr = {}; + } else { + srslog::fetch_basic_logger(LOGSERVICE).debug("Socket=%d could not be closed.", sockfd); } } @@ -327,25 +371,25 @@ bool unique_socket::start_listen() return net_utils::start_listen(sockfd); } -/*********************************************************************** - * SCTP socket - **********************************************************************/ +bool unique_socket::reuse_addr() +{ + return net_utils::reuse_addr(sockfd); +} -namespace net_utils { +bool unique_socket::sctp_subscribe_to_events() +{ + return net_utils::sctp_subscribe_to_events(sockfd); +} -bool sctp_init_socket(unique_socket* socket, net_utils::socket_type socktype, const char* bind_addr_str, int bind_port) +bool unique_socket::sctp_set_rto_opts(int rto_max) { - if (not socket->open_socket(net_utils::addr_family::ipv4, socktype, net_utils::protocol_type::SCTP)) { - return false; - } - if (not socket->bind_addr(bind_addr_str, bind_port)) { - socket->close(); - return false; - } - return true; + return net_utils::sctp_set_rto_opts(sockfd, rto_max); } -} // namespace net_utils +bool unique_socket::sctp_set_init_msg_opts(int max_init_attempts, int max_init_timeo) +{ + return net_utils::sctp_set_init_msg_opts(sockfd, max_init_attempts, max_init_timeo); +} /*************************************************************** * Rx Multisocket Handler diff --git a/lib/src/phy/rf/rf_imp.c b/lib/src/phy/rf/rf_imp.c index 95ee4f113..6e756385b 100644 --- a/lib/src/phy/rf/rf_imp.c +++ b/lib/src/phy/rf/rf_imp.c @@ -428,8 +428,9 @@ static int load_plugin(srsran_rf_plugin_t* rf_plugin) rf_plugin->dl_handle = dlopen(rf_plugin->plugin_name, RTLD_NOW); if (rf_plugin->dl_handle == NULL) { // Not an error, if loading failed due to missing dependencies. - // Mark this plugin as not available and return SUCCESS. - INFO("Failed to load RF plugin %s: %s", rf_plugin->plugin_name, dlerror()); + // Flag this plugin as not available and return SUCCESS. + // Note: as this function is called before log-level is configured, use plain printf for any messages < ERROR + printf("Skipping RF plugin %s: %s\n", rf_plugin->plugin_name, dlerror()); rf_plugin->rf_api = NULL; return SRSRAN_SUCCESS; } diff --git a/lib/test/common/network_utils_test.cc b/lib/test/common/network_utils_test.cc index 6cb12818c..a41f08558 100644 --- a/lib/test/common/network_utils_test.cc +++ b/lib/test/common/network_utils_test.cc @@ -61,13 +61,19 @@ int test_socket_handler() const char* server_addr = "127.0.100.1"; using namespace srsran::net_utils; - TESTASSERT(sctp_init_socket(&server_socket, socket_type::seqpacket, server_addr, server_port)); + TESTASSERT(server_socket.open_socket( + srsran::net_utils::addr_family::ipv4, socket_type::seqpacket, srsran::net_utils::protocol_type::SCTP)); + TESTASSERT(server_socket.bind_addr(server_addr, server_port)); TESTASSERT(server_socket.start_listen()); logger.info("Listening from fd=%d", server_socket.fd()); - TESTASSERT(sctp_init_socket(&client_socket, socket_type::seqpacket, "127.0.0.1", 0)); - TESTASSERT(sctp_init_socket(&client_socket2, socket_type::seqpacket, "127.0.0.2", 0)); + TESTASSERT(client_socket.open_socket( + srsran::net_utils::addr_family::ipv4, socket_type::seqpacket, srsran::net_utils::protocol_type::SCTP)); + TESTASSERT(client_socket.bind_addr("127.0.0.1", 0)); TESTASSERT(client_socket.connect_to(server_addr, server_port)); + TESTASSERT(client_socket2.open_socket( + srsran::net_utils::addr_family::ipv4, socket_type::seqpacket, srsran::net_utils::protocol_type::SCTP)); + TESTASSERT(client_socket2.bind_addr("127.0.0.2", 0)); TESTASSERT(client_socket2.connect_to(server_addr, server_port)); // register server Rx handler @@ -127,12 +133,18 @@ int test_socket_handler() int test_sctp_bind_error() { srsran::unique_socket sock; - TESTASSERT(not srsran::net_utils::sctp_init_socket( - &sock, srsran::net_utils::socket_type::seqpacket, "1.1.1.1", 8000)); // Bogus IP address - // should not be able to bind - TESTASSERT(srsran::net_utils::sctp_init_socket( - &sock, srsran::net_utils::socket_type::seqpacket, "127.0.0.1", 8000)); // Good IP address - // should be able to bind + TESTASSERT(sock.open_socket(srsran::net_utils::addr_family::ipv4, + srsran::net_utils::socket_type::seqpacket, + srsran::net_utils::protocol_type::SCTP)); + TESTASSERT(not sock.bind_addr("1.1.1.1", 8000)); // Bogus IP address + // should not be able to bind + + srsran::unique_socket sock2; + TESTASSERT(sock2.open_socket(srsran::net_utils::addr_family::ipv4, + srsran::net_utils::socket_type::seqpacket, + srsran::net_utils::protocol_type::SCTP)); + TESTASSERT(sock.bind_addr("127.0.0.1", 8000)); // Good IP address + // should be able to bind return SRSRAN_SUCCESS; } diff --git a/srsenb/hdr/stack/rrc/rrc_ue.h b/srsenb/hdr/stack/rrc/rrc_ue.h index ec77aea50..d2bc2d580 100644 --- a/srsenb/hdr/stack/rrc/rrc_ue.h +++ b/srsenb/hdr/stack/rrc/rrc_ue.h @@ -39,7 +39,8 @@ public: enum activity_timeout_type_t { MSG3_RX_TIMEOUT = 0, ///< Msg3 has its own timeout to quickly remove fake UEs from random PRACHs UE_INACTIVITY_TIMEOUT, ///< UE inactivity timeout (usually bigger than reestablishment timeout) - MSG5_RX_TIMEOUT, ///< UE timeout for receiving RRCConnectionSetupComplete / RRCReestablishmentComplete + MSG5_RX_TIMEOUT_T300, ///< UE timeout for receiving RRCConnectionSetupComplete + MSG5_RX_TIMEOUT_T301, ///< UE timeout for receiving RRCReestablishmentComplete nulltype }; diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index 2e7153296..baac499c0 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -267,7 +267,12 @@ void parse_args(all_args_t* args, int argc, char* argv[]) ("expert.ts1_reloc_prep_timeout", bpo::value(&args->stack.s1ap.ts1_reloc_prep_timeout)->default_value(10000), "S1AP TS 36.413 TS1RelocPrep Expiry Timeout value in milliseconds.") ("expert.ts1_reloc_overall_timeout", bpo::value(&args->stack.s1ap.ts1_reloc_overall_timeout)->default_value(10000), "S1AP TS 36.413 TS1RelocOverall Expiry Timeout value in milliseconds.") ("expert.rlf_min_ul_snr_estim", bpo::value(&args->stack.mac.rlf_min_ul_snr_estim)->default_value(-2), "SNR threshold in dB below which the eNB is notified with rlf ko.") + + ("expert.sctp_reuse_addr", bpo::value(&args->stack.s1ap.sctp_reuse_addr)->default_value(false), "Use SO_REUSE_ADDR on S1-C interface.") ("expert.max_s1_setup_retries", bpo::value(&args->stack.s1ap.max_s1_setup_retries)->default_value(-1), "Max S1 setup retries") + ("expert.sctp_rto_max", bpo::value(&args->stack.s1ap.sctp_rto_max)->default_value(6000), "SCTP maximum RTO.") + ("expert.sctp_init_max_attempts", bpo::value(&args->stack.s1ap.sctp_init_max_attempts)->default_value(3), "Maximum SCTP init attempts.") + ("expert.sctp_max_init_timeo)", bpo::value(&args->stack.s1ap.sctp_max_init_timeo)->default_value(5000), "Maximum SCTP init timeout.") ("expert.rx_gain_offset", bpo::value(&args->phy.rx_gain_offset)->default_value(62), "RX Gain offset to add to rx_gain to calibrate RSRP readings") ("expert.mac_prach_bi", bpo::value(&args->stack.mac.prach_bi)->default_value(0), "Backoff Indicator to reduce contention in the PRACH channel") diff --git a/srsenb/src/stack/rrc/rrc_ue.cc b/srsenb/src/stack/rrc/rrc_ue.cc index e82c956d2..3c9a86984 100644 --- a/srsenb/src/stack/rrc/rrc_ue.cc +++ b/srsenb/src/stack/rrc/rrc_ue.cc @@ -221,7 +221,8 @@ void rrc::ue::activity_timer_expired(const activity_timeout_type_t type) con_release_result = procedure_result_code::activity_timeout; break; case MSG3_RX_TIMEOUT: - case MSG5_RX_TIMEOUT: + case MSG5_RX_TIMEOUT_T300: + case MSG5_RX_TIMEOUT_T301: // MSG3 timeout, no need to notify S1AP, just remove UE parent->rem_user_thread(rnti); con_release_result = procedure_result_code::msg3_timeout; @@ -301,7 +302,10 @@ void rrc::ue::set_activity_timeout(activity_timeout_type_t type) case UE_INACTIVITY_TIMEOUT: deadline_ms = parent->cfg.inactivity_timeout_ms; break; - case MSG5_RX_TIMEOUT: + case MSG5_RX_TIMEOUT_T300: + deadline_ms = get_ue_cc_cfg(UE_PCELL_CC_IDX)->sib2.ue_timers_and_consts.t300.to_number(); + break; + case MSG5_RX_TIMEOUT_T301: deadline_ms = get_ue_cc_cfg(UE_PCELL_CC_IDX)->sib2.ue_timers_and_consts.t301.to_number(); break; default: @@ -350,6 +354,7 @@ void rrc::ue::parse_ul_dcch(uint32_t lcid, srsran::unique_byte_buffer_t pdu) case ul_dcch_msg_type_c::c1_c_::types::rrc_conn_setup_complete: save_ul_message(std::move(original_pdu)); handle_rrc_con_setup_complete(&ul_dcch_msg.msg.c1().rrc_conn_setup_complete(), std::move(pdu)); + set_activity_timeout(UE_INACTIVITY_TIMEOUT); set_activity(); break; case ul_dcch_msg_type_c::c1_c_::types::rrc_conn_reest_complete: @@ -429,7 +434,7 @@ void rrc::ue::parse_ul_dcch(uint32_t lcid, srsran::unique_byte_buffer_t pdu) std::string rrc::ue::to_string(const activity_timeout_type_t& type) { - constexpr static const char* options[] = {"Msg3 reception", "UE inactivity", "UE reestablishment"}; + constexpr static const char* options[] = {"Msg3 reception", "UE inactivity", "UE establishment", "UE reestablishment"}; return srsran::enum_to_text(options, (uint32_t)activity_timeout_type_t::nulltype, (uint32_t)type); } @@ -483,7 +488,7 @@ void rrc::ue::handle_rrc_con_req(rrc_conn_request_s* msg) send_connection_setup(); state = RRC_STATE_WAIT_FOR_CON_SETUP_COMPLETE; - set_activity_timeout(UE_INACTIVITY_TIMEOUT); + set_activity_timeout(MSG5_RX_TIMEOUT_T300); } void rrc::ue::send_connection_setup() @@ -739,7 +744,7 @@ void rrc::ue::handle_rrc_con_reest_req(rrc_conn_reest_request_s* msg) parent->rem_user_thread(old_rnti); state = RRC_STATE_WAIT_FOR_CON_REEST_COMPLETE; - set_activity_timeout(MSG5_RX_TIMEOUT); + set_activity_timeout(MSG5_RX_TIMEOUT_T301); } void rrc::ue::send_connection_reest(uint8_t ncc) diff --git a/srsenb/src/stack/s1ap/s1ap.cc b/srsenb/src/stack/s1ap/s1ap.cc index 230688d68..8fa6ead04 100644 --- a/srsenb/src/stack/s1ap/s1ap.cc +++ b/srsenb/src/stack/s1ap/s1ap.cc @@ -500,9 +500,39 @@ bool s1ap::connect_mme() using namespace srsran::net_utils; logger.info("Connecting to MME %s:%d", args.mme_addr.c_str(), int(MME_PORT)); - // Init SCTP socket and bind it - if (not srsran::net_utils::sctp_init_socket( - &mme_socket, socket_type::seqpacket, args.s1c_bind_addr.c_str(), args.s1c_bind_port)) { + // Open SCTP socket + if (not mme_socket.open_socket( + srsran::net_utils::addr_family::ipv4, socket_type::seqpacket, srsran::net_utils::protocol_type::SCTP)) { + return false; + } + + // Set SO_REUSE_ADDR if necessary + if (args.sctp_reuse_addr) { + if (not mme_socket.reuse_addr()) { + mme_socket.close(); + return false; + } + } + + // Subscribe to shutdown events + if (not mme_socket.sctp_subscribe_to_events()) { + mme_socket.close(); + return false; + } + + // Set SRTO_MAX + if (not mme_socket.sctp_set_rto_opts(args.sctp_rto_max)) { + return false; + } + + // Set SCTP init options + if (not mme_socket.sctp_set_init_msg_opts(args.sctp_init_max_attempts, args.sctp_max_init_timeo)) { + return false; + } + + // Bind socket + if (not mme_socket.bind_addr(args.s1c_bind_addr.c_str(), args.s1c_bind_port)) { + mme_socket.close(); return false; } logger.info("SCTP socket opened. fd=%d", mme_socket.fd()); @@ -1112,6 +1142,10 @@ bool s1ap::handle_s1setupfailure(const asn1::s1ap::s1_setup_fail_s& msg) return false; } + s1_setup_proc_t::s1setupresult res; + res.success = false; + s1setup_proc.trigger(res); + std::string cause = get_cause(msg->cause.value); logger.error("S1 Setup Failure. Cause: %s", cause.c_str()); srsran::console("S1 Setup Failure. Cause: %s\n", cause.c_str()); diff --git a/srsgnb/src/stack/ngap/ngap.cc b/srsgnb/src/stack/ngap/ngap.cc index d25184dc7..881e8ada2 100644 --- a/srsgnb/src/stack/ngap/ngap.cc +++ b/srsgnb/src/stack/ngap/ngap.cc @@ -642,12 +642,34 @@ bool ngap::connect_amf() using namespace srsran::net_utils; logger.info("Connecting to AMF %s:%d", args.amf_addr.c_str(), int(AMF_PORT)); - // Init SCTP socket and bind it - if (not sctp_init_socket(&amf_socket, socket_type::seqpacket, args.ngc_bind_addr.c_str(), 0)) { + // Open SCTP socket + if (not amf_socket.open_socket( + srsran::net_utils::addr_family::ipv4, socket_type::seqpacket, srsran::net_utils::protocol_type::SCTP)) { return false; } logger.info("SCTP socket opened. fd=%d", amf_socket.fd()); + if (not amf_socket.sctp_subscribe_to_events()) { + amf_socket.close(); + return false; + } + + if (not amf_socket.sctp_set_rto_opts(5000)) { + amf_socket.close(); + return false; + } + + if (not amf_socket.sctp_set_init_msg_opts(3, 6000)) { + amf_socket.close(); + return false; + } + + // Bind socket + if (not amf_socket.bind_addr(args.ngc_bind_addr.c_str(), 0)) { + amf_socket.close(); + return false; + } + // Connect to the AMF address if (not amf_socket.connect_to(args.amf_addr.c_str(), AMF_PORT, &amf_addr)) { return false;