From 2923e50ed0dcae12a565a11609e4f6fe5c8f7e05 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 12 Dec 2025 15:39:23 +0100 Subject: [PATCH] RRC/E1AP: Fix SDAP header mapping in E1AP and test callback header handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit fixes two related issues: 1. SDAP Header Mapping Bug (cucp_cuup_handler.c): The original code incorrectly mapped SDAP header configuration from internal E1AP representation to ASN.1 enum values. The internal representation (`bearer_context_sdap_config_t`) uses true=present/false=absent, while ASN.1 enum (`E1AP_SDAP_Configuration_t`) uses 0=present/1=absent. The fix correctly inverts the mapping: - Internal true (1) → ASN.1 0 (present) - Internal false (0) → ASN.1 1 (absent) The commit also clarifies internal representation in the stack. 2. Test Overhead Adjustment (nr-cuup-load-test.c): The change in (1) led to a failure in nr_cuup_functional_test with assertion: "size % 4 == 0" in recv_ng() - Changed UL packet overhead from 3 bytes to 2 bytes in sender_thread() - Before the SDAP fix, the test incorrectly accounted for 3 bytes: * 2 bytes PDCP header (correct) * 1 byte SDAP header (incorrectly included) - After the SDAP fix, SDAP headers are correctly set to absent, so only 2 bytes (PDCP header) are needed This ensures the test sends packets with the correct header size, matching what CU-UP expects after the SDAP configuration fix. The load test does not enable SDAP headers, therefore the original 3-byte overhead was possibly a workaround for the SDAP header bug. With the bug fixed, the test correctly uses 2-byte overhead (PDCP header). --- openair2/COMMON/e1ap_messages_types.h | 4 ++-- openair2/E1AP/lib/e1ap_bearer_context_management.c | 12 ++++++------ openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c | 7 +++++-- openair2/RRC/NR/rrc_gNB_NGAP.c | 4 ++-- tests/nr-cuup/nr-cuup-load-test.c | 4 +++- 5 files changed, 18 insertions(+), 13 deletions(-) diff --git a/openair2/COMMON/e1ap_messages_types.h b/openair2/COMMON/e1ap_messages_types.h index 37f29c1f4c..48cfef98f3 100644 --- a/openair2/COMMON/e1ap_messages_types.h +++ b/openair2/COMMON/e1ap_messages_types.h @@ -268,8 +268,8 @@ typedef struct up_params_s { /* IE SDAP Configuration (clause 9.3.1.39 of 3GPP TS 38.463) */ typedef struct bearer_context_sdap_config_s { long defaultDRB; - long sDAP_Header_UL; - long sDAP_Header_DL; + bool sDAP_Header_UL; + bool sDAP_Header_DL; } bearer_context_sdap_config_t; /* IE PDCP Configuration (clause 9.3.1.38 of 3GPP TS 38.463) */ diff --git a/openair2/E1AP/lib/e1ap_bearer_context_management.c b/openair2/E1AP/lib/e1ap_bearer_context_management.c index ee832ef85a..15c472b10d 100644 --- a/openair2/E1AP/lib/e1ap_bearer_context_management.c +++ b/openair2/E1AP/lib/e1ap_bearer_context_management.c @@ -192,8 +192,8 @@ static E1AP_SDAP_Configuration_t e1_encode_sdap_config(const bearer_context_sdap { E1AP_SDAP_Configuration_t out = {0}; out.defaultDRB = in->defaultDRB ? E1AP_DefaultDRB_true : E1AP_DefaultDRB_false; - out.sDAP_Header_UL = in->sDAP_Header_UL; - out.sDAP_Header_DL = in->sDAP_Header_DL; + out.sDAP_Header_UL = in->sDAP_Header_UL ? E1AP_SDAP_Header_UL_present : E1AP_SDAP_Header_UL_absent; + out.sDAP_Header_DL = in->sDAP_Header_DL ? E1AP_SDAP_Header_DL_present : E1AP_SDAP_Header_DL_absent; return out; } @@ -201,8 +201,8 @@ static E1AP_SDAP_Configuration_t e1_encode_sdap_config(const bearer_context_sdap static bool e1_decode_sdap_config(bearer_context_sdap_config_t *out, const E1AP_SDAP_Configuration_t *in) { out->defaultDRB = in->defaultDRB == E1AP_DefaultDRB_true; - out->sDAP_Header_UL = in->sDAP_Header_UL; - out->sDAP_Header_DL = in->sDAP_Header_DL; + out->sDAP_Header_UL = in->sDAP_Header_UL == E1AP_SDAP_Header_UL_present; + out->sDAP_Header_DL = in->sDAP_Header_DL == E1AP_SDAP_Header_DL_present; return true; } @@ -212,8 +212,8 @@ static bool e1_decode_sdap_config(bearer_context_sdap_config_t *out, const E1AP_ static bool eq_sdap_config(const bearer_context_sdap_config_t *a, const bearer_context_sdap_config_t *b) { _E1_EQ_CHECK_LONG(a->defaultDRB, b->defaultDRB); - _E1_EQ_CHECK_LONG(a->sDAP_Header_UL, b->sDAP_Header_UL); - _E1_EQ_CHECK_LONG(a->sDAP_Header_DL, b->sDAP_Header_DL); + _E1_EQ_CHECK_INT(a->sDAP_Header_UL, b->sDAP_Header_UL); + _E1_EQ_CHECK_INT(a->sDAP_Header_DL, b->sDAP_Header_DL); return true; } diff --git a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c index ecdf3dfd72..feb4ea3eff 100644 --- a/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c +++ b/openair2/LAYER2/nr_pdcp/cucp_cuup_handler.c @@ -60,8 +60,11 @@ static void fill_DRB_configList_e1(NR_DRB_ToAddModList_t *DRB_configList, const asn1cCalloc(ie->cnAssociation->choice.sdap_Config, sdap_config); sdap_config->pdu_Session = pdu->sessionId; /* SDAP */ - sdap_config->sdap_HeaderDL = drb->sdap_config.sDAP_Header_DL; - sdap_config->sdap_HeaderUL = drb->sdap_config.sDAP_Header_UL; + /* Convert from internal representation to ASN.1 enum: + * Internal: false=absent, true=present (or uninitialized=false means absent) + * ASN.1: 0=present, 1=absent */ + sdap_config->sdap_HeaderDL = drb->sdap_config.sDAP_Header_DL ? NR_SDAP_Config__sdap_HeaderDL_present : NR_SDAP_Config__sdap_HeaderDL_absent; + sdap_config->sdap_HeaderUL = drb->sdap_config.sDAP_Header_UL ? NR_SDAP_Config__sdap_HeaderUL_present : NR_SDAP_Config__sdap_HeaderUL_absent; sdap_config->defaultDRB = drb->sdap_config.defaultDRB; asn1cCalloc(sdap_config->mappedQoS_FlowsToAdd, FlowsToAdd); for (int j = 0; j < drb->numQosFlow2Setup; j++) { diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 3792b0e999..ce87d56661 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -299,8 +299,8 @@ static DRB_nGRAN_to_setup_t fill_e1_drb_to_setup(const drb_t *rrc_drb, drb_ngran.id = rrc_drb->drb_id; drb_ngran.sdap_config.defaultDRB = true; - drb_ngran.sdap_config.sDAP_Header_UL = session->sdap_config.header_ul_absent ? 1 : 0; - drb_ngran.sdap_config.sDAP_Header_DL = session->sdap_config.header_dl_absent ? 1 : 0; + drb_ngran.sdap_config.sDAP_Header_UL = session->sdap_config.header_ul_absent ? false : true; + drb_ngran.sdap_config.sDAP_Header_DL = session->sdap_config.header_dl_absent ? false : true; drb_ngran.pdcp_config = set_bearer_context_pdcp_config(rrc_drb->pdcp_config, um_on_default_drb, redcap_cap); diff --git a/tests/nr-cuup/nr-cuup-load-test.c b/tests/nr-cuup/nr-cuup-load-test.c index 0774b26b1b..047d316afc 100644 --- a/tests/nr-cuup/nr-cuup-load-test.c +++ b/tests/nr-cuup/nr-cuup-load-test.c @@ -418,7 +418,9 @@ static void *sender_thread(void *v) { struct thr_data *d = v; - size_t oh = d->is_ul ? 3 : 0; + // Overhead: PDCP header (2 bytes) for UL packets + // SDAP headers are disabled, so only PDCP header is added + size_t oh = d->is_ul ? 2 : 0; size_t packet_len = d->data_len + oh; uint8_t buf[packet_len]; memset(buf, 0, packet_len);