Commit 0a6998db authored by Robert Schmidt's avatar Robert Schmidt

Select CU-UP based on slice

parent e07a741e
...@@ -133,7 +133,7 @@ rrc_gNB_generate_dedicatedRRCReconfiguration_release( ...@@ -133,7 +133,7 @@ rrc_gNB_generate_dedicatedRRCReconfiguration_release(
void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP); void rrc_gNB_generate_dedicatedRRCReconfiguration(const protocol_ctxt_t *const ctxt_pP, rrc_gNB_ue_context_t *ue_context_pP);
sctp_assoc_t get_existing_cuup_for_ue(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue); sctp_assoc_t get_existing_cuup_for_ue(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue);
sctp_assoc_t get_new_cuup_for_ue(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue); sctp_assoc_t get_new_cuup_for_ue(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue, int sst, int sd);
int rrc_gNB_process_e1_setup_req(sctp_assoc_t assoc_id, e1ap_setup_req_t *req); int rrc_gNB_process_e1_setup_req(sctp_assoc_t assoc_id, e1ap_setup_req_t *req);
void bearer_context_setup_direct(e1ap_bearer_setup_req_t *req, void bearer_context_setup_direct(e1ap_bearer_setup_req_t *req,
......
...@@ -757,6 +757,8 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins ...@@ -757,6 +757,8 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins
UE->amf_ue_ngap_id = msg->amf_ue_ngap_id; UE->amf_ue_ngap_id = msg->amf_ue_ngap_id;
e1ap_bearer_setup_req_t bearer_req = {0}; e1ap_bearer_setup_req_t bearer_req = {0};
e1ap_nssai_t cuup_nssai = {0};
for (int i = 0; i < msg->nb_pdusessions_tosetup; i++) { for (int i = 0; i < msg->nb_pdusessions_tosetup; i++) {
rrc_pdu_session_param_t *pduSession = find_pduSession(UE, msg->pdusession_setup_params[i].pdusession_id, true); rrc_pdu_session_param_t *pduSession = find_pduSession(UE, msg->pdusession_setup_params[i].pdusession_id, true);
pdusession_t *session = &pduSession->param; pdusession_t *session = &pduSession->param;
...@@ -780,6 +782,8 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins ...@@ -780,6 +782,8 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins
pdu->nssai.sd = 0xffffff; pdu->nssai.sd = 0xffffff;
if (nssai->sD_flag) if (nssai->sD_flag)
pdu->nssai.sd = nssai->sD[0] << 16 | nssai->sD[1] << 8 | nssai->sD[0]; pdu->nssai.sd = nssai->sD[0] << 16 | nssai->sD[1] << 8 | nssai->sD[0];
if (cuup_nssai.sst == 0)
cuup_nssai = pdu->nssai; /* for CU-UP selection below */
pdu->integrityProtectionIndication = rrc->security.do_drb_integrity ? E1AP_IntegrityProtectionIndication_required : E1AP_IntegrityProtectionIndication_not_needed; pdu->integrityProtectionIndication = rrc->security.do_drb_integrity ? E1AP_IntegrityProtectionIndication_required : E1AP_IntegrityProtectionIndication_not_needed;
pdu->confidentialityProtectionIndication = rrc->security.do_drb_ciphering ? E1AP_ConfidentialityProtectionIndication_required : E1AP_ConfidentialityProtectionIndication_not_needed; pdu->confidentialityProtectionIndication = rrc->security.do_drb_ciphering ? E1AP_ConfidentialityProtectionIndication_required : E1AP_ConfidentialityProtectionIndication_not_needed;
...@@ -827,7 +831,12 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins ...@@ -827,7 +831,12 @@ void rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ(MessageDef *msg_p, instance_t ins
} }
int xid = rrc_gNB_get_next_transaction_identifier(instance); int xid = rrc_gNB_get_next_transaction_identifier(instance);
UE->xids[xid] = RRC_PDUSESSION_ESTABLISH; UE->xids[xid] = RRC_PDUSESSION_ESTABLISH;
sctp_assoc_t assoc_id = get_new_cuup_for_ue(rrc, UE); /* Limitation: we assume one fixed CU-UP per UE. We base the selection on
* NSSAI, but the UE might have multiple PDU sessions with differing slices,
* in which we might need to select different CU-UPs. In this case, we would
* actually need to group the E1 bearer context setup for the different
* CU-UPs, and send them to the different CU-UPs. */
sctp_assoc_t assoc_id = get_new_cuup_for_ue(rrc, UE, cuup_nssai.sst, cuup_nssai.sd);
rrc->cucp_cuup.bearer_context_setup(assoc_id, &bearer_req); rrc->cucp_cuup.bearer_context_setup(assoc_id, &bearer_req);
return; return;
} }
......
...@@ -35,6 +35,29 @@ static int cuup_compare(const nr_rrc_cuup_container_t *a, const nr_rrc_cuup_cont ...@@ -35,6 +35,29 @@ static int cuup_compare(const nr_rrc_cuup_container_t *a, const nr_rrc_cuup_cont
/* Tree management functions */ /* Tree management functions */
RB_GENERATE/*_STATIC*/(rrc_cuup_tree, nr_rrc_cuup_container_t, entries, cuup_compare); RB_GENERATE/*_STATIC*/(rrc_cuup_tree, nr_rrc_cuup_container_t, entries, cuup_compare);
static const nr_rrc_cuup_container_t *select_cuup_slice(const struct rrc_cuup_tree *t, const gNB_RRC_UE_t *ue, int sst, int sd)
{
nr_rrc_cuup_container_t *second_best_match = NULL; /* if no NSSAI matches exactly */
nr_rrc_cuup_container_t *cuup = NULL;
RB_FOREACH(cuup, rrc_cuup_tree, (struct rrc_cuup_tree *)&t) {
e1ap_setup_req_t *sr = cuup->setup_req;
for (int p = 0; p < sr->supported_plmns; ++p) {
/* actually we should also check that the PLMN selected by the UE matches */
for (int s = 0; s < sr->plmn[p].supported_slices; ++s) {
e1ap_nssai_t *nssai = &sr->plmn[p].slice[s];
if (nssai->sst == sst && nssai->sd == sd) {
LOG_I(RRC, "selecting CU-UP ID %ld based on exact NSSAI match (%d:0x%06x)\n", sr->gNB_cu_up_id, sst, sd);
return cuup; /* exact match */
} else if (nssai->sst == sst && second_best_match == NULL) {
LOG_I(RRC, "second best match: CU-UP ID %ld matches SST %d\n", sr->gNB_cu_up_id, sst);
second_best_match = cuup; /* only the SST matches -> "good enough" */
}
}
}
}
return second_best_match;
}
static const nr_rrc_cuup_container_t *select_cuup_round_robin(size_t n_t, const struct rrc_cuup_tree *t, const gNB_RRC_UE_t *ue) static const nr_rrc_cuup_container_t *select_cuup_round_robin(size_t n_t, const struct rrc_cuup_tree *t, const gNB_RRC_UE_t *ue)
{ {
/* pick the CU-UP following a "round-robin" fashion: select CU-UP M = RRC UE /* pick the CU-UP following a "round-robin" fashion: select CU-UP M = RRC UE
...@@ -42,8 +65,10 @@ static const nr_rrc_cuup_container_t *select_cuup_round_robin(size_t n_t, const ...@@ -42,8 +65,10 @@ static const nr_rrc_cuup_container_t *select_cuup_round_robin(size_t n_t, const
int m = (ue->rrc_ue_id - 1) % n_t; int m = (ue->rrc_ue_id - 1) % n_t;
nr_rrc_cuup_container_t *cuup = NULL; nr_rrc_cuup_container_t *cuup = NULL;
RB_FOREACH(cuup, rrc_cuup_tree, (struct rrc_cuup_tree *)&t) { RB_FOREACH(cuup, rrc_cuup_tree, (struct rrc_cuup_tree *)&t) {
if (m == 0) if (m == 0) {
LOG_I(RRC, "round-robin match: select CU-UP ID %ld (no NSSAI match)\n", cuup->setup_req->gNB_cu_up_id);
return cuup; return cuup;
}
m--; m--;
} }
/* this should not happen: no CU-UP available? */ /* this should not happen: no CU-UP available? */
...@@ -55,18 +80,19 @@ sctp_assoc_t get_existing_cuup_for_ue(const gNB_RRC_INST *rrc, const gNB_RRC_UE_ ...@@ -55,18 +80,19 @@ sctp_assoc_t get_existing_cuup_for_ue(const gNB_RRC_INST *rrc, const gNB_RRC_UE_
f1_ue_data_t ue_data = cu_get_f1_ue_data(ue->rrc_ue_id); f1_ue_data_t ue_data = cu_get_f1_ue_data(ue->rrc_ue_id);
if (ue_data.e1_assoc_id == 0) { if (ue_data.e1_assoc_id == 0) {
LOG_W(RRC, "UE %d should be associated to CU-UP, but is not\n", ue->rrc_ue_id); LOG_W(RRC, "UE %d should be associated to CU-UP, but is not\n", ue->rrc_ue_id);
return get_new_cuup_for_ue(rrc, ue); /* we could possibly check the SST/SD from the PDU session */
return get_new_cuup_for_ue(rrc, ue, 0, 0);
} }
LOG_D(RRC, "UE %d using CU-UP assoc_id %d\n", ue->rrc_ue_id, ue_data.e1_assoc_id); LOG_D(RRC, "UE %d using CU-UP assoc_id %d\n", ue->rrc_ue_id, ue_data.e1_assoc_id);
return ue_data.e1_assoc_id; return ue_data.e1_assoc_id;
} }
sctp_assoc_t get_new_cuup_for_ue(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue) sctp_assoc_t get_new_cuup_for_ue(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue, int sst, int sd)
{ {
/* check if there is already a UE associated */ /* check if there is already a UE associated */
f1_ue_data_t ue_data = cu_get_f1_ue_data(ue->rrc_ue_id); f1_ue_data_t ue_data = cu_get_f1_ue_data(ue->rrc_ue_id);
if (ue_data.e1_assoc_id != 0) { if (ue_data.e1_assoc_id != 0) {
LOG_D(RRC, "UE %d using CU-UP assoc_id %d\n", ue->rrc_ue_id, ue_data.e1_assoc_id); LOG_I(RRC, "UE %d using CU-UP assoc_id %d\n", ue->rrc_ue_id, ue_data.e1_assoc_id);
return ue_data.e1_assoc_id; return ue_data.e1_assoc_id;
} }
...@@ -77,10 +103,15 @@ sctp_assoc_t get_new_cuup_for_ue(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue ...@@ -77,10 +103,15 @@ sctp_assoc_t get_new_cuup_for_ue(const gNB_RRC_INST *rrc, const gNB_RRC_UE_t *ue
return 0; /* no CUUP connected */ return 0; /* no CUUP connected */
} }
const nr_rrc_cuup_container_t *selected = select_cuup_round_robin(rrc->num_cuups, &rrc->cuups, ue); const nr_rrc_cuup_container_t *selected = NULL;
if (selected == NULL) if (sst != 0) /* only do if there is slice information */
selected = select_cuup_slice(&rrc->cuups, ue, sst, sd);
if (selected == NULL) /* nothing found yet */
selected = select_cuup_round_robin(rrc->num_cuups, &rrc->cuups, ue);
if (selected == NULL) {
selected = RB_ROOT(&rrc->cuups); selected = RB_ROOT(&rrc->cuups);
AssertFatal(selected != NULL, "logic error: could not select CU-UP\n"); }
AssertFatal(selected != NULL, "logic error: could not select CU-UP, is one connected?\n");
/* update the association for the UE so it will be picked up later */ /* update the association for the UE so it will be picked up later */
ue_data.e1_assoc_id = selected->assoc_id; ue_data.e1_assoc_id = selected->assoc_id;
......
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