RRC: enhance AMBR management in CU-CP
According to TS 38.413: * AMBR is conditional to PDU Session Resource to setup in the Initial UE Context Setup procedure * The UE Aggregate Maximum Bit Rate IE should be sent to the NG-RAN node if the AMF has not sent it previously. If it is included in the PDU SESSION RESOURCE SETUP REQUEST message, the NG-RAN node shall store it in the UE context * Range is INTEGER [0..4,000,000,000,000] To this purpose, changes in the commit: * Init AMBR to out of range value when creating UE context * Store AMBR in UE context whenever is received * Assert if not set at the time of Bearer Setup (should be known at that stage)
This commit is contained in:
@@ -166,6 +166,11 @@ typedef struct {
|
|||||||
pdusession_level_qos_parameter_t qos;
|
pdusession_level_qos_parameter_t qos;
|
||||||
} nr_rrc_qos_t;
|
} nr_rrc_qos_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_t dl_br;
|
||||||
|
uint64_t ul_br;
|
||||||
|
} nr_rrc_ambr_t;
|
||||||
|
|
||||||
/* forward declaration */
|
/* forward declaration */
|
||||||
typedef struct nr_handover_context_s nr_handover_context_t;
|
typedef struct nr_handover_context_s nr_handover_context_t;
|
||||||
|
|
||||||
@@ -244,6 +249,9 @@ typedef struct gNB_RRC_UE_s {
|
|||||||
int n_initial_pdu;
|
int n_initial_pdu;
|
||||||
pdusession_t *initial_pdus;
|
pdusession_t *initial_pdus;
|
||||||
|
|
||||||
|
// Aggregate Maximum Bit Rate
|
||||||
|
nr_rrc_ambr_t ambr;
|
||||||
|
|
||||||
/* Nas Pdu */
|
/* Nas Pdu */
|
||||||
byte_array_t nas_pdu;
|
byte_array_t nas_pdu;
|
||||||
|
|
||||||
|
|||||||
@@ -1963,7 +1963,7 @@ static void handle_ueCapabilityInformation(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE,
|
|||||||
* up security and request capabilities, so trigger PDU sessions now. The
|
* up security and request capabilities, so trigger PDU sessions now. The
|
||||||
* UE NAS message will be forwarded in the corresponding reconfiguration,
|
* UE NAS message will be forwarded in the corresponding reconfiguration,
|
||||||
* the Initial context setup response after reconfiguration complete. */
|
* the Initial context setup response after reconfiguration complete. */
|
||||||
if (!trigger_bearer_setup(rrc, UE, UE->n_initial_pdu, UE->initial_pdus, 0)) {
|
if (!trigger_bearer_setup(rrc, UE, UE->n_initial_pdu, UE->initial_pdus, UE->ambr.dl_br)) {
|
||||||
LOG_W(NR_RRC, "Failed to setup bearers for UE %d: send Initial Context Setup Response\n", UE->rrc_ue_id);
|
LOG_W(NR_RRC, "Failed to setup bearers for UE %d: send Initial Context Setup Response\n", UE->rrc_ue_id);
|
||||||
rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(rrc, UE);
|
rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(rrc, UE);
|
||||||
rrc_forward_ue_nas_message(rrc, UE);
|
rrc_forward_ue_nas_message(rrc, UE);
|
||||||
@@ -2213,7 +2213,7 @@ static int rrc_gNB_decode_dcch(gNB_RRC_INST *rrc, const f1ap_ul_rrc_message_t *m
|
|||||||
* to set up security, so trigger PDU sessions now. The UE NAS
|
* to set up security, so trigger PDU sessions now. The UE NAS
|
||||||
* message will be forwarded in the corresponding reconfiguration,
|
* message will be forwarded in the corresponding reconfiguration,
|
||||||
* the Initial context setup response after reconfiguration complete. */
|
* the Initial context setup response after reconfiguration complete. */
|
||||||
if (!trigger_bearer_setup(rrc, UE, UE->n_initial_pdu, UE->initial_pdus, 0)) {
|
if (!trigger_bearer_setup(rrc, UE, UE->n_initial_pdu, UE->initial_pdus, UE->ambr.dl_br)) {
|
||||||
LOG_W(NR_RRC, "Failed to setup bearers for UE %d: send Initial Context Setup Response\n", UE->rrc_ue_id);
|
LOG_W(NR_RRC, "Failed to setup bearers for UE %d: send Initial Context Setup Response\n", UE->rrc_ue_id);
|
||||||
rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(rrc, UE);
|
rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(rrc, UE);
|
||||||
rrc_forward_ue_nas_message(rrc, UE);
|
rrc_forward_ue_nas_message(rrc, UE);
|
||||||
|
|||||||
@@ -367,6 +367,10 @@ static nr_sdap_configuration_t get_sdap_config(const bool enable_sdap)
|
|||||||
*/
|
*/
|
||||||
bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession_t *sessions, uint64_t ueAggMaxBitRateDownlink)
|
bool trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession_t *sessions, uint64_t ueAggMaxBitRateDownlink)
|
||||||
{
|
{
|
||||||
|
if (ueAggMaxBitRateDownlink == UINT64_MAX) {
|
||||||
|
LOG_E(NR_RRC, "UE %d: UE aggregate maximum bitrate must be known by the NG-RAN node\n", UE->rrc_ue_id);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
AssertFatal(UE->as_security_active, "logic bug: security should be active when activating DRBs\n");
|
AssertFatal(UE->as_security_active, "logic bug: security should be active when activating DRBs\n");
|
||||||
e1ap_bearer_setup_req_t bearer_req = {0};
|
e1ap_bearer_setup_req_t bearer_req = {0};
|
||||||
|
|
||||||
@@ -497,12 +501,15 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t
|
|||||||
UE->nas_pdu = req->nas_pdu;
|
UE->nas_pdu = req->nas_pdu;
|
||||||
|
|
||||||
if (req->nb_of_pdusessions > 0) {
|
if (req->nb_of_pdusessions > 0) {
|
||||||
|
AssertFatal(req->has_ue_ambr, "UE aggregate maximum bitrate is required when there are PDU sessions to setup");
|
||||||
/* if there are PDU sessions to setup, store them to be created once
|
/* if there are PDU sessions to setup, store them to be created once
|
||||||
* security (and UE capabilities) are received */
|
* security (and UE capabilities) are received */
|
||||||
UE->n_initial_pdu = req->nb_of_pdusessions;
|
UE->n_initial_pdu = req->nb_of_pdusessions;
|
||||||
UE->initial_pdus = calloc_or_fail(UE->n_initial_pdu, sizeof(*UE->initial_pdus));
|
UE->initial_pdus = calloc_or_fail(UE->n_initial_pdu, sizeof(*UE->initial_pdus));
|
||||||
for (int i = 0; i < UE->n_initial_pdu; ++i)
|
for (int i = 0; i < UE->n_initial_pdu; ++i)
|
||||||
cp_pdusession_resource_item_to_pdusession(&UE->initial_pdus[i], &req->pdusession[i]);
|
cp_pdusession_resource_item_to_pdusession(&UE->initial_pdus[i], &req->pdusession[i]);
|
||||||
|
UE->ambr.dl_br = req->ue_ambr.br_dl;
|
||||||
|
UE->ambr.ul_br = req->ue_ambr.br_ul;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* security */
|
/* security */
|
||||||
@@ -525,7 +532,7 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t
|
|||||||
// do not remove the above allocation which is reused here: this is used
|
// do not remove the above allocation which is reused here: this is used
|
||||||
// in handle_rrcReconfigurationComplete() to know that we need to send a
|
// in handle_rrcReconfigurationComplete() to know that we need to send a
|
||||||
// Initial context setup response message
|
// Initial context setup response message
|
||||||
if (!trigger_bearer_setup(rrc, UE, UE->n_initial_pdu, UE->initial_pdus, 0)) {
|
if (!trigger_bearer_setup(rrc, UE, UE->n_initial_pdu, UE->initial_pdus, UE->ambr.dl_br)) {
|
||||||
LOG_W(NR_RRC, "UE %d: reject PDU Session Setup in Initial Context Setup Response\n", UE->rrc_ue_id);
|
LOG_W(NR_RRC, "UE %d: reject PDU Session Setup in Initial Context Setup Response\n", UE->rrc_ue_id);
|
||||||
ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CAUSE_RADIO_NETWORK_RESOURCES_NOT_AVAILABLE_FOR_THE_SLICE};
|
ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CAUSE_RADIO_NETWORK_RESOURCES_NOT_AVAILABLE_FOR_THE_SLICE};
|
||||||
send_ngap_initial_context_setup_resp_fail(rrc->module_id, req, cause);
|
send_ngap_initial_context_setup_resp_fail(rrc->module_id, req, cause);
|
||||||
@@ -878,9 +885,13 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins
|
|||||||
for (int i = 0; i < msg->nb_pdusessions_tosetup; ++i)
|
for (int i = 0; i < msg->nb_pdusessions_tosetup; ++i)
|
||||||
cp_pdusession_resource_item_to_pdusession(&to_setup[i], &msg->pdusession[i]);
|
cp_pdusession_resource_item_to_pdusession(&to_setup[i], &msg->pdusession[i]);
|
||||||
|
|
||||||
uint64_t dl_ambr = msg->has_ue_ambr ? msg->ueAggMaxBitRate.br_dl : 0;
|
/** Set AMBR if provided (optional) */
|
||||||
|
if (msg->has_ue_ambr) {
|
||||||
|
UE->ambr.dl_br = msg->ueAggMaxBitRate.br_dl;
|
||||||
|
UE->ambr.ul_br = msg->ueAggMaxBitRate.br_ul;
|
||||||
|
}
|
||||||
|
|
||||||
if (!trigger_bearer_setup(rrc, UE, msg->nb_pdusessions_tosetup, to_setup, dl_ambr)) {
|
if (!trigger_bearer_setup(rrc, UE, msg->nb_pdusessions_tosetup, to_setup, UE->ambr.dl_br)) {
|
||||||
// Reject PDU Session Resource setup if there's no CU-UP associated
|
// Reject PDU Session Resource setup if there's no CU-UP associated
|
||||||
LOG_W(NR_RRC, "UE %d: reject PDU Session Setup in PDU Session Resource Setup Response\n", UE->rrc_ue_id);
|
LOG_W(NR_RRC, "UE %d: reject PDU Session Setup in PDU Session Resource Setup Response\n", UE->rrc_ue_id);
|
||||||
ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CAUSE_RADIO_NETWORK_RESOURCES_NOT_AVAILABLE_FOR_THE_SLICE};
|
ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CAUSE_RADIO_NETWORK_RESOURCES_NOT_AVAILABLE_FOR_THE_SLICE};
|
||||||
@@ -1199,7 +1210,11 @@ int rrc_gNB_process_Handover_Request(gNB_RRC_INST *rrc, instance_t instance, nga
|
|||||||
cp_pdusession_transfer_to_pdusession(pdu, &ho_pdu->pdusessionTransfer);
|
cp_pdusession_transfer_to_pdusession(pdu, &ho_pdu->pdusessionTransfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!trigger_bearer_setup(rrc, UE, msg->nb_of_pdusessions, to_setup, msg->ue_ambr.br_dl)) {
|
// Store UE aggregate maximum bitrate
|
||||||
|
UE->ambr.dl_br = msg->ue_ambr.br_dl;
|
||||||
|
UE->ambr.ul_br = msg->ue_ambr.br_ul;
|
||||||
|
|
||||||
|
if (!trigger_bearer_setup(rrc, UE, msg->nb_of_pdusessions, to_setup, UE->ambr.dl_br)) {
|
||||||
LOG_E(NR_RRC, "Failed to establish PDU session: handover failed\n");
|
LOG_E(NR_RRC, "Failed to establish PDU session: handover failed\n");
|
||||||
|
|
||||||
ngap_handover_failure_t fail = {
|
ngap_handover_failure_t fail = {
|
||||||
@@ -1211,7 +1226,6 @@ int rrc_gNB_process_Handover_Request(gNB_RRC_INST *rrc, instance_t instance, nga
|
|||||||
rrc_remove_ue(rrc, ue_context_p);
|
rrc_remove_ue(rrc, ue_context_p);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -218,6 +218,8 @@ rrc_gNB_ue_context_t *rrc_gNB_create_ue_context(sctp_assoc_t assoc_id,
|
|||||||
ue->rrc_ue_id);
|
ue->rrc_ue_id);
|
||||||
bool success = cu_add_f1_ue_data(ue->rrc_ue_id, &ue_data);
|
bool success = cu_add_f1_ue_data(ue->rrc_ue_id, &ue_data);
|
||||||
DevAssert(success);
|
DevAssert(success);
|
||||||
|
ue->ambr.dl_br = UINT64_MAX;
|
||||||
|
ue->ambr.ul_br = UINT64_MAX;
|
||||||
|
|
||||||
// Initialise setup PDU Sessions list
|
// Initialise setup PDU Sessions list
|
||||||
seq_arr_init(&ue->pduSessions, sizeof(rrc_pdu_session_param_t));
|
seq_arr_init(&ue->pduSessions, sizeof(rrc_pdu_session_param_t));
|
||||||
|
|||||||
Reference in New Issue
Block a user