Merge remote-tracking branch 'origin/add-support-eth-pdu-sess' into integration_2026_w05 (!3769)
Add Ethernet PDU session support and make PDU session request configurable
This MR adds support for Ethernet PDU sessions, and makes PDU sessions
configurable: per-PDU session ID, type (IPv4/IPv4v6/IPv6/Ethernet [1]),
DNN, NSSAI.
Concretely, it adds a new configuration file section pdu_sessions below
uicc0 that looks like this if everything is specified (default values
are shown):
uicc0:
[...]
pdu_sessions:
- id: 1
type: "IPv4"
nssai_sst: 1
nssai_sd: 0xffffff
dnn: "oai"
It is possible to list multiple PDU sessions (add new line - id: 2 to
request a second PDU session). It is backwards-compatible to the current
PDU session configuration (uicc0.dnn/nssai_sst/etc), the idea being that
either legacy or new configuration could be used, but (1) if
pdu_sessions exist, it will overwrite the legacy configuration, and (2)
multiple PDU sessions, and type, can only be configured using the new
config. The old parameters --extra-pdu-id and --default-pdu-id are not
accepted anymore. Documentation has been added to the UE tutorial.
It is possible to test an Ethernet PDU session [1]. It is possible to
test the PDU session inside the UE by verifying it has an TAP interface
oaitap_ue1, and ARPing the data network (arping has been added to
oai-nr-ue container for that purpose):
ip addr add 192.168.72.140/26 dev oaitap_ue1 # same subnet as data network!
ip link set dev oaitap_ue1 up
arping -c 20 -I oaitap_ue1 192.168.72.135 # will send ARP request in Ethernet frame to get IP address of data network
[1] See description MR !3769 for more information. On the UE side, only
the type has to be changed to "Ethernet".
This commit is contained in:
@@ -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;
|
||||
|
||||
/*
|
||||
|
||||
@@ -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 <pthread.h>
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user