diff --git a/common/utils/tun_if.c b/common/utils/tun_if.c index 4d0432599898a9491f97794d5e1b473c83f3eea0..79fcc6a9540a4acd7873ca7ff11499a2771d91d8 100644 --- a/common/utils/tun_if.c +++ b/common/utils/tun_if.c @@ -38,7 +38,7 @@ int nas_sock_fd[MAX_MOBILES_PER_ENB * 2]; // Allocated for both LTE UE and NR UE. int nas_sock_mbms_fd; -static int tun_alloc(char *dev) +static int tun_alloc(const char *dev) { struct ifreq ifr; int fd, err; @@ -55,25 +55,27 @@ static int tun_alloc(char *dev) * IFF_NO_PI - Do not provide packet information */ ifr.ifr_flags = IFF_TUN | IFF_NO_PI; - - if (*dev) - strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name) - 1); - + strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name) - 1); if ((err = ioctl(fd, TUNSETIFF, (void *)&ifr)) < 0) { close(fd); return err; } + // According to https://www.kernel.org/doc/Documentation/networking/tuntap.txt, TUNSETIFF performs string + // formatting on ifr_name. To ensure that the generated name is what we expect, check it here. + AssertFatal(strcmp(ifr.ifr_name, dev) == 0, "Failed to create tun interface, expected ifname %s, got %s\n", dev, ifr.ifr_name); + + err = fcntl(fd, F_SETFL, O_NONBLOCK); + if (err == -1) { + close(fd); + LOG_E(UTIL, "Error fcntl (%d:%s)\n", errno, strerror(errno)); + return err; + } - strcpy(dev, ifr.ifr_name); return fd; } -int tun_init_mbms(char *ifprefix, int id) +int tun_init_mbms(char *ifname) { - int ret; - char ifname[64]; - - sprintf(ifname, "%s%d", ifprefix, id); nas_sock_mbms_fd = tun_alloc(ifname); if (nas_sock_mbms_fd == -1) { @@ -82,48 +84,26 @@ int tun_init_mbms(char *ifprefix, int id) } LOG_D(UTIL, "Opened socket %s with fd %d\n", ifname, nas_sock_mbms_fd); - ret = fcntl(nas_sock_mbms_fd, F_SETFL, O_NONBLOCK); - - if (ret == -1) { - LOG_E(UTIL, "Error fcntl (%d:%s)\n", errno, strerror(errno)); - return 0; - } struct sockaddr_nl nas_src_addr = {0}; nas_src_addr.nl_family = AF_NETLINK; nas_src_addr.nl_pid = 1; nas_src_addr.nl_groups = 0; /* not in mcast groups */ - ret = bind(nas_sock_mbms_fd, (struct sockaddr *)&nas_src_addr, sizeof(nas_src_addr)); + bind(nas_sock_mbms_fd, (struct sockaddr *)&nas_src_addr, sizeof(nas_src_addr)); return 1; } -int tun_init(const char *ifprefix, int num_if, int id) +int tun_init(const char *ifname, int instance_id) { - int ret; - char ifname[64]; - - int begx = (id == 0) ? 0 : id - 1; - int endx = (id == 0) ? num_if : id; - for (int i = begx; i < endx; i++) { - sprintf(ifname, "%s%d", ifprefix, i + 1); - nas_sock_fd[i] = tun_alloc(ifname); - - if (nas_sock_fd[i] == -1) { - LOG_E(UTIL, "Error opening socket %s (%d:%s)\n", ifname, errno, strerror(errno)); - return 0; - } - - LOG_I(UTIL, "Opened socket %s with fd nas_sock_fd[%d]=%d\n", ifname, i, nas_sock_fd[i]); - ret = fcntl(nas_sock_fd[i], F_SETFL, O_NONBLOCK); - - if (ret == -1) { - LOG_E(UTIL, "Error fcntl (%d:%s)\n", errno, strerror(errno)); + nas_sock_fd[instance_id] = tun_alloc(ifname); - return 0; - } + if (nas_sock_fd[instance_id] == -1) { + LOG_E(UTIL, "Error opening socket %s (%d:%s)\n", ifname, errno, strerror(errno)); + return 0; } + LOG_I(UTIL, "Opened socket %s with fd nas_sock_fd[%d]=%d\n", ifname, instance_id, nas_sock_fd[instance_id]); return 1; } @@ -209,12 +189,8 @@ fail_interface_state: return false; } -// non blocking full configuration of the interface (address, and the two lest octets of the address) -bool tun_config(int interface_id, const char *ipv4, const char *ipv6, const char *ifpref) +bool tun_config(const char* ifname, const char *ipv4, const char *ipv6) { - char interfaceName[IFNAMSIZ]; - snprintf(interfaceName, sizeof(interfaceName), "%s%d", ifpref, interface_id); - AssertFatal(ipv4 != NULL || ipv6 != NULL, "need to have IP address, but none given\n"); int sock_fd = socket(AF_INET, SOCK_DGRAM, 0); @@ -223,13 +199,16 @@ bool tun_config(int interface_id, const char *ipv4, const char *ipv6, const char return false; } - change_interface_state(sock_fd, interfaceName, INTERFACE_DOWN); + if (!change_interface_state(sock_fd, ifname, INTERFACE_DOWN)) { + close(sock_fd); + return false; + } bool success = true; if (ipv4 != NULL) - success = setInterfaceParameter(sock_fd, interfaceName, AF_INET, ipv4, SIOCSIFADDR); + success = setInterfaceParameter(sock_fd, ifname, AF_INET, ipv4, SIOCSIFADDR); // set the machine network mask for IPv4 if (success && ipv4 != NULL) - success = setInterfaceParameter(sock_fd, interfaceName, AF_INET, "255.255.255.0", SIOCSIFNETMASK); + success = setInterfaceParameter(sock_fd, ifname, AF_INET, "255.255.255.0", SIOCSIFNETMASK); if (ipv6 != NULL) { // for setting the IPv6 address, we need an IPv6 socket. For setting IPv4, @@ -240,27 +219,25 @@ bool tun_config(int interface_id, const char *ipv4, const char *ipv6, const char LOG_E(UTIL, "Failed creating socket for interface management: %d, %s\n", errno, strerror(errno)); success = false; } - success = success && setInterfaceParameter(sock_fd, interfaceName, AF_INET6, ipv6, SIOCSIFADDR); + success = success && setInterfaceParameter(sock_fd, ifname, AF_INET6, ipv6, SIOCSIFADDR); close(sock_fd); } if (success) - success = change_interface_state(sock_fd, interfaceName, INTERFACE_UP); + success = change_interface_state(sock_fd, ifname, INTERFACE_UP); if (success) - LOG_I(OIP, "Interface %s successfully configured, IPv4 %s, IPv6 %s\n", interfaceName, ipv4, ipv6); + LOG_I(OIP, "Interface %s successfully configured, IPv4 %s, IPv6 %s\n", ifname, ipv4, ipv6); else - LOG_E(OIP, "Interface %s couldn't be configured (IPv4 %s, IPv6 %s)\n", interfaceName, ipv4, ipv6); + LOG_E(OIP, "Interface %s couldn't be configured (IPv4 %s, IPv6 %s)\n", ifname, ipv4, ipv6); close(sock_fd); return success; } -void setup_ue_ipv4_route(int interface_id, const char *ipv4, const char *ifpref) +void setup_ue_ipv4_route(const char* ifname, int instance_id, const char *ipv4) { - int table_id = interface_id - 1 + 10000; - char interfaceName[IFNAMSIZ]; - snprintf(interfaceName, sizeof(interfaceName), "%s%d", ifpref, interface_id); + int table_id = instance_id - 1 + 10000; char command_line[500]; int res = sprintf(command_line, @@ -271,7 +248,7 @@ void setup_ue_ipv4_route(int interface_id, const char *ipv4, const char *ifpref) table_id, ipv4, table_id, - interfaceName, + ifname, table_id); if (res < 0) { @@ -281,3 +258,7 @@ void setup_ue_ipv4_route(int interface_id, const char *ipv4, const char *ifpref) background_system(command_line); } +int tun_generate_ifname(char *ifname, const char *ifprefix, int instance_id) +{ + return snprintf(ifname, IFNAMSIZ, "%s%d", ifprefix, instance_id + 1); +} diff --git a/common/utils/tun_if.h b/common/utils/tun_if.h index 45ae34983f70409819562f80efd8b019a9eece41..eafc5b3350a4c3808f3b146ea15e74372859f576 100644 --- a/common/utils/tun_if.h +++ b/common/utils/tun_if.h @@ -23,28 +23,43 @@ #define TUN_IF_H_ #include <stdbool.h> +#include <net/if.h> -/* TODO: doc */ -int tun_init(const char *ifprefix, int num_if, int id); +/*! + * \brief This function generates the name of the interface based on the prefix and + * the instance id. + * + * \param[in,out] ifname name of the interface + * \param[in] ifprefix prefix of the interface + * \param[in] instance_id unique instance number + */ +int tun_generate_ifname(char *ifname, const char *ifprefix, int instance_id); -/* TODO: doc */ -int tun_init_mbms(char *ifsuffix, int id); +/*! + * \brief This function initializes the TUN interface + * \param[in] ifname name of the interface + * \param[in] instance_id unique instance number, used to save socket file descriptor + */ +int tun_init(const char *ifname, int instance_id); -/*! \fn int tun_config(char*, int, int) +/*! + * \brief This function initializes the TUN interface for MBMS + * \param[in] ifname name of the interface + */ +int tun_init_mbms(char *ifname); + +/*! * \brief This function initializes the nasmesh interface using the basic values, * basic address, network mask and broadcast address, as the default configured * ones - * \param[in] interface_id number of this interface, prepended after interface - * name + * \param[in] ifname name of the interface * \param[in] ipv4 IPv4 address of this interface as a string * \param[in] ipv6 IPv6 address of this interface as a string - * \param[in] ifprefix interface name prefix to which an interface number will - * be appended * \return true on success, otherwise false * \note * @ingroup _nas */ -bool tun_config(int interface_id, const char *ipv4, const char *ipv6, const char *ifprefix); +bool tun_config(const char* ifname, const char *ipv4, const char *ipv6); /*! * \brief Setup a IPv4 rule in table (interface_id - 1 + 10000) and route to @@ -52,12 +67,10 @@ bool tun_config(int interface_id, const char *ipv4, const char *ipv6, const char * net.ipv4.conf.all.rp_filter=2 (strict source filtering would filter out * responses of packets going out through interface to another IP address not * in same subnet). - * \param[in] interface_id number of this interface, prepended after interface - * name + * \param[in] ifname name of the interface + * \param[in] instance_id unique instance number, used to create the table * \param[in] ipv4 IPv4 address of the UE - * \param[in] ifprefix interface name prefix to which an interface number will - * be appended */ -void setup_ue_ipv4_route(int interface_id, const char *ipv4, const char *ifpref); +void setup_ue_ipv4_route(const char* ifname, int instance_id, const char *ipv4); #endif /*TUN_IF_H_*/ diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c index 3c3ef5367f1f3e3eff880ab648ebddb16eb1df57..f93044f9cde469d6425218629190762ff4cce95f 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c @@ -2172,22 +2172,35 @@ uint64_t pdcp_module_init( uint64_t pdcp_optmask, int id) { if (UE_NAS_USE_TUN) { int num_if = (NFAPI_MODE == NFAPI_UE_STUB_PNF || IS_SOFTMODEM_SIML1 || NFAPI_MODE == NFAPI_MODE_STANDALONE_PNF) ? MAX_MOBILES_PER_ENB : 1; - tun_init("oaitun_ue", num_if, id); - tun_init_mbms("oaitun_uem", id + 1); - tun_config(1, "10.0.2.2", NULL, "oaitun_uem"); + int begx = (id == 0) ? 0 : id - 1; + int endx = (id == 0) ? num_if : id; + for (int i = begx; i < endx; i++) { + char ifname[IFNAMSIZ]; + tun_generate_ifname(ifname, "oaitun_ue", i); + tun_init(ifname, i); + } + char ifname[IFNAMSIZ]; + tun_generate_ifname(ifname, "oaitun_uem", id + 1); + tun_init_mbms(ifname); + tun_config(ifname, "10.0.2.2", NULL); LOG_I(PDCP, "UE pdcp will use tun interface\n"); } else if (ENB_NAS_USE_TUN) { - tun_init("oaitun_enb", 1, 0); - tun_config(1, "10.0.1.1", NULL, "oaitun_enb"); + char ifname[IFNAMSIZ]; + tun_generate_ifname(ifname, "oaitun_enb", 0); + tun_init(ifname, 0); + tun_config(ifname, "10.0.1.1", NULL); if (pdcp_optmask & ENB_NAS_USE_TUN_W_MBMS_BIT) { - tun_init_mbms("oaitun_enm", 1); - tun_config(1, "10.0.2.1", NULL, "oaitun_enm"); + tun_generate_ifname(ifname, "oaitun_enm", 0); + tun_init_mbms(ifname); + tun_config(ifname, "10.0.2.1", NULL); LOG_I(PDCP, "ENB pdcp will use mbms tun interface\n"); } LOG_I(PDCP, "ENB pdcp will use tun interface\n"); } else if (pdcp_optmask & ENB_NAS_USE_TUN_W_MBMS_BIT) { - tun_init_mbms("oaitun_enm", 0); - tun_config(1, "10.0.2.1", NULL, "oaitun_enm"); + char ifname[IFNAMSIZ]; + tun_generate_ifname(ifname, "oaitun_enm", 0); + tun_init_mbms(ifname); + tun_config(ifname, "10.0.2.1", NULL); LOG_I(PDCP, "ENB pdcp will use mbms tun interface\n"); } diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index 7691871b33ec675bded6b4eeb82f76f5e1a13f37..54880e828a2556c03c3dee6f2c6927c920cc1f35 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -640,18 +640,28 @@ uint64_t nr_pdcp_module_init(uint64_t _pdcp_optmask, int id) int num_if = (NFAPI_MODE == NFAPI_UE_STUB_PNF || IS_SOFTMODEM_SIML1 || NFAPI_MODE == NFAPI_MODE_STANDALONE_PNF) ? MAX_MOBILES_PER_ENB : 1; - tun_init(ifprefix, num_if, id); + int begx = (id == 0) ? 0 : id - 1; + int endx = (id == 0) ? num_if : id; + for (int i = begx; i < endx; i++) { + char ifname[IFNAMSIZ]; + tun_generate_ifname(ifname, ifprefix, i); + tun_init(ifname, i); + } if (IS_SOFTMODEM_NOS1) { const char *ip = !get_softmodem_params()->nsa ? "10.0.1.2" : "10.0.1.3"; - tun_config(1, ip, NULL, ifprefix); + char ifname[IFNAMSIZ]; + tun_generate_ifname(ifname, ifprefix, id); + tun_config(ifname, ip, NULL); set_qfi_pduid(7, 10); } LOG_I(PDCP, "UE pdcp will use tun interface\n"); start_pdcp_tun_ue(); } else if (ENB_NAS_USE_TUN) { char *ifprefix = get_softmodem_params()->nsa ? "oaitun_gnb" : "oaitun_enb"; - tun_init(ifprefix, 1, id); - tun_config(1, "10.0.1.1", NULL, ifprefix); + char ifname[IFNAMSIZ]; + tun_generate_ifname(ifname, ifprefix, id); + tun_init(ifname, id); + tun_config(ifname, "10.0.1.1", NULL); LOG_I(PDCP, "ENB pdcp will use tun interface\n"); start_pdcp_tun_enb(); } diff --git a/openair2/RRC/LTE/rrc_UE.c b/openair2/RRC/LTE/rrc_UE.c index 1e125436049edc3a93c6e48eba07342ccafe784d..f7b513d2646fe0dd8affe6183edf83f60b4712f9 100644 --- a/openair2/RRC/LTE/rrc_UE.c +++ b/openair2/RRC/LTE/rrc_UE.c @@ -777,7 +777,9 @@ rrc_ue_establish_drb( "10.0.%d.%d", UE_NAS_USE_TUN ? 1 : (ip_addr_offset3 + ue_mod_idP + 1), ip_addr_offset4 + ue_mod_idP + 1); - oip_ifup = tun_config(ip_addr_offset3 + ue_mod_idP + 1, ip, NULL, "oaitun_ue"); + char ifname[IFNAMSIZ]; + tun_generate_ifname(ifname, "oaitun_ue", ip_addr_offset3 + ue_mod_idP); + oip_ifup = tun_config(ifname, ip, NULL); if (oip_ifup == 0 && (!UE_NAS_USE_TUN)) { // interface is up --> send a config the DRB LOG_I(OIP,"[UE %d] Config the ue net interface %d to send/receive pkt on DRB %ld to/from the protocol stack\n", diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index 78f05cf56a086c0bd2f1513cd09635ce87379e79..8d0fd2f8ed5042258629fa63e6f82922958d8118 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -5250,7 +5250,9 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( ctxt_pP->module_id); char ip[20]; snprintf(ip, sizeof(ip), "10.0.%d.%d", ctxt_pP->module_id + 1, ctxt_pP->module_id + 1); - oip_ifup = tun_config(ctxt_pP->module_id, ip, NULL, "oaitun_oai"); + char ifname[IFNAMSIZ]; + tun_generate_ifname(ifname, "oaitun_oai", ctxt_pP->module_id); + oip_ifup = tun_config(ifname, ip, NULL); if (oip_ifup == 0) { // interface is up --> send a config the DRB module_id_t ue_module_id; diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index d7a1c42bf34af3bad3f73c6073af5c2e41ebddde..d2764ac2e1b2719bf4afdd2fb7eabcf87ceb85c5 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -855,14 +855,18 @@ static void process_pdu_session_addr(pdu_session_establishment_accept_msg_t *msg case PDU_SESSION_TYPE_IPV4: { char ip[20]; capture_ipv4_addr(&addr[0], ip, sizeof(ip)); - tun_config(1, ip, NULL, "oaitun_ue"); - setup_ue_ipv4_route(1, ip, "oaitun_ue"); + char ifname[IFNAMSIZ]; + tun_generate_ifname(ifname, "oaitun_ue", 0); + tun_config(ifname, ip, NULL); + setup_ue_ipv4_route(ifname, 0, ip); } break; case PDU_SESSION_TYPE_IPV6: { char ipv6[40]; capture_ipv6_addr(addr, ipv6, sizeof(ipv6)); - tun_config(1, NULL, ipv6, "oaitun_ue"); + char ifname[IFNAMSIZ]; + tun_generate_ifname(ifname, "oaitun_ue", 0); + tun_config(ifname, NULL, ipv6); } break; case PDU_SESSION_TYPE_IPV4V6: { @@ -870,8 +874,10 @@ static void process_pdu_session_addr(pdu_session_establishment_accept_msg_t *msg capture_ipv6_addr(addr, ipv6, sizeof(ipv6)); char ipv4[20]; capture_ipv4_addr(&addr[IPv6_INTERFACE_ID_LENGTH], ipv4, sizeof(ipv4)); - tun_config(1, ipv4, ipv6, "oaitun_ue"); - setup_ue_ipv4_route(1, ipv4, "oaitun_ue"); + char ifname[IFNAMSIZ]; + tun_generate_ifname(ifname, "oaitun_ue", 0); + tun_config(ifname, ipv4, ipv6); + setup_ue_ipv4_route(ifname, 0, ipv4); } break; default: diff --git a/openair3/NAS/UE/ESM/esm_ebr_context.c b/openair3/NAS/UE/ESM/esm_ebr_context.c index 72b5d240e06c11a71ba6c680a75ed3e5208a1490..7a8de459e7818b4c01c16024553d4bed94cbec1d 100644 --- a/openair3/NAS/UE/ESM/esm_ebr_context.c +++ b/openair3/NAS/UE/ESM/esm_ebr_context.c @@ -207,8 +207,10 @@ int esm_ebr_context_create( char *ip_addr = pdn->ip_addr; snprintf(ip, sizeof(ip), "%d.%d.%d.%d", ip_addr[0], ip_addr[1], ip_addr[2], ip_addr[3]); const char *ifn = get_softmodem_params()->nsa ? "oaitun_nru" : "oaitun_ue"; - tun_config(1, ip, NULL, ifn); - setup_ue_ipv4_route(1, ip, ifn); + char ifname[IFNAMSIZ]; + tun_generate_ifname(ifname, ifn, 0); + tun_config(ifname, ip, NULL); + setup_ue_ipv4_route(ifname, 0, ip); } break; case NET_PDN_TYPE_IPV6: