Merge remote-tracking branch 'origin/sdap-qos-improvements' into integration_2025_w43 (!3519)

Refactor SDAP adaptation work for QoS

This MR is an adaptation of the code introduced in !2703.

The goal is a cleanup and functional refactor of the SDAP/PDCP
integration, that is:

- centralize SDAP configuration logic
- simplify entity creation
- improve robustness of role-based SDAP handling
- prepare the codebase for clean support of DRB reconfiguration and
  teardown flows

More concretely:

1. New sdap_config_t and get_sdap_Config()

  - Introduced an internal struct sdap_config_t to abstract SDAP config
    input
  - Centralized SDAP config parsing into new get_sdap_Config() function
    that translates ASN.1 NR_SDAP_Config into this internal
    representation. This is called during RRC triggered
    (re)configuration procedures.
  - Enable mapping of number of QoS flows > 1

2. Unified role handling with bitmasks

  - Added a bitmask-based entity_role field to track SDAP directions:
    SDAP_UL_RX, SDAP_UL_TX, SDAP_DL_RX, SDAP_DL_TX: header presence was
    determined by simple direction (UE vs gNB) and individual
    is_sdap_rx/tx() checks, however nr_sdap_rx_entity behaves
    differently depending on the direction of the RX entity (DL/UL),
    therefore this change can help enable a more accurate SDAP header
    handling across directions and node types.
  - Replaces old helpers is_sdap_rx() / is_sdap_tx() with internal
    checks against the role bitfield
  - QFI-to-DRB mapping is now annotated with direction for both data and
    control PDUs

3. Simplified DRB and SDAP setup

  - add_drb() in PDCP API now delegates SDAP config processing cleanly
  - new_nr_sdap_entity() is used consistently to register a fresh SDAP
    context for the UE and PDU session.
    - Also, re-use and reconfigure existing SDAP entity if already
      exists.
  - logging has been added to trace mapped QFIs from RRC and resulting
    table entries

4. Improved QFI-to-DRB management

  - Refactored nr_sdap_qfi2drb_map_update() to register QFIs based on
    parsed config
  - Ensures control PDUs are correctly routed even after reconfiguration
  - Extended nr_sdap_ue_qfi2drb_config: perform UL QoS flow to DRB
    mapping configuration for a SDAP entity has already been established
    according to TS 37.324, 5.3 QoS flow to DRB Mapping, 5.3.1
    Configuration Procedures. Handle both UL QoS Flows mapping rules to
    add and to remove. QFIs will now be properly unmapped if specified
    via mappedQoS_FlowsToRelease, this might prevent stale QFI mappings
    from being used incorrectly.
  - nr_sdap_qfi2drb() and sdap_map_ctrl_pdu() now strictly fallback to
    default_drb only if a QFI mapping is missing. Missing default DRB
    now triggers LOG_E() (previously silent or misrouted to DRB 0).

5. Other cleanup

  - Remove dependencies from legacy rb_id_t
This commit is contained in:
Robert Schmidt
2025-10-24 14:31:00 +02:00
14 changed files with 367 additions and 378 deletions
+23 -4
View File
@@ -161,6 +161,28 @@ static NR_RadioBearerConfig_t *get_default_rbconfig(int eps_bearer_id,
return rbconfig;
}
static void rrc_nsa_add_drb(const int ue_id,
const NR_DRB_ToAddModList_t *addMod,
const nr_pdcp_entity_security_keys_and_algos_t *sp)
{
for (int i = 0; i < addMod->list.count; i++) {
NR_DRB_ToAddMod_t *drb = addMod->list.array[i];
DevAssert(drb->cnAssociation);
DevAssert(drb->cnAssociation->present != NR_DRB_ToAddMod__cnAssociation_PR_NOTHING);
DevAssert(drb->cnAssociation->present == NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity);
// get SDAP config
sdap_config_t sdap = {0};
// EPC association
sdap.pdusession_id = drb->cnAssociation->choice.eps_BearerIdentity;
sdap.drb_id = drb->drb_Identity;
sdap.defaultDRB = true;
// add SDAP entity (terminated at gNB, since it's EPC)
nr_sdap_addmod_entity(GNB_FLAG_YES, ue_id, sdap);
// add PDCP entity
nr_pdcp_add_drb(GNB_FLAG_YES, ue_id, drb->pdcp_Config, &sdap, sp);
}
}
/* generate prototypes for the tree management functions (RB_INSERT used in rrc_add_nsa_user) */
RB_PROTOTYPE(rrc_nr_ue_tree_s, rrc_gNB_ue_context_s, entries,
rrc_gNB_compare_ue_rnti_id);
@@ -304,10 +326,7 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m, sctp_
}
DevAssert(UE->rb_config != NULL);
nr_pdcp_add_drbs(GNB_FLAG_YES,
UE->rrc_ue_id,
UE->rb_config->drb_ToAddModList,
&security_parameters);
rrc_nsa_add_drb(UE->rrc_ue_id, UE->rb_config->drb_ToAddModList, &security_parameters);
/* assumption: only a single bearer, see above */
NR_DRB_ToAddModList_t *rb_list = UE->rb_config->drb_ToAddModList;
+26 -4
View File
@@ -599,6 +599,31 @@ static void nr_rrc_process_dedicatedNAS_MessageList(NR_UE_RRC_INST_t *rrc, NR_RR
}
}
/** @brief Add bearer in PDCP/SDAP for 5GC association (SA) */
static void rrc_ue_add_bearer(const int ue_id, const NR_DRB_ToAddMod_t *drb, const nr_pdcp_entity_security_keys_and_algos_t *sp)
{
DevAssert(drb->cnAssociation);
DevAssert(drb->cnAssociation->present != NR_DRB_ToAddMod__cnAssociation_PR_NOTHING);
// get SDAP config
sdap_config_t sdap = {0};
if (drb->cnAssociation->present == NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity) {
DevAssert(drb->cnAssociation->present == NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity);
// EPC association
sdap.pdusession_id = drb->cnAssociation->choice.eps_BearerIdentity;
sdap.drb_id = drb->drb_Identity;
sdap.defaultDRB = true;
} else {
DevAssert(drb->cnAssociation->present == NR_DRB_ToAddMod__cnAssociation_PR_sdap_Config);
DevAssert(drb->cnAssociation->choice.sdap_Config);
sdap = nr_sdap_get_config(GNB_FLAG_NO, drb->cnAssociation->choice.sdap_Config, drb->drb_Identity);
}
// add SDAP entity
nr_sdap_addmod_entity(GNB_FLAG_NO, ue_id, sdap);
// add PDCP entity
nr_pdcp_add_drb(GNB_FLAG_NO, ue_id, drb->pdcp_Config, &sdap, sp);
}
/**
* @brief add, modify and release SRBs and/or DRBs
* @ref 3GPP TS 38.331
@@ -706,10 +731,7 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, NR_Rad
nr_reconfigure_sdap_entity(sdap_Config, ue_rrc->ue_id, sdap_Config->pdu_Session, DRB_id);
} else {
set_DRB_status(ue_rrc ,DRB_id, RB_ESTABLISHED);
add_drb(false,
ue_rrc->ue_id,
radioBearerConfig->drb_ToAddModList->list.array[cnt],
&security_up_parameters);
rrc_ue_add_bearer(ue_rrc->ue_id, radioBearerConfig->drb_ToAddModList->list.array[cnt], &security_up_parameters);
}
}
} // drb_ToAddModList //