diff --git a/ci-scripts/conf_files/nrue.band78.106prb.l2sim.conf b/ci-scripts/conf_files/nrue.band78.106prb.l2sim.conf index 0dfd31a789..4c382c4c37 100644 --- a/ci-scripts/conf_files/nrue.band78.106prb.l2sim.conf +++ b/ci-scripts/conf_files/nrue.band78.106prb.l2sim.conf @@ -12,8 +12,7 @@ uicc0 = { imsi = "208990100001100"; key = "fec86ba6eb707ed08905757b1bb44b8f"; opc= "C42449363BBAD02B66D16BC975D77CC1"; -dnn= "oai"; -nssai_sst=1; +pdu_sessions = ({ dnn = "oai"; nssai_sst = 1; }); } MACRLCs = ( diff --git a/ci-scripts/conf_files/nrue.uicc.2pdu.conf b/ci-scripts/conf_files/nrue.uicc.2pdu.conf new file mode 100644 index 0000000000..03f64f47fc --- /dev/null +++ b/ci-scripts/conf_files/nrue.uicc.2pdu.conf @@ -0,0 +1,11 @@ +uicc0 = { + imsi = "208990100001100"; + key = "fec86ba6eb707ed08905757b1bb44b8f"; + opc= "C42449363BBAD02B66D16BC975D77CC1"; + pdu_sessions = ( + { id = 1; dnn = "oai"; nssai_sst = 1; }, + { id = 2; dnn = "oai"; nssai_sst = 1; } + ) +} + +thread-pool = "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1" diff --git a/ci-scripts/conf_files/nrue.uicc.conf b/ci-scripts/conf_files/nrue.uicc.conf index 3b5deb5a4c..e9c0855d88 100644 --- a/ci-scripts/conf_files/nrue.uicc.conf +++ b/ci-scripts/conf_files/nrue.uicc.conf @@ -2,8 +2,7 @@ uicc0 = { imsi = "208990100001100"; key = "fec86ba6eb707ed08905757b1bb44b8f"; opc= "C42449363BBAD02B66D16BC975D77CC1"; - dnn= "oai"; - nssai_sst=1; + pdu_sessions = ({ dnn = "oai"; nssai_sst = 1; }); } position0 = { diff --git a/ci-scripts/conf_files/nrue.uicc.ntn-leo.conf b/ci-scripts/conf_files/nrue.uicc.ntn-leo.conf index 5072c5ea4a..8e0baab5cd 100644 --- a/ci-scripts/conf_files/nrue.uicc.ntn-leo.conf +++ b/ci-scripts/conf_files/nrue.uicc.ntn-leo.conf @@ -2,8 +2,7 @@ uicc0 = { imsi = "208990100001100"; key = "fec86ba6eb707ed08905757b1bb44b8f"; opc= "C42449363BBAD02B66D16BC975D77CC1"; - dnn= "oai"; - nssai_sst=1; + pdu_sessions = ({ dnn = "oai"; nssai_sst = 1; }); } position0 = { diff --git a/ci-scripts/conf_files/nrue.uicc.yaml b/ci-scripts/conf_files/nrue.uicc.yaml index a9ccee51f1..40d9947f88 100644 --- a/ci-scripts/conf_files/nrue.uicc.yaml +++ b/ci-scripts/conf_files/nrue.uicc.yaml @@ -2,8 +2,9 @@ uicc0: imsi: 208990100001100 key: fec86ba6eb707ed08905757b1bb44b8f opc: C42449363BBAD02B66D16BC975D77CC1 - dnn: oai - nssai_sst: 1 + pdu_sessions: + - dnn: oai + nssai_sst: 1 thread-pool: "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1" diff --git a/ci-scripts/conf_files/nrue.vrtsim.chanmod.yaml b/ci-scripts/conf_files/nrue.vrtsim.chanmod.yaml index a9488007d7..6be862e432 100644 --- a/ci-scripts/conf_files/nrue.vrtsim.chanmod.yaml +++ b/ci-scripts/conf_files/nrue.vrtsim.chanmod.yaml @@ -2,8 +2,9 @@ uicc0: imsi: 208990100001100 key: fec86ba6eb707ed08905757b1bb44b8f opc: C42449363BBAD02B66D16BC975D77CC1 - dnn: oai - nssai_sst: 1 + pdu_sessions: + - dnn: oai + nssai_sst: 1 thread-pool: "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1" diff --git a/ci-scripts/conf_files/ue.sa.conf b/ci-scripts/conf_files/ue.sa.conf index dc744fb732..d02095ac61 100644 --- a/ci-scripts/conf_files/ue.sa.conf +++ b/ci-scripts/conf_files/ue.sa.conf @@ -2,8 +2,7 @@ uicc0 = { imsi = "208970100001127"; key = "fec86ba6eb707ed08905757b1bb44b8f"; opc= "c42449363bbad02b66d16bc975d77cc1"; - dnn= "oai"; - nssai_sst=1; + pdu_sessions = ({ dnn = "oai"; nssai_sst = 1; }); } thread-pool = "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1" diff --git a/ci-scripts/conf_files/untested/episci/episci_nr-ue.nfapi.conf b/ci-scripts/conf_files/untested/episci/episci_nr-ue.nfapi.conf index fcdce84334..4603651eb0 100644 --- a/ci-scripts/conf_files/untested/episci/episci_nr-ue.nfapi.conf +++ b/ci-scripts/conf_files/untested/episci/episci_nr-ue.nfapi.conf @@ -12,9 +12,7 @@ uicc0 = { imsi = "208950000000031"; key = "0c0a34601d4f07677303652c0462535b"; opc= "63bfa50ee6523365ff14c1f45f88737d"; -dnn= "oai"; -nssai_sst=222; -nssai_sd=123; +pdu_sessions = ({ dnn = "oai"; nssai_sst = 222; nssai_sd = 123; }); } MACRLCs = ( diff --git a/ci-scripts/conf_files/untested/episci/proxy_nr-ue.nfapi.conf b/ci-scripts/conf_files/untested/episci/proxy_nr-ue.nfapi.conf index 8d6cca014f..b297e509c9 100644 --- a/ci-scripts/conf_files/untested/episci/proxy_nr-ue.nfapi.conf +++ b/ci-scripts/conf_files/untested/episci/proxy_nr-ue.nfapi.conf @@ -12,9 +12,7 @@ uicc0 = { imsi = "2089900007487"; key = "fec86ba6eb707ed08905757b1bb44b8f"; opc= "C42449363BBAD02B66D16BC975D77CC1"; -dnn= "oai"; -nssai_sst=1; -nssai_sd=1; +pdu_sessions = ({ dnn = "oai"; nssai_sst = 1; nssai_sd = 1; }); } MACRLCs = ( diff --git a/ci-scripts/yaml_files/5g_rfsimulator/README.md b/ci-scripts/yaml_files/5g_rfsimulator/README.md index 3d5d1c3583..dd114ad667 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator/README.md +++ b/ci-scripts/yaml_files/5g_rfsimulator/README.md @@ -518,8 +518,7 @@ uicc0 = { imsi = "208990100001100"; key = "fec86ba6eb707ed08905757b1bb44b8f"; opc= "C42449363BBAD02B66D16BC975D77CC1"; - dnn= "oai"; - nssai_sst=1; + pdu_sessions = ({ dnn = "oai"; nssai_sst = 1; }); } ``` 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 12ae3d41c6..e2cb9d6c7c 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_e1/docker-compose.yaml @@ -338,7 +338,7 @@ services: environment: USE_ADDITIONAL_OPTIONS: --rfsim --log_config.global_log_options level,nocolor,time -r 106 --numerology 1 -C 3619200000 - --uicc0.imsi 208990100001101 --uicc0.nssai_sst 2 + --uicc0.imsi 208990100001101 --uicc0.pdu_sessions.[0].nssai_sst 2 --rfsimulator.[0].serveraddr 192.168.78.3 depends_on: - oai-du2 @@ -368,7 +368,7 @@ services: environment: USE_ADDITIONAL_OPTIONS: --rfsim --log_config.global_log_options level,nocolor,time -r 106 --numerology 1 -C 3619200000 - --uicc0.imsi 208990100001102 --uicc0.nssai_sst 3 + --uicc0.imsi 208990100001102 --uicc0.pdu_sessions.[0].nssai_sst 3 --rfsimulator.[0].serveraddr 192.168.78.4 ASAN_OPTIONS: detect_leaks=0 depends_on: diff --git a/ci-scripts/yaml_files/5g_rfsimulator_multiue/nrue.uicc.conf b/ci-scripts/yaml_files/5g_rfsimulator_multiue/nrue.uicc.conf index f0ac4dfff3..f346c1a44d 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_multiue/nrue.uicc.conf +++ b/ci-scripts/yaml_files/5g_rfsimulator_multiue/nrue.uicc.conf @@ -2,71 +2,61 @@ uicc0 = { imsi = "208990100001100"; key = "fec86ba6eb707ed08905757b1bb44b8f"; opc= "C42449363BBAD02B66D16BC975D77CC1"; - dnn= "oai"; - nssai_sst=1; + pdu_sessions = ({ dnn = "oai"; nssai_sst = 1; }); } uicc1 = { imsi = "208990100001101"; key = "fec86ba6eb707ed08905757b1bb44b8f"; opc= "C42449363BBAD02B66D16BC975D77CC1"; - dnn= "oai"; - nssai_sst=1; + pdu_sessions = ({ dnn = "oai"; nssai_sst = 1; }); } uicc2 = { imsi = "208990100001102"; key = "fec86ba6eb707ed08905757b1bb44b8f"; opc= "C42449363BBAD02B66D16BC975D77CC1"; - dnn= "oai"; - nssai_sst=1; + pdu_sessions = ({ dnn = "oai"; nssai_sst = 1; }); } uicc3 = { imsi = "208990100001103"; key = "fec86ba6eb707ed08905757b1bb44b8f"; opc= "C42449363BBAD02B66D16BC975D77CC1"; - dnn= "oai"; - nssai_sst=1; + pdu_sessions = ({ dnn = "oai"; nssai_sst = 1; }); } uicc4 = { imsi = "208990100001104"; key = "fec86ba6eb707ed08905757b1bb44b8f"; opc= "C42449363BBAD02B66D16BC975D77CC1"; - dnn= "oai"; - nssai_sst=1; + pdu_sessions = ({ dnn = "oai"; nssai_sst = 1; }); } uicc5 = { imsi = "208990100001105"; key = "fec86ba6eb707ed08905757b1bb44b8f"; opc= "C42449363BBAD02B66D16BC975D77CC1"; - dnn= "oai"; - nssai_sst=1; + pdu_sessions = ({ dnn = "oai"; nssai_sst = 1; }); } uicc6 = { imsi = "208990100001106"; key = "fec86ba6eb707ed08905757b1bb44b8f"; opc= "C42449363BBAD02B66D16BC975D77CC1"; - dnn= "oai"; - nssai_sst=1; + pdu_sessions = ({ dnn = "oai"; nssai_sst = 1; }); } uicc7 = { imsi = "208990100001107"; key = "fec86ba6eb707ed08905757b1bb44b8f"; opc= "C42449363BBAD02B66D16BC975D77CC1"; - dnn= "oai"; - nssai_sst=1; + pdu_sessions = ({ dnn = "oai"; nssai_sst = 1; }); } uicc8 = { imsi = "208990100001108"; key = "fec86ba6eb707ed08905757b1bb44b8f"; opc= "C42449363BBAD02B66D16BC975D77CC1"; - dnn= "oai"; - nssai_sst=1; + pdu_sessions = ({ dnn = "oai"; nssai_sst = 1; }); } uicc9 = { imsi = "208990100001109"; key = "fec86ba6eb707ed08905757b1bb44b8f"; opc= "C42449363BBAD02B66D16BC975D77CC1"; - dnn= "oai"; - nssai_sst=1; + pdu_sessions = ({ dnn = "oai"; nssai_sst = 1; }); } thread-pool: "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1" diff --git a/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml index 3ceddd79b9..0a02976868 100644 --- a/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml +++ b/ci-scripts/yaml_files/5g_rfsimulator_u0_25prb/docker-compose.yaml @@ -149,7 +149,7 @@ services: - NET_RAW # for ping environment: USE_ADDITIONAL_OPTIONS: --rfsim -r 25 --numerology 0 --uicc0.imsi 208990100001100 --band 66 -C 2152680000 --CO -400000000 --ssb 48 - --rfsimulator.[0].serveraddr 192.168.71.141 --extra-pdu-id 2 --log_config.global_log_options level,nocolor,time + --rfsimulator.[0].serveraddr 192.168.71.141 --log_config.global_log_options level,nocolor,time --telnetsrv --telnetsrv.shrmod ciUE --telnetsrv.listenaddr 192.168.71.150 --telnetsrv.listenport 8091 ASAN_OPTIONS: detect_leaks=0:detect_odr_violation=0 depends_on: @@ -160,7 +160,7 @@ services: devices: - /dev/net/tun:/dev/net/tun volumes: - - ../../conf_files/nrue.uicc.conf:/opt/oai-nr-ue/etc/nr-ue.conf + - ../../conf_files/nrue.uicc.2pdu.conf:/opt/oai-nr-ue/etc/nr-ue.conf healthcheck: test: /bin/bash -c "pgrep nr-uesoftmodem" start_period: 10s diff --git a/common/config/config_load_configmodule.c b/common/config/config_load_configmodule.c index 5d8bb2cfcc..da589d3759 100644 --- a/common/config/config_load_configmodule.c +++ b/common/config/config_load_configmodule.c @@ -144,7 +144,7 @@ int config_cmdlineonly_getlist(configmodule_interface_t *cfg, paramlist_def_t *ParamList, paramdef_t *params, int numparams, - char *prefix) + const char *prefix) { ParamList->numelt = 0; return 0; diff --git a/common/config/config_load_configmodule.h b/common/config/config_load_configmodule.h index 2c45f788d4..93753ef358 100644 --- a/common/config/config_load_configmodule.h +++ b/common/config/config_load_configmodule.h @@ -61,7 +61,7 @@ struct configmodule_interface; typedef int (*configmodule_getfunc_t)(struct configmodule_interface *, paramdef_t *, int numparams, const char *prefix); typedef int ( - *configmodule_getlistfunc_t)(struct configmodule_interface *, paramlist_def_t *, paramdef_t *, int numparams, char *prefix); + *configmodule_getlistfunc_t)(struct configmodule_interface *, paramlist_def_t *, paramdef_t *, int numparams, const char *prefix); typedef int (*configmodule_setfunc_t)(paramdef_t *cfgoptions, int numoptions, const char *prefix); typedef void (*configmodule_endfunc_t)(struct configmodule_interface *cfg); diff --git a/common/config/config_userapi.c b/common/config/config_userapi.c index 7c92a611de..271b9ba0a9 100644 --- a/common/config/config_userapi.c +++ b/common/config/config_userapi.c @@ -142,7 +142,7 @@ int config_get(configmodule_interface_t *cfgif, paramdef_t *params, int numparam return ret; } -int config_getlist(configmodule_interface_t *cfg, paramlist_def_t *ParamList, paramdef_t *params, int numparams, char *prefix) +int config_getlist(configmodule_interface_t *cfg, paramlist_def_t *ParamList, paramdef_t *params, int numparams, const char *prefix) { if (CONFIG_ISFLAGSET(CONFIG_ABORT)) { fprintf(stderr,"[CONFIG] config_get skipped, config module not properly initialized\n"); diff --git a/common/config/config_userapi.h b/common/config/config_userapi.h index 3aeeeec3c1..57d738ae83 100644 --- a/common/config/config_userapi.h +++ b/common/config/config_userapi.h @@ -62,7 +62,7 @@ int config_assign_ipv4addr(configmodule_interface_t *cfg, paramdef_t *cfgoptions #define CONFIG_CHECKALLSECTIONS "ALLSECTIONS" int config_check_unknown_cmdlineopt(configmodule_interface_t *cfg, char *prefix); int config_get(configmodule_interface_t *cfg, paramdef_t *params, int numparams, const char *prefix); -int config_getlist(configmodule_interface_t *cfg, paramlist_def_t *ParamList, paramdef_t *params, int numparams, char *prefix); +int config_getlist(configmodule_interface_t *cfg, paramlist_def_t *ParamList, paramdef_t *params, int numparams, const char *prefix); /* apis to set some of the paramdef_t fields before using the get/getlist api's */ void config_set_checkfunctions(paramdef_t *params, checkedparam_t *checkfunctions, int numparams); diff --git a/common/platform_constants.h b/common/platform_constants.h index 2faadc3dcd..f76025c06a 100644 --- a/common/platform_constants.h +++ b/common/platform_constants.h @@ -100,5 +100,8 @@ // SDAP #define MAX_QOS_FLOWS 64 +// SDAP/5G NAS NOS1 +#define DEFAULT_NOS1_PDU_ID 10 + #define SPEED_OF_LIGHT 299792458 // in m/s #endif /* __PLATFORM_CONSTANTS_H__ */ diff --git a/common/utils/CMakeLists.txt b/common/utils/CMakeLists.txt index dc997db6c7..395139132d 100644 --- a/common/utils/CMakeLists.txt +++ b/common/utils/CMakeLists.txt @@ -14,7 +14,7 @@ add_subdirectory(nr) add_subdirectory(LOG) add_subdirectory(threadPool) add_subdirectory(time_manager) -add_library(utils utils.c system.c time_meas.c time_stat.c tun_if.c) +add_library(utils utils.c system.c time_meas.c time_stat.c tuntap_if.c) target_include_directories(utils PUBLIC .) target_link_libraries(utils PRIVATE ${T_LIB}) if (ENABLE_TESTS) diff --git a/common/utils/telnetsrv/telnetsrv_ciUE.c b/common/utils/telnetsrv/telnetsrv_ciUE.c index cc580b1a83..457ba77b4b 100644 --- a/common/utils/telnetsrv/telnetsrv_ciUE.c +++ b/common/utils/telnetsrv/telnetsrv_ciUE.c @@ -172,7 +172,11 @@ static int add_pdu_session(char *buf, int debug, telnet_printfunc_t prnt) if (!nas) ERROR_MSG_RET("No NAS context found for UE_ID %d\n", ue_id); - request_pdusession(nas, pdusession_id); + DevAssert(nas->uicc); + nssai_t nssai = {nas->uicc->nssai_sst, nas->uicc->nssai_sd}; + pdu_session_config_t c = {pdusession_id, 1 /* = PDU_SESSION_TYPE_IPV4 */, nssai, nas->uicc->dnnStr}; + nas->uicc->pdu_sessions[nas->uicc->n_pdu_sessions++] = c; + request_pdusession(nas, &c); prnt("Triggered PDU session request for UE %d with ID %d\n", ue_id, pdusession_id); return 0; } diff --git a/common/utils/tun_if.c b/common/utils/tuntap_if.c similarity index 73% rename from common/utils/tun_if.c rename to common/utils/tuntap_if.c index f74ab3c7f2..b4722d69f1 100644 --- a/common/utils/tun_if.c +++ b/common/utils/tuntap_if.c @@ -27,10 +27,9 @@ #include #include #include -#include #include -#include "tun_if.h" +#include "tuntap_if.h" #include "common/platform_constants.h" #include "common/utils/LOG/log.h" #include "common/utils/system.h" @@ -38,7 +37,7 @@ int nas_sock_fd[MAX_MOBILES_PER_ENB * 2]; // Allocated for both LTE UE and NR UE. int nas_sock_mbms_fd; -int tun_alloc(const char *dev) +int tuntap_alloc(int flag, const char *dev) { struct ifreq ifr; int fd, err; @@ -54,7 +53,8 @@ int tun_alloc(const char *dev) * * IFF_NO_PI - Do not provide packet information */ - ifr.ifr_flags = IFF_TUN | IFF_NO_PI; + DevAssert(flag == IFF_TUN || flag == IFF_TAP); + ifr.ifr_flags = flag | IFF_NO_PI; strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name) - 1); if ((err = ioctl(fd, TUNSETIFF, (void *)&ifr)) < 0) { close(fd); @@ -76,7 +76,7 @@ int tun_alloc(const char *dev) int tun_init_mbms(char *ifname) { - nas_sock_mbms_fd = tun_alloc(ifname); + nas_sock_mbms_fd = tuntap_alloc(IFF_TUN, ifname); if (nas_sock_mbms_fd == -1) { LOG_E(UTIL, "Error opening mbms socket %s (%d:%s)\n", ifname, errno, strerror(errno)); @@ -96,7 +96,7 @@ int tun_init_mbms(char *ifname) int tun_init(const char *ifname, int instance_id) { - nas_sock_fd[instance_id] = tun_alloc(ifname); + nas_sock_fd[instance_id] = tuntap_alloc(IFF_TUN, ifname); if (nas_sock_fd[instance_id] == -1) { LOG_E(UTIL, "Error opening socket %s (%d:%s)\n", ifname, errno, strerror(errno)); @@ -158,42 +158,47 @@ static bool setInterfaceParameter(int sock_fd, const char *ifn, int af, const ch } -typedef enum { INTERFACE_DOWN, INTERFACE_UP } if_action_t; /* -* \brief bring interface up (up != 0) or down (up == 0) +* \brief Get an interface's flags. +* \param[in] sock_fd socket to use for getting the flags +* \param[in] ifn the interface name for which to get flags +* \param[out] flags the flags of the interface +* \return true on success, false otherwise */ -static bool change_interface_state(int sock_fd, const char *ifn, if_action_t if_action) +static bool get_if_flags(int sock_fd, const char *ifn, short *flags) { - const char *action = if_action == INTERFACE_DOWN ? "DOWN" : "UP"; - struct ifreq ifr = {0}; strncpy(ifr.ifr_name, ifn, sizeof(ifr.ifr_name) - 1); /* get flags of this interface: see netdevice(7) */ - bool success = ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t)&ifr) == 0; - if (!success && if_action == INTERFACE_DOWN && errno == ENODEV) { - LOG_W(OIP, "trying to remove non-existant device %s\n", ifn); - return true; + int success = ioctl(sock_fd, SIOCGIFFLAGS, (caddr_t)&ifr) == 0; + if (!success) { + LOG_W(OIP, "On interface %s: ioctl() failed: %d, %s\n", ifn, errno, strerror(errno)); + return false; } - LOG_D(OIP, "Got flags for %s: 0x%x (action: %s)\n", ifn, ifr.ifr_flags, action); - - if (if_action == INTERFACE_UP) { - ifr.ifr_flags |= IFF_UP | IFF_NOARP | IFF_POINTOPOINT; - ifr.ifr_flags &= ~IFF_MULTICAST; - } else { - ifr.ifr_flags &= ~IFF_UP; - } - - success = ioctl(sock_fd, SIOCSIFFLAGS, (caddr_t)&ifr) == 0; - if (!success) - goto fail_interface_state; - LOG_D(OIP, "Interface %s successfully set %s\n", ifn, action); - + *flags = ifr.ifr_flags; return true; +} -fail_interface_state: - LOG_E(OIP, "Bringing interface %s for %s: ioctl call failed: %d, %s\n", action, ifn, errno, strerror(errno)); - return false; +/* + * \brief Set an interface's flags. +* \param[in] sock_fd socket to use for setting the flags +* \param[in] ifn the interface name for which to set flags +* \param[in] flags the flags to set for the interface +* \return true on success, false otherwise + */ +static bool set_if_flags(int sock_fd, const char *ifn, short flags) +{ + struct ifreq ifr = {0}; + strncpy(ifr.ifr_name, ifn, sizeof(ifr.ifr_name) - 1); + ifr.ifr_flags = flags; + + int success = ioctl(sock_fd, SIOCSIFFLAGS, (caddr_t)&ifr) == 0; + if (!success) { + LOG_W(OIP, "On interface %s: ioctl() failed: %d, %s\n", ifn, errno, strerror(errno)); + return false; + } + return true; } @@ -227,11 +232,13 @@ bool tun_config(const char* ifname, const char *ipv4, const char *ipv6) close(sock_fd); } + // if successfully set IP addresses: set iterface up, disable ARP, no + // multicast, point-to-point if (success) - success = change_interface_state(sock_fd, ifname, INTERFACE_UP); + success = set_if_flags(sock_fd, ifname, (IFF_UP | IFF_NOARP | IFF_POINTOPOINT) & ~IFF_MULTICAST); if (success) - LOG_I(OIP, "Interface %s successfully configured, IPv4 %s, IPv6 %s\n", ifname, ipv4, ipv6); + LOG_A(OIP, "TUN 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", ifname, ipv4, ipv6); @@ -239,6 +246,25 @@ bool tun_config(const char* ifname, const char *ipv4, const char *ipv6) return success; } +bool tap_config(const char* ifname) +{ + int sock_fd = socket(AF_INET, SOCK_DGRAM, 0); + if (sock_fd < 0) { + LOG_E(UTIL, "Failed creating socket for interface management: %d, %s\n", errno, strerror(errno)); + return false; + } + + bool success = set_if_flags(sock_fd, ifname, IFF_UP); + + if (success) + LOG_A(OIP, "TAP interface %s successfully configured\n", ifname); + else + LOG_E(OIP, "Tap interface %s couldn't be configured\n", ifname); + + close(sock_fd); + return success; +} + void setup_ue_ipv4_route(const char* ifname, int instance_id, const char *ipv4) { int table_id = instance_id - 1 + 10000; @@ -267,14 +293,16 @@ int tun_generate_ifname(char *ifname, const char *ifprefix, int instance_id) return snprintf(ifname, IFNAMSIZ, "%s%d", ifprefix, instance_id + 1); } -int tun_generate_ue_ifname(char *ifname, int instance_id, int pdu_session_id) +int tuntap_generate_ue_ifname(char *ifname, int flag, int instance_id, int pdu_session_id) { + DevAssert(flag == IFF_TUN || flag == IFF_TAP); char pdu_session_string[10]; snprintf(pdu_session_string, sizeof(pdu_session_string), "p%d", pdu_session_id); - return snprintf(ifname, IFNAMSIZ, "%s%d%s", "oaitun_ue", instance_id + 1, pdu_session_id == -1 ? "" : pdu_session_string); + const char *basename = flag == IFF_TUN ? "oaitun_ue" : "oaitap_ue"; + return snprintf(ifname, IFNAMSIZ, "%s%d%s", basename, instance_id + 1, pdu_session_id == -1 ? "" : pdu_session_string); } -void tun_destroy(const char *dev) +void tuntap_destroy(const char *dev) { // Use a new socket for ioctl operations int fd = socket(AF_INET, SOCK_DGRAM, 0); @@ -283,11 +311,12 @@ void tun_destroy(const char *dev) return; } - bool success = change_interface_state(fd, dev, INTERFACE_DOWN); + // interface not up => down + short flags; + bool success = get_if_flags(fd, dev, &flags); + success = success && set_if_flags(fd, dev, flags & ~IFF_UP); if (success) { LOG_I(UTIL, "Interface %s is now down.\n", dev); - } else { - LOG_E(UTIL, "Could not bring interface %s down.\n", dev); - } + } // no else: get_if_flags()/set_if_flags() should have printed error close(fd); } diff --git a/common/utils/tun_if.h b/common/utils/tuntap_if.h similarity index 73% rename from common/utils/tun_if.h rename to common/utils/tuntap_if.h index 8e1463624f..152cc5064f 100644 --- a/common/utils/tun_if.h +++ b/common/utils/tuntap_if.h @@ -24,6 +24,7 @@ #include #include +#include /*! * \brief This function generates the name of the interface based on the prefix and @@ -34,7 +35,17 @@ * \param[in] instance_id unique instance number */ int tun_generate_ifname(char *ifname, const char *ifprefix, int instance_id); -int tun_generate_ue_ifname(char *ifname, int instance_id, int pdu_session_id); + +/*! + * \brief This function generates the name of the interface based on the prefix and + * the instance id for a UE. + * + * \param[in,out] ifname name of the interface + * \param[in] flag IFF_TUN (for TUN device) or IFF_TAP (for TAP device) + * \param[in] ifprefix prefix of the interface + * \param[in] instance_id unique instance number + */ +int tuntap_generate_ue_ifname(char *ifname, int flag, int instance_id, int pdu_session_id); /*! * \brief This function initializes the TUN interface @@ -50,9 +61,8 @@ int tun_init(const char *ifname, int instance_id); 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 + * \brief Initializes the TUN interface with an IPv4 or IPv6 address and + * activates the interface. * \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 @@ -62,6 +72,15 @@ int tun_init_mbms(char *ifname); */ bool tun_config(const char* ifname, const char *ipv4, const char *ipv6); +/*! + * \brief Initializes and activates the TAP interface. + * \param[in] ifname name of the interface + * \return true on success, otherwise false + * \note + * @ingroup _nas + */ +bool tap_config(const char* ifname); + /*! * \brief Setup a IPv4 rule in table (interface_id - 1 + 10000) and route to * force packets coming into interface back through it, and workaround @@ -75,16 +94,17 @@ bool tun_config(const char* ifname, const char *ipv4, const char *ipv6); void setup_ue_ipv4_route(const char* ifname, int instance_id, const char *ipv4); /*! - * \brief This function allocates a TUN interface + * \brief This function allocates a TUN or TAP interface + * \param[in] flag IFF_TUN (for TUN device) or IFF_TAP (for TAP device) * \param[in] dev name of the interface * \return file descriptor of the allocated interface */ -int tun_alloc(const char *dev); +int tuntap_alloc(int flag, const char *dev); /*! - * \brief This function destroys the TUN interface + * \brief This function destroys the TUN or TAP interface * \param[in] dev name of the interface */ -void tun_destroy(const char *dev); +void tuntap_destroy(const char *dev); #endif /*TUN_IF_H_*/ diff --git a/doc/Doxyfile b/doc/Doxyfile index 39c7983e72..20202b3c00 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -866,8 +866,8 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../common/config/config_cmdline.c \ @CMAKE_CURRENT_SOURCE_DIR@/../common/utils/time_meas.c \ @CMAKE_CURRENT_SOURCE_DIR@/../common/utils/time_meas.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../common/utils/tun_if.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../common/utils/tun_if.c \ +@CMAKE_CURRENT_SOURCE_DIR@/../common/utils/tuntap_if.h \ +@CMAKE_CURRENT_SOURCE_DIR@/../common/utils/tuntap_if.c \ @CMAKE_CURRENT_SOURCE_DIR@/../common/utils/utils.c \ @CMAKE_CURRENT_SOURCE_DIR@/../common/utils/oai_asn1.h \ @CMAKE_CURRENT_SOURCE_DIR@/../common/utils/system.h \ diff --git a/doc/NR_SA_Tutorial_OAI_nrUE.md b/doc/NR_SA_Tutorial_OAI_nrUE.md index 7a16897abf..4b0d8be96d 100644 --- a/doc/NR_SA_Tutorial_OAI_nrUE.md +++ b/doc/NR_SA_Tutorial_OAI_nrUE.md @@ -173,8 +173,7 @@ uicc0 = { imsi = "001010000000001"; key = "fec86ba6eb707ed08905757b1bb44b8f"; opc = "C42449363BBAD02B66D16BC975D77CC1"; - dnn = "oai"; - nssai_sst = 1; + pdu_sessions = ({ dnn = "oai"; nssai_sst = 1; }); } ``` @@ -183,8 +182,23 @@ uicc0 = { | **IMSI** | Unique identifier for the UE within the mobile network. Used by the network to identify the UE during authentication. It ensures that the UE is correctly identified by the network. | 001010000000001 | | **key** | Cryptographic key shared between the UE and the network, used for encryption during the authentication process. | `fec86ba6eb707ed08905757b1bb44b8f` | | **OPC** | Operator key for the Milenage Authentication and Key Agreement algorithm used for encryption during the authentication process. | Ensures secure communication between the UE and the network by matching the encryption keys. | `C42449363BBAD02B66D16BC975D77CC1` | -| **DNN** | Specifies the name of the data network the UE wishes to connect to, similar to an APN in 4G networks. | `oai` | -| **NSSAI** | Allows the UE to select the appropriate network slice, which provides different QoS. | `1` | +| **DNN** | _Deprecated_: Specifies the name of the data network the UE wishes to connect to, similar to an APN in 4G networks. | `oai` | +| **NSSAI** | _Deprecated_: Allows the UE to select the appropriate network slice, which provides different QoS. | `1` | +| **pdu_sessions** | list of PDU sessions to request | empty array (no PDU session) | + +Note that DNN and NSSAI parameters are deprecated, and `pdu_sessions` should be +used. If the `pdu_sessions` array is present, DNN and NSSAI are ignored. + +Each element within the `pdu_sessions` array takes the following parameters. +Multiple PDU sessions can be requested. + +| **Parameter** | **Description** | **Default Value** | +|---------------|-----------------|-------------------| +| `id` | ID of the PDU session to request | index of the current element (1..16) | +| `type` | Type of the PDU session to request (allowed: `IPv4`, `IPv6`, `IPv4v6`, `Ethernet` | `IPv4` | +| `dnn` | Specifies the name of the data network the UE wishes to connect to | `oai` | +| `nssai_sst` | Slice Service Type to request (1=eMBB, 2=URLLC, 3=mMTC) | `1` | +| `nssai_sd` | Slice Differentiator to request | `0xffffff` (meaning "no SD") | The UE configuration must match the one of the network's AMF. The nrUE can connect by default to OAI CN5G with no need to provide the configuration file. diff --git a/docker/Dockerfile.nrUE.ubuntu b/docker/Dockerfile.nrUE.ubuntu index 806e2b635f..7c8b15d013 100644 --- a/docker/Dockerfile.nrUE.ubuntu +++ b/docker/Dockerfile.nrUE.ubuntu @@ -39,6 +39,7 @@ ENV TZ=Europe/Paris RUN apt-get update && \ apt-get upgrade --yes && \ apt-get install --yes \ + arping \ software-properties-common \ procps \ libsctp1 \ diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 71c0f8f996..a1dcaed52c 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -168,10 +168,8 @@ static void get_options(configmodule_interface_t *cfg) config_get(cfg, cmdline_params, numparams, NULL); if (nrUE_params.vcdflag > 0) ouput_vcd = 1; - AssertFatal(nrUE_params.extra_pdu_id != get_softmodem_params()->default_pdu_session_id, - "Default PDU ID (%d) and Extra PDU ID (%d) must be different!\n", - get_softmodem_params()->default_pdu_session_id, - nrUE_params.extra_pdu_id); + AssertFatal(nrUE_params.extra_pdu_id == -1, + "Add additional PDU sessions in uicc.pdu_sessions array instead\n"); } // set PHY vars from command line diff --git a/executables/softmodem-common.c b/executables/softmodem-common.c index 09fced4aa3..558fd4968b 100644 --- a/executables/softmodem-common.c +++ b/executables/softmodem-common.c @@ -156,6 +156,10 @@ void get_common_options(configmodule_interface_t *cfg) nfapi_setmode(nfapi_mode); if (stats_disabled) IS_SOFTMODEM_NOSTATS = true; + + // To be removed in a future release (after 1 month) + AssertFatal(get_softmodem_params()->default_pdu_session_id == -1, + "Use uicc0.pdu_sessions.[0].id to change the requested PDU session ID (is %d)\n", get_softmodem_params()->default_pdu_session_id); } void softmodem_verify_mode(const softmodem_params_t *p) diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index fcffabcb86..3a793a89d0 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -180,7 +180,7 @@ extern int usrp_tx_thread; {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, .iptr=&softmodem_params.threequarter_fs, .defintval=0, TYPE_INT, 0}, \ {"imscope" , CONFIG_HLP_IMSCOPE, PARAMFLAG_BOOL, .uptr=&enable_imscope, .defintval=0, TYPE_UINT, 0}, \ {"imscope-record" , CONFIG_HLP_IMSCOPE_RECORD,PARAMFLAG_BOOL, .uptr=&enable_imscope_record, .defintval=0, TYPE_UINT, 0}, \ - {"default-pdu-id", NULL, 0, .iptr=&DEFAULT_PDU_ID, .defintval=10, TYPE_INT, 0}, \ + {"default-pdu-id", NULL, 0, .iptr=&DEFAULT_PDU_ID, .defintval=-1, TYPE_INT, 0}, \ } // clang-format on diff --git a/openair2/COMMON/as_message.h b/openair2/COMMON/as_message.h index a134c1b47c..d82d1ce53f 100644 --- a/openair2/COMMON/as_message.h +++ b/openair2/COMMON/as_message.h @@ -474,6 +474,7 @@ typedef struct nas_pdu_session_req_s { int pdusession_type; int sst; int sd; + char dnn[103]; /* 24.501 §9.11.2.1A: max length 102 + 0-byte */ } nas_pdu_session_req_t; /* diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c index 884c5f5621..03b8ecc2d3 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c @@ -49,7 +49,7 @@ #include "common/ngran_types.h" #include "common/openairinterface5g_limits.h" #include "executables/lte-softmodem.h" -#include "common/utils/tun_if.h" +#include "common/utils/tuntap_if.h" #include "intertask_interface.h" #include "openair3/S1AP/s1ap_eNB.h" #include diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index 3fd4c4bdd4..88f9fec043 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -46,7 +46,7 @@ #include "common/platform_constants.h" #include "common/ran_context.h" #include "common/utils/T/T.h" -#include "common/utils/tun_if.h" +#include "common/utils/tuntap_if.h" #include "cuup_cucp_if.h" #include "executables/lte-softmodem.h" #include "executables/softmodem-common.h" @@ -405,7 +405,7 @@ void nr_pdcp_layer_init(void) #include "nfapi/oai_integration/vendor_ext.h" #include "executables/lte-softmodem.h" -#include "common/utils/tun_if.h" +#include "common/utils/tuntap_if.h" #include "openair2/SDAP/nr_sdap/nr_sdap.h" static void deliver_sdu_drb(void *_ue, nr_pdcp_entity_t *entity, diff --git a/openair2/RRC/LTE/rrc_UE.c b/openair2/RRC/LTE/rrc_UE.c index 70692bfaa9..428e59ca5c 100644 --- a/openair2/RRC/LTE/rrc_UE.c +++ b/openair2/RRC/LTE/rrc_UE.c @@ -64,7 +64,7 @@ #include "LTE_UECapabilityEnquiry.h" #include "LTE_UE-CapabilityRequest.h" -#include "common/utils/tun_if.h" +#include "common/utils/tuntap_if.h" #if ENABLE_RAL #include "rrc_UE_ral.h" #endif diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index 4ddd7fc625..36d1a72653 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -79,7 +79,7 @@ #include "T.h" #include "LTE_MeasResults.h" -#include "common/utils/tun_if.h" +#include "common/utils/tuntap_if.h" #include "rrc_eNB_S1AP.h" #include "rrc_eNB_GTPV1U.h" diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index 3e3c462145..8c24b8aedd 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -201,7 +201,7 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m, sctp_ byte_array_t cgci = {0}; if (get_softmodem_params()->phy_test == 1 || get_softmodem_params()->do_ra == 1) { DevAssert(m == NULL); - UE->rb_config = get_default_rbconfig(10 /* EPS bearer ID */, 1 /* drb ID */, NR_CipheringAlgorithm_nea0, NR_SecurityConfig__keyToUse_master, &rrc->pdcp_config); + UE->rb_config = get_default_rbconfig(DEFAULT_NOS1_PDU_ID, 1 /* drb ID */, NR_CipheringAlgorithm_nea0, NR_SecurityConfig__keyToUse_master, &rrc->pdcp_config); int len = cg_config_info_from_ue_cap_file(sizeof tmp, tmp); DevAssert(len > 0); cgci = create_byte_array(len, tmp); diff --git a/openair2/SDAP/nr_sdap/nr_sdap.c b/openair2/SDAP/nr_sdap/nr_sdap.c index 1aec02814e..29e5dc93db 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap.c +++ b/openair2/SDAP/nr_sdap/nr_sdap.c @@ -29,7 +29,7 @@ #include "common/utils/LOG/log.h" #include "errno.h" #include "rlc.h" -#include "tun_if.h" +#include "tuntap_if.h" #include "system.h" static void reblock_tun_socket(int fd) @@ -157,25 +157,27 @@ static void *sdap_tun_read_thread(void *arg) return NULL; } -void start_sdap_tun_gnb_first_ue_default_pdu_session(ue_id_t ue_id) +void start_sdap_tun_gnb_first_ue_default_pdu_session(ue_id_t ue_id, int pdu_session_id) { - nr_sdap_entity_t *entity = nr_sdap_get_entity(ue_id, get_softmodem_params()->default_pdu_session_id); + nr_sdap_entity_t *entity = nr_sdap_get_entity(ue_id, pdu_session_id); DevAssert(entity != NULL); DevAssert(entity->is_gnb); char *ifprefix = get_softmodem_params()->nsa ? "oaitun_gnb" : "oaitun_enb"; char ifname[IFNAMSIZ]; tun_generate_ifname(ifname, ifprefix, ue_id - 1); - entity->pdusession_sock = tun_alloc(ifname); + entity->pdusession_sock = tuntap_alloc(IFF_TUN, ifname); + entity->pdusession_if_name = strdup(ifname); tun_config(ifname, "10.0.1.1", NULL); threadCreate(&entity->pdusession_thread, sdap_tun_read_thread, entity, "gnb_tun_read_thread", -1, OAI_PRIORITY_RT_LOW); } -void start_sdap_tun_ue(ue_id_t ue_id, int pdu_session_id, int sock) +static void start_sdap_tun_ue(ue_id_t ue_id, int pdu_session_id, int sock, const char *ifname) { nr_sdap_entity_t *entity = nr_sdap_get_entity(ue_id, pdu_session_id); DevAssert(entity != NULL); DevAssert(!entity->is_gnb); entity->pdusession_sock = sock; + entity->pdusession_if_name = strdup(ifname); entity->stop_thread = false; char thread_name[64]; snprintf(thread_name, sizeof(thread_name), "ue_tun_read_%ld_p%d", ue_id, pdu_session_id); @@ -183,22 +185,32 @@ void start_sdap_tun_ue(ue_id_t ue_id, int pdu_session_id, int sock) } -void create_ue_ip_if(const char *ipv4, const char *ipv6, int ue_id, int pdu_session_id) +void create_ue_ip_if(const char *ipv4, const char *ipv6, int ue_id, int pdu_session_id, bool is_default) { - int default_pdu = get_softmodem_params()->default_pdu_session_id; char ifname[IFNAMSIZ]; - tun_generate_ue_ifname(ifname, ue_id, pdu_session_id != default_pdu ? pdu_session_id : -1); - const int sock = tun_alloc(ifname); + tuntap_generate_ue_ifname(ifname, IFF_TUN, ue_id, is_default ? -1 : pdu_session_id); + const int sock = tuntap_alloc(IFF_TUN, ifname); tun_config(ifname, ipv4, ipv6); if (ipv4) { setup_ue_ipv4_route(ifname, ue_id, ipv4); } - start_sdap_tun_ue(ue_id, pdu_session_id, sock); // interface name suffix is ue_id+1 + start_sdap_tun_ue(ue_id, pdu_session_id, sock, ifname); // interface name suffix is ue_id+1 +} + +void create_ue_eth_if(int ue_id, int pdu_session_id, bool is_default) +{ + char ifname[IFNAMSIZ]; + tuntap_generate_ue_ifname(ifname, IFF_TAP, ue_id, is_default ? -1 : pdu_session_id); + const int sock = tuntap_alloc(IFF_TAP, ifname); + tap_config(ifname); // brings the interface up + start_sdap_tun_ue(ue_id, pdu_session_id, sock, ifname); } void remove_ip_if(nr_sdap_entity_t *entity) { DevAssert(entity != NULL); + DevAssert(entity->pdusession_if_name != NULL); + // Stop the read thread entity->stop_thread = true; @@ -208,13 +220,7 @@ void remove_ip_if(nr_sdap_entity_t *entity) int ret = pthread_join(entity->pdusession_thread, NULL); AssertFatal(ret == 0, "pthread_join() failed, errno: %d, %s\n", errno, strerror(errno)); // Bring down the IP interface - int default_pdu = get_softmodem_params()->default_pdu_session_id; - char ifname[IFNAMSIZ]; - if (entity->is_gnb) { - char *ifprefix = get_softmodem_params()->nsa ? "oaitun_gnb" : "oaitun_enb"; - tun_generate_ifname(ifname, ifprefix, entity->ue_id - 1); - } else { - tun_generate_ue_ifname(ifname, entity->ue_id, entity->pdusession_id != default_pdu ? entity->pdusession_id : -1); - } - tun_destroy(ifname); + tuntap_destroy(entity->pdusession_if_name); + free(entity->pdusession_if_name); + entity->pdusession_if_name = NULL; } diff --git a/openair2/SDAP/nr_sdap/nr_sdap.h b/openair2/SDAP/nr_sdap/nr_sdap.h index 1164641970..bb85fdf249 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap.h +++ b/openair2/SDAP/nr_sdap/nr_sdap.h @@ -60,8 +60,8 @@ void sdap_data_ind(int pdcp_entity, char *buf, int size); -void start_sdap_tun_ue(ue_id_t ue_id, int pdu_session_id, int sock); -void start_sdap_tun_gnb_first_ue_default_pdu_session(ue_id_t ue_id); -void create_ue_ip_if(const char *ipv4, const char *ipv6, int ue_id, int pdu_session_id); +void start_sdap_tun_gnb_first_ue_default_pdu_session(ue_id_t ue_id, int pdu_session_id); +void create_ue_ip_if(const char *ipv4, const char *ipv6, int ue_id, int pdu_session_id, bool is_default); +void create_ue_eth_if(int ue_id, int pdu_session_id, bool is_default); #endif diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.c b/openair2/SDAP/nr_sdap/nr_sdap_entity.c index dc747e5a60..266fff17ae 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.c +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.c @@ -31,7 +31,7 @@ #include "gtpv1_u_messages_types.h" #include "intertask_interface.h" #include "rlc.h" -#include "tun_if.h" +#include "tuntap_if.h" #include "nr_sdap.h" #define NO_SDAP_HEADER 0 @@ -534,7 +534,7 @@ static void nr_sdap_add_entity(const int is_gnb, const ue_id_t ue_id, const sdap if (IS_SOFTMODEM_NOS1 && is_gnb) { // In NOS1 mode, terminate SDAP for the first UE on the gNB. This allows injecting/receiving // PDCP SDUs to/from the TUN interface. - start_sdap_tun_gnb_first_ue_default_pdu_session(ue_id); + start_sdap_tun_gnb_first_ue_default_pdu_session(ue_id, sdap_entity->pdusession_id); } } diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.h b/openair2/SDAP/nr_sdap/nr_sdap_entity.h index 9f85ac21cf..c8a43dbc2a 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.h +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.h @@ -102,6 +102,7 @@ typedef struct nr_sdap_entity_s { bool enable_sdap; int pdusession_id; int pdusession_sock; + char *pdusession_if_name; pthread_t pdusession_thread; bool stop_thread; int qfi; diff --git a/openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishmentAccept.c b/openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishmentAccept.c index cb12e5dc6c..f59111cf43 100644 --- a/openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishmentAccept.c +++ b/openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishmentAccept.c @@ -23,7 +23,6 @@ #include #include "PduSessionEstablishmentAccept.h" #include "common/utils/LOG/log.h" -#include "common/utils/tun_if.h" #include "fgs_nas_utils.h" /** diff --git a/openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishmentAccept.h b/openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishmentAccept.h index 80694814b4..9c515e858f 100644 --- a/openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishmentAccept.h +++ b/openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishmentAccept.h @@ -49,6 +49,8 @@ typedef enum { FOREACH_IEI(TO_ENUM) } pduSessionEstablishment_IEI_t; #define PDU_SESSION_TYPE_IPV4 0b001 #define PDU_SESSION_TYPE_IPV6 0b010 #define PDU_SESSION_TYPE_IPV4V6 0b011 +#define PDU_SESSION_TYPE_UNSTRUCT 0b100 +#define PDU_SESSION_TYPE_ETHER 0b101 #define IPv4_ADDRESS_LENGTH 4 // length of the IPv4 address associated with a PDU session #define IPv6_INTERFACE_ID_LENGTH 8 // interface identifier for the IPv6 link local address #define SMF_IPv6_LLA_LENGTH 16 diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index 5a58af6b84..8f4f9bd280 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -56,7 +56,6 @@ #include "aka_functions.h" #include "assertions.h" #include "common/utils/ds/byte_array.h" -#include "common/utils/tun_if.h" #include "commonDef.h" #include "intertask_interface.h" #include "kdf.h" @@ -1473,7 +1472,10 @@ static int capture_ipv6_addr(const uint8_t *addr, char *ip, size_t len) * @brief Process PDU Session Address in PDU Session Establishment Accept message * and configure the tun interface */ -static void process_pdu_session_addr(pdu_session_establishment_accept_msg_t *msg, int instance_id, int pdu_session_id) +static void process_pdu_session_addr(pdu_session_establishment_accept_msg_t *msg, + int instance_id, + int pdu_session_id, + bool is_default) { uint8_t *addr = msg->pdu_addr_ie.pdu_addr_oct; @@ -1481,13 +1483,13 @@ 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)); - create_ue_ip_if(ip, NULL, instance_id, pdu_session_id); + create_ue_ip_if(ip, NULL, instance_id, pdu_session_id, is_default); } break; case PDU_SESSION_TYPE_IPV6: { char ipv6[40]; capture_ipv6_addr(addr, ipv6, sizeof(ipv6)); - create_ue_ip_if(NULL, ipv6, instance_id, pdu_session_id); + create_ue_ip_if(NULL, ipv6, instance_id, pdu_session_id, is_default); } break; case PDU_SESSION_TYPE_IPV4V6: { @@ -1495,7 +1497,7 @@ 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)); - create_ue_ip_if(ipv4, ipv6, instance_id, pdu_session_id); + create_ue_ip_if(ipv4, ipv6, instance_id, pdu_session_id, is_default); } break; default: @@ -1507,7 +1509,7 @@ static void process_pdu_session_addr(pdu_session_establishment_accept_msg_t *msg /** * @brief Handle PDU Session Establishment Accept and process decoded message */ -static void handle_pdu_session_accept(uint8_t *pdu_buffer, uint32_t msg_length, int instance) +static void handle_pdu_session_accept(const nr_ue_nas_t *nas, uint8_t *pdu_buffer, uint32_t msg_length, int instance) { pdu_session_establishment_accept_msg_t msg = {0}; int size = 0; @@ -1545,22 +1547,42 @@ static void handle_pdu_session_accept(uint8_t *pdu_buffer, uint32_t msg_length, size += decoded; // decode PDU Session Establishment Accept - if (!decode_pdu_session_establishment_accept_msg(&msg, pdu_buffer + size, msg_length)) + if (!decode_pdu_session_establishment_accept_msg(&msg, pdu_buffer + size, msg_length)) { LOG_E(NAS, "decode_pdu_session_establishment_accept_msg failure\n"); + return; + } + + int idx; + for (idx = 0; idx < nas->uicc->n_pdu_sessions; ++idx) { + const pdu_session_config_t *pdu = &nas->uicc->pdu_sessions[idx]; + if (pdu->id == sm_header.pdu_session_id && pdu->type == msg.pdu_type) + break; + } + if (idx == nas->uicc->n_pdu_sessions) { + LOG_E(NAS, + "PDU session establishment accept for ID %d type %d not in list of configured PDU sessions, abort transaction\n", + sm_header.pdu_session_id, + msg.pdu_type); + return; + } + + // process PDU Session: pass ID -1 to not append PDU ID to interface + bool is_default = idx == 0; + if (msg.pdu_type == PDU_SESSION_TYPE_ETHER) { + create_ue_eth_if(instance, sm_header.pdu_session_id, is_default); + } else if (msg.pdu_addr_ie.pdu_length) { + process_pdu_session_addr(&msg, instance, sm_header.pdu_session_id, is_default); + } else { + LOG_W(NAS, "Unhandled PDU session type %d, ignoring PDU session ID %d\n", msg.pdu_type, sm_header.pdu_session_id); + } - // process PDU Session - if (msg.pdu_addr_ie.pdu_length) - process_pdu_session_addr(&msg, instance, sm_header.pdu_session_id); - else - LOG_W(NAS, "Optional PDU Address IE was not provided\n"); - set_qfi(msg.qos_rules.rule->qfi, sm_header.pdu_session_id, instance); } /** * @brief Handle DL NAS Transport and process piggybacked 5GSM messages */ -void handleDownlinkNASTransport(uint8_t * pdu_buffer, int pdu_length, int instance) +void handleDownlinkNASTransport(const nr_ue_nas_t *nas, uint8_t * pdu_buffer, int pdu_length, int instance) { if (pdu_length < 17) { LOG_E(NAS, "Received DL NAS Transport message too short (%d)\n", pdu_length); @@ -1569,7 +1591,7 @@ void handleDownlinkNASTransport(uint8_t * pdu_buffer, int pdu_length, int instan uint8_t msg_type = *(pdu_buffer + 16); if (msg_type == FGS_PDU_SESSION_ESTABLISHMENT_ACC) { LOG_A(NAS, "Received PDU Session Establishment Accept in DL NAS Transport\n"); - handle_pdu_session_accept(pdu_buffer, pdu_length, instance); + handle_pdu_session_accept(nas, pdu_buffer, pdu_length, instance); } else { LOG_E(NAS, "Received unexpected message in DLinformationTransfer %d\n", msg_type); } @@ -1688,19 +1710,16 @@ static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t * const bool has_nssai_sd = pdu_req->sd != 0xffffff; // 0xffffff means "no SD", TS 23.003 const size_t nssai_len = has_nssai_sd ? 4 : 1; mm_msg->snssai.length = nssai_len; - // Fixme: it seems there are a lot of memory errors in this: this value was on the stack, - // but pushed in a itti message to another thread - // this kind of error seems in many places in 5G NAS mm_msg->snssai.value = calloc(1, nssai_len); mm_msg->snssai.value[0] = pdu_req->sst; if (has_nssai_sd) INT24_TO_BUFFER(pdu_req->sd, &mm_msg->snssai.value[1]); size += 1 + 1 + nssai_len; - int dnnSize = strlen(nas->uicc->dnnStr); + int dnnSize = strlen(pdu_req->dnn); mm_msg->dnn.value = calloc(1, dnnSize + 1); mm_msg->dnn.length = dnnSize + 1; mm_msg->dnn.value[0] = dnnSize; - memcpy(mm_msg->dnn.value + 1, nas->uicc->dnnStr, dnnSize); + memcpy(mm_msg->dnn.value + 1, pdu_req->dnn, dnnSize); size += (1 + 1 + dnnSize + 1); // encode the message @@ -1772,24 +1791,33 @@ static void send_nas_5gmm_ind(instance_t instance, const Guti5GSMobileIdentity_t itti_send_msg_to_task(TASK_RRC_NRUE, instance, msg); } -void request_pdusession(nr_ue_nas_t *nas, int pdusession_id) +void request_pdusession(nr_ue_nas_t *nas, const pdu_session_config_t *pdu) { + int t = pdu->type; + AssertFatal(t == PDU_SESSION_TYPE_IPV4 || t == PDU_SESSION_TYPE_IPV6 || t == PDU_SESSION_TYPE_IPV4V6 + || t == PDU_SESSION_TYPE_UNSTRUCT || t == PDU_SESSION_TYPE_ETHER, + "illegal PDU session type %d\n", + t); + AssertFatal(t != PDU_SESSION_TYPE_UNSTRUCT, "unstructured PDU sessions not handled yet\n"); MessageDef *message_p = itti_alloc_new_message(TASK_NAS_NRUE, nas->UE_id, NAS_PDU_SESSION_REQ); - NAS_PDU_SESSION_REQ(message_p).pdusession_id = pdusession_id; - NAS_PDU_SESSION_REQ(message_p).pdusession_type = 0x91; // 0x91 = IPv4, 0x92 = IPv6, 0x93 = IPv4v6 - NAS_PDU_SESSION_REQ(message_p).sst = nas->uicc->nssai_sst; - NAS_PDU_SESSION_REQ(message_p).sd = nas->uicc->nssai_sd; + nas_pdu_session_req_t *pdu_req = &NAS_PDU_SESSION_REQ(message_p); + pdu_req->pdusession_id = pdu->id; + // 24.501: joint PDU session type IEI (0x9-, Table 8.3.1.1.1) and type (9.11.4.11) + pdu_req->pdusession_type = 0x90 | t; + pdu_req->sst = pdu->nssai.sst; + pdu_req->sd = pdu->nssai.sd; + snprintf(pdu_req->dnn, sizeof(pdu_req->dnn), "%s", pdu->dnn); itti_send_msg_to_task(TASK_NAS_NRUE, nas->UE_id, message_p); } -static int get_user_nssai_idx(const nr_nas_msg_snssai_t allowed_nssai[NAS_MAX_NUMBER_SLICES], const nr_ue_nas_t *nas) +static int get_user_nssai_idx(nssai_t ch_nssai, const nr_nas_msg_snssai_t allowed_nssai[NAS_MAX_NUMBER_SLICES]) { for (int i = 0; i < NAS_MAX_NUMBER_SLICES; i++) { const nr_nas_msg_snssai_t *nssai = allowed_nssai + i; /* If it was received in Registration Accept, check the SD in the stored Allowed N-SSAI, else, consider the SD valid */ - bool sd_match = !nssai->sd || (nas->uicc->nssai_sd == *nssai->sd); - if ((nas->uicc->nssai_sst == nssai->sst) && sd_match) + bool sd_match = !nssai->sd || (ch_nssai.sd == *nssai->sd); + if ((ch_nssai.sst == nssai->sst) && sd_match) return i; } return -1; @@ -1864,12 +1892,18 @@ static void handle_registration_accept(nr_ue_nas_t *nas, const uint8_t *pdu_buff send_nas_uplink_data_req(nas, &initialNasMsg); LOG_I(NAS, "Send NAS_UPLINK_DATA_REQ message(RegistrationComplete)\n"); } - if (get_user_nssai_idx(msg.nas_allowed_nssai, nas) < 0) { - LOG_E(NAS, "NSSAI parameters not match with allowed NSSAI. Couldn't request PDU session.\n"); - } else { - request_pdusession(nas, get_softmodem_params()->default_pdu_session_id); - if (get_nrUE_params()->extra_pdu_id != -1) { - request_pdusession(nas, get_nrUE_params()->extra_pdu_id); + if (nas->uicc->n_pdu_sessions == 0) + LOG_W(SIM, "no PDU sessions to request configured\n"); + for (const pdu_session_config_t *pdu = nas->uicc->pdu_sessions; pdu < nas->uicc->pdu_sessions + nas->uicc->n_pdu_sessions; ++pdu) { + if (get_user_nssai_idx(pdu->nssai, msg.nas_allowed_nssai) < 0) { + LOG_E(NAS, + "PDU session ID %d NSSAI %d.%d: mismatch for allowed NSSAI. Couldn't request PDU session.\n", + pdu->id, + pdu->nssai.sst, + pdu->nssai.sd); + } else { + LOG_I(NAS, "requested PDU session ID %d type %d NSSAI %d.%d DNN %s\n", pdu->id, pdu->type, pdu->nssai.sst, pdu->nssai.sd, pdu->dnn); + request_pdusession(nas, pdu); } } // Free local message after processing @@ -2017,7 +2051,7 @@ void *nas_nrue(void *args_p) if (msg_type == FGS_REGISTRATION_ACCEPT) { handle_registration_accept(nas, ba.buf, ba.len); } else if (msg_type == FGS_PDU_SESSION_ESTABLISHMENT_ACC) { - handle_pdu_session_accept(ba.buf, ba.len, nas->UE_id); + handle_pdu_session_accept(nas, ba.buf, ba.len, nas->UE_id); } // Free NAS buffer memory after use (coming from RRC) @@ -2103,7 +2137,7 @@ void *nas_nrue(void *args_p) handle_security_mode_command(nas, &initialNasMsg, pdu_buffer, pdu_length); break; case FGS_DOWNLINK_NAS_TRANSPORT: - handleDownlinkNASTransport(pdu_buffer, pdu_length, nas->UE_id); + handleDownlinkNASTransport(nas, pdu_buffer, pdu_length, nas->UE_id); break; case FGS_REGISTRATION_ACCEPT: handle_registration_accept(nas, pdu_buffer, pdu_length); @@ -2114,7 +2148,7 @@ void *nas_nrue(void *args_p) nas->fiveGMM_state = FGS_DEREGISTERED; break; case FGS_PDU_SESSION_ESTABLISHMENT_ACC: - handle_pdu_session_accept(pdu_buffer, pdu_length, nas->UE_id); + handle_pdu_session_accept(nas, pdu_buffer, pdu_length, nas->UE_id); break; case FGS_PDU_SESSION_ESTABLISHMENT_REJ: LOG_E(NAS, "Received PDU Session Establishment reject\n"); @@ -2159,10 +2193,11 @@ void *nas_nrue(void *args_p) } break; case NAS_INIT_NOS1_IF: { - const int pdu_session_id = get_softmodem_params()->default_pdu_session_id; + const int pdu_session_id = DEFAULT_NOS1_PDU_ID; const char *ip = "10.0.1.2"; const int qfi = 7; - create_ue_ip_if(ip, NULL, nas->UE_id, pdu_session_id); + const bool is_default = true; + create_ue_ip_if(ip, NULL, nas->UE_id, pdu_session_id, is_default); set_qfi(qfi, pdu_session_id, nas->UE_id); break; } diff --git a/openair3/NAS/NR_UE/nr_nas_msg.h b/openair3/NAS/NR_UE/nr_nas_msg.h index 7a19997444..1bed56aa3c 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.h +++ b/openair3/NAS/NR_UE/nr_nas_msg.h @@ -32,6 +32,7 @@ #define __NR_NAS_MSG_SIM_H__ #include +#include "common/5g_platform_types.h" #include #include #include @@ -113,6 +114,6 @@ void *nas_nrue_task(void *args_p); void *nas_nrue(void *args_p); void nas_init_nrue(int num_ues); void nr_ue_create_ip_if(const char *ifnameprefix, const char *ipv4, const char *ipv6, int ue_id, int pdu_session_id); -void request_pdusession(nr_ue_nas_t *nas, int pdusession_id); +void request_pdusession(nr_ue_nas_t *nas, const pdu_session_config_t *pdu); #endif /* __NR_NAS_MSG_SIM_H__*/ diff --git a/openair3/NAS/UE/ESM/esm_ebr_context.c b/openair3/NAS/UE/ESM/esm_ebr_context.c index cec4c268bd..63cfabbac4 100644 --- a/openair3/NAS/UE/ESM/esm_ebr_context.c +++ b/openair3/NAS/UE/ESM/esm_ebr_context.c @@ -45,7 +45,7 @@ Description Defines functions used to handle EPS bearer contexts. #include "esm_ebr.h" #include "esm_ebr_context.h" -#include "common/utils/tun_if.h" +#include "common/utils/tuntap_if.h" #include "emm_sap.h" #include "system.h" diff --git a/openair3/UICC/CMakeLists.txt b/openair3/UICC/CMakeLists.txt index c80694e1a5..3e72949a1b 100644 --- a/openair3/UICC/CMakeLists.txt +++ b/openair3/UICC/CMakeLists.txt @@ -1,3 +1,3 @@ -add_library(lib_uicc OBJECT usim_interface.c) +add_library(lib_uicc OBJECT usim_interface.c pdu_session.c) target_include_directories(lib_uicc PRIVATE .) target_link_libraries(lib_uicc PRIVATE log_headers) diff --git a/openair3/UICC/pdu_session.c b/openair3/UICC/pdu_session.c new file mode 100644 index 0000000000..1eabeb7f37 --- /dev/null +++ b/openair3/UICC/pdu_session.c @@ -0,0 +1,116 @@ +/* + * 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 OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * 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 + +#include "pdu_session.h" +// we can't include the file for PDU session type defines, as it pulls in too +// much. However, we only use it for mapping types to integers, which are +// standard defined, so it should be ok. +//#include "openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishmentAccept.h" +#include "common/utils/utils.h" +#include "common/config/config_paramdesc.h" +#include "common/config/config_userapi.h" + + +// clang-format off +// Note: Default PDU session ID 0 does not exist and will be replaced with PDU +// session index if not set to a parameter > 0! +#define PDU_SESS_PARAMS_DESC { \ + {"id", "PDU session ID\n", 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \ + {"type", "PDU session type\n", 0, .strptr=NULL, .defstrval="IPv4", TYPE_STRING, 0}, \ + {"nssai_sst", "NSSAI slice type\n", 0, .u8ptr=NULL, .defintval=1, TYPE_UINT8, 0}, \ + {"nssai_sd", "NSSAI slice differentiator\n", 0, .uptr=NULL, .defintval=0xffffff, TYPE_UINT32, 0}, \ + {"dnn", "PDU session DNN (APN)\n", 0, .strptr=NULL, .defstrval="oai", TYPE_STRING, 0}, \ +} + +#define PDU_SESS_PARAMS_CHECK { \ + {.s2 = {config_check_intrange, {0, 255}}}, \ + {.s3a = {config_checkstr_assign_integer, \ + {"IPv4", "IPv6", "IPv4v6", "Ethernet"}, \ + {1 /*PDU_SESSION_TYPE_IPV4*/, \ + 2 /*PDU_SESSION_TYPE_IPV6*/, \ + 3 /*PDU_SESSION_TYPE_IPV4V6*/, \ + 5 /*PDU_SESSION_TYPE_ETHER*/}, \ + 4}}, \ + {.s2 = {config_check_intrange, {1, 4}}}, \ + {.s2 = {config_check_intrange, {1, 0xffffff}}}, \ + {.s4 = {config_check_dnn}}, \ +} +// clang-format on + +static int config_check_dnn(configmodule_interface_t *cfg, paramdef_t *param) +{ + const char *dnn = *param->strptr; + int dnn_len = strlen(dnn); + if (dnn_len > 102) { + printf("DNN '%s' exceeds max len of 102 (is %d) (TS 24.501 §9.11.2.1A)\n", dnn, dnn_len); + return -1; + } + + // check for valid characters in the APN (TS 23.003 §9.1) + // we don't enforce all conditions + const char *allowed = "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789.-"; + while (*dnn) { + if (!strchr(allowed, *dnn)) { + printf("character '%c' in DNN '%s' is not allowed (TS 23.003 §9.1)\n", *dnn, *param->strptr); + return -1; + } + dnn++; + } + + return 0; +} + +int get_pdu_session_configs(const char *uiccName, pdu_session_config_t *configs, int max_len) +{ + paramdef_t pdu_sess_params[] = PDU_SESS_PARAMS_DESC; + const int npsp = sizeofArray(pdu_sess_params); + paramlist_def_t pdu_sess_list = {"pdu_sessions"}; + checkedparam_t pdu_sess_params_check[] = PDU_SESS_PARAMS_CHECK; + static_assert(sizeofArray(pdu_sess_params) == sizeofArray(pdu_sess_params_check), + "param_def_t array and corresponding checkedparam_t array should have the same size"); + for (int i = 0; i < sizeofArray(pdu_sess_params); ++i) + pdu_sess_params[i].chkPptr = &pdu_sess_params_check[i]; + int ret = config_getlist(config_get_if(), &pdu_sess_list, pdu_sess_params, sizeofArray(pdu_sess_params), uiccName); + if (ret < 0) { + // couldn't load configuration from pdu_sessions, caller has to handle + return -1; + } + + int num = pdu_sess_list.numelt; + AssertFatal(num <= max_len, "cannot handle more than %d PDU sessions\n", max_len); + + for (int i = 0; i < num; ++i) { + pdu_session_config_t *pdu = configs + i; + paramdef_t *p = pdu_sess_list.paramarray[i]; + int id = *gpd(p, npsp, "id")->iptr; + pdu->id = id > 0 ? id : i + 1; // if not user-specified ID, use PDU session index + pdu->type = config_get_processedint(config_get_if(), (paramdef_t *)gpd(p, npsp, "type")); + pdu->nssai.sst = *gpd(p, npsp, "nssai_sst")->iptr; + pdu->nssai.sd = *gpd(p, npsp, "nssai_sd")->iptr; + pdu->dnn = strdup(*gpd(p, npsp, "dnn")->strptr); + } + + return num; +} diff --git a/openair3/UICC/pdu_session.h b/openair3/UICC/pdu_session.h new file mode 100644 index 0000000000..c1acaa82b1 --- /dev/null +++ b/openair3/UICC/pdu_session.h @@ -0,0 +1,36 @@ +/* + * 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 OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * 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 + */ + +#ifndef PDU_SESSION_H_ +#define PDU_SESSION_H_ + +#include "common/5g_platform_types.h" + +typedef struct { + int id; + int type; + nssai_t nssai; + char *dnn; // [103]? +} pdu_session_config_t; + +int get_pdu_session_configs(const char *uiccName, pdu_session_config_t *configs, int max_len); + +#endif /* PDU_SESSION_H_ */ diff --git a/openair3/UICC/usim_interface.c b/openair3/UICC/usim_interface.c index f1019366b1..f722d6ccd6 100644 --- a/openair3/UICC/usim_interface.c +++ b/openair3/UICC/usim_interface.c @@ -22,6 +22,7 @@ */ #include +#include "common/platform_constants.h" #include #include extern uint16_t NB_UE_INST; @@ -76,10 +77,7 @@ uicc_t *init_uicc(char *sectionName) { // key, OPc, sqn, amf don't need to be read from the true USIM int ret = config_get(config_get_if(), uicc_params, sizeofArray(uicc_params), sectionName); AssertFatal(ret >= 0, "configuration couldn't be performed for uicc name: %s", sectionName); - LOG_I(SIM, - "UICC simulation: IMSI=%s, IMEISV=%s, Ki=%s, OPc=%s, DNN=%s, SST=0x%02x, SD=0x%06x\n", - uicc->imsiStr, uicc->imeisvStr, uicc->keyStr, uicc->opcStr, - uicc->dnnStr, uicc->nssai_sst, uicc->nssai_sd); + LOG_I(SIM, "UICC simulation: IMSI=%s, IMEISV=%s, Ki=%s, OPc=%s\n", uicc->imsiStr, uicc->imeisvStr, uicc->keyStr, uicc->opcStr); to_hex(uicc->keyStr,uicc->key, sizeof(uicc->key) ); to_hex(uicc->opcStr,uicc->opc, sizeof(uicc->opc) ); to_hex(uicc->sqnStr,uicc->sqn, sizeof(uicc->sqn) ); @@ -112,6 +110,36 @@ uicc_t * checkUicc(int Mod_id) { char uiccName[64]; sprintf(uiccName,"uicc%d", Mod_id); uiccArray[Mod_id]=(void*)init_uicc(uiccName); + uicc_t *uicc = uiccArray[Mod_id]; + uicc->n_pdu_sessions = get_pdu_session_configs(uiccName, uicc->pdu_sessions, sizeof(uicc->pdu_sessions)); + if (uicc->n_pdu_sessions > 0) { + LOG_I(SIM, "overriding potential %s.dnn/nssai_sst/nssai_sd from %s.pdu_sessions\n", uiccName, uiccName); + } else if (uicc->n_pdu_sessions < 0) { + // we could not load from "new" pdu_sessions list, so read from "legacy" + // config + LOG_W(SIM, + "loading PDU session parameters from legacy UICC configuration. Please update to use %s.pdu_sessions instead to make this warning disappear\n", + uiccName); + sleep(3); + uicc->n_pdu_sessions = 1; + pdu_session_config_t *pdu = &uicc->pdu_sessions[0]; + AssertFatal(uicc->dnnStr != NULL, "no default DNN, cannot create\n"); + pdu->id = DEFAULT_NOS1_PDU_ID; // any default would do + pdu->dnn = strdup(uicc->dnnStr); + pdu->nssai.sst = uicc->nssai_sst; + pdu->nssai.sd = uicc->nssai_sd; + pdu->type = 1; /* = PDU_SESSION_TYPE_IPV4 */ + } // else: uicc->n_pdu_sessions == 0 => don't request a PDU session + for (int i = 0; i < uicc->n_pdu_sessions; ++i) { + const pdu_session_config_t *pdu = &uicc->pdu_sessions[i]; + LOG_I(SIM, + "will request PDU session ID %d, type %d, DNN %s, NSSAI %d.%6x\n", + pdu->id, + pdu->type, + pdu->dnn, + pdu->nssai.sst, + pdu->nssai.sd); + } } return (uicc_t*) uiccArray[Mod_id]; } diff --git a/openair3/UICC/usim_interface.h b/openair3/UICC/usim_interface.h index 1a275db887..f4689594c2 100644 --- a/openair3/UICC/usim_interface.h +++ b/openair3/UICC/usim_interface.h @@ -34,6 +34,7 @@ #include #include #include "common_lib.h" +#include "pdu_session.h" /* 3GPP glossary RES RESponse @@ -53,6 +54,8 @@ typedef struct { char *dnnStr; int nssai_sst; int nssai_sd; + pdu_session_config_t pdu_sessions[256]; + int n_pdu_sessions; uint8_t key[16]; uint8_t opc[16]; uint8_t amf[2]; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf index 4cea93ea46..d4f51cd6ea 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf @@ -2,9 +2,7 @@ uicc0 = { imsi = "2089900007487"; key = "fec86ba6eb707ed08905757b1bb44b8f"; opc= "C42449363BBAD02B66D16BC975D77CC1"; -dnn= "oai"; -nssai_sst=1; -nssai_sd=1; +pdu_sessions = ({ dnn = "oai"; nssai_sst = 1; nssai_sd = 1; }); } position0 = {