Skip to content

Commit

Permalink
Merge branch 'next' into agpl_next
Browse files Browse the repository at this point in the history
  • Loading branch information
srs-codebot committed Oct 9, 2022
2 parents 3defd1b + 3c17686 commit e1d5f40
Show file tree
Hide file tree
Showing 10 changed files with 240 additions and 108 deletions.
6 changes: 5 additions & 1 deletion lib/include/srsran/common/network_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,14 @@ class unique_socket
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:
Expand Down
4 changes: 4 additions & 0 deletions lib/include/srsran/interfaces/enb_s1ap_interfaces.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
214 changes: 129 additions & 85 deletions lib/src/common/network_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand Down Expand Up @@ -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

/********************************************
Expand Down Expand Up @@ -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);
}
}

Expand All @@ -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
Expand Down
5 changes: 3 additions & 2 deletions lib/src/phy/rf/rf_imp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
30 changes: 21 additions & 9 deletions lib/test/common/network_utils_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
}

Expand Down
3 changes: 2 additions & 1 deletion srsenb/hdr/stack/rrc/rrc_ue.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ class rrc::ue
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
};

Expand Down
5 changes: 5 additions & 0 deletions srsenb/src/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,12 @@ void parse_args(all_args_t* args, int argc, char* argv[])
("expert.ts1_reloc_prep_timeout", bpo::value<uint32_t>(&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<uint32_t>(&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<int>(&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<bool>(&args->stack.s1ap.sctp_reuse_addr)->default_value(false), "Use SO_REUSE_ADDR on S1-C interface.")
("expert.max_s1_setup_retries", bpo::value<int32_t>(&args->stack.s1ap.max_s1_setup_retries)->default_value(-1), "Max S1 setup retries")
("expert.sctp_rto_max", bpo::value<int32_t>(&args->stack.s1ap.sctp_rto_max)->default_value(6000), "SCTP maximum RTO.")
("expert.sctp_init_max_attempts", bpo::value<int32_t>(&args->stack.s1ap.sctp_init_max_attempts)->default_value(3), "Maximum SCTP init attempts.")
("expert.sctp_max_init_timeo)", bpo::value<int32_t>(&args->stack.s1ap.sctp_max_init_timeo)->default_value(5000), "Maximum SCTP init timeout.")
("expert.rx_gain_offset", bpo::value<float>(&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<uint32_t>(&args->stack.mac.prach_bi)->default_value(0), "Backoff Indicator to reduce contention in the PRACH channel")

Expand Down
Loading

0 comments on commit e1d5f40

Please sign in to comment.