QoS handling: add F1AP DRB QoS (IE) aggregation

DRB QoS IE (mandatory in DRB-Information IE) represents the DRB level QoS,
which shall be computed from multiple QoS flows mapped to the DRB instead
of using only the first QoS flow.

ARP is for admission control/preemption (1-15, 1 = highest priority) and
DRB-level QoS selection should use ARP for admission control decisions.

Changes:
- Use ARP priority (not 5QI priority) for selection (admission control decision)
- Iterate through all flows to find the flow with highest ARP priority (lowest ARP priority_level value
- Add fill_f1_drb_qos to return DRB QoS by value, i.e. QoS characteristics (5QI, priority, delay budget, error rate)
- Replace 'drb.nr.drb_qos = drb.nr.flows[0].param' with proper aggregation

Example: DRB with Flow1 (ARP=10) and Flow2 (ARP=5)
- Old: Would incorrectly use Flow1's QoS
- New: Correctly uses Flow2 (ARP=5) which has higher priority

This commit is a refactoring of commit 398ae02ab9 from !2836

Co-authored-by: Sriharsha Korada <sriharsha.korada@iis.fraunhofer.de>

Signed-off-by: Guido Casati <guido.casati@openairinterface.org>
This commit is contained in:
Guido Casati
2025-09-08 20:14:45 +02:00
parent e041a2a078
commit 4ad557a0e3
3 changed files with 42 additions and 3 deletions

View File

@@ -446,7 +446,7 @@ static bool decode_qos_flow_param(const F1AP_QoSFlowLevelQoSParameters_t *f1ap,
return true;
}
static f1ap_qos_flow_param_t cp_qos_flow_param(const f1ap_qos_flow_param_t *orig)
f1ap_qos_flow_param_t cp_qos_flow_param(const f1ap_qos_flow_param_t *orig)
{
f1ap_qos_flow_param_t cp = {
.qos_type = orig->qos_type,

View File

@@ -52,4 +52,6 @@ f1ap_ue_context_rel_cplt_t cp_ue_context_rel_cplt(const f1ap_ue_context_rel_cplt
bool eq_ue_context_rel_cplt(const f1ap_ue_context_rel_cplt_t *a, const f1ap_ue_context_rel_cplt_t *b);
void free_ue_context_rel_cplt(f1ap_ue_context_rel_cplt_t *cplt);
f1ap_qos_flow_param_t cp_qos_flow_param(const f1ap_qos_flow_param_t *orig);
#endif /* F1AP_UE_CONTEXT_SETUP_REQ_H_ */

View File

@@ -2909,12 +2909,42 @@ f1ap_qos_flow_param_t get_qos_char_from_qos_flow_param(const pdusession_level_qo
return qos_char;
}
/** @brief Aggregate DRB QoS characteristics from multiple QoS flows
* @param highest_priority_flow Highest priority flow (lowest ARP priority value)
* @param highest_arp Highest ARP priority value
* @return Aggregated DRB QoS characteristics
* @note About ARP (Allocation Retention Priority):
* - ARP is for admission control/preemption (priority_level: 1-15)
* - DRB-level QoS selection should use ARP for admission control decisions
* Required for F1AP spec compliance (dRB-QoS is mandatory in DRB-Information IE) */
static f1ap_qos_flow_param_t fill_f1_drb_qos(const f1ap_qos_flow_param_t *highest_priority_flow, const uint16_t highest_arp)
{
DevAssert(highest_arp >= MIN_QOS_ARP_PRIORITY_LEVEL);
f1ap_qos_flow_param_t drb_qos = cp_qos_flow_param(highest_priority_flow);
// Optional fields: delay_critical and avg_win are not copied for DRB-level QoS
// (they are per-flow specific, not aggregated at DRB level)
if (drb_qos.qos_type == DYNAMIC) {
free(drb_qos.dyn.delay_critical);
free(drb_qos.dyn.avg_win);
}
return drb_qos;
}
/** @brief Fill F1 DRB Info (NR) from QoS flows, including DRB-level QoS and QoS flows mapped to DRB
* @param pdu PDU session parameters
* @param qfis List of QFIs
* @param num_qfis Number of QFIs in list
* @return Filled F1 DRB Info (NR) */
static f1ap_drb_info_nr_t fill_f1_drb_info_nr(pdusession_t *pdu, const uint8_t *qfis, const int num_qfis)
{
uint16_t highest_arp = MAX_QOS_ARP_PRIORITY_LEVEL; // lowest priority
const f1ap_drb_flows_mapped_t *highest_priority_flow = NULL;
f1ap_drb_info_nr_t drb_info = {0};
drb_info.nssai = pdu->nssai;
drb_info.flows_len = num_qfis;
drb_info.flows = calloc_or_fail(num_qfis, sizeof(*drb_info.flows));
for (int i = 0; i < num_qfis; i++) {
int qfi = qfis[i];
/* find the stored QoS flow parameters for this QFI */
@@ -2924,9 +2954,16 @@ static f1ap_drb_info_nr_t fill_f1_drb_info_nr(pdusession_t *pdu, const uint8_t *
f1ap_drb_flows_mapped_t *flow = &drb_info.flows[i];
flow->qfi = qfi;
flow->param = get_qos_char_from_qos_flow_param(&qos_param->qos);
// Find flow with highest ARP priority (lowest ARP priority_level value)
// (lower ARP priority value = higher priority for admission/preemption)
if (highest_priority_flow == NULL || flow->param.arp.prio < highest_arp) {
highest_arp = flow->param.arp.prio;
highest_priority_flow = flow;
}
}
/* DRB QoS IE: we just reuse the ones from the first flow */
drb_info.drb_qos = drb_info.flows[0].param;
/* DRB QoS IE: aggregate DRB-level QoS from all flows (highest priority) */
DevAssert(highest_priority_flow);
drb_info.drb_qos = fill_f1_drb_qos(&highest_priority_flow->param, highest_arp);
return drb_info;
}