diff --git a/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml index 8c937ed76cc014330f600b3968fb77214a39d74e..c5d4d3aa6144cab4440297e338c37859925e1ec9 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml @@ -289,7 +289,7 @@ services: USE_ADDITIONAL_OPTIONS: --sa --rfsim --log_config.global_log_options level,nocolor,time -r 106 --numerology 1 -C 3619200000 --uicc0.imsi 208990100001100 - --rfsimulator.serveraddr 192.168.78.2 + --rfsimulator.serveraddr oai-du depends_on: - oai-du networks: diff --git a/radio/rfsimulator/README.md b/radio/rfsimulator/README.md index ba63ae4ec045cd6da6e2f8da22c35d2f73580906..c86724fa0dea1255797745ed645bb627fd2409db 100644 --- a/radio/rfsimulator/README.md +++ b/radio/rfsimulator/README.md @@ -71,7 +71,7 @@ The RF simulator is using the configuration module, and its parameters are defin | CL option | usage | default | |:--------------------- |:-------------------------------------------------------------------------------|----: | -|`--rfsimulator.serveraddr <addr>`| ip address to connect to, or `server` to behave as a tcp server | 127.0.0.1 | +|`--rfsimulator.serveraddr <addr>`| IPv4v6 address or DNS name to connect to, or `server` to behave as a IPv4v6 TCP server | 127.0.0.1 | |`--rfsimulator.serverport <port>`| port number to connect to or to listen on (eNB, which behaves as a tcp server) | 4043 | |`--rfsimulator.options` | list of comma separated run-time options, two are supported: `chanmod`, `saviq`| all options disabled | |`--rfsimulator.options saviq` | store IQs to a file for future replay | disabled | diff --git a/radio/rfsimulator/simulator.c b/radio/rfsimulator/simulator.c index c5197eaab8d62d824f0a44a50ce557faa489f610..3c19b492c87b9531c9dca38d9077733ac52405ce 100644 --- a/radio/rfsimulator/simulator.c +++ b/radio/rfsimulator/simulator.c @@ -29,6 +29,7 @@ */ #include <sys/socket.h> +#include <sys/types.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdlib.h> @@ -38,6 +39,8 @@ #include <stdbool.h> #include <errno.h> #include <sys/epoll.h> +#include <netdb.h> + #include <common/utils/assertions.h> #include <common/utils/LOG/log.h> #include <common/utils/load_module_shlib.h> @@ -544,30 +547,68 @@ static int rfsimu_vtime_cmd(char *buff, int debug, telnet_printfunc_t prnt, void return CMDSTATUS_FOUND; } -static int startServer(openair0_device *device) { - rfsimulator_state_t *t = (rfsimulator_state_t *) device->priv; +static int startServer(openair0_device *device) +{ + int sock = -1; + struct addrinfo *results = NULL; + struct addrinfo *rp= NULL; + + rfsimulator_state_t *t = (rfsimulator_state_t *)device->priv; t->role = SIMU_ROLE_SERVER; - t->listen_sock = socket(AF_INET, SOCK_STREAM, 0); - if (t->listen_sock < 0) { - LOG_E(HW, "socket(SOCK_STREAM) failed, errno(%d)\n", errno); + + char port[6]; + snprintf(port, sizeof(port), "%d", t->port); + + struct addrinfo hints = { + .ai_family = AF_INET6, + .ai_socktype = SOCK_STREAM, + .ai_flags = AI_PASSIVE, + }; + + int s = getaddrinfo(NULL, port, &hints, &results); + if (s != 0) { + LOG_E(HW, "getaddrinfo: %s\n", gai_strerror(s)); + freeaddrinfo(results); return -1; } + int enable = 1; - if (setsockopt(t->listen_sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) != 0) { - LOG_E(HW, "setsockopt(SO_REUSEADDR) failed, errno(%d)\n", errno); - return -1; + int disable = 0; + for (rp = results; rp != NULL; rp = rp->ai_next) { + sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if (sock == -1) { + continue; + } + + if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &disable, sizeof(int)) != 0) { + continue; + } + + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) != 0) { + continue; + } + + if (bind(sock, rp->ai_addr, rp->ai_addrlen) == 0) { + break; + } + + close(sock); + sock = -1; } - struct sockaddr_in addr = {.sin_family = AF_INET, .sin_port = htons(t->port), .sin_addr = {.s_addr = INADDR_ANY}}; - int rc = bind(t->listen_sock, (struct sockaddr *)&addr, sizeof(addr)); - if (rc < 0) { - LOG_E(HW, "bind() failed, errno(%d)\n", errno); + + freeaddrinfo(results); + + if (sock <= 0) { + LOG_E(HW, "could not open a socket\n"); return -1; } + t->listen_sock = sock; + if (listen(t->listen_sock, 5) != 0) { LOG_E(HW, "listen() failed, errno(%d)\n", errno); return -1; } - struct epoll_event ev= {0}; + struct epoll_event ev = {0}; ev.events = EPOLLIN; ev.data.fd = t->listen_sock; if (epoll_ctl(t->epollfd, EPOLL_CTL_ADD, t->listen_sock, &ev) != 0) { @@ -577,24 +618,58 @@ static int startServer(openair0_device *device) { return 0; } -static int startClient(openair0_device *device) { +static int client_try_connect(const char *host, uint16_t port) +{ + int sock = -1; + int s; + struct addrinfo *result = NULL; + struct addrinfo *rp = NULL; + + char dport[6]; + snprintf(dport, sizeof(dport), "%d", port); + + struct addrinfo hints = { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + }; + + s = getaddrinfo(host, dport, &hints, &result); + if (s != 0) { + LOG_E(HW, "getaddrinfo: %s\n", gai_strerror(s)); + return -1; + } + for (rp = result; rp != NULL; rp = rp->ai_next) { + sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if (sock == -1) { + continue; + } + + if (connect(sock, rp->ai_addr, rp->ai_addrlen) != -1) { + break; + } + + close(sock); + sock = -1; + } + + freeaddrinfo(result); + + return sock; +} + +static int startClient(openair0_device *device) +{ rfsimulator_state_t *t = device->priv; t->role = SIMU_ROLE_CLIENT; int sock; - if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - LOG_E(HW, "socket(SOCK_STREAM) failed, errno(%d)\n", errno); - return -1; - } - struct sockaddr_in addr = {.sin_family = AF_INET, .sin_port = htons(t->port), .sin_addr = {.s_addr = INADDR_ANY}}; - addr.sin_addr.s_addr = inet_addr(t->ip); - bool connected=false; - while(!connected) { + while (true) { LOG_I(HW, "Trying to connect to %s:%d\n", t->ip, t->port); + sock = client_try_connect(t->ip, t->port); - if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) { + if (sock > 0) { LOG_I(HW, "Connection to %s:%d established\n", t->ip, t->port); - connected=true; + break; } LOG_I(HW, "connect() to %s:%d failed, errno(%d)\n", t->ip, t->port, errno);