F1AP and E1AP interface changes for QoS

- Implement: Extend the F1 encoding and decoding with Qos
- Implement: E1 decoding for QoS
- Fix: Modify the UE_MODIFICATION_REQUEST_MSG towards DU to contain QoS info based on E1AP context response
- Fix: Modify the E1AP and F1AP message structures
- Fill the Qos configuration to send to MAC
This commit is contained in:
Sriharsha Korada
2023-11-30 17:41:12 +01:00
parent 6debc5dd21
commit ed29252c6d
12 changed files with 441 additions and 120 deletions
+40 -3
View File
@@ -2027,6 +2027,17 @@ unsigned int mask_flip(unsigned int x) {
return((((x>>8) + (x<<8))&0xffff)>>6);
}
static 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;
}
void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp, instance_t instance)
{
gNB_RRC_INST *rrc = RC.nrrrc[0];
@@ -2060,12 +2071,34 @@ void rrc_gNB_process_e1_bearer_context_setup_resp(e1ap_bearer_setup_resp_t *resp
rrc_pdu_session_param_t *RRC_pduSession = find_pduSession(UE, resp->pduSession[0].id, false);
DevAssert(RRC_pduSession);
for (int i = 0; i < nb_drb; i++) {
DRB_nGRAN_setup_t *drb_config = &resp->pduSession[0].DRBnGRanList[i];
drbs[i].drb_id = resp->pduSession[0].DRBnGRanList[i].id;
drbs[i].rlc_mode = rrc->configuration.um_on_default_drb ? RLC_MODE_UM : RLC_MODE_AM;
drbs[i].up_ul_tnl[0].tl_address = resp->pduSession[0].DRBnGRanList[i].UpParamList[0].tlAddress;
drbs[i].up_ul_tnl[0].tl_address = drb_config->UpParamList[0].tlAddress;
drbs[i].up_ul_tnl[0].port = rrc->eth_params_s.my_portd;
drbs[i].up_ul_tnl[0].teid = resp->pduSession[0].DRBnGRanList[i].UpParamList[0].teId;
drbs[i].up_ul_tnl[0].teid = drb_config->UpParamList[0].teId;
drbs[i].up_ul_tnl_length = 1;
/* pass QoS info to MAC */
int nb_qos_flows = drb_config->numQosFlowSetup;
drbs[i].drb_info.flows_to_be_setup_length = nb_qos_flows;
drbs[i].drb_info.flows_mapped_to_drb = (f1ap_flows_mapped_to_drb_t *)calloc(nb_qos_flows, sizeof(f1ap_flows_mapped_to_drb_t));
AssertFatal(drbs[i].drb_info.flows_mapped_to_drb, "could not allocate memory\n");
for (int j = 0; j < nb_qos_flows; j++) {
drbs[i].drb_info.flows_mapped_to_drb[j].qfi = drb_config->qosFlows[j].qfi;
pdusession_level_qos_parameter_t *in_qos_char = get_qos_characteristics(drb_config->qosFlows[j].qfi, RRC_pduSession);
f1ap_qos_characteristics_t *qos_char = &drbs[i].drb_info.flows_mapped_to_drb[j].qos_params.qos_characteristics;
if (in_qos_char->fiveQI_type == dynamic) {
qos_char->qos_type = dynamic;
qos_char->dynamic.fiveqi = in_qos_char->fiveQI;
qos_char->dynamic.qos_priority_level = in_qos_char->qos_priority;
} else {
qos_char->qos_type = non_dynamic;
qos_char->non_dynamic.fiveqi = in_qos_char->fiveQI;
qos_char->non_dynamic.qos_priority_level = in_qos_char->qos_priority;
}
}
/* pass NSSAI info to MAC */
drbs[i].nssai = RRC_pduSession->param.nssai;
}
@@ -2261,7 +2294,11 @@ void *rrc_gnb_task(void *args_p) {
itti_receive_msg(TASK_RRC_GNB, &msg_p);
const char *msg_name_p = ITTI_MSG_NAME(msg_p);
instance = ITTI_MSG_DESTINATION_INSTANCE(msg_p);
LOG_D(NR_RRC, "Received Msg %s\n", msg_name_p);
LOG_D(NR_RRC,
"RRC GNB Task Received %s for instance %ld from task %s\n",
ITTI_MSG_NAME(msg_p),
ITTI_MSG_DESTINATION_INSTANCE(msg_p),
ITTI_MSG_ORIGIN_NAME(msg_p));
switch (ITTI_MSG_ID(msg_p)) {
case TERMINATE_MESSAGE:
LOG_W(NR_RRC, " *** Exiting NR_RRC thread\n");
+34 -15
View File
@@ -68,6 +68,7 @@
#include "NGAP_QosFlowSetupRequestItem.h"
#include "NGAP_QosFlowAddOrModifyRequestItem.h"
#include "NGAP_NonDynamic5QIDescriptor.h"
#include "NGAP_Dynamic5QIDescriptor.h"
#include "conversions.h"
#include "RRC/NR/rrc_gNB_radio_bearers.h"
@@ -263,10 +264,15 @@ static void fill_qos(NGAP_QosFlowSetupRequestList_t *qos, pdusession_t *session)
// Set the QOS informations
session->qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier;
NGAP_QosCharacteristics_t *qosChar = &qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics;
AssertFatal(qosChar, "Qos characteristics are not available for qos flow index %d\n", qosIdx);
if (qosChar->present == NGAP_QosCharacteristics_PR_nonDynamic5QI) {
if (qosChar->choice.nonDynamic5QI != NULL) {
session->qos[qosIdx].fiveQI = (uint64_t)qosChar->choice.nonDynamic5QI->fiveQI;
}
AssertFatal(qosChar->choice.dynamic5QI, "Non-Dynamic 5QI is NULL\n");
session->qos[qosIdx].fiveQI_type = non_dynamic;
session->qos[qosIdx].fiveQI = (uint64_t)qosChar->choice.nonDynamic5QI->fiveQI;
} else {
AssertFatal(qosChar->choice.dynamic5QI, "Dynamic 5QI is NULL\n");
session->qos[qosIdx].fiveQI_type = dynamic;
session->qos[qosIdx].fiveQI = (uint64_t)(*qosChar->choice.dynamic5QI->fiveQI);
}
ngap_allocation_retention_priority_t *tmp = &session->qos[qosIdx].allocation_retention_priority;
@@ -820,15 +826,25 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins
drb->numQosFlow2Setup = session->nb_qos;
for (int k=0; k < drb->numQosFlow2Setup; k++) {
qos_flow_to_setup_t *qos = drb->qosFlows + k;
qos_flow_to_setup_t *qos_flow = drb->qosFlows + k;
pdusession_level_qos_parameter_t *qos_session = session->qos + k;
qos->id = session->qos[k].qfi;
qos->fiveQI = session->qos[k].fiveQI;
qos->fiveQI_type = session->qos[k].fiveQI_type;
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;
if (qos_char->qos_type == dynamic) {
qos_char->dynamic.fiveqi = qos_session->fiveQI;
qos_char->dynamic.qos_priority_level = qos_session->qos_priority;
} else {
qos_char->non_dynamic.fiveqi = qos_session->fiveQI;
qos_char->non_dynamic.qos_priority_level = qos_session->qos_priority;
}
qos->qoSPriorityLevel = session->qos[k].allocation_retention_priority.priority_level;
qos->pre_emptionCapability = session->qos[k].allocation_retention_priority.pre_emp_capability;
qos->pre_emptionVulnerability = session->qos[k].allocation_retention_priority.pre_emp_vulnerability;
ngran_allocation_retention_priority_t *rent_priority = &qos_flow->qos_params.alloc_reten_priority;
ngap_allocation_retention_priority_t *rent_priority_in = &qos_session->allocation_retention_priority;
rent_priority->priority_level = rent_priority_in->priority_level;
rent_priority->preemption_capability = rent_priority_in->pre_emp_capability;
rent_priority->preemption_vulnerability = rent_priority_in->pre_emp_vulnerability;
}
}
}
@@ -854,12 +870,15 @@ static void fill_qos2(NGAP_QosFlowAddOrModifyRequestList_t *qos, pdusession_t *s
// Set the QOS informations
session->qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier;
NGAP_QosCharacteristics_t *qosChar = &qosFlowItem_p->qosFlowLevelQosParameters->qosCharacteristics;
AssertFatal(qosChar, "Qos characteristics are not available for qos flow index %d\n", qosIdx);
if (qosChar->present == NGAP_QosCharacteristics_PR_nonDynamic5QI) {
if (qosChar->choice.nonDynamic5QI != NULL) {
session->qos[qosIdx].fiveQI = (uint64_t)qosChar->choice.nonDynamic5QI->fiveQI;
}
} else if (qosChar->present == NGAP_QosCharacteristics_PR_dynamic5QI) {
// TODO
AssertFatal(qosChar->choice.dynamic5QI, "Non-Dynamic 5QI is NULL\n");
session->qos[qosIdx].fiveQI_type = non_dynamic;
session->qos[qosIdx].fiveQI = (uint64_t)qosChar->choice.nonDynamic5QI->fiveQI;
} else {
AssertFatal(qosChar->choice.dynamic5QI, "Dynamic 5QI is NULL\n");
session->qos[qosIdx].fiveQI_type = dynamic;
session->qos[qosIdx].fiveQI = (uint64_t)(*qosChar->choice.dynamic5QI->fiveQI);
}
ngap_allocation_retention_priority_t *tmp = &session->qos[qosIdx].allocation_retention_priority;