Adopt dynamic seq_arr in QoS Flow list (RRC PDU Session)
This commit is contained in:
@@ -67,9 +67,9 @@ bool read_gtp_sm(void * data)
|
||||
gtp->msg.ngut[i].teidgnb = session->param.n3_outgoing.teid;
|
||||
gtp->msg.ngut[i].teidupf = session->param.n3_incoming.teid;
|
||||
// TODO: one PDU session has multiple QoS Flow
|
||||
int nb_qos_flow = session->param.nb_qos;
|
||||
if (nb_qos_flow > 0) {
|
||||
gtp->msg.ngut[i].qfi = session->param.qos[nb_qos_flow - 1].qfi;
|
||||
DevAssert(seq_arr_size(&session->param.qos) == 1);
|
||||
FOR_EACH_SEQ_ARR(nr_rrc_qos_t *, qos, &session->param.qos) {
|
||||
gtp->msg.ngut[i].qfi = qos->qos.qfi;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -103,9 +103,8 @@ typedef struct pdusession_s {
|
||||
/* Unique pdusession_id for the UE. */
|
||||
int pdusession_id;
|
||||
byte_array_t nas_pdu;
|
||||
uint8_t nb_qos;
|
||||
/* Quality of service for this pdusession */
|
||||
pdusession_level_qos_parameter_t qos[QOSFLOW_MAX_VALUE];
|
||||
seq_arr_t qos;
|
||||
/* The transport layer address for the IP packets */
|
||||
pdu_session_type_t pdu_session_type;
|
||||
// NG-RAN endpoint of the NG-U (N3) transport bearer
|
||||
@@ -176,6 +175,11 @@ typedef struct nr_redcap_ue_cap {
|
||||
bool rlc_am_drb_long_sn_redcap_r17;
|
||||
} nr_redcap_ue_cap_t;
|
||||
|
||||
typedef struct {
|
||||
int drb_id;
|
||||
pdusession_level_qos_parameter_t qos;
|
||||
} nr_rrc_qos_t;
|
||||
|
||||
/* forward declaration */
|
||||
typedef struct nr_handover_context_s nr_handover_context_t;
|
||||
|
||||
|
||||
@@ -122,7 +122,6 @@ byte_array_t rrc_gNB_encode_RRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t *
|
||||
|
||||
nr_rrc_reconfig_param_t get_RRCReconfiguration_params(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, uint8_t srb_reest_bitmap, bool drb_reestablish);
|
||||
|
||||
pdusession_level_qos_parameter_t *get_qos_characteristics(const int qfi, rrc_pdu_session_param_t *pduSession);
|
||||
f1ap_qos_flow_param_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param);
|
||||
void openair_rrc_gNB_configuration(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration);
|
||||
NR_SRB_ToAddModList_t *createSRBlist(gNB_RRC_UE_t *ue, uint8_t reestablish);
|
||||
|
||||
+13
-22
@@ -733,9 +733,8 @@ void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t
|
||||
}
|
||||
|
||||
// Reference TS23501 Table 5.7.4-1: Standardized 5QI to QoS characteristics mapping
|
||||
for (qos_flow_index = 0; qos_flow_index < session->nb_qos; qos_flow_index++) {
|
||||
pdusession_level_qos_parameter_t *qos = &session->qos[qos_flow_index];
|
||||
switch (qos->fiveQI) {
|
||||
FOR_EACH_SEQ_ARR(nr_rrc_qos_t *, qos, &session->qos) {
|
||||
switch (qos->qos.fiveQI) {
|
||||
case 1: //100ms
|
||||
case 2: //150ms
|
||||
case 3: //50ms
|
||||
@@ -749,14 +748,14 @@ void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_E(NR_RRC, "not supported 5qi %lu\n", qos->fiveQI);
|
||||
LOG_E(NR_RRC, "not supported 5qi %lu\n", qos->qos.fiveQI);
|
||||
ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CauseRadioNetwork_not_supported_5QI_value};
|
||||
item->status = PDU_SESSION_STATUS_FAILED;
|
||||
item->xid = params.transaction_id;
|
||||
item->cause = cause;
|
||||
continue;
|
||||
}
|
||||
LOG_I(NR_RRC, "PDU Session ID %d, QOS flow %d, 5QI %ld \n", session->pdusession_id, qos_flow_index, qos->fiveQI);
|
||||
LOG_I(NR_RRC, "PDU Session ID %d, QOS flow %d, 5QI %ld \n", session->pdusession_id, qos_flow_index, qos->qos.fiveQI);
|
||||
}
|
||||
item->status = PDU_SESSION_STATUS_DONE;
|
||||
item->xid = params.transaction_id;
|
||||
@@ -2101,14 +2100,15 @@ void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb
|
||||
};
|
||||
|
||||
bool is_inter_cu_ho = UE->ho_context && UE->ho_context->source && !UE->ho_context->target;
|
||||
for (int i = 0; i < MAX_DRBS_PER_UE; i++) {
|
||||
int drb_id = i + 1;
|
||||
int drb_index = 0;
|
||||
FOR_EACH_SEQ_ARR(drb_t *, drb, &UE->drbs) {
|
||||
int drb_id = drb->drb_id;
|
||||
DRB_nGRAN_to_mod_t drb_to_mod = {0};
|
||||
if (n > 0) {
|
||||
/* DRBs to Setup in F1 UE Context Modifcation Response */
|
||||
if (i == n)
|
||||
if (drb_index == n)
|
||||
break;
|
||||
const f1ap_drb_setup_t *drb_f1 = &drbs[i];
|
||||
const f1ap_drb_setup_t *drb_f1 = &drbs[drb_index];
|
||||
drb_id = drb_f1->id;
|
||||
fill_e1_bearer_modif(&drb_to_mod, drb_f1);
|
||||
} else if (is_inter_cu_ho) {
|
||||
@@ -2134,6 +2134,8 @@ void e1_send_bearer_updates(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, f1ap_drb
|
||||
to_mod->sessionId = pdu->param.pdusession_id;
|
||||
// Fill E1 DRB to Modify item
|
||||
to_mod->DRBnGRanModList[to_mod->numDRB2Modify++] = drb_to_mod;
|
||||
|
||||
drb_index++;
|
||||
}
|
||||
DevAssert(req.numPDUSessionsMod > 0);
|
||||
DevAssert(req.numPDUSessions == 0);
|
||||
@@ -2448,17 +2450,6 @@ unsigned int mask_flip(unsigned int x) {
|
||||
return((((x>>8) + (x<<8))&0xffff)>>6);
|
||||
}
|
||||
|
||||
pdusession_level_qos_parameter_t *get_qos_characteristics(const int qfi, rrc_pdu_session_param_t *pduSession)
|
||||
{
|
||||
pdusession_t *pdu = &pduSession->param;
|
||||
for (int i = 0; i < pdu->nb_qos; i++) {
|
||||
if (qfi == pdu->qos[i].qfi)
|
||||
return &pdu->qos[i];
|
||||
}
|
||||
AssertFatal(1 == 0, "The pdu session %d does not contain a qos flow with qfi = %d\n", pdu->pdusession_id, qfi);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* \bref return F1AP QoS characteristics based on Qos flow parameters */
|
||||
f1ap_qos_flow_param_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param)
|
||||
{
|
||||
@@ -2516,11 +2507,11 @@ static int fill_drb_to_be_setup_from_e1_resp(const gNB_RRC_INST *rrc,
|
||||
/* find the QoS characteristics stored at RRC based on QFI returned
|
||||
* from E1. We expect this to correspond to a QFI we passed to E1
|
||||
* previously, so we expect it to exist. */
|
||||
pdusession_level_qos_parameter_t *qos_param = get_qos_characteristics(qfi, pdu);
|
||||
nr_rrc_qos_t *qos_param = find_qos(&pdu->param.qos, qfi);
|
||||
DevAssert(qos_param);
|
||||
f1ap_drb_flows_mapped_t *flow = &drb->nr.flows[j];
|
||||
flow->qfi = qfi;
|
||||
flow->param = get_qos_char_from_qos_flow_param(qos_param);
|
||||
flow->param = get_qos_char_from_qos_flow_param(&qos_param->qos);
|
||||
}
|
||||
/* the DRB QoS parameters: we just reuse the ones from the first flow */
|
||||
drb->nr.drb_qos = drb->nr.flows[0].param;
|
||||
|
||||
@@ -172,20 +172,30 @@ static nr_guami_t get_guami(const uint32_t amf_Id, const plmn_id_t plmn)
|
||||
/** @brief Copy NGAP PDU Session Transfer item to RRC pdusession_t struct */
|
||||
static void cp_pdusession_transfer_to_pdusession(pdusession_t *dst, const pdusession_transfer_t *src)
|
||||
{
|
||||
dst->nb_qos = src->nb_qos;
|
||||
for (uint8_t i = 0; i < src->nb_qos && i < QOSFLOW_MAX_VALUE; ++i) {
|
||||
dst->qos[i] = src->qos[i];
|
||||
}
|
||||
dst->pdu_session_type = src->pdu_session_type;
|
||||
dst->n3_incoming = src->n3_incoming;
|
||||
/* QoS handling */
|
||||
DevAssert(!dst->qos.data);
|
||||
DevAssert(src->nb_qos < QOSFLOW_MAX_VALUE);
|
||||
// Initialise mapped QoS list per PDU Session
|
||||
seq_arr_init(&dst->qos, sizeof(nr_rrc_qos_t));
|
||||
// Add QoS flow to list
|
||||
for (uint8_t i = 0; i < src->nb_qos; ++i) {
|
||||
if (!add_qos(&dst->qos, &src->qos[i])) {
|
||||
LOG_E(NR_RRC, "Failed to add QoS flow %d for PDU session %d\n", src->qos[i].qfi, dst->pdusession_id);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief Copy NGAP PDU Session Resource item to RRC pdusession_t struct */
|
||||
/** @brief Copy NGAP PDU Session Resource item to RRC pdusession_t struct to setup */
|
||||
static void cp_pdusession_resource_item_to_pdusession(pdusession_t *dst, const pdusession_resource_item_t *src)
|
||||
{
|
||||
dst->pdusession_id = src->pdusession_id;
|
||||
dst->nas_pdu = src->nas_pdu;
|
||||
dst->nssai = src->nssai;
|
||||
|
||||
// Use the PDU session transfer function to handle QoS and other PDU session transfer-specific fields
|
||||
cp_pdusession_transfer_to_pdusession(dst, &src->pdusessionTransfer);
|
||||
}
|
||||
|
||||
@@ -343,11 +353,10 @@ bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession
|
||||
*cellGroup = MCG;
|
||||
}
|
||||
|
||||
drb->numQosFlow2Setup = session->nb_qos;
|
||||
for (int k=0; k < drb->numQosFlow2Setup; k++) {
|
||||
qos_flow_to_setup_t *qos_flow = drb->qosFlows + k;
|
||||
pdusession_level_qos_parameter_t *qos_session = session->qos + k;
|
||||
|
||||
FOR_EACH_SEQ_ARR(nr_rrc_qos_t *, qos, &session->qos) {
|
||||
pdusession_level_qos_parameter_t *qos_session = &qos->qos;
|
||||
DevAssert(drb->numQosFlow2Setup < QOSFLOW_MAX_VALUE);
|
||||
qos_flow_to_setup_t *qos_flow = &drb->qosFlows[drb->numQosFlow2Setup++];
|
||||
qos_characteristics_t *qos_char = &qos_flow->qos_params.qos_characteristics;
|
||||
qos_flow->qfi = qos_session->qfi;
|
||||
qos_char->qos_type = qos_session->fiveQI_type;
|
||||
@@ -505,10 +514,11 @@ static pdusession_setup_t fill_ngap_pdusession_setup(pdusession_t *session)
|
||||
out.pdusession_id = session->pdusession_id;
|
||||
out.pdu_session_type = session->pdu_session_type;
|
||||
out.n3_outgoing = cp_gtp_tunnel(session->n3_outgoing);
|
||||
out.nb_of_qos_flow = session->nb_qos;
|
||||
for (int q = 0; q < session->nb_qos; q++) {
|
||||
out.associated_qos_flows[q].qfi = session->qos[q].qfi;
|
||||
out.associated_qos_flows[q].qos_flow_mapping_ind = QOSFLOW_MAPPING_INDICATION_DL;
|
||||
FOR_EACH_SEQ_ARR(nr_rrc_qos_t *, qos_session, &session->qos) {
|
||||
DevAssert(out.nb_of_qos_flow < QOSFLOW_MAX_VALUE);
|
||||
pdusession_associate_qosflow_t *q = &out.associated_qos_flows[out.nb_of_qos_flow++];
|
||||
q->qfi = qos_session->qos.qfi;
|
||||
q->qos_flow_mapping_ind = QOSFLOW_MAPPING_INDICATION_DL;
|
||||
}
|
||||
char ip_str[INET_ADDRSTRLEN] = {0};
|
||||
inet_ntop(AF_INET, out.n3_outgoing.addr.buffer, ip_str, sizeof(ip_str));
|
||||
@@ -868,6 +878,36 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief Update existing QoS Flow mapped in the UE context */
|
||||
static void nr_rrc_update_qos(seq_arr_t *list, const int nb_qos, const pdusession_level_qos_parameter_t *in_qos)
|
||||
{
|
||||
DevAssert(nb_qos == 1);
|
||||
DevAssert(nb_qos < QOSFLOW_MAX_VALUE);
|
||||
for (uint8_t i = 0; i < nb_qos; ++i) {
|
||||
nr_rrc_qos_t *qos = find_qos(list, in_qos[i].qfi);
|
||||
if (qos) {
|
||||
AssertFatal(qos->qos.qfi == in_qos[i].qfi, "QoS Flow to modify must match existing one");
|
||||
LOG_I(NR_RRC, "Updating QoS for QFI=%d\n", in_qos[i].qfi);
|
||||
qos->qos = in_qos[i];
|
||||
} else {
|
||||
LOG_E(NR_RRC, "Failed to update QoS for QFI=%d: QoS flow not found\n", in_qos[i].qfi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief Update stored pdusession_t in list from NGAP PDU Session Resource item */
|
||||
static void nr_rrc_update_pdusession(pdusession_t *dst, const pdusession_resource_item_t *src)
|
||||
{
|
||||
dst->pdusession_id = src->pdusession_id;
|
||||
dst->nas_pdu = src->nas_pdu;
|
||||
dst->pdu_session_type = src->pdusessionTransfer.pdu_session_type;
|
||||
dst->n3_incoming = src->pdusessionTransfer.n3_incoming;
|
||||
dst->nssai = src->nssai;
|
||||
DevAssert(dst->qos.data); // QoS list has to be initialized at this stage
|
||||
// Update QoS flow
|
||||
nr_rrc_update_qos(&dst->qos, src->pdusessionTransfer.nb_qos, src->pdusessionTransfer.qos);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(MessageDef *msg_p, instance_t instance)
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -900,7 +940,7 @@ int rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(MessageDef *msg_p, instance_t ins
|
||||
all_failed = false;
|
||||
session->status = PDU_SESSION_STATUS_NEW;
|
||||
session->cause.type = NGAP_CAUSE_NOTHING;
|
||||
cp_pdusession_resource_item_to_pdusession(&session->param, sessMod);
|
||||
nr_rrc_update_pdusession(&session->param, sessMod);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -969,20 +1009,20 @@ int rrc_gNB_send_NGAP_PDUSESSION_MODIFY_RESP(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE
|
||||
session->cause.type = NGAP_CAUSE_NOTHING;
|
||||
// Fill response
|
||||
DevAssert(pdu_sessions_done < NGAP_MAX_PDU_SESSION);
|
||||
resp->pdusessions[pdu_sessions_done].pdusession_id = session->param.pdusession_id;
|
||||
for (int qos_flow_index = 0; qos_flow_index < session->param.nb_qos; qos_flow_index++) {
|
||||
resp->pdusessions[pdu_sessions_done].qos[qos_flow_index].qfi = session->param.qos[qos_flow_index].qfi;
|
||||
pdusession_modify_t *p = &resp->pdusessions[pdu_sessions_done++];
|
||||
p->pdusession_id = session->param.pdusession_id;
|
||||
FOR_EACH_SEQ_ARR(nr_rrc_qos_t *, qos_session, &session->param.qos) {
|
||||
DevAssert(p->nb_of_qos_flow < QOSFLOW_MAX_VALUE);
|
||||
qos_flow_tobe_modified_t *q = &p->qos[p->nb_of_qos_flow++];
|
||||
q->qfi = qos_session->qos.qfi;
|
||||
}
|
||||
resp->pdusessions[pdu_sessions_done].pdusession_id = session->param.pdusession_id;
|
||||
resp->pdusessions[pdu_sessions_done].nb_of_qos_flow = session->param.nb_qos;
|
||||
LOG_I(NR_RRC,
|
||||
"Modify Resp (msg index %d, status %d, xid %d): nb_of_pduSessions %ld, pdusession_id %d \n ",
|
||||
pdu_sessions_done,
|
||||
session->status,
|
||||
xid,
|
||||
seq_arr_size(&UE->pduSessions),
|
||||
resp->pdusessions[pdu_sessions_done].pdusession_id);
|
||||
pdu_sessions_done++;
|
||||
p->pdusession_id);
|
||||
} else if ((session->status == PDU_SESSION_STATUS_NEW) || (session->status == PDU_SESSION_STATUS_ESTABLISHED)) {
|
||||
LOG_D(NR_RRC, "PDU SESSION is NEW or already ESTABLISHED\n");
|
||||
} else if (session->status == PDU_SESSION_STATUS_FAILED) {
|
||||
@@ -1373,10 +1413,11 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUEST_ACKNOWLEDGE(gNB_RRC_INST *rrc, gNB_RRC_U
|
||||
transfer->gtp_teid = session->param.n3_outgoing.teid;
|
||||
memcpy(transfer->gNB_addr.buffer, session->param.n3_outgoing.addr.buffer, session->param.n3_outgoing.addr.length);
|
||||
transfer->gNB_addr.length = session->param.n3_outgoing.addr.length;
|
||||
transfer->nb_of_qos_flow = session->param.nb_qos;
|
||||
for (int q = 0; q < transfer->nb_of_qos_flow; q++) {
|
||||
transfer->qos_setup_list[q].qfi = session->param.qos[q].qfi;
|
||||
transfer->qos_setup_list[q].qos_flow_mapping_ind = QOSFLOW_MAPPING_INDICATION_DL;
|
||||
FOR_EACH_SEQ_ARR(nr_rrc_qos_t *, qos, &session->param.qos) {
|
||||
DevAssert(transfer->nb_of_qos_flow < QOSFLOW_MAX_VALUE);
|
||||
pdusession_associate_qosflow_t *qos_setup = &transfer->qos_setup_list[transfer->nb_of_qos_flow++];
|
||||
qos_setup->qfi = qos->qos.qfi;
|
||||
qos_setup->qos_flow_mapping_ind = QOSFLOW_MAPPING_INDICATION_DL;
|
||||
}
|
||||
}
|
||||
// Target to Source Transparent Container
|
||||
@@ -1620,9 +1661,10 @@ void rrc_gNB_send_NGAP_HANDOVER_REQUIRED(gNB_RRC_INST *rrc,
|
||||
DevAssert(msg.source2target->nb_pdu_session_resource < NGAP_MAX_PDU_SESSION);
|
||||
pdusession_resource_info_t *pdu_info = &msg.source2target->pdu_session_resource[msg.source2target->nb_pdu_session_resource++];
|
||||
pdu_info->pdusession_id = session->pdusession_id;
|
||||
pdu_info->nb_of_qos_flow = session->nb_qos;
|
||||
for (int j = 0; j < pdu_info->nb_of_qos_flow; ++j) {
|
||||
pdu_info->qos_flow_info[j].qfi = session->qos[j].qfi;
|
||||
FOR_EACH_SEQ_ARR(nr_rrc_qos_t *, qos, &session->qos) {
|
||||
DevAssert(pdu_info->nb_of_qos_flow < QOSFLOW_MAX_VALUE);
|
||||
qosflow_info_t *qos_flow = &pdu_info->qos_flow_info[pdu_info->nb_of_qos_flow++];
|
||||
qos_flow->qfi = qos->qos.qfi;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -77,11 +77,8 @@ static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_
|
||||
rrc_pdu_session_param_t *pdu = find_pduSession_from_drbId(ue, rrc_drb->drb_id);
|
||||
AssertFatal(pdu != NULL, "no PDU session for DRB ID %d\n", rrc_drb->drb_id);
|
||||
|
||||
// for the moment, we only support one QoS flow. Put a reminder in case
|
||||
// this changes
|
||||
AssertFatal(pdu->param.nb_qos == 1, "only 1 Qos flow supported\n");
|
||||
int qfi = rrc_drb->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[0];
|
||||
pdusession_level_qos_parameter_t *qos_param = get_qos_characteristics(qfi, pdu);
|
||||
nr_rrc_qos_t *qos_param = find_qos(&pdu->param.qos, qfi);
|
||||
|
||||
drb->id = rrc_drb->drb_id;
|
||||
|
||||
@@ -91,7 +88,7 @@ static int fill_drb_to_be_setup(const gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue, f1ap_
|
||||
drb->nr.flows = calloc_or_fail(1, sizeof(*drb->nr.flows));
|
||||
DevAssert(qfi > 0);
|
||||
drb->nr.flows[0].qfi = qfi;
|
||||
drb->nr.flows[0].param = get_qos_char_from_qos_flow_param(qos_param);
|
||||
drb->nr.flows[0].param = get_qos_char_from_qos_flow_param(&qos_param->qos);
|
||||
/* the DRB QoS parameters: we just reuse the ones from the first flow */
|
||||
drb->nr.drb_qos = drb->nr.flows[0].param;
|
||||
|
||||
|
||||
@@ -33,6 +33,61 @@
|
||||
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_asn1_utils.h"
|
||||
#include "common/utils/alg/find.h"
|
||||
|
||||
static bool eq_qfi(const void *vval, const void *vit)
|
||||
{
|
||||
const int id = *(const int *)vval;
|
||||
const nr_rrc_qos_t *elem = (const nr_rrc_qos_t *)vit;
|
||||
return elem->qos.qfi == id;
|
||||
}
|
||||
|
||||
/** @brief Retrieves mapped QoS in UE context for the input @param qfi
|
||||
* @return pointer to the found QoS, NULL if not found */
|
||||
nr_rrc_qos_t *find_qos(seq_arr_t *seq, int qfi)
|
||||
{
|
||||
DevAssert(seq);
|
||||
elm_arr_t elm = find_if(seq, &qfi, eq_qfi);
|
||||
if (elm.found)
|
||||
return (nr_rrc_qos_t *)elm.it;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** @brief Adds a new QoS @param in to UE context the list
|
||||
* @note A UE can have up to 64 QoS flows which can be multiplexed
|
||||
* into one or more DRBs. The QFI is the unique ID of the mapping.
|
||||
* @return pointer to the newly added QoS */
|
||||
nr_rrc_qos_t *add_qos(seq_arr_t *qos, const pdusession_level_qos_parameter_t *in)
|
||||
{
|
||||
DevAssert(qos);
|
||||
DevAssert(in);
|
||||
|
||||
if (seq_arr_size(qos) == QOSFLOW_MAX_VALUE) {
|
||||
LOG_W(NR_RRC, "Reached maximum number of QoS flows = %ld\n", seq_arr_size(qos));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nr_rrc_qos_t item = {.qos = *in};
|
||||
seq_arr_push_back(qos, &item, sizeof(nr_rrc_qos_t));
|
||||
|
||||
// Double check successful add
|
||||
nr_rrc_qos_t *added = find_qos(qos, in->qfi);
|
||||
DevAssert(added);
|
||||
LOG_I(NR_RRC, "Added QoS flow with qfi=%d, total number of QoS flows = %ld\n", in->qfi, seq_arr_size(qos));
|
||||
|
||||
// Only one QoS flow is supported
|
||||
AssertFatal(seq_arr_size(qos) == 1, "only 1 Qos flow supported\n");
|
||||
|
||||
return added;
|
||||
}
|
||||
|
||||
/** @brief Free QoS flows list items */
|
||||
static void free_qos(void *ptr) { /*nothing to do*/ }
|
||||
|
||||
/** @brief Free QoS flows list */
|
||||
static void free_rrc_qos_list(seq_arr_t *seq)
|
||||
{
|
||||
seq_arr_free(seq, free_qos);
|
||||
}
|
||||
|
||||
static bool eq_pdu_session_id(const void *vval, const void *vit)
|
||||
{
|
||||
const int id = *(const int *)vval;
|
||||
@@ -44,6 +99,7 @@ static bool eq_pdu_session_id(const void *vval, const void *vit)
|
||||
void free_pdusession(void *ptr)
|
||||
{
|
||||
rrc_pdu_session_param_t *elem = ptr;
|
||||
free_rrc_qos_list(&elem->param.qos);
|
||||
free_byte_array(elem->param.nas_pdu);
|
||||
}
|
||||
|
||||
@@ -210,8 +266,11 @@ drb_t *generateDRB(gNB_RRC_UE_t *ue,
|
||||
est_drb->cnAssociation.sdap_config.sdap_HeaderDL = NR_SDAP_Config__sdap_HeaderDL_absent;
|
||||
est_drb->cnAssociation.sdap_config.sdap_HeaderUL = NR_SDAP_Config__sdap_HeaderUL_absent;
|
||||
}
|
||||
for (int qos_flow_index = 0; qos_flow_index < pduSession->nb_qos; qos_flow_index++) {
|
||||
est_drb->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[qos_flow_index] = pduSession->qos[qos_flow_index].qfi;
|
||||
int qos_flow_index = 0;
|
||||
FOR_EACH_SEQ_ARR(nr_rrc_qos_t *, qos_session, &pduSession->qos) {
|
||||
qos_session->drb_id = est_drb->drb_id; // Map DRB to QoS
|
||||
est_drb->cnAssociation.sdap_config.mappedQoS_FlowsToAdd[qos_flow_index++] = qos_session->qos.qfi;
|
||||
DevAssert(qos_flow_index <= QOSFLOW_MAX_VALUE);
|
||||
}
|
||||
/* PDCP Configuration */
|
||||
set_default_drb_pdcp_config(&est_drb->pdcp_config, do_drb_integrity, do_drb_ciphering, pdcp_config, ue->redcap_cap);
|
||||
|
||||
@@ -72,4 +72,10 @@ drb_t *nr_rrc_add_drb(seq_arr_t *drb_ptr, int pdusession_id);
|
||||
/// @brief Function to free DRB in RRC
|
||||
void free_drb(void *ptr);
|
||||
|
||||
/// @brief retrieve QoS flow associated to @param qfi
|
||||
nr_rrc_qos_t *find_qos(seq_arr_t *seq, int qfi);
|
||||
|
||||
/// @brief Add a new QoS to the list
|
||||
nr_rrc_qos_t *add_qos(seq_arr_t *qos, const pdusession_level_qos_parameter_t *in);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user