Commit ed29252c authored by Sriharsha Korada's avatar Sriharsha Korada

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
parent 6debc5dd
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#define NR_NB_REG_PER_CCE 6 #define NR_NB_REG_PER_CCE 6
#define NR_NB_SC_PER_RB 12 #define NR_NB_SC_PER_RB 12
#define NR_MAX_NUM_LCID 32 #define NR_MAX_NUM_LCID 32
#define NR_MAX_NUM_QFI 64
typedef enum { typedef enum {
nr_FR1 = 0, nr_FR1 = 0,
......
...@@ -118,17 +118,39 @@ typedef struct drb_to_setup_s { ...@@ -118,17 +118,39 @@ typedef struct drb_to_setup_s {
cell_group_t cellGroupList[E1AP_MAX_NUM_CELL_GROUPS]; cell_group_t cellGroupList[E1AP_MAX_NUM_CELL_GROUPS];
} drb_to_setup_t; } drb_to_setup_t;
typedef struct qos_flow_to_setup_s { typedef struct qos_characteristics_s {
long id; union {
fiveQI_type_t fiveQI_type; struct {
long fiveQI; long fiveqi;
long qoSPriorityLevel; long qos_priority_level;
long packetDelayBudget; } non_dynamic;
long packetError_scalar; struct {
long packetError_exponent; long fiveqi; // -1 -> optional
long priorityLevel; long qos_priority_level;
long pre_emptionCapability; long packet_delay_budget;
long pre_emptionVulnerability; struct {
long per_scalar;
long per_exponent;
} packet_error_rate;
} dynamic;
};
fiveQI_type_t qos_type;
} qos_characteristics_t;
typedef struct ngran_allocation_retention_priority_s {
uint16_t priority_level;
long preemption_capability;
long preemption_vulnerability;
} ngran_allocation_retention_priority_t;
typedef struct qos_flow_level_qos_parameters_s {
qos_characteristics_t qos_characteristics;
ngran_allocation_retention_priority_t alloc_reten_priority; // additional members should be added!!
} qos_flow_level_qos_parameters_t;
typedef struct qos_flow_setup_e {
long qfi; // qos flow identifier
qos_flow_level_qos_parameters_t qos_params;
} qos_flow_to_setup_t; } qos_flow_to_setup_t;
typedef struct DRB_nGRAN_to_setup_s { typedef struct DRB_nGRAN_to_setup_s {
...@@ -198,7 +220,7 @@ typedef struct e1ap_bearer_release_cplt_s { ...@@ -198,7 +220,7 @@ typedef struct e1ap_bearer_release_cplt_s {
} e1ap_bearer_release_cplt_t; } e1ap_bearer_release_cplt_t;
typedef struct qos_flow_setup_s { typedef struct qos_flow_setup_s {
long id; long qfi;
} qos_flow_setup_t; } qos_flow_setup_t;
typedef struct DRB_nGRAN_setup_s { typedef struct DRB_nGRAN_setup_s {
......
...@@ -284,12 +284,64 @@ typedef struct f1ap_up_tnl_s { ...@@ -284,12 +284,64 @@ typedef struct f1ap_up_tnl_s {
uint16_t port; uint16_t port;
} f1ap_up_tnl_t; } f1ap_up_tnl_t;
typedef enum preemption_capability_e {
SHALL_NOT_TRIGGER_PREEMPTION,
MAY_TRIGGER_PREEMPTION,
} preemption_capability_t;
typedef enum preemption_vulnerability_e {
NOT_PREEMPTABLE,
PREEMPTABLE,
} preemption_vulnerability_t;
typedef struct f1ap_qos_characteristics_s {
union {
struct {
long fiveqi;
long qos_priority_level;
} non_dynamic;
struct {
long fiveqi; // -1 -> optional
long qos_priority_level;
long packet_delay_budget;
struct {
long per_scalar;
long per_exponent;
} packet_error_rate;
} dynamic;
};
fiveQI_type_t qos_type;
} f1ap_qos_characteristics_t;
typedef struct f1ap_ngran_allocation_retention_priority_s {
uint16_t priority_level;
preemption_capability_t preemption_capability;
preemption_vulnerability_t preemption_vulnerability;
} f1ap_ngran_allocation_retention_priority_t;
typedef struct f1ap_qos_flow_level_qos_parameters_s {
f1ap_qos_characteristics_t qos_characteristics;
f1ap_ngran_allocation_retention_priority_t alloc_reten_priority;
} f1ap_qos_flow_level_qos_parameters_t;
typedef struct f1ap_flows_mapped_to_drb_s {
long qfi; // qos flow identifier
f1ap_qos_flow_level_qos_parameters_t qos_params;
} f1ap_flows_mapped_to_drb_t;
typedef struct f1ap_drb_information_s {
f1ap_qos_flow_level_qos_parameters_t drb_qos;
f1ap_flows_mapped_to_drb_t *flows_mapped_to_drb;
uint8_t flows_to_be_setup_length;
} f1ap_drb_information_t;
typedef struct f1ap_drb_to_be_setup_s { typedef struct f1ap_drb_to_be_setup_s {
long drb_id; long drb_id;
f1ap_up_tnl_t up_ul_tnl[2]; f1ap_up_tnl_t up_ul_tnl[2];
uint8_t up_ul_tnl_length; uint8_t up_ul_tnl_length;
f1ap_up_tnl_t up_dl_tnl[2]; f1ap_up_tnl_t up_dl_tnl[2];
uint8_t up_dl_tnl_length; uint8_t up_dl_tnl_length;
f1ap_drb_information_t drb_info;
rlc_mode_t rlc_mode; rlc_mode_t rlc_mode;
nssai_t nssai; nssai_t nssai;
} f1ap_drb_to_be_setup_t; } f1ap_drb_to_be_setup_t;
......
...@@ -150,14 +150,14 @@ typedef enum ngap_priority_level_s { ...@@ -150,14 +150,14 @@ typedef enum ngap_priority_level_s {
} ngap_priority_level_t; } ngap_priority_level_t;
typedef enum ngap_pre_emp_capability_e { typedef enum ngap_pre_emp_capability_e {
NGAP_PRE_EMPTION_CAPABILITY_ENABLED = 0, NGAP_PRE_EMPTION_CAPABILITY_SHALL_NOT_TRIGGER_PREEMPTION = 0,
NGAP_PRE_EMPTION_CAPABILITY_DISABLED = 1, NGAP_PRE_EMPTION_CAPABILITY_MAY_TRIGGER_PREEMPTION = 1,
NGAP_PRE_EMPTION_CAPABILITY_MAX, NGAP_PRE_EMPTION_CAPABILITY_MAX,
} ngap_pre_emp_capability_t; } ngap_pre_emp_capability_t;
typedef enum ngap_pre_emp_vulnerability_e { typedef enum ngap_pre_emp_vulnerability_e {
NGAP_PRE_EMPTION_VULNERABILITY_ENABLED = 0, NGAP_PRE_EMPTION_VULNERABILITY_NOT_PREEMPTABLE = 0,
NGAP_PRE_EMPTION_VULNERABILITY_DISABLED = 1, NGAP_PRE_EMPTION_VULNERABILITY_PREEMPTABLE = 1,
NGAP_PRE_EMPTION_VULNERABILITY_MAX, NGAP_PRE_EMPTION_VULNERABILITY_MAX,
} ngap_pre_emp_vulnerability_t; } ngap_pre_emp_vulnerability_t;
...@@ -202,6 +202,7 @@ typedef struct nssai_s { ...@@ -202,6 +202,7 @@ typedef struct nssai_s {
typedef struct pdusession_level_qos_parameter_s { typedef struct pdusession_level_qos_parameter_s {
uint8_t qfi; uint8_t qfi;
uint64_t fiveQI; uint64_t fiveQI;
uint64_t qos_priority;
fiveQI_type_t fiveQI_type; fiveQI_type_t fiveQI_type;
ngap_allocation_retention_priority_t allocation_retention_priority; ngap_allocation_retention_priority_t allocation_retention_priority;
} pdusession_level_qos_parameter_t; } pdusession_level_qos_parameter_t;
......
...@@ -655,24 +655,28 @@ static int fill_BEARER_CONTEXT_SETUP_REQUEST(e1ap_bearer_setup_req_t *const bear ...@@ -655,24 +655,28 @@ static int fill_BEARER_CONTEXT_SETUP_REQUEST(e1ap_bearer_setup_req_t *const bear
for (qos_flow_to_setup_t *k=j->qosFlows; k < j->qosFlows+j->numQosFlow2Setup; k++) { for (qos_flow_to_setup_t *k=j->qosFlows; k < j->qosFlows+j->numQosFlow2Setup; k++) {
asn1cSequenceAdd(ieC6_1_1->qos_flow_Information_To_Be_Setup, E1AP_QoS_Flow_QoS_Parameter_Item_t, ieC6_1_1_1); asn1cSequenceAdd(ieC6_1_1->qos_flow_Information_To_Be_Setup, E1AP_QoS_Flow_QoS_Parameter_Item_t, ieC6_1_1_1);
ieC6_1_1_1->qoS_Flow_Identifier = k->id; ieC6_1_1_1->qoS_Flow_Identifier = k->qfi;
if (k->fiveQI_type == non_dynamic) { // non Dynamic 5QI qos_characteristics_t *qos_char_in = &k->qos_params.qos_characteristics;
if (qos_char_in->qos_type == non_dynamic) { // non Dynamic 5QI
ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.present = E1AP_QoS_Characteristics_PR_non_Dynamic_5QI; ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.present = E1AP_QoS_Characteristics_PR_non_Dynamic_5QI;
asn1cCalloc(ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.non_Dynamic_5QI, non_Dynamic_5QI); asn1cCalloc(ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.non_Dynamic_5QI, non_Dynamic_5QI);
non_Dynamic_5QI->fiveQI = k->fiveQI; non_Dynamic_5QI->fiveQI = qos_char_in->non_dynamic.fiveqi;
} else { // dynamic 5QI } else { // dynamic 5QI
ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.present = E1AP_QoS_Characteristics_PR_dynamic_5QI; ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.present = E1AP_QoS_Characteristics_PR_dynamic_5QI;
asn1cCalloc(ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.dynamic_5QI, dynamic_5QI); asn1cCalloc(ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.dynamic_5QI, dynamic_5QI);
dynamic_5QI->qoSPriorityLevel = k->qoSPriorityLevel; dynamic_5QI->qoSPriorityLevel = qos_char_in->dynamic.qos_priority_level;
dynamic_5QI->packetDelayBudget = k->packetDelayBudget; dynamic_5QI->packetDelayBudget = qos_char_in->dynamic.packet_delay_budget;
dynamic_5QI->packetErrorRate.pER_Scalar = k->packetError_scalar; dynamic_5QI->packetErrorRate.pER_Scalar = qos_char_in->dynamic.packet_error_rate.per_scalar;
dynamic_5QI->packetErrorRate.pER_Exponent = k->packetError_exponent; dynamic_5QI->packetErrorRate.pER_Exponent = qos_char_in->dynamic.packet_error_rate.per_exponent;
} }
ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.priorityLevel = k->priorityLevel; ngran_allocation_retention_priority_t *rent_priority_in = &k->qos_params.alloc_reten_priority;
ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionCapability = k->pre_emptionCapability; ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.priorityLevel = rent_priority_in->priority_level;
ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionVulnerability = k->pre_emptionVulnerability; ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionCapability =
rent_priority_in->preemption_capability;
ieC6_1_1_1->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionVulnerability =
rent_priority_in->preemption_vulnerability;
} }
} }
} }
...@@ -775,7 +779,7 @@ static void fill_BEARER_CONTEXT_SETUP_RESPONSE(const e1ap_bearer_setup_resp_t *r ...@@ -775,7 +779,7 @@ static void fill_BEARER_CONTEXT_SETUP_RESPONSE(const e1ap_bearer_setup_resp_t *r
for (const qos_flow_setup_t *k=j->qosFlows; k < j->qosFlows+j->numQosFlowSetup; k++) { for (const qos_flow_setup_t *k=j->qosFlows; k < j->qosFlows+j->numQosFlowSetup; k++) {
asn1cSequenceAdd(ieC3_1_1->flow_Setup_List.list, E1AP_QoS_Flow_Item_t, ieC3_1_1_1); asn1cSequenceAdd(ieC3_1_1->flow_Setup_List.list, E1AP_QoS_Flow_Item_t, ieC3_1_1_1);
ieC3_1_1_1->qoS_Flow_Identifier = k->id; ieC3_1_1_1->qoS_Flow_Identifier = k->qfi;
} }
} }
...@@ -953,27 +957,32 @@ void extract_BEARER_CONTEXT_SETUP_REQUEST(const E1AP_E1AP_PDU_t *pdu, ...@@ -953,27 +957,32 @@ void extract_BEARER_CONTEXT_SETUP_REQUEST(const E1AP_E1AP_PDU_t *pdu,
E1AP_QoS_Flow_QoS_Parameter_List_t *qos2SetupList = &drb2Setup->qos_flow_Information_To_Be_Setup; E1AP_QoS_Flow_QoS_Parameter_List_t *qos2SetupList = &drb2Setup->qos_flow_Information_To_Be_Setup;
drb->numQosFlow2Setup = qos2SetupList->list.count; drb->numQosFlow2Setup = qos2SetupList->list.count;
for (int k=0; k < qos2SetupList->list.count; k++) { for (int k=0; k < qos2SetupList->list.count; k++) {
qos_flow_to_setup_t *qos = drb->qosFlows + k; qos_flow_to_setup_t *qos_flow = drb->qosFlows + k;
E1AP_QoS_Flow_QoS_Parameter_Item_t *qos2Setup = qos2SetupList->list.array[k]; E1AP_QoS_Flow_QoS_Parameter_Item_t *qos2Setup = qos2SetupList->list.array[k];
qos->id = qos2Setup->qoS_Flow_Identifier; qos_flow->qfi = qos2Setup->qoS_Flow_Identifier;
qos_characteristics_t *qos_char = &qos_flow->qos_params.qos_characteristics;
if (qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.present == if (qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.present ==
E1AP_QoS_Characteristics_PR_non_Dynamic_5QI) { E1AP_QoS_Characteristics_PR_non_Dynamic_5QI) {
qos->fiveQI_type = non_dynamic; qos_char->qos_type = non_dynamic;
qos->fiveQI = qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.non_Dynamic_5QI->fiveQI; qos_char->non_dynamic.fiveqi =
qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.non_Dynamic_5QI->fiveQI;
} else { } else {
E1AP_Dynamic5QIDescriptor_t *dynamic5QI = qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.dynamic_5QI; E1AP_Dynamic5QIDescriptor_t *dynamic5QI = qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.dynamic_5QI;
qos->fiveQI_type = dynamic; qos_char->qos_type = dynamic;
qos->qoSPriorityLevel = dynamic5QI->qoSPriorityLevel; qos_char->dynamic.qos_priority_level = dynamic5QI->qoSPriorityLevel;
qos->packetDelayBudget = dynamic5QI->packetDelayBudget; qos_char->dynamic.packet_delay_budget = dynamic5QI->packetDelayBudget;
qos->packetError_scalar = dynamic5QI->packetErrorRate.pER_Scalar; qos_char->dynamic.packet_error_rate.per_scalar = dynamic5QI->packetErrorRate.pER_Scalar;
qos->packetError_exponent = dynamic5QI->packetErrorRate.pER_Exponent; qos_char->dynamic.packet_error_rate.per_exponent = dynamic5QI->packetErrorRate.pER_Exponent;
} }
qos->priorityLevel = qos2Setup->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.priorityLevel; ngran_allocation_retention_priority_t *rent_priority = &qos_flow->qos_params.alloc_reten_priority;
qos->pre_emptionCapability = qos2Setup->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionCapability; rent_priority->priority_level = qos2Setup->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.priorityLevel;
qos->pre_emptionVulnerability = qos2Setup->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionVulnerability; rent_priority->preemption_capability =
qos2Setup->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionCapability;
rent_priority->preemption_vulnerability =
qos2Setup->qoSFlowLevelQoSParameters.nGRANallocationRetentionPriority.pre_emptionVulnerability;
} }
} }
} }
...@@ -1076,6 +1085,14 @@ void extract_BEARER_CONTEXT_SETUP_RESPONSE(const E1AP_E1AP_PDU_t *pdu, ...@@ -1076,6 +1085,14 @@ void extract_BEARER_CONTEXT_SETUP_RESPONSE(const E1AP_E1AP_PDU_t *pdu,
AssertFatal(false, "gTPTunnel information in required\n"); AssertFatal(false, "gTPTunnel information in required\n");
} }
} }
// Qos Flow Information
drbSetup->numQosFlowSetup = drb->flow_Setup_List.list.count;
for (int q = 0; q < drb->flow_Setup_List.list.count; q++) {
qos_flow_setup_t *qosflowSetup = &drbSetup->qosFlows[q];
E1AP_QoS_Flow_Item_t *in_qosflowSetup = drb->flow_Setup_List.list.array[q];
qosflowSetup->qfi = in_qosflowSetup->qoS_Flow_Identifier;
}
} }
} }
break; break;
......
...@@ -893,11 +893,99 @@ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, sctp_assoc_t ...@@ -893,11 +893,99 @@ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, sctp_assoc_t
(F1AP_QoSInformation_ExtIEs_t *)drbs_tobesetupmod_item_p->qoSInformation.choice.choice_extension; (F1AP_QoSInformation_ExtIEs_t *)drbs_tobesetupmod_item_p->qoSInformation.choice.choice_extension;
if (ie->id == F1AP_ProtocolIE_ID_id_DRB_Information && ie->criticality == F1AP_Criticality_reject if (ie->id == F1AP_ProtocolIE_ID_id_DRB_Information && ie->criticality == F1AP_Criticality_reject
&& ie->value.present == F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information) { && ie->value.present == F1AP_QoSInformation_ExtIEs__value_PR_DRB_Information) {
F1AP_DRB_Information_t *DRB_Information = &ie->value.choice.DRB_Information; F1AP_DRB_Information_t *dRB_Info = &ie->value.choice.DRB_Information;
f1ap_drb_information_t *drb_info = &f1ap_ue_context_modification_req->drbs_to_be_setup->drb_info;
/* 12.1.2.1 dRB_QoS */
{
/* QoS-Flow-Level-QoS-Parameters */
f1ap_qos_flow_level_qos_parameters_t *drb_qos = &drb_info->drb_qos;
F1AP_QoSFlowLevelQoSParameters_t *dRB_QoS = &dRB_Info->dRB_QoS;
{
/* QoS Characteristics*/
f1ap_qos_characteristics_t *drb_qos_char = &drb_qos->qos_characteristics;
F1AP_QoS_Characteristics_t *dRB_QoS_Char = &dRB_QoS->qoS_Characteristics;
if (dRB_QoS_Char->present == F1AP_QoS_Characteristics_PR_non_Dynamic_5QI) {
drb_qos_char->qos_type = non_dynamic;
drb_qos_char->non_dynamic.fiveqi = dRB_QoS_Char->choice.non_Dynamic_5QI->fiveQI;
drb_qos_char->non_dynamic.qos_priority_level = (dRB_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel != NULL)
? *dRB_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel
: -1;
} else {
drb_qos_char->qos_type = dynamic;
drb_qos_char->dynamic.fiveqi =
(dRB_QoS_Char->choice.dynamic_5QI->fiveQI != NULL) ? *dRB_QoS_Char->choice.dynamic_5QI->fiveQI : -1;
drb_qos_char->dynamic.qos_priority_level = dRB_QoS_Char->choice.dynamic_5QI->qoSPriorityLevel;
drb_qos_char->dynamic.packet_delay_budget = dRB_QoS_Char->choice.dynamic_5QI->packetDelayBudget;
drb_qos_char->dynamic.packet_error_rate.per_scalar = dRB_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Scalar;
drb_qos_char->dynamic.packet_error_rate.per_exponent =
dRB_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Exponent;
}
}
/* nGRANallocationRetentionPriority */
drb_qos->alloc_reten_priority.priority_level = dRB_QoS->nGRANallocationRetentionPriority.priorityLevel;
drb_qos->alloc_reten_priority.preemption_vulnerability =
dRB_QoS->nGRANallocationRetentionPriority.pre_emptionVulnerability;
drb_qos->alloc_reten_priority.preemption_capability =
dRB_QoS->nGRANallocationRetentionPriority.pre_emptionVulnerability;
} // dRB_QoS
// 12.1.2.4 flows_Mapped_To_DRB_List
drb_info->flows_to_be_setup_length = dRB_Info->flows_Mapped_To_DRB_List.list.count;
drb_info->flows_mapped_to_drb = calloc(drb_info->flows_to_be_setup_length, sizeof(f1ap_flows_mapped_to_drb_t));
AssertFatal(drb_info->flows_mapped_to_drb, "could not allocate memory for drb_p->drb_info.flows_mapped_to_drb\n");
for (int k = 0; k < drb_p->drb_info.flows_to_be_setup_length; k++) {
f1ap_flows_mapped_to_drb_t *flows_mapped_to_drb = drb_info->flows_mapped_to_drb + k;
F1AP_Flows_Mapped_To_DRB_Item_t *flows_Mapped_To_Drb = dRB_Info->flows_Mapped_To_DRB_List.list.array[0] + k;
flows_mapped_to_drb->qfi = flows_Mapped_To_Drb->qoSFlowIdentifier;
/* QoS-Flow-Level-QoS-Parameters */
{
f1ap_qos_flow_level_qos_parameters_t *flow_qos = &flows_mapped_to_drb->qos_params;
F1AP_QoSFlowLevelQoSParameters_t *Flow_QoS = &flows_Mapped_To_Drb->qoSFlowLevelQoSParameters;
/* QoS Characteristics*/
{
f1ap_qos_characteristics_t *flow_qos_char = &flow_qos->qos_characteristics;
F1AP_QoS_Characteristics_t *Flow_QoS_Char = &Flow_QoS->qoS_Characteristics;
if (Flow_QoS_Char->present == F1AP_QoS_Characteristics_PR_non_Dynamic_5QI) {
flow_qos_char->qos_type = non_dynamic;
flow_qos_char->non_dynamic.fiveqi = Flow_QoS_Char->choice.non_Dynamic_5QI->fiveQI;
flow_qos_char->non_dynamic.qos_priority_level =
(Flow_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel != NULL)
? *Flow_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel
: -1;
} else {
flow_qos_char->qos_type = dynamic;
flow_qos_char->dynamic.fiveqi =
(Flow_QoS_Char->choice.dynamic_5QI->fiveQI != NULL) ? *Flow_QoS_Char->choice.dynamic_5QI->fiveQI : -1;
flow_qos_char->dynamic.qos_priority_level = Flow_QoS_Char->choice.dynamic_5QI->qoSPriorityLevel;
flow_qos_char->dynamic.packet_delay_budget = Flow_QoS_Char->choice.dynamic_5QI->packetDelayBudget;
flow_qos_char->dynamic.packet_error_rate.per_scalar =
Flow_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Scalar;
flow_qos_char->dynamic.packet_error_rate.per_exponent =
Flow_QoS_Char->choice.dynamic_5QI->packetErrorRate.pER_Exponent;
}
}
/* nGRANallocationRetentionPriority */
flow_qos->alloc_reten_priority.priority_level = Flow_QoS->nGRANallocationRetentionPriority.priorityLevel;
flow_qos->alloc_reten_priority.preemption_vulnerability =
Flow_QoS->nGRANallocationRetentionPriority.pre_emptionVulnerability;
flow_qos->alloc_reten_priority.preemption_capability =
Flow_QoS->nGRANallocationRetentionPriority.pre_emptionVulnerability;
}
}
/* S-NSSAI */ /* S-NSSAI */
OCTET_STRING_TO_INT8(&DRB_Information->sNSSAI.sST, drb_p->nssai.sst); OCTET_STRING_TO_INT8(&dRB_Info->sNSSAI.sST, drb_p->nssai.sst);
if (DRB_Information->sNSSAI.sD != NULL) if (dRB_Info->sNSSAI.sD != NULL)
memcpy((uint8_t *)&drb_p->nssai.sd, DRB_Information->sNSSAI.sD->buf, 3); memcpy((uint8_t *)&drb_p->nssai.sd, dRB_Info->sNSSAI.sD->buf, 3);
else else
drb_p->nssai.sd = 0xffffff; drb_p->nssai.sd = 0xffffff;
} }
......
...@@ -30,6 +30,11 @@ ...@@ -30,6 +30,11 @@
#include "uper_decoder.h" #include "uper_decoder.h"
#include "uper_encoder.h" #include "uper_encoder.h"
// Standarized 5QI values and Default Priority levels as mentioned in 3GPP TS 23.501 Table 5.7.4-1
const uint64_t qos_fiveqi[26] = {1, 2, 3, 4, 65, 66, 67, 71, 72, 73, 74, 76, 5, 6, 7, 8, 9, 69, 70, 79, 80, 82, 83, 84, 85, 86};
const uint64_t qos_priority[26] = {20, 40, 30, 50, 7, 20, 15, 56, 56, 56, 56, 56, 10,
60, 70, 80, 90, 5, 55, 65, 68, 19, 22, 24, 21, 18};
static long get_lcid_from_drbid(int drb_id) static long get_lcid_from_drbid(int drb_id)
{ {
return drb_id + 3; /* LCID is DRB + 3 */ return drb_id + 3; /* LCID is DRB + 3 */
...@@ -243,6 +248,49 @@ static void set_nssaiConfig(const int drb_len, const f1ap_drb_to_be_setup_t *req ...@@ -243,6 +248,49 @@ static void set_nssaiConfig(const int drb_len, const f1ap_drb_to_be_setup_t *req
} }
} }
static void set_QoSConfig(const f1ap_ue_context_modif_req_t *req, NR_UE_sched_ctrl_t *sched_ctrl)
{
AssertFatal(req != NULL, "f1ap_ue_context_modif_req is NULL\n");
uint8_t drb_count = req->drbs_to_be_setup_length;
uint8_t srb_count = req->srbs_to_be_setup_length;
LOG_I(NR_MAC, "Number of DRBs = %d and SRBs = %d\n", drb_count, srb_count);
/* DRBs*/
for (int i = 0; i < drb_count; i++) {
f1ap_drb_to_be_setup_t *drb_p = &req->drbs_to_be_setup[i];
uint8_t nb_qos_flows = drb_p->drb_info.flows_to_be_setup_length;
long drb_id = drb_p->drb_id;
LOG_I(NR_MAC, "In %s: number of QOS flows mapped to DRB_id %d: %ld \n", __func__, drb_count, drb_id);
for (int q = 0; q < nb_qos_flows; q++) {
f1ap_flows_mapped_to_drb_t *qos_flow = &drb_p->drb_info.flows_mapped_to_drb[q];
f1ap_qos_characteristics_t *qos_char = &qos_flow->qos_params.qos_characteristics;
uint64_t priority = qos_char->non_dynamic.qos_priority_level;
int64_t fiveqi = qos_char->non_dynamic.fiveqi;
if (qos_char->qos_type == dynamic) {
priority = qos_char->dynamic.qos_priority_level;
fiveqi = qos_char->dynamic.fiveqi > 0 ? qos_char->dynamic.fiveqi : 0;
}
if (qos_char->qos_type == non_dynamic) {
LOG_D(NR_MAC, "Qos Priority level is considered from the standarsdized 5QI to QoS mapping table\n");
for (int id = 0; id < 26; id++) {
if (qos_fiveqi[id] == fiveqi)
priority = qos_priority[id];
}
}
sched_ctrl->qos_config[drb_id - 1][q].fiveQI = fiveqi;
sched_ctrl->qos_config[drb_id - 1][q].priority = priority;
LOG_D(NR_MAC,
"In %s: drb_id %ld: 5QI %lu priority %lu\n",
__func__,
drb_id,
sched_ctrl->qos_config[drb_id - 1][q].fiveQI,
sched_ctrl->qos_config[drb_id - 1][q].priority);
}
}
}
void ue_context_setup_request(const f1ap_ue_context_setup_t *req) void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
{ {
gNB_MAC_INST *mac = RC.nrmac[0]; gNB_MAC_INST *mac = RC.nrmac[0];
...@@ -309,6 +357,9 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req) ...@@ -309,6 +357,9 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
/* TODO: need to apply after UE context reconfiguration confirmed? */ /* TODO: need to apply after UE context reconfiguration confirmed? */
nr_mac_prepare_cellgroup_update(mac, UE, new_CellGroup); nr_mac_prepare_cellgroup_update(mac, UE, new_CellGroup);
/* Fill the QoS config in MAC for each active DRB */
set_QoSConfig(req, &UE->UE_sched_ctrl);
/* Set NSSAI config in MAC for each active DRB */ /* Set NSSAI config in MAC for each active DRB */
set_nssaiConfig(req->drbs_to_be_setup_length, req->drbs_to_be_setup, &UE->UE_sched_ctrl); set_nssaiConfig(req->drbs_to_be_setup_length, req->drbs_to_be_setup, &UE->UE_sched_ctrl);
...@@ -409,6 +460,9 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) ...@@ -409,6 +460,9 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
nr_mac_prepare_cellgroup_update(mac, UE, new_CellGroup); nr_mac_prepare_cellgroup_update(mac, UE, new_CellGroup);
/* Fill the QoS config in MAC for each active DRB */
set_QoSConfig(req, &UE->UE_sched_ctrl);
/* Set NSSAI config in MAC for each active DRB */ /* Set NSSAI config in MAC for each active DRB */
set_nssaiConfig(req->drbs_to_be_setup_length, req->drbs_to_be_setup, &UE->UE_sched_ctrl); set_nssaiConfig(req->drbs_to_be_setup_length, req->drbs_to_be_setup, &UE->UE_sched_ctrl);
} else { } else {
......
...@@ -536,6 +536,11 @@ typedef struct NR_UE_ul_harq { ...@@ -536,6 +536,11 @@ typedef struct NR_UE_ul_harq {
NR_sched_pusch_t sched_pusch; NR_sched_pusch_t sched_pusch;
} NR_UE_ul_harq_t; } NR_UE_ul_harq_t;
typedef struct NR_QoS_config_s {
uint64_t fiveQI;
uint64_t priority;
} NR_QoS_config_t;
/*! \brief scheduling control information set through an API */ /*! \brief scheduling control information set through an API */
#define MAX_CSI_REPORTS 48 #define MAX_CSI_REPORTS 48
typedef struct { typedef struct {
...@@ -635,6 +640,9 @@ typedef struct { ...@@ -635,6 +640,9 @@ typedef struct {
/// sri, ul_ri and tpmi based on SRS /// sri, ul_ri and tpmi based on SRS
nr_srs_feedback_t srs_feedback; nr_srs_feedback_t srs_feedback;
nssai_t dl_lc_nssai[NR_MAX_NUM_LCID]; nssai_t dl_lc_nssai[NR_MAX_NUM_LCID];
// Information about the QoS configuration for each LCID/DRB
NR_QoS_config_t qos_config[NR_MAX_NUM_LCID - 4][NR_MAX_NUM_QFI]; // 0 -CCCH and 1- 3 SRBs(0,1,2)
} NR_UE_sched_ctrl_t; } NR_UE_sched_ctrl_t;
typedef struct { typedef struct {
......
...@@ -53,8 +53,8 @@ static void fill_DRB_configList_e1(NR_DRB_ToAddModList_t *DRB_configList, const ...@@ -53,8 +53,8 @@ static void fill_DRB_configList_e1(NR_DRB_ToAddModList_t *DRB_configList, const
asn1cCalloc(sdap_config->mappedQoS_FlowsToAdd, FlowsToAdd); asn1cCalloc(sdap_config->mappedQoS_FlowsToAdd, FlowsToAdd);
for (int j=0; j < drb->numQosFlow2Setup; j++) { for (int j=0; j < drb->numQosFlow2Setup; j++) {
asn1cSequenceAdd(FlowsToAdd->list, NR_QFI_t, id); asn1cSequenceAdd(FlowsToAdd->list, NR_QFI_t, qfi);
*id = drb->qosFlows[j].id; *qfi = drb->qosFlows[j].qfi;
} }
sdap_config->mappedQoS_FlowsToRelease = NULL; sdap_config->mappedQoS_FlowsToRelease = NULL;
...@@ -164,8 +164,11 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req) ...@@ -164,8 +164,11 @@ void e1_bearer_context_setup(const e1ap_bearer_setup_req_t *req)
DRB_nGRAN_setup_t *resp_drb = &resp_pdu->DRBnGRanList[0]; DRB_nGRAN_setup_t *resp_drb = &resp_pdu->DRBnGRanList[0];
resp_drb->id = req_drb->id; resp_drb->id = req_drb->id;
resp_drb->numQosFlowSetup = req_drb->numQosFlow2Setup; resp_drb->numQosFlowSetup = req_drb->numQosFlow2Setup;
for (int k = 0; k < resp_drb->numQosFlowSetup; k++) for (int k = 0; k < resp_drb->numQosFlowSetup; k++) {
resp_drb->qosFlows[k].id = req_drb->qosFlows[k].id; const qos_flow_to_setup_t *qosflow2Setup = &req_drb->qosFlows[k];
qos_flow_setup_t *qosflowSetup = &resp_drb->qosFlows[k];
qosflowSetup->qfi = qosflow2Setup->qfi;
}
// GTP tunnel for N3/to core // GTP tunnel for N3/to core
gtpv1u_gnb_create_tunnel_resp_t resp_n3 = {0}; gtpv1u_gnb_create_tunnel_resp_t resp_n3 = {0};
......
...@@ -2027,6 +2027,17 @@ unsigned int mask_flip(unsigned int x) { ...@@ -2027,6 +2027,17 @@ unsigned int mask_flip(unsigned int x) {
return((((x>>8) + (x<<8))&0xffff)>>6); 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) 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]; 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 ...@@ -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); rrc_pdu_session_param_t *RRC_pduSession = find_pduSession(UE, resp->pduSession[0].id, false);
DevAssert(RRC_pduSession); DevAssert(RRC_pduSession);
for (int i = 0; i < nb_drb; i++) { 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].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].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].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; 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 */ /* pass NSSAI info to MAC */
drbs[i].nssai = RRC_pduSession->param.nssai; drbs[i].nssai = RRC_pduSession->param.nssai;
} }
...@@ -2261,7 +2294,11 @@ void *rrc_gnb_task(void *args_p) { ...@@ -2261,7 +2294,11 @@ void *rrc_gnb_task(void *args_p) {
itti_receive_msg(TASK_RRC_GNB, &msg_p); itti_receive_msg(TASK_RRC_GNB, &msg_p);
const char *msg_name_p = ITTI_MSG_NAME(msg_p); const char *msg_name_p = ITTI_MSG_NAME(msg_p);
instance = ITTI_MSG_DESTINATION_INSTANCE(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)) { switch (ITTI_MSG_ID(msg_p)) {
case TERMINATE_MESSAGE: case TERMINATE_MESSAGE:
LOG_W(NR_RRC, " *** Exiting NR_RRC thread\n"); LOG_W(NR_RRC, " *** Exiting NR_RRC thread\n");
......
...@@ -68,6 +68,7 @@ ...@@ -68,6 +68,7 @@
#include "NGAP_QosFlowSetupRequestItem.h" #include "NGAP_QosFlowSetupRequestItem.h"
#include "NGAP_QosFlowAddOrModifyRequestItem.h" #include "NGAP_QosFlowAddOrModifyRequestItem.h"
#include "NGAP_NonDynamic5QIDescriptor.h" #include "NGAP_NonDynamic5QIDescriptor.h"
#include "NGAP_Dynamic5QIDescriptor.h"
#include "conversions.h" #include "conversions.h"
#include "RRC/NR/rrc_gNB_radio_bearers.h" #include "RRC/NR/rrc_gNB_radio_bearers.h"
...@@ -263,10 +264,15 @@ static void fill_qos(NGAP_QosFlowSetupRequestList_t *qos, pdusession_t *session) ...@@ -263,10 +264,15 @@ static void fill_qos(NGAP_QosFlowSetupRequestList_t *qos, pdusession_t *session)
// Set the QOS informations // Set the QOS informations
session->qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier; session->qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier;
NGAP_QosCharacteristics_t *qosChar = &qosFlowItem_p->qosFlowLevelQosParameters.qosCharacteristics; 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->present == NGAP_QosCharacteristics_PR_nonDynamic5QI) {
if (qosChar->choice.nonDynamic5QI != NULL) { AssertFatal(qosChar->choice.dynamic5QI, "Non-Dynamic 5QI is NULL\n");
session->qos[qosIdx].fiveQI = (uint64_t)qosChar->choice.nonDynamic5QI->fiveQI; 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; 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 ...@@ -820,15 +826,25 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins
drb->numQosFlow2Setup = session->nb_qos; drb->numQosFlow2Setup = session->nb_qos;
for (int k=0; k < drb->numQosFlow2Setup; k++) { 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_characteristics_t *qos_char = &qos_flow->qos_params.qos_characteristics;
qos->fiveQI_type = session->qos[k].fiveQI_type; 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; ngran_allocation_retention_priority_t *rent_priority = &qos_flow->qos_params.alloc_reten_priority;
qos->pre_emptionCapability = session->qos[k].allocation_retention_priority.pre_emp_capability; ngap_allocation_retention_priority_t *rent_priority_in = &qos_session->allocation_retention_priority;
qos->pre_emptionVulnerability = session->qos[k].allocation_retention_priority.pre_emp_vulnerability; 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 ...@@ -854,12 +870,15 @@ static void fill_qos2(NGAP_QosFlowAddOrModifyRequestList_t *qos, pdusession_t *s
// Set the QOS informations // Set the QOS informations
session->qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier; session->qos[qosIdx].qfi = (uint8_t)qosFlowItem_p->qosFlowIdentifier;
NGAP_QosCharacteristics_t *qosChar = &qosFlowItem_p->qosFlowLevelQosParameters->qosCharacteristics; 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->present == NGAP_QosCharacteristics_PR_nonDynamic5QI) {
if (qosChar->choice.nonDynamic5QI != NULL) { AssertFatal(qosChar->choice.dynamic5QI, "Non-Dynamic 5QI is NULL\n");
session->qos[qosIdx].fiveQI = (uint64_t)qosChar->choice.nonDynamic5QI->fiveQI; session->qos[qosIdx].fiveQI_type = non_dynamic;
} session->qos[qosIdx].fiveQI = (uint64_t)qosChar->choice.nonDynamic5QI->fiveQI;
} else if (qosChar->present == NGAP_QosCharacteristics_PR_dynamic5QI) { } else {
// TODO 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; ngap_allocation_retention_priority_t *tmp = &session->qos[qosIdx].allocation_retention_priority;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment