From b90e57549ce137fb601f03af30f5f3bb8f8b43f2 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Wed, 17 Jun 2020 09:53:36 +0200 Subject: [PATCH 01/66] ignore inconsistent DCI instead of exiting --- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 32 +++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 0da02bd7d1..b0437ea972 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -2232,9 +2232,14 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac, pdsch_TimeDomainAllocationList = mac->DLbwp[0]->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList; if (pdsch_TimeDomainAllocationList) { - AssertFatal(pdsch_TimeDomainAllocationList->list.count > time_domain_ind, - "time_domain_ind %d >= pdsch->TimeDomainAllocationList->list.count %d\n", - time_domain_ind,pdsch_TimeDomainAllocationList->list.count); + if (time_domain_ind >= pdsch_TimeDomainAllocationList->list.count) { + LOG_E(MAC, "time_domain_ind %d >= pdsch->TimeDomainAllocationList->list.count %d\n", + time_domain_ind, pdsch_TimeDomainAllocationList->list.count); + dlsch_config_pdu->start_symbol = 0; + dlsch_config_pdu->number_symbols = 0; + return -1; + } + int startSymbolAndLength = pdsch_TimeDomainAllocationList->list.array[time_domain_ind]->startSymbolAndLength; int S,L; SLIV2SL(startSymbolAndLength,&S,&L); @@ -2342,10 +2347,8 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, nr /* FREQ_DOM_RESOURCE_ASSIGNMENT_UL */ nr_ue_process_dci_freq_dom_resource_assignment(pusch_config_pdu_0_0,NULL,n_RB_ULBWP,0,dci->freq_dom_resource_assignment_UL); /* TIME_DOM_RESOURCE_ASSIGNMENT */ - nr_ue_process_dci_time_dom_resource_assignment(mac, - pusch_config_pdu_0_0,NULL, - dci->time_dom_resource_assignment); - + if (nr_ue_process_dci_time_dom_resource_assignment(mac,pusch_config_pdu_0_0,NULL,dci->time_dom_resource_assignment) < 0) + break; /* FREQ_HOPPING_FLAG */ if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.resource_allocation != 0) && (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.frequency_hopping !=0)) @@ -2417,8 +2420,8 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, nr /* FREQ_DOM_RESOURCE_ASSIGNMENT_UL */ nr_ue_process_dci_freq_dom_resource_assignment(pusch_config_pdu_0_1,NULL,n_RB_ULBWP,0,dci->freq_dom_resource_assignment_UL); /* TIME_DOM_RESOURCE_ASSIGNMENT */ - nr_ue_process_dci_time_dom_resource_assignment(mac,pusch_config_pdu_0_1,NULL, - dci->time_dom_resource_assignment); + if (nr_ue_process_dci_time_dom_resource_assignment(mac,pusch_config_pdu_0_1,NULL,dci->time_dom_resource_assignment) < 0) + break; /* FREQ_HOPPING_FLAG */ if ((mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.resource_allocation != 0) && (mac->phy_config.config_req.ul_bwp_dedicated.pusch_config_dedicated.frequency_hopping !=0)) @@ -2748,9 +2751,8 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, nr /* FREQ_DOM_RESOURCE_ASSIGNMENT_DL */ nr_ue_process_dci_freq_dom_resource_assignment(NULL,dlsch_config_pdu_1_0,0,n_RB_DLBWP,dci->freq_dom_resource_assignment_DL); /* TIME_DOM_RESOURCE_ASSIGNMENT */ - nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_0, - dci->time_dom_resource_assignment); - + if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_0,dci->time_dom_resource_assignment) < 0) + break; /* dmrs symbol positions*/ dlsch_config_pdu_1_0->dlDmrsSymbPos = fill_dmrs_mask(pdsch_config, mac->scc->dmrs_TypeA_Position, @@ -2868,8 +2870,8 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, nr /* FREQ_DOM_RESOURCE_ASSIGNMENT_DL */ nr_ue_process_dci_freq_dom_resource_assignment(NULL,dlsch_config_pdu_1_1,0,n_RB_DLBWP,dci->freq_dom_resource_assignment_DL); /* TIME_DOM_RESOURCE_ASSIGNMENT */ - nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_1, - dci->time_dom_resource_assignment); + if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_1,dci->time_dom_resource_assignment) < 0) + break; /* VRB_TO_PRB_MAPPING */ if (mac->phy_config.config_req.dl_bwp_dedicated.pdsch_config_dedicated.resource_allocation != 0) dlsch_config_pdu_1_1->vrb_to_prb_mapping = (dci->vrb_to_prb_mapping == 0) ? vrb_to_prb_mapping_non_interleaved:vrb_to_prb_mapping_interleaved; @@ -3140,7 +3142,7 @@ void nr_extract_dci_info(NR_UE_MAC_INST_t *mac, pos+=4; dci_pdu_rel15->time_dom_resource_assignment = (*dci_pdu >> (dci_size-pos))&0xf; #ifdef DEBUG_EXTRACT_DCI - LOG_D(MAC,"time-domain assignment %d (3 bits)=> %d (0x%lx)\n",dci_pdu_rel15->time_dom_resource_assignment,dci_size-pos,*dci_pdu); + LOG_D(MAC,"time-domain assignment %d (4 bits)=> %d (0x%lx)\n",dci_pdu_rel15->time_dom_resource_assignment,dci_size-pos,*dci_pdu); #endif // VRB to PRB mapping From a5a1d7b918d9d26a7601aa3b53026427d01c31ef Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Mon, 29 Jun 2020 12:13:27 +0200 Subject: [PATCH 02/66] Improve stability by replacing AssertFatal() with LOG_E() in nr_rx_pdsch() --- openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index 7f941e5567..a8827b4e92 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -214,7 +214,8 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, printf("[DEMOD] I am assuming only TB1 is active, it is in cw %d\n", dlsch1_harq->codeword); #endif - AssertFatal(1 == 0, "[UE][FATAL] DLSCH: TB0 not active and TB1 active case is not supported\n"); + LOG_E(PHY, "[UE][FATAL] DLSCH: TB0 not active and TB1 active case is not supported\n"); + return -1; } else { LOG_E(PHY,"[UE][FATAL] nr_tti_rx %d: no active DLSCH\n", nr_tti_rx); @@ -224,14 +225,16 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, break; default: - AssertFatal(1 == 0, "[UE][FATAL] nr_tti_rx %d: Unknown PDSCH format %d\n", nr_tti_rx, type); + LOG_E(PHY, "[UE][FATAL] nr_tti_rx %d: Unknown PDSCH format %d\n", nr_tti_rx, type); return(-1); break; } - if (dlsch0_harq == NULL) - AssertFatal(1 == 0, "Done\n"); + if (dlsch0_harq == NULL) { + LOG_E(PHY, "Done\n"); + return -1; + } dlsch0_harq->Qm = nr_get_Qm_dl(dlsch[0]->harq_processes[harq_pid]->mcs, dlsch[0]->harq_processes[harq_pid]->mcs_table); dlsch0_harq->R = nr_get_code_rate_dl(dlsch[0]->harq_processes[harq_pid]->mcs, dlsch[0]->harq_processes[harq_pid]->mcs_table); From c5fdcd85cc936677e65daa378c11b6b35a8cb0cf Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 11 Apr 2020 15:42:13 +0200 Subject: [PATCH 03/66] Bugfix FlexRAN: if a UE is in RRC but not S1AP, treat as no bug --- openair2/ENB_APP/flexran_agent_ran_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index 32cb8c74e1..abade20846 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -3644,7 +3644,7 @@ int flexran_get_s1ap_ue(mid_t mod_id, rnti_t rnti, Protocol__FlexS1apUe * ue_con RB_FOREACH(ue, s1ap_ue_map, &s1ap->s1ap_ue_head){ if (ue->eNB_ue_s1ap_id == enb_ue_s1ap_id) break; } - if (ue == NULL) return -1; + if (!ue) return 0; // UE does not exist: it might be connected but CN did not answer if (ue->mme_ref->mme_s1_ip.ipv4) ue_conf->mme_s1_ip = (char*) &ue->mme_ref->mme_s1_ip.ipv4_address[0]; From 9072101a1a9c802de3334aa4e020417b6849b9ae Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 15 Apr 2020 21:25:42 +0200 Subject: [PATCH 04/66] Correctly decode IMSI also when not integrity protected --- openair2/RRC/LTE/rrc_eNB_S1AP.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/openair2/RRC/LTE/rrc_eNB_S1AP.c b/openair2/RRC/LTE/rrc_eNB_S1AP.c index 27a442ed05..9f92be366b 100644 --- a/openair2/RRC/LTE/rrc_eNB_S1AP.c +++ b/openair2/RRC/LTE/rrc_eNB_S1AP.c @@ -96,36 +96,34 @@ void extract_imsi(uint8_t *pdu_buf, uint32_t pdu_len, rrc_eNB_ue_context_t *ue_c && pdu_len > NAS_MESSAGE_SECURITY_HEADER_SIZE)) return; + /* Decode plain NAS message */ + EMM_msg *e_msg = &nas_msg.plain.emm; + emm_msg_header_t *emm_header = &e_msg->header; + if (header->security_header_type != SECURITY_HEADER_TYPE_NOT_PROTECTED) { /* Decode the message authentication code */ DECODE_U32((char *) pdu_buf+size, header->message_authentication_code, size); /* Decode the sequence number */ DECODE_U8((char *) pdu_buf+size, header->sequence_number, size); - } + /* Decode the security header type and the protocol discriminator */ + DECODE_U8(pdu_buf + size, *(uint8_t *)(emm_header), size); - /* Note: the value of the pointer (i.e. the address) is given by value, so we - * can modify it as we want. The callee retains the original address! */ + /* Check that this is the right message */ + if (emm_header->protocol_discriminator != EPS_MOBILITY_MANAGEMENT_MESSAGE) + return; + } pdu_buf += size; pdu_len -= size; - /* Decode plain NAS message */ - EMM_msg *e_msg = &nas_msg.plain.emm; - emm_msg_header_t *emm_header = &e_msg->header; - /* First decode the EMM message header */ - int e_head_size = 0; /* Check that buffer contains more than only the header */ if (pdu_len <= sizeof(emm_msg_header_t)) return; - /* Decode the security header type and the protocol discriminator */ - DECODE_U8(pdu_buf + e_head_size, *(uint8_t *)(emm_header), e_head_size); + /* First decode the EMM message header */ + int e_head_size = 0; /* Decode the message type */ DECODE_U8(pdu_buf + e_head_size, emm_header->message_type, e_head_size); - /* Check that this is the right message */ - if (emm_header->protocol_discriminator != EPS_MOBILITY_MANAGEMENT_MESSAGE) - return; - pdu_buf += e_head_size; pdu_len -= e_head_size; From b01d63ba4ecf7995c35a3fbbc097cc2bdda1dbf4 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 11 Apr 2020 00:20:24 +0200 Subject: [PATCH 05/66] Do not check for register_enb_pending The test seemingly ensures that this code block is hit only once. However, if we enable later activation of MMEs, it will be hit a second (and third, ...) time. The only thing in guards against, though, is an INIT message to the L1L2 thread, when register_enb_pending == 0, which should only be sent once. Therefore, functionality won't be changed if register_enb_pending becomes negative, and the assert can be removed. --- openair2/ENB_APP/enb_app.c | 1 - 1 file changed, 1 deletion(-) diff --git a/openair2/ENB_APP/enb_app.c b/openair2/ENB_APP/enb_app.c index 0e1c7e64bc..7c91e57813 100644 --- a/openair2/ENB_APP/enb_app.c +++ b/openair2/ENB_APP/enb_app.c @@ -273,7 +273,6 @@ void *eNB_app_task(void *args_p) { if (EPC_MODE_ENABLED) { LOG_I(ENB_APP, "[eNB %d] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p), S1AP_REGISTER_ENB_CNF(msg_p).nb_mme); - DevAssert(register_enb_pending > 0); register_enb_pending--; /* Check if at least eNB is registered with one MME */ From 1363a53dd070fd49bf3efb21dea94abad288887d Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 11 Apr 2020 00:23:40 +0200 Subject: [PATCH 06/66] S1AP: Only register MME if we do not know it yet --- openair3/S1AP/s1ap_eNB.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/openair3/S1AP/s1ap_eNB.c b/openair3/S1AP/s1ap_eNB.c index c228034245..c703501847 100644 --- a/openair3/S1AP/s1ap_eNB.c +++ b/openair3/S1AP/s1ap_eNB.c @@ -220,8 +220,21 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * /* Trying to connect to provided list of MME ip address */ for (index = 0; index < s1ap_register_eNB->nb_mme; index++) { + net_ip_address_t *mme_ip = &s1ap_register_eNB->mme_ip_address[index]; + struct s1ap_eNB_mme_data_s *mme = NULL; + RB_FOREACH(mme, s1ap_mme_map, &new_instance->s1ap_mme_head) { + /* Compare whether IPv4 and IPv6 information is already present, in which + * wase we do not register again */ + if (mme->mme_s1_ip.ipv4 == mme_ip->ipv4 && (!mme_ip->ipv4 + || strncmp(mme->mme_s1_ip.ipv4_address, mme_ip->ipv4_address, 16) == 0) + && mme->mme_s1_ip.ipv6 == mme_ip->ipv6 && (!mme_ip->ipv6 + || strncmp(mme->mme_s1_ip.ipv6_address, mme_ip->ipv6_address, 46) == 0)) + break; + } + if (mme) + continue; s1ap_eNB_register_mme(new_instance, - &s1ap_register_eNB->mme_ip_address[index], + mme_ip, &s1ap_register_eNB->enb_ip_address, s1ap_register_eNB->sctp_in_streams, s1ap_register_eNB->sctp_out_streams, From df3f7e1ecfe0556bc3363c643ed811a1c3772ec1 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 10 Apr 2020 23:17:36 +0200 Subject: [PATCH 07/66] FlexRAN: Enable MME adding/removing --- .../CONTROL_MODULES/S1AP/flexran_agent_s1ap.c | 33 +++++++ .../CONTROL_MODULES/S1AP/flexran_agent_s1ap.h | 5 + openair2/ENB_APP/flexran_agent_common.c | 47 +++++----- openair2/ENB_APP/flexran_agent_ran_api.c | 91 +++++++++++++++++++ openair2/ENB_APP/flexran_agent_ran_api.h | 6 ++ 5 files changed, 160 insertions(+), 22 deletions(-) diff --git a/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.c b/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.c index 04a47406e1..d5fc5627a0 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.c +++ b/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.c @@ -125,6 +125,39 @@ void flexran_agent_s1ap_destroy_stats_reply(Protocol__FlexStatsReply *reply) { } } +void flexran_agent_handle_mme_update(mid_t mod_id, + size_t n_mme, + Protocol__FlexS1apMme **mme) { + if (n_mme == 0 || n_mme > 1) { + LOG_E(FLEXRAN_AGENT, "cannot handle %lu MMEs yet\n", n_mme); + return; + } + + if (!mme[0]->s1_ip) { + LOG_E(FLEXRAN_AGENT, "no S1 IP present, cannot handle request\n"); + return; + } + + if (mme[0]->has_state + && mme[0]->state == PROTOCOL__FLEX_MME_STATE__FLMMES_DISCONNECTED) { + int rc = flexran_remove_s1ap_mme(mod_id, 1, &mme[0]->s1_ip); + if (rc == 0) + LOG_I(FLEXRAN_AGENT, "remove MME at IP %s\n", mme[0]->s1_ip); + else + LOG_W(FLEXRAN_AGENT, + "could not remove MME: flexran_remove_s1ap_mme() returned %d\n", + rc); + } else { + int rc = flexran_add_s1ap_mme(mod_id, 1, &mme[0]->s1_ip); + if (rc == 0) + LOG_I(FLEXRAN_AGENT, "add MME at IP %s\n", mme[0]->s1_ip); + else + LOG_W(FLEXRAN_AGENT, + "could not add MME: flexran_add_s1ap_mme() returned %d\n", + rc); + } +} + int flexran_agent_register_s1ap_xface(mid_t mod_id) { if (agent_s1ap_xface[mod_id]) { LOG_E(FLEXRAN_AGENT, "S1AP agent CM for eNB %d is already registered\n", mod_id); diff --git a/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.h b/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.h index 1cca6ac9c1..54ea2926a8 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.h +++ b/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.h @@ -60,6 +60,11 @@ int flexran_agent_s1ap_stats_reply(mid_t mod_id, /* Free allocated S1AP stats message */ void flexran_agent_s1ap_destroy_stats_reply(Protocol__FlexStatsReply *reply); +/* Add or remove MME updates */ +void flexran_agent_handle_mme_update(mid_t mod_id, + size_t n_mme, + Protocol__FlexS1apMme **mme); + /* Register technology specific interface callbacks */ int flexran_agent_register_s1ap_xface(mid_t mod_id); diff --git a/openair2/ENB_APP/flexran_agent_common.c b/openair2/ENB_APP/flexran_agent_common.c index dc320ef974..ec0b780a3a 100644 --- a/openair2/ENB_APP/flexran_agent_common.c +++ b/openair2/ENB_APP/flexran_agent_common.c @@ -893,31 +893,34 @@ int flexran_agent_handle_enb_config_reply(mid_t mod_id, const void *params, Prot Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params; Protocol__FlexEnbConfigReply *enb_config = input->enb_config_reply_msg; - if (enb_config->n_cell_config == 0) { - LOG_W(FLEXRAN_AGENT, - "received enb_config_reply message does not contain a cell_config\n"); - *msg = NULL; - return 0; - } - if (enb_config->n_cell_config > 1) LOG_W(FLEXRAN_AGENT, "ignoring slice configs for other cell except cell 0\n"); - if (flexran_agent_get_mac_xface(mod_id) && enb_config->cell_config[0]->slice_config) { - prepare_update_slice_config(mod_id, enb_config->cell_config[0]->slice_config); - } else if (enb_config->cell_config[0]->has_eutra_band - && enb_config->cell_config[0]->has_dl_freq - && enb_config->cell_config[0]->has_ul_freq - && enb_config->cell_config[0]->has_dl_bandwidth) { - initiate_soft_restart(mod_id, enb_config->cell_config[0]); - } else if (flexran_agent_get_rrc_xface(mod_id) - && enb_config->cell_config[0]->has_x2_ho_net_control) { - LOG_I(FLEXRAN_AGENT, - "setting X2 HO NetControl to %d\n", - enb_config->cell_config[0]->x2_ho_net_control); - const int rc = flexran_set_x2_ho_net_control(mod_id, enb_config->cell_config[0]->x2_ho_net_control); - if (rc < 0) - LOG_E(FLEXRAN_AGENT, "Error in configuring X2 handover controlled by network"); + if (enb_config->n_cell_config > 0) { + if (flexran_agent_get_mac_xface(mod_id) && enb_config->cell_config[0]->slice_config) { + prepare_update_slice_config(mod_id, enb_config->cell_config[0]->slice_config); + } + if (enb_config->cell_config[0]->has_eutra_band + && enb_config->cell_config[0]->has_dl_freq + && enb_config->cell_config[0]->has_ul_freq + && enb_config->cell_config[0]->has_dl_bandwidth) { + initiate_soft_restart(mod_id, enb_config->cell_config[0]); + } + if (flexran_agent_get_rrc_xface(mod_id) + && enb_config->cell_config[0]->has_x2_ho_net_control) { + LOG_I(FLEXRAN_AGENT, + "setting X2 HO NetControl to %d\n", + enb_config->cell_config[0]->x2_ho_net_control); + const int rc = flexran_set_x2_ho_net_control(mod_id, enb_config->cell_config[0]->x2_ho_net_control); + if (rc < 0) + LOG_E(FLEXRAN_AGENT, "Error in configuring X2 handover controlled by network"); + } + } + + if (flexran_agent_get_s1ap_xface(mod_id) && enb_config->s1ap) { + flexran_agent_handle_mme_update(mod_id, + enb_config->s1ap->n_mme, + enb_config->s1ap->mme); } *msg = NULL; diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index abade20846..3306dfe61b 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -3634,6 +3634,97 @@ int flexran_get_s1ap_mme_conf(mid_t mod_id, mid_t mme_index, Protocol__FlexS1apM return 0; } +int flexran_add_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4) { + s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id); + if (!s1ap) return -1; + if (!rrc_is_present(mod_id)) return -2; + + /* Reconstruct S1AP_REGISTER_ENB_REQ */ + MessageDef *m = itti_alloc_new_message(TASK_FLEXRAN_AGENT, S1AP_REGISTER_ENB_REQ); + RCconfig_S1(m, mod_id); + + const int CC_id = 0; + eNB_RRC_INST *rrc = RC.rrc[CC_id]; + RrcConfigurationReq *conf = &rrc->configuration; + S1AP_REGISTER_ENB_REQ(m).num_plmn = conf->num_plmn; + for (int i = 0; i < conf->num_plmn; ++i) { + S1AP_REGISTER_ENB_REQ(m).mcc[i] = conf->mcc[i]; + S1AP_REGISTER_ENB_REQ(m).mnc[i] = conf->mnc[i]; + S1AP_REGISTER_ENB_REQ(m).mnc_digit_length[i] = conf->mnc_digit_length[i]; + } + + /* reconstruct MME list, it might have been updated since initial + * configuration */ + S1AP_REGISTER_ENB_REQ(m).nb_mme = 0; + struct s1ap_eNB_mme_data_s *mme = NULL; + RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head) { + const int n = S1AP_REGISTER_ENB_REQ(m).nb_mme; + S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4 = mme->mme_s1_ip.ipv4; + strcpy(S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4_address, mme->mme_s1_ip.ipv4_address); + S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv6 = mme->mme_s1_ip.ipv6; + strcpy(S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv6_address, mme->mme_s1_ip.ipv6_address); + S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_num[n] = mme->broadcast_plmn_num; + for (int i = 0; i < mme->broadcast_plmn_num; ++i) + S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_index[n][i] = mme->broadcast_plmn_index[i]; + S1AP_REGISTER_ENB_REQ(m).nb_mme += 1; + } + + if (S1AP_REGISTER_ENB_REQ(m).nb_mme + n_mme > S1AP_MAX_NB_MME_IP_ADDRESS) + return -1; + + for (int i = 0; i < n_mme; ++i) { + const int n = S1AP_REGISTER_ENB_REQ(m).nb_mme; + strcpy(S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4_address, mme_ipv4[0]); + S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4 = 1; + S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv6 = 0; + S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_num[n] = S1AP_REGISTER_ENB_REQ(m).num_plmn; + for (int i = 0; i < S1AP_REGISTER_ENB_REQ(m).num_plmn; ++i) + S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_index[n][i] = i; + S1AP_REGISTER_ENB_REQ(m).nb_mme += 1; + } + + itti_send_msg_to_task (TASK_S1AP, ENB_MODULE_ID_TO_INSTANCE(mod_id), m); + + return 0; +} + +int flexran_remove_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4) { + s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id); + if (!s1ap) return -1; + struct s1ap_eNB_mme_data_s *mme = NULL; + RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head) { + if (mme->mme_s1_ip.ipv4 + && strncmp(mme->mme_s1_ip.ipv4_address, mme_ipv4[0], 16) == 0) + break; + } + if (!mme) + return -2; + + MessageDef *m = itti_alloc_new_message(TASK_FLEXRAN_AGENT, SCTP_CLOSE_ASSOCIATION); + SCTP_CLOSE_ASSOCIATION(m).assoc_id = mme->assoc_id; + itti_send_msg_to_task (TASK_SCTP, ENB_MODULE_ID_TO_INSTANCE(mod_id), m); + + switch (mme->state) { + case S1AP_ENB_STATE_WAITING: + s1ap->s1ap_mme_nb -= 1; + if (s1ap->s1ap_mme_pending_nb > 0) + s1ap->s1ap_mme_pending_nb -= 1; + break; + case S1AP_ENB_STATE_CONNECTED: + case S1AP_ENB_OVERLOAD: /* I am not sure the decrements are right here */ + s1ap->s1ap_mme_nb -= 1; + s1ap->s1ap_mme_associated_nb -= 1; + break; + case S1AP_ENB_STATE_DISCONNECTED: + default: + break; + } + RB_REMOVE(s1ap_mme_map, &s1ap->s1ap_mme_head, mme); + + return 0; +} + + int flexran_get_s1ap_ue(mid_t mod_id, rnti_t rnti, Protocol__FlexS1apUe * ue_conf){ if (!rrc_is_present(mod_id)) return -1; s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id); diff --git a/openair2/ENB_APP/flexran_agent_ran_api.h b/openair2/ENB_APP/flexran_agent_ran_api.h index ce32883852..3c2803d663 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.h +++ b/openair2/ENB_APP/flexran_agent_ran_api.h @@ -832,6 +832,12 @@ int flexran_get_s1ap_mme_conf(mid_t mod_id, mid_t mme_index, Protocol__FlexS1apM /* Get the S1AP UE conf */ int flexran_get_s1ap_ue(mid_t mod_id, rnti_t rnti, Protocol__FlexS1apUe * ue_conf); +/* Add MMEs and re-issue S1AP Registration Request */ +int flexran_add_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4); + +/* Remove MMEs and and cut SCTP to MME */ +int flexran_remove_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4); + /********************* general information *****************/ /* get an ID for this BS (or part of a BS) */ uint64_t flexran_get_bs_id(mid_t mod_id); From f895a28645b277bfb3c061789594044839a6751a Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 11 Apr 2020 13:40:50 +0200 Subject: [PATCH 08/66] FlexRAN: Manage PLMNs --- .../CONTROL_MODULES/S1AP/flexran_agent_s1ap.c | 24 +++++++ .../CONTROL_MODULES/S1AP/flexran_agent_s1ap.h | 6 ++ openair2/ENB_APP/flexran_agent_common.c | 6 ++ openair2/ENB_APP/flexran_agent_ran_api.c | 71 +++++++++++++++++++ openair2/ENB_APP/flexran_agent_ran_api.h | 3 + 5 files changed, 110 insertions(+) diff --git a/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.c b/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.c index d5fc5627a0..c2d7cb9e55 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.c +++ b/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.c @@ -158,6 +158,30 @@ void flexran_agent_handle_mme_update(mid_t mod_id, } } +void flexran_agent_handle_plmn_update(mid_t mod_id, + int CC_id, + size_t n_plmn, + Protocol__FlexPlmn **plmn_id) { + if (n_plmn < 1 || n_plmn > 6) { + LOG_E(FLEXRAN_AGENT, "cannot handle %lu PLMNs\n", n_plmn); + return; + } + + /* We assume the controller has checked all the parameters within each + * plmn_id */ + int rc = flexran_set_new_plmn_id(mod_id, CC_id, n_plmn, plmn_id); + if (rc == 0) { + LOG_I(FLEXRAN_AGENT, "set %lu new PLMNs:\n", n_plmn); + for (int i = 0; i < (int)n_plmn; ++i) + LOG_I(FLEXRAN_AGENT, " MCC %d MNC %d MNC length %d\n", + plmn_id[i]->mcc, plmn_id[i]->mnc, plmn_id[0]->mnc_length); + } else { + LOG_W(FLEXRAN_AGENT, + "could not set new PLMN configuration: flexran_set_new_plmn_id() returned %d\n", + rc); + } +} + int flexran_agent_register_s1ap_xface(mid_t mod_id) { if (agent_s1ap_xface[mod_id]) { LOG_E(FLEXRAN_AGENT, "S1AP agent CM for eNB %d is already registered\n", mod_id); diff --git a/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.h b/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.h index 54ea2926a8..006eaa1d3c 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.h +++ b/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.h @@ -65,6 +65,12 @@ void flexran_agent_handle_mme_update(mid_t mod_id, size_t n_mme, Protocol__FlexS1apMme **mme); +/* Set a new PLMN configuration */ +void flexran_agent_handle_plmn_update(mid_t mod_id, + int CC_id, + size_t n_plmn, + Protocol__FlexPlmn **plmn_id); + /* Register technology specific interface callbacks */ int flexran_agent_register_s1ap_xface(mid_t mod_id); diff --git a/openair2/ENB_APP/flexran_agent_common.c b/openair2/ENB_APP/flexran_agent_common.c index ec0b780a3a..e77b2fb386 100644 --- a/openair2/ENB_APP/flexran_agent_common.c +++ b/openair2/ENB_APP/flexran_agent_common.c @@ -915,6 +915,12 @@ int flexran_agent_handle_enb_config_reply(mid_t mod_id, const void *params, Prot if (rc < 0) LOG_E(FLEXRAN_AGENT, "Error in configuring X2 handover controlled by network"); } + if (flexran_agent_get_rrc_xface(mod_id) && enb_config->cell_config[0]->n_plmn_id > 0) { + flexran_agent_handle_plmn_update(mod_id, + 0, + enb_config->cell_config[0]->n_plmn_id, + enb_config->cell_config[0]->plmn_id); + } } if (flexran_agent_get_s1ap_xface(mod_id) && enb_config->s1ap) { diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index 3306dfe61b..0fcc51782e 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -3724,6 +3724,77 @@ int flexran_remove_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4) { return 0; } +int flexran_set_new_plmn_id(mid_t mod_id, int CC_id, size_t n_plmn, Protocol__FlexPlmn **plmn_id) { + if (!rrc_is_present(mod_id)) + return -1; + s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id); + if (!s1ap) + return -2; + + eNB_RRC_INST *rrc = RC.rrc[CC_id]; + RrcConfigurationReq *conf = &rrc->configuration; + + uint8_t num_plmn_old = conf->num_plmn; + uint16_t mcc[PLMN_LIST_MAX_SIZE]; + uint16_t mnc[PLMN_LIST_MAX_SIZE]; + uint8_t mnc_digit_length[PLMN_LIST_MAX_SIZE]; + for (int i = 0; i < num_plmn_old; ++i) { + mcc[i] = conf->mcc[i]; + mnc[i] = conf->mnc[i]; + mnc_digit_length[i] = conf->mnc_digit_length[i]; + } + + conf->num_plmn = (uint8_t) n_plmn; + for (int i = 0; i < conf->num_plmn; ++i) { + conf->mcc[i] = plmn_id[i]->mcc; + conf->mnc[i] = plmn_id[i]->mnc; + conf->mnc_digit_length[i] = plmn_id[i]->mnc_length; + } + + rrc_eNB_carrier_data_t *carrier = &rrc->carrier[CC_id]; + extern uint8_t do_SIB1(rrc_eNB_carrier_data_t *carrier, + int Mod_id, + int CC_id, + BOOLEAN_t brOption, + RrcConfigurationReq *configuration); + carrier->sizeof_SIB1 = do_SIB1(carrier, mod_id, CC_id, FALSE, conf); + if (carrier->sizeof_SIB1 < 0) + return -1337; /* SIB1 encoding failed, hell will probably break loose */ + + s1ap->num_plmn = (uint8_t) n_plmn; + for (int i = 0; i < conf->num_plmn; ++i) { + s1ap->mcc[i] = plmn_id[i]->mcc; + s1ap->mnc[i] = plmn_id[i]->mnc; + s1ap->mnc_digit_length[i] = plmn_id[i]->mnc_length; + } + + int bpn_failed = 0; + struct s1ap_eNB_mme_data_s *mme = NULL; + RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head) { + for (int i = 0; i < mme->broadcast_plmn_num; ++i) { + /* search the new index and update. If we don't find, we count this using + * bpn_failed to now how many broadcast_plmns could not be updated */ + int idx = mme->broadcast_plmn_index[i]; + int omcc = mcc[idx]; + int omnc = mnc[idx]; + int omncl = mnc_digit_length[idx]; + int j = 0; + for (j = 0; j < s1ap->num_plmn; ++j) { + if (s1ap->mcc[j] == omcc + && s1ap->mnc[j] == omnc + && s1ap->mnc_digit_length[j] == omncl) { + mme->broadcast_plmn_index[i] = j; + break; + } + } + if (j == s1ap->num_plmn) /* could not find the old PLMN in the new ones */ + bpn_failed++; + } + } + if (bpn_failed > 0) + return -10000 - bpn_failed; + return 0; +} int flexran_get_s1ap_ue(mid_t mod_id, rnti_t rnti, Protocol__FlexS1apUe * ue_conf){ if (!rrc_is_present(mod_id)) return -1; diff --git a/openair2/ENB_APP/flexran_agent_ran_api.h b/openair2/ENB_APP/flexran_agent_ran_api.h index 3c2803d663..9d1bfb9d3e 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.h +++ b/openair2/ENB_APP/flexran_agent_ran_api.h @@ -838,6 +838,9 @@ int flexran_add_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4); /* Remove MMEs and and cut SCTP to MME */ int flexran_remove_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4); +/* Set a new PLMN configuration */ +int flexran_set_new_plmn_id(mid_t mod_id, int CC_id, size_t n_plmn, Protocol__FlexPlmn **plmn_id); + /********************* general information *****************/ /* get an ID for this BS (or part of a BS) */ uint64_t flexran_get_bs_id(mid_t mod_id); From d2cc43b4e772de499a406f0e199e1c26851d42d3 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 14 Apr 2020 14:47:27 +0200 Subject: [PATCH 09/66] UE: Print all SIB1 decoded PLMNs --- openair2/RRC/LTE/rrc_UE.c | 65 +++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/openair2/RRC/LTE/rrc_UE.c b/openair2/RRC/LTE/rrc_UE.c index 4116f5367e..53348f5621 100644 --- a/openair2/RRC/LTE/rrc_UE.c +++ b/openair2/RRC/LTE/rrc_UE.c @@ -2794,44 +2794,43 @@ int decode_SIB1( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index, LTE_SystemInformationBlockType1_t *sib1 = UE_rrc_inst[ctxt_pP->module_id].sib1[eNB_index]; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SIB1, VCD_FUNCTION_IN ); LOG_I( RRC, "[UE %d] : Dumping SIB 1\n", ctxt_pP->module_id ); - LTE_PLMN_Identity_t *PLMN_identity = &sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->plmn_Identity; - int mccdigits = PLMN_identity->mcc->list.count; - int mncdigits = PLMN_identity->mnc.list.count; - int mcc; + const int n = sib1->cellAccessRelatedInfo.plmn_IdentityList.list.count; + for (int i = 0; i < n; ++i) { + LTE_PLMN_Identity_t *PLMN_identity = &sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[i]->plmn_Identity; + int mccdigits = PLMN_identity->mcc->list.count; + int mncdigits = PLMN_identity->mnc.list.count; - if (mccdigits == 2) { - mcc = *PLMN_identity->mcc->list.array[0]*10 + *PLMN_identity->mcc->list.array[1]; - } else { - mcc = *PLMN_identity->mcc->list.array[0]*100 + *PLMN_identity->mcc->list.array[1]*10 + *PLMN_identity->mcc->list.array[2]; + int mcc; + if (mccdigits == 2) { + mcc = *PLMN_identity->mcc->list.array[0]*10 + *PLMN_identity->mcc->list.array[1]; + } else { + mcc = *PLMN_identity->mcc->list.array[0]*100 + *PLMN_identity->mcc->list.array[1]*10 + *PLMN_identity->mcc->list.array[2]; + } + + int mnc; + if (mncdigits == 2) { + mnc = *PLMN_identity->mnc.list.array[0]*10 + *PLMN_identity->mnc.list.array[1]; + } else { + mnc = *PLMN_identity->mnc.list.array[0]*100 + *PLMN_identity->mnc.list.array[1]*10 + *PLMN_identity->mnc.list.array[2]; + } + + LOG_I( RRC, "PLMN %d MCC %0*d, MNC %0*d\n", i + 1, mccdigits, mcc, mncdigits, mnc); + // search internal table for provider name + int plmn_ind = 0; + + while (plmn_data[plmn_ind].mcc > 0) { + if ((plmn_data[plmn_ind].mcc == mcc) && (plmn_data[plmn_ind].mnc == mnc)) { + LOG_I( RRC, "Found %s (name from internal table)\n", plmn_data[plmn_ind].oper_short ); + break; + } + + plmn_ind++; + } } - - int mnc; - - if (mncdigits == 2) { - mnc = *PLMN_identity->mnc.list.array[0]*10 + *PLMN_identity->mnc.list.array[1]; - } else { - mnc = *PLMN_identity->mnc.list.array[0]*100 + *PLMN_identity->mnc.list.array[1]*10 + *PLMN_identity->mnc.list.array[2]; - } - - LOG_I( RRC, "PLMN MCC %0*d, MNC %0*d, TAC 0x%04x\n", mccdigits, mcc, mncdigits, mnc, + LOG_I( RRC, "TAC 0x%04x\n", ((sib1->cellAccessRelatedInfo.trackingAreaCode.size == 2)?((sib1->cellAccessRelatedInfo.trackingAreaCode.buf[0]<<8) + sib1->cellAccessRelatedInfo.trackingAreaCode.buf[1]):0)); LOG_I( RRC, "cellReservedForOperatorUse : raw:%ld decoded:%s\n", sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellReservedForOperatorUse, SIBreserved(sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellReservedForOperatorUse) ); - // search internal table for provider name - int plmn_ind = 0; - - while (plmn_data[plmn_ind].mcc > 0) { - if ((plmn_data[plmn_ind].mcc == mcc) && (plmn_data[plmn_ind].mnc == mnc)) { - LOG_I( RRC, "Found %s (name from internal table)\n", plmn_data[plmn_ind].oper_short ); - break; - } - - plmn_ind++; - } - - if (plmn_data[plmn_ind].mcc < 0) { - LOG_I( RRC, "Found Unknown operator (no entry in internal table)\n" ); - } LOG_I( RRC, "cellAccessRelatedInfo.cellIdentity : raw:%"PRIu32" decoded:%02x.%02x.%02x.%02x\n", BIT_STRING_to_uint32( &sib1->cellAccessRelatedInfo.cellIdentity ), From 9d5a46dcfa12985d5e52b8066bdfa6b696e008ef Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 14 Apr 2020 14:47:59 +0200 Subject: [PATCH 10/66] UE: Set correct selected PLMN Identity --- openair2/RRC/LTE/MESSAGES/asn1_msg.c | 4 ++-- openair2/RRC/LTE/MESSAGES/asn1_msg.h | 6 +++++- openair2/RRC/LTE/rrc_UE.c | 26 +++++++++++++++++++++----- openair2/RRC/LTE/rrc_defs.h | 1 + 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/openair2/RRC/LTE/MESSAGES/asn1_msg.c b/openair2/RRC/LTE/MESSAGES/asn1_msg.c index 583e10da94..9ede543003 100644 --- a/openair2/RRC/LTE/MESSAGES/asn1_msg.c +++ b/openair2/RRC/LTE/MESSAGES/asn1_msg.c @@ -2310,7 +2310,7 @@ uint8_t do_SidelinkUEInformation(uint8_t Mod_id, uint8_t *buffer, LTE_SL_Destin return((enc_rval.encoded+7)/8); } -uint8_t do_RRCConnectionSetupComplete(uint8_t Mod_id, uint8_t *buffer, const uint8_t Transaction_id, const int dedicatedInfoNASLength, const char *dedicatedInfoNAS) { +uint8_t do_RRCConnectionSetupComplete(uint8_t Mod_id, uint8_t *buffer, const uint8_t Transaction_id, uint8_t sel_plmn_id, const int dedicatedInfoNASLength, const char *dedicatedInfoNAS) { asn_enc_rval_t enc_rval; LTE_UL_DCCH_Message_t ul_dcch_msg; LTE_RRCConnectionSetupComplete_t *rrcConnectionSetupComplete; @@ -2323,7 +2323,7 @@ uint8_t do_RRCConnectionSetupComplete(uint8_t Mod_id, uint8_t *buffer, const uin rrcConnectionSetupComplete->criticalExtensions.choice.c1.present = LTE_RRCConnectionSetupComplete__criticalExtensions__c1_PR_rrcConnectionSetupComplete_r8; rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.nonCriticalExtension=CALLOC(1, sizeof(*rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.nonCriticalExtension)); - rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.selectedPLMN_Identity= 1; + rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.selectedPLMN_Identity= sel_plmn_id; rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.registeredMME = NULL;//calloc(1,sizeof(*rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.registeredMME)); /* diff --git a/openair2/RRC/LTE/MESSAGES/asn1_msg.h b/openair2/RRC/LTE/MESSAGES/asn1_msg.h index dda2340610..640d18a61f 100644 --- a/openair2/RRC/LTE/MESSAGES/asn1_msg.h +++ b/openair2/RRC/LTE/MESSAGES/asn1_msg.h @@ -142,7 +142,11 @@ uint8_t do_SidelinkUEInformation(uint8_t Mod_id, uint8_t *buffer, LTE_SL_Destina /** \brief Generate an RRCConnectionSetupComplete UL-DCCH-Message (UE) @param buffer Pointer to PER-encoded ASN.1 description of UL-DCCH-Message PDU @returns Size of encoded bit stream in bytes*/ -uint8_t do_RRCConnectionSetupComplete(uint8_t Mod_id, uint8_t *buffer, const uint8_t Transaction_id, const int dedicatedInfoNASLength, +uint8_t do_RRCConnectionSetupComplete(uint8_t Mod_id, + uint8_t *buffer, + const uint8_t Transaction_id, + uint8_t sel_plmn_id, + const int dedicatedInfoNASLength, const char *dedicatedInfoNAS); /** \brief Generate an RRCConnectionReconfigurationComplete UL-DCCH-Message (UE) diff --git a/openair2/RRC/LTE/rrc_UE.c b/openair2/RRC/LTE/rrc_UE.c index 53348f5621..bdf992c76a 100644 --- a/openair2/RRC/LTE/rrc_UE.c +++ b/openair2/RRC/LTE/rrc_UE.c @@ -128,8 +128,13 @@ static int decode_SIB1_MBMS( const protocol_ctxt_t *const ctxt_pP, const uint8_t * \param ctxt_pP Running context * \param eNB_index Index of corresponding eNB/CH * \param Transaction_id Transaction identifier + * \param sel_plmn_id selected PLMN Identity */ -static void rrc_ue_generate_RRCConnectionSetupComplete( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index, const uint8_t Transaction_id ); +static void rrc_ue_generate_RRCConnectionSetupComplete( + const protocol_ctxt_t *const ctxt_pP, + const uint8_t eNB_index, + const uint8_t Transaction_id, + uint8_t sel_plmn_id); /** \brief Generates/Encodes RRCConnectionReconfigurationComplete message at UE * \param ctxt_pP Running context @@ -367,6 +372,7 @@ char openair_rrc_ue_init( const module_id_t ue_mod_idP, const unsigned char eNB_ rrc_set_state (ue_mod_idP, RRC_STATE_INACTIVE); rrc_set_sub_state (ue_mod_idP, RRC_SUB_STATE_INACTIVE); LOG_I(RRC,"[UE %d] INIT State = RRC_IDLE (eNB %d)\n",ctxt.module_id,eNB_index); + UE_rrc_inst[ctxt.module_id].selected_plmn_identity = 1; UE_rrc_inst[ctxt.module_id].Info[eNB_index].State=RRC_IDLE; UE_rrc_inst[ctxt.module_id].Info[eNB_index].T300_active = 0; UE_rrc_inst[ctxt.module_id].Info[eNB_index].T304_active = 0; @@ -490,7 +496,11 @@ rrc_t310_expiration( } //----------------------------------------------------------------------------- -static void rrc_ue_generate_RRCConnectionSetupComplete( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index, const uint8_t Transaction_id ) { +static void rrc_ue_generate_RRCConnectionSetupComplete( + const protocol_ctxt_t *const ctxt_pP, + const uint8_t eNB_index, + const uint8_t Transaction_id, + uint8_t sel_plmn_id) { uint8_t buffer[100]; uint8_t size; const char *nas_msg; @@ -504,7 +514,7 @@ static void rrc_ue_generate_RRCConnectionSetupComplete( const protocol_ctxt_t *c nas_msg_length = sizeof(nas_attach_req_imsi); } - size = do_RRCConnectionSetupComplete(ctxt_pP->module_id, buffer, Transaction_id, nas_msg_length, nas_msg); + size = do_RRCConnectionSetupComplete(ctxt_pP->module_id, buffer, Transaction_id, sel_plmn_id, nas_msg_length, nas_msg); LOG_I(RRC,"[UE %d][RAPROC] Frame %d : Logical Channel UL-DCCH (SRB1), Generating RRCConnectionSetupComplete (bytes%d, eNB %d)\n", ctxt_pP->module_id,ctxt_pP->frame, size, eNB_index); LOG_D(RLC, @@ -624,7 +634,8 @@ int rrc_ue_decode_ccch( const protocol_ctxt_t *const ctxt_pP, const SRB_INFO *co rrc_ue_generate_RRCConnectionSetupComplete( ctxt_pP, eNB_index, - dl_ccch_msg->message.choice.c1.choice.rrcConnectionSetup.rrc_TransactionIdentifier); + dl_ccch_msg->message.choice.c1.choice.rrcConnectionSetup.rrc_TransactionIdentifier, + UE_rrc_inst[ctxt_pP->module_id].selected_plmn_identity); rval = 0; break; @@ -2969,6 +2980,7 @@ int decode_SIB1( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index, NAS_CELL_SELECTION_CNF (msg_p).rsrp = rsrp; itti_send_msg_to_task(TASK_NAS_UE, ctxt_pP->instance, msg_p); cell_valid = 1; + UE_rrc_inst[ctxt_pP->module_id].selected_plmn_identity = plmn + 1; break; } } @@ -2979,7 +2991,11 @@ int decode_SIB1( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index, MessageDef *msg_p; msg_p = itti_alloc_new_message(TASK_RRC_UE, PHY_FIND_NEXT_CELL_REQ); itti_send_msg_to_task(TASK_PHY_UE, ctxt_pP->instance, msg_p); - LOG_E(RRC, "Synched with a cell, but PLMN doesn't match our SIM, the message PHY_FIND_NEXT_CELL_REQ is sent but lost in current UE implementation! \n"); + LOG_E(RRC, + "Synched with a cell, but PLMN doesn't match our SIM " + "(selected_plmn_identity %d), the message PHY_FIND_NEXT_CELL_REQ " + "is sent but lost in current UE implementation!\n", + UE_rrc_inst[ctxt_pP->module_id].selected_plmn_identity); } } diff --git a/openair2/RRC/LTE/rrc_defs.h b/openair2/RRC/LTE/rrc_defs.h index 42fa5f6de1..03b6c759b6 100644 --- a/openair2/RRC/LTE/rrc_defs.h +++ b/openair2/RRC/LTE/rrc_defs.h @@ -808,6 +808,7 @@ typedef struct UE_RRC_INST_s { Rrc_Sub_State_t RrcSubState; plmn_t plmnID; Byte_t rat; + uint8_t selected_plmn_identity; as_nas_info_t initialNasMsg; OAI_UECapability_t *UECap; uint8_t *UECapability; From 476d58a8deef0f15ce3a59870e4cc80a122313e8 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 21 May 2020 21:18:26 +0200 Subject: [PATCH 11/66] Log TBS in every window --- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 7621994ab2..2382af3636 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -588,6 +588,7 @@ schedule_ue_spec(module_id_t module_idP, UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; UE_TEMPLATE *ue_template = &UE_info->UE_template[CC_id][UE_id]; eNB_UE_STATS *eNB_UE_stats = &UE_info->eNB_UE_stats[CC_id][UE_id]; + eNB_UE_stats->TBS = 0; const rnti_t rnti = ue_template->rnti; // If TDD @@ -799,6 +800,7 @@ schedule_ue_spec(module_id_t module_idP, eNB_UE_stats->rbs_used_retx = nb_rb; eNB_UE_stats->total_rbs_used_retx += nb_rb; eNB_UE_stats->dlsch_mcs2 = eNB_UE_stats->dlsch_mcs1; + eNB_UE_stats->TBS = TBS; } else { // Now check RLC information to compute number of required RBs // get maximum TBS size for RLC request From 71647eb4effe80bf5defada0e314acbd4e98f7a1 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 12 Jun 2020 19:25:44 +0200 Subject: [PATCH 12/66] DLSCH: limit LC bytes according to preprocessor --- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 2382af3636..c35af34a7f 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -844,13 +844,18 @@ schedule_ue_spec(module_id_t module_idP, if (ue_sched_ctrl->dl_lc_bytes[i] == 0) // no data in this LC! continue; - LOG_D(MAC, "[eNB %d] SFN/SF %d.%d, LC%d->DLSCH CC_id %d, Requesting %d bytes from RLC (RRC message)\n", + const uint32_t data = + min(ue_sched_ctrl->dl_lc_bytes[i], + TBS - ta_len - header_length_total - sdu_length_total - 3); + LOG_D(MAC, + "[eNB %d] SFN/SF %d.%d, LC%d->DLSCH CC_id %d, Requesting %d " + "bytes from RLC (RRC message)\n", module_idP, frameP, subframeP, lcid, CC_id, - TBS - ta_len - header_length_total - sdu_length_total - 3); + data); sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, rnti, @@ -859,7 +864,7 @@ schedule_ue_spec(module_id_t module_idP, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, - TBS - ta_len - header_length_total - sdu_length_total - 3, + data, (char *)&dlsch_buffer[sdu_length_total], 0, 0 From b06dadbdb0d25162149d016650740f2b6a75f3e2 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 24 Jun 2020 14:24:02 +0200 Subject: [PATCH 13/66] Bugfix DLSCH: only warn when retx with less RB The preprocessor pre-allocates a CCE. Thus, when arriving at the check for the number of RBs for retransmission, it is too late to skip the UE. Therefore, only print a warning. The default schedulers allocate a correct amount of RBs for retransmissions, therefore it is ok. --- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index c35af34a7f..783d4e8b1a 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -680,15 +680,15 @@ schedule_ue_spec(module_id_t module_idP, const uint32_t rbc = allocate_prbs_sub( nb_rb, N_RB_DL, N_RBG, ue_sched_ctrl->rballoc_sub_UE[CC_id]); - if (nb_rb > ue_sched_ctrl->pre_nb_available_rbs[CC_id]) { - LOG_D(MAC, - "[eNB %d] Frame %d CC_id %d : don't schedule UE %d, its retransmission takes more resources than we have\n", + if (nb_rb > ue_sched_ctrl->pre_nb_available_rbs[CC_id]) + LOG_W(MAC, + "[eNB %d] %d.%d CC_id %d : should not schedule UE %d, its " + "retransmission takes more resources than we have\n", module_idP, frameP, + subframeP, CC_id, UE_id); - continue; - } /* CDRX */ ue_sched_ctrl->harq_rtt_timer[CC_id][harq_pid] = 1; // restart HARQ RTT timer From 1401d21081805d42f45ced99becbb2dbd5907ee8 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 20 May 2020 12:45:35 +0200 Subject: [PATCH 14/66] Default SCHED RR algo: optimize algo and defer RB calc. - Loop only to next UE instead of jumping multiple - mark used RBGs in rbg_mask - Only calculate number of RBs based on CQI when UE is selected, instead of calculating for all UEs which might be unnecessary. - When looping the list of UEs for RB allocation, remove UEs that have no data anymore instead of skipping them. --- openair2/LAYER2/MAC/pre_processor.c | 72 ++++++++++------------------- 1 file changed, 25 insertions(+), 47 deletions(-) diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 8569d8f166..d4e39b2b6b 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -86,9 +86,6 @@ int round_robin_dl(module_id_t Mod_id, int num_ue_req = 0; UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; - int rb_required[MAX_MOBILES_PER_ENB]; // how much UEs request - memset(rb_required, 0, sizeof(rb_required)); - int rbg = 0; for (; !rbgalloc_mask[rbg]; rbg++) ; /* fast-forward to first allowed RBG */ @@ -133,6 +130,7 @@ int round_robin_dl(module_id_t Mod_id, if (!rbgalloc_mask[rbg]) continue; ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1; + rbgalloc_mask[rbg] = 0; nb_rbg--; } LOG_D(MAC, @@ -150,22 +148,8 @@ int round_robin_dl(module_id_t Mod_id, return n_rbg_sched; for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; } else { - const int dlsch_mcs1 = cqi_to_mcs[UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]]; - UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = dlsch_mcs1; - rb_required[UE_id] = - find_nb_rb_DL(dlsch_mcs1, - UE_info->UE_template[CC_id][UE_id].dl_buffer_total, - n_rbg_sched * RBGsize, - RBGsize); - if (rb_required[UE_id] > 0) + if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total > 0) num_ue_req++; - LOG_D(MAC, - "%d/%d UE_id %d rb_required %d n_rbg_sched %d\n", - frame, - subframe, - UE_id, - rb_required[UE_id], - n_rbg_sched); } } @@ -178,12 +162,13 @@ int round_robin_dl(module_id_t Mod_id, g_start_ue_dl = UE_list->head; int UE_id = g_start_ue_dl; UE_list_t UE_sched; - int rb_required_total = 0; + int *cur_UE = &UE_sched.head; + int num_ue_sched = 0; max_num_ue = min(min(max_num_ue, num_ue_req), n_rbg_sched); - int *cur_UE = &UE_sched.head; + int rb_required[MAX_MOBILES_PER_ENB]; // how much UEs request while (num_ue_sched < max_num_ue) { - while (rb_required[UE_id] == 0) + while (UE_info->UE_template[CC_id][UE_id].dl_buffer_total <= 0) UE_id = next_ue_list_looped(UE_list, UE_id); const uint8_t cqi = UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]; const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi); @@ -195,42 +180,42 @@ int round_robin_dl(module_id_t Mod_id, continue; } UE_info->UE_sched_ctrl[UE_id].pre_dci_dl_pdu_idx = idx; + const int mcs = cqi_to_mcs[cqi]; + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = mcs; + const uint32_t B = UE_info->UE_template[CC_id][UE_id].dl_buffer_total; + rb_required[UE_id] = find_nb_rb_DL(mcs, B, n_rbg_sched * RBGsize, RBGsize); *cur_UE = UE_id; cur_UE = &UE_sched.next[UE_id]; - rb_required_total += rb_required[UE_id]; num_ue_sched++; UE_id = next_ue_list_looped(UE_list, UE_id); // next candidate } *cur_UE = -1; /* for one UE after the next: allocate resources */ - for (int UE_id = UE_sched.head; UE_id >= 0; - UE_id = next_ue_list_looped(&UE_sched, UE_id)) { - if (rb_required[UE_id] <= 0) - continue; + cur_UE = &UE_sched.head; + while (*cur_UE >= 0) { + const int UE_id = *cur_UE; UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id]; ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1; + rbgalloc_mask[rbg] = 0; const int sRBG = rbg == N_RBG - 1 ? RBGlastsize : RBGsize; ue_ctrl->pre_nb_available_rbs[CC_id] += sRBG; rb_required[UE_id] -= sRBG; - rb_required_total -= sRBG; - if (rb_required_total <= 0) - break; + if (rb_required[UE_id] <= 0) { + *cur_UE = UE_sched.next[*cur_UE]; + if (*cur_UE < 0) + cur_UE = &UE_sched.head; + } else { + cur_UE = UE_sched.next[*cur_UE] < 0 ? &UE_sched.head : &UE_sched.next[*cur_UE]; + } n_rbg_sched--; if (n_rbg_sched <= 0) break; for (rbg++; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; } - /* if not all UEs could be allocated in this round */ - if (num_ue_req > max_num_ue) { - /* go to the first one we missed */ - for (int i = 0; i < max_num_ue; ++i) - g_start_ue_dl = next_ue_list_looped(UE_list, g_start_ue_dl); - } else { - /* else, just start with the next UE next time */ - g_start_ue_dl = next_ue_list_looped(UE_list, g_start_ue_dl); - } + /* just start with the next UE next time */ + g_start_ue_dl = next_ue_list_looped(UE_list, g_start_ue_dl); return n_rbg_sched; } @@ -730,15 +715,8 @@ int round_robin_ul(module_id_t Mod_id, } } - /* if not all UEs could be allocated in this round */ - if (num_ue_req > max_num_ue) { - /* go to the first one we missed */ - for (int i = 0; i < max_num_ue; ++i) - g_start_ue_ul = next_ue_list_looped(UE_list, g_start_ue_ul); - } else { - /* else, just start with the next UE next time */ - g_start_ue_ul = next_ue_list_looped(UE_list, g_start_ue_ul); - } + /* just start with the next UE next time */ + g_start_ue_ul = next_ue_list_looped(UE_list, g_start_ue_ul); return rbs[0].length + (num_contig_rb > 1 ? rbs[1].length : 0); } From 31ad66e146b0ceaabe45688e43bf9ae131bfd8ce Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 24 Jun 2020 14:20:27 +0200 Subject: [PATCH 15/66] Bugfix RR DL: a retx UE might not be allocated again --- openair2/LAYER2/MAC/pre_processor.c | 68 ++++++++++++++--------------- 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index d4e39b2b6b..eea3b55f6e 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -83,15 +83,22 @@ int round_robin_dl(module_id_t Mod_id, const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); const int RBGsize = get_min_rb_unit(Mod_id, CC_id); const int RBGlastsize = get_rbg_size_last(Mod_id, CC_id); - int num_ue_req = 0; UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; int rbg = 0; for (; !rbgalloc_mask[rbg]; rbg++) ; /* fast-forward to first allowed RBG */ - // Calculate the amount of RBs every UE wants to send. - for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + /* just start with the UE after the one we had last time. If it does not + * exist, this will start at the head */ + int g_start_ue_dl = data; + g_start_ue_dl = next_ue_list_looped(UE_list, g_start_ue_dl); + + int UE_id = g_start_ue_dl; + UE_list_t UE_sched; + int *cur_UE = &UE_sched.head; + // Allocate retransmissions, and mark UEs with new transmissions + do { // check whether there are HARQ retransmissions const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id]; const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, frame, subframe); @@ -100,14 +107,14 @@ int round_robin_dl(module_id_t Mod_id, if (round != 8) { // retransmission: allocate const int nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid]; if (nb_rb == 0) - continue; + goto skip_ue; int nb_rbg = (nb_rb + (nb_rb % RBGsize)) / RBGsize; // needs more RBGs than we can allocate if (nb_rbg > n_rbg_sched) { LOG_D(MAC, "retransmission of UE %d needs more RBGs (%d) than we have (%d)\n", UE_id, nb_rbg, n_rbg_sched); - continue; + goto skip_ue; } // ensure that the number of RBs can be contained by the RBGs (!), i.e. // if we allocate the last RBG this one should have the full RBGsize @@ -116,12 +123,12 @@ int round_robin_dl(module_id_t Mod_id, LOG_D(MAC, "retransmission of UE %d needs %d RBs, but the last RBG %d is too small (%d, normal %d)\n", UE_id, nb_rb, N_RBG - 1, RBGlastsize, RBGsize); - continue; + goto skip_ue; } const uint8_t cqi = ue_ctrl->dl_cqi[CC_id]; const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi); if (idx < 0) - continue; // cannot allocate CCE + goto skip_ue; // cannot allocate CCE ue_ctrl->pre_dci_dl_pdu_idx = idx; // retransmissions: directly allocate n_rbg_sched -= nb_rbg; @@ -148,35 +155,32 @@ int round_robin_dl(module_id_t Mod_id, return n_rbg_sched; for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; } else { - if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total > 0) - num_ue_req++; + if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total > 0) { + *cur_UE = UE_id; + cur_UE = &UE_sched.next[UE_id]; + } } - } - if (num_ue_req == 0) +skip_ue: + UE_id = next_ue_list_looped(UE_list, UE_id); + } while (UE_id != g_start_ue_dl); + *cur_UE = -1; // mark end + + if (UE_sched.head < 0) return n_rbg_sched; // no UE has a transmission - // after allocating retransmissions: build list of UE to allocate. - // if start_UE does not exist anymore (detach etc), start at first UE - if (g_start_ue_dl == -1) - g_start_ue_dl = UE_list->head; - int UE_id = g_start_ue_dl; - UE_list_t UE_sched; - int *cur_UE = &UE_sched.head; - - int num_ue_sched = 0; - max_num_ue = min(min(max_num_ue, num_ue_req), n_rbg_sched); + // after allocating retransmissions: pre-allocate CCE, compute number of + // requested RBGs + max_num_ue = min(max_num_ue, n_rbg_sched); int rb_required[MAX_MOBILES_PER_ENB]; // how much UEs request - while (num_ue_sched < max_num_ue) { - while (UE_info->UE_template[CC_id][UE_id].dl_buffer_total <= 0) - UE_id = next_ue_list_looped(UE_list, UE_id); + cur_UE = &UE_sched.head; + while (*cur_UE >= 0 && max_num_ue > 0) { + const int UE_id = *cur_UE; + cur_UE = &UE_sched.next[UE_id]; // go to next const uint8_t cqi = UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]; const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi); if (idx < 0) { LOG_D(MAC, "cannot allocate CCE for UE %d, skipping\n", UE_id); - num_ue_req--; - max_num_ue = min(min(max_num_ue, num_ue_req), n_rbg_sched); - UE_id = next_ue_list_looped(UE_list, UE_id); // next candidate continue; } UE_info->UE_sched_ctrl[UE_id].pre_dci_dl_pdu_idx = idx; @@ -184,12 +188,9 @@ int round_robin_dl(module_id_t Mod_id, UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = mcs; const uint32_t B = UE_info->UE_template[CC_id][UE_id].dl_buffer_total; rb_required[UE_id] = find_nb_rb_DL(mcs, B, n_rbg_sched * RBGsize, RBGsize); - *cur_UE = UE_id; - cur_UE = &UE_sched.next[UE_id]; - num_ue_sched++; - UE_id = next_ue_list_looped(UE_list, UE_id); // next candidate + max_num_ue--; } - *cur_UE = -1; + *cur_UE = -1; // not all UEs might be allocated, mark end /* for one UE after the next: allocate resources */ cur_UE = &UE_sched.head; @@ -214,9 +215,6 @@ int round_robin_dl(module_id_t Mod_id, for (rbg++; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; } - /* just start with the next UE next time */ - g_start_ue_dl = next_ue_list_looped(UE_list, g_start_ue_dl); - return n_rbg_sched; } From dc5357ca13d6dda0768e047168522c503bf3fb4a Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 17 Jun 2020 11:05:35 +0200 Subject: [PATCH 16/66] Format to dynamically handle default DL SCHED algo --- openair2/LAYER2/MAC/mac.h | 15 +++++++ openair2/LAYER2/MAC/main.c | 6 ++- openair2/LAYER2/MAC/pre_processor.c | 69 +++++++++++++++++++---------- 3 files changed, 65 insertions(+), 25 deletions(-) diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h index 329e262c82..0264951683 100644 --- a/openair2/LAYER2/MAC/mac.h +++ b/openair2/LAYER2/MAC/mac.h @@ -1274,6 +1274,19 @@ typedef struct { int length; } contig_rbs_t; +/** + * definition of a scheduling algorithm implementation used in the + * default scheduler + */ +typedef struct { + char *name; + void *(*setup)(void); + void (*unset)(void **); + int (*run)( + module_id_t, int, int, int, UE_list_t *, int, int, uint8_t *, void *); + void *data; +} default_sched_dl_algo_t; + /*! \brief eNB common channels */ typedef struct { int physCellId; @@ -1432,6 +1445,8 @@ typedef struct eNB_MAC_INST_s { UE_free_list_t UE_free_list; /// for scheduling selection SCHEDULER_MODES scheduler_mode; + /// scheduling algorithm used in default scheduler + default_sched_dl_algo_t dl_algo; int32_t puSch10xSnr; int32_t puCch10xSnr; diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index 1a88623a1f..39e342cba0 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -128,7 +128,11 @@ void mac_top_init_eNB(void) } mac[i]->if_inst = IF_Module_init(i); - + char *s = "round_robin_dl"; + void *d = dlsym(NULL, s); + AssertFatal(d, "%s(): no scheduler algo '%s' found\n", __func__, s); + mac[i]->dl_algo = *(default_sched_dl_algo_t *) d; + mac[i]->dl_algo.data = mac[i]->dl_algo.setup(); init_UE_info(&mac[i]->UE_info); init_slice_info(&mac[i]->slice_info); } diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index eea3b55f6e..8c4b91ce87 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -69,15 +69,26 @@ int get_rbg_size_last(module_id_t Mod_id, int CC_id) { return RBGsize; } -int g_start_ue_dl = -1; -int round_robin_dl(module_id_t Mod_id, - int CC_id, - int frame, - int subframe, - UE_list_t *UE_list, - int max_num_ue, - int n_rbg_sched, - uint8_t *rbgalloc_mask) { +void *rr_dl_setup(void) { + void *data = malloc(sizeof(int)); + *(int *) data = 0; + AssertFatal(data, "could not allocate data in %s()\n", __func__); + return data; +} +void rr_dl_unset(void **data) { + if (*data) + free(*data); + *data = NULL; +} +int rr_dl_run(module_id_t Mod_id, + int CC_id, + int frame, + int subframe, + UE_list_t *UE_list, + int max_num_ue, + int n_rbg_sched, + uint8_t *rbgalloc_mask, + void *data) { DevAssert(UE_list->head >= 0); DevAssert(n_rbg_sched > 0); const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); @@ -91,10 +102,10 @@ int round_robin_dl(module_id_t Mod_id, /* just start with the UE after the one we had last time. If it does not * exist, this will start at the head */ - int g_start_ue_dl = data; - g_start_ue_dl = next_ue_list_looped(UE_list, g_start_ue_dl); + int *start_ue = data; + *start_ue = next_ue_list_looped(UE_list, *start_ue); - int UE_id = g_start_ue_dl; + int UE_id = *start_ue; UE_list_t UE_sched; int *cur_UE = &UE_sched.head; // Allocate retransmissions, and mark UEs with new transmissions @@ -163,7 +174,7 @@ int round_robin_dl(module_id_t Mod_id, skip_ue: UE_id = next_ue_list_looped(UE_list, UE_id); - } while (UE_id != g_start_ue_dl); + } while (UE_id != *start_ue); *cur_UE = -1; // mark end if (UE_sched.head < 0) @@ -217,6 +228,14 @@ skip_ue: return n_rbg_sched; } +default_sched_dl_algo_t round_robin_dl = { + .name = "round_robin_dl", + .setup = rr_dl_setup, + .unset = rr_dl_unset, + .run = rr_dl_run, + .data = NULL +}; + // This function stores the downlink buffer for all the logical channels void @@ -294,8 +313,9 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, int CC_id, frame_t frameP, sub_frame_t subframeP) { - UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; - const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); + eNB_MAC_INST *mac = RC.mac[Mod_id]; + UE_info_t *UE_info = &mac->UE_info; + const int N_RBG = to_rbg(mac->common_channels[CC_id].mib->message.dl_Bandwidth); const int RBGsize = get_min_rb_unit(Mod_id, CC_id); store_dlsch_buffer(Mod_id, CC_id, frameP, subframeP); @@ -352,7 +372,7 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, if (UE_to_sched.head < 0) return; - uint8_t *vrb_map = RC.mac[Mod_id]->common_channels[CC_id].vrb_map; + uint8_t *vrb_map = mac->common_channels[CC_id].vrb_map; uint8_t rbgalloc_mask[N_RBG_MAX]; int n_rbg_sched = 0; for (int i = 0; i < N_RBG; i++) { @@ -364,14 +384,15 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, n_rbg_sched += rbgalloc_mask[i]; } - round_robin_dl(Mod_id, - CC_id, - frameP, - subframeP, - &UE_to_sched, - 4, // max_num_ue - n_rbg_sched, - rbgalloc_mask); + mac->dl_algo.run(Mod_id, + CC_id, + frameP, + subframeP, + &UE_to_sched, + 4, // max_num_ue + n_rbg_sched, + rbgalloc_mask, + mac->dl_algo.data); // the following block is meant for validation of the pre-processor to check // whether all UE allocations are non-overlapping and is not necessary for From a0b331415fc13ca49f5afbb9203f9ad5ee1fc83c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 28 May 2020 16:17:52 +0200 Subject: [PATCH 17/66] Add Proportional Fair scheduler, wbCqi Selects UE with highest coefficient. Allocates until there are no more RBGs to allocate, or UE has no more data. In the latter case, continues with the next UE (second-highest coefficient). --- openair2/LAYER2/MAC/pre_processor.c | 164 ++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 8c4b91ce87..5c2b72d199 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -237,6 +237,170 @@ default_sched_dl_algo_t round_robin_dl = { }; +void *pf_dl_setup(void) { + void *data = calloc(MAX_MOBILES_PER_ENB, sizeof(float)); + for (int i = 0; i < MAX_MOBILES_PER_ENB; i++) + *(float *) data = 0.0f; + AssertFatal(data, "could not allocate data in %s()\n", __func__); + return data; +} +void pf_dl_unset(void **data) { + if (*data) + free(*data); + *data = NULL; +} +int pf_wbcqi_dl_run(module_id_t Mod_id, + int CC_id, + int frame, + int subframe, + UE_list_t *UE_list, + int max_num_ue, + int n_rbg_sched, + uint8_t *rbgalloc_mask, + void *data) { + DevAssert(UE_list->head >= 0); + DevAssert(n_rbg_sched > 0); + const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); + const int RBGsize = get_min_rb_unit(Mod_id, CC_id); + const int RBGlastsize = get_rbg_size_last(Mod_id, CC_id); + UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; + + int rbg = 0; + for (; !rbgalloc_mask[rbg]; rbg++) + ; /* fast-forward to first allowed RBG */ + + UE_list_t UE_sched; // UEs that could be scheduled + int *uep = &UE_sched.head; + float *thr_ue = data; + float coeff_ue[MAX_MOBILES_PER_ENB]; + + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + const float a = 0.0005f; // corresponds to 200ms window + const uint32_t b = UE_info->eNB_UE_stats[CC_id][UE_id].TBS; + thr_ue[UE_id] = (1 - a) * thr_ue[UE_id] + a * b; + + // check whether there are HARQ retransmissions + const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id]; + const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, frame, subframe); + UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + const uint8_t round = ue_ctrl->round[CC_id][harq_pid]; + if (round != 8) { // retransmission: allocate + const int nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid]; + if (nb_rb == 0) + continue; + int nb_rbg = (nb_rb + (nb_rb % RBGsize)) / RBGsize; + // needs more RBGs than we can allocate + if (nb_rbg > n_rbg_sched) { + LOG_D(MAC, + "retransmission of UE %d needs more RBGs (%d) than we have (%d)\n", + UE_id, nb_rbg, n_rbg_sched); + continue; + } + // ensure that the number of RBs can be contained by the RBGs (!), i.e. + // if we allocate the last RBG this one should have the full RBGsize + if ((nb_rb % RBGsize) == 0 && nb_rbg == n_rbg_sched + && rbgalloc_mask[N_RBG - 1] && RBGlastsize != RBGsize) { + LOG_D(MAC, + "retransmission of UE %d needs %d RBs, but the last RBG %d is too small (%d, normal %d)\n", + UE_id, nb_rb, N_RBG - 1, RBGlastsize, RBGsize); + continue; + } + const uint8_t cqi = ue_ctrl->dl_cqi[CC_id]; + const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi); + if (idx < 0) + continue; // cannot allocate CCE + ue_ctrl->pre_dci_dl_pdu_idx = idx; + // retransmissions: directly allocate + n_rbg_sched -= nb_rbg; + ue_ctrl->pre_nb_available_rbs[CC_id] += nb_rb; + for (; nb_rbg > 0; rbg++) { + if (!rbgalloc_mask[rbg]) + continue; + ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1; + rbgalloc_mask[rbg] = 0; + nb_rbg--; + } + LOG_D(MAC, + "%4d.%d n_rbg_sched %d after retransmission reservation for UE %d " + "round %d retx nb_rb %d pre_nb_available_rbs %d\n", + frame, subframe, n_rbg_sched, UE_id, round, + UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid], + ue_ctrl->pre_nb_available_rbs[CC_id]); + /* if there are no more RBG to give, return */ + if (n_rbg_sched <= 0) + return 0; + max_num_ue--; + /* if there are no UEs that can be allocated anymore, return */ + if (max_num_ue == 0) + return n_rbg_sched; + for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; + } else { + if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total == 0) + continue; + + const int mcs = cqi_to_mcs[UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]]; + const uint32_t tbs = get_TBS_DL(mcs, RBGsize); + coeff_ue[UE_id] = (float) tbs / thr_ue[UE_id]; + //LOG_I(MAC, " pf UE %d: old TBS %d thr %f MCS %d TBS %d coeff %f\n", + // UE_id, b, thr_ue[UE_id], mcs, tbs, coeff_ue[UE_id]); + *uep = UE_id; + uep = &UE_sched.next[UE_id]; + } + } + *uep = -1; + + while (max_num_ue > 0 && n_rbg_sched > 0 && UE_sched.head >= 0) { + int *max = &UE_sched.head; /* assume head is max */ + int *p = &UE_sched.next[*max]; + while (*p >= 0) { + /* if the current one has larger coeff, save for later */ + if (coeff_ue[*p] > coeff_ue[*max]) + max = p; + p = &UE_sched.next[*p]; + } + /* remove the max one */ + const int UE_id = *max; + p = &UE_sched.next[*max]; + *max = UE_sched.next[*max]; + *p = -1; + + const uint8_t cqi = UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]; + const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi); + if (idx < 0) + continue; + UE_info->UE_sched_ctrl[UE_id].pre_dci_dl_pdu_idx = idx; + + max_num_ue--; + + /* allocate as much as possible */ + const int mcs = cqi_to_mcs[cqi]; + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = mcs; + int req = find_nb_rb_DL(mcs, + UE_info->UE_template[CC_id][UE_id].dl_buffer_total, + n_rbg_sched * RBGsize, + RBGsize); + UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + while (req > 0 && n_rbg_sched > 0) { + ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1; + rbgalloc_mask[rbg] = 0; + const int sRBG = rbg == N_RBG - 1 ? RBGlastsize : RBGsize; + ue_ctrl->pre_nb_available_rbs[CC_id] += sRBG; + req -= sRBG; + n_rbg_sched--; + for (rbg++; n_rbg_sched > 0 && !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; + } + } + + return n_rbg_sched; +} +default_sched_dl_algo_t proportional_fair_wbcqi_dl = { + .name = "proportional_fair_wbcqi_dl", + .setup = pf_dl_setup, + .unset = pf_dl_unset, + .run = pf_wbcqi_dl_run, + .data = NULL +}; + // This function stores the downlink buffer for all the logical channels void store_dlsch_buffer(module_id_t Mod_id, From 36cd697b626a6133d9c0eecb1dfb8a659640fa4b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 22 May 2020 16:43:24 +0200 Subject: [PATCH 18/66] Add Maximum Throughput scheduler, wbCqi Selects the UE with the highest CQI. If two UEs have the same CQI, choses the one with highest number of bytes in RLC queue. Allocates as many RBGs as possible, and potentially continues with the next UE. --- openair2/LAYER2/MAC/pre_processor.c | 150 ++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 5c2b72d199..e7adbb7c80 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -401,6 +401,156 @@ default_sched_dl_algo_t proportional_fair_wbcqi_dl = { .data = NULL }; +void *mt_dl_setup(void) { + return NULL; +} +void mt_dl_unset(void **data) { + *data = NULL; +} +int mt_wbcqi_dl_run(module_id_t Mod_id, + int CC_id, + int frame, + int subframe, + UE_list_t *UE_list, + int max_num_ue, + int n_rbg_sched, + uint8_t *rbgalloc_mask, + void *data) { + DevAssert(UE_list->head >= 0); + DevAssert(n_rbg_sched > 0); + const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); + const int RBGsize = get_min_rb_unit(Mod_id, CC_id); + const int RBGlastsize = get_rbg_size_last(Mod_id, CC_id); + UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; + + int rbg = 0; + for (; !rbgalloc_mask[rbg]; rbg++) + ; /* fast-forward to first allowed RBG */ + + UE_list_t UE_sched; // UEs that could be scheduled + int *uep = &UE_sched.head; + + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + // check whether there are HARQ retransmissions + const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id]; + const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, frame, subframe); + UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + const uint8_t round = ue_ctrl->round[CC_id][harq_pid]; + if (round != 8) { // retransmission: allocate + const int nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid]; + if (nb_rb == 0) + continue; + int nb_rbg = (nb_rb + (nb_rb % RBGsize)) / RBGsize; + // needs more RBGs than we can allocate + if (nb_rbg > n_rbg_sched) { + LOG_D(MAC, + "retransmission of UE %d needs more RBGs (%d) than we have (%d)\n", + UE_id, nb_rbg, n_rbg_sched); + continue; + } + // ensure that the number of RBs can be contained by the RBGs (!), i.e. + // if we allocate the last RBG this one should have the full RBGsize + if ((nb_rb % RBGsize) == 0 && nb_rbg == n_rbg_sched + && rbgalloc_mask[N_RBG - 1] && RBGlastsize != RBGsize) { + LOG_D(MAC, + "retransmission of UE %d needs %d RBs, but the last RBG %d is too small (%d, normal %d)\n", + UE_id, nb_rb, N_RBG - 1, RBGlastsize, RBGsize); + continue; + } + const uint8_t cqi = ue_ctrl->dl_cqi[CC_id]; + const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi); + if (idx < 0) + continue; // cannot allocate CCE + ue_ctrl->pre_dci_dl_pdu_idx = idx; + // retransmissions: directly allocate + n_rbg_sched -= nb_rbg; + ue_ctrl->pre_nb_available_rbs[CC_id] += nb_rb; + for (; nb_rbg > 0; rbg++) { + if (!rbgalloc_mask[rbg]) + continue; + ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1; + rbgalloc_mask[rbg] = 0; + nb_rbg--; + } + LOG_D(MAC, + "%4d.%d n_rbg_sched %d after retransmission reservation for UE %d " + "round %d retx nb_rb %d pre_nb_available_rbs %d\n", + frame, subframe, n_rbg_sched, UE_id, round, + UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid], + ue_ctrl->pre_nb_available_rbs[CC_id]); + /* if there are no more RBG to give, return */ + if (n_rbg_sched <= 0) + return 0; + max_num_ue--; + /* if there are no UEs that can be allocated anymore, return */ + if (max_num_ue == 0) + return n_rbg_sched; + for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; + } else { + if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total == 0) + continue; + *uep = UE_id; + uep = &UE_sched.next[UE_id]; + } + } + *uep = -1; + + while (max_num_ue > 0 && n_rbg_sched > 0 && UE_sched.head >= 0) { + int *max = &UE_sched.head; /* assume head is max */ + int *p = &UE_sched.next[*max]; + while (*p >= 0) { + /* if the current one has better CQI, or the same and more data */ + const uint8_t maxCqi = UE_info->UE_sched_ctrl[*max].dl_cqi[CC_id]; + const uint32_t maxB = UE_info->UE_template[CC_id][*max].dl_buffer_total; + const uint8_t pCqi = UE_info->UE_sched_ctrl[*p].dl_cqi[CC_id]; + const uint32_t pB = UE_info->UE_template[CC_id][*p].dl_buffer_total; + if (pCqi > maxCqi || (pCqi == maxCqi && pB > maxB)) + max = p; + p = &UE_sched.next[*p]; + } + /* remove the max one */ + const int UE_id = *max; + p = &UE_sched.next[*max]; + *max = UE_sched.next[*max]; + *p = -1; + + const uint8_t cqi = UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]; + const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi); + if (idx < 0) + continue; + UE_info->UE_sched_ctrl[UE_id].pre_dci_dl_pdu_idx = idx; + + max_num_ue--; + + /* allocate as much as possible */ + const int mcs = cqi_to_mcs[cqi]; + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = mcs; + int req = find_nb_rb_DL(mcs, + UE_info->UE_template[CC_id][UE_id].dl_buffer_total, + n_rbg_sched * RBGsize, + RBGsize); + UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + while (req > 0 && n_rbg_sched > 0) { + ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1; + rbgalloc_mask[rbg] = 0; + const int sRBG = rbg == N_RBG - 1 ? RBGlastsize : RBGsize; + ue_ctrl->pre_nb_available_rbs[CC_id] += sRBG; + req -= sRBG; + n_rbg_sched--; + for (rbg++; n_rbg_sched > 0 && !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; + } + } + + return n_rbg_sched; +} +default_sched_dl_algo_t maximum_throughput_wbcqi_dl = { + .name = "maximum_throughput_wbcqi_dl", + .setup = mt_dl_setup, + .unset = mt_dl_unset, + .run = mt_wbcqi_dl_run, + .data = NULL +}; + // This function stores the downlink buffer for all the logical channels void store_dlsch_buffer(module_id_t Mod_id, From 5d1d2bcd1c17e6e12d36e94f77babd8d7a8c4da5 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 17 Jun 2020 18:40:48 +0200 Subject: [PATCH 19/66] Configurable Default Scheduler DL Algo --- openair2/ENB_APP/MACRLC_paramdef.h | 3 +++ openair2/ENB_APP/enb_config.c | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/openair2/ENB_APP/MACRLC_paramdef.h b/openair2/ENB_APP/MACRLC_paramdef.h index 55ce9d5059..fcee6142f0 100644 --- a/openair2/ENB_APP/MACRLC_paramdef.h +++ b/openair2/ENB_APP/MACRLC_paramdef.h @@ -58,6 +58,7 @@ #define CONFIG_STRING_MACRLC_SCHED_MODE "scheduler_mode" #define CONFIG_MACRLC_PUSCH10xSNR "puSch10xSnr" #define CONFIG_MACRLC_PUCCH10xSNR "puCch10xSnr" +#define CONFIG_STRING_MACRLC_DEFAULT_SCHED_DL_ALGO "default_sched_dl_algo" /*-------------------------------------------------------------------------------------------------------------------------------------------------------*/ /* MacRLC configuration parameters */ @@ -84,6 +85,7 @@ {CONFIG_STRING_MACRLC_SCHED_MODE, NULL, 0, strptr:NULL, defstrval:"default", TYPE_STRING, 0}, \ {CONFIG_MACRLC_PUSCH10xSNR, NULL, 0, iptr:NULL, defintval:200, TYPE_INT, 0}, \ {CONFIG_MACRLC_PUCCH10xSNR, NULL, 0, iptr:NULL, defintval:200, TYPE_INT, 0}, \ +{CONFIG_STRING_MACRLC_DEFAULT_SCHED_DL_ALGO, NULL, 0, strptr:NULL, defstrval:"round_robin_dl", TYPE_STRING, 0}, \ } #define MACRLC_CC_IDX 0 #define MACRLC_TRANSPORT_N_PREFERENCE_IDX 1 @@ -105,6 +107,7 @@ #define MACRLC_SCHED_MODE_IDX 17 #define MACRLC_PUSCH10xSNR_IDX 18 #define MACRLC_PUCCH10xSNR_IDX 19 +#define MACRLC_DEFAULT_SCHED_DL_ALGO_IDX 20 /*---------------------------------------------------------------------------------------------------------------------------------------------------------*/ #endif diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 6dcc574746..3bde7da02c 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -29,6 +29,7 @@ #include #include +#include #include "common/utils/LOG/log.h" #include "assertions.h" @@ -260,6 +261,15 @@ void RCconfig_macrlc(int macrlc_has_f1[MAX_MAC_INST]) { global_scheduler_mode=SCHED_MODE_DEFAULT; printf("sched mode = default %d [%s]\n",global_scheduler_mode,*(MacRLC_ParamList.paramarray[j][MACRLC_SCHED_MODE_IDX].strptr)); } + + char *s = *MacRLC_ParamList.paramarray[j][MACRLC_DEFAULT_SCHED_DL_ALGO_IDX].strptr; + void *d = dlsym(NULL, s); + AssertFatal(d, "%s(): no default scheduler DL algo '%s' found\n", __func__, s); + // release default, add new + RC.mac[j]->dl_algo.unset(&RC.mac[j]->dl_algo.data); + RC.mac[j]->dl_algo = *(default_sched_dl_algo_t *) d; + RC.mac[j]->dl_algo.data = RC.mac[j]->dl_algo.setup(); + LOG_I(ENB_APP, "using default scheduler DL algo '%s'\n", RC.mac[j]->dl_algo.name); }// j=0..num_inst } /*else {// MacRLC_ParamList.numelt > 0 // ignore it From 41de51b18744901df1368ae700b4b639d832d987 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 18 Jun 2020 17:32:01 +0200 Subject: [PATCH 20/66] Format to dynamically handle UL SCHED --- openair2/LAYER2/MAC/mac.h | 16 +++++- openair2/LAYER2/MAC/main.c | 5 ++ openair2/LAYER2/MAC/pre_processor.c | 79 ++++++++++++++++++----------- 3 files changed, 70 insertions(+), 30 deletions(-) diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h index 0264951683..09585fae55 100644 --- a/openair2/LAYER2/MAC/mac.h +++ b/openair2/LAYER2/MAC/mac.h @@ -1276,7 +1276,7 @@ typedef struct { /** * definition of a scheduling algorithm implementation used in the - * default scheduler + * default DL scheduler */ typedef struct { char *name; @@ -1287,6 +1287,19 @@ typedef struct { void *data; } default_sched_dl_algo_t; +/** + * definition of a scheduling algorithm implementation used in the + * default UL scheduler + */ +typedef struct { + char *name; + void *(*setup)(void); + void (*unset)(void **); + int (*run)( + module_id_t, int, int, int, int, int, UE_list_t *, int, int, contig_rbs_t *, void *); + void *data; +} default_sched_ul_algo_t; + /*! \brief eNB common channels */ typedef struct { int physCellId; @@ -1447,6 +1460,7 @@ typedef struct eNB_MAC_INST_s { SCHEDULER_MODES scheduler_mode; /// scheduling algorithm used in default scheduler default_sched_dl_algo_t dl_algo; + default_sched_ul_algo_t ul_algo; int32_t puSch10xSnr; int32_t puCch10xSnr; diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index 39e342cba0..294eb12159 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -133,6 +133,11 @@ void mac_top_init_eNB(void) AssertFatal(d, "%s(): no scheduler algo '%s' found\n", __func__, s); mac[i]->dl_algo = *(default_sched_dl_algo_t *) d; mac[i]->dl_algo.data = mac[i]->dl_algo.setup(); + s = "round_robin_ul"; + d = dlsym(NULL, s); + AssertFatal(d, "%s(): no scheduler algo '%s' found\n", __func__, s); + mac[i]->ul_algo = *(default_sched_ul_algo_t *) d; + mac[i]->ul_algo.data = mac[i]->ul_algo.setup(); init_UE_info(&mac[i]->UE_info); init_slice_info(&mac[i]->slice_info); } diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index e7adbb7c80..72455f7125 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -818,17 +818,28 @@ int pp_find_rb_table_index(int approximate) { return p + 1; } -int g_start_ue_ul = -1; -int round_robin_ul(module_id_t Mod_id, - int CC_id, - int frame, - int subframe, - int sched_frame, - int sched_subframe, - UE_list_t *UE_list, - int max_num_ue, - int num_contig_rb, - contig_rbs_t *rbs) { +void *rr_ul_setup(void) { + void *data = malloc(sizeof(int)); + *(int *) data = 0; + AssertFatal(data, "could not allocate data in %s()\n", __func__); + return data; +} +void rr_ul_unset(void **data) { + if (*data) + free(*data); + *data = NULL; +} +int rr_ul_run(module_id_t Mod_id, + int CC_id, + int frame, + int subframe, + int sched_frame, + int sched_subframe, + UE_list_t *UE_list, + int max_num_ue, + int num_contig_rb, + contig_rbs_t *rbs, + void *data) { AssertFatal(num_contig_rb <= 2, "cannot handle more than two contiguous RB regions\n"); UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; const int max_rb = num_contig_rb > 1 ? MAX(rbs[0].length, rbs[1].length) : rbs[0].length; @@ -968,9 +979,10 @@ int round_robin_ul(module_id_t Mod_id, end = la > lb ? 2 : -1; } - if (g_start_ue_ul == -1) - g_start_ue_ul = UE_list->head; - int sUE_id = g_start_ue_ul; + int *start_ue = data; + if (*start_ue == -1) + *start_ue = UE_list->head; + int sUE_id = *start_ue; int rb_idx_given[MAX_MOBILES_PER_ENB]; memset(rb_idx_given, 0, sizeof(rb_idx_given)); @@ -1049,10 +1061,17 @@ int round_robin_ul(module_id_t Mod_id, } /* just start with the next UE next time */ - g_start_ue_ul = next_ue_list_looped(UE_list, g_start_ue_ul); + *start_ue = next_ue_list_looped(UE_list, *start_ue); return rbs[0].length + (num_contig_rb > 1 ? rbs[1].length : 0); } +default_sched_ul_algo_t round_robin_ul = { + .name = "round_robin_ul", + .setup = rr_ul_setup, + .unset = rr_ul_unset, + .run = rr_ul_run, + .data = NULL +}; void ulsch_scheduler_pre_processor(module_id_t Mod_id, int CC_id, @@ -1060,9 +1079,10 @@ void ulsch_scheduler_pre_processor(module_id_t Mod_id, sub_frame_t subframeP, int sched_frameP, unsigned char sched_subframeP) { - UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; - const int N_RB_UL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].ul_Bandwidth); - COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id]; + eNB_MAC_INST *mac = RC.mac[Mod_id]; + UE_info_t *UE_info = &mac->UE_info; + const int N_RB_UL = to_prb(mac->common_channels[CC_id].ul_Bandwidth); + COMMON_channels_t *cc = &mac->common_channels[CC_id]; UE_list_t UE_to_sched; UE_to_sched.head = -1; @@ -1119,16 +1139,17 @@ void ulsch_scheduler_pre_processor(module_id_t Mod_id, } } - round_robin_ul(Mod_id, - CC_id, - frameP, - subframeP, - sched_frameP, - sched_subframeP, - &UE_to_sched, - 4, // max_num_ue - n_contig, - rbs); + mac->ul_algo.run(Mod_id, + CC_id, + frameP, + subframeP, + sched_frameP, + sched_subframeP, + &UE_to_sched, + 4, // max_num_ue + n_contig, + rbs, + mac->ul_algo.data); // the following block is meant for validation of the pre-processor to check // whether all UE allocations are non-overlapping and is not necessary for @@ -1147,7 +1168,7 @@ void ulsch_scheduler_pre_processor(module_id_t Mod_id, continue; print = 1; - uint8_t harq_pid = subframe2harqpid(&RC.mac[Mod_id]->common_channels[CC_id], + uint8_t harq_pid = subframe2harqpid(&mac->common_channels[CC_id], sched_frameP, sched_subframeP); LOG_D(MAC, "%4d.%d UE%d %d RBs (index %d) at start %d, pre MCS %d %s\n", frameP, From 9f26028ded0201efb7906c682568eb1519f4eb12 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 23 Jun 2020 10:27:45 +0200 Subject: [PATCH 21/66] Default pre-processor: efficiently build UE list --- openair2/LAYER2/MAC/pre_processor.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 72455f7125..5eb27699be 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -635,12 +635,10 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, store_dlsch_buffer(Mod_id, CC_id, frameP, subframeP); UE_list_t UE_to_sched; - UE_to_sched.head = -1; for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) UE_to_sched.next[i] = -1; + int *cur = &UE_to_sched.head; - int first = 1; - int last_UE_id = -1; for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; const UE_TEMPLATE *ue_template = &UE_info->UE_template[CC_id][UE_id]; @@ -673,15 +671,10 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, } /* define UEs to schedule */ - if (first) { - first = 0; - UE_to_sched.head = UE_id; - } else { - UE_to_sched.next[last_UE_id] = UE_id; - } - UE_to_sched.next[UE_id] = -1; - last_UE_id = UE_id; + *cur = UE_id; + cur = &UE_to_sched.next[UE_id]; } + *cur = -1; if (UE_to_sched.head < 0) return; @@ -1085,11 +1078,10 @@ void ulsch_scheduler_pre_processor(module_id_t Mod_id, COMMON_channels_t *cc = &mac->common_channels[CC_id]; UE_list_t UE_to_sched; - UE_to_sched.head = -1; for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) UE_to_sched.next[i] = -1; + int *cur = &UE_to_sched.head; - int last_UE_id = -1; for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { UE_TEMPLATE *UE_template = &UE_info->UE_template[CC_id][UE_id]; UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; @@ -1112,13 +1104,10 @@ void ulsch_scheduler_pre_processor(module_id_t Mod_id, continue; /* define UEs to schedule */ - if (UE_to_sched.head < 0) - UE_to_sched.head = UE_id; - else - UE_to_sched.next[last_UE_id] = UE_id; - UE_to_sched.next[UE_id] = -1; - last_UE_id = UE_id; + *cur = UE_id; + cur = &UE_to_sched.next[UE_id]; } + *cur = -1; if (UE_to_sched.head < 0) return; From 198822aa17cc47b8b563491f2a76bb0d4da51813 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 12 Apr 2020 12:00:43 +0200 Subject: [PATCH 22/66] Remove any slice-related information from OAI --- .../CONTROL_MODULES/MAC/flexran_agent_mac.c | 13 - .../MAC/flexran_agent_mac_internal.c | 28 +- .../flexran_agent_mac_slice_verification.c | 4 +- openair2/ENB_APP/flexran_agent_ran_api.c | 314 ++---------------- openair2/LAYER2/MAC/mac.h | 104 ------ openair2/LAYER2/MAC/mac_proto.h | 2 - openair2/LAYER2/MAC/main.c | 27 -- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 2 - 8 files changed, 39 insertions(+), 455 deletions(-) diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c index 603ff25198..669eb33ea3 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c @@ -49,19 +49,6 @@ struct lfds700_misc_prng_state ps[NUM_MAX_ENB]; struct lfds700_ringbuffer_element *dl_mac_config_array[NUM_MAX_ENB]; struct lfds700_ringbuffer_state ringbuffer_state[NUM_MAX_ENB]; -/* the slice config as kept in the underlying system */ -Protocol__FlexSliceConfig *slice_config[MAX_NUM_SLICES]; -/* a structure that keeps updates which will be reflected in slice_config later */ -Protocol__FlexSliceConfig *sc_update[MAX_NUM_SLICES]; -/* indicates whether sc_update contains new data */ -int perform_slice_config_update_count = 1; -/* queue of incoming new UE<>slice association commands */ -Protocol__FlexUeConfig *ue_slice_assoc_update[MAX_NUM_SLICES]; -int n_ue_slice_assoc_updates = 0; -/* mutex for sc_update: do not receive new config and write it at the same time */ -pthread_mutex_t sc_update_mtx = PTHREAD_MUTEX_INITIALIZER; - - int flexran_agent_mac_stats_reply_ue(mid_t mod_id, Protocol__FlexUeStatsReport **ue_report, int n_ue, diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c index a85cbac543..84a28683b7 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c @@ -33,14 +33,6 @@ #include "flexran_agent_mac_internal.h" #include "flexran_agent_mac_slice_verification.h" -/* from flexran_agent_mac.c */ -extern Protocol__FlexSliceConfig *slice_config[MAX_NUM_SLICES]; -extern Protocol__FlexSliceConfig *sc_update[MAX_NUM_SLICES]; -extern int perform_slice_config_update_count; -extern Protocol__FlexUeConfig *ue_slice_assoc_update[MAX_NUM_SLICES]; -extern int n_ue_slice_assoc_updates; -extern pthread_mutex_t sc_update_mtx; - Protocol__FlexranMessage * flexran_agent_generate_diff_mac_stats_report(Protocol__FlexranMessage *new_message, Protocol__FlexranMessage *old_message) { @@ -1040,12 +1032,12 @@ Protocol__FlexSliceConfig *flexran_agent_create_slice_config(int n_dl, int m_ul) if (!fsc) return NULL; protocol__flex_slice_config__init(fsc); - /* say there are n_dl slices but reserve memory for up to MAX_NUM_SLICES so + /* say there are n_dl slices but reserve memory for up to 10 so * we don't need to reserve again later */ fsc->n_dl = n_dl; - fsc->dl = calloc(MAX_NUM_SLICES, sizeof(Protocol__FlexDlSlice *)); + fsc->dl = calloc(10, sizeof(Protocol__FlexDlSlice *)); if (!fsc->dl) fsc->n_dl = 0; - for (i = 0; i < MAX_NUM_SLICES; i++) { + for (i = 0; i < 10; i++) { fsc->dl[i] = malloc(sizeof(Protocol__FlexDlSlice)); if (!fsc->dl[i]) continue; protocol__flex_dl_slice__init(fsc->dl[i]); @@ -1053,9 +1045,9 @@ Protocol__FlexSliceConfig *flexran_agent_create_slice_config(int n_dl, int m_ul) /* as above */ fsc->n_ul = m_ul; - fsc->ul = calloc(MAX_NUM_SLICES, sizeof(Protocol__FlexUlSlice *)); + fsc->ul = calloc(10, sizeof(Protocol__FlexUlSlice *)); if (!fsc->ul) fsc->n_ul = 0; - for (i = 0; i < MAX_NUM_SLICES; i++) { + for (i = 0; i < 10; i++) { fsc->ul[i] = malloc(sizeof(Protocol__FlexUlSlice)); if (!fsc->ul[i]) continue; protocol__flex_ul_slice__init(fsc->ul[i]); @@ -1401,8 +1393,8 @@ Protocol__FlexDlSlice *create_new_dl_slice(mid_t mod_id, int id) mod_id, id); Protocol__FlexDlSlice *to = sc_update[mod_id]->dl[sc_update[mod_id]->n_dl]; sc_update[mod_id]->n_dl++; - AssertFatal(sc_update[mod_id]->n_dl <= MAX_NUM_SLICES, - "cannot create more than MAX_NUM_SLICES\n"); + AssertFatal(sc_update[mod_id]->n_dl <= 10, + "cannot create more than 10\n"); to->id = id; return to; } @@ -1468,8 +1460,8 @@ Protocol__FlexUlSlice *create_new_ul_slice(mid_t mod_id, int id) mod_id, id); Protocol__FlexUlSlice *to = sc_update[mod_id]->ul[sc_update[mod_id]->n_ul]; sc_update[mod_id]->n_ul++; - AssertFatal(sc_update[mod_id]->n_ul <= MAX_NUM_SLICES, - "cannot create more than MAX_NUM_SLICES\n"); + AssertFatal(sc_update[mod_id]->n_ul <= 10, + "cannot create more than 10\n"); to->id = id; return to; } @@ -1698,7 +1690,7 @@ int apply_new_slice_ul_config(mid_t mod_id, Protocol__FlexUlSlice *oldc, Protoco void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config) { - if (n_ue_slice_assoc_updates == MAX_NUM_SLICES) { + if (n_ue_slice_assoc_updates == 10) { LOG_E(FLEXRAN_AGENT, "[%d] can not handle flex_ue_config message, buffer is full; try again later\n", mod_id); diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c index 67329e91be..f7f60541f5 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c @@ -132,7 +132,7 @@ int flexran_verify_group_dl_slices(mid_t mod_id, Protocol__FlexDlSlice **existin /* else "only" an update */ } - if (n < 1 || n > MAX_NUM_SLICES) { + if (n < 1 || n > 10) { LOG_E(FLEXRAN_AGENT, "[%d] Illegal number of resulting DL slices (%d -> %d)\n", mod_id, n_ex, n); return 0; @@ -253,7 +253,7 @@ int flexran_verify_group_ul_slices(mid_t mod_id, Protocol__FlexUlSlice **existin /* else "only" an update */ } - if (n < 1 || n > MAX_NUM_SLICES) { + if (n < 1 || n > 10) { LOG_E(FLEXRAN_AGENT, "[%d] Illegal number of resulting UL slices (%d -> %d)\n", mod_id, n_ex, n); return 0; diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index 0fcc51782e..291c4dc7d8 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -3015,469 +3015,209 @@ uint32_t flexran_get_rrc_enb_ue_s1ap_id(mid_t mod_id, rnti_t rnti) /**************************** SLICING ****************************/ int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return -1; - - int slice_idx = 0; //RC.mac[mod_id]->UE_info.assoc_dl_slice_idx[ue_id]; - - if (slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_dl) - return RC.mac[mod_id]->slice_info.dl[slice_idx].id; - return 0; } void flexran_set_ue_dl_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx) { if (!mac_is_present(mod_id)) return; - - if (flexran_get_mac_ue_crnti(mod_id, ue_id) == NOT_A_RNTI) return; - - if (!flexran_dl_slice_exists(mod_id, slice_idx)) return; - - //RC.mac[mod_id]->UE_info.assoc_dl_slice_idx[ue_id] = slice_idx; } int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return -1; - - int slice_idx = 0; //RC.mac[mod_id]->UE_info.assoc_ul_slice_idx[ue_id]; - - if (slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_ul) - return RC.mac[mod_id]->slice_info.ul[slice_idx].id; - return 0; } void flexran_set_ue_ul_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx) { if (!mac_is_present(mod_id)) return; - - if (flexran_get_mac_ue_crnti(mod_id, ue_id) == NOT_A_RNTI) return; - - if (!flexran_ul_slice_exists(mod_id, slice_idx)) return; - - //RC.mac[mod_id]->UE_info.assoc_ul_slice_idx[ue_id] = slice_idx; } int flexran_dl_slice_exists(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - return slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_dl; + return 0; } int flexran_create_dl_slice(mid_t mod_id, slice_id_t slice_id) { if (!mac_is_present(mod_id)) return -1; - - int newidx = RC.mac[mod_id]->slice_info.n_dl; - - if (newidx >= MAX_NUM_SLICES) return -1; - - ++RC.mac[mod_id]->slice_info.n_dl; - flexran_set_dl_slice_id(mod_id, newidx, slice_id); - return newidx; + return -1; } int flexran_find_dl_slice(mid_t mod_id, slice_id_t slice_id) { if (!mac_is_present(mod_id)) return -1; - - slice_info_t *sli = &RC.mac[mod_id]->slice_info; - int n = sli->n_dl; - - for (int i = 0; i < n; i++) { - if (sli->dl[i].id == slice_id) return i; - } - return -1; } int flexran_remove_dl_slice(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - slice_info_t *sli = &RC.mac[mod_id]->slice_info; - - if (sli->n_dl <= 1) return -1; - - if (sli->dl[slice_idx].sched_name) free(sli->dl[slice_idx].sched_name); - - --sli->n_dl; - - /* move last element to the position of the removed one */ - if (slice_idx != sli->n_dl) - memcpy(&sli->dl[slice_idx], &sli->dl[sli->n_dl], sizeof(sli->dl[sli->n_dl])); - - memset(&sli->dl[sli->n_dl], 0, sizeof(sli->dl[sli->n_dl])); - /* all UEs that have been in the old slice are put into slice index 0 */ - //int *assoc_list = RC.mac[mod_id]->UE_info.assoc_dl_slice_idx; - - //for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) { - // if (assoc_list[i] == slice_idx) - // assoc_list[i] = 0; - //} - - return 1; + return -1; } int flexran_get_num_dl_slices(mid_t mod_id) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.n_dl; + return 0; } int flexran_get_intraslice_sharing_active(mid_t mod_id) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.intraslice_share_active; + return -1; } void flexran_set_intraslice_sharing_active(mid_t mod_id, int intraslice_active) { if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.intraslice_share_active = intraslice_active; } int flexran_get_interslice_sharing_active(mid_t mod_id) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.interslice_share_active; + return -1; } void flexran_set_interslice_sharing_active(mid_t mod_id, int interslice_active) { if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.interslice_share_active = interslice_active; } slice_id_t flexran_get_dl_slice_id(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.dl[slice_idx].id; + return -1; } void flexran_set_dl_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id) { if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.dl[slice_idx].id = slice_id; } int flexran_get_dl_slice_percentage(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.dl[slice_idx].pct * 100.0f; + return -1; } void flexran_set_dl_slice_percentage(mid_t mod_id, int slice_idx, int percentage) { if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.dl[slice_idx].pct = percentage / 100.0f; } int flexran_get_dl_slice_isolation(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.dl[slice_idx].isol; + return -1; } void flexran_set_dl_slice_isolation(mid_t mod_id, int slice_idx, int is_isolated) { if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.dl[slice_idx].isol = is_isolated; } int flexran_get_dl_slice_priority(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.dl[slice_idx].prio; + return -1; } void flexran_set_dl_slice_priority(mid_t mod_id, int slice_idx, int priority) { if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.dl[slice_idx].prio = priority; } int flexran_get_dl_slice_position_low(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.dl[slice_idx].pos_low; + return -1; } void flexran_set_dl_slice_position_low(mid_t mod_id, int slice_idx, int poslow) { if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.dl[slice_idx].pos_low = poslow; } int flexran_get_dl_slice_position_high(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.dl[slice_idx].pos_high; + return -1; } void flexran_set_dl_slice_position_high(mid_t mod_id, int slice_idx, int poshigh) { if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.dl[slice_idx].pos_high = poshigh; } int flexran_get_dl_slice_maxmcs(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.dl[slice_idx].maxmcs; + return -1; } void flexran_set_dl_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs) { if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.dl[slice_idx].maxmcs = maxmcs; } int flexran_get_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting **sorting_list) { if (!mac_is_present(mod_id)) return -1; - - if (!(*sorting_list)) { - *sorting_list = calloc(CR_NUM, sizeof(Protocol__FlexDlSorting)); - - if (!(*sorting_list)) return -1; - } - - uint32_t policy = RC.mac[mod_id]->slice_info.dl[slice_idx].sorting; - - for (int i = 0; i < CR_NUM; i++) { - switch (policy >> 4 * (CR_NUM - 1 - i) & 0xF) { - case CR_ROUND: - (*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_ROUND; - break; - - case CR_SRB12: - (*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_SRB12; - break; - - case CR_HOL: - (*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_HOL; - break; - - case CR_LC: - (*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_LC; - break; - - case CR_CQI: - (*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_CQI; - break; - - case CR_LCP: - (*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_LCP; - break; - - default: - /* this should not happen, but a "default" */ - (*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_ROUND; - break; - } - } - - return CR_NUM; + return -1; } void flexran_set_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting *sorting_list, int n) { if (!mac_is_present(mod_id)) return; - - uint32_t policy = 0; - - for (int i = 0; i < n && i < CR_NUM; i++) { - switch (sorting_list[i]) { - case PROTOCOL__FLEX_DL_SORTING__CR_ROUND: - policy = policy << 4 | CR_ROUND; - break; - - case PROTOCOL__FLEX_DL_SORTING__CR_SRB12: - policy = policy << 4 | CR_SRB12; - break; - - case PROTOCOL__FLEX_DL_SORTING__CR_HOL: - policy = policy << 4 | CR_HOL; - break; - - case PROTOCOL__FLEX_DL_SORTING__CR_LC: - policy = policy << 4 | CR_LC; - break; - - case PROTOCOL__FLEX_DL_SORTING__CR_CQI: - policy = policy << 4 | CR_CQI; - break; - - case PROTOCOL__FLEX_DL_SORTING__CR_LCP: - policy = policy << 4 | CR_LCP; - break; - - default: /* suppresses warnings */ - policy = policy << 4 | CR_ROUND; - break; - } - } - - /* fill up with 0 == CR_ROUND */ - if (CR_NUM > n) policy = policy << 4 * (CR_NUM - n); - - RC.mac[mod_id]->slice_info.dl[slice_idx].sorting = policy; } Protocol__FlexDlAccountingPolicy flexran_get_dl_slice_accounting_policy(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR; - - switch (RC.mac[mod_id]->slice_info.dl[slice_idx].accounting) { - case POL_FAIR: - return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR; - - case POL_GREEDY: - return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_GREEDY; - - default: - return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR; - } + return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR; } void flexran_set_dl_slice_accounting_policy(mid_t mod_id, int slice_idx, Protocol__FlexDlAccountingPolicy accounting) { if (!mac_is_present(mod_id)) return; - - switch (accounting) { - case PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR: - RC.mac[mod_id]->slice_info.dl[slice_idx].accounting = POL_FAIR; - return; - - case PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_GREEDY: - RC.mac[mod_id]->slice_info.dl[slice_idx].accounting = POL_GREEDY; - return; - - default: - RC.mac[mod_id]->slice_info.dl[slice_idx].accounting = POL_FAIR; - return; - } } char *flexran_get_dl_slice_scheduler(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return NULL; - - return RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name; + return NULL; } int flexran_set_dl_slice_scheduler(mid_t mod_id, int slice_idx, char *name) { if (!mac_is_present(mod_id)) return 0; - - if (RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name) - free(RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name); - - RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name = strdup(name); - RC.mac[mod_id]->slice_info.dl[slice_idx].sched_cb = dlsym(NULL, name); - return RC.mac[mod_id]->slice_info.dl[slice_idx].sched_cb != NULL; + return 0; } int flexran_create_ul_slice(mid_t mod_id, slice_id_t slice_id) { if (!mac_is_present(mod_id)) return -1; - - int newidx = RC.mac[mod_id]->slice_info.n_ul; - - if (newidx >= MAX_NUM_SLICES) return -1; - - ++RC.mac[mod_id]->slice_info.n_ul; - flexran_set_ul_slice_id(mod_id, newidx, slice_id); - return newidx; + return -1; } int flexran_find_ul_slice(mid_t mod_id, slice_id_t slice_id) { if (!mac_is_present(mod_id)) return -1; - - slice_info_t *sli = &RC.mac[mod_id]->slice_info; - int n = sli->n_ul; - - for (int i = 0; i < n; i++) { - if (sli->ul[i].id == slice_id) return i; - } - return -1; } int flexran_remove_ul_slice(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - slice_info_t *sli = &RC.mac[mod_id]->slice_info; - - if (sli->n_ul <= 1) return -1; - - if (sli->ul[slice_idx].sched_name) free(sli->ul[slice_idx].sched_name); - - --sli->n_ul; - - /* move last element to the position of the removed one */ - if (slice_idx != sli->n_ul) - memcpy(&sli->ul[slice_idx], &sli->ul[sli->n_ul], sizeof(sli->ul[sli->n_ul])); - - memset(&sli->ul[sli->n_ul], 0, sizeof(sli->ul[sli->n_ul])); - /* all UEs that have been in the old slice are put into slice index 0 */ - //int *assoc_list = RC.mac[mod_id]->UE_info.assoc_ul_slice_idx; - - //for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) { - // if (assoc_list[i] == slice_idx) - // assoc_list[i] = 0; - //} - - return sli->n_ul; + return -1; } int flexran_get_num_ul_slices(mid_t mod_id) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.n_ul; + return 0; } int flexran_ul_slice_exists(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - return slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_ul; + return 0; } slice_id_t flexran_get_ul_slice_id(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.ul[slice_idx].id; + return -1; } void flexran_set_ul_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id) { if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.ul[slice_idx].id = slice_id; } int flexran_get_ul_slice_percentage(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.ul[slice_idx].pct * 100.0f; + return -1; } void flexran_set_ul_slice_percentage(mid_t mod_id, int slice_idx, int percentage) { if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.ul[slice_idx].pct = percentage / 100.0f; } int flexran_get_ul_slice_first_rb(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.ul[slice_idx].first_rb; + return -1; } void flexran_set_ul_slice_first_rb(mid_t mod_id, int slice_idx, int first_rb) { if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.ul[slice_idx].first_rb = first_rb; } int flexran_get_ul_slice_maxmcs(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.ul[slice_idx].maxmcs; + return -1; } void flexran_set_ul_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs) { if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.ul[slice_idx].maxmcs = maxmcs; } char *flexran_get_ul_slice_scheduler(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return NULL; - - return RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name; + return ""; } int flexran_set_ul_slice_scheduler(mid_t mod_id, int slice_idx, char *name) { if (!mac_is_present(mod_id)) return 0; - - if (RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name) - free(RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name); - - RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name = strdup(name); - RC.mac[mod_id]->slice_info.ul[slice_idx].sched_cb = dlsym(NULL, name); - return RC.mac[mod_id]->slice_info.ul[slice_idx].sched_cb != NULL; + return 0; } /************************** S1AP **************************/ diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h index 09585fae55..8349d84d48 100644 --- a/openair2/LAYER2/MAC/mac.h +++ b/openair2/LAYER2/MAC/mac.h @@ -155,9 +155,6 @@ /*!\brief minimum MAC data needed for transmitting 1 min RLC PDU size + 1 byte MAC subHeader */ #define MIN_MAC_HDR_RLC_SIZE (1 + MIN_RLC_PDU_SIZE) -/*!\brief maximum number of slices / groups */ -#define MAX_NUM_SLICES 10 - #define U_PLANE_INACTIVITY_VALUE 0 /* defined 10ms order (zero means infinity) */ @@ -1150,9 +1147,6 @@ typedef struct { UE_list_t list; int num_UEs; boolean_t active[MAX_MOBILES_PER_ENB]; - - /// Sorting criteria for the UE list in the MAC preprocessor - uint16_t sorting_criteria[MAX_NUM_SLICES][CR_NUM]; } UE_info_t; /*! \brief deleting control information*/ @@ -1171,101 +1165,6 @@ typedef struct { int tail_freelist; ///the tail position of the delete list } UE_free_list_t; -/** - * slice specific scheduler for the DL - */ -typedef void (*slice_scheduler_dl)(module_id_t mod_id, - int slice_idx, - frame_t frame, - sub_frame_t subframe, - int *mbsfn_flag); - -typedef struct { - slice_id_t id; - - /// RB share for each slice - float pct; - - /// whether this slice is isolated from the others - int isol; - - int prio; - - /// Frequency ranges for slice positioning - int pos_low; - int pos_high; - - // max mcs for each slice - int maxmcs; - - /// criteria for sorting policies of the slices - uint32_t sorting; - - /// Accounting policy (just greedy(1) or fair(0) setting for now) - int accounting; - - /// name of available scheduler - char *sched_name; - - /// pointer to the slice specific scheduler in DL - slice_scheduler_dl sched_cb; - -} slice_sched_conf_dl_t; - -typedef void (*slice_scheduler_ul)(module_id_t mod_id, - int slice_idx, - frame_t frame, - sub_frame_t subframe, - unsigned char sched_subframe, - uint16_t *first_rb); - -typedef struct { - slice_id_t id; - - /// RB share for each slice - float pct; - - // MAX MCS for each slice - int maxmcs; - - /// criteria for sorting policies of the slices - uint32_t sorting; - - /// starting RB (RB offset) of UL scheduling - int first_rb; - - /// name of available scheduler - char *sched_name; - - /// pointer to the slice specific scheduler in UL - slice_scheduler_ul sched_cb; - -} slice_sched_conf_ul_t; - - -typedef struct { - /// counter used to indicate when all slices have pre-allocated UEs - //int slice_counter; - - /// indicates whether remaining RBs after first intra-slice allocation will - /// be allocated to UEs of the same slice - int intraslice_share_active; - /// indicates whether remaining RBs after slice allocation will be - /// allocated to UEs of another slice. Isolated slices will be ignored - int interslice_share_active; - - /// number of active DL slices - int n_dl; - slice_sched_conf_dl_t dl[MAX_NUM_SLICES]; - - /// number of active UL slices - int n_ul; - slice_sched_conf_ul_t ul[MAX_NUM_SLICES]; - - /// common rb allocation list between slices - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]; -} slice_info_t; - /** * describes contiguous RBs */ @@ -1421,9 +1320,6 @@ typedef struct eNB_MAC_INST_s { uint32_t ul_handle; UE_info_t UE_info; - /// slice-related configuration - slice_info_t slice_info; - ///subband bitmap configuration SBMAP_CONF sbmap_conf; /// CCE table used to build DCI scheduling information diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index 2cb86c25af..61251ef088 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -187,8 +187,6 @@ void add_msg3(module_id_t module_idP, int CC_id, RA_t *ra, frame_t frameP, void init_UE_info(UE_info_t *UE_info); -void init_slice_info(slice_info_t *sli); - int mac_top_init(int eMBMS_active, char *uecap_xer, uint8_t cba_group_active, uint8_t HO_active); diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index 294eb12159..35b5136889 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -57,32 +57,6 @@ void init_UE_info(UE_info_t *UE_info) memset(UE_info->active, 0, sizeof(UE_info->active)); } -void init_slice_info(slice_info_t *sli) -{ - sli->intraslice_share_active = 1; - sli->interslice_share_active = 1; - - sli->n_dl = 1; - memset(sli->dl, 0, sizeof(slice_sched_conf_dl_t) * MAX_NUM_SLICES); - sli->dl[0].pct = 1.0; - sli->dl[0].prio = 10; - sli->dl[0].pos_high = N_RBG_MAX; - sli->dl[0].maxmcs = 28; - sli->dl[0].sorting = 0x012345; - sli->dl[0].sched_name = "schedule_ue_spec"; - sli->dl[0].sched_cb = dlsym(NULL, sli->dl[0].sched_name); - AssertFatal(sli->dl[0].sched_cb, "DLSCH scheduler callback is NULL\n"); - - sli->n_ul = 1; - memset(sli->ul, 0, sizeof(slice_sched_conf_ul_t) * MAX_NUM_SLICES); - sli->ul[0].pct = 1.0; - sli->ul[0].maxmcs = 20; - sli->ul[0].sorting = 0x0123; - sli->ul[0].sched_name = "schedule_ulsch_rnti"; - sli->ul[0].sched_cb = dlsym(NULL, sli->ul[0].sched_name); - AssertFatal(sli->ul[0].sched_cb, "ULSCH scheduler callback is NULL\n"); -} - void mac_top_init_eNB(void) { module_id_t i, j; @@ -139,7 +113,6 @@ void mac_top_init_eNB(void) mac[i]->ul_algo = *(default_sched_ul_algo_t *) d; mac[i]->ul_algo.data = mac[i]->ul_algo.setup(); init_UE_info(&mac[i]->UE_info); - init_slice_info(&mac[i]->slice_info); } RC.mac = mac; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index d3412095e3..8afa3a04f5 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -68,8 +68,6 @@ extern RAN_CONTEXT_t RC; -extern int n_active_slices; - // Note the 2 scs values in the table names represent resp. scs_common and pdcch_scs /// LUT for the number of symbols in the coreset indexed by coreset index (4 MSB rmsi_pdcch_config) uint8_t nr_coreset_nsymb_pdcch_type_0_scs_15_15[15] = {2,2,2,3,3,3,1,1,2,2,3,3,1,2,3}; From 8c76d6ab57e6088d317db51d454257f9bde0b463 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 14 Apr 2020 16:17:56 +0200 Subject: [PATCH 23/66] Delete old protobuf slice types flex_slice_{dl,ul} --- .../CONTROL_MODULES/MAC/flexran_agent_mac.c | 206 +----- .../MAC/flexran_agent_mac_internal.c | 666 +----------------- .../MAC/flexran_agent_mac_internal.h | 20 - .../flexran_agent_mac_slice_verification.c | 343 --------- .../flexran_agent_mac_slice_verification.h | 6 - .../ENB_APP/MESSAGES/V2/config_common.proto | 77 -- .../ENB_APP/MESSAGES/V2/config_messages.proto | 8 - openair2/ENB_APP/flexran_agent_common.c | 20 +- openair2/ENB_APP/flexran_agent_ran_api.c | 178 +---- openair2/ENB_APP/flexran_agent_ran_api.h | 149 +--- 10 files changed, 47 insertions(+), 1626 deletions(-) diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c index 669eb33ea3..4800fccea9 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c @@ -1468,10 +1468,12 @@ void flexran_agent_fill_mac_ue_config(mid_t mod_id, mid_t ue_id, ue_conf->rnti = flexran_get_mac_ue_crnti(mod_id, ue_id); ue_conf->has_rnti = 1; - ue_conf->dl_slice_id = flexran_get_ue_dl_slice_id(mod_id, ue_id); - ue_conf->has_dl_slice_id = 1; - ue_conf->ul_slice_id = flexran_get_ue_ul_slice_id(mod_id, ue_id); - ue_conf->has_ul_slice_id = 1; + int dl_id = flexran_get_ue_dl_slice_id(mod_id, ue_id); + ue_conf->dl_slice_id = dl_id; + ue_conf->has_dl_slice_id = dl_id >= 0; + int ul_id = flexran_get_ue_ul_slice_id(mod_id, ue_id); + ue_conf->ul_slice_id = ul_id; + ue_conf->has_ul_slice_id = ul_id >= 0; ue_conf->ue_aggregated_max_bitrate_ul = flexran_get_ue_aggregated_max_bitrate_ul(mod_id, ue_id); ue_conf->has_ue_aggregated_max_bitrate_ul = 1; @@ -1576,149 +1578,24 @@ void flexran_create_config_structures(mid_t mod_id) sc_update[mod_id] = flexran_agent_create_slice_config(n_dl, m_ul); if (!slice_config[mod_id] || !sc_update[mod_id]) return; - flexran_agent_read_slice_config(mod_id, slice_config[mod_id]); - flexran_agent_read_slice_config(mod_id, sc_update[mod_id]); + //flexran_agent_read_slice_config(mod_id, slice_config[mod_id]); + //flexran_agent_read_slice_config(mod_id, sc_update[mod_id]); for (i = 0; i < n_dl; i++) { - flexran_agent_read_slice_dl_config(mod_id, i, slice_config[mod_id]->dl[i]); - flexran_agent_read_slice_dl_config(mod_id, i, sc_update[mod_id]->dl[i]); + //flexran_agent_read_slice_dl_config(mod_id, i, slice_config[mod_id]->dl[i]); + //flexran_agent_read_slice_dl_config(mod_id, i, sc_update[mod_id]->dl[i]); } for (i = 0; i < m_ul; i++) { - flexran_agent_read_slice_ul_config(mod_id, i, slice_config[mod_id]->ul[i]); - flexran_agent_read_slice_ul_config(mod_id, i, sc_update[mod_id]->ul[i]); + //flexran_agent_read_slice_ul_config(mod_id, i, slice_config[mod_id]->ul[i]); + //flexran_agent_read_slice_ul_config(mod_id, i, sc_update[mod_id]->ul[i]); } } void flexran_check_and_remove_slices(mid_t mod_id) { - Protocol__FlexDlSlice **dl = sc_update[mod_id]->dl; - Protocol__FlexDlSlice **dlreal = slice_config[mod_id]->dl; - int i = 0; - while (i < sc_update[mod_id]->n_dl) { - /* remove slices whose percentage is zero */ - if (dl[i]->percentage > 0) { - ++i; - continue; - } - if (flexran_remove_dl_slice(mod_id, i) < 1) { - LOG_W(FLEXRAN_AGENT, "[%d] can not remove slice index %d ID %d\n", - mod_id, i, dl[i]->id); - ++i; - continue; - } - LOG_I(FLEXRAN_AGENT, "[%d] removed slice index %d ID %d\n", - mod_id, i, dl[i]->id); - if (dl[i]->n_sorting > 0) free(dl[i]->sorting); - free(dl[i]->scheduler_name); - if (dlreal[i]->n_sorting > 0) { - dlreal[i]->n_sorting = 0; - free(dlreal[i]->sorting); - } - free(dlreal[i]->scheduler_name); - --sc_update[mod_id]->n_dl; - --slice_config[mod_id]->n_dl; - const size_t last = sc_update[mod_id]->n_dl; - /* we need to memcpy the higher slice to the position we just deleted */ - memcpy(dl[i], dl[last], sizeof(*dl[last])); - memset(dl[last], 0, sizeof(*dl[last])); - memcpy(dlreal[i], dlreal[last], sizeof(*dlreal[last])); - memset(dlreal[last], 0, sizeof(*dlreal[last])); - /* dont increase i but recheck the slice which has been copied to here */ - } - Protocol__FlexUlSlice **ul = sc_update[mod_id]->ul; - Protocol__FlexUlSlice **ulreal = slice_config[mod_id]->ul; - i = 0; - while (i < sc_update[mod_id]->n_ul) { - if (ul[i]->percentage > 0) { - ++i; - continue; - } - if (flexran_remove_ul_slice(mod_id, i) < 1) { - LOG_W(FLEXRAN_AGENT, "[%d] can not remove slice index %d ID %d\n", - mod_id, i, ul[i]->id); - ++i; - continue; - } - LOG_I(FLEXRAN_AGENT, "[%d] removed slice index %d ID %d\n", - mod_id, i, ul[i]->id); - free(ul[i]->scheduler_name); - free(ulreal[i]->scheduler_name); - --sc_update[mod_id]->n_ul; - --slice_config[mod_id]->n_ul; - const size_t last = sc_update[mod_id]->n_ul; - /* see DL remarks */ - memcpy(ul[i], ul[last], sizeof(*ul[last])); - memset(ul[last], 0, sizeof(*ul[last])); - memcpy(ulreal[i], ulreal[last], sizeof(*ulreal[last])); - memset(ulreal[last], 0, sizeof(*ulreal[last])); - /* dont increase i but recheck the slice which has been copied to here */ - } } void flexran_agent_slice_update(mid_t mod_id) { - int i; - int changes = 0; - - if (perform_slice_config_update_count <= 0) return; - perform_slice_config_update_count--; - - pthread_mutex_lock(&sc_update_mtx); - - if (!slice_config[mod_id]) { - /* if the configuration does not exist for agent, create from eNB structure - * and exit */ - flexran_create_config_structures(mod_id); - pthread_mutex_unlock(&sc_update_mtx); - return; - } - - /********* read existing config *********/ - /* simply update slice_config all the time and write new config - * (apply_new_slice_dl_config() only updates if changes are necessary) */ - slice_config[mod_id]->n_dl = flexran_get_num_dl_slices(mod_id); - slice_config[mod_id]->n_ul = flexran_get_num_ul_slices(mod_id); - for (i = 0; i < slice_config[mod_id]->n_dl; i++) { - flexran_agent_read_slice_dl_config(mod_id, i, slice_config[mod_id]->dl[i]); - } - for (i = 0; i < slice_config[mod_id]->n_ul; i++) { - flexran_agent_read_slice_ul_config(mod_id, i, slice_config[mod_id]->ul[i]); - } - - /********* write new config *********/ - /* check for removal (sc_update[X]->dl[Y].percentage == 0) - * and update sc_update & slice_config accordingly */ - flexran_check_and_remove_slices(mod_id); - - /* create new DL and UL slices if necessary */ - for (i = slice_config[mod_id]->n_dl; i < sc_update[mod_id]->n_dl; i++) { - flexran_create_dl_slice(mod_id, sc_update[mod_id]->dl[i]->id); - } - for (i = slice_config[mod_id]->n_ul; i < sc_update[mod_id]->n_ul; i++) { - flexran_create_ul_slice(mod_id, sc_update[mod_id]->ul[i]->id); - } - slice_config[mod_id]->n_dl = flexran_get_num_dl_slices(mod_id); - slice_config[mod_id]->n_ul = flexran_get_num_ul_slices(mod_id); - changes += apply_new_slice_config(mod_id, slice_config[mod_id], sc_update[mod_id]); - for (i = 0; i < slice_config[mod_id]->n_dl; i++) { - changes += apply_new_slice_dl_config(mod_id, - slice_config[mod_id]->dl[i], - sc_update[mod_id]->dl[i]); - flexran_agent_read_slice_dl_config(mod_id, i, slice_config[mod_id]->dl[i]); - } - for (i = 0; i < slice_config[mod_id]->n_ul; i++) { - changes += apply_new_slice_ul_config(mod_id, - slice_config[mod_id]->ul[i], - sc_update[mod_id]->ul[i]); - flexran_agent_read_slice_ul_config(mod_id, i, slice_config[mod_id]->ul[i]); - } - flexran_agent_read_slice_config(mod_id, slice_config[mod_id]); - if (n_ue_slice_assoc_updates > 0) { - changes += apply_ue_slice_assoc_update(mod_id); - } - if (changes > 0) - LOG_I(FLEXRAN_AGENT, "[%d] slice configuration: applied %d changes\n", mod_id, changes); - - pthread_mutex_unlock(&sc_update_mtx); } Protocol__FlexSliceConfig *flexran_agent_get_slice_config(mid_t mod_id) @@ -1727,69 +1604,10 @@ Protocol__FlexSliceConfig *flexran_agent_get_slice_config(mid_t mod_id) Protocol__FlexSliceConfig *config = NULL; pthread_mutex_lock(&sc_update_mtx); - config = flexran_agent_create_slice_config(slice_config[mod_id]->n_dl, - slice_config[mod_id]->n_ul); if (!config) { pthread_mutex_unlock(&sc_update_mtx); return NULL; } - config->has_intraslice_share_active = 1; - config->intraslice_share_active = slice_config[mod_id]->intraslice_share_active; - config->has_interslice_share_active = 1; - config->interslice_share_active = slice_config[mod_id]->interslice_share_active; - for (int i = 0; i < slice_config[mod_id]->n_dl; ++i) { - if (!config->dl[i]) continue; - config->dl[i]->has_id = 1; - config->dl[i]->id = slice_config[mod_id]->dl[i]->id; - config->dl[i]->has_label = 1; - config->dl[i]->label = slice_config[mod_id]->dl[i]->label; - config->dl[i]->has_percentage = 1; - config->dl[i]->percentage = slice_config[mod_id]->dl[i]->percentage; - config->dl[i]->has_isolation = 1; - config->dl[i]->isolation = slice_config[mod_id]->dl[i]->isolation; - config->dl[i]->has_priority = 1; - config->dl[i]->priority = slice_config[mod_id]->dl[i]->priority; - config->dl[i]->has_position_low = 1; - config->dl[i]->position_low = slice_config[mod_id]->dl[i]->position_low; - config->dl[i]->has_position_high = 1; - config->dl[i]->position_high = slice_config[mod_id]->dl[i]->position_high; - config->dl[i]->has_maxmcs = 1; - config->dl[i]->maxmcs = slice_config[mod_id]->dl[i]->maxmcs; - config->dl[i]->n_sorting = slice_config[mod_id]->dl[i]->n_sorting; - config->dl[i]->sorting = calloc(config->dl[i]->n_sorting, sizeof(Protocol__FlexDlSorting)); - if (!config->dl[i]->sorting) config->dl[i]->n_sorting = 0; - for (int j = 0; j < config->dl[i]->n_sorting; ++j) - config->dl[i]->sorting[j] = slice_config[mod_id]->dl[i]->sorting[j]; - config->dl[i]->has_accounting = 1; - config->dl[i]->accounting = slice_config[mod_id]->dl[i]->accounting; - config->dl[i]->scheduler_name = strdup(slice_config[mod_id]->dl[i]->scheduler_name); - } - for (int i = 0; i < slice_config[mod_id]->n_ul; ++i) { - if (!config->ul[i]) continue; - config->ul[i]->has_id = 1; - config->ul[i]->id = slice_config[mod_id]->ul[i]->id; - config->ul[i]->has_label = 1; - config->ul[i]->label = slice_config[mod_id]->ul[i]->label; - config->ul[i]->has_percentage = 1; - config->ul[i]->percentage = slice_config[mod_id]->ul[i]->percentage; - config->ul[i]->has_isolation = 1; - config->ul[i]->isolation = slice_config[mod_id]->ul[i]->isolation; - config->ul[i]->has_priority = 1; - config->ul[i]->priority = slice_config[mod_id]->ul[i]->priority; - config->ul[i]->has_first_rb = 1; - config->ul[i]->first_rb = slice_config[mod_id]->ul[i]->first_rb; - config->ul[i]->has_maxmcs = 1; - config->ul[i]->maxmcs = slice_config[mod_id]->ul[i]->maxmcs; - config->ul[i]->n_sorting = slice_config[mod_id]->ul[i]->n_sorting; - config->ul[i]->sorting = calloc(config->ul[i]->n_sorting, sizeof(Protocol__FlexUlSorting)); - if (!config->ul[i]->sorting) config->ul[i]->n_sorting = 0; - for (int j = 0; j < config->ul[i]->n_sorting; ++j) - config->ul[i]->sorting[j] = slice_config[mod_id]->ul[i]->sorting[j]; - config->ul[i]->has_accounting = 1; - config->ul[i]->accounting = slice_config[mod_id]->ul[i]->accounting; - config->ul[i]->scheduler_name = strdup(slice_config[mod_id]->ul[i]->scheduler_name); - } - pthread_mutex_unlock(&sc_update_mtx); return config; } diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c index 84a28683b7..4c80c561ee 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c @@ -1027,666 +1027,18 @@ int load_dl_scheduler_function(mid_t mod_id, const char *function_name) { Protocol__FlexSliceConfig *flexran_agent_create_slice_config(int n_dl, int m_ul) { - int i; Protocol__FlexSliceConfig *fsc = malloc(sizeof(Protocol__FlexSliceConfig)); if (!fsc) return NULL; protocol__flex_slice_config__init(fsc); - /* say there are n_dl slices but reserve memory for up to 10 so - * we don't need to reserve again later */ - fsc->n_dl = n_dl; - fsc->dl = calloc(10, sizeof(Protocol__FlexDlSlice *)); - if (!fsc->dl) fsc->n_dl = 0; - for (i = 0; i < 10; i++) { - fsc->dl[i] = malloc(sizeof(Protocol__FlexDlSlice)); - if (!fsc->dl[i]) continue; - protocol__flex_dl_slice__init(fsc->dl[i]); - } - - /* as above */ - fsc->n_ul = m_ul; - fsc->ul = calloc(10, sizeof(Protocol__FlexUlSlice *)); - if (!fsc->ul) fsc->n_ul = 0; - for (i = 0; i < 10; i++) { - fsc->ul[i] = malloc(sizeof(Protocol__FlexUlSlice)); - if (!fsc->ul[i]) continue; - protocol__flex_ul_slice__init(fsc->ul[i]); - } + /* TODO */ return fsc; } -void flexran_agent_read_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *s) -{ - s->intraslice_share_active = flexran_get_intraslice_sharing_active(mod_id); - s->has_intraslice_share_active = 1; - s->interslice_share_active = flexran_get_interslice_sharing_active(mod_id); - s->has_interslice_share_active = 1; -} - -void flexran_agent_read_slice_dl_config(mid_t mod_id, int slice_idx, Protocol__FlexDlSlice *dl_slice) -{ - dl_slice->id = flexran_get_dl_slice_id(mod_id, slice_idx); - dl_slice->has_id = 1; - /* read label from corresponding sc_update entry or give default */ - dl_slice->label = PROTOCOL__FLEX_SLICE_LABEL__xMBB; - dl_slice->has_label = 1; - for (int i = 0; i < sc_update[mod_id]->n_dl; i++) { - if (sc_update[mod_id]->dl[i]->id == dl_slice->id - && sc_update[mod_id]->dl[i]->has_label) { - dl_slice->label = sc_update[mod_id]->dl[i]->label; - break; - } - } - dl_slice->percentage = flexran_get_dl_slice_percentage(mod_id, slice_idx); - dl_slice->has_percentage = 1; - dl_slice->isolation = flexran_get_dl_slice_isolation(mod_id, slice_idx); - dl_slice->has_isolation = 1; - dl_slice->priority = flexran_get_dl_slice_priority(mod_id, slice_idx); - dl_slice->has_priority = 1; - dl_slice->position_low = flexran_get_dl_slice_position_low(mod_id, slice_idx); - dl_slice->has_position_low = 1; - dl_slice->position_high = flexran_get_dl_slice_position_high(mod_id, slice_idx); - dl_slice->has_position_high = 1; - dl_slice->maxmcs = flexran_get_dl_slice_maxmcs(mod_id, slice_idx); - dl_slice->has_maxmcs = 1; - dl_slice->n_sorting = flexran_get_dl_slice_sorting(mod_id, slice_idx, &dl_slice->sorting); - if (dl_slice->n_sorting < 1) dl_slice->sorting = NULL; - dl_slice->accounting = flexran_get_dl_slice_accounting_policy(mod_id, slice_idx); - dl_slice->has_accounting = 1; - const char *s_name = flexran_get_dl_slice_scheduler(mod_id, slice_idx); - if (!dl_slice->scheduler_name - || strcmp(dl_slice->scheduler_name, s_name) != 0) { - dl_slice->scheduler_name = realloc(dl_slice->scheduler_name, strlen(s_name) + 1); - strcpy(dl_slice->scheduler_name, s_name); - } -} - -void flexran_agent_read_slice_ul_config(mid_t mod_id, int slice_idx, Protocol__FlexUlSlice *ul_slice) -{ - ul_slice->id = flexran_get_ul_slice_id(mod_id, slice_idx); - ul_slice->has_id = 1; - /* read label from corresponding sc_update entry or give default */ - ul_slice->label = PROTOCOL__FLEX_SLICE_LABEL__xMBB; - ul_slice->has_label = 1; - for (int i = 0; i < sc_update[mod_id]->n_ul; i++) { - if (sc_update[mod_id]->ul[i]->id == ul_slice->id - && sc_update[mod_id]->ul[i]->has_label) { - ul_slice->label = sc_update[mod_id]->ul[i]->label; - break; - } - } - ul_slice->percentage = flexran_get_ul_slice_percentage(mod_id, slice_idx); - ul_slice->has_percentage = 1; - /*ul_slice->isolation = flexran_get_ul_slice_isolation(mod_id, slice_idx);*/ - ul_slice->has_isolation = 0; - /*ul_slice->priority = flexran_get_ul_slice_priority(mod_id, slice_idx);*/ - ul_slice->has_priority = 0; - ul_slice->first_rb = flexran_get_ul_slice_first_rb(mod_id, slice_idx); - ul_slice->has_first_rb = 1; - /*ul_slice-> = flexran_get_ul_slice_length_rb(mod_id, slice_idx); - ul_slice->has_length_rb = 0;*/ - ul_slice->maxmcs = flexran_get_ul_slice_maxmcs(mod_id, slice_idx); - ul_slice->has_maxmcs = 1; - ul_slice->n_sorting = 0; - /*if (ul_slice->sorting) { - free(ul_slice->sorting); - ul_slice->sorting = NULL; - } - ul_slice->n_sorting = flexran_get_ul_slice_sorting(mod_id, slice_idx, &ul_slice->sorting); - if (ul_slice->n_sorting < 1) ul_slice->sorting = NULL;*/ - /*ul_slice->accounting = flexran_get_ul_slice_accounting_policy(mod_id, slice_idx);*/ - ul_slice->has_accounting = 0; - const char *s_name = flexran_get_ul_slice_scheduler(mod_id, slice_idx); - if (!ul_slice->scheduler_name - || strcmp(ul_slice->scheduler_name, s_name) != 0) { - ul_slice->scheduler_name = realloc(ul_slice->scheduler_name, strlen(s_name) + 1); - strcpy(ul_slice->scheduler_name, s_name); - } -} - -int check_dl_sorting_update(Protocol__FlexDlSlice *old, Protocol__FlexDlSlice *new) -{ - /* sorting_update => true when old->n_sorting == 0 or different numbers of - * elements; otherwise will check * element-wise */ - int sorting_update = old->n_sorting == 0 || (old->n_sorting != new->n_sorting); - for (int i = 0; i < old->n_sorting && !sorting_update; ++i) { - sorting_update = sorting_update || (new->sorting[i] != old->sorting[i]); - } - return sorting_update; -} - -int check_ul_sorting_update(Protocol__FlexUlSlice *old, Protocol__FlexUlSlice *new) -{ - /* sorting_update => true when old->n_sorting == 0 or different numbers of - * elements; otherwise will check * element-wise */ - int sorting_update = old->n_sorting == 0 || (old->n_sorting != new->n_sorting); - for (int i = 0; i < old->n_sorting && !sorting_update; ++i) { - sorting_update = sorting_update || (new->sorting[i] != old->sorting[i]); - } - return sorting_update; -} - -void overwrite_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *exist, Protocol__FlexSliceConfig *update) -{ - if (update->has_intraslice_share_active - && exist->intraslice_share_active != update->intraslice_share_active) { - LOG_I(FLEXRAN_AGENT, "[%d] update intraslice_share_active: %d -> %d\n", - mod_id, exist->intraslice_share_active, update->intraslice_share_active); - exist->intraslice_share_active = update->intraslice_share_active; - exist->has_intraslice_share_active = 1; - } - if (update->has_interslice_share_active - && exist->interslice_share_active != update->interslice_share_active) { - LOG_I(FLEXRAN_AGENT, "[%d] update interslice_share_active: %d -> %d\n", - mod_id, exist->interslice_share_active, update->interslice_share_active); - exist->interslice_share_active = update->interslice_share_active; - exist->has_interslice_share_active = 1; - } -} - -void overwrite_slice_config_dl(mid_t mod_id, Protocol__FlexDlSlice *exist, Protocol__FlexDlSlice *update) -{ - if (update->label != exist->label) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update label: %d -> %d\n", - mod_id, update->id, exist->label, update->label); - exist->label = update->label; - exist->has_label = 1; - } - if (update->percentage != exist->percentage) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update percentage: %d -> %d\n", - mod_id, update->id, exist->percentage, update->percentage); - exist->percentage = update->percentage; - exist->has_percentage = 1; - } - if (update->isolation != exist->isolation) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update isolation: %d -> %d\n", - mod_id, update->id, exist->isolation, update->isolation); - exist->isolation = update->isolation; - exist->has_isolation = 1; - } - if (update->priority != exist->priority) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update priority: %d -> %d\n", - mod_id, update->id, exist->priority, update->priority); - exist->priority = update->priority; - exist->has_priority = 1; - } - if (update->position_low != exist->position_low) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update position_low: %d -> %d\n", - mod_id, update->id, exist->position_low, update->position_low); - exist->position_low = update->position_low; - exist->has_position_low = 1; - } - if (update->position_high != exist->position_high) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update position_high: %d -> %d\n", - mod_id, update->id, exist->position_high, update->position_high); - exist->position_high = update->position_high; - exist->has_position_high = 1; - } - if (update->maxmcs != exist->maxmcs) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update maxmcs: %d -> %d\n", - mod_id, update->id, exist->maxmcs, update->maxmcs); - exist->maxmcs = update->maxmcs; - exist->has_maxmcs = 1; - } - if (check_dl_sorting_update(exist, update)) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update sorting array\n", mod_id, update->id); - if (exist->n_sorting != update->n_sorting) { - exist->n_sorting = update->n_sorting; - exist->sorting = realloc(exist->sorting, exist->n_sorting * sizeof(Protocol__FlexDlSorting)); - if (!exist->sorting) exist->n_sorting = 0; - } - for (int i = 0; i < exist->n_sorting; i++) - exist->sorting[i] = update->sorting[i]; - } - if (update->accounting != exist->accounting) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update accounting: %d -> %d\n", - mod_id, update->id, exist->accounting, update->accounting); - exist->accounting = update->accounting; - exist->has_accounting = 1; - } - if (!exist->scheduler_name - || strcmp(update->scheduler_name, exist->scheduler_name) != 0) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update scheduler: %s -> %s\n", - mod_id, update->id, exist->scheduler_name, update->scheduler_name); - if (exist->scheduler_name) free(exist->scheduler_name); - exist->scheduler_name = strdup(update->scheduler_name); - } -} - -void overwrite_slice_config_ul(mid_t mod_id, Protocol__FlexUlSlice *exist, Protocol__FlexUlSlice *update) -{ - if (update->label != exist->label) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update label: %d -> %d\n", - mod_id, update->id, exist->label, update->label); - exist->label = update->label; - exist->has_label = 1; - } - if (update->percentage != exist->percentage) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update percentage: %d -> %d\n", - mod_id, update->id, exist->percentage, update->percentage); - exist->percentage = update->percentage; - exist->has_percentage = 1; - } - if (update->isolation != exist->isolation) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update isolation: %d -> %d\n", - mod_id, update->id, exist->isolation, update->isolation); - exist->isolation = update->isolation; - exist->has_isolation = 1; - } - if (update->priority != exist->priority) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update priority: %d -> %d\n", - mod_id, update->id, exist->priority, update->priority); - exist->priority = update->priority; - exist->has_priority = 1; - } - if (update->first_rb != exist->first_rb) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update first_rb: %d -> %d\n", - mod_id, update->id, exist->first_rb, update->first_rb); - exist->first_rb = update ->first_rb; - exist->has_first_rb = 1; - } - /*if (update->lenght_rb != exist->lenght_rb) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update lenght_rb: %d -> %d\n", - mod_id, update->id, exist->lenght_rb, update->lenght_rb); - exist->lenght_rb = update->lenght_rb; - }*/ - if (update->maxmcs != exist->maxmcs) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update maxmcs: %d -> %d\n", - mod_id, update->id, exist->maxmcs, update->maxmcs); - exist->maxmcs = update->maxmcs; - exist->has_maxmcs = 1; - } - /* TODO - int sorting_update = 0; - int n = min(exist->n_sorting, update->n_sorting); - int i = 0; - while (i < n && !sorting_update) { - sorting_update = sorting_update || (update->sorting[i] != exist->sorting[i]); - i++; - } - if (sorting_update) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update sorting array\n", update->id, mod_id); - if (exist->n_sorting != update->n_sorting) - LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] only writing %d elements\n", - mod_id, update->id, n); - for (i = 0; i < n; i++) - exist->sorting[i] = update->sorting[i]; - } - */ - if (update->accounting != exist->accounting) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update accounting: %d -> %d\n", - mod_id, update->id, exist->accounting, update->accounting); - exist->accounting = update->accounting; - exist->has_accounting = 1; - } - if (!exist->scheduler_name - || strcmp(update->scheduler_name, exist->scheduler_name) != 0) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update scheduler: %s -> %s\n", - mod_id, update->id, exist->scheduler_name, update->scheduler_name); - if (exist->scheduler_name) free(exist->scheduler_name); - exist->scheduler_name = strdup(update->scheduler_name); - } -} - -void fill_dl_slice(mid_t mod_id, Protocol__FlexDlSlice *s, Protocol__FlexDlSlice *from) -{ - /* function fills slice with information from another slice or with default - * values (currently slice 0) if from is NULL */ - /* TODO fill the slice depending on the chosen label */ - if (!s->has_label) { - s->has_label = 1; - s->label = from ? from->label : sc_update[mod_id]->dl[0]->label; - } - if (!s->has_percentage) { - s->has_percentage = 1; - s->percentage = from ? from->percentage : sc_update[mod_id]->dl[0]->percentage; - } - if (!s->has_isolation) { - s->has_isolation = 1; - s->isolation = from ? from->isolation : sc_update[mod_id]->dl[0]->isolation; - } - if (!s->has_priority) { - s->has_priority = 1; - s->priority = from ? from->priority : sc_update[mod_id]->dl[0]->priority; - } - if (!s->has_position_low) { - s->has_position_low = 1; - s->position_low = from ? from->position_low : sc_update[mod_id]->dl[0]->position_low; - } - if (!s->has_position_high) { - s->has_position_high = 1; - s->position_high = from ? from->position_high : sc_update[mod_id]->dl[0]->position_high; - } - if (!s->has_maxmcs) { - s->has_maxmcs = 1; - s->maxmcs = from ? from->maxmcs : sc_update[mod_id]->dl[0]->maxmcs; - } - if (s->n_sorting == 0) { - s->n_sorting = from ? from->n_sorting : sc_update[mod_id]->dl[0]->n_sorting; - s->sorting = calloc(s->n_sorting, sizeof(Protocol__FlexDlSorting)); - if (!s->sorting) s->n_sorting = 0; - for (int i = 0; i < s->n_sorting; ++i) - s->sorting[i] = from ? from->sorting[i] : sc_update[0]->dl[0]->sorting[i]; - } - if (!s->has_accounting) { - s->accounting = from ? from->accounting : sc_update[mod_id]->dl[0]->accounting; - } - if (!s->scheduler_name) { - s->scheduler_name = strdup(from ? from->scheduler_name : sc_update[mod_id]->dl[0]->scheduler_name); - } -} - -Protocol__FlexDlSlice *get_existing_dl_slice(mid_t mod_id, int id) -{ - for (int i = 0; i < sc_update[mod_id]->n_dl; ++i) { - if (id == sc_update[mod_id]->dl[i]->id) { - return sc_update[mod_id]->dl[i]; - } - } - return NULL; -} - -Protocol__FlexDlSlice *create_new_dl_slice(mid_t mod_id, int id) -{ - LOG_I(FLEXRAN_AGENT, - "[%d] Creating DL slice with ID %d, taking default values from DL slice 0\n", - mod_id, id); - Protocol__FlexDlSlice *to = sc_update[mod_id]->dl[sc_update[mod_id]->n_dl]; - sc_update[mod_id]->n_dl++; - AssertFatal(sc_update[mod_id]->n_dl <= 10, - "cannot create more than 10\n"); - to->id = id; - return to; -} - -void fill_ul_slice(mid_t mod_id, Protocol__FlexUlSlice *s, Protocol__FlexUlSlice *from) -{ - /* function fills slice with information from another slice or with default - * values (currently slice 0) if from is NULL */ - /* TODO fill the slice depending on the chosen label */ - if (!s->has_label) { - s->has_label = 1; - s->label = from ? from->label : sc_update[mod_id]->ul[0]->label; - } - if (!s->has_percentage) { - s->has_percentage = 1; - s->percentage = from ? from->percentage : sc_update[mod_id]->ul[0]->percentage; - } - if (!s->has_isolation) { - s->has_isolation = 1; - s->isolation = from ? from->isolation : sc_update[mod_id]->ul[0]->isolation; - } - if (!s->has_priority) { - s->has_priority = 1; - s->priority = from ? from->priority : sc_update[mod_id]->ul[0]->priority; - } - if (!s->has_first_rb) { - s->has_first_rb = 1; - s->first_rb = from ? from->first_rb : sc_update[mod_id]->ul[0]->first_rb; - } - if (!s->has_maxmcs) { - s->has_maxmcs = 1; - s->maxmcs = from ? from->maxmcs : sc_update[mod_id]->ul[0]->maxmcs; - } - if (s->n_sorting == 0) { - s->n_sorting = from ? from->n_sorting : sc_update[0]->ul[0]->n_sorting; - s->sorting = calloc(s->n_sorting, sizeof(Protocol__FlexUlSorting)); - if (!s->sorting) s->n_sorting = 0; - for (int i = 0; i < s->n_sorting; ++i) - s->sorting[i] = from ? from->sorting[i] : sc_update[0]->ul[0]->sorting[i]; - } - if (!s->has_accounting) { - s->accounting = from ? from->accounting : sc_update[0]->ul[0]->accounting; - } - if (!s->scheduler_name) { - s->scheduler_name = strdup(from ? from->scheduler_name : sc_update[mod_id]->ul[0]->scheduler_name); - } -} - -Protocol__FlexUlSlice *get_existing_ul_slice(mid_t mod_id, int id) -{ - for (int i = 0; i < sc_update[mod_id]->n_ul; ++i) { - if (id == sc_update[mod_id]->ul[i]->id) { - return sc_update[mod_id]->ul[i]; - } - } - return NULL; -} - -Protocol__FlexUlSlice *create_new_ul_slice(mid_t mod_id, int id) -{ - LOG_I(FLEXRAN_AGENT, - "[%d] Creating UL slice with ID %d, taking default values from UL slice 0\n", - mod_id, id); - Protocol__FlexUlSlice *to = sc_update[mod_id]->ul[sc_update[mod_id]->n_ul]; - sc_update[mod_id]->n_ul++; - AssertFatal(sc_update[mod_id]->n_ul <= 10, - "cannot create more than 10\n"); - to->id = id; - return to; -} - void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *sup) { - int verified = 1; - if (!sc_update[mod_id]) { - LOG_E(FLEXRAN_AGENT, "Can not update slice policy (no existing slice profile)\n"); - return; - } - - pthread_mutex_lock(&sc_update_mtx); - /* no need for tests in the current state as there are only two protobuf - * bools for intra-/interslice sharing. The function applies new values if - * applicable */ - overwrite_slice_config(mod_id, sc_update[mod_id], sup); - - if (sup->n_dl == 0) { - LOG_I(FLEXRAN_AGENT, "[%d] no DL slice configuration in flex_slice_config message\n", mod_id); - } else { - /* verify slice parameters */ - for (int i = 0; i < sup->n_dl; i++) { - if (!sup->dl[i]->has_id) { - verified = 0; - break; - } - Protocol__FlexDlSlice *dls = get_existing_dl_slice(mod_id, sup->dl[i]->id); - /* fill up so that the slice is complete. This way, we don't need to - * worry about it later */ - fill_dl_slice(mod_id, sup->dl[i], dls); - verified = verified && flexran_verify_dl_slice(mod_id, sup->dl[i]); - if (!verified) break; - } - - /* verify group-based parameters (e.g. sum percentage should not exceed - * 100%). Can be used to perform admission control */ - verified = verified && flexran_verify_group_dl_slices(mod_id, - sc_update[mod_id]->dl, sc_update[mod_id]->n_dl, sup->dl, sup->n_dl); - - if (verified) { - for (int i = 0; i < sup->n_dl; i++) { - /* if all verifications were successful, get existing slice for ID or - * create new one and overwrite with the update */ - Protocol__FlexDlSlice *dls = get_existing_dl_slice(mod_id, sup->dl[i]->id); - if (!dls) dls = create_new_dl_slice(mod_id, sup->dl[i]->id); - overwrite_slice_config_dl(mod_id, dls, sup->dl[i]); - } - } else { - LOG_E(FLEXRAN_AGENT, "[%d] DL slice verification failed, refusing application\n", mod_id); - } - } - - verified = 1; - if (sup->n_ul == 0) { - LOG_I(FLEXRAN_AGENT, "[%d] no UL slice configuration in flex_slice_config message\n", mod_id); - } else { - /* verify slice parameters */ - for (int i = 0; i < sup->n_ul; i++) { - if (!sup->ul[i]->has_id) { - verified = 0; - break; - } - Protocol__FlexUlSlice *uls = get_existing_ul_slice(mod_id, sup->ul[i]->id); - /* fill up so that the slice is complete. This way, we don't need to - * worry about it later */ - fill_ul_slice(mod_id, sup->ul[i], uls); - verified = verified && flexran_verify_ul_slice(mod_id, sup->ul[i]); - if (!verified) break; - } - - /* verify group-based parameters (e.g. sum percentage should not exceed - * 100%). Can be used to perform admission control */ - verified = verified && flexran_verify_group_ul_slices(mod_id, - sc_update[mod_id]->ul, sc_update[mod_id]->n_ul, sup->ul, sup->n_ul); - - if (verified) { - for (int i = 0; i < sup->n_ul; i++) { - /* if all verifications were successful, get existing slice for ID or - * create new one and overwrite with the update */ - Protocol__FlexUlSlice *uls = get_existing_ul_slice(mod_id, sup->ul[i]->id); - if (!uls) uls = create_new_ul_slice(mod_id, sup->ul[i]->id); - overwrite_slice_config_ul(mod_id, uls, sup->ul[i]); - } - } else { - LOG_E(FLEXRAN_AGENT, "[%d] UL slice verification failed, refusing application\n", mod_id); - } - } - pthread_mutex_unlock(&sc_update_mtx); - - perform_slice_config_update_count = 1; } -int apply_new_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *olds, Protocol__FlexSliceConfig *news) -{ - /* not setting the old configuration is intentional, as it will be picked up - * later when reading the configuration. There is thus a direct feedback - * whether it has been set. */ - int changes = 0; - if (olds->intraslice_share_active != news->intraslice_share_active) { - flexran_set_intraslice_sharing_active(mod_id, news->intraslice_share_active); - changes++; - } - if (olds->interslice_share_active != news->interslice_share_active) { - flexran_set_interslice_sharing_active(mod_id, news->interslice_share_active); - changes++; - } - return changes; -} - -int apply_new_slice_dl_config(mid_t mod_id, Protocol__FlexDlSlice *oldc, Protocol__FlexDlSlice *newc) -{ - /* not setting the old configuration is intentional, as it will be picked up - * later when reading the configuration. There is thus a direct feedback - * whether it has been set. */ - int changes = 0; - int slice_idx = flexran_find_dl_slice(mod_id, newc->id); - if (slice_idx < 0) { - LOG_W(FLEXRAN_AGENT, "[%d] cannot find index for slice ID %d\n", mod_id, newc->id); - return 0; - } - if (oldc->percentage != newc->percentage) { - flexran_set_dl_slice_percentage(mod_id, slice_idx, newc->percentage); - changes++; - } - if (oldc->isolation != newc->isolation) { - flexran_set_dl_slice_isolation(mod_id, slice_idx, newc->isolation); - changes++; - } - if (oldc->priority != newc->priority) { - flexran_set_dl_slice_priority(mod_id, slice_idx, newc->priority); - changes++; - } - if (oldc->position_low != newc->position_low) { - flexran_set_dl_slice_position_low(mod_id, slice_idx, newc->position_low); - changes++; - } - if (oldc->position_high != newc->position_high) { - flexran_set_dl_slice_position_high(mod_id, slice_idx, newc->position_high); - changes++; - } - if (oldc->maxmcs != newc->maxmcs) { - flexran_set_dl_slice_maxmcs(mod_id, slice_idx, newc->maxmcs); - changes++; - } - if (check_dl_sorting_update(oldc, newc)) { - flexran_set_dl_slice_sorting(mod_id, slice_idx, newc->sorting, newc->n_sorting); - changes++; - } - if (oldc->accounting != newc->accounting) { - flexran_set_dl_slice_accounting_policy(mod_id, slice_idx, newc->accounting); - changes++; - } - if (!oldc->scheduler_name - || strcmp(oldc->scheduler_name, newc->scheduler_name) != 0) { - int ret = flexran_set_dl_slice_scheduler(mod_id, slice_idx, newc->scheduler_name); - AssertFatal(ret, "could not set DL slice scheduler for slice %d idx %d\n", - newc->id, slice_idx); - changes++; - } - return changes; -} - -int apply_new_slice_ul_config(mid_t mod_id, Protocol__FlexUlSlice *oldc, Protocol__FlexUlSlice *newc) -{ - /* not setting the old configuration is intentional, as it will be picked up - * later when reading the configuration. There is thus a direct feedback - * whether it has been set. */ - int changes = 0; - int slice_idx = flexran_find_ul_slice(mod_id, newc->id); - if (slice_idx < 0) { - LOG_W(FLEXRAN_AGENT, "[%d] cannot find index for slice ID %d\n", mod_id, newc->id); - return 0; - } - if (oldc->percentage != newc->percentage) { - flexran_set_ul_slice_percentage(mod_id, slice_idx, newc->percentage); - changes++; - } - if (oldc->isolation != newc->isolation) { - /*flexran_set_ul_slice_isolation(mod_id, slice_idx, newc->isolation); - *changes++;*/ - LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting isolation is not supported\n", - mod_id, newc->id); - } - if (oldc->priority != newc->priority) { - /*flexran_set_ul_slice_priority(mod_id, slice_idx, newc->priority); - *changes++;*/ - LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting the priority is not supported\n", - mod_id, newc->id); - } - if (oldc->first_rb != newc->first_rb) { - flexran_set_ul_slice_first_rb(mod_id, slice_idx, newc->first_rb); - changes++; - } - /*if (oldc->length_rb != newc->length_rb) { - flexran_set_ul_slice_length_rb(mod_id, slice_idx, newc->length_rb); - changes++; - LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting length_rb is not supported\n", - mod_id, newc->id); - }*/ - if (oldc->maxmcs != newc->maxmcs) { - flexran_set_ul_slice_maxmcs(mod_id, slice_idx, newc->maxmcs); - changes++; - } - /*if (check_ul_sorting_update(oldc, newc)) { - flexran_set_ul_slice_sorting(mod_id, slice_idx, newc->sorting, n); - changes++; - LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting the sorting is not supported\n", - mod_id, newc->id); - }*/ - if (oldc->accounting != newc->accounting) { - /*flexran_set_ul_slice_accounting_policy(mod_id, slice_idx, newc->accounting); - *changes++;*/ - LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting the accounting is not supported\n", - mod_id, newc->id); - } - if (!oldc->scheduler_name - || strcmp(oldc->scheduler_name, newc->scheduler_name) != 0) { - int ret = flexran_set_ul_slice_scheduler(mod_id, slice_idx, newc->scheduler_name); - AssertFatal(ret, "could not set DL slice scheduler for slice %d idx %d\n", - newc->id, slice_idx); - changes++; - } - return changes; -} void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config) { @@ -1723,24 +1075,8 @@ int apply_ue_slice_assoc_update(mid_t mod_id) continue; } if (ue_slice_assoc_update[i]->has_dl_slice_id) { - int slice_idx = flexran_find_dl_slice(mod_id, ue_slice_assoc_update[i]->dl_slice_id); - if (flexran_dl_slice_exists(mod_id, slice_idx)) { - flexran_set_ue_dl_slice_idx(mod_id, ue_id, slice_idx); - changes++; - } else { - LOG_W(FLEXRAN_AGENT, "[%d] DL slice %d does not exist, refusing change\n", - mod_id, ue_slice_assoc_update[i]->dl_slice_id); - } } if (ue_slice_assoc_update[i]->has_ul_slice_id) { - int slice_idx = flexran_find_ul_slice(mod_id, ue_slice_assoc_update[i]->ul_slice_id); - if (flexran_ul_slice_exists(mod_id, slice_idx)) { - flexran_set_ue_ul_slice_idx(mod_id, ue_id, slice_idx); - changes++; - } else { - LOG_W(FLEXRAN_AGENT, "[%d] UL slice %d does not exist, refusing change\n", - mod_id, ue_slice_assoc_update[i]->ul_slice_id); - } } } n_ue_slice_assoc_updates = 0; diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h index 957fe6065e..ef2a7e40a9 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h @@ -111,30 +111,10 @@ Protocol__FlexSliceConfig *flexran_agent_create_slice_config(int n_dl, int m_ul) * Protocol__FlexSliceConfig struct */ void flexran_agent_read_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *s); -/* read the DL slice config via the RAN into a given Protocol__FlexDlSlice - * struct */ -void flexran_agent_read_slice_dl_config(mid_t mod_id, int slice_idx, Protocol__FlexDlSlice *dl_slice); - -/* read the UL slice config via the RAN into a given Protocol__FlexUlSlice - * struct */ -void flexran_agent_read_slice_ul_config(mid_t mod_id, int slice_idx, Protocol__FlexUlSlice *ul_slice); - /* reads content of slice over the sc_update structure, so that it can be * applied later by performing a diff between slice_config and sc_update */ void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *slice); -/* apply generic slice parameters (e.g. intra-/interslice sharing activated or - * not) if there are changes. Returns the number of changed parameters. */ -int apply_new_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *olds, Protocol__FlexSliceConfig *news); - -/* apply new configuration of slice in DL if there are changes between the - * parameters. Returns the number of changed parameters. */ -int apply_new_slice_dl_config(mid_t mod_id, Protocol__FlexDlSlice *oldc, Protocol__FlexDlSlice *newc); - -/* apply new configuration of slice in UL if there are changes between the - * parameters. Returns the number of changed parameters. */ -int apply_new_slice_ul_config(mid_t mod_id, Protocol__FlexUlSlice *oldc, Protocol__FlexUlSlice *newc); - /* inserts a new ue_config into the structure keeping ue to slice association * updates and marks so it can be applied */ void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config); diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c index f7f60541f5..6e54e155c2 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c @@ -28,346 +28,3 @@ #include "flexran_agent_mac_slice_verification.h" - -/* overlap check for UL slices, helper type */ -struct sregion_s { - int start; - int length; -}; - -/* forward declaration of locally-used verification functions */ -int flexran_dl_slice_verify_pct(int pct); -int flexran_dl_slice_verify_priority(int prio); -int flexran_dl_slice_verify_position(int pos_low, int pos_high); -int flexran_dl_slice_verify_maxmcs(int maxmcs); -int flexran_ul_slice_verify_pct(int pct); -int flexran_ul_slice_verify_priority(int prio); -int flexran_ul_slice_verify_first_rb(int first_rb); -int flexran_ul_slice_verify_maxmcs(int maxmcs); -int check_ul_slice_overlap(mid_t mod_id, struct sregion_s *sr, int n); - -int flexran_verify_dl_slice(mid_t mod_id, Protocol__FlexDlSlice *dls) -{ - /* check mandatory parameters */ - if (!dls->has_id) { - LOG_E(FLEXRAN_AGENT, "[%d] Incoming DL slice configuration has no ID\n", mod_id); - return 0; - } - - /* verify parameters individualy */ - /* label is enum */ - if (!flexran_dl_slice_verify_pct(dls->percentage)) { - LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] illegal DL slice percentage (%d)\n", - mod_id, dls->id, dls->percentage); - return 0; - } - /* isolation is a protobuf bool */ - if (!flexran_dl_slice_verify_priority(dls->priority)) { - LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] illegal DL slice priority (%d)\n", - mod_id, dls->id, dls->priority); - return 0; - } - if (!flexran_dl_slice_verify_position(dls->position_low, dls->position_high)) { - LOG_E(FLEXRAN_AGENT, - "[%d][DL slice %d] illegal DL slice position low (%d) and/or high (%d)\n", - mod_id, dls->id, dls->position_low, dls->position_high); - return 0; - } - if (!flexran_dl_slice_verify_maxmcs(dls->maxmcs)) { - LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] illegal DL slice max mcs %d\n", - mod_id, dls->id, dls->maxmcs); - return 0; - } - if (dls->n_sorting == 0) { - LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] no sorting in DL slice\n", - mod_id, dls->id); - return 0; - } - if (!dls->sorting) { - LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] no sorting found in DL slice\n", - mod_id, dls->id); - return 0; - } - /* sorting is an enum */ - /* accounting is an enum */ - if (!dls->scheduler_name) { - LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] no scheduler name found\n", - mod_id, dls->id); - return 0; - } - if (strcmp(dls->scheduler_name, "schedule_ue_spec") != 0) { - LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] setting the scheduler to something " - "different than schedule_ue_spec is currently not allowed\n", - mod_id, dls->id); - return 0; - } - - return 1; -} - -int flexran_verify_group_dl_slices(mid_t mod_id, Protocol__FlexDlSlice **existing, - int n_ex, Protocol__FlexDlSlice **update, int n_up) -{ - int i, j, n; - int pct, pct_orig; - /* for every update, array points to existing slice, or NULL if update - * creates new slice */ - Protocol__FlexDlSlice *s[n_up]; - for (i = 0; i < n_up; i++) { - s[i] = NULL; - for (j = 0; j < n_ex; j++) { - if (existing[j]->id == update[i]->id) - s[i] = existing[j]; - } - } - - /* check that number of created and number of added slices in total matches - * [1,10] */ - n = n_ex; - for (i = 0; i < n_up; i++) { - /* new slice */ - if (!s[i]) n += 1; - /* slice will be deleted */ - else if (s[i]->percentage == 0) n -= 1; - /* else "only" an update */ - } - - if (n < 1 || n > 10) { - LOG_E(FLEXRAN_AGENT, "[%d] Illegal number of resulting DL slices (%d -> %d)\n", - mod_id, n_ex, n); - return 0; - } - - /* check that the sum of all slices percentages (including removed/added - * slices) matches [1,100] */ - pct = 0; - for (i = 0; i < n_ex; i++) { - pct += existing[i]->percentage; - } - pct_orig = pct; - for (i = 0; i < n_up; i++) { - /* if there is an existing slice, subtract its percentage and add the - * update's percentage */ - if (s[i]) - pct -= s[i]->percentage; - pct += update[i]->percentage; - } - if (pct < 1 || pct > 100) { - LOG_E(FLEXRAN_AGENT, - "[%d] invalid total RB share for DL slices (%d%% -> %d%%)\n", - mod_id, pct_orig, pct); - return 0; - } - - return 1; -} - -int flexran_verify_ul_slice(mid_t mod_id, Protocol__FlexUlSlice *uls) -{ - /* check mandatory parameters */ - if (!uls->has_id) { - LOG_E(FLEXRAN_AGENT, "[%d] Incoming UL slice configuration has no ID\n", mod_id); - return 0; - } - - /* verify parameters individually */ - /* label is enum */ - if (!flexran_ul_slice_verify_pct(uls->percentage)) { - LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] illegal UL slice percentage (%d)\n", - mod_id, uls->id, uls->percentage); - return 0; - } - /* isolation is a protobuf bool */ - if (!flexran_ul_slice_verify_priority(uls->priority)) { - LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] illegal UL slice percentage (%d)\n", - mod_id, uls->id, uls->priority); - return 0; - } - if (!flexran_ul_slice_verify_first_rb(uls->first_rb)) { - LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] illegal UL slice first RB (%d)\n", - mod_id, uls->id, uls->first_rb); - return 0; - } - if (!flexran_ul_slice_verify_maxmcs(uls->maxmcs)) { - LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] illegal UL slice max mcs (%d)\n", - mod_id, uls->id, uls->maxmcs); - return 0; - } - /* TODO - if (uls->n_sorting == 0) { - LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] no sorting in UL slice\n", - mod_id, uls->id); - return 0; - } - if (!uls->sorting) { - LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] no sorting found in UL slice\n", - mod_id, uls->id); - return 0; - } - */ - /* sorting is an enum */ - /* accounting is an enum */ - if (!uls->scheduler_name) { - LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] no scheduler name found\n", - mod_id, uls->id); - return 0; - } - if (strcmp(uls->scheduler_name, "schedule_ulsch_rnti") != 0) { - LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] setting the scheduler to something " - "different than schedule_ulsch_rnti is currently not allowed\n", - mod_id, uls->id); - return 0; - } - - return 1; -} - -int flexran_verify_group_ul_slices(mid_t mod_id, Protocol__FlexUlSlice **existing, - int n_ex, Protocol__FlexUlSlice **update, int n_up) -{ - int i, j, n; - int pct, pct_orig; - /* for every update, array "s" points to existing slice, or NULL if update - * creates new slice; array "offs" gives the offset of this slice */ - Protocol__FlexUlSlice *s[n_up]; - int offs[n_up]; - for (i = 0; i < n_up; i++) { - s[i] = NULL; - offs[i] = 0; - for (j = 0; j < n_ex; j++) { - if (existing[j]->id == update[i]->id) { - s[i] = existing[j]; - offs[i] = j; - } - } - } - - /* check that number of created and number of added slices in total matches - * [1,10] */ - n = n_ex; - for (i = 0; i < n_up; i++) { - /* new slice */ - if (!s[i]) n += 1; - /* slice will be deleted */ - else if (s[i]->percentage == 0) n -= 1; - /* else "only" an update */ - } - - if (n < 1 || n > 10) { - LOG_E(FLEXRAN_AGENT, "[%d] Illegal number of resulting UL slices (%d -> %d)\n", - mod_id, n_ex, n); - return 0; - } - - /* check that the sum of all slices percentages (including removed/added - * slices) matches [1,100] */ - pct = 0; - for (i = 0; i < n_ex; i++) { - pct += existing[i]->percentage; - } - pct_orig = pct; - for (i = 0; i < n_up; i++) { - /* if there is an existing slice, subtract its percentage and add the - * update's percentage */ - if (s[i]) - pct -= s[i]->percentage; - pct += update[i]->percentage; - } - if (pct < 1 || pct > 100) { - LOG_E(FLEXRAN_AGENT, "[%d] invalid total RB share (%d%% -> %d%%)\n", - mod_id, pct_orig, pct); - return 0; - } - - /* check that there is no overlap in slices resulting as the combination of - * first_rb and percentage */ - struct sregion_s sregion[n]; - const int N_RB = flexran_get_N_RB_UL(mod_id, 0); /* assume PCC */ - int k = n_ex; - for (i = 0; i < n_ex; i++) { - sregion[i].start = existing[i]->first_rb; - sregion[i].length = existing[i]->percentage * N_RB / 100; - } - for (i = 0; i < n_up; i++) { - ptrdiff_t d = s[i] ? offs[i] : k++; - AssertFatal(d >= 0 && d < k, "illegal pointer offset (%ld, k=%d)\n", d, k); - sregion[d].start = update[i]->first_rb; - sregion[d].length = update[i]->percentage * N_RB / 100; - } - AssertFatal(k == n, "illegal number of slices while calculating overlap\n"); - if (!check_ul_slice_overlap(mod_id, sregion, k)) { - LOG_E(FLEXRAN_AGENT, "[%d] UL slices are overlapping\n", mod_id); - return 0; - } - - return 1; -} - -int flexran_dl_slice_verify_pct(int pct) -{ - return pct >= 0 && pct <= 100; -} - -int flexran_dl_slice_verify_priority(int prio) -{ - return prio >= 0; -} - -int flexran_dl_slice_verify_position(int pos_low, int pos_high) -{ - return pos_low < pos_high && pos_low >= 0 && pos_high <= N_RBG_MAX; -} - -int flexran_dl_slice_verify_maxmcs(int maxmcs) -{ - return maxmcs >= 0 && maxmcs <= 28; -} - -int flexran_ul_slice_verify_pct(int pct) -{ - return pct >= 0 && pct <= 100; -} - -int flexran_ul_slice_verify_priority(int prio) -{ - return prio >= 0; -} - -int flexran_ul_slice_verify_first_rb(int first_rb) -{ - return first_rb >= 0 && first_rb < 100; -} - -int flexran_ul_slice_verify_maxmcs(int maxmcs) -{ - return maxmcs >= 0 && maxmcs <= 20; -} - -int sregion_compare(const void *_a, const void *_b) -{ - const struct sregion_s *a = (const struct sregion_s *)_a; - const struct sregion_s *b = (const struct sregion_s *)_b; - const int res = a->start - b->start; - if (res < 0) return -1; - else if (res == 0) return 0; - else return 1; -} - -int check_ul_slice_overlap(mid_t mod_id, struct sregion_s *sr, int n) -{ - int i; - int overlap, op, u; - const int N_RB = flexran_get_N_RB_UL(mod_id, 0); /* assume PCC */ - qsort(sr, n, sizeof(sr[0]), sregion_compare); - for (i = 0; i < n; i++) { - u = i == n-1 ? N_RB : sr[i+1].start; - AssertFatal(sr[i].start <= u, "unsorted slice list\n"); - overlap = sr[i].start + sr[i].length - u; - if (overlap <= 0) continue; - op = overlap * 100 / sr[i].length; - LOG_W(FLEXRAN_AGENT, "[%d] slice overlap of %d%% detected\n", mod_id, op); - if (op >= 10) /* more than 10% overlap -> refuse */ - return 0; - } - return 1; -} diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.h b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.h index a8f4030d36..c9e66b6f88 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.h +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.h @@ -29,9 +29,3 @@ #include "flexran_agent_common_internal.h" #include "flexran_agent_mac_internal.h" -int flexran_verify_dl_slice(mid_t mod_id, Protocol__FlexDlSlice *dls); -int flexran_verify_group_dl_slices(mid_t mod_id, Protocol__FlexDlSlice **existing, - int n_ex, Protocol__FlexDlSlice **update, int n_up); -int flexran_verify_ul_slice(mid_t mod_id, Protocol__FlexUlSlice *uls); -int flexran_verify_group_ul_slices(mid_t mod_id, Protocol__FlexUlSlice **existing, - int n_ex, Protocol__FlexUlSlice **update, int n_up); diff --git a/openair2/ENB_APP/MESSAGES/V2/config_common.proto b/openair2/ENB_APP/MESSAGES/V2/config_common.proto index 733d883c92..e5d01ebdc0 100644 --- a/openair2/ENB_APP/MESSAGES/V2/config_common.proto +++ b/openair2/ENB_APP/MESSAGES/V2/config_common.proto @@ -61,83 +61,6 @@ enum flex_qam { // // Slice config related structures and enums // -enum flex_dl_sorting { - - CR_ROUND = 0; // Highest HARQ first - CR_SRB12 = 1; // Highest SRB1+2 first - CR_HOL = 2; // Highest HOL first - CR_LC = 3; // Greatest RLC buffer first - CR_CQI = 4; // Highest CQI first - CR_LCP = 5; // Highest LC priority first -} - -enum flex_ul_sorting { - CRU_ROUND = 0; // Highest HARQ first - CRU_BUF = 1; // Highest BSR first - CRU_BTS = 2; // More bytes to schedule first - CRU_MCS = 3; // Highest MCS first - CRU_LCP = 4; // Highest LC priority first - CRU_HOL = 5; // Highest HOL first -} - -enum flex_dl_accounting_policy { - POL_FAIR = 0; - POL_GREEDY = 1; - POL_NUM = 2; -} - -enum flex_ul_accounting_policy { - POLU_FAIR = 0; - POLU_GREEDY = 1; - POLU_NUM = 2; -} - -enum flex_slice_label { - xMBB = 0; - URLLC = 1; - mMTC = 2; - xMTC = 3; - Other = 4; -} - -message flex_dl_slice { - optional uint32 id = 1; - optional flex_slice_label label = 2; - // should be between 0 and 100 - optional uint32 percentage = 3; - // whether this slice should be exempted form interslice sharing - optional bool isolation = 4; - // increasing value means increasing prio - optional uint32 priority = 5; - // min and max RB to use (in frequency) in the range [0, N_RBG_MAX] - optional uint32 position_low = 6; - optional uint32 position_high = 7; - // maximum MCS to be allowed in this slice - optional uint32 maxmcs = 8; - repeated flex_dl_sorting sorting = 9; - optional flex_dl_accounting_policy accounting = 10; - optional string scheduler_name = 11; -} - -message flex_ul_slice { - optional uint32 id = 1; - optional flex_slice_label label = 2; - // should be between 0 and 100 - optional uint32 percentage = 3; - // whether this slice should be exempted form interslice sharing - optional bool isolation = 4; - // increasing value means increasing prio - optional uint32 priority = 5; - // RB start to use (in frequency) in the range [0, N_RB_MAX] - optional uint32 first_rb = 6; - // TODO RB number - //optional uint32 length_rb = 7; - // maximum MCS to be allowed in this slice - optional uint32 maxmcs = 8; - repeated flex_ul_sorting sorting = 9; - optional flex_ul_accounting_policy accounting = 10; - optional string scheduler_name = 11; -} // // UE config related structures and enums diff --git a/openair2/ENB_APP/MESSAGES/V2/config_messages.proto b/openair2/ENB_APP/MESSAGES/V2/config_messages.proto index 324153613d..1a66a4f20f 100644 --- a/openair2/ENB_APP/MESSAGES/V2/config_messages.proto +++ b/openair2/ENB_APP/MESSAGES/V2/config_messages.proto @@ -49,14 +49,6 @@ message flex_cell_config { } message flex_slice_config { - // whether remaining RBs after first intra-slice allocation will - // be allocated to UEs of the same slice - optional bool intraslice_share_active = 3; - // whether remaining RBs after slice allocation will be allocated - // to UEs of another slice. Isolated slices will be ignored. - optional bool interslice_share_active = 4; - repeated flex_dl_slice dl = 1; - repeated flex_ul_slice ul = 2; } message flex_ue_config { diff --git a/openair2/ENB_APP/flexran_agent_common.c b/openair2/ENB_APP/flexran_agent_common.c index e77b2fb386..3dd9f5b957 100644 --- a/openair2/ENB_APP/flexran_agent_common.c +++ b/openair2/ENB_APP/flexran_agent_common.c @@ -316,25 +316,7 @@ int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg) { } if (reply->cell_config[i]->slice_config) { - for (int j = 0; j < reply->cell_config[i]->slice_config->n_dl; ++j) { - if (reply->cell_config[i]->slice_config->dl[j]->n_sorting > 0) - free(reply->cell_config[i]->slice_config->dl[j]->sorting); - - free(reply->cell_config[i]->slice_config->dl[j]->scheduler_name); - free(reply->cell_config[i]->slice_config->dl[j]); - } - - free(reply->cell_config[i]->slice_config->dl); - - for (int j = 0; j < reply->cell_config[i]->slice_config->n_ul; ++j) { - if (reply->cell_config[i]->slice_config->ul[j]->n_sorting > 0) - free(reply->cell_config[i]->slice_config->ul[j]->sorting); - - free(reply->cell_config[i]->slice_config->ul[j]->scheduler_name); - free(reply->cell_config[i]->slice_config->ul[j]); - } - - free(reply->cell_config[i]->slice_config->ul); + /* TODO */ free(reply->cell_config[i]->slice_config); } diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index 291c4dc7d8..cd8b0b8f67 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -3018,142 +3018,44 @@ int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) { return 0; } -void flexran_set_ue_dl_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx) { - if (!mac_is_present(mod_id)) return; -} - int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return -1; return 0; } -void flexran_set_ue_ul_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx) { - if (!mac_is_present(mod_id)) return; -} - -int flexran_dl_slice_exists(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return 0; -} - +/* TODO */ int flexran_create_dl_slice(mid_t mod_id, slice_id_t slice_id) { if (!mac_is_present(mod_id)) return -1; return -1; } +/* TODO */ +int flexran_remove_dl_slice(mid_t mod_id, int slice_idx) { + if (!mac_is_present(mod_id)) return -1; + return -1; +} + int flexran_find_dl_slice(mid_t mod_id, slice_id_t slice_id) { if (!mac_is_present(mod_id)) return -1; return -1; } -int flexran_remove_dl_slice(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} +//int flexran_get_dl_slice(mid_t mod_id, int slice_idx, Protocol__FlexSlice *s) { +//} int flexran_get_num_dl_slices(mid_t mod_id) { if (!mac_is_present(mod_id)) return -1; return 0; } -int flexran_get_intraslice_sharing_active(mid_t mod_id) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} -void flexran_set_intraslice_sharing_active(mid_t mod_id, int intraslice_active) { +/* TODO */ +void flexran_create_ul_slice(mid_t mod_id, slice_id_t slice_id) { if (!mac_is_present(mod_id)) return; + return; } -int flexran_get_interslice_sharing_active(mid_t mod_id) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} -void flexran_set_interslice_sharing_active(mid_t mod_id, int interslice_active) { - if (!mac_is_present(mod_id)) return; -} - -slice_id_t flexran_get_dl_slice_id(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} -void flexran_set_dl_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id) { - if (!mac_is_present(mod_id)) return; -} - -int flexran_get_dl_slice_percentage(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} -void flexran_set_dl_slice_percentage(mid_t mod_id, int slice_idx, int percentage) { - if (!mac_is_present(mod_id)) return; -} - -int flexran_get_dl_slice_isolation(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} -void flexran_set_dl_slice_isolation(mid_t mod_id, int slice_idx, int is_isolated) { - if (!mac_is_present(mod_id)) return; -} - -int flexran_get_dl_slice_priority(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} -void flexran_set_dl_slice_priority(mid_t mod_id, int slice_idx, int priority) { - if (!mac_is_present(mod_id)) return; -} - -int flexran_get_dl_slice_position_low(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} -void flexran_set_dl_slice_position_low(mid_t mod_id, int slice_idx, int poslow) { - if (!mac_is_present(mod_id)) return; -} - -int flexran_get_dl_slice_position_high(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} -void flexran_set_dl_slice_position_high(mid_t mod_id, int slice_idx, int poshigh) { - if (!mac_is_present(mod_id)) return; -} - -int flexran_get_dl_slice_maxmcs(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} -void flexran_set_dl_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs) { - if (!mac_is_present(mod_id)) return; -} - -int flexran_get_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting **sorting_list) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} -void flexran_set_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting *sorting_list, int n) { - if (!mac_is_present(mod_id)) return; -} - -Protocol__FlexDlAccountingPolicy flexran_get_dl_slice_accounting_policy(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR; - return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR; -} -void flexran_set_dl_slice_accounting_policy(mid_t mod_id, int slice_idx, Protocol__FlexDlAccountingPolicy accounting) { - if (!mac_is_present(mod_id)) return; -} - -char *flexran_get_dl_slice_scheduler(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return NULL; - return NULL; -} -int flexran_set_dl_slice_scheduler(mid_t mod_id, int slice_idx, char *name) { - if (!mac_is_present(mod_id)) return 0; - return 0; -} - -int flexran_create_ul_slice(mid_t mod_id, slice_id_t slice_id) { +/* TODO */ +int flexran_remove_ul_slice(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; return -1; } @@ -3163,62 +3065,14 @@ int flexran_find_ul_slice(mid_t mod_id, slice_id_t slice_id) { return -1; } -int flexran_remove_ul_slice(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} +//int flexran_get_ul_slice(mid_t mod_id, int slice_idx, Protocol__FlexSlice *s) { +//} int flexran_get_num_ul_slices(mid_t mod_id) { if (!mac_is_present(mod_id)) return -1; return 0; } -int flexran_ul_slice_exists(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return 0; -} - -slice_id_t flexran_get_ul_slice_id(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} -void flexran_set_ul_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id) { - if (!mac_is_present(mod_id)) return; -} - -int flexran_get_ul_slice_percentage(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} -void flexran_set_ul_slice_percentage(mid_t mod_id, int slice_idx, int percentage) { - if (!mac_is_present(mod_id)) return; -} - -int flexran_get_ul_slice_first_rb(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} - -void flexran_set_ul_slice_first_rb(mid_t mod_id, int slice_idx, int first_rb) { - if (!mac_is_present(mod_id)) return; -} - -int flexran_get_ul_slice_maxmcs(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} -void flexran_set_ul_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs) { - if (!mac_is_present(mod_id)) return; -} - -char *flexran_get_ul_slice_scheduler(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return NULL; - return ""; -} -int flexran_set_ul_slice_scheduler(mid_t mod_id, int slice_idx, char *name) { - if (!mac_is_present(mod_id)) return 0; - return 0; -} /************************** S1AP **************************/ int flexran_get_s1ap_mme_pending(mid_t mod_id){ diff --git a/openair2/ENB_APP/flexran_agent_ran_api.h b/openair2/ENB_APP/flexran_agent_ran_api.h index 9d1bfb9d3e..c29ba53c11 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.h +++ b/openair2/ENB_APP/flexran_agent_ran_api.h @@ -659,153 +659,38 @@ uint32_t flexran_get_rrc_enb_ue_s1ap_id(mid_t mod_id, rnti_t rnti); /* Get the DL slice ID for a UE */ int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id); - /* Set the DL slice index(!) for a UE */ -void flexran_set_ue_dl_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx); +//void flexran_set_ue_dl_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx); /* Get the UL slice ID for a UE */ int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id); - /* Set the UL slice index(!) for a UE */ -void flexran_set_ue_ul_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx); +//void flexran_set_ue_ul_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx); -/* Whether intraslice sharing is active, return boolean */ -int flexran_get_intraslice_sharing_active(mid_t mod_id); -/* Set whether intraslice sharing is active */ -void flexran_set_intraslice_sharing_active(mid_t mod_id, int intraslice_active); - -/* Whether intraslice sharing is active, return boolean */ -int flexran_get_interslice_sharing_active(mid_t mod_id); -/* Set whether intraslice sharing is active */ -void flexran_set_interslice_sharing_active(mid_t mod_id, int interslice_active); +/* Create slice in DL, returns the new slice index */ +//int flexran_create_dl_slice(mid_t mod_id, slice_id_t slice_id); +/* Remove slice in DL, returns new number of slices or -1 on error */ +//int flexran_remove_dl_slice(mid_t mod_id, int slice_idx); +/* Finds slice in DL with given slice_id and returns slice index */ +int flexran_find_dl_slice(mid_t mod_id, slice_id_t slice_id); +/* Return the parameters of slice at index slice_idx */ +//void flexran_get_dl_slice(mid_t mod_id, int slice_idx, Protocol__FlexSlice *s); /* Get the number of slices in DL */ int flexran_get_num_dl_slices(mid_t mod_id); -/* Query slice existence in DL. Return is boolean value */ -int flexran_dl_slice_exists(mid_t mod_id, int slice_idx); +/* Create slice in UL, returns the new slice index */ +//int flexran_create_ul_slice(mid_t mod_id, slice_id_t slice_id); +/* Remove slice in UL */ +//int flexran_remove_ul_slice(mid_t mod_id, int slice_idx); -/* Create slice in DL, returns the new slice index */ -int flexran_create_dl_slice(mid_t mod_id, slice_id_t slice_id); /* Finds slice in DL with given slice_id and returns slice index */ -int flexran_find_dl_slice(mid_t mod_id, slice_id_t slice_id); -/* Remove slice in DL, returns new number of slices or -1 on error */ -int flexran_remove_dl_slice(mid_t mod_id, int slice_idx); - -/* Get the ID of a slice in DL */ -slice_id_t flexran_get_dl_slice_id(mid_t mod_id, int slice_idx); -/* Set the ID of a slice in DL */ -void flexran_set_dl_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id); - -/* Get the RB share a slice in DL, value 0-100 */ -int flexran_get_dl_slice_percentage(mid_t mod_id, int slice_idx); -/* Set the RB share a slice in DL, value 0-100 */ -void flexran_set_dl_slice_percentage(mid_t mod_id, int slice_idx, int percentage); - -/* Whether a slice in DL is isolated */ -int flexran_get_dl_slice_isolation(mid_t mod_id, int slice_idx); -/* Set whether a slice in DL is isolated */ -void flexran_set_dl_slice_isolation(mid_t mod_id, int slice_idx, int is_isolated); - -/* Get the priority of a slice in DL */ -int flexran_get_dl_slice_priority(mid_t mod_id, int slice_idx); -/* Get the priority of a slice in DL */ -void flexran_set_dl_slice_priority(mid_t mod_id, int slice_idx, int priority); - -/* Get the lower end of the frequency range for the slice positioning in DL */ -int flexran_get_dl_slice_position_low(mid_t mod_id, int slice_idx); -/* Set the lower end of the frequency range for the slice positioning in DL */ -void flexran_set_dl_slice_position_low(mid_t mod_id, int slice_idx, int poslow); - -/* Get the higher end of the frequency range for the slice positioning in DL */ -int flexran_get_dl_slice_position_high(mid_t mod_id, int slice_idx); -/* Set the higher end of the frequency range for the slice positioning in DL */ -void flexran_set_dl_slice_position_high(mid_t mod_id, int slice_idx, int poshigh); - -/* Get the maximum MCS for slice in DL */ -int flexran_get_dl_slice_maxmcs(mid_t mod_id, int slice_idx); -/* Set the maximum MCS for slice in DL */ -void flexran_set_dl_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs); - -/* Get the sorting order of a slice in DL, return value is number of elements - * in sorting_list */ -int flexran_get_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting **sorting_list); -/* Set the sorting order of a slice in DL */ -void flexran_set_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting *sorting_list, int n); - -/* Get the accounting policy for a slice in DL */ -Protocol__FlexDlAccountingPolicy flexran_get_dl_slice_accounting_policy(mid_t mod_id, int slice_idx); -/* Set the accounting policy for a slice in DL */ -void flexran_set_dl_slice_accounting_policy(mid_t mod_id, int slice_idx, Protocol__FlexDlAccountingPolicy accounting); - -/* Get the scheduler name for a slice in DL */ -char *flexran_get_dl_slice_scheduler(mid_t mod_id, int slice_idx); -/* Set the scheduler name for a slice in DL */ -int flexran_set_dl_slice_scheduler(mid_t mod_id, int slice_idx, char *name); - +int flexran_find_ul_slice(mid_t mod_id, slice_id_t slice_id); +/* Return the parameters of slice at index slice_idx */ +//void flexran_get_ul_slice(mid_t mod_id, int slice_idx, Protocol__FlexSlice *s); /* Get the number of slices in UL */ int flexran_get_num_ul_slices(mid_t mod_id); -/* Query slice existence in UL. Return is boolean value */ -int flexran_ul_slice_exists(mid_t mod_id, int slice_idx); - -/* Create slice in UL, returns the new slice index */ -int flexran_create_ul_slice(mid_t mod_id, slice_id_t slice_id); -/* Finds slice in UL with given slice_id and returns slice index */ -int flexran_find_ul_slice(mid_t mod_id, slice_id_t slice_id); -/* Remove slice in UL */ -int flexran_remove_ul_slice(mid_t mod_id, int slice_idx); - -/* Get the ID of a slice in UL */ -slice_id_t flexran_get_ul_slice_id(mid_t mod_id, int slice_idx); -/* Set the ID of a slice in UL */ -void flexran_set_ul_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id); - -/* Get the RB share a slice in UL, value 0-100 */ -int flexran_get_ul_slice_percentage(mid_t mod_id, int slice_idx); -/* Set the RB share a slice in UL, value 0-100 */ -void flexran_set_ul_slice_percentage(mid_t mod_id, int slice_idx, int percentage); - -/* TODO Whether a slice in UL is isolated */ -/*int flexran_get_ul_slice_isolation(mid_t mod_id, int slice_idx);*/ -/* TODO Set whether a slice in UL is isolated */ -/*void flexran_set_ul_slice_isolation(mid_t mod_id, int slice_idx, int is_isolated);*/ - -/* TODO Get the priority of a slice in UL */ -/*int flexran_get_ul_slice_priority(mid_t mod_id, int slice_idx);*/ -/* TODO Set the priority of a slice in UL */ -/*void flexran_set_ul_slice_priority(mid_t mod_id, int slice_idx, int priority);*/ - -/* Get the first RB for allocation in a slice in UL */ -int flexran_get_ul_slice_first_rb(mid_t mod_id, int slice_idx); -/* Set the first RB for allocation in a slice in UL */ -void flexran_set_ul_slice_first_rb(mid_t mod_id, int slice_idx, int first_rb); - -/* TODO Get the number of RB for the allocation in a slice in UL */ -/*int flexran_get_ul_slice_length_rb(mid_t mod_id, int slice_idx);*/ -/* TODO Set the of number of RB for the allocation in a slice in UL */ -/*void flexran_set_ul_slice_length_rb(mid_t mod_id, int slice_idx, int poshigh);*/ - -/* Get the maximum MCS for slice in UL */ -int flexran_get_ul_slice_maxmcs(mid_t mod_id, int slice_idx); -/* Set the maximum MCS for slice in UL */ -void flexran_set_ul_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs); - -/* TODO Get the sorting order of a slice in UL, return value is number of elements - * in sorting_list */ -/*int flexran_get_ul_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexUlSorting **sorting_list);*/ -/* TODO Set the sorting order of a slice in UL */ -/*void flexran_set_ul_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexUlSorting *sorting_list, int n);*/ - -/* TODO Get the accounting policy for a slice in UL */ -/*Protocol__UlAccountingPolicy flexran_get_ul_slice_accounting_policy(mid_t mod_id, int slice_idx);*/ -/* TODO Set the accounting policy for a slice in UL */ -/*void flexran_get_ul_slice_accounting_policy(mid_t mod_id, int slice_idx, Protocol__UlAccountingPolicy accountin);*/ - -/* Get the scheduler name for a slice in UL */ -char *flexran_get_ul_slice_scheduler(mid_t mod_id, int slice_idx); -/* Set the scheduler name for a slice in UL */ -int flexran_set_ul_slice_scheduler(mid_t mod_id, int slice_idx, char *name); /************************** S1AP **************************/ /* Get the number of MMEs to be connected */ From a21e9aa6ef4a840a343abab0da7e5df9153e8f4b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 12 Apr 2020 15:16:21 +0200 Subject: [PATCH 24/66] Simplify add_ue_list(), remove_ue_list(); add init_ue_list() --- .../LAYER2/MAC/eNB_scheduler_primitives.c | 43 ++++++++++--------- openair2/LAYER2/MAC/mac_proto.h | 1 + openair2/LAYER2/MAC/main.c | 5 +-- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index 78d6f6a3d7..b75ab774c6 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -2131,33 +2131,36 @@ dump_ue_list(UE_list_t *listP) { * Add a UE to UE_list listP */ inline void add_ue_list(UE_list_t *listP, int UE_id) { - if (listP->head == -1) { - listP->head = UE_id; - listP->next[UE_id] = -1; - } else { - int i = listP->head; - while (listP->next[i] >= 0) - i = listP->next[i]; - listP->next[i] = UE_id; - listP->next[UE_id] = -1; - } + int *cur = &listP->head; + while (*cur >= 0) + cur = &listP->next[*cur]; + *cur = UE_id; } //------------------------------------------------------------------------------ /* - * Remove a UE from the UE_list listP, return the previous element + * Remove a UE from the UE_list listP */ inline int remove_ue_list(UE_list_t *listP, int UE_id) { - listP->next[UE_id] = -1; - if (listP->head == UE_id) { - listP->head = listP->next[UE_id]; - return -1; - } + int *cur = &listP->head; + while (*cur != -1 && *cur != UE_id) + cur = &listP->next[*cur]; + if (*cur == -1) + return 0; + int *next = &listP->next[*cur]; + *cur = listP->next[*cur]; + *next = -1; + return 1; +} - int previous = prev(listP, UE_id); - if (previous != -1) - listP->next[previous] = listP->next[UE_id]; - return previous; +//------------------------------------------------------------------------------ +/* + * Initialize the UE_list listP + */ +inline void init_ue_list(UE_list_t *listP) { + listP->head = -1; + for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) + listP->next[i] = -1; } //------------------------------------------------------------------------------ diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index 61251ef088..818eb834fb 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -659,6 +659,7 @@ int prev(UE_list_t *listP, int nodeP); void add_ue_list(UE_list_t *listP, int UE_id); int remove_ue_list(UE_list_t *listP, int UE_id); void dump_ue_list(UE_list_t *listP); +void init_ue_list(UE_list_t *listP); int UE_num_active_CC(UE_info_t *listP, int ue_idP); int UE_PCCID(module_id_t mod_idP, int ue_idP); rnti_t UE_RNTI(module_id_t mod_idP, int ue_idP); diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index 35b5136889..659c7250e8 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -45,11 +45,8 @@ extern RAN_CONTEXT_t RC; void init_UE_info(UE_info_t *UE_info) { - int list_el; UE_info->num_UEs = 0; - UE_info->list.head = -1; - for (list_el = 0; list_el < MAX_MOBILES_PER_ENB; list_el++) - UE_info->list.next[list_el] = -1; + init_ue_list(&UE_info->list); memset(UE_info->DLSCH_pdu, 0, sizeof(UE_info->DLSCH_pdu)); memset(UE_info->UE_template, 0, sizeof(UE_info->UE_template)); memset(UE_info->eNB_UE_stats, 0, sizeof(UE_info->eNB_UE_stats)); From 115c1f38f6164786123c443ecac0df727123a07f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 12 Apr 2020 14:38:05 +0200 Subject: [PATCH 25/66] Use fptr for preproc and align UL PP definition --- openair2/ENB_APP/enb_config.c | 9 +-- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 5 +- .../LAYER2/MAC/eNB_scheduler_primitives.c | 12 ++++ openair2/LAYER2/MAC/eNB_scheduler_ulsch.c | 4 +- openair2/LAYER2/MAC/mac.h | 59 +++++++++++++++++-- openair2/LAYER2/MAC/mac_proto.h | 6 +- openair2/LAYER2/MAC/main.c | 13 ++-- openair2/LAYER2/MAC/pre_processor.c | 46 +++++++-------- 8 files changed, 110 insertions(+), 44 deletions(-) diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 3bde7da02c..2e8ee0329f 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -266,10 +266,11 @@ void RCconfig_macrlc(int macrlc_has_f1[MAX_MAC_INST]) { void *d = dlsym(NULL, s); AssertFatal(d, "%s(): no default scheduler DL algo '%s' found\n", __func__, s); // release default, add new - RC.mac[j]->dl_algo.unset(&RC.mac[j]->dl_algo.data); - RC.mac[j]->dl_algo = *(default_sched_dl_algo_t *) d; - RC.mac[j]->dl_algo.data = RC.mac[j]->dl_algo.setup(); - LOG_I(ENB_APP, "using default scheduler DL algo '%s'\n", RC.mac[j]->dl_algo.name); + pp_impl_param_t *dl_pp = &RC.mac[j]->pre_processor_dl; + dl_pp->dl_algo.unset(&dl_pp->dl_algo.data); + dl_pp->dl_algo = *(default_sched_dl_algo_t *) d; + dl_pp->dl_algo.data = dl_pp->dl_algo.setup(); + LOG_I(ENB_APP, "using default scheduler DL algo '%s'\n", dl_pp->dl_algo.name); }// j=0..num_inst } /*else {// MacRLC_ParamList.numelt > 0 // ignore it diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 783d4e8b1a..1f99f50ece 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -573,10 +573,7 @@ schedule_ue_spec(module_id_t module_idP, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR, VCD_FUNCTION_IN); start_meas(&eNB->schedule_dlsch_preprocessor); - dlsch_scheduler_pre_processor(module_idP, - CC_id, - frameP, - subframeP); + eNB->pre_processor_dl.dl(module_idP, CC_id, frameP, subframeP); stop_meas(&eNB->schedule_dlsch_preprocessor); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR, VCD_FUNCTION_OUT); diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index b75ab774c6..89c2ecc83d 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -2199,6 +2199,12 @@ add_new_ue(module_id_t mod_idP, UE_info->active[UE_id] = TRUE; add_ue_list(&UE_info->list, UE_id); dump_ue_list(&UE_info->list); + pp_impl_param_t* dl = &RC.mac[mod_idP]->pre_processor_dl; + if (dl->slices) // inform slice implementation about new UE + dl->add_UE(dl->slices, UE_id); + pp_impl_param_t* ul = &RC.mac[mod_idP]->pre_processor_ul; + if (ul->slices) // inform slice implementation about new UE + ul->add_UE(ul->slices, UE_id); if (IS_SOFTMODEM_IQPLAYER)// not specific to record/playback ? UE_info->UE_template[cc_idP][UE_id].pre_assigned_mcs_ul = 0; UE_info->UE_template[cc_idP][UE_id].rach_resource_type = rach_resource_type; @@ -2262,6 +2268,12 @@ rrc_mac_remove_ue(module_id_t mod_idP, UE_info->num_UEs--; remove_ue_list(&UE_info->list, UE_id); + pp_impl_param_t* dl = &RC.mac[mod_idP]->pre_processor_dl; + if (dl->slices) // inform slice implementation about new UE + dl->remove_UE(dl->slices, UE_id); + pp_impl_param_t* ul = &RC.mac[mod_idP]->pre_processor_ul; + if (ul->slices) // inform slice implementation about new UE + ul->remove_UE(ul->slices, UE_id); /* Clear all remaining pending transmissions */ memset(&UE_info->UE_template[pCC_id][UE_id], 0, sizeof(UE_TEMPLATE)); diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index 3062e5c964..2de45db856 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -1301,11 +1301,11 @@ schedule_ulsch_rnti(module_id_t module_idP, /* * ULSCH preprocessor: set UE_template-> - * pre_allocated_nb_rb_ul[slice_idx] + * pre_allocated_nb_rb_ul * pre_assigned_mcs_ul * pre_allocated_rb_table_index_ul */ - ulsch_scheduler_pre_processor(module_idP, CC_id, frameP, subframeP, sched_frame, sched_subframeP); + mac->pre_processor_ul.ul(module_idP, CC_id, frameP, subframeP, sched_frame, sched_subframeP); for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { if (UE_info->UE_template[CC_id][UE_id].rach_resource_type > 0) diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h index 8349d84d48..faefc481f6 100644 --- a/openair2/LAYER2/MAC/mac.h +++ b/openair2/LAYER2/MAC/mac.h @@ -540,7 +540,6 @@ typedef enum { SCHED_MODE_FAIR_RR /// fair raund robin } SCHEDULER_MODES; - /*! \brief temporary struct for ULSCH sched */ typedef struct { rnti_t rnti; @@ -1199,6 +1198,56 @@ typedef struct { void *data; } default_sched_ul_algo_t; +typedef void (*pp_impl_dl)(module_id_t mod_id, + int CC_id, + frame_t frame, + sub_frame_t subframe); +typedef void (*pp_impl_ul)(module_id_t mod_id, + int CC_id, + frame_t frame, + sub_frame_t subframe, + frame_t sched_frame, + sub_frame_t sched_subframe); + +struct slice_info_s; +typedef struct { + int algorithm; + + /// inform the slice algorithm about a new UE + void (*add_UE)(struct slice_info_s *s, int UE_id); + /// inform the slice algorithm about a UE that disconnected + void (*remove_UE)(struct slice_info_s *s, int UE_id); + /// move a UE to a slice in DL/UL, -1 means don't move (no-op). + void (*move_UE)(struct slice_info_s *s, int UE_id, int idx); + + /// Adds a new slice through admission control. slice_params are + /// algorithm-specific parameters. sched is either a default_sched_ul_algo_t + /// or default_sched_dl_algo_t, depending on whether this implementation + /// handles UL/DL. If slice at index exists, updates existing + /// slice. Returns index of new slice or -1 on failure. + int (*addmod_slice)(struct slice_info_s *s, + int id, + char *label, + void *sched, + void *slice_params); + /// Returns slice through slice_idx. 1 if successful, 0 if not. + int (*remove_slice)(struct slice_info_s *s, uint8_t slice_idx); + + union { + pp_impl_dl dl; + pp_impl_ul ul; + }; + + union { + default_sched_ul_algo_t ul_algo; + default_sched_dl_algo_t dl_algo; + }; + + void (*destroy)(struct slice_info_s **s); + + struct slice_info_s *slices; +} pp_impl_param_t; + /*! \brief eNB common channels */ typedef struct { int physCellId; @@ -1354,9 +1403,11 @@ typedef struct eNB_MAC_INST_s { UE_free_list_t UE_free_list; /// for scheduling selection SCHEDULER_MODES scheduler_mode; - /// scheduling algorithm used in default scheduler - default_sched_dl_algo_t dl_algo; - default_sched_ul_algo_t ul_algo; + /// Default scheduler: Pre-processor implementation. Algorithms for UL/DL + /// are called by ULSCH/DLSCH, respectively. Pro-processor implementation can + /// encapsulate slicing. + pp_impl_param_t pre_processor_dl; + pp_impl_param_t pre_processor_ul; int32_t puSch10xSnr; int32_t puCch10xSnr; diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index 818eb834fb..9d49fdffd5 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -674,10 +674,10 @@ void set_ul_DAI(int module_idP, void ulsch_scheduler_pre_processor(module_id_t module_idP, int CC_id, - int frameP, + frame_t frameP, sub_frame_t subframeP, - int sched_frameP, - unsigned char sched_subframeP); + frame_t sched_frameP, + sub_frame_t sched_subframeP); int phy_stats_exist(module_id_t Mod_id, int rnti); diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index 659c7250e8..24038e60d5 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -99,16 +99,21 @@ void mac_top_init_eNB(void) } mac[i]->if_inst = IF_Module_init(i); + + mac[i]->pre_processor_dl.dl = dlsch_scheduler_pre_processor; char *s = "round_robin_dl"; void *d = dlsym(NULL, s); AssertFatal(d, "%s(): no scheduler algo '%s' found\n", __func__, s); - mac[i]->dl_algo = *(default_sched_dl_algo_t *) d; - mac[i]->dl_algo.data = mac[i]->dl_algo.setup(); + mac[i]->pre_processor_dl.dl_algo = *(default_sched_dl_algo_t *) d; + mac[i]->pre_processor_dl.dl_algo.data = mac[i]->pre_processor_dl.dl_algo.setup(); + + mac[i]->pre_processor_ul.ul = ulsch_scheduler_pre_processor; s = "round_robin_ul"; d = dlsym(NULL, s); AssertFatal(d, "%s(): no scheduler algo '%s' found\n", __func__, s); - mac[i]->ul_algo = *(default_sched_ul_algo_t *) d; - mac[i]->ul_algo.data = mac[i]->ul_algo.setup(); + mac[i]->pre_processor_ul.ul_algo = *(default_sched_ul_algo_t *) d; + mac[i]->pre_processor_ul.ul_algo.data = mac[i]->pre_processor_ul.ul_algo.setup(); + init_UE_info(&mac[i]->UE_info); } diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 5eb27699be..b39ce62bb7 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -691,15 +691,15 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, n_rbg_sched += rbgalloc_mask[i]; } - mac->dl_algo.run(Mod_id, - CC_id, - frameP, - subframeP, - &UE_to_sched, - 4, // max_num_ue - n_rbg_sched, - rbgalloc_mask, - mac->dl_algo.data); + mac->pre_processor_dl.dl_algo.run(Mod_id, + CC_id, + frameP, + subframeP, + &UE_to_sched, + 4, // max_num_ue + n_rbg_sched, + rbgalloc_mask, + mac->pre_processor_dl.dl_algo.data); // the following block is meant for validation of the pre-processor to check // whether all UE allocations are non-overlapping and is not necessary for @@ -1068,10 +1068,10 @@ default_sched_ul_algo_t round_robin_ul = { void ulsch_scheduler_pre_processor(module_id_t Mod_id, int CC_id, - int frameP, + frame_t frameP, sub_frame_t subframeP, - int sched_frameP, - unsigned char sched_subframeP) { + frame_t sched_frameP, + sub_frame_t sched_subframeP) { eNB_MAC_INST *mac = RC.mac[Mod_id]; UE_info_t *UE_info = &mac->UE_info; const int N_RB_UL = to_prb(mac->common_channels[CC_id].ul_Bandwidth); @@ -1128,17 +1128,17 @@ void ulsch_scheduler_pre_processor(module_id_t Mod_id, } } - mac->ul_algo.run(Mod_id, - CC_id, - frameP, - subframeP, - sched_frameP, - sched_subframeP, - &UE_to_sched, - 4, // max_num_ue - n_contig, - rbs, - mac->ul_algo.data); + mac->pre_processor_ul.ul_algo.run(Mod_id, + CC_id, + frameP, + subframeP, + sched_frameP, + sched_subframeP, + &UE_to_sched, + 4, // max_num_ue + n_contig, + rbs, + mac->pre_processor_ul.ul_algo.data); // the following block is meant for validation of the pre-processor to check // whether all UE allocations are non-overlapping and is not necessary for From d2fe5af67a844744c3b455a0129397ee5e4c1e2f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 12 Apr 2020 18:33:55 +0200 Subject: [PATCH 26/66] Implement Static Slicing --- cmake_targets/CMakeLists.txt | 1 + openair2/LAYER2/MAC/slicing/slicing.c | 586 ++++++++++++++++++ openair2/LAYER2/MAC/slicing/slicing.h | 74 +++ .../LAYER2/MAC/slicing/slicing_internal.h | 46 ++ 4 files changed, 707 insertions(+) create mode 100644 openair2/LAYER2/MAC/slicing/slicing.c create mode 100644 openair2/LAYER2/MAC/slicing/slicing.h create mode 100644 openair2/LAYER2/MAC/slicing/slicing_internal.h diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 525c9eae56..8d964821c0 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -1830,6 +1830,7 @@ set (MAC_SRC ${MAC_DIR}/eNB_scheduler_fairRR.c ${MAC_DIR}/eNB_scheduler_phytest.c ${MAC_DIR}/pre_processor.c + ${MAC_DIR}/slicing/slicing.c ${MAC_DIR}/config.c ${MAC_DIR}/config_ue.c ) diff --git a/openair2/LAYER2/MAC/slicing/slicing.c b/openair2/LAYER2/MAC/slicing/slicing.c new file mode 100644 index 0000000000..a1de326df0 --- /dev/null +++ b/openair2/LAYER2/MAC/slicing/slicing.c @@ -0,0 +1,586 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! + * \file slicing.c + * \brief Generic slicing helper functions and Static Slicing Implementation + * \author Robert Schmidt + * \date 2020 + * \email robert.schmidt@eurecom.fr + */ + +#define _GNU_SOURCE +#include +#include + +#include "assertions.h" +#include "common/utils/LOG/log.h" + +#include "slicing.h" +#include "slicing_internal.h" + +#include "common/ran_context.h" +extern RAN_CONTEXT_t RC; + +#define RET_FAIL(ret, x...) do { LOG_E(MAC, x); return ret; } while (0) + +int slicing_get_UE_slice_idx(slice_info_t *si, int UE_id) { + return si->UE_assoc_slice[UE_id]; +} + +void slicing_add_UE(slice_info_t *si, int UE_id) { + add_ue_list(&si->s[0]->UEs, UE_id); + si->UE_assoc_slice[UE_id] = 0; +} + +void _remove_UE(slice_t **s, uint8_t *assoc, int UE_id) { + const uint8_t i = assoc[UE_id]; + DevAssert(remove_ue_list(&s[i]->UEs, UE_id)); + assoc[UE_id] = -1; +} + +void slicing_remove_UE(slice_info_t *si, int UE_id) { + _remove_UE(si->s, si->UE_assoc_slice, UE_id); +} + +void _move_UE(slice_t **s, uint8_t *assoc, int UE_id, int to) { + const uint8_t i = assoc[UE_id]; + const int ri = remove_ue_list(&s[i]->UEs, UE_id); + if (!ri) + LOG_W(MAC, "did not find UE %d in DL slice index %d\n", UE_id, i); + add_ue_list(&s[to]->UEs, UE_id); + assoc[UE_id] = to; +} + +void slicing_move_UE(slice_info_t *si, int UE_id, int idx) { + DevAssert(idx >= -1 && idx < si->num); + if (idx >= 0) + _move_UE(si->s, si->UE_assoc_slice, UE_id, idx); +} + +int _exists_slice(uint8_t n, slice_t **s, int id) { + for (int i = 0; i < n; ++i) + if (s[i]->id == id) + return i; + return -1; +} + +slice_t *_add_slice(uint8_t *n, slice_t **s) { + s[*n] = calloc(1, sizeof(slice_t)); + if (!s[*n]) + return NULL; + init_ue_list(&s[*n]->UEs); + *n += 1; + return s[*n - 1]; +} + +slice_t *_remove_slice(uint8_t *n, slice_t **s, uint8_t *assoc, int idx) { + if (idx >= *n) + return NULL; + + slice_t *sr = s[idx]; + while (sr->UEs.head >= 0) + _move_UE(s, assoc, sr->UEs.head, 0); + + for (int i = idx + 1; i < *n; ++i) + s[i - 1] = s[i]; + *n -= 1; + s[*n] = NULL; + + for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) + if (assoc[i] > idx) + assoc[i] -= 1; + + if (sr->label) + free(sr->label); + + return sr; +} + +/************************ Static Slicing Implementation ************************/ + +int addmod_static_slice_dl(slice_info_t *si, + int id, + char *label, + void *algo, + void *slice_params_dl) { + static_slice_param_t *dl = slice_params_dl; + if (dl && dl->posLow > dl->posHigh) + RET_FAIL(-1, "%s(): slice id %d posLow > posHigh\n", __func__, id); + + uint8_t rbgMap[25] = { 0 }; + int index = _exists_slice(si->num, si->s, id); + if (index >= 0) { + for (int s = 0; s < si->num; ++s) { + static_slice_param_t *sd = dl && si->s[s]->id == id ? dl : si->s[s]->algo_data; + for (int i = sd->posLow; i <= sd->posHigh; ++i) { + if (rbgMap[i]) + RET_FAIL(-33, "%s(): overlap of slices detected at RBG %d\n", __func__, i); + rbgMap[i] = 1; + } + } + /* no problem, can allocate */ + slice_t *s = si->s[index]; + if (label) { + if (s->label) free(s->label); + s->label = label; + } + if (algo) { + s->dl_algo.unset(&s->dl_algo.data); + s->dl_algo = *(default_sched_dl_algo_t *) algo; + if (!s->dl_algo.data) + s->dl_algo.data = s->dl_algo.setup(); + } + if (dl) { + free(s->algo_data); + s->algo_data = dl; + } + return index; + } + + if (!dl) + RET_FAIL(-100, "%s(): no parameters for new slice %d, aborting\n", __func__, id); + + if (si->num >= MAX_STATIC_SLICES) + RET_FAIL(-2, "%s(): cannot have more than %d slices\n", __func__, MAX_STATIC_SLICES); + for (int s = 0; s < si->num; ++s) { + static_slice_param_t *sd = si->s[s]->algo_data; + for (int i = sd->posLow; i <= sd->posHigh; ++i) + rbgMap[i] = 1; + } + + for (int i = dl->posLow; i <= dl->posHigh; ++i) + if (rbgMap[i]) + RET_FAIL(-3, "%s(): overlap of slices detected at RBG %d\n", __func__, i); + + if (!algo) + RET_FAIL(-14, "%s(): no scheduler algorithm provided\n", __func__); + + slice_t *ns = _add_slice(&si->num, si->s); + if (!ns) + RET_FAIL(-4, "%s(): could not create new slice\n", __func__); + ns->id = id; + ns->label = label; + ns->dl_algo = *(default_sched_dl_algo_t *) algo; + if (!ns->dl_algo.data) + ns->dl_algo.data = ns->dl_algo.setup(); + ns->algo_data = dl; + + return si->num - 1; +} + +int addmod_static_slice_ul(slice_info_t *si, + int id, + char *label, + void *algo, + void *slice_params_ul) { + static_slice_param_t *ul = slice_params_ul; + /* Minimum 3RBs, because LTE stack requires this */ + if (ul && ul->posLow + 2 > ul->posHigh) + RET_FAIL(-1, "%s(): slice id %d posLow + 2 > posHigh\n", __func__, id); + + uint8_t rbMap[110] = { 0 }; + int index = _exists_slice(si->num, si->s, id); + if (index >= 0) { + for (int s = 0; s < si->num; ++s) { + static_slice_param_t *su = ul && si->s[s]->id == id && ul ? ul : si->s[s]->algo_data; + for (int i = su->posLow; i <= su->posHigh; ++i) { + if (rbMap[i]) + RET_FAIL(-33, "%s(): overlap of slices detected at RBG %d\n", __func__, i); + rbMap[i] = 1; + } + } + /* no problem, can allocate */ + slice_t *s = si->s[index]; + if (algo) { + s->ul_algo.unset(&s->ul_algo.data); + s->ul_algo = *(default_sched_ul_algo_t *) algo; + if (!s->ul_algo.data) + s->ul_algo.data = s->ul_algo.setup(); + } + if (label) { + if (s->label) free(s->label); + s->label = label; + } + if (ul) { + free(s->algo_data); + s->algo_data = ul; + } + return index; + } + + if (!ul) + RET_FAIL(-100, "%s(): no parameters for new slice %d, aborting\n", __func__, id); + + if (si->num >= MAX_STATIC_SLICES) + RET_FAIL(-2, "%s(): cannot have more than %d slices\n", __func__, MAX_STATIC_SLICES); + for (int s = 0; s < si->num; ++s) { + static_slice_param_t *sd = si->s[s]->algo_data; + for (int i = sd->posLow; i <= sd->posHigh; ++i) + rbMap[i] = 1; + } + + for (int i = ul->posLow; i <= ul->posHigh; ++i) + if (rbMap[i]) + RET_FAIL(-3, "%s(): overlap of slices detected at RBG %d\n", __func__, i); + + if (!algo) + RET_FAIL(-14, "%s(): no scheduler algorithm provided\n", __func__); + + slice_t *ns = _add_slice(&si->num, si->s); + if (!ns) + RET_FAIL(-4, "%s(): could not create new slice\n", __func__); + ns->id = id; + ns->label = label; + ns->ul_algo = *(default_sched_ul_algo_t *) algo; + if (!ns->ul_algo.data) + ns->ul_algo.data = ns->ul_algo.setup(); + ns->algo_data = ul; + + return si->num - 1; +} + +int remove_static_slice(slice_info_t *si, uint8_t slice_idx) { + if (slice_idx == 0) + return 0; + slice_t *sr = _remove_slice(&si->num, si->s, si->UE_assoc_slice, slice_idx); + if (!sr) + return 0; + free(sr->algo_data); + free(sr); + return 1; +} + +void static_dl(module_id_t mod_id, + int CC_id, + frame_t frame, + sub_frame_t subframe) { + UE_info_t *UE_info = &RC.mac[mod_id]->UE_info; + + store_dlsch_buffer(mod_id, CC_id, frame, subframe); + + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + + /* initialize per-UE scheduling information */ + ue_sched_ctrl->pre_nb_available_rbs[CC_id] = 0; + ue_sched_ctrl->dl_pow_off[CC_id] = 2; + memset(ue_sched_ctrl->rballoc_sub_UE[CC_id], 0, sizeof(ue_sched_ctrl->rballoc_sub_UE[CC_id])); + ue_sched_ctrl->pre_dci_dl_pdu_idx = -1; + } + + const int N_RBG = to_rbg(RC.mac[mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); + const int RBGsize = get_min_rb_unit(mod_id, CC_id); + uint8_t *vrb_map = RC.mac[mod_id]->common_channels[CC_id].vrb_map; + uint8_t rbgalloc_mask[N_RBG_MAX]; + for (int i = 0; i < N_RBG; i++) { + // calculate mask: init to one + "AND" with vrb_map: + // if any RB in vrb_map is blocked (1), the current RBG will be 0 + rbgalloc_mask[i] = 1; + for (int j = 0; j < RBGsize; j++) + rbgalloc_mask[i] &= !vrb_map[RBGsize * i + j]; + } + + slice_info_t *s = RC.mac[mod_id]->pre_processor_dl.slices; + int max_num_ue; + switch (s->num) { + case 1: + max_num_ue = 4; + break; + case 2: + max_num_ue = 2; + break; + default: + max_num_ue = 1; + break; + } + for (int i = 0; i < s->num; ++i) { + if (s->s[i]->UEs.head < 0) + continue; + uint8_t rbgalloc_slice_mask[N_RBG_MAX]; + memset(rbgalloc_slice_mask, 0, sizeof(rbgalloc_slice_mask)); + static_slice_param_t *p = s->s[i]->algo_data; + int n_rbg_sched = 0; + for (int rbg = p->posLow; rbg <= p->posHigh && rbg <= N_RBG; ++rbg) { + rbgalloc_slice_mask[rbg] = rbgalloc_mask[rbg]; + n_rbg_sched += rbgalloc_mask[rbg]; + } + + s->s[i]->dl_algo.run(mod_id, + CC_id, + frame, + subframe, + &s->s[i]->UEs, + max_num_ue, // max_num_ue + n_rbg_sched, + rbgalloc_slice_mask, + s->s[i]->dl_algo.data); + } + + // the following block is meant for validation of the pre-processor to check + // whether all UE allocations are non-overlapping and is not necessary for + // scheduling functionality + char t[26] = "_________________________"; + t[N_RBG] = 0; + for (int i = 0; i < N_RBG; i++) + for (int j = 0; j < RBGsize; j++) + if (vrb_map[RBGsize*i+j] != 0) + t[i] = 'x'; + int print = 0; + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + const UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + + if (ue_sched_ctrl->pre_nb_available_rbs[CC_id] == 0) + continue; + + LOG_D(MAC, + "%4d.%d UE%d %d RBs allocated, pre MCS %d\n", + frame, + subframe, + UE_id, + ue_sched_ctrl->pre_nb_available_rbs[CC_id], + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1); + + print = 1; + + for (int i = 0; i < N_RBG; i++) { + if (!ue_sched_ctrl->rballoc_sub_UE[CC_id][i]) + continue; + for (int j = 0; j < RBGsize; j++) { + if (vrb_map[RBGsize*i+j] != 0) { + LOG_I(MAC, "%4d.%d DL scheduler allocation list: %s\n", frame, subframe, t); + LOG_E(MAC, "%4d.%d: UE %d allocated at locked RB %d/RBG %d\n", frame, + subframe, UE_id, RBGsize * i + j, i); + } + vrb_map[RBGsize*i+j] = 1; + } + t[i] = '0' + UE_id; + } + } + if (print) + LOG_D(MAC, "%4d.%d DL scheduler allocation list: %s\n", frame, subframe, t); +} + +void static_ul(module_id_t mod_id, + int CC_id, + frame_t frame, + sub_frame_t subframe, + frame_t sched_frame, + sub_frame_t sched_subframe) { + UE_info_t *UE_info = &RC.mac[mod_id]->UE_info; + const int N_RB_UL = to_prb(RC.mac[mod_id]->common_channels[CC_id].ul_Bandwidth); + COMMON_channels_t *cc = &RC.mac[mod_id]->common_channels[CC_id]; + + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + UE_TEMPLATE *UE_template = &UE_info->UE_template[CC_id][UE_id]; + UE_template->pre_assigned_mcs_ul = 0; + UE_template->pre_allocated_nb_rb_ul = 0; + UE_template->pre_allocated_rb_table_index_ul = -1; + UE_template->pre_first_nb_rb_ul = 0; + UE_template->pre_dci_ul_pdu_idx = -1; + } + + slice_info_t *s = RC.mac[mod_id]->pre_processor_ul.slices; + int max_num_ue; + switch (s->num) { + case 1: + max_num_ue = 4; + break; + case 2: + max_num_ue = 2; + break; + default: + max_num_ue = 1; + break; + } + for (int i = 0; i < s->num; ++i) { + if (s->s[i]->UEs.head < 0) + continue; + int last_rb_blocked = 1; + int n_contig = 0; + contig_rbs_t rbs[2]; // up to two contig RBs for PRACH in between + static_slice_param_t *p = s->s[i]->algo_data; + for (int rb = p->posLow; rb <= p->posHigh && rb < N_RB_UL; ++rb) { + if (cc->vrb_map_UL[rb] == 0 && last_rb_blocked) { + last_rb_blocked = 0; + n_contig++; + AssertFatal(n_contig <= 2, "cannot handle more than two contiguous RB regions\n"); + rbs[n_contig - 1].start = rb; + } + if (cc->vrb_map_UL[rb] == 1 && !last_rb_blocked) { + last_rb_blocked = 1; + rbs[n_contig - 1].length = rb - rbs[n_contig - 1].start; + } + } + if (!last_rb_blocked) + rbs[n_contig - 1].length = p->posHigh - rbs[n_contig - 1].start + 1; + + s->s[i]->ul_algo.run(mod_id, + CC_id, + frame, + subframe, + sched_frame, + sched_subframe, + &s->s[i]->UEs, + max_num_ue, // max_num_ue + n_contig, + rbs, + s->s[i]->ul_algo.data); + } + + // the following block is meant for validation of the pre-processor to check + // whether all UE allocations are non-overlapping and is not necessary for + // scheduling functionality + char t[101] = "__________________________________________________" + "__________________________________________________"; + t[N_RB_UL] = 0; + for (int j = 0; j < N_RB_UL; j++) + if (cc->vrb_map_UL[j] != 0) + t[j] = 'x'; + int print = 0; + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + UE_TEMPLATE *UE_template = &UE_info->UE_template[CC_id][UE_id]; + if (UE_template->pre_allocated_nb_rb_ul == 0) + continue; + + print = 1; + uint8_t harq_pid = subframe2harqpid(&RC.mac[mod_id]->common_channels[CC_id], + sched_frame, sched_subframe); + LOG_D(MAC, "%4d.%d UE%d %d RBs (index %d) at start %d, pre MCS %d %s\n", + frame, + subframe, + UE_id, + UE_template->pre_allocated_nb_rb_ul, + UE_template->pre_allocated_rb_table_index_ul, + UE_template->pre_first_nb_rb_ul, + UE_template->pre_assigned_mcs_ul, + UE_info->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid] > 0 ? "(retx)" : ""); + + for (int i = 0; i < UE_template->pre_allocated_nb_rb_ul; ++i) { + /* only check if this is not a retransmission */ + if (UE_info->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid] == 0 + && cc->vrb_map_UL[UE_template->pre_first_nb_rb_ul + i] == 1) { + + LOG_I(MAC, "%4d.%d UL scheduler allocation list: %s\n", frame, subframe, t); + LOG_E(MAC, + "%4d.%d: UE %d allocated at locked RB %d (is: allocated start " + "%d/length %d)\n", + frame, subframe, UE_id, UE_template->pre_first_nb_rb_ul + i, + UE_template->pre_first_nb_rb_ul, + UE_template->pre_allocated_nb_rb_ul); + } + cc->vrb_map_UL[UE_template->pre_first_nb_rb_ul + i] = 1; + t[UE_template->pre_first_nb_rb_ul + i] = UE_id + '0'; + } + } + if (print) + LOG_D(MAC, + "%4d.%d UL scheduler allocation list: %s\n", + sched_frame, + sched_subframe, + t); +} + +void static_destroy(slice_info_t **si) { + const int n = (*si)->num; + (*si)->num = 0; + for (int i = 0; i < n; ++i) { + slice_t *s = (*si)->s[i]; + if (s->label) + free(s->label); + free(s->algo_data); + free(s); + } + free((*si)->s); + free(*si); +} + +pp_impl_param_t static_dl_init(module_id_t mod_id, int CC_id) { + slice_info_t *si = calloc(1, sizeof(slice_info_t)); + DevAssert(si); + + si->num = 0; + si->s = calloc(MAX_STATIC_SLICES, sizeof(slice_t)); + DevAssert(si->s); + for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) + si->UE_assoc_slice[i] = -1; + + /* insert default slice, all resources */ + static_slice_param_t *dlp = malloc(sizeof(static_slice_param_t)); + dlp->posLow = 0; + dlp->posHigh = to_rbg(RC.mac[mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth) - 1; + default_sched_dl_algo_t *algo = &RC.mac[mod_id]->pre_processor_dl.dl_algo; + DevAssert(0 == addmod_static_slice_dl(si, 0, strdup("default"), algo, dlp)); + const UE_list_t *UE_list = &RC.mac[mod_id]->UE_info.list; + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) + slicing_add_UE(si, UE_id); + + pp_impl_param_t sttc; + sttc.algorithm = STATIC_SLICING; + sttc.add_UE = slicing_add_UE; + sttc.remove_UE = slicing_remove_UE; + sttc.move_UE = slicing_move_UE; + sttc.addmod_slice = addmod_static_slice_dl; + sttc.remove_slice = remove_static_slice; + sttc.dl = static_dl; + // current DL algo becomes default scheduler + sttc.dl_algo = *algo; + sttc.destroy = static_destroy; + sttc.slices = si; + + return sttc; +} + +pp_impl_param_t static_ul_init(module_id_t mod_id, int CC_id) { + slice_info_t *si = calloc(1, sizeof(slice_info_t)); + DevAssert(si); + + si->num = 0; + si->s = calloc(MAX_STATIC_SLICES, sizeof(slice_t)); + DevAssert(si->s); + for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) + si->UE_assoc_slice[i] = -1; + + /* insert default slice, all resources */ + static_slice_param_t *ulp = malloc(sizeof(static_slice_param_t)); + ulp->posLow = 0; + ulp->posHigh = to_prb(RC.mac[mod_id]->common_channels[CC_id].ul_Bandwidth) - 1; + default_sched_ul_algo_t *algo = &RC.mac[mod_id]->pre_processor_ul.ul_algo; + DevAssert(0 == addmod_static_slice_ul(si, 0, strdup("default"), algo, ulp)); + const UE_list_t *UE_list = &RC.mac[mod_id]->UE_info.list; + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) + slicing_add_UE(si, UE_id); + + pp_impl_param_t sttc; + sttc.algorithm = STATIC_SLICING; + sttc.add_UE = slicing_add_UE; + sttc.remove_UE = slicing_remove_UE; + sttc.move_UE = slicing_move_UE; + sttc.addmod_slice = addmod_static_slice_ul; + sttc.remove_slice = remove_static_slice; + sttc.ul = static_ul; + // current DL algo becomes default scheduler + sttc.ul_algo = *algo; + sttc.destroy = static_destroy; + sttc.slices = si; + + return sttc; +} diff --git a/openair2/LAYER2/MAC/slicing/slicing.h b/openair2/LAYER2/MAC/slicing/slicing.h new file mode 100644 index 0000000000..1099b50ea0 --- /dev/null +++ b/openair2/LAYER2/MAC/slicing/slicing.h @@ -0,0 +1,74 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! + * \file slicing.h + * \brief General slice definition and helper parameters + * \author Robert Schmidt + * \date 2020 + * \email robert.schmidt@eurecom.fr + */ + +#ifndef __SLICING_H__ +#define __SLICING_H__ + +#include "openair2/LAYER2/MAC/mac.h" + +typedef struct slice_s { + /// Arbitrary ID + slice_id_t id; + /// Arbitrary label + char *label; + + union { + default_sched_dl_algo_t dl_algo; + default_sched_ul_algo_t ul_algo; + }; + + /// A specific algorithm's implementation parameters + void *algo_data; + /// Internal data that might be kept alongside a slice's params + void *int_data; + + // list of users in this slice + UE_list_t UEs; +} slice_t; + +typedef struct slice_info_s { + uint8_t num; + slice_t **s; + uint8_t UE_assoc_slice[MAX_MOBILES_PER_ENB]; +} slice_info_t; + +int slicing_get_UE_slice_idx(slice_info_t *si, int UE_id); + +#define STATIC_SLICING 10 +/* only four static slices for UL, DL resp. (not enough DCIs) */ +#define MAX_STATIC_SLICES 4 +typedef struct { + uint16_t posLow; + uint16_t posHigh; +} static_slice_param_t; +pp_impl_param_t static_dl_init(module_id_t mod_id, int CC_id); +pp_impl_param_t static_ul_init(module_id_t mod_id, int CC_id); + + +#endif /* __SLICING_H__ */ diff --git a/openair2/LAYER2/MAC/slicing/slicing_internal.h b/openair2/LAYER2/MAC/slicing/slicing_internal.h new file mode 100644 index 0000000000..744f8924d9 --- /dev/null +++ b/openair2/LAYER2/MAC/slicing/slicing_internal.h @@ -0,0 +1,46 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! + * \file slicing_internal.h + * \brief Internal slice helper functions + * \author Robert Schmidt + * \date 2020 + * \email robert.schmidt@eurecom.fr + */ + +#ifndef __SLICING_INTERNAL_H__ +#define __SLICING_INTERNAL_H__ + +#include "slicing.h" + +void slicing_add_UE(slice_info_t *si, int UE_id); + +void _remove_UE(slice_t **s, uint8_t *assoc, int UE_id); +void slicing_remove_UE(slice_info_t *si, int UE_id); + +void _move_UE(slice_t **s, uint8_t *assoc, int UE_id, int to); +void slicing_move_UE(slice_info_t *si, int UE_id, int idx); + +slice_t *_add_slice(uint8_t *n, slice_t **s); +slice_t *_remove_slice(uint8_t *n, slice_t **s, uint8_t *assoc, int idx); + +#endif /* __SLICING_INTERNAL_H__ */ From d926a9a9c818e01fff34e3b96e0611929325faca Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 18 Jun 2020 19:12:15 +0200 Subject: [PATCH 27/66] FlexRAN: New protobuf slice structure + Static Slice handling --- .../CONTROL_MODULES/MAC/flexran_agent_mac.c | 139 ++++++--- .../CONTROL_MODULES/MAC/flexran_agent_mac.h | 13 +- .../MAC/flexran_agent_mac_internal.c | 202 ++++++++++--- .../MAC/flexran_agent_mac_internal.h | 20 +- .../ENB_APP/MESSAGES/V2/config_common.proto | 25 ++ .../ENB_APP/MESSAGES/V2/config_messages.proto | 2 + openair2/ENB_APP/flexran_agent_common.c | 12 +- openair2/ENB_APP/flexran_agent_ran_api.c | 277 ++++++++++++++++-- openair2/ENB_APP/flexran_agent_ran_api.h | 45 ++- openair2/LAYER2/MAC/main.c | 2 + openair2/LAYER2/MAC/slicing/slicing.c | 21 +- 11 files changed, 614 insertions(+), 144 deletions(-) diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c index 4800fccea9..e5d1c94c95 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c @@ -1452,9 +1452,74 @@ void flexran_agent_fill_mac_cell_config(mid_t mod_id, uint8_t cc_id, conf->si_config->has_sfn = 1; } - /* get a pointer to the config which is maintained in the agent throughout - * its lifetime */ - conf->slice_config = flexran_agent_get_slice_config(mod_id); + conf->slice_config = malloc(sizeof(Protocol__FlexSliceConfig)); + if (conf->slice_config) { + protocol__flex_slice_config__init(conf->slice_config); + Protocol__FlexSliceConfig *sc = conf->slice_config; + + sc->dl = malloc(sizeof(Protocol__FlexSliceDlUlConfig)); + DevAssert(sc->dl); + protocol__flex_slice_dl_ul_config__init(sc->dl); + sc->dl->algorithm = flexran_get_dl_slice_algo(mod_id); + sc->dl->has_algorithm = 1; + sc->dl->n_slices = flexran_get_num_dl_slices(mod_id); + if (sc->dl->n_slices > 0) { + sc->dl->slices = calloc(sc->dl->n_slices, sizeof(Protocol__FlexSlice *)); + DevAssert(sc->dl->slices); + for (int i = 0; i < sc->dl->n_slices; ++i) { + sc->dl->slices[i] = malloc(sizeof(Protocol__FlexSlice)); + DevAssert(sc->dl->slices[i]); + protocol__flex_slice__init(sc->dl->slices[i]); + flexran_get_dl_slice(mod_id, i, sc->dl->slices[i], sc->dl->algorithm); + } + } else { + sc->dl->scheduler = flexran_get_dl_scheduler_name(mod_id); + } + + sc->ul = malloc(sizeof(Protocol__FlexSliceDlUlConfig)); + DevAssert(sc->ul); + protocol__flex_slice_dl_ul_config__init(sc->ul); + sc->ul->algorithm = flexran_get_ul_slice_algo(mod_id); + sc->ul->has_algorithm = 1; + sc->ul->n_slices = flexran_get_num_ul_slices(mod_id); + if (sc->ul->n_slices > 0) { + sc->ul->slices = calloc(sc->ul->n_slices, sizeof(Protocol__FlexSlice *)); + DevAssert(sc->ul->slices); + for (int i = 0; i < sc->ul->n_slices; ++i) { + sc->ul->slices[i] = malloc(sizeof(Protocol__FlexSlice)); + DevAssert(sc->ul->slices[i]); + protocol__flex_slice__init(sc->ul->slices[i]); + flexran_get_ul_slice(mod_id, i, sc->ul->slices[i], sc->ul->algorithm); + } + } else { + sc->ul->scheduler = flexran_get_ul_scheduler_name(mod_id); + } + } +} + +void flexran_agent_destroy_mac_slice_config(Protocol__FlexCellConfig *conf) { + Protocol__FlexSliceConfig *sc = conf->slice_config; + for (int i = 0; i < sc->dl->n_slices; ++i) { + free(sc->dl->slices[i]); + sc->dl->slices[i] = NULL; + /* scheduler names are not freed: we assume we read them directly from the + * underlying memory and do not dispose it */ + } + free(sc->dl->slices); + /* scheduler name is not freed */ + free(sc->dl); + sc->dl = NULL; + for (int i = 0; i < sc->ul->n_slices; ++i) { + free(sc->ul->slices[i]); + sc->ul->slices[i] = NULL; + /* scheduler names are not freed */ + } + free(sc->ul->slices); + /* scheduler name is not freed */ + free(sc->ul); + sc->ul = NULL; + free(conf->slice_config); + conf->slice_config = NULL; } void flexran_agent_fill_mac_ue_config(mid_t mod_id, mid_t ue_id, @@ -1568,46 +1633,46 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id) return 0; } - -void flexran_create_config_structures(mid_t mod_id) -{ - int i; - int n_dl = flexran_get_num_dl_slices(mod_id); - int m_ul = flexran_get_num_ul_slices(mod_id); - slice_config[mod_id] = flexran_agent_create_slice_config(n_dl, m_ul); - sc_update[mod_id] = flexran_agent_create_slice_config(n_dl, m_ul); - if (!slice_config[mod_id] || !sc_update[mod_id]) return; - - //flexran_agent_read_slice_config(mod_id, slice_config[mod_id]); - //flexran_agent_read_slice_config(mod_id, sc_update[mod_id]); - for (i = 0; i < n_dl; i++) { - //flexran_agent_read_slice_dl_config(mod_id, i, slice_config[mod_id]->dl[i]); - //flexran_agent_read_slice_dl_config(mod_id, i, sc_update[mod_id]->dl[i]); +void helper_destroy_mac_slice_config(Protocol__FlexSliceConfig *slice_config) { + if (slice_config->dl) { + if (slice_config->dl->scheduler) + free(slice_config->dl->scheduler); + for (int i = 0; i < slice_config->dl->n_slices; i++) + if (slice_config->dl->slices[i]->scheduler) + free(slice_config->dl->slices[i]->scheduler); } - for (i = 0; i < m_ul; i++) { - //flexran_agent_read_slice_ul_config(mod_id, i, slice_config[mod_id]->ul[i]); - //flexran_agent_read_slice_ul_config(mod_id, i, sc_update[mod_id]->ul[i]); + if (slice_config->ul) { + if (slice_config->ul->scheduler) + free(slice_config->ul->scheduler); + for (int i = 0; i < slice_config->ul->n_slices; i++) + if (slice_config->ul->slices[i]->scheduler) + free(slice_config->ul->slices[i]->scheduler); } + + Protocol__FlexCellConfig helper; + helper.slice_config = slice_config; + flexran_agent_destroy_mac_slice_config(&helper); } -void flexran_check_and_remove_slices(mid_t mod_id) -{ +void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig **slice_config) { + if (!*slice_config) return; + Protocol__FlexSliceConfig *sc = *slice_config; + *slice_config = NULL; + + /* TODO handle using lock-free queue */ + apply_update_dl_slice_config(mod_id, sc->dl); + apply_update_ul_slice_config(mod_id, sc->ul); + + helper_destroy_mac_slice_config(*slice_config); } -void flexran_agent_slice_update(mid_t mod_id) -{ +void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig **ue_config) { + /* TODO handle using lock-free queue */ + apply_ue_slice_assoc_update(mod_id, *ue_config); + + free(*ue_config); + *ue_config = NULL; } -Protocol__FlexSliceConfig *flexran_agent_get_slice_config(mid_t mod_id) -{ - if (!slice_config[mod_id]) return NULL; - Protocol__FlexSliceConfig *config = NULL; - - pthread_mutex_lock(&sc_update_mtx); - if (!config) { - pthread_mutex_unlock(&sc_update_mtx); - return NULL; - } - pthread_mutex_unlock(&sc_update_mtx); - return config; +void flexran_agent_slice_update(mid_t mod_id) { } diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h index 2f9f99c740..5a8d4f31aa 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h @@ -115,7 +115,16 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id); /* Inform controller about possibility to update slice configuration */ void flexran_agent_slice_update(mid_t mod_id); -/* return a pointer to the current config */ -Protocol__FlexSliceConfig *flexran_agent_get_slice_config(mid_t mod_id); +/* marks slice_config so that it can be applied later. Takes ownership of the + * FlexSliceConfig message */ +void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig **slice); + +/* inserts a new ue_config into the structure keeping ue to slice association + * updates and marks so it can be applied. Takes ownership of the FlexUeConfig message */ +void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig **ue_config); + +/* free slice_config part of flexCellConfig, filled in + * flexran_agent_fill_mac_cell_config() */ +void flexran_agent_destroy_mac_slice_config(Protocol__FlexCellConfig *conf); #endif diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c index 4c80c561ee..93de0b11ec 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c @@ -1025,60 +1025,166 @@ int load_dl_scheduler_function(mid_t mod_id, const char *function_name) { } -Protocol__FlexSliceConfig *flexran_agent_create_slice_config(int n_dl, int m_ul) -{ - Protocol__FlexSliceConfig *fsc = malloc(sizeof(Protocol__FlexSliceConfig)); - if (!fsc) return NULL; - protocol__flex_slice_config__init(fsc); - - /* TODO */ - return fsc; -} - -void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *sup) -{ -} - - -void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config) -{ - if (n_ue_slice_assoc_updates == 10) { - LOG_E(FLEXRAN_AGENT, - "[%d] can not handle flex_ue_config message, buffer is full; try again later\n", - mod_id); - return; +void update_or_remove_dl(mid_t mod_id, Protocol__FlexSlice *s) { + if (s->params_case == PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET + && !s->label && !s->scheduler) { + LOG_I(FLEXRAN_AGENT, "remove DL slice ID %d\n", s->id); + const int rc = flexran_remove_dl_slice(mod_id, s); + if (!rc) + LOG_W(FLEXRAN_AGENT, "error while removing slice ID %d\n", s->id); + } else { + LOG_I(FLEXRAN_AGENT, "updating DL slice ID %d\n", s->id); + const int rc = flexran_create_dl_slice(mod_id, s); + if (rc < 0) + LOG_W(FLEXRAN_AGENT, + "error while update slice ID %d: flexran_create_dl_slice() -> %d\n", + s->id, rc); } +} + +void update_or_remove_ul(mid_t mod_id, Protocol__FlexSlice *s) { + if (s->params_case == PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET + && !s->label && !s->scheduler) { + LOG_I(FLEXRAN_AGENT, "remove UL slice ID %d\n", s->id); + const int rc = flexran_remove_ul_slice(mod_id, s); + if (!rc) + LOG_W(FLEXRAN_AGENT, "error while removing slice ID %d\n", s->id); + } else { + LOG_I(FLEXRAN_AGENT, "updating UL slice ID %d\n", s->id); + const int rc = flexran_create_ul_slice(mod_id, s); + if (rc < 0) + LOG_W(FLEXRAN_AGENT, + "error while updating slice ID %d: flexran_create_ul_slice() -> %d)\n", + s->id, rc); + } +} + +void apply_update_dl_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *dl) { + if (!dl) + return; + + Protocol__FlexSliceAlgorithm dl_algo = flexran_get_dl_slice_algo(mod_id); + if (dl->has_algorithm && dl_algo != dl->algorithm) { + LOG_I(FLEXRAN_AGENT, "loading new DL slice algorithm %d\n", dl->algorithm); + dl_algo = dl->algorithm; + flexran_set_dl_slice_algo(mod_id, dl_algo); + } + + /* first update existing slices, then create new. Thus, we go through the + * list twice. First round, if a slice exists, handle and mark as such. Then, + * apply all others in the second round */ + if (dl->n_slices > 0) { + if (dl_algo == PROTOCOL__FLEX_SLICE_ALGORITHM__None) { + LOG_E(FLEXRAN_AGENT, "cannot update slices: no algorithm loaded\n"); + return; + } + int handled_dl[dl->n_slices]; + for (int i = 0; i < dl->n_slices; ++i) { + if (flexran_find_dl_slice(mod_id, dl->slices[i]->id) < 0) { + handled_dl[i] = 0; + continue; + } + update_or_remove_dl(mod_id, dl->slices[i]); + handled_dl[i] = 1; + } + for (int i = 0; i < dl->n_slices; ++i) { + if (handled_dl[i]) + continue; + update_or_remove_dl(mod_id, dl->slices[i]); + } + } + + if (dl->scheduler) { + if (dl_algo != PROTOCOL__FLEX_SLICE_ALGORITHM__None) { + LOG_E(FLEXRAN_AGENT, "cannot update scheduling algorithm: slice algorithm loaded\n"); + return; + } + LOG_I(FLEXRAN_AGENT, "loading DL new scheduling algorithm '%s'\n", dl->scheduler); + const int rc = flexran_set_dl_scheduler(mod_id, dl->scheduler); + if (rc < 0) { + LOG_E(FLEXRAN_AGENT, + "error while updating scheduling algorithm: " + "flexran_update_dl_sched_algo() -> %d)\n", + rc); + return; + } + } +} + +void apply_update_ul_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *ul) { + if (!ul) + return; + + Protocol__FlexSliceAlgorithm ul_algo = flexran_get_ul_slice_algo(mod_id); + if (ul->has_algorithm && ul_algo != ul->algorithm) { + LOG_I(FLEXRAN_AGENT, "loading new UL slice algorithm %d\n", ul->algorithm); + ul_algo = ul->algorithm; + flexran_set_ul_slice_algo(mod_id, ul_algo); + } + if (ul->n_slices > 0) { + if (ul_algo == PROTOCOL__FLEX_SLICE_ALGORITHM__None) { + LOG_E(FLEXRAN_AGENT, "cannot update slices: no algorithm loaded\n"); + return; + } + int handled_ul[ul->n_slices]; + for (int i = 0; i < ul->n_slices; ++i) { + if (flexran_find_ul_slice(mod_id, ul->slices[i]->id) < 0) { + handled_ul[i] = 0; + continue; + } + update_or_remove_ul(mod_id, ul->slices[i]); + handled_ul[i] = 1; + } + for (int i = 0; i < ul->n_slices; ++i) { + if (handled_ul[i]) + continue; + update_or_remove_ul(mod_id, ul->slices[i]); + } + } + + if (ul->scheduler) { + if (ul_algo != PROTOCOL__FLEX_SLICE_ALGORITHM__None) { + LOG_E(FLEXRAN_AGENT, "cannot update scheduling algorithm: slice algorithm loaded\n"); + return; + } + LOG_I(FLEXRAN_AGENT, "loading new UL scheduling algorithm '%s'\n", ul->scheduler); + const int rc = flexran_set_ul_scheduler(mod_id, ul->scheduler); + if (rc < 0) { + LOG_E(FLEXRAN_AGENT, + "error while updating scheduling algorithm: " + "flexran_update_dl_sched_algo() -> %d)\n", + rc); + return; + } + } +} + +int apply_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config) +{ if (!ue_config->has_rnti) { LOG_E(FLEXRAN_AGENT, "[%d] cannot update UE to slice association, no RNTI in flex_ue_config message\n", mod_id); - return; + return 0; } - if (ue_config->has_dl_slice_id) - LOG_I(FLEXRAN_AGENT, "[%d] associating UE RNTI %#x to DL slice ID %d\n", - mod_id, ue_config->rnti, ue_config->dl_slice_id); - if (ue_config->has_ul_slice_id) - LOG_I(FLEXRAN_AGENT, "[%d] associating UE RNTI %#x to UL slice ID %d\n", - mod_id, ue_config->rnti, ue_config->ul_slice_id); - ue_slice_assoc_update[n_ue_slice_assoc_updates++] = ue_config; - perform_slice_config_update_count = 2; -} - -int apply_ue_slice_assoc_update(mid_t mod_id) -{ - int i; - int changes = 0; - for (i = 0; i < n_ue_slice_assoc_updates; i++) { - int ue_id = find_UE_id(mod_id, ue_slice_assoc_update[i]->rnti); - if (ue_id < 0 || ue_id > MAX_MOBILES_PER_ENB){ - LOG_E(FLEXRAN_AGENT,"UE_id %d is wrong!!\n",ue_id); - continue; - } - if (ue_slice_assoc_update[i]->has_dl_slice_id) { - } - if (ue_slice_assoc_update[i]->has_ul_slice_id) { + int UE_id = flexran_get_mac_ue_id_rnti(mod_id, ue_config->rnti); + if (ue_config->has_dl_slice_id) { + if (flexran_get_dl_slice_algo(mod_id) == PROTOCOL__FLEX_SLICE_ALGORITHM__None) { + LOG_E(FLEXRAN_AGENT, "no DL slice algorithm loaded\n"); + } else { + LOG_I(FLEXRAN_AGENT, "[%d] associating UE RNTI %04x - %d/UE %d to DL slice ID %d\n", + mod_id, ue_config->rnti, ue_config->rnti, UE_id, ue_config->dl_slice_id); + flexran_set_ue_dl_slice_id(mod_id, UE_id, ue_config->dl_slice_id); } } - n_ue_slice_assoc_updates = 0; - return changes; + if (ue_config->has_ul_slice_id) { + if (flexran_get_ul_slice_algo(mod_id) == PROTOCOL__FLEX_SLICE_ALGORITHM__None) { + LOG_E(FLEXRAN_AGENT, "no UL slice algorithm loaded\n"); + } else { + LOG_I(FLEXRAN_AGENT, "[%d] associating UE RNTI %04x - %d/UE %d to UL slice ID %d\n", + mod_id, ue_config->rnti, ue_config->rnti, UE_id, ue_config->ul_slice_id); + flexran_set_ue_ul_slice_id(mod_id, UE_id, ue_config->ul_slice_id); + } + } + return 0; } diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h index ef2a7e40a9..9db5d61a11 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h @@ -103,23 +103,11 @@ int load_dl_scheduler_function(mid_t mod_id, const char *function_name); /*** Functions for handling a slice config ***/ -/* allocate memory for a Protocol__FlexSliceConfig structure with n_dl DL slice - * configs and m_ul UL slice configs */ -Protocol__FlexSliceConfig *flexran_agent_create_slice_config(int n_dl, int m_ul); - -/* read the general slice parameters via RAN into the given - * Protocol__FlexSliceConfig struct */ -void flexran_agent_read_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *s); - -/* reads content of slice over the sc_update structure, so that it can be - * applied later by performing a diff between slice_config and sc_update */ -void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *slice); - -/* inserts a new ue_config into the structure keeping ue to slice association - * updates and marks so it can be applied */ -void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config); +/* Prepare the application of a slicing config */ +void apply_update_dl_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *slice); +void apply_update_ul_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *slice); /* apply a new association between a UE and a slice (both DL and UL) */ -int apply_ue_slice_assoc_update(mid_t mod_id); +int apply_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config); #endif /*FLEXRAN_AGENT_MAC_INTERNAL_H_*/ diff --git a/openair2/ENB_APP/MESSAGES/V2/config_common.proto b/openair2/ENB_APP/MESSAGES/V2/config_common.proto index e5d01ebdc0..2f2267b628 100644 --- a/openair2/ENB_APP/MESSAGES/V2/config_common.proto +++ b/openair2/ENB_APP/MESSAGES/V2/config_common.proto @@ -61,6 +61,31 @@ enum flex_qam { // // Slice config related structures and enums // +enum flex_slice_algorithm { + None = 0; + Static = 1; + NVS = 2; +} + +message flex_slice_static { + optional uint32 posLow = 1; + optional uint32 posHigh = 2; +} + +message flex_slice { + optional uint32 id = 1; + optional string label = 2; + optional string scheduler = 3; + oneof params { + flex_slice_static static = 10; + } +} + +message flex_slice_dl_ul_config { + optional flex_slice_algorithm algorithm = 1; + repeated flex_slice slices = 2; + optional string scheduler = 3; // if no slicing +} // // UE config related structures and enums diff --git a/openair2/ENB_APP/MESSAGES/V2/config_messages.proto b/openair2/ENB_APP/MESSAGES/V2/config_messages.proto index 1a66a4f20f..1a69deec71 100644 --- a/openair2/ENB_APP/MESSAGES/V2/config_messages.proto +++ b/openair2/ENB_APP/MESSAGES/V2/config_messages.proto @@ -49,6 +49,8 @@ message flex_cell_config { } message flex_slice_config { + optional flex_slice_dl_ul_config dl = 6; + optional flex_slice_dl_ul_config ul = 7; } message flex_ue_config { diff --git a/openair2/ENB_APP/flexran_agent_common.c b/openair2/ENB_APP/flexran_agent_common.c index 3dd9f5b957..7569ca1ac1 100644 --- a/openair2/ENB_APP/flexran_agent_common.c +++ b/openair2/ENB_APP/flexran_agent_common.c @@ -306,6 +306,7 @@ int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg) { if (reply->cell_config[i]->mbsfn_subframe_config_sfalloc) free(reply->cell_config[i]->mbsfn_subframe_config_sfalloc); + /* si_config is shared between MAC and RRC, free here */ if (reply->cell_config[i]->si_config) { for(int j = 0; j < reply->cell_config[i]->si_config->n_si_message; j++) { free(reply->cell_config[i]->si_config->si_message[j]); @@ -316,8 +317,7 @@ int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg) { } if (reply->cell_config[i]->slice_config) { - /* TODO */ - free(reply->cell_config[i]->slice_config); + flexran_agent_destroy_mac_slice_config(reply->cell_config[i]); } free(reply->cell_config[i]); @@ -880,7 +880,7 @@ int flexran_agent_handle_enb_config_reply(mid_t mod_id, const void *params, Prot if (enb_config->n_cell_config > 0) { if (flexran_agent_get_mac_xface(mod_id) && enb_config->cell_config[0]->slice_config) { - prepare_update_slice_config(mod_id, enb_config->cell_config[0]->slice_config); + prepare_update_slice_config(mod_id, &enb_config->cell_config[0]->slice_config); } if (enb_config->cell_config[0]->has_eutra_band && enb_config->cell_config[0]->has_dl_freq @@ -921,7 +921,11 @@ int flexran_agent_handle_ue_config_reply(mid_t mod_id, const void *params, Proto Protocol__FlexUeConfigReply *ue_config_reply = input->ue_config_reply_msg; for (i = 0; flexran_agent_get_mac_xface(mod_id) && i < ue_config_reply->n_ue_config; i++) - prepare_ue_slice_assoc_update(mod_id, ue_config_reply->ue_config[i]); + prepare_ue_slice_assoc_update(mod_id, &ue_config_reply->ue_config[i]); + /* prepare_ue_slice_assoc_update takes ownership of the individual + * FlexUeConfig messages. Therefore, mark zero messages to not accidentally + * free them twice */ + ue_config_reply->n_ue_config = 0; *msg = NULL; return 0; diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index cd8b0b8f67..79c992a4d7 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -30,6 +30,7 @@ #include "flexran_agent_ran_api.h" #include "s1ap_eNB_ue_context.h" #include "s1ap_eNB_management_procedures.h" +#include "openair2/LAYER2/MAC/slicing/slicing.h" static inline int phy_is_present(mid_t mod_id, uint8_t cc_id) { return RC.eNB && RC.eNB[mod_id] && RC.eNB[mod_id][cc_id]; @@ -3013,66 +3014,294 @@ uint32_t flexran_get_rrc_enb_ue_s1ap_id(mid_t mod_id, rnti_t rnti) } /**************************** SLICING ****************************/ +Protocol__FlexSliceAlgorithm flexran_get_dl_slice_algo(mid_t mod_id) { + if (!mac_is_present(mod_id)) return PROTOCOL__FLEX_SLICE_ALGORITHM__None; + + switch (RC.mac[mod_id]->pre_processor_dl.algorithm) { + case STATIC_SLICING: + return PROTOCOL__FLEX_SLICE_ALGORITHM__Static; + default: + return PROTOCOL__FLEX_SLICE_ALGORITHM__None; + } +} + +int flexran_set_dl_slice_algo(mid_t mod_id, Protocol__FlexSliceAlgorithm algo) { + if (!mac_is_present(mod_id)) return 0; + eNB_MAC_INST *mac = RC.mac[mod_id]; + const int cc_id = 0; + + pp_impl_param_t dl = mac->pre_processor_dl; + switch (algo) { + case PROTOCOL__FLEX_SLICE_ALGORITHM__Static: + mac->pre_processor_dl = static_dl_init(mod_id, cc_id); + break; + default: + mac->pre_processor_dl.algorithm = 0; + mac->pre_processor_dl.dl = dlsch_scheduler_pre_processor; + mac->pre_processor_dl.dl_algo.data = mac->pre_processor_dl.dl_algo.setup(); + mac->pre_processor_dl.slices = NULL; + break; + } + if (dl.slices) + dl.destroy(&dl.slices); + if (dl.dl_algo.data) + dl.dl_algo.unset(&dl.dl_algo.data); + return 1; +} + +Protocol__FlexSliceAlgorithm flexran_get_ul_slice_algo(mid_t mod_id) { + if (!mac_is_present(mod_id)) return PROTOCOL__FLEX_SLICE_ALGORITHM__None; + + switch (RC.mac[mod_id]->pre_processor_ul.algorithm) { + case STATIC_SLICING: + return PROTOCOL__FLEX_SLICE_ALGORITHM__Static; + default: + return PROTOCOL__FLEX_SLICE_ALGORITHM__None; + } +} + +int flexran_set_ul_slice_algo(mid_t mod_id, Protocol__FlexSliceAlgorithm algo) { + if (!mac_is_present(mod_id)) return 0; + eNB_MAC_INST *mac = RC.mac[mod_id]; + const int cc_id = 0; + + pp_impl_param_t ul = mac->pre_processor_ul; + switch (algo) { + case PROTOCOL__FLEX_SLICE_ALGORITHM__Static: + mac->pre_processor_ul = static_ul_init(mod_id, cc_id); + break; + default: + mac->pre_processor_ul.algorithm = 0; + mac->pre_processor_ul.ul = ulsch_scheduler_pre_processor; + mac->pre_processor_ul.ul_algo.data = mac->pre_processor_ul.ul_algo.setup(); + mac->pre_processor_ul.slices = NULL; + break; + } + if (ul.slices) + ul.destroy(&ul.slices); + if (ul.ul_algo.data) + ul.ul_algo.unset(&ul.ul_algo.data); + return 1; +} + int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return -1; - return 0; + slice_info_t *slices = RC.mac[mod_id]->pre_processor_dl.slices; + if (!slices) return -1; + const int idx = slices->UE_assoc_slice[ue_id]; + return slices->s[idx]->id; +} + +void flexran_set_ue_dl_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) { + if (!mac_is_present(mod_id)) return; + int idx = flexran_find_dl_slice(mod_id, slice_id); + if (idx < 0) return; + pp_impl_param_t *dl = &RC.mac[mod_id]->pre_processor_dl; + dl->move_UE(dl->slices, ue_id, idx); } int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return -1; - return 0; + slice_info_t *slices = RC.mac[mod_id]->pre_processor_ul.slices; + if (!slices) return -1; + const int idx = slices->UE_assoc_slice[ue_id]; + return slices->s[idx]->id; } -/* TODO */ -int flexran_create_dl_slice(mid_t mod_id, slice_id_t slice_id) { - if (!mac_is_present(mod_id)) return -1; - return -1; +void flexran_set_ue_ul_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) { + if (!mac_is_present(mod_id)) return; + int idx = flexran_find_ul_slice(mod_id, slice_id); + if (idx < 0) return; + pp_impl_param_t *ul = &RC.mac[mod_id]->pre_processor_ul; + ul->move_UE(ul->slices, ue_id, idx); } -/* TODO */ -int flexran_remove_dl_slice(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; +int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s) { + if (!mac_is_present(mod_id)) return 0; + void *params = NULL; + switch (s->params_case) { + case PROTOCOL__FLEX_SLICE__PARAMS_STATIC: + params = malloc(sizeof(static_slice_param_t)); + if (!params) return 0; + ((static_slice_param_t *)params)->posLow = s->static_->poslow; + ((static_slice_param_t *)params)->posHigh = s->static_->poshigh; + break; + default: + break; + } + pp_impl_param_t *dl = &RC.mac[mod_id]->pre_processor_dl; + char *l = s->label ? strdup(s->label) : NULL; + void *algo = &dl->dl_algo; // default scheduler + if (s->scheduler) { + algo = dlsym(NULL, s->scheduler); + if (!algo) { + free(params); + LOG_E(FLEXRAN_AGENT, "cannot locate scheduler '%s'\n", s->scheduler); + return -15; + } + } + return dl->addmod_slice(dl->slices, s->id, l, algo, params); +} + +int flexran_remove_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s) { + if (!mac_is_present(mod_id)) return 0; + const int idx = flexran_find_dl_slice(mod_id, s->id); + if (idx < 0) return 0; + pp_impl_param_t *dl = &RC.mac[mod_id]->pre_processor_dl; + return dl->remove_slice(dl->slices, idx); } int flexran_find_dl_slice(mid_t mod_id, slice_id_t slice_id) { if (!mac_is_present(mod_id)) return -1; + slice_info_t *si = RC.mac[mod_id]->pre_processor_dl.slices; + for (int i = 0; i < si->num; ++i) + if (si->s[i]->id == slice_id) + return i; return -1; } -//int flexran_get_dl_slice(mid_t mod_id, int slice_idx, Protocol__FlexSlice *s) { -//} +void flexran_get_dl_slice(mid_t mod_id, + int slice_idx, + Protocol__FlexSlice *slice, + Protocol__FlexSliceAlgorithm algo) { + if (!mac_is_present(mod_id)) return; + slice_t *s_ = RC.mac[mod_id]->pre_processor_dl.slices->s[slice_idx]; + slice->has_id = 1; + slice->id = s_->id; + slice->label = s_->label; + slice->scheduler = s_->dl_algo.name; + slice->params_case = PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET; + switch (algo) { + case PROTOCOL__FLEX_SLICE_ALGORITHM__Static: + slice->static_ = malloc(sizeof(Protocol__FlexSliceStatic)); + if (!slice->static_) return; + protocol__flex_slice_static__init(slice->static_); + slice->static_->has_poslow = 1; + slice->static_->poslow = ((static_slice_param_t *)s_->algo_data)->posLow; + slice->static_->has_poshigh = 1; + slice->static_->poshigh = ((static_slice_param_t *)s_->algo_data)->posHigh; + slice->params_case = PROTOCOL__FLEX_SLICE__PARAMS_STATIC; + break; + default: + break; + } +} int flexran_get_num_dl_slices(mid_t mod_id) { - if (!mac_is_present(mod_id)) return -1; - return 0; + if (!mac_is_present(mod_id)) return 0; + if (!RC.mac[mod_id]->pre_processor_dl.slices) return 0; + return RC.mac[mod_id]->pre_processor_dl.slices->num; } -/* TODO */ -void flexran_create_ul_slice(mid_t mod_id, slice_id_t slice_id) { - if (!mac_is_present(mod_id)) return; - return; +int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s) { + if (!mac_is_present(mod_id)) return -1; + void *params = NULL; + switch (s->params_case) { + case PROTOCOL__FLEX_SLICE__PARAMS_STATIC: + params = malloc(sizeof(static_slice_param_t)); + if (!params) return 0; + ((static_slice_param_t *)params)->posLow = s->static_->poslow; + ((static_slice_param_t *)params)->posHigh = s->static_->poshigh; + break; + default: + break; + } + pp_impl_param_t *ul = &RC.mac[mod_id]->pre_processor_ul; + char *l = s->label ? strdup(s->label) : NULL; + void *algo = &ul->ul_algo; // default scheduler + if (s->scheduler) { + algo = dlsym(NULL, s->scheduler); + if (!algo) { + free(params); + LOG_E(FLEXRAN_AGENT, "cannot locate scheduler '%s'\n", s->scheduler); + return -15; + } + } + return ul->addmod_slice(ul->slices, s->id, l, algo, params); } -/* TODO */ -int flexran_remove_ul_slice(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; +int flexran_remove_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s) { + if (!mac_is_present(mod_id)) return 0; + const int idx = flexran_find_ul_slice(mod_id, s->id); + if (idx < 0) return 0; + pp_impl_param_t *ul = &RC.mac[mod_id]->pre_processor_ul; + return ul->remove_slice(ul->slices, idx); } int flexran_find_ul_slice(mid_t mod_id, slice_id_t slice_id) { if (!mac_is_present(mod_id)) return -1; + slice_info_t *si = RC.mac[mod_id]->pre_processor_ul.slices; + for (int i = 0; i < si->num; ++i) + if (si->s[i]->id == slice_id) + return i; return -1; } -//int flexran_get_ul_slice(mid_t mod_id, int slice_idx, Protocol__FlexSlice *s) { -//} +void flexran_get_ul_slice(mid_t mod_id, + int slice_idx, + Protocol__FlexSlice *slice, + Protocol__FlexSliceAlgorithm algo) { + if (!mac_is_present(mod_id)) return; + slice_t *s_ = RC.mac[mod_id]->pre_processor_ul.slices->s[slice_idx]; + slice->has_id = 1; + slice->id = s_->id; + slice->label = s_->label; + slice->scheduler = s_->ul_algo.name; + slice->params_case = PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET; + switch (algo) { + case PROTOCOL__FLEX_SLICE_ALGORITHM__Static: + slice->static_ = malloc(sizeof(Protocol__FlexSliceStatic)); + if (!slice->static_) return; + protocol__flex_slice_static__init(slice->static_); + slice->static_->has_poslow = 1; + slice->static_->poslow = ((static_slice_param_t *)s_->algo_data)->posLow; + slice->static_->has_poshigh = 1; + slice->static_->poshigh = ((static_slice_param_t *)s_->algo_data)->posHigh; + slice->params_case = PROTOCOL__FLEX_SLICE__PARAMS_STATIC; + break; + default: + break; + } + +} int flexran_get_num_ul_slices(mid_t mod_id) { + if (!mac_is_present(mod_id)) return 0; + if (!RC.mac[mod_id]->pre_processor_ul.slices) return 0; + return RC.mac[mod_id]->pre_processor_ul.slices->num; +} + +char *flexran_get_dl_scheduler_name(mid_t mod_id) { + if (!mac_is_present(mod_id)) return NULL; + return RC.mac[mod_id]->pre_processor_dl.dl_algo.name; +} + +int flexran_set_dl_scheduler(mid_t mod_id, char *sched) { if (!mac_is_present(mod_id)) return -1; + void *d = dlsym(NULL, sched); + if (!d) return -2; + pp_impl_param_t *dl_pp = &RC.mac[mod_id]->pre_processor_dl; + dl_pp->dl_algo.unset(&dl_pp->dl_algo.data); + dl_pp->dl_algo = *(default_sched_dl_algo_t *) d; + dl_pp->dl_algo.data = dl_pp->dl_algo.setup(); return 0; } +char *flexran_get_ul_scheduler_name(mid_t mod_id) { + if (!mac_is_present(mod_id)) return NULL; + return RC.mac[mod_id]->pre_processor_ul.ul_algo.name; +} + +int flexran_set_ul_scheduler(mid_t mod_id, char *sched) { + if (!mac_is_present(mod_id)) return -1; + void *d = dlsym(NULL, sched); + if (!d) return -2; + pp_impl_param_t *ul_pp = &RC.mac[mod_id]->pre_processor_ul; + ul_pp->ul_algo.unset(&ul_pp->ul_algo.data); + ul_pp->ul_algo = *(default_sched_ul_algo_t *) d; + ul_pp->ul_algo.data = ul_pp->ul_algo.setup(); + return 0; +} /************************** S1AP **************************/ int flexran_get_s1ap_mme_pending(mid_t mod_id){ diff --git a/openair2/ENB_APP/flexran_agent_ran_api.h b/openair2/ENB_APP/flexran_agent_ran_api.h index c29ba53c11..2d8a86f7d0 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.h +++ b/openair2/ENB_APP/flexran_agent_ran_api.h @@ -656,41 +656,66 @@ int flexran_agent_rrc_gtp_get_teid_sgw(mid_t mod_id, rnti_t rnti, int index); uint32_t flexran_get_rrc_enb_ue_s1ap_id(mid_t mod_id, rnti_t rnti); /************************** Slice configuration **************************/ +/* Get the currently active DL slicing algorithm */ +Protocol__FlexSliceAlgorithm flexran_get_dl_slice_algo(mid_t mod_id); +/* Set the active DL slicing algorithm */ +int flexran_set_dl_slice_algo(mid_t mod_id, Protocol__FlexSliceAlgorithm algo); + +/* Get the currently active UL slicing algorithm */ +Protocol__FlexSliceAlgorithm flexran_get_ul_slice_algo(mid_t mod_id); +/* Set the active UL slicing algorithm */ +int flexran_set_ul_slice_algo(mid_t mod_id, Protocol__FlexSliceAlgorithm algo); /* Get the DL slice ID for a UE */ int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id); -/* Set the DL slice index(!) for a UE */ -//void flexran_set_ue_dl_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx); +/* Set the DL slice for a UE */ +void flexran_set_ue_dl_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id); /* Get the UL slice ID for a UE */ int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id); -/* Set the UL slice index(!) for a UE */ -//void flexran_set_ue_ul_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx); +/* Set the UL slice for a UE */ +void flexran_set_ue_ul_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id); /* Create slice in DL, returns the new slice index */ -//int flexran_create_dl_slice(mid_t mod_id, slice_id_t slice_id); +int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s); /* Remove slice in DL, returns new number of slices or -1 on error */ -//int flexran_remove_dl_slice(mid_t mod_id, int slice_idx); +int flexran_remove_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s); /* Finds slice in DL with given slice_id and returns slice index */ int flexran_find_dl_slice(mid_t mod_id, slice_id_t slice_id); /* Return the parameters of slice at index slice_idx */ -//void flexran_get_dl_slice(mid_t mod_id, int slice_idx, Protocol__FlexSlice *s); +void flexran_get_dl_slice(mid_t mod_id, + int slice_idx, + Protocol__FlexSlice *slice, + Protocol__FlexSliceAlgorithm algo); /* Get the number of slices in DL */ int flexran_get_num_dl_slices(mid_t mod_id); /* Create slice in UL, returns the new slice index */ -//int flexran_create_ul_slice(mid_t mod_id, slice_id_t slice_id); +int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s); /* Remove slice in UL */ -//int flexran_remove_ul_slice(mid_t mod_id, int slice_idx); +int flexran_remove_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s); /* Finds slice in DL with given slice_id and returns slice index */ int flexran_find_ul_slice(mid_t mod_id, slice_id_t slice_id); /* Return the parameters of slice at index slice_idx */ -//void flexran_get_ul_slice(mid_t mod_id, int slice_idx, Protocol__FlexSlice *s); +void flexran_get_ul_slice(mid_t mod_id, + int slice_idx, + Protocol__FlexSlice *slice, + Protocol__FlexSliceAlgorithm algo); /* Get the number of slices in UL */ int flexran_get_num_ul_slices(mid_t mod_id); +/* Get the name of/Set the DL scheduling algorithm. If slicing is active, this + * corresponds to the default algorithm for slices, otherwise the currently + * used one. */ +char *flexran_get_dl_scheduler_name(mid_t mod_id); +int flexran_set_dl_scheduler(mid_t mod_id, char *sched); + +/* Get the name of/Set the UL scheduler algorithm. Same applies as for the DL + * case */ +char *flexran_get_ul_scheduler_name(mid_t mod_id); +int flexran_set_ul_scheduler(mid_t mod_id, char *sched); /************************** S1AP **************************/ /* Get the number of MMEs to be connected */ diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index 24038e60d5..af6d1a7ac3 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -100,6 +100,7 @@ void mac_top_init_eNB(void) mac[i]->if_inst = IF_Module_init(i); + mac[i]->pre_processor_dl.algorithm = 0; mac[i]->pre_processor_dl.dl = dlsch_scheduler_pre_processor; char *s = "round_robin_dl"; void *d = dlsym(NULL, s); @@ -107,6 +108,7 @@ void mac_top_init_eNB(void) mac[i]->pre_processor_dl.dl_algo = *(default_sched_dl_algo_t *) d; mac[i]->pre_processor_dl.dl_algo.data = mac[i]->pre_processor_dl.dl_algo.setup(); + mac[i]->pre_processor_ul.algorithm = 0; mac[i]->pre_processor_ul.ul = ulsch_scheduler_pre_processor; s = "round_robin_ul"; d = dlsym(NULL, s); diff --git a/openair2/LAYER2/MAC/slicing/slicing.c b/openair2/LAYER2/MAC/slicing/slicing.c index a1de326df0..9c88f6cffb 100644 --- a/openair2/LAYER2/MAC/slicing/slicing.c +++ b/openair2/LAYER2/MAC/slicing/slicing.c @@ -258,13 +258,26 @@ int addmod_static_slice_ul(slice_info_t *si, return si->num - 1; } -int remove_static_slice(slice_info_t *si, uint8_t slice_idx) { +int remove_static_slice_dl(slice_info_t *si, uint8_t slice_idx) { if (slice_idx == 0) return 0; slice_t *sr = _remove_slice(&si->num, si->s, si->UE_assoc_slice, slice_idx); if (!sr) return 0; free(sr->algo_data); + sr->dl_algo.unset(&sr->dl_algo.data); + free(sr); + return 1; +} + +int remove_static_slice_ul(slice_info_t *si, uint8_t slice_idx) { + if (slice_idx == 0) + return 0; + slice_t *sr = _remove_slice(&si->num, si->s, si->UE_assoc_slice, slice_idx); + if (!sr) + return 0; + free(sr->algo_data); + sr->ul_algo.unset(&sr->ul_algo.data); free(sr); return 1; } @@ -528,6 +541,7 @@ pp_impl_param_t static_dl_init(module_id_t mod_id, int CC_id) { dlp->posLow = 0; dlp->posHigh = to_rbg(RC.mac[mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth) - 1; default_sched_dl_algo_t *algo = &RC.mac[mod_id]->pre_processor_dl.dl_algo; + algo->data = NULL; DevAssert(0 == addmod_static_slice_dl(si, 0, strdup("default"), algo, dlp)); const UE_list_t *UE_list = &RC.mac[mod_id]->UE_info.list; for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) @@ -539,7 +553,7 @@ pp_impl_param_t static_dl_init(module_id_t mod_id, int CC_id) { sttc.remove_UE = slicing_remove_UE; sttc.move_UE = slicing_move_UE; sttc.addmod_slice = addmod_static_slice_dl; - sttc.remove_slice = remove_static_slice; + sttc.remove_slice = remove_static_slice_dl; sttc.dl = static_dl; // current DL algo becomes default scheduler sttc.dl_algo = *algo; @@ -564,6 +578,7 @@ pp_impl_param_t static_ul_init(module_id_t mod_id, int CC_id) { ulp->posLow = 0; ulp->posHigh = to_prb(RC.mac[mod_id]->common_channels[CC_id].ul_Bandwidth) - 1; default_sched_ul_algo_t *algo = &RC.mac[mod_id]->pre_processor_ul.ul_algo; + algo->data = NULL; DevAssert(0 == addmod_static_slice_ul(si, 0, strdup("default"), algo, ulp)); const UE_list_t *UE_list = &RC.mac[mod_id]->UE_info.list; for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) @@ -575,7 +590,7 @@ pp_impl_param_t static_ul_init(module_id_t mod_id, int CC_id) { sttc.remove_UE = slicing_remove_UE; sttc.move_UE = slicing_move_UE; sttc.addmod_slice = addmod_static_slice_ul; - sttc.remove_slice = remove_static_slice; + sttc.remove_slice = remove_static_slice_ul; sttc.ul = static_ul; // current DL algo becomes default scheduler sttc.ul_algo = *algo; From 05c10662daf0ee11dee115e473cf7681000a2fc1 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 23 Jun 2020 13:25:28 +0200 Subject: [PATCH 28/66] FlexRAN Bugfix: Free Ringbuffer on exit --- openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c index e5d1c94c95..4c5f3e5609 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c @@ -1619,6 +1619,11 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id) LOG_E(FLEXRAN_AGENT, "MAC agent CM for eNB %d is not registered\n", mod_id); return -1; } + + lfds700_ringbuffer_cleanup(&ringbuffer_state[mod_id], NULL ); + free(dl_mac_config_array[mod_id]); + lfds700_misc_library_cleanup(); + AGENT_MAC_xface *xface = agent_mac_xface[mod_id]; xface->flexran_agent_send_sr_info = NULL; xface->flexran_agent_send_sf_trigger = NULL; From dcd43c1526104567d052e6138f9fd799ee3befa6 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 23 Jun 2020 13:50:59 +0200 Subject: [PATCH 29/66] FlexRAN: use lock-free ringbuffers for slice conf Use LFDS 7.0.0 Ringbuffer implementation to handle * Slice Configuration * UE slice association which is then uploaded through MAC scheduling thread --- .../CONTROL_MODULES/MAC/flexran_agent_mac.c | 100 ++++++++++++++++-- 1 file changed, 92 insertions(+), 8 deletions(-) diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c index 4c5f3e5609..f1daacbb65 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c @@ -49,6 +49,14 @@ struct lfds700_misc_prng_state ps[NUM_MAX_ENB]; struct lfds700_ringbuffer_element *dl_mac_config_array[NUM_MAX_ENB]; struct lfds700_ringbuffer_state ringbuffer_state[NUM_MAX_ENB]; +/* Ringbuffer-related to slice configuration */ +struct lfds700_ringbuffer_element *slice_config_array[NUM_MAX_ENB]; +struct lfds700_ringbuffer_state slice_config_ringbuffer_state[NUM_MAX_ENB]; + +/* Ringbuffer-related to slice configuration */ +struct lfds700_ringbuffer_element *ue_assoc_array[NUM_MAX_ENB]; +struct lfds700_ringbuffer_state ue_assoc_ringbuffer_state[NUM_MAX_ENB]; + int flexran_agent_mac_stats_reply_ue(mid_t mod_id, Protocol__FlexUeStatsReport **ue_report, int n_ue, @@ -1341,6 +1349,33 @@ void flexran_agent_init_mac_agent(mid_t mod_id) { AssertFatal(i == 0, "posix_memalign(): could not allocate aligned memory for lfds library\n"); lfds700_ringbuffer_init_valid_on_current_logical_core(&ringbuffer_state[mod_id], dl_mac_config_array[mod_id], num_elements, &ps[mod_id], NULL); + + struct lfds700_misc_prng_state scrng; + i = posix_memalign((void **) &slice_config_array[mod_id], + LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES, + sizeof(struct lfds700_ringbuffer_element) * num_elements); + AssertFatal(i == 0, + "posix_memalign(): could not allocate aligned memory\n"); + lfds700_ringbuffer_init_valid_on_current_logical_core( + &slice_config_ringbuffer_state[mod_id], + slice_config_array[mod_id], + num_elements, + &scrng, + NULL); + + struct lfds700_misc_prng_state uarng; + i = posix_memalign((void **) &ue_assoc_array[mod_id], + LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES, + sizeof(struct lfds700_ringbuffer_element) * num_elements); + AssertFatal(i == 0, + "posix_memalign(): could not allocate aligned memory\n"); + lfds700_ringbuffer_init_valid_on_current_logical_core( + &ue_assoc_ringbuffer_state[mod_id], + ue_assoc_array[mod_id], + num_elements, + &uarng, + NULL); + for (i = 0; i < MAX_MOBILES_PER_ENB; i++) { for (j = 0; j < 8; j++) { if (RC.mac && RC.mac[mod_id]) @@ -1622,6 +1657,10 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id) lfds700_ringbuffer_cleanup(&ringbuffer_state[mod_id], NULL ); free(dl_mac_config_array[mod_id]); + lfds700_ringbuffer_cleanup(&slice_config_ringbuffer_state[mod_id], NULL ); + free(slice_config_array[mod_id]); + lfds700_ringbuffer_cleanup(&ue_assoc_ringbuffer_state[mod_id], NULL ); + free(ue_assoc_array[mod_id]); lfds700_misc_library_cleanup(); AGENT_MAC_xface *xface = agent_mac_xface[mod_id]; @@ -1661,23 +1700,68 @@ void helper_destroy_mac_slice_config(Protocol__FlexSliceConfig *slice_config) { void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig **slice_config) { if (!*slice_config) return; + /* just use the memory and set to NULL in original */ Protocol__FlexSliceConfig *sc = *slice_config; *slice_config = NULL; - /* TODO handle using lock-free queue */ - apply_update_dl_slice_config(mod_id, sc->dl); - apply_update_ul_slice_config(mod_id, sc->ul); + struct lfds700_misc_prng_state ls; + LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE; + lfds700_misc_prng_init(&ls); + enum lfds700_misc_flag overwrite_occurred_flag; - helper_destroy_mac_slice_config(*slice_config); + Protocol__FlexSliceConfig *overwritten_sc; + lfds700_ringbuffer_write(&slice_config_ringbuffer_state[mod_id], + NULL, + (void *)sc, + &overwrite_occurred_flag, + NULL, + (void **)&overwritten_sc, + &ls); + + if (overwrite_occurred_flag == LFDS700_MISC_FLAG_RAISED) { + helper_destroy_mac_slice_config(overwritten_sc); + LOG_E(FLEXRAN_AGENT, "lost slice config: too many reconfigurations at once\n"); + } } void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig **ue_config) { - /* TODO handle using lock-free queue */ - apply_ue_slice_assoc_update(mod_id, *ue_config); + struct lfds700_misc_prng_state ls; + LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE; + lfds700_misc_prng_init(&ls); + enum lfds700_misc_flag overwrite_occurred_flag; - free(*ue_config); - *ue_config = NULL; + Protocol__FlexUeConfig *overwritten_ue_config; + lfds700_ringbuffer_write(&ue_assoc_ringbuffer_state[mod_id], + NULL, + (void *) *ue_config, + &overwrite_occurred_flag, + NULL, + (void **)&overwritten_ue_config, + &ls); + + if (overwrite_occurred_flag == LFDS700_MISC_FLAG_RAISED) { + free(overwritten_ue_config); + LOG_E(FLEXRAN_AGENT, "lost UE-slice association: too many UE-slice associations at once\n"); + } } void flexran_agent_slice_update(mid_t mod_id) { + struct lfds700_misc_prng_state ls; + LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE; + lfds700_misc_prng_init(&ls); + + Protocol__FlexSliceConfig *sc = NULL; + struct lfds700_ringbuffer_state *state = &slice_config_ringbuffer_state[mod_id]; + if (lfds700_ringbuffer_read(state, NULL, (void **) &sc, &ls) != 0) { + apply_update_dl_slice_config(mod_id, sc->dl); + apply_update_ul_slice_config(mod_id, sc->ul); + helper_destroy_mac_slice_config(sc); + } + + Protocol__FlexUeConfig *ue_config = NULL; + state = &ue_assoc_ringbuffer_state[mod_id]; + if (lfds700_ringbuffer_read(state, NULL, (void **) &ue_config, &ls) != 0) { + apply_ue_slice_assoc_update(mod_id, ue_config); + free(ue_config); + } } From 5fc3a991c91ac117c10b6a5e268f2441b6015cb8 Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Wed, 8 Jul 2020 18:44:34 +0200 Subject: [PATCH 30/66] dci size for 0_1 and some other modifications --- openair2/LAYER2/NR_MAC_COMMON/nr_mac.h | 4 +- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 232 +++++++++++++++++- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h | 5 +- .../NR_MAC_UE/nr_ue_dci_configuration.c | 4 +- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 2 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 2 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 154 ++++++++---- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 34 ++- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 12 +- openair2/RRC/NR/rrc_gNB_reconfig.c | 14 +- 10 files changed, 389 insertions(+), 74 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h index 591c2448b8..d8583167dd 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h @@ -251,9 +251,8 @@ typedef struct { uint8_t short_messages; //8 bits uint8_t tb_scaling; //2 bits uint8_t pucch_resource_indicator; //3 bits - uint8_t dmrs_sequence_initialization; //1 bit uint8_t system_info_indicator; //1 bit - + uint8_t ulsch_indicator; uint8_t slot_format_indicator_count; uint8_t *slot_format_indicators; @@ -290,6 +289,7 @@ typedef struct { dci_field_t cloded_loop_indicator; //variable dci_field_t ul_sul_indicator; //variable dci_field_t antenna_ports; //variable + dci_field_t dmrs_sequence_initialization; dci_field_t reserved; //1_0/C-RNTI:10 bits, 1_0/P-RNTI: 6 bits, 1_0/SI-&RA-RNTI: 16 bits } dci_pdu_rel15_t; diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 8ff0aff5dc..a4097e4d32 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -31,6 +31,7 @@ */ #include "LAYER2/NR_MAC_gNB/mac_proto.h" +#include const uint8_t nr_slots_per_frame[5] = {10, 20, 40, 80, 160}; @@ -1879,7 +1880,8 @@ uint8_t get_K_ptrs(uint16_t nrb0, uint16_t nrb1, uint16_t N_RB) { return 1; } -uint16_t nr_dci_size(NR_CellGroupConfig_t *secondaryCellGroup, +uint16_t nr_dci_size(NR_ServingCellConfigCommon_t *scc, + NR_CellGroupConfig_t *secondaryCellGroup, dci_pdu_rel15_t *dci_pdu, nr_dci_format_t format, nr_rnti_type_t rnti_type, @@ -1887,9 +1889,15 @@ uint16_t nr_dci_size(NR_CellGroupConfig_t *secondaryCellGroup, int bwp_id) { uint16_t size = 0; + uint16_t numRBG = 0; + long rbg_size_config; + int num_entries = 0; + int pusch_antenna_ports = 1; // TODO hardcoded number of antenna ports for pusch NR_BWP_Downlink_t *bwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]; NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_id-1]; NR_PDSCH_Config_t *pdsch_config = bwp->bwp_Dedicated->pdsch_Config->choice.setup; + NR_PUSCH_Config_t *pusch_Config = ubwp->bwp_Dedicated->pusch_Config->choice.setup; + NR_SRS_Config_t *srs_config = ubwp->bwp_Dedicated->srs_Config->choice.setup; switch(format) { /*Only sizes for 0_0 and 1_0 are correct at the moment*/ @@ -1897,30 +1905,197 @@ uint16_t nr_dci_size(NR_CellGroupConfig_t *secondaryCellGroup, /// fixed: Format identifier 1, Hop flag 1, MCS 5, NDI 1, RV 2, HARQ PID 4, PUSCH TPC 2 Time Domain assgnmt 4 --20 size += 20; size += (uint8_t)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); // Freq domain assignment -- hopping scenario to be updated - size += nr_dci_size(secondaryCellGroup,dci_pdu,NR_DL_DCI_FORMAT_1_0, rnti_type, N_RB, bwp_id) - size; // Padding to match 1_0 size + size += nr_dci_size(scc,secondaryCellGroup,dci_pdu,NR_DL_DCI_FORMAT_1_0, rnti_type, N_RB, bwp_id) - size; // Padding to match 1_0 size // UL/SUL indicator assumed to be 0 break; case NR_UL_DCI_FORMAT_0_1: - /// fixed: Format identifier 1, MCS 5, NDI 1, RV 2, HARQ PID 4, PUSCH TPC 2, SRS request 2 --17 - size += 17; + /// fixed: Format identifier 1, MCS 5, NDI 1, RV 2, HARQ PID 4, PUSCH TPC 2, ULSCH indicator 1 --16 + size += 16; // Carrier indicator + if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->crossCarrierSchedulingConfig != NULL) { + dci_pdu->carrier_indicator.nbits=3; + size += dci_pdu->carrier_indicator.nbits; + } // UL/SUL indicator + if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->supplementaryUplink != NULL) { + dci_pdu->carrier_indicator.nbits=1; + size += dci_pdu->ul_sul_indicator.nbits; + } // BWP Indicator + uint8_t n_ul_bwp = secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count; + if (n_ul_bwp < 2) + dci_pdu->bwp_indicator.nbits = n_ul_bwp; + else + dci_pdu->bwp_indicator.nbits = 2; + size += dci_pdu->bwp_indicator.nbits; // Freq domain assignment + if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->pusch_Config->choice.setup->rbg_Size != NULL) + rbg_size_config = 1; + else + rbg_size_config = 0; + numRBG = getNRBG(NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275), + NRRIV2PRBOFFSET(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275), + rbg_size_config); + if (pusch_Config->resourceAllocation == 0) + dci_pdu->frequency_domain_assignment.nbits = numRBG; + else if (pusch_Config->resourceAllocation == 1) + dci_pdu->frequency_domain_assignment.nbits = (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) ); + else + dci_pdu->frequency_domain_assignment.nbits = ((int)ceil( log2( (N_RB*(N_RB+1))>>1 ) )>numRBG) ? (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) )+1 : numRBG+1; + size += dci_pdu->frequency_domain_assignment.nbits; // Time domain assignment - // VRB to PRB mapping + if (pusch_Config->pusch_TimeDomainAllocationList==NULL) { + if (ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList==NULL) + num_entries = 16; // num of entries in default table + else + num_entries = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.count; + } + else + num_entries = pusch_Config->pusch_TimeDomainAllocationList->choice.setup->list.count; + dci_pdu->time_domain_assignment.nbits = (int)ceil(log2(num_entries)); + size += dci_pdu->time_domain_assignment.nbits; // Frequency Hopping flag + if ((pusch_Config->frequencyHopping!=NULL) && (pusch_Config->resourceAllocation != NR_PUSCH_Config__resourceAllocation_resourceAllocationType0)) { + dci_pdu->frequency_hopping_flag.nbits = 1; + size += 1; + } // 1st DAI + if (secondaryCellGroup->physicalCellGroupConfig->pdsch_HARQ_ACK_Codebook==NR_PhysicalCellGroupConfig__pdsch_HARQ_ACK_Codebook_dynamic) + dci_pdu->dai[0].nbits = 2; + else + dci_pdu->dai[0].nbits = 1; + size += dci_pdu->dai[0].nbits; // 2nd DAI + if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->codeBlockGroupTransmission != NULL) { //TODO not sure about that + dci_pdu->dai[1].nbits = 2; + size += dci_pdu->dai[1].nbits; + } // SRS resource indicator + if (pusch_Config->txConfig != NULL){ + int count=0; + if (*pusch_Config->txConfig == NR_PUSCH_Config__txConfig_codebook){ + for (int i=0; isrs_ResourceSetToAddModList->list.count; i++) { + if (srs_config->srs_ResourceSetToAddModList->list.array[i]->usage == NR_SRS_ResourceSet__usage_codebook) + count++; + } + if (count>1) + dci_pdu->srs_resource_indicator.nbits = 1; + } + else { + int lmin,Lmax = 0; + int lsum = 0; + if ( secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig != NULL) { + if ( secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers != NULL) + Lmax = *secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->ext1->maxMIMO_Layers; + else + AssertFatal(1==0,"MIMO on PUSCH not supported, maxMIMO_Layers needs to be set to 1\n"); + } + else + AssertFatal(1==0,"MIMO on PUSCH not supported, maxMIMO_Layers needs to be set to 1\n"); + for (int i=0; isrs_ResourceSetToAddModList->list.count; i++) { + if (srs_config->srs_ResourceSetToAddModList->list.array[i]->usage == NR_SRS_ResourceSet__usage_nonCodebook) + count++; + if (count < Lmax) lmin = count; + else lmin = Lmax; + for (int k=1;k<=lmin;k++) { + lsum += binomial(count,k); + } + } + dci_pdu->srs_resource_indicator.nbits = (int)ceil(log2(lsum)); + } + } + size += dci_pdu->srs_resource_indicator.nbits; // Precoding info and number of layers + long transformPrecoder; + if (pusch_Config->transformPrecoder == NULL){ + // if transform precoder is null, apply the values from msg3 + if(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL) + transformPrecoder = 1; + else + transformPrecoder = 0; + } + else + transformPrecoder = *pusch_Config->transformPrecoder; + if (pusch_Config->txConfig != NULL){ + if (*pusch_Config->txConfig == NR_PUSCH_Config__txConfig_codebook){ + if (pusch_antenna_ports > 1) { + if (pusch_antenna_ports == 4) { + if ((transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) && (*pusch_Config->maxRank>1)) + dci_pdu->precoding_information.nbits = 6-(*pusch_Config->codebookSubset); + else { + if(*pusch_Config->codebookSubset == NR_PUSCH_Config__codebookSubset_nonCoherent) + dci_pdu->precoding_information.nbits = 2; + else + dci_pdu->precoding_information.nbits = 5-(*pusch_Config->codebookSubset); + } + } + else { + AssertFatal(pusch_antenna_ports==2,"Not valid number of antenna ports"); + if ((transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) && (*pusch_Config->maxRank==2)) + dci_pdu->precoding_information.nbits = 4-(*pusch_Config->codebookSubset); + else + dci_pdu->precoding_information.nbits = 3-(*pusch_Config->codebookSubset); + } + } + } + } + size += dci_pdu->precoding_information.nbits; // Antenna ports + NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig = NULL; + int xa=0; + int xb=0; + if(pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA != NULL){ + NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup; + xa = ul_ant_bits(NR_DMRS_UplinkConfig,transformPrecoder); + } + if(pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB != NULL){ + NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; + xb = ul_ant_bits(NR_DMRS_UplinkConfig,transformPrecoder); + } + if (xa>xb) + dci_pdu->antenna_ports.nbits = xa; + else + dci_pdu->antenna_ports.nbits = xb; + size += dci_pdu->antenna_ports.nbits; + // SRS request + if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->supplementaryUplink==NULL) + dci_pdu->srs_request.nbits = 2; + else + dci_pdu->srs_request.nbits = 3; + size += dci_pdu->srs_request.nbits; // CSI request + if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig != NULL) { + if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup->reportTriggerSize != NULL) { + dci_pdu->csi_request.nbits = *secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup->reportTriggerSize; + size += dci_pdu->csi_request.nbits; + } + } // CBGTI + if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->codeBlockGroupTransmission != NULL) { + int num = secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup->codeBlockGroupTransmission->choice.setup->maxCodeBlockGroupsPerTransportBlock; + dci_pdu->cbgti.nbits = 2 + (num<<1); + size += dci_pdu->cbgti.nbits; + } // PTRS - DMRS association + if ( (NR_DMRS_UplinkConfig->phaseTrackingRS == NULL && transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) || + transformPrecoder == NR_PUSCH_Config__transformPrecoder_enabled || (*pusch_Config->maxRank==1) ) + dci_pdu->ptrs_dmrs_association.nbits = 0; + else + dci_pdu->ptrs_dmrs_association.nbits = 2; + size += dci_pdu->ptrs_dmrs_association.nbits; // beta offset indicator + if (pusch_Config->uci_OnPUSCH!=NULL){ + if (pusch_Config->uci_OnPUSCH->choice.setup->betaOffsets->present == NR_UCI_OnPUSCH__betaOffsets_PR_dynamic) { + dci_pdu->beta_offset_indicator.nbits = 2; + size += dci_pdu->beta_offset_indicator.nbits; + } + } // DMRS sequence init + if (transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) { + dci_pdu->dmrs_sequence_initialization.nbits = 1; + size += dci_pdu->dmrs_sequence_initialization.nbits; + } break; case NR_DL_DCI_FORMAT_1_0: @@ -1946,10 +2121,10 @@ uint16_t nr_dci_size(NR_CellGroupConfig_t *secondaryCellGroup, dci_pdu->bwp_indicator.nbits = 2; size += dci_pdu->bwp_indicator.nbits; // Freq domain assignment - long rbg_size_config = secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->rbg_Size; - uint16_t numRBG = getNRBG(NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275), - NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth,275), - rbg_size_config); + rbg_size_config = secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->rbg_Size; + numRBG = getNRBG(NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275), + NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth,275), + rbg_size_config); if (pdsch_config->resourceAllocation == 0) dci_pdu->frequency_domain_assignment.nbits = numRBG; else if (pdsch_config->resourceAllocation == 1) @@ -1958,7 +2133,6 @@ uint16_t nr_dci_size(NR_CellGroupConfig_t *secondaryCellGroup, dci_pdu->frequency_domain_assignment.nbits = ((int)ceil( log2( (N_RB*(N_RB+1))>>1 ) )>numRBG) ? (int)ceil( log2( (N_RB*(N_RB+1))>>1 ) )+1 : numRBG+1; size += dci_pdu->frequency_domain_assignment.nbits; // Time domain assignment (see table 5.1.2.1.1-1 in 38.214 - int num_entries; if (pdsch_config->pdsch_TimeDomainAllocationList==NULL) { if (bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList==NULL) num_entries = 16; // num of entries in default table @@ -2068,6 +2242,27 @@ uint16_t nr_dci_size(NR_CellGroupConfig_t *secondaryCellGroup, return size; } +int ul_ant_bits(NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig, long transformPrecoder) { + + uint8_t type,maxl; + if(NR_DMRS_UplinkConfig->dmrs_Type == NULL) + type = 1; + else + type = 2; + if(NR_DMRS_UplinkConfig->maxLength == NULL) + maxl = 1; + else + maxl = 2; + if (transformPrecoder == NR_PUSCH_Config__transformPrecoder_disabled) + return( maxl+type+1); + else { + if (type==1) + return (maxl<<1); + else + AssertFatal(1==0,"DMRS type not valid for this choice"); + } +} + int tdd_period_to_num[8] = {500,625,1000,1250,2000,2500,5000,10000}; int is_nr_DL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slot) { @@ -2208,3 +2403,20 @@ int16_t fill_dmrs_mask(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,i AssertFatal(1==0,"Shouldn't get here\n"); return(-1); } + + +int binomial(int n, int k) { + int c = 1, i; + + if (k > n-k) + k = n-k; + + for (i = 1; i <= k; i++, n--) { + if (c/i > UINT_MAX/n) // return 0 on overflow + return 0; + + c = c / i * n + c % i * n / i; + } + return c; +} + diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h index 2f7f144983..a5e38bf128 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h @@ -77,7 +77,8 @@ int is_nr_DL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slotP); int is_nr_UL_slot(NR_ServingCellConfigCommon_t *scc,slot_t slotP); -uint16_t nr_dci_size(NR_CellGroupConfig_t *secondaryCellGroup, +uint16_t nr_dci_size(NR_ServingCellConfigCommon_t *scc, + NR_CellGroupConfig_t *secondaryCellGroup, dci_pdu_rel15_t *dci_pdu, nr_dci_format_t format, nr_rnti_type_t rnti_type, @@ -103,6 +104,8 @@ uint8_t compute_nr_root_seq(NR_RACH_ConfigCommon_t *rach_config, uint8_t nb_preambles, uint8_t unpaired); +int ul_ant_bits(NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig,long transformPrecoder); + int get_format0(uint8_t index, uint8_t unpaired); uint16_t get_NCS(uint8_t index, uint16_t format, uint8_t restricted_set_config); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c index a79b4083e3..53263747fc 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -223,7 +223,7 @@ void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl rel15->BWPSize = NRRIV2BW(initialDownlinkBWP->genericParameters.locationAndBandwidth, 275); rel15->BWPStart = NRRIV2PRBOFFSET(bwp_Common->genericParameters.locationAndBandwidth, 275); // NRRIV2PRBOFFSET(initialDownlinkBWP->genericParameters.locationAndBandwidth, 275); rel15->SubcarrierSpacing = initialDownlinkBWP->genericParameters.subcarrierSpacing; - rel15->dci_length = nr_dci_size(mac->scg,def_dci_pdu_rel15,rel15->dci_format,NR_RNTI_C,rel15->BWPSize,bwp_id); + rel15->dci_length = nr_dci_size(scc,mac->scg,def_dci_pdu_rel15,rel15->dci_format,NR_RNTI_C,rel15->BWPSize,bwp_id); for (int i = 0; i < sps; i++) if ((monitoringSymbolsWithinSlot >> (sps - 1 - i)) & 1) { rel15->coreset.StartSymbolIndex = i; @@ -243,7 +243,7 @@ void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl rel15->BWPSize = NRRIV2BW(bwp_Common->genericParameters.locationAndBandwidth, 275); rel15->BWPStart = NRRIV2PRBOFFSET(bwp_Common->genericParameters.locationAndBandwidth, 275); rel15->SubcarrierSpacing = bwp_Common->genericParameters.subcarrierSpacing; - rel15->dci_length = nr_dci_size(mac->scg,def_dci_pdu_rel15,rel15->dci_format,NR_RNTI_C,rel15->BWPSize,bwp_id); + rel15->dci_length = nr_dci_size(scc,mac->scg,def_dci_pdu_rel15,rel15->dci_format,NR_RNTI_C,rel15->BWPSize,bwp_id); // get UE-specific search space for (ss_id = 0; ss_id < FAPI_NR_MAX_SS_PER_CORESET && mac->SSpace[0][0][ss_id] != NULL; ss_id++){ uss = mac->SSpace[0][0][ss_id]; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 163855a093..2f264d9c7e 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -3530,7 +3530,7 @@ void nr_extract_dci_info(NR_UE_MAC_INST_t *mac, dci_pdu_rel15->cbgfi.val = (*dci_pdu>>(dci_size-pos))&((1<cbgfi.nbits)-1); // DMRS sequence init pos+=1; - dci_pdu_rel15->dmrs_sequence_initialization = (*dci_pdu>>(dci_size-pos))&0x1; + dci_pdu_rel15->dmrs_sequence_initialization.val = (*dci_pdu>>(dci_size-pos))&0x1; break; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index db93734a7d..2eb4ad498b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -688,7 +688,7 @@ void nr_generate_Msg2(module_id_t module_idP, pdcch_pdu_rel15->StartSymbolIndex, pdcch_pdu_rel15->DurationSymbols); - fill_dci_pdu_rel15(secondaryCellGroup,pdcch_pdu_rel15, &dci_pdu_rel15[0], dci_formats, rnti_types,dci10_bw,ra->bwp_id); + fill_dci_pdu_rel15(scc,secondaryCellGroup,pdcch_pdu_rel15, &dci_pdu_rel15[0], dci_formats, rnti_types,dci10_bw,ra->bwp_id); dl_req->nPDUs+=2; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index a9bc3447aa..e9fbdf489c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -329,7 +329,7 @@ int configure_fapi_dl_pdu(int Mod_idP, pdsch_pdu_rel15->rbStart = (rbStart!=NULL) ? *rbStart : 0; pdsch_pdu_rel15->rbSize = (rbSize!=NULL) ? *rbSize : pdsch_pdu_rel15->BWPSize; pdsch_pdu_rel15->VRBtoPRBMapping = 1; // non-interleaved, check if this is ok for initialBWP - // choose shortest PDSCH + int startSymbolAndLength=0; int time_domain_assignment=2; int StartSymbolIndex,NrOfSymbols; @@ -362,10 +362,10 @@ int configure_fapi_dl_pdu(int Mod_idP, AssertFatal(1==0,"Only frequency resource allocation type 1 is currently supported\n"); // time domain assignment dci_pdu_rel15[0].time_domain_assignment.val = time_domain_assignment; // row index used here instead of SLIV; - // mcs ndi and rv + // mcs and rv dci_pdu_rel15[0].mcs = pdsch_pdu_rel15->mcsIndex[0]; dci_pdu_rel15[0].rv = pdsch_pdu_rel15->rvIndex[0]; - // harq pid + // harq pid and ndi dci_pdu_rel15[0].harq_pid = current_harq_pid; dci_pdu_rel15[0].ndi = UE_list->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].ndi; // DAI @@ -381,7 +381,8 @@ int configure_fapi_dl_pdu(int Mod_idP, UE_list->UE_sched_ctrl[UE_id].harq_processes[current_harq_pid].is_waiting = 1; // antenna ports dci_pdu_rel15[0].antenna_ports.val = 0; // nb of cdm groups w/o data 1 and dmrs port 0 - + // dmrs sequence initialization + dci_pdu_rel15[0].dmrs_sequence_initialization.val = pdsch_pdu_rel15->SCID; LOG_D(MAC, "[gNB scheduler phytest] DCI type 1 payload: freq_alloc %d (%d,%d,%d), time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d ndi %d rv %d\n", dci_pdu_rel15[0].frequency_domain_assignment.val, pdsch_pdu_rel15->rbStart, @@ -436,7 +437,7 @@ int configure_fapi_dl_pdu(int Mod_idP, rnti_types[0] = NR_RNTI_C; - fill_dci_pdu_rel15(secondaryCellGroup,pdcch_pdu_rel15,dci_pdu_rel15,dci_formats,rnti_types,pdsch_pdu_rel15->BWPSize,bwp_id); + fill_dci_pdu_rel15(scc,secondaryCellGroup,pdcch_pdu_rel15,dci_pdu_rel15,dci_formats,rnti_types,pdsch_pdu_rel15->BWPSize,bwp_id); LOG_D(MAC, "DCI params: rnti %x, rnti_type %d, dci_format %d\n \ coreset params: FreqDomainResource %llx, start_symbol %d n_symb %d\n", @@ -466,22 +467,69 @@ int configure_fapi_dl_pdu(int Mod_idP, return TBS; //Return TBS in bytes } -void config_uldci(NR_BWP_Uplink_t *ubwp,nfapi_nr_pusch_pdu_t *pusch_pdu,nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, dci_pdu_rel15_t *dci_pdu_rel15, int *dci_formats, int *rnti_types) { +void config_uldci(NR_BWP_Uplink_t *ubwp, + nfapi_nr_pusch_pdu_t *pusch_pdu, + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, + dci_pdu_rel15_t *dci_pdu_rel15, + int *dci_formats, int *rnti_types, + int n_ubwp, int bwp_id) { - dci_pdu_rel15->frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pusch_pdu->rb_size, - pusch_pdu->rb_start, - NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275)); + switch(dci_formats[(pdcch_pdu_rel15->numDlDci)-1]) { + case NR_UL_DCI_FORMAT_0_0: + dci_pdu_rel15->frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pusch_pdu->rb_size, + pusch_pdu->rb_start, + NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275)); + + dci_pdu_rel15->time_domain_assignment.val = 2; // row index used here instead of SLIV; + dci_pdu_rel15->frequency_hopping_flag.val = pusch_pdu->frequency_hopping; + dci_pdu_rel15->mcs = 9; + + dci_pdu_rel15->format_indicator = 0; + dci_pdu_rel15->ndi = 1; + dci_pdu_rel15->rv = 0; + dci_pdu_rel15->harq_pid = 0; + dci_pdu_rel15->tpc = 2; + break; + case NR_UL_DCI_FORMAT_0_1: + dci_pdu_rel15->ndi = pusch_pdu->pusch_data.new_data_indicator; + dci_pdu_rel15->rv = pusch_pdu->pusch_data.rv_index; + dci_pdu_rel15->harq_pid = pusch_pdu->pusch_data.harq_process_id; + dci_pdu_rel15->frequency_hopping_flag.val = pusch_pdu->frequency_hopping; + //dci_pdu_rel15->dai[0].val = ???; //TODO + // bwp indicator + if (n_ubwp < 4) + dci_pdu_rel15->bwp_indicator.val = bwp_id; + else + dci_pdu_rel15->bwp_indicator.val = bwp_id - 1; // as per table 7.3.1.1.2-1 in 38.212 + // frequency domain assignment + if (ubwp->bwp_Dedicated->pusch_Config->choice.setup->resourceAllocation==NR_PUSCH_Config__resourceAllocation_resourceAllocationType1) + dci_pdu_rel15->frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pusch_pdu->rb_size, + pusch_pdu->rb_start, + NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275)); + else + AssertFatal(1==0,"Only frequency resource allocation type 1 is currently supported\n"); + // time domain assignment + dci_pdu_rel15->time_domain_assignment.val = 2; + // mcs + dci_pdu_rel15->mcs = pusch_pdu->mcs_index; + // tpc command for pusch + dci_pdu_rel15->tpc = 2; //TODO + // SRS resource indicator + if (ubwp->bwp_Dedicated->pusch_Config->choice.setup->txConfig != NULL) { + if (*ubwp->bwp_Dedicated->pusch_Config->choice.setup->txConfig == NR_PUSCH_Config__txConfig_codebook) + dci_pdu_rel15->srs_resource_indicator.val = 0; // taking resource 0 for SRS + else + AssertFatal(1==0,"Non Codebook configuration non supported\n"); + } + // Antenna Ports + dci_pdu_rel15->antenna_ports.val = 0; // TODO for now it is hardcoded, it should depends on cdm group no data and rank + // DMRS sequence initialization + dci_pdu_rel15->dmrs_sequence_initialization.val = pusch_pdu->scid; + break; + default : + AssertFatal(1==0,"Valid UL formats are 0_0 and 0_1 \n"); + } - dci_pdu_rel15->time_domain_assignment.val = 2; // row index used here instead of SLIV; - dci_pdu_rel15->frequency_hopping_flag.val = 0; - dci_pdu_rel15->mcs = 9; - - dci_pdu_rel15->format_indicator = 0; - dci_pdu_rel15->ndi = 1; - dci_pdu_rel15->rv = 0; - dci_pdu_rel15->harq_pid = 0; - dci_pdu_rel15->tpc = 2; - LOG_D(MAC, "[gNB scheduler phytest] ULDCI type 0 payload: PDCCH CCEIndex %d, freq_alloc %d, time_alloc %d, freq_hop_flag %d, mcs %d tpc %d ndi %d rv %d\n", pdcch_pdu_rel15->dci_pdu.CceIndex[pdcch_pdu_rel15->numDlDci], dci_pdu_rel15->frequency_domain_assignment.val, @@ -491,10 +539,6 @@ void config_uldci(NR_BWP_Uplink_t *ubwp,nfapi_nr_pusch_pdu_t *pusch_pdu,nfapi_nr dci_pdu_rel15->tpc, dci_pdu_rel15->ndi, dci_pdu_rel15->rv); - - dci_formats[pdcch_pdu_rel15->numDlDci] = NR_UL_DCI_FORMAT_0_0; - rnti_types[pdcch_pdu_rel15->numDlDci] = NR_RNTI_C; - pdcch_pdu_rel15->numDlDci++; } @@ -736,7 +780,7 @@ void nr_schedule_uss_ulsch_phytest(int Mod_idP, NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; int bwp_id=1; - + int mu = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing; int UE_id = 0; NR_UE_list_t *UE_list = &RC.nrmac[Mod_idP]->UE_list; AssertFatal(UE_list->active[UE_id] >=0,"Cannot find UE_id %d is not active\n",UE_id); @@ -746,7 +790,9 @@ void nr_schedule_uss_ulsch_phytest(int Mod_idP, "downlinkBWP_ToAddModList has %d BWP!\n", secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count); NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_id-1]; + int n_ubwp = secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.count; NR_BWP_Downlink_t *bwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]; + NR_PUSCH_Config_t *pusch_Config = ubwp->bwp_Dedicated->pusch_Config->choice.setup; nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[Mod_idP]->UL_tti_req[0]; nfapi_nr_ul_dci_request_t *UL_dci_req = &RC.nrmac[Mod_idP]->UL_dci_req[0]; @@ -767,20 +813,27 @@ void nr_schedule_uss_ulsch_phytest(int Mod_idP, LOG_D(MAC, "Scheduling UE specific PUSCH\n"); //UL_tti_req = &nr_mac->UL_tti_req[CC_id]; - /* - // original configuration - rel15_ul->rnti = 0x1234; - rel15_ul->ulsch_pdu_rel15.start_rb = 30; - rel15_ul->ulsch_pdu_rel15.number_rbs = 50; - rel15_ul->ulsch_pdu_rel15.start_symbol = 2; - rel15_ul->ulsch_pdu_rel15.number_symbols = 12; - rel15_ul->ulsch_pdu_rel15.nb_re_dmrs = 6; - rel15_ul->ulsch_pdu_rel15.length_dmrs = 1; - rel15_ul->ulsch_pdu_rel15.Qm = 2; - rel15_ul->ulsch_pdu_rel15.mcs = 9; - rel15_ul->ulsch_pdu_rel15.rv = 0; - rel15_ul->ulsch_pdu_rel15.n_layers = 1; - */ + + //Resource Allocation in time domain + int startSymbolAndLength=0; + int time_domain_assignment=1; + int StartSymbolIndex,NrOfSymbols,K2,mapping_type; + + AssertFatal(time_domain_assignmentbwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.count, + "time_domain_assignment %d>=%d\n",time_domain_assignment,ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.count); + startSymbolAndLength = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment]->startSymbolAndLength; + SLIV2SL(startSymbolAndLength,&StartSymbolIndex,&NrOfSymbols); + pusch_pdu->start_symbol_index = StartSymbolIndex; + pusch_pdu->nr_of_symbols = NrOfSymbols; + mapping_type = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment]->mappingType; + if (ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment]->k2 != NULL) + K2 = *ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment]->k2; + else { + if (mu<2) K2=1; + else if(mu==2) K2=2; + else K2=3; + } + pusch_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; pusch_pdu->rnti = rnti; pusch_pdu->handle = 0; //not yet used @@ -800,17 +853,22 @@ void nr_schedule_uss_ulsch_phytest(int Mod_idP, pusch_pdu->nrOfLayers = 1; //Pusch Allocation in frequency domain [TS38.214, sec 6.1.2.2] - pusch_pdu->resource_alloc = 1; //type 1 - //pusch_pdu->rb_bitmap;// for ressource alloc type 0 - pusch_pdu->rb_start = 0; - pusch_pdu->rb_size = 50; + if (pusch_Config->resourceAllocation==NR_PUSCH_Config__resourceAllocation_resourceAllocationType1) { + pusch_pdu->resource_alloc = 1; //type 1 + pusch_pdu->rb_start = 0; + pusch_pdu->rb_size = 50; + } + else + AssertFatal(1==0,"Only frequency resource allocation type 1 is currently supported\n"); + pusch_pdu->vrb_to_prb_mapping = 0; - pusch_pdu->frequency_hopping = 0; + if (pusch_Config->frequencyHopping==NULL) + pusch_pdu->frequency_hopping = 0; + else + pusch_pdu->frequency_hopping = 1; //pusch_pdu->tx_direct_current_location;//The uplink Tx Direct Current location for the carrier. Only values in the value range of this field between 0 and 3299, which indicate the subcarrier index within the carrier corresponding 1o the numerology of the corresponding uplink BWP and value 3300, which indicates "Outside the carrier" and value 3301, which indicates "Undetermined position within the carrier" are used. [TS38.331, UplinkTxDirectCurrentBWP IE] pusch_pdu->uplink_frequency_shift_7p5khz = 0; - //Resource Allocation in time domain - pusch_pdu->start_symbol_index = 2; - pusch_pdu->nr_of_symbols = 12; + // -------------------- // ------- DMRS ------- @@ -934,8 +992,8 @@ void nr_schedule_uss_ulsch_phytest(int Mod_idP, } else { dci_pdu_rel15_t dci_pdu_rel15[MAX_DCI_CORESET]; - config_uldci(ubwp,pusch_pdu,pdcch_pdu_rel15, &dci_pdu_rel15[0], dci_formats, rnti_types); - fill_dci_pdu_rel15(secondaryCellGroup,pdcch_pdu_rel15,dci_pdu_rel15,dci_formats,rnti_types,pusch_pdu->bwp_size,bwp_id); + config_uldci(ubwp,pusch_pdu,pdcch_pdu_rel15,&dci_pdu_rel15[0],dci_formats,rnti_types,n_ubwp,bwp_id); + fill_dci_pdu_rel15(scc,secondaryCellGroup,pdcch_pdu_rel15,dci_pdu_rel15,dci_formats,rnti_types,pusch_pdu->bwp_size,bwp_id); } } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 44f4edd3ea..8253dbc4be 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -734,6 +734,19 @@ void prepare_dci(NR_CellGroupConfig_t *secondaryCellGroup, NR_BWP_Downlink_t *bwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[bwp_id-1]; switch(format) { + case NR_UL_DCI_FORMAT_0_1: + // format indicator + dci_pdu_rel15->format_indicator = 0; + // carrier indicator + if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->crossCarrierSchedulingConfig != NULL) + AssertFatal(1==0,"Cross Carrier Scheduling Config currently not supported\n"); + // supplementary uplink + if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->supplementaryUplink != NULL) + AssertFatal(1==0,"Supplementary Uplink currently not supported\n"); + // SRS request + dci_pdu_rel15->srs_request.val = 0; + dci_pdu_rel15->ulsch_indicator = 1; + break; case NR_DL_DCI_FORMAT_1_1: // format indicator dci_pdu_rel15->format_indicator = 1; @@ -782,16 +795,15 @@ void prepare_dci(NR_CellGroupConfig_t *secondaryCellGroup, // CBGTI and CBGFI if (secondaryCellGroup->spCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup->codeBlockGroupTransmission != NULL) AssertFatal(1==0,"CBG transmission currently not supported\n"); - // dmrs sequence initialization - dci_pdu_rel15->dmrs_sequence_initialization = 0; // FIXME no information on what this bit should be in 38.212 break; default : - AssertFatal(1==0,"Prepare dci currently only implemented for 1_1 \n"); + AssertFatal(1==0,"Prepare dci currently only implemented for 1_1 and 0_1 \n"); } } -void fill_dci_pdu_rel15(NR_CellGroupConfig_t *secondaryCellGroup, +void fill_dci_pdu_rel15(NR_ServingCellConfigCommon_t *scc, + NR_CellGroupConfig_t *secondaryCellGroup, nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, dci_pdu_rel15_t *dci_pdu_rel15, int *dci_formats, @@ -805,7 +817,7 @@ void fill_dci_pdu_rel15(NR_CellGroupConfig_t *secondaryCellGroup, for (int d=0;dnumDlDci;d++) { uint64_t *dci_pdu = (uint64_t *)pdcch_pdu_rel15->dci_pdu.Payload[d]; - int dci_size = nr_dci_size(secondaryCellGroup,&dci_pdu_rel15[d],dci_formats[d],rnti_types[d],N_RB,bwp_id); + int dci_size = nr_dci_size(scc,secondaryCellGroup,&dci_pdu_rel15[d],dci_formats[d],rnti_types[d],N_RB,bwp_id); pdcch_pdu_rel15->dci_pdu.PayloadSizeBits[d] = dci_size; AssertFatal(pdcch_pdu_rel15->dci_pdu.PayloadSizeBits[d]<=64, "DCI sizes above 64 bits not yet supported"); @@ -1119,6 +1131,16 @@ void fill_dci_pdu_rel15(NR_CellGroupConfig_t *secondaryCellGroup, } break; + case NR_UL_DCI_FORMAT_0_1: + switch(rnti_types[d]) + { + case NR_RNTI_C: + // Frequency domain resource assignment + // add potential MSB for N_UL_HOP + break; + } + break; + case NR_DL_DCI_FORMAT_1_1: // Indicating a DL DCI format 1bit pos=1; @@ -1224,7 +1246,7 @@ void fill_dci_pdu_rel15(NR_CellGroupConfig_t *secondaryCellGroup, // DMRS sequence init pos+=1; - *dci_pdu |= ((uint64_t)dci_pdu_rel15->dmrs_sequence_initialization&0x1)<<(dci_size-pos); + *dci_pdu |= ((uint64_t)dci_pdu_rel15->dmrs_sequence_initialization.val&0x1)<<(dci_size-pos); } } } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 78920dd2ea..8b38c357c6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -132,7 +132,12 @@ int configure_fapi_dl_pdu(int Mod_id, uint16_t *rbSize, uint16_t *rbStart); -void config_uldci(NR_BWP_Uplink_t *ubwp,nfapi_nr_pusch_pdu_t *pusch_pdu,nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, dci_pdu_rel15_t *dci_pdu_rel15, int *dci_formats, int *rnti_types); +void config_uldci(NR_BWP_Uplink_t *ubwp, + nfapi_nr_pusch_pdu_t *pusch_pdu, + nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, + dci_pdu_rel15_t *dci_pdu_rel15, + int *dci_formats, int *rnti_types, + int n_ubwp, int bwp_id); void configure_fapi_dl_Tx(module_id_t Mod_idP, frame_t frameP, @@ -203,7 +208,8 @@ int nr_configure_pdcch(gNB_MAC_INST *nr_mac, NR_ServingCellConfigCommon_t *scc, NR_BWP_Downlink_t *bwp); -void fill_dci_pdu_rel15(NR_CellGroupConfig_t *secondaryCellGroup, +void fill_dci_pdu_rel15(NR_ServingCellConfigCommon_t *scc, + NR_CellGroupConfig_t *secondaryCellGroup, nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, dci_pdu_rel15_t *dci_pdu_rel15, int *dci_formats, @@ -289,6 +295,8 @@ void nr_process_mac_pdu( uint8_t *pduP, uint16_t mac_pdu_len); +int binomial(int n, int k); + /* \brief Function to indicate a received SDU on ULSCH. @param Mod_id Instance ID of gNB diff --git a/openair2/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c index 7b0bb099f7..a99c1125e4 100644 --- a/openair2/RRC/NR/rrc_gNB_reconfig.c +++ b/openair2/RRC/NR/rrc_gNB_reconfig.c @@ -1095,7 +1095,19 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id)); *secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id = 1; - secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig = NULL; + + secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig = calloc(1,sizeof(*secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig)); + NR_PUSCH_ServingCellConfig_t *pusch_scc = calloc(1,sizeof(*pusch_scc)); + secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->present = NR_SetupRelease_PUSCH_ServingCellConfig_PR_setup; + secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->pusch_ServingCellConfig->choice.setup = pusch_scc; + pusch_scc->codeBlockGroupTransmission = NULL; + pusch_scc->rateMatching = NULL; + pusch_scc->xOverhead = NULL; + pusch_scc->ext1=calloc(1,sizeof(*pusch_scc->ext1)); + pusch_scc->ext1->maxMIMO_Layers = calloc(1,sizeof(*pusch_scc->ext1->maxMIMO_Layers)); + *pusch_scc->ext1->maxMIMO_Layers = 1; + pusch_scc->ext1->processingType2Enabled = NULL; + secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->carrierSwitching = NULL; secondaryCellGroup->spCellConfig->spCellConfigDedicated->supplementaryUplink=NULL; From 0f9519925d95a7fc5ad5f250bfda56116ef538e4 Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Thu, 9 Jul 2020 11:58:15 +0200 Subject: [PATCH 31/66] fill dci pdu --- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 96 ++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 8253dbc4be..9eab75e7bc 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -1135,8 +1135,102 @@ void fill_dci_pdu_rel15(NR_ServingCellConfigCommon_t *scc, switch(rnti_types[d]) { case NR_RNTI_C: + // Indicating a DL DCI format 1bit + pos=1; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->format_indicator&0x1)<<(dci_size-pos); + + // Carrier indicator + pos+=dci_pdu_rel15->carrier_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->carrier_indicator.val&((1<carrier_indicator.nbits)-1))<<(dci_size-pos); + + // UL/SUL Indicator + pos+=dci_pdu_rel15->ul_sul_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->ul_sul_indicator.val&((1<ul_sul_indicator.nbits)-1))<<(dci_size-pos); + + // BWP indicator + pos+=dci_pdu_rel15->bwp_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->bwp_indicator.val&((1<bwp_indicator.nbits)-1))<<(dci_size-pos); + // Frequency domain resource assignment - // add potential MSB for N_UL_HOP + pos+=dci_pdu_rel15->frequency_domain_assignment.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_domain_assignment.val&((1<frequency_domain_assignment.nbits)-1)) << (dci_size-pos); + + // Time domain resource assignment + pos+=dci_pdu_rel15->time_domain_assignment.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->time_domain_assignment.val&((1<time_domain_assignment.nbits)-1)) << (dci_size-pos); + + // Frequency hopping + pos+=dci_pdu_rel15->frequency_hopping_flag.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->frequency_hopping_flag.val&((1<frequency_hopping_flag.nbits)-1)) << (dci_size-pos); + + // MCS 5bit + pos+=5; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->mcs&0x1f)<<(dci_size-pos); + + // New data indicator 1bit + pos+=1; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->ndi&0x1)<<(dci_size-pos); + + // Redundancy version 2bit + pos+=2; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->rv&0x3)<<(dci_size-pos); + + // HARQ process number 4bit + pos+=4; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->harq_pid&0xf)<<(dci_size-pos); + + // 1st Downlink assignment index + pos+=dci_pdu_rel15->dai[0].nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->dai[0].val&((1<dai[0].nbits)-1))<<(dci_size-pos); + + // 2nd Downlink assignment index + pos+=dci_pdu_rel15->dai[1].nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->dai[1].val&((1<dai[1].nbits)-1))<<(dci_size-pos); + + // TPC command for scheduled PUSCH 2bit + pos+=2; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->tpc&0x3)<<(dci_size-pos); + + // SRS resource indicator + pos+=dci_pdu_rel15->srs_resource_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->srs_resource_indicator.val&((1<srs_resource_indicator.nbits)-1))<<(dci_size-pos); + + // Precoding info and n. of layers + pos+=dci_pdu_rel15->precoding_information.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->precoding_information.val&((1<precoding_information.nbits)-1))<<(dci_size-pos); + + // Antenna ports + pos+=dci_pdu_rel15->antenna_ports.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->antenna_ports.val&((1<antenna_ports.nbits)-1))<<(dci_size-pos); + + // SRS request + pos+=dci_pdu_rel15->srs_request.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->srs_request.val&((1<srs_request.nbits)-1))<<(dci_size-pos); + + // CSI request + pos+=dci_pdu_rel15->csi_request.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->csi_request.val&((1<csi_request.nbits)-1))<<(dci_size-pos); + + // CBG transmission information + pos+=dci_pdu_rel15->cbgti.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->cbgti.val&((1<cbgti.nbits)-1))<<(dci_size-pos); + + // PTRS DMRS association + pos+=dci_pdu_rel15->ptrs_dmrs_association.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->ptrs_dmrs_association.val&((1<ptrs_dmrs_association.nbits)-1))<<(dci_size-pos); + + // Beta offset indicator + pos+=dci_pdu_rel15->beta_offset_indicator.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->beta_offset_indicator.val&((1<beta_offset_indicator.nbits)-1))<<(dci_size-pos); + + // DMRS sequence initialization + pos+=dci_pdu_rel15->dmrs_sequence_initialization.nbits; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->dmrs_sequence_initialization.val&((1<dmrs_sequence_initialization.nbits)-1))<<(dci_size-pos); + + // UL-SCH indicator + pos+=1; + *dci_pdu |= ((uint64_t)dci_pdu_rel15->ulsch_indicator&0x1)<<(dci_size-pos); + break; } break; From d66aea3fe610037008070018caa255237ce8fd9e Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Thu, 9 Jul 2020 17:57:39 +0200 Subject: [PATCH 32/66] bugfixes in dci size --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index a4097e4d32..3ffa1beaad 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -1979,8 +1979,10 @@ uint16_t nr_dci_size(NR_ServingCellConfigCommon_t *scc, if (srs_config->srs_ResourceSetToAddModList->list.array[i]->usage == NR_SRS_ResourceSet__usage_codebook) count++; } - if (count>1) + if (count>1) { dci_pdu->srs_resource_indicator.nbits = 1; + size += dci_pdu->srs_resource_indicator.nbits; + } } else { int lmin,Lmax = 0; @@ -2003,11 +2005,12 @@ uint16_t nr_dci_size(NR_ServingCellConfigCommon_t *scc, } } dci_pdu->srs_resource_indicator.nbits = (int)ceil(log2(lsum)); + size += dci_pdu->srs_resource_indicator.nbits; } } - size += dci_pdu->srs_resource_indicator.nbits; // Precoding info and number of layers long transformPrecoder; + dci_pdu->precoding_information.nbits = 0; if (pusch_Config->transformPrecoder == NULL){ // if transform precoder is null, apply the values from msg3 if(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL) From 5651b9073ce1af0b238954d6744863a273e5ad98 Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Fri, 10 Jul 2020 09:16:11 +0200 Subject: [PATCH 33/66] pusch config in mac gnb from rrc --- .../nfapi/public_inc/nfapi_nr_interface_scf.h | 1 + openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 4 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 107 ++++++++++++++---- openair2/RRC/NR/rrc_gNB_reconfig.c | 3 +- 4 files changed, 88 insertions(+), 27 deletions(-) diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h index fea64e3f3e..e342ab0b67 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h @@ -1120,6 +1120,7 @@ typedef struct uint16_t ul_dmrs_symb_pos; uint8_t dmrs_config_type; uint16_t ul_dmrs_scrambling_id; + uint16_t pusch_identity; uint8_t scid; uint8_t num_dmrs_cdm_grps_no_data; uint16_t dmrs_ports;//DMRS ports. [TS38.212 7.3.1.1.2] provides description between DCI 0-1 content and DMRS ports. Bitmap occupying the 11 LSBs with: bit 0: antenna port 1000 bit 11: antenna port 1011 and for each bit 0: DMRS port not used 1: DMRS port used diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 2f264d9c7e..d02d9afcce 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -773,8 +773,8 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in uint16_t rnti = 0x1234; uint32_t rb_size = 50; uint32_t rb_start = 0; - uint8_t nr_of_symbols = 12; - uint8_t start_symbol_index = 2; + uint8_t nr_of_symbols = 11; + uint8_t start_symbol_index = 0; uint8_t nrOfLayers = 1; uint8_t mcs_index = 9; uint8_t mcs_table = 0; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index e9fbdf489c..a1ada71538 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -825,6 +825,7 @@ void nr_schedule_uss_ulsch_phytest(int Mod_idP, SLIV2SL(startSymbolAndLength,&StartSymbolIndex,&NrOfSymbols); pusch_pdu->start_symbol_index = StartSymbolIndex; pusch_pdu->nr_of_symbols = NrOfSymbols; + mapping_type = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment]->mappingType; if (ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment]->k2 != NULL) K2 = *ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment]->k2; @@ -848,8 +849,19 @@ void nr_schedule_uss_ulsch_phytest(int Mod_idP, pusch_pdu->mcs_table = 0; //0: notqam256 [TS38.214, table 5.1.3.1-1] - corresponds to nr_target_code_rate_table1 in PHY pusch_pdu->target_code_rate = nr_get_code_rate_ul(pusch_pdu->mcs_index,pusch_pdu->mcs_table) ; pusch_pdu->qam_mod_order = nr_get_Qm_ul(pusch_pdu->mcs_index,pusch_pdu->mcs_table) ; - pusch_pdu->transform_precoding = 0; - pusch_pdu->data_scrambling_id = 0; //It equals the higher-layer parameter Data-scrambling-Identity if configured and the RNTI equals the C-RNTI, otherwise L2 needs to set it to physical cell id.; + if (pusch_Config->transformPrecoder == NULL) { + if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL) + pusch_pdu->transform_precoding = 1; + else + pusch_pdu->transform_precoding = 0; + } + else + pusch_pdu->transform_precoding = *pusch_Config->transformPrecoder; + if (pusch_Config->dataScramblingIdentityPUSCH != NULL) + pusch_pdu->data_scrambling_id = *pusch_Config->dataScramblingIdentityPUSCH; + else + pusch_pdu->data_scrambling_id = *scc->physCellId; + pusch_pdu->nrOfLayers = 1; //Pusch Allocation in frequency domain [TS38.214, sec 6.1.2.2] @@ -862,51 +874,98 @@ void nr_schedule_uss_ulsch_phytest(int Mod_idP, AssertFatal(1==0,"Only frequency resource allocation type 1 is currently supported\n"); pusch_pdu->vrb_to_prb_mapping = 0; + if (pusch_Config->frequencyHopping==NULL) pusch_pdu->frequency_hopping = 0; else pusch_pdu->frequency_hopping = 1; + //pusch_pdu->tx_direct_current_location;//The uplink Tx Direct Current location for the carrier. Only values in the value range of this field between 0 and 3299, which indicate the subcarrier index within the carrier corresponding 1o the numerology of the corresponding uplink BWP and value 3300, which indicates "Outside the carrier" and value 3301, which indicates "Undetermined position within the carrier" are used. [TS38.331, UplinkTxDirectCurrentBWP IE] - pusch_pdu->uplink_frequency_shift_7p5khz = 0; + //pusch_pdu->uplink_frequency_shift_7p5khz = 0; // -------------------- // ------- DMRS ------- // -------------------- - uint16_t l_prime_mask = get_l_prime(pusch_pdu->nr_of_symbols, typeB, pusch_dmrs_pos0, pusch_len1); - pusch_pdu->ul_dmrs_symb_pos = l_prime_mask << pusch_pdu->start_symbol_index; - pusch_pdu->dmrs_config_type = 0; // dmrs-type 1 (the one with a single DMRS symbol in the beginning) - pusch_pdu->ul_dmrs_scrambling_id = 0; // If provided and the PUSCH is not a msg3 PUSCH, otherwise, L2 should set this to physical cell id - pusch_pdu->scid = 0; // DMRS sequence initialization [TS38.211, sec 6.4.1.1.1] - // Should match what is sent in DCI 0_1, otherwise set to 0 + NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig; + if (mapping_type == NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeA) + NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeA->choice.setup; + else + NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; + if (NR_DMRS_UplinkConfig->dmrs_Type == NULL) + pusch_pdu->dmrs_config_type = 0; + else + pusch_pdu->dmrs_config_type = 1; + pusch_pdu->scid = 0; // DMRS sequence initialization [TS38.211, sec 6.4.1.1.1] + if (pusch_pdu->transform_precoding) { // transform precoding disabled + long *scramblingid; + if (pusch_pdu->scid == 0) + scramblingid = NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID0; + else + scramblingid = NR_DMRS_UplinkConfig->transformPrecodingDisabled->scramblingID1; + if (scramblingid == NULL) + pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId; + else + pusch_pdu->ul_dmrs_scrambling_id = *scramblingid; + } + else { + pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId; + if (NR_DMRS_UplinkConfig->transformPrecodingEnabled->nPUSCH_Identity != NULL) + pusch_pdu->pusch_identity = *NR_DMRS_UplinkConfig->transformPrecodingEnabled->nPUSCH_Identity; + else + pusch_pdu->pusch_identity = *scc->physCellId; + } + pusch_dmrs_AdditionalPosition_t additional_pos; + if (NR_DMRS_UplinkConfig->dmrs_AdditionalPosition == NULL){printf("%d\n",2); + additional_pos = 2;} + else { + if (*NR_DMRS_UplinkConfig->dmrs_AdditionalPosition == NR_DMRS_UplinkConfig__dmrs_AdditionalPosition_pos3) + additional_pos = 3; + else + additional_pos = *NR_DMRS_UplinkConfig->dmrs_AdditionalPosition; + } + pusch_maxLength_t pusch_maxLength; + if (NR_DMRS_UplinkConfig->maxLength == NULL) + pusch_maxLength = 1; + else + pusch_maxLength = 2; + uint16_t l_prime_mask = get_l_prime(pusch_pdu->nr_of_symbols, mapping_type, additional_pos, pusch_maxLength); + pusch_pdu->ul_dmrs_symb_pos = l_prime_mask << pusch_pdu->start_symbol_index; + pusch_pdu->num_dmrs_cdm_grps_no_data = 1; - //pusch_pdu->dmrs_ports; // DMRS ports. [TS38.212 7.3.1.1.2] provides description between DCI 0-1 content and DMRS ports - // Bitmap occupying the 11 LSBs with: bit 0: antenna port 1000 bit 11: antenna port 1011, - // and for each bit 0: DMRS port not used 1: DMRS port used + pusch_pdu->dmrs_ports = 1; // -------------------------------------------------------------------------------------------------------------------------------------------- // -------------------- // ------- PTRS ------- // -------------------- - uint8_t ptrs_mcs1 = 2; // higher layer parameter in PTRS-UplinkConfig - uint8_t ptrs_mcs2 = 4; // higher layer parameter in PTRS-UplinkConfig - uint8_t ptrs_mcs3 = 10; // higher layer parameter in PTRS-UplinkConfig - uint16_t n_rb0 = 25; // higher layer parameter in PTRS-UplinkConfig - uint16_t n_rb1 = 75; // higher layer parameter in PTRS-UplinkConfig - pusch_pdu->pusch_ptrs.ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, pusch_pdu->mcs_index, pusch_pdu->mcs_table); - pusch_pdu->pusch_ptrs.ptrs_freq_density = get_K_ptrs(n_rb0, n_rb1, pusch_pdu->rb_size); - pusch_pdu->pusch_ptrs.ptrs_ports_list = (nfapi_nr_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ptrs_ports_t)); - pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0; + if (NR_DMRS_UplinkConfig->phaseTrackingRS != NULL) { + // TODO to be fixed from RRC config + uint8_t ptrs_mcs1 = 2; // higher layer parameter in PTRS-UplinkConfig + uint8_t ptrs_mcs2 = 4; // higher layer parameter in PTRS-UplinkConfig + uint8_t ptrs_mcs3 = 10; // higher layer parameter in PTRS-UplinkConfig + uint16_t n_rb0 = 25; // higher layer parameter in PTRS-UplinkConfig + uint16_t n_rb1 = 75; // higher layer parameter in PTRS-UplinkConfig + pusch_pdu->pusch_ptrs.ptrs_time_density = get_L_ptrs(ptrs_mcs1, ptrs_mcs2, ptrs_mcs3, pusch_pdu->mcs_index, pusch_pdu->mcs_table); + pusch_pdu->pusch_ptrs.ptrs_freq_density = get_K_ptrs(n_rb0, n_rb1, pusch_pdu->rb_size); + pusch_pdu->pusch_ptrs.ptrs_ports_list = (nfapi_nr_ptrs_ports_t *) malloc(2*sizeof(nfapi_nr_ptrs_ports_t)); + pusch_pdu->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset = 0; + + pusch_pdu->pdu_bit_map &= PUSCH_PDU_BITMAP_PUSCH_PTRS; // enable PUSCH PTRS + } + else{ +// if(1<pusch_ptrs.ptrs_time_density >= pusch_pdu->nr_of_symbols) + pusch_pdu->pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS + } - if(1<pusch_ptrs.ptrs_time_density >= pusch_pdu->nr_of_symbols) - pusch_pdu->pdu_bit_map &= ~PUSCH_PDU_BITMAP_PUSCH_PTRS; // disable PUSCH PTRS // -------------------------------------------------------------------------------------------------------------------------------------------- //Pusch Allocation in frequency domain [TS38.214, sec 6.1.2.2] //Optional Data only included if indicated in pduBitmap + // TODO from harq function as in pdsch pusch_pdu->pusch_data.rv_index = 0; pusch_pdu->pusch_data.harq_process_id = 0; - pusch_pdu->pusch_data.new_data_indicator = 0; + pusch_pdu->pusch_data.new_data_indicator = 1; uint8_t num_dmrs_symb = 0; diff --git a/openair2/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c index a99c1125e4..a7aa38dfe3 100644 --- a/openair2/RRC/NR/rrc_gNB_reconfig.c +++ b/openair2/RRC/NR/rrc_gNB_reconfig.c @@ -825,7 +825,8 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup = calloc(1,sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup)); NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup; NR_DMRS_UplinkConfig->dmrs_Type = NULL; - NR_DMRS_UplinkConfig->dmrs_AdditionalPosition =NR_DMRS_UplinkConfig__dmrs_AdditionalPosition_pos0; + NR_DMRS_UplinkConfig->dmrs_AdditionalPosition = calloc(1,sizeof(*NR_DMRS_UplinkConfig->dmrs_AdditionalPosition)); + *NR_DMRS_UplinkConfig->dmrs_AdditionalPosition = NR_DMRS_UplinkConfig__dmrs_AdditionalPosition_pos0; NR_DMRS_UplinkConfig->phaseTrackingRS=NULL; NR_DMRS_UplinkConfig->maxLength=NULL; NR_DMRS_UplinkConfig->transformPrecodingDisabled = calloc(1,sizeof(*NR_DMRS_UplinkConfig->transformPrecodingDisabled)); From bbca88ad78906d732fb067875f0a2787752488b4 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 11 Apr 2020 15:42:13 +0200 Subject: [PATCH 34/66] Bugfix FlexRAN: if a UE is in RRC but not S1AP, treat as no bug --- openair2/ENB_APP/flexran_agent_ran_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index 32cb8c74e1..abade20846 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -3644,7 +3644,7 @@ int flexran_get_s1ap_ue(mid_t mod_id, rnti_t rnti, Protocol__FlexS1apUe * ue_con RB_FOREACH(ue, s1ap_ue_map, &s1ap->s1ap_ue_head){ if (ue->eNB_ue_s1ap_id == enb_ue_s1ap_id) break; } - if (ue == NULL) return -1; + if (!ue) return 0; // UE does not exist: it might be connected but CN did not answer if (ue->mme_ref->mme_s1_ip.ipv4) ue_conf->mme_s1_ip = (char*) &ue->mme_ref->mme_s1_ip.ipv4_address[0]; From 40fdd53adcaf2dc61c2cc34991bea7074c7a114d Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 15 Apr 2020 21:25:42 +0200 Subject: [PATCH 35/66] Correctly decode IMSI also when not integrity protected --- openair2/RRC/LTE/rrc_eNB_S1AP.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/openair2/RRC/LTE/rrc_eNB_S1AP.c b/openair2/RRC/LTE/rrc_eNB_S1AP.c index 27a442ed05..9f92be366b 100644 --- a/openair2/RRC/LTE/rrc_eNB_S1AP.c +++ b/openair2/RRC/LTE/rrc_eNB_S1AP.c @@ -96,36 +96,34 @@ void extract_imsi(uint8_t *pdu_buf, uint32_t pdu_len, rrc_eNB_ue_context_t *ue_c && pdu_len > NAS_MESSAGE_SECURITY_HEADER_SIZE)) return; + /* Decode plain NAS message */ + EMM_msg *e_msg = &nas_msg.plain.emm; + emm_msg_header_t *emm_header = &e_msg->header; + if (header->security_header_type != SECURITY_HEADER_TYPE_NOT_PROTECTED) { /* Decode the message authentication code */ DECODE_U32((char *) pdu_buf+size, header->message_authentication_code, size); /* Decode the sequence number */ DECODE_U8((char *) pdu_buf+size, header->sequence_number, size); - } + /* Decode the security header type and the protocol discriminator */ + DECODE_U8(pdu_buf + size, *(uint8_t *)(emm_header), size); - /* Note: the value of the pointer (i.e. the address) is given by value, so we - * can modify it as we want. The callee retains the original address! */ + /* Check that this is the right message */ + if (emm_header->protocol_discriminator != EPS_MOBILITY_MANAGEMENT_MESSAGE) + return; + } pdu_buf += size; pdu_len -= size; - /* Decode plain NAS message */ - EMM_msg *e_msg = &nas_msg.plain.emm; - emm_msg_header_t *emm_header = &e_msg->header; - /* First decode the EMM message header */ - int e_head_size = 0; /* Check that buffer contains more than only the header */ if (pdu_len <= sizeof(emm_msg_header_t)) return; - /* Decode the security header type and the protocol discriminator */ - DECODE_U8(pdu_buf + e_head_size, *(uint8_t *)(emm_header), e_head_size); + /* First decode the EMM message header */ + int e_head_size = 0; /* Decode the message type */ DECODE_U8(pdu_buf + e_head_size, emm_header->message_type, e_head_size); - /* Check that this is the right message */ - if (emm_header->protocol_discriminator != EPS_MOBILITY_MANAGEMENT_MESSAGE) - return; - pdu_buf += e_head_size; pdu_len -= e_head_size; From 64f0b7e0e53094279ef87f20941fa11513fbf9eb Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 11 Apr 2020 00:20:24 +0200 Subject: [PATCH 36/66] Do not check for register_enb_pending The test seemingly ensures that this code block is hit only once. However, if we enable later activation of MMEs, it will be hit a second (and third, ...) time. The only thing in guards against, though, is an INIT message to the L1L2 thread, when register_enb_pending == 0, which should only be sent once. Therefore, functionality won't be changed if register_enb_pending becomes negative, and the assert can be removed. --- openair2/ENB_APP/enb_app.c | 1 - 1 file changed, 1 deletion(-) diff --git a/openair2/ENB_APP/enb_app.c b/openair2/ENB_APP/enb_app.c index 0e1c7e64bc..7c91e57813 100644 --- a/openair2/ENB_APP/enb_app.c +++ b/openair2/ENB_APP/enb_app.c @@ -273,7 +273,6 @@ void *eNB_app_task(void *args_p) { if (EPC_MODE_ENABLED) { LOG_I(ENB_APP, "[eNB %d] Received %s: associated MME %d\n", instance, ITTI_MSG_NAME (msg_p), S1AP_REGISTER_ENB_CNF(msg_p).nb_mme); - DevAssert(register_enb_pending > 0); register_enb_pending--; /* Check if at least eNB is registered with one MME */ From d47c539ddae4cd28d0a3254f67651b62565e7039 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 11 Apr 2020 00:23:40 +0200 Subject: [PATCH 37/66] S1AP: Only register MME if we do not know it yet --- openair3/S1AP/s1ap_eNB.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/openair3/S1AP/s1ap_eNB.c b/openair3/S1AP/s1ap_eNB.c index c228034245..c703501847 100644 --- a/openair3/S1AP/s1ap_eNB.c +++ b/openair3/S1AP/s1ap_eNB.c @@ -220,8 +220,21 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t * /* Trying to connect to provided list of MME ip address */ for (index = 0; index < s1ap_register_eNB->nb_mme; index++) { + net_ip_address_t *mme_ip = &s1ap_register_eNB->mme_ip_address[index]; + struct s1ap_eNB_mme_data_s *mme = NULL; + RB_FOREACH(mme, s1ap_mme_map, &new_instance->s1ap_mme_head) { + /* Compare whether IPv4 and IPv6 information is already present, in which + * wase we do not register again */ + if (mme->mme_s1_ip.ipv4 == mme_ip->ipv4 && (!mme_ip->ipv4 + || strncmp(mme->mme_s1_ip.ipv4_address, mme_ip->ipv4_address, 16) == 0) + && mme->mme_s1_ip.ipv6 == mme_ip->ipv6 && (!mme_ip->ipv6 + || strncmp(mme->mme_s1_ip.ipv6_address, mme_ip->ipv6_address, 46) == 0)) + break; + } + if (mme) + continue; s1ap_eNB_register_mme(new_instance, - &s1ap_register_eNB->mme_ip_address[index], + mme_ip, &s1ap_register_eNB->enb_ip_address, s1ap_register_eNB->sctp_in_streams, s1ap_register_eNB->sctp_out_streams, From e4eea33de6928ce5ad0c8fe40dba1f403f61f38d Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 10 Apr 2020 23:17:36 +0200 Subject: [PATCH 38/66] FlexRAN: Enable MME adding/removing --- .../CONTROL_MODULES/S1AP/flexran_agent_s1ap.c | 33 +++++++ .../CONTROL_MODULES/S1AP/flexran_agent_s1ap.h | 5 + openair2/ENB_APP/flexran_agent_common.c | 47 +++++----- openair2/ENB_APP/flexran_agent_ran_api.c | 91 +++++++++++++++++++ openair2/ENB_APP/flexran_agent_ran_api.h | 6 ++ 5 files changed, 160 insertions(+), 22 deletions(-) diff --git a/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.c b/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.c index 04a47406e1..d5fc5627a0 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.c +++ b/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.c @@ -125,6 +125,39 @@ void flexran_agent_s1ap_destroy_stats_reply(Protocol__FlexStatsReply *reply) { } } +void flexran_agent_handle_mme_update(mid_t mod_id, + size_t n_mme, + Protocol__FlexS1apMme **mme) { + if (n_mme == 0 || n_mme > 1) { + LOG_E(FLEXRAN_AGENT, "cannot handle %lu MMEs yet\n", n_mme); + return; + } + + if (!mme[0]->s1_ip) { + LOG_E(FLEXRAN_AGENT, "no S1 IP present, cannot handle request\n"); + return; + } + + if (mme[0]->has_state + && mme[0]->state == PROTOCOL__FLEX_MME_STATE__FLMMES_DISCONNECTED) { + int rc = flexran_remove_s1ap_mme(mod_id, 1, &mme[0]->s1_ip); + if (rc == 0) + LOG_I(FLEXRAN_AGENT, "remove MME at IP %s\n", mme[0]->s1_ip); + else + LOG_W(FLEXRAN_AGENT, + "could not remove MME: flexran_remove_s1ap_mme() returned %d\n", + rc); + } else { + int rc = flexran_add_s1ap_mme(mod_id, 1, &mme[0]->s1_ip); + if (rc == 0) + LOG_I(FLEXRAN_AGENT, "add MME at IP %s\n", mme[0]->s1_ip); + else + LOG_W(FLEXRAN_AGENT, + "could not add MME: flexran_add_s1ap_mme() returned %d\n", + rc); + } +} + int flexran_agent_register_s1ap_xface(mid_t mod_id) { if (agent_s1ap_xface[mod_id]) { LOG_E(FLEXRAN_AGENT, "S1AP agent CM for eNB %d is already registered\n", mod_id); diff --git a/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.h b/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.h index 1cca6ac9c1..54ea2926a8 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.h +++ b/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.h @@ -60,6 +60,11 @@ int flexran_agent_s1ap_stats_reply(mid_t mod_id, /* Free allocated S1AP stats message */ void flexran_agent_s1ap_destroy_stats_reply(Protocol__FlexStatsReply *reply); +/* Add or remove MME updates */ +void flexran_agent_handle_mme_update(mid_t mod_id, + size_t n_mme, + Protocol__FlexS1apMme **mme); + /* Register technology specific interface callbacks */ int flexran_agent_register_s1ap_xface(mid_t mod_id); diff --git a/openair2/ENB_APP/flexran_agent_common.c b/openair2/ENB_APP/flexran_agent_common.c index dc320ef974..ec0b780a3a 100644 --- a/openair2/ENB_APP/flexran_agent_common.c +++ b/openair2/ENB_APP/flexran_agent_common.c @@ -893,31 +893,34 @@ int flexran_agent_handle_enb_config_reply(mid_t mod_id, const void *params, Prot Protocol__FlexranMessage *input = (Protocol__FlexranMessage *)params; Protocol__FlexEnbConfigReply *enb_config = input->enb_config_reply_msg; - if (enb_config->n_cell_config == 0) { - LOG_W(FLEXRAN_AGENT, - "received enb_config_reply message does not contain a cell_config\n"); - *msg = NULL; - return 0; - } - if (enb_config->n_cell_config > 1) LOG_W(FLEXRAN_AGENT, "ignoring slice configs for other cell except cell 0\n"); - if (flexran_agent_get_mac_xface(mod_id) && enb_config->cell_config[0]->slice_config) { - prepare_update_slice_config(mod_id, enb_config->cell_config[0]->slice_config); - } else if (enb_config->cell_config[0]->has_eutra_band - && enb_config->cell_config[0]->has_dl_freq - && enb_config->cell_config[0]->has_ul_freq - && enb_config->cell_config[0]->has_dl_bandwidth) { - initiate_soft_restart(mod_id, enb_config->cell_config[0]); - } else if (flexran_agent_get_rrc_xface(mod_id) - && enb_config->cell_config[0]->has_x2_ho_net_control) { - LOG_I(FLEXRAN_AGENT, - "setting X2 HO NetControl to %d\n", - enb_config->cell_config[0]->x2_ho_net_control); - const int rc = flexran_set_x2_ho_net_control(mod_id, enb_config->cell_config[0]->x2_ho_net_control); - if (rc < 0) - LOG_E(FLEXRAN_AGENT, "Error in configuring X2 handover controlled by network"); + if (enb_config->n_cell_config > 0) { + if (flexran_agent_get_mac_xface(mod_id) && enb_config->cell_config[0]->slice_config) { + prepare_update_slice_config(mod_id, enb_config->cell_config[0]->slice_config); + } + if (enb_config->cell_config[0]->has_eutra_band + && enb_config->cell_config[0]->has_dl_freq + && enb_config->cell_config[0]->has_ul_freq + && enb_config->cell_config[0]->has_dl_bandwidth) { + initiate_soft_restart(mod_id, enb_config->cell_config[0]); + } + if (flexran_agent_get_rrc_xface(mod_id) + && enb_config->cell_config[0]->has_x2_ho_net_control) { + LOG_I(FLEXRAN_AGENT, + "setting X2 HO NetControl to %d\n", + enb_config->cell_config[0]->x2_ho_net_control); + const int rc = flexran_set_x2_ho_net_control(mod_id, enb_config->cell_config[0]->x2_ho_net_control); + if (rc < 0) + LOG_E(FLEXRAN_AGENT, "Error in configuring X2 handover controlled by network"); + } + } + + if (flexran_agent_get_s1ap_xface(mod_id) && enb_config->s1ap) { + flexran_agent_handle_mme_update(mod_id, + enb_config->s1ap->n_mme, + enb_config->s1ap->mme); } *msg = NULL; diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index abade20846..3306dfe61b 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -3634,6 +3634,97 @@ int flexran_get_s1ap_mme_conf(mid_t mod_id, mid_t mme_index, Protocol__FlexS1apM return 0; } +int flexran_add_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4) { + s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id); + if (!s1ap) return -1; + if (!rrc_is_present(mod_id)) return -2; + + /* Reconstruct S1AP_REGISTER_ENB_REQ */ + MessageDef *m = itti_alloc_new_message(TASK_FLEXRAN_AGENT, S1AP_REGISTER_ENB_REQ); + RCconfig_S1(m, mod_id); + + const int CC_id = 0; + eNB_RRC_INST *rrc = RC.rrc[CC_id]; + RrcConfigurationReq *conf = &rrc->configuration; + S1AP_REGISTER_ENB_REQ(m).num_plmn = conf->num_plmn; + for (int i = 0; i < conf->num_plmn; ++i) { + S1AP_REGISTER_ENB_REQ(m).mcc[i] = conf->mcc[i]; + S1AP_REGISTER_ENB_REQ(m).mnc[i] = conf->mnc[i]; + S1AP_REGISTER_ENB_REQ(m).mnc_digit_length[i] = conf->mnc_digit_length[i]; + } + + /* reconstruct MME list, it might have been updated since initial + * configuration */ + S1AP_REGISTER_ENB_REQ(m).nb_mme = 0; + struct s1ap_eNB_mme_data_s *mme = NULL; + RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head) { + const int n = S1AP_REGISTER_ENB_REQ(m).nb_mme; + S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4 = mme->mme_s1_ip.ipv4; + strcpy(S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4_address, mme->mme_s1_ip.ipv4_address); + S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv6 = mme->mme_s1_ip.ipv6; + strcpy(S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv6_address, mme->mme_s1_ip.ipv6_address); + S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_num[n] = mme->broadcast_plmn_num; + for (int i = 0; i < mme->broadcast_plmn_num; ++i) + S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_index[n][i] = mme->broadcast_plmn_index[i]; + S1AP_REGISTER_ENB_REQ(m).nb_mme += 1; + } + + if (S1AP_REGISTER_ENB_REQ(m).nb_mme + n_mme > S1AP_MAX_NB_MME_IP_ADDRESS) + return -1; + + for (int i = 0; i < n_mme; ++i) { + const int n = S1AP_REGISTER_ENB_REQ(m).nb_mme; + strcpy(S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4_address, mme_ipv4[0]); + S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv4 = 1; + S1AP_REGISTER_ENB_REQ(m).mme_ip_address[n].ipv6 = 0; + S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_num[n] = S1AP_REGISTER_ENB_REQ(m).num_plmn; + for (int i = 0; i < S1AP_REGISTER_ENB_REQ(m).num_plmn; ++i) + S1AP_REGISTER_ENB_REQ(m).broadcast_plmn_index[n][i] = i; + S1AP_REGISTER_ENB_REQ(m).nb_mme += 1; + } + + itti_send_msg_to_task (TASK_S1AP, ENB_MODULE_ID_TO_INSTANCE(mod_id), m); + + return 0; +} + +int flexran_remove_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4) { + s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id); + if (!s1ap) return -1; + struct s1ap_eNB_mme_data_s *mme = NULL; + RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head) { + if (mme->mme_s1_ip.ipv4 + && strncmp(mme->mme_s1_ip.ipv4_address, mme_ipv4[0], 16) == 0) + break; + } + if (!mme) + return -2; + + MessageDef *m = itti_alloc_new_message(TASK_FLEXRAN_AGENT, SCTP_CLOSE_ASSOCIATION); + SCTP_CLOSE_ASSOCIATION(m).assoc_id = mme->assoc_id; + itti_send_msg_to_task (TASK_SCTP, ENB_MODULE_ID_TO_INSTANCE(mod_id), m); + + switch (mme->state) { + case S1AP_ENB_STATE_WAITING: + s1ap->s1ap_mme_nb -= 1; + if (s1ap->s1ap_mme_pending_nb > 0) + s1ap->s1ap_mme_pending_nb -= 1; + break; + case S1AP_ENB_STATE_CONNECTED: + case S1AP_ENB_OVERLOAD: /* I am not sure the decrements are right here */ + s1ap->s1ap_mme_nb -= 1; + s1ap->s1ap_mme_associated_nb -= 1; + break; + case S1AP_ENB_STATE_DISCONNECTED: + default: + break; + } + RB_REMOVE(s1ap_mme_map, &s1ap->s1ap_mme_head, mme); + + return 0; +} + + int flexran_get_s1ap_ue(mid_t mod_id, rnti_t rnti, Protocol__FlexS1apUe * ue_conf){ if (!rrc_is_present(mod_id)) return -1; s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id); diff --git a/openair2/ENB_APP/flexran_agent_ran_api.h b/openair2/ENB_APP/flexran_agent_ran_api.h index ce32883852..3c2803d663 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.h +++ b/openair2/ENB_APP/flexran_agent_ran_api.h @@ -832,6 +832,12 @@ int flexran_get_s1ap_mme_conf(mid_t mod_id, mid_t mme_index, Protocol__FlexS1apM /* Get the S1AP UE conf */ int flexran_get_s1ap_ue(mid_t mod_id, rnti_t rnti, Protocol__FlexS1apUe * ue_conf); +/* Add MMEs and re-issue S1AP Registration Request */ +int flexran_add_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4); + +/* Remove MMEs and and cut SCTP to MME */ +int flexran_remove_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4); + /********************* general information *****************/ /* get an ID for this BS (or part of a BS) */ uint64_t flexran_get_bs_id(mid_t mod_id); From a1f77198f74701c07340f3f51e06cc830c834e60 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 11 Apr 2020 13:40:50 +0200 Subject: [PATCH 39/66] FlexRAN: Manage PLMNs --- .../CONTROL_MODULES/S1AP/flexran_agent_s1ap.c | 24 +++++++ .../CONTROL_MODULES/S1AP/flexran_agent_s1ap.h | 6 ++ openair2/ENB_APP/flexran_agent_common.c | 6 ++ openair2/ENB_APP/flexran_agent_ran_api.c | 71 +++++++++++++++++++ openair2/ENB_APP/flexran_agent_ran_api.h | 3 + 5 files changed, 110 insertions(+) diff --git a/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.c b/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.c index d5fc5627a0..c2d7cb9e55 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.c +++ b/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.c @@ -158,6 +158,30 @@ void flexran_agent_handle_mme_update(mid_t mod_id, } } +void flexran_agent_handle_plmn_update(mid_t mod_id, + int CC_id, + size_t n_plmn, + Protocol__FlexPlmn **plmn_id) { + if (n_plmn < 1 || n_plmn > 6) { + LOG_E(FLEXRAN_AGENT, "cannot handle %lu PLMNs\n", n_plmn); + return; + } + + /* We assume the controller has checked all the parameters within each + * plmn_id */ + int rc = flexran_set_new_plmn_id(mod_id, CC_id, n_plmn, plmn_id); + if (rc == 0) { + LOG_I(FLEXRAN_AGENT, "set %lu new PLMNs:\n", n_plmn); + for (int i = 0; i < (int)n_plmn; ++i) + LOG_I(FLEXRAN_AGENT, " MCC %d MNC %d MNC length %d\n", + plmn_id[i]->mcc, plmn_id[i]->mnc, plmn_id[0]->mnc_length); + } else { + LOG_W(FLEXRAN_AGENT, + "could not set new PLMN configuration: flexran_set_new_plmn_id() returned %d\n", + rc); + } +} + int flexran_agent_register_s1ap_xface(mid_t mod_id) { if (agent_s1ap_xface[mod_id]) { LOG_E(FLEXRAN_AGENT, "S1AP agent CM for eNB %d is already registered\n", mod_id); diff --git a/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.h b/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.h index 54ea2926a8..006eaa1d3c 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.h +++ b/openair2/ENB_APP/CONTROL_MODULES/S1AP/flexran_agent_s1ap.h @@ -65,6 +65,12 @@ void flexran_agent_handle_mme_update(mid_t mod_id, size_t n_mme, Protocol__FlexS1apMme **mme); +/* Set a new PLMN configuration */ +void flexran_agent_handle_plmn_update(mid_t mod_id, + int CC_id, + size_t n_plmn, + Protocol__FlexPlmn **plmn_id); + /* Register technology specific interface callbacks */ int flexran_agent_register_s1ap_xface(mid_t mod_id); diff --git a/openair2/ENB_APP/flexran_agent_common.c b/openair2/ENB_APP/flexran_agent_common.c index ec0b780a3a..e77b2fb386 100644 --- a/openair2/ENB_APP/flexran_agent_common.c +++ b/openair2/ENB_APP/flexran_agent_common.c @@ -915,6 +915,12 @@ int flexran_agent_handle_enb_config_reply(mid_t mod_id, const void *params, Prot if (rc < 0) LOG_E(FLEXRAN_AGENT, "Error in configuring X2 handover controlled by network"); } + if (flexran_agent_get_rrc_xface(mod_id) && enb_config->cell_config[0]->n_plmn_id > 0) { + flexran_agent_handle_plmn_update(mod_id, + 0, + enb_config->cell_config[0]->n_plmn_id, + enb_config->cell_config[0]->plmn_id); + } } if (flexran_agent_get_s1ap_xface(mod_id) && enb_config->s1ap) { diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index 3306dfe61b..0fcc51782e 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -3724,6 +3724,77 @@ int flexran_remove_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4) { return 0; } +int flexran_set_new_plmn_id(mid_t mod_id, int CC_id, size_t n_plmn, Protocol__FlexPlmn **plmn_id) { + if (!rrc_is_present(mod_id)) + return -1; + s1ap_eNB_instance_t *s1ap = s1ap_eNB_get_instance(mod_id); + if (!s1ap) + return -2; + + eNB_RRC_INST *rrc = RC.rrc[CC_id]; + RrcConfigurationReq *conf = &rrc->configuration; + + uint8_t num_plmn_old = conf->num_plmn; + uint16_t mcc[PLMN_LIST_MAX_SIZE]; + uint16_t mnc[PLMN_LIST_MAX_SIZE]; + uint8_t mnc_digit_length[PLMN_LIST_MAX_SIZE]; + for (int i = 0; i < num_plmn_old; ++i) { + mcc[i] = conf->mcc[i]; + mnc[i] = conf->mnc[i]; + mnc_digit_length[i] = conf->mnc_digit_length[i]; + } + + conf->num_plmn = (uint8_t) n_plmn; + for (int i = 0; i < conf->num_plmn; ++i) { + conf->mcc[i] = plmn_id[i]->mcc; + conf->mnc[i] = plmn_id[i]->mnc; + conf->mnc_digit_length[i] = plmn_id[i]->mnc_length; + } + + rrc_eNB_carrier_data_t *carrier = &rrc->carrier[CC_id]; + extern uint8_t do_SIB1(rrc_eNB_carrier_data_t *carrier, + int Mod_id, + int CC_id, + BOOLEAN_t brOption, + RrcConfigurationReq *configuration); + carrier->sizeof_SIB1 = do_SIB1(carrier, mod_id, CC_id, FALSE, conf); + if (carrier->sizeof_SIB1 < 0) + return -1337; /* SIB1 encoding failed, hell will probably break loose */ + + s1ap->num_plmn = (uint8_t) n_plmn; + for (int i = 0; i < conf->num_plmn; ++i) { + s1ap->mcc[i] = plmn_id[i]->mcc; + s1ap->mnc[i] = plmn_id[i]->mnc; + s1ap->mnc_digit_length[i] = plmn_id[i]->mnc_length; + } + + int bpn_failed = 0; + struct s1ap_eNB_mme_data_s *mme = NULL; + RB_FOREACH(mme, s1ap_mme_map, &s1ap->s1ap_mme_head) { + for (int i = 0; i < mme->broadcast_plmn_num; ++i) { + /* search the new index and update. If we don't find, we count this using + * bpn_failed to now how many broadcast_plmns could not be updated */ + int idx = mme->broadcast_plmn_index[i]; + int omcc = mcc[idx]; + int omnc = mnc[idx]; + int omncl = mnc_digit_length[idx]; + int j = 0; + for (j = 0; j < s1ap->num_plmn; ++j) { + if (s1ap->mcc[j] == omcc + && s1ap->mnc[j] == omnc + && s1ap->mnc_digit_length[j] == omncl) { + mme->broadcast_plmn_index[i] = j; + break; + } + } + if (j == s1ap->num_plmn) /* could not find the old PLMN in the new ones */ + bpn_failed++; + } + } + if (bpn_failed > 0) + return -10000 - bpn_failed; + return 0; +} int flexran_get_s1ap_ue(mid_t mod_id, rnti_t rnti, Protocol__FlexS1apUe * ue_conf){ if (!rrc_is_present(mod_id)) return -1; diff --git a/openair2/ENB_APP/flexran_agent_ran_api.h b/openair2/ENB_APP/flexran_agent_ran_api.h index 3c2803d663..9d1bfb9d3e 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.h +++ b/openair2/ENB_APP/flexran_agent_ran_api.h @@ -838,6 +838,9 @@ int flexran_add_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4); /* Remove MMEs and and cut SCTP to MME */ int flexran_remove_s1ap_mme(mid_t mod_id, size_t n_mme, char **mme_ipv4); +/* Set a new PLMN configuration */ +int flexran_set_new_plmn_id(mid_t mod_id, int CC_id, size_t n_plmn, Protocol__FlexPlmn **plmn_id); + /********************* general information *****************/ /* get an ID for this BS (or part of a BS) */ uint64_t flexran_get_bs_id(mid_t mod_id); From 332dec605ace8cfec771d3c578b335588563ac9e Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 14 Apr 2020 14:47:27 +0200 Subject: [PATCH 40/66] UE: Print all SIB1 decoded PLMNs --- openair2/RRC/LTE/rrc_UE.c | 65 +++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/openair2/RRC/LTE/rrc_UE.c b/openair2/RRC/LTE/rrc_UE.c index 4116f5367e..53348f5621 100644 --- a/openair2/RRC/LTE/rrc_UE.c +++ b/openair2/RRC/LTE/rrc_UE.c @@ -2794,44 +2794,43 @@ int decode_SIB1( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index, LTE_SystemInformationBlockType1_t *sib1 = UE_rrc_inst[ctxt_pP->module_id].sib1[eNB_index]; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SIB1, VCD_FUNCTION_IN ); LOG_I( RRC, "[UE %d] : Dumping SIB 1\n", ctxt_pP->module_id ); - LTE_PLMN_Identity_t *PLMN_identity = &sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->plmn_Identity; - int mccdigits = PLMN_identity->mcc->list.count; - int mncdigits = PLMN_identity->mnc.list.count; - int mcc; + const int n = sib1->cellAccessRelatedInfo.plmn_IdentityList.list.count; + for (int i = 0; i < n; ++i) { + LTE_PLMN_Identity_t *PLMN_identity = &sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[i]->plmn_Identity; + int mccdigits = PLMN_identity->mcc->list.count; + int mncdigits = PLMN_identity->mnc.list.count; - if (mccdigits == 2) { - mcc = *PLMN_identity->mcc->list.array[0]*10 + *PLMN_identity->mcc->list.array[1]; - } else { - mcc = *PLMN_identity->mcc->list.array[0]*100 + *PLMN_identity->mcc->list.array[1]*10 + *PLMN_identity->mcc->list.array[2]; + int mcc; + if (mccdigits == 2) { + mcc = *PLMN_identity->mcc->list.array[0]*10 + *PLMN_identity->mcc->list.array[1]; + } else { + mcc = *PLMN_identity->mcc->list.array[0]*100 + *PLMN_identity->mcc->list.array[1]*10 + *PLMN_identity->mcc->list.array[2]; + } + + int mnc; + if (mncdigits == 2) { + mnc = *PLMN_identity->mnc.list.array[0]*10 + *PLMN_identity->mnc.list.array[1]; + } else { + mnc = *PLMN_identity->mnc.list.array[0]*100 + *PLMN_identity->mnc.list.array[1]*10 + *PLMN_identity->mnc.list.array[2]; + } + + LOG_I( RRC, "PLMN %d MCC %0*d, MNC %0*d\n", i + 1, mccdigits, mcc, mncdigits, mnc); + // search internal table for provider name + int plmn_ind = 0; + + while (plmn_data[plmn_ind].mcc > 0) { + if ((plmn_data[plmn_ind].mcc == mcc) && (plmn_data[plmn_ind].mnc == mnc)) { + LOG_I( RRC, "Found %s (name from internal table)\n", plmn_data[plmn_ind].oper_short ); + break; + } + + plmn_ind++; + } } - - int mnc; - - if (mncdigits == 2) { - mnc = *PLMN_identity->mnc.list.array[0]*10 + *PLMN_identity->mnc.list.array[1]; - } else { - mnc = *PLMN_identity->mnc.list.array[0]*100 + *PLMN_identity->mnc.list.array[1]*10 + *PLMN_identity->mnc.list.array[2]; - } - - LOG_I( RRC, "PLMN MCC %0*d, MNC %0*d, TAC 0x%04x\n", mccdigits, mcc, mncdigits, mnc, + LOG_I( RRC, "TAC 0x%04x\n", ((sib1->cellAccessRelatedInfo.trackingAreaCode.size == 2)?((sib1->cellAccessRelatedInfo.trackingAreaCode.buf[0]<<8) + sib1->cellAccessRelatedInfo.trackingAreaCode.buf[1]):0)); LOG_I( RRC, "cellReservedForOperatorUse : raw:%ld decoded:%s\n", sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellReservedForOperatorUse, SIBreserved(sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->cellReservedForOperatorUse) ); - // search internal table for provider name - int plmn_ind = 0; - - while (plmn_data[plmn_ind].mcc > 0) { - if ((plmn_data[plmn_ind].mcc == mcc) && (plmn_data[plmn_ind].mnc == mnc)) { - LOG_I( RRC, "Found %s (name from internal table)\n", plmn_data[plmn_ind].oper_short ); - break; - } - - plmn_ind++; - } - - if (plmn_data[plmn_ind].mcc < 0) { - LOG_I( RRC, "Found Unknown operator (no entry in internal table)\n" ); - } LOG_I( RRC, "cellAccessRelatedInfo.cellIdentity : raw:%"PRIu32" decoded:%02x.%02x.%02x.%02x\n", BIT_STRING_to_uint32( &sib1->cellAccessRelatedInfo.cellIdentity ), From 19c2856bbe0bf3400262085c1e8ef5dc05fbd1b7 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 14 Apr 2020 14:47:59 +0200 Subject: [PATCH 41/66] UE: Set correct selected PLMN Identity --- openair2/RRC/LTE/MESSAGES/asn1_msg.c | 4 ++-- openair2/RRC/LTE/MESSAGES/asn1_msg.h | 6 +++++- openair2/RRC/LTE/rrc_UE.c | 26 +++++++++++++++++++++----- openair2/RRC/LTE/rrc_defs.h | 1 + 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/openair2/RRC/LTE/MESSAGES/asn1_msg.c b/openair2/RRC/LTE/MESSAGES/asn1_msg.c index 583e10da94..9ede543003 100644 --- a/openair2/RRC/LTE/MESSAGES/asn1_msg.c +++ b/openair2/RRC/LTE/MESSAGES/asn1_msg.c @@ -2310,7 +2310,7 @@ uint8_t do_SidelinkUEInformation(uint8_t Mod_id, uint8_t *buffer, LTE_SL_Destin return((enc_rval.encoded+7)/8); } -uint8_t do_RRCConnectionSetupComplete(uint8_t Mod_id, uint8_t *buffer, const uint8_t Transaction_id, const int dedicatedInfoNASLength, const char *dedicatedInfoNAS) { +uint8_t do_RRCConnectionSetupComplete(uint8_t Mod_id, uint8_t *buffer, const uint8_t Transaction_id, uint8_t sel_plmn_id, const int dedicatedInfoNASLength, const char *dedicatedInfoNAS) { asn_enc_rval_t enc_rval; LTE_UL_DCCH_Message_t ul_dcch_msg; LTE_RRCConnectionSetupComplete_t *rrcConnectionSetupComplete; @@ -2323,7 +2323,7 @@ uint8_t do_RRCConnectionSetupComplete(uint8_t Mod_id, uint8_t *buffer, const uin rrcConnectionSetupComplete->criticalExtensions.choice.c1.present = LTE_RRCConnectionSetupComplete__criticalExtensions__c1_PR_rrcConnectionSetupComplete_r8; rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.nonCriticalExtension=CALLOC(1, sizeof(*rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.nonCriticalExtension)); - rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.selectedPLMN_Identity= 1; + rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.selectedPLMN_Identity= sel_plmn_id; rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.registeredMME = NULL;//calloc(1,sizeof(*rrcConnectionSetupComplete->criticalExtensions.choice.c1.choice.rrcConnectionSetupComplete_r8.registeredMME)); /* diff --git a/openair2/RRC/LTE/MESSAGES/asn1_msg.h b/openair2/RRC/LTE/MESSAGES/asn1_msg.h index dda2340610..640d18a61f 100644 --- a/openair2/RRC/LTE/MESSAGES/asn1_msg.h +++ b/openair2/RRC/LTE/MESSAGES/asn1_msg.h @@ -142,7 +142,11 @@ uint8_t do_SidelinkUEInformation(uint8_t Mod_id, uint8_t *buffer, LTE_SL_Destina /** \brief Generate an RRCConnectionSetupComplete UL-DCCH-Message (UE) @param buffer Pointer to PER-encoded ASN.1 description of UL-DCCH-Message PDU @returns Size of encoded bit stream in bytes*/ -uint8_t do_RRCConnectionSetupComplete(uint8_t Mod_id, uint8_t *buffer, const uint8_t Transaction_id, const int dedicatedInfoNASLength, +uint8_t do_RRCConnectionSetupComplete(uint8_t Mod_id, + uint8_t *buffer, + const uint8_t Transaction_id, + uint8_t sel_plmn_id, + const int dedicatedInfoNASLength, const char *dedicatedInfoNAS); /** \brief Generate an RRCConnectionReconfigurationComplete UL-DCCH-Message (UE) diff --git a/openair2/RRC/LTE/rrc_UE.c b/openair2/RRC/LTE/rrc_UE.c index 53348f5621..bdf992c76a 100644 --- a/openair2/RRC/LTE/rrc_UE.c +++ b/openair2/RRC/LTE/rrc_UE.c @@ -128,8 +128,13 @@ static int decode_SIB1_MBMS( const protocol_ctxt_t *const ctxt_pP, const uint8_t * \param ctxt_pP Running context * \param eNB_index Index of corresponding eNB/CH * \param Transaction_id Transaction identifier + * \param sel_plmn_id selected PLMN Identity */ -static void rrc_ue_generate_RRCConnectionSetupComplete( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index, const uint8_t Transaction_id ); +static void rrc_ue_generate_RRCConnectionSetupComplete( + const protocol_ctxt_t *const ctxt_pP, + const uint8_t eNB_index, + const uint8_t Transaction_id, + uint8_t sel_plmn_id); /** \brief Generates/Encodes RRCConnectionReconfigurationComplete message at UE * \param ctxt_pP Running context @@ -367,6 +372,7 @@ char openair_rrc_ue_init( const module_id_t ue_mod_idP, const unsigned char eNB_ rrc_set_state (ue_mod_idP, RRC_STATE_INACTIVE); rrc_set_sub_state (ue_mod_idP, RRC_SUB_STATE_INACTIVE); LOG_I(RRC,"[UE %d] INIT State = RRC_IDLE (eNB %d)\n",ctxt.module_id,eNB_index); + UE_rrc_inst[ctxt.module_id].selected_plmn_identity = 1; UE_rrc_inst[ctxt.module_id].Info[eNB_index].State=RRC_IDLE; UE_rrc_inst[ctxt.module_id].Info[eNB_index].T300_active = 0; UE_rrc_inst[ctxt.module_id].Info[eNB_index].T304_active = 0; @@ -490,7 +496,11 @@ rrc_t310_expiration( } //----------------------------------------------------------------------------- -static void rrc_ue_generate_RRCConnectionSetupComplete( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index, const uint8_t Transaction_id ) { +static void rrc_ue_generate_RRCConnectionSetupComplete( + const protocol_ctxt_t *const ctxt_pP, + const uint8_t eNB_index, + const uint8_t Transaction_id, + uint8_t sel_plmn_id) { uint8_t buffer[100]; uint8_t size; const char *nas_msg; @@ -504,7 +514,7 @@ static void rrc_ue_generate_RRCConnectionSetupComplete( const protocol_ctxt_t *c nas_msg_length = sizeof(nas_attach_req_imsi); } - size = do_RRCConnectionSetupComplete(ctxt_pP->module_id, buffer, Transaction_id, nas_msg_length, nas_msg); + size = do_RRCConnectionSetupComplete(ctxt_pP->module_id, buffer, Transaction_id, sel_plmn_id, nas_msg_length, nas_msg); LOG_I(RRC,"[UE %d][RAPROC] Frame %d : Logical Channel UL-DCCH (SRB1), Generating RRCConnectionSetupComplete (bytes%d, eNB %d)\n", ctxt_pP->module_id,ctxt_pP->frame, size, eNB_index); LOG_D(RLC, @@ -624,7 +634,8 @@ int rrc_ue_decode_ccch( const protocol_ctxt_t *const ctxt_pP, const SRB_INFO *co rrc_ue_generate_RRCConnectionSetupComplete( ctxt_pP, eNB_index, - dl_ccch_msg->message.choice.c1.choice.rrcConnectionSetup.rrc_TransactionIdentifier); + dl_ccch_msg->message.choice.c1.choice.rrcConnectionSetup.rrc_TransactionIdentifier, + UE_rrc_inst[ctxt_pP->module_id].selected_plmn_identity); rval = 0; break; @@ -2969,6 +2980,7 @@ int decode_SIB1( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index, NAS_CELL_SELECTION_CNF (msg_p).rsrp = rsrp; itti_send_msg_to_task(TASK_NAS_UE, ctxt_pP->instance, msg_p); cell_valid = 1; + UE_rrc_inst[ctxt_pP->module_id].selected_plmn_identity = plmn + 1; break; } } @@ -2979,7 +2991,11 @@ int decode_SIB1( const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index, MessageDef *msg_p; msg_p = itti_alloc_new_message(TASK_RRC_UE, PHY_FIND_NEXT_CELL_REQ); itti_send_msg_to_task(TASK_PHY_UE, ctxt_pP->instance, msg_p); - LOG_E(RRC, "Synched with a cell, but PLMN doesn't match our SIM, the message PHY_FIND_NEXT_CELL_REQ is sent but lost in current UE implementation! \n"); + LOG_E(RRC, + "Synched with a cell, but PLMN doesn't match our SIM " + "(selected_plmn_identity %d), the message PHY_FIND_NEXT_CELL_REQ " + "is sent but lost in current UE implementation!\n", + UE_rrc_inst[ctxt_pP->module_id].selected_plmn_identity); } } diff --git a/openair2/RRC/LTE/rrc_defs.h b/openair2/RRC/LTE/rrc_defs.h index e366061674..3c02c45bc1 100644 --- a/openair2/RRC/LTE/rrc_defs.h +++ b/openair2/RRC/LTE/rrc_defs.h @@ -809,6 +809,7 @@ typedef struct UE_RRC_INST_s { Rrc_Sub_State_t RrcSubState; plmn_t plmnID; Byte_t rat; + uint8_t selected_plmn_identity; as_nas_info_t initialNasMsg; OAI_UECapability_t *UECap; uint8_t *UECapability; From a96c3761cc24101c1708b7bec465afa6dd553fed Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 21 May 2020 21:18:26 +0200 Subject: [PATCH 42/66] Log TBS in every window --- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 7621994ab2..2382af3636 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -588,6 +588,7 @@ schedule_ue_spec(module_id_t module_idP, UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; UE_TEMPLATE *ue_template = &UE_info->UE_template[CC_id][UE_id]; eNB_UE_STATS *eNB_UE_stats = &UE_info->eNB_UE_stats[CC_id][UE_id]; + eNB_UE_stats->TBS = 0; const rnti_t rnti = ue_template->rnti; // If TDD @@ -799,6 +800,7 @@ schedule_ue_spec(module_id_t module_idP, eNB_UE_stats->rbs_used_retx = nb_rb; eNB_UE_stats->total_rbs_used_retx += nb_rb; eNB_UE_stats->dlsch_mcs2 = eNB_UE_stats->dlsch_mcs1; + eNB_UE_stats->TBS = TBS; } else { // Now check RLC information to compute number of required RBs // get maximum TBS size for RLC request From d0baab6ed3ca0e618283620059faf28ae97ba832 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 12 Jun 2020 19:25:44 +0200 Subject: [PATCH 43/66] DLSCH: limit LC bytes according to preprocessor --- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 2382af3636..c35af34a7f 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -844,13 +844,18 @@ schedule_ue_spec(module_id_t module_idP, if (ue_sched_ctrl->dl_lc_bytes[i] == 0) // no data in this LC! continue; - LOG_D(MAC, "[eNB %d] SFN/SF %d.%d, LC%d->DLSCH CC_id %d, Requesting %d bytes from RLC (RRC message)\n", + const uint32_t data = + min(ue_sched_ctrl->dl_lc_bytes[i], + TBS - ta_len - header_length_total - sdu_length_total - 3); + LOG_D(MAC, + "[eNB %d] SFN/SF %d.%d, LC%d->DLSCH CC_id %d, Requesting %d " + "bytes from RLC (RRC message)\n", module_idP, frameP, subframeP, lcid, CC_id, - TBS - ta_len - header_length_total - sdu_length_total - 3); + data); sdu_lengths[num_sdus] = mac_rlc_data_req(module_idP, rnti, @@ -859,7 +864,7 @@ schedule_ue_spec(module_id_t module_idP, ENB_FLAG_YES, MBMS_FLAG_NO, lcid, - TBS - ta_len - header_length_total - sdu_length_total - 3, + data, (char *)&dlsch_buffer[sdu_length_total], 0, 0 From 82194319cfca0ef23c5a838f8d517faf424ed147 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 24 Jun 2020 14:24:02 +0200 Subject: [PATCH 44/66] Bugfix DLSCH: only warn when retx with less RB The preprocessor pre-allocates a CCE. Thus, when arriving at the check for the number of RBs for retransmission, it is too late to skip the UE. Therefore, only print a warning. The default schedulers allocate a correct amount of RBs for retransmissions, therefore it is ok. --- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index c35af34a7f..783d4e8b1a 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -680,15 +680,15 @@ schedule_ue_spec(module_id_t module_idP, const uint32_t rbc = allocate_prbs_sub( nb_rb, N_RB_DL, N_RBG, ue_sched_ctrl->rballoc_sub_UE[CC_id]); - if (nb_rb > ue_sched_ctrl->pre_nb_available_rbs[CC_id]) { - LOG_D(MAC, - "[eNB %d] Frame %d CC_id %d : don't schedule UE %d, its retransmission takes more resources than we have\n", + if (nb_rb > ue_sched_ctrl->pre_nb_available_rbs[CC_id]) + LOG_W(MAC, + "[eNB %d] %d.%d CC_id %d : should not schedule UE %d, its " + "retransmission takes more resources than we have\n", module_idP, frameP, + subframeP, CC_id, UE_id); - continue; - } /* CDRX */ ue_sched_ctrl->harq_rtt_timer[CC_id][harq_pid] = 1; // restart HARQ RTT timer From 864fa84ba80c99e831a7d9be5f88968a728a8efc Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 20 May 2020 12:45:35 +0200 Subject: [PATCH 45/66] Default SCHED RR algo: optimize algo and defer RB calc. - Loop only to next UE instead of jumping multiple - mark used RBGs in rbg_mask - Only calculate number of RBs based on CQI when UE is selected, instead of calculating for all UEs which might be unnecessary. - When looping the list of UEs for RB allocation, remove UEs that have no data anymore instead of skipping them. --- openair2/LAYER2/MAC/pre_processor.c | 72 ++++++++++------------------- 1 file changed, 25 insertions(+), 47 deletions(-) diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 4f3baf1783..62b9e1c2cc 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -86,9 +86,6 @@ int round_robin_dl(module_id_t Mod_id, int num_ue_req = 0; UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; - int rb_required[MAX_MOBILES_PER_ENB]; // how much UEs request - memset(rb_required, 0, sizeof(rb_required)); - int rbg = 0; for (; !rbgalloc_mask[rbg]; rbg++) ; /* fast-forward to first allowed RBG */ @@ -133,6 +130,7 @@ int round_robin_dl(module_id_t Mod_id, if (!rbgalloc_mask[rbg]) continue; ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1; + rbgalloc_mask[rbg] = 0; nb_rbg--; } LOG_D(MAC, @@ -150,22 +148,8 @@ int round_robin_dl(module_id_t Mod_id, return n_rbg_sched; for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; } else { - const int dlsch_mcs1 = cqi_to_mcs[UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]]; - UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = dlsch_mcs1; - rb_required[UE_id] = - find_nb_rb_DL(dlsch_mcs1, - UE_info->UE_template[CC_id][UE_id].dl_buffer_total, - n_rbg_sched * RBGsize, - RBGsize); - if (rb_required[UE_id] > 0) + if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total > 0) num_ue_req++; - LOG_D(MAC, - "%d/%d UE_id %d rb_required %d n_rbg_sched %d\n", - frame, - subframe, - UE_id, - rb_required[UE_id], - n_rbg_sched); } } @@ -178,12 +162,13 @@ int round_robin_dl(module_id_t Mod_id, g_start_ue_dl = UE_list->head; int UE_id = g_start_ue_dl; UE_list_t UE_sched; - int rb_required_total = 0; + int *cur_UE = &UE_sched.head; + int num_ue_sched = 0; max_num_ue = min(min(max_num_ue, num_ue_req), n_rbg_sched); - int *cur_UE = &UE_sched.head; + int rb_required[MAX_MOBILES_PER_ENB]; // how much UEs request while (num_ue_sched < max_num_ue) { - while (rb_required[UE_id] == 0) + while (UE_info->UE_template[CC_id][UE_id].dl_buffer_total <= 0) UE_id = next_ue_list_looped(UE_list, UE_id); const uint8_t cqi = UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]; const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi); @@ -195,42 +180,42 @@ int round_robin_dl(module_id_t Mod_id, continue; } UE_info->UE_sched_ctrl[UE_id].pre_dci_dl_pdu_idx = idx; + const int mcs = cqi_to_mcs[cqi]; + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = mcs; + const uint32_t B = UE_info->UE_template[CC_id][UE_id].dl_buffer_total; + rb_required[UE_id] = find_nb_rb_DL(mcs, B, n_rbg_sched * RBGsize, RBGsize); *cur_UE = UE_id; cur_UE = &UE_sched.next[UE_id]; - rb_required_total += rb_required[UE_id]; num_ue_sched++; UE_id = next_ue_list_looped(UE_list, UE_id); // next candidate } *cur_UE = -1; /* for one UE after the next: allocate resources */ - for (int UE_id = UE_sched.head; UE_id >= 0; - UE_id = next_ue_list_looped(&UE_sched, UE_id)) { - if (rb_required[UE_id] <= 0) - continue; + cur_UE = &UE_sched.head; + while (*cur_UE >= 0) { + const int UE_id = *cur_UE; UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id]; ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1; + rbgalloc_mask[rbg] = 0; const int sRBG = rbg == N_RBG - 1 ? RBGlastsize : RBGsize; ue_ctrl->pre_nb_available_rbs[CC_id] += sRBG; rb_required[UE_id] -= sRBG; - rb_required_total -= sRBG; - if (rb_required_total <= 0) - break; + if (rb_required[UE_id] <= 0) { + *cur_UE = UE_sched.next[*cur_UE]; + if (*cur_UE < 0) + cur_UE = &UE_sched.head; + } else { + cur_UE = UE_sched.next[*cur_UE] < 0 ? &UE_sched.head : &UE_sched.next[*cur_UE]; + } n_rbg_sched--; if (n_rbg_sched <= 0) break; for (rbg++; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; } - /* if not all UEs could be allocated in this round */ - if (num_ue_req > max_num_ue) { - /* go to the first one we missed */ - for (int i = 0; i < max_num_ue; ++i) - g_start_ue_dl = next_ue_list_looped(UE_list, g_start_ue_dl); - } else { - /* else, just start with the next UE next time */ - g_start_ue_dl = next_ue_list_looped(UE_list, g_start_ue_dl); - } + /* just start with the next UE next time */ + g_start_ue_dl = next_ue_list_looped(UE_list, g_start_ue_dl); return n_rbg_sched; } @@ -742,15 +727,8 @@ int round_robin_ul(module_id_t Mod_id, } } - /* if not all UEs could be allocated in this round */ - if (num_ue_req > max_num_ue) { - /* go to the first one we missed */ - for (int i = 0; i < max_num_ue; ++i) - g_start_ue_ul = next_ue_list_looped(UE_list, g_start_ue_ul); - } else { - /* else, just start with the next UE next time */ - g_start_ue_ul = next_ue_list_looped(UE_list, g_start_ue_ul); - } + /* just start with the next UE next time */ + g_start_ue_ul = next_ue_list_looped(UE_list, g_start_ue_ul); return rbs[0].length + (num_contig_rb > 1 ? rbs[1].length : 0); } From 8c7d94133f2400c836725484ec70820b9a10b1f0 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 24 Jun 2020 14:20:27 +0200 Subject: [PATCH 46/66] Bugfix RR DL: a retx UE might not be allocated again --- openair2/LAYER2/MAC/pre_processor.c | 68 ++++++++++++++--------------- 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 62b9e1c2cc..8324969a9c 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -83,15 +83,22 @@ int round_robin_dl(module_id_t Mod_id, const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); const int RBGsize = get_min_rb_unit(Mod_id, CC_id); const int RBGlastsize = get_rbg_size_last(Mod_id, CC_id); - int num_ue_req = 0; UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; int rbg = 0; for (; !rbgalloc_mask[rbg]; rbg++) ; /* fast-forward to first allowed RBG */ - // Calculate the amount of RBs every UE wants to send. - for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + /* just start with the UE after the one we had last time. If it does not + * exist, this will start at the head */ + int g_start_ue_dl = data; + g_start_ue_dl = next_ue_list_looped(UE_list, g_start_ue_dl); + + int UE_id = g_start_ue_dl; + UE_list_t UE_sched; + int *cur_UE = &UE_sched.head; + // Allocate retransmissions, and mark UEs with new transmissions + do { // check whether there are HARQ retransmissions const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id]; const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, frame, subframe); @@ -100,14 +107,14 @@ int round_robin_dl(module_id_t Mod_id, if (round != 8) { // retransmission: allocate const int nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid]; if (nb_rb == 0) - continue; + goto skip_ue; int nb_rbg = (nb_rb + (nb_rb % RBGsize)) / RBGsize; // needs more RBGs than we can allocate if (nb_rbg > n_rbg_sched) { LOG_D(MAC, "retransmission of UE %d needs more RBGs (%d) than we have (%d)\n", UE_id, nb_rbg, n_rbg_sched); - continue; + goto skip_ue; } // ensure that the number of RBs can be contained by the RBGs (!), i.e. // if we allocate the last RBG this one should have the full RBGsize @@ -116,12 +123,12 @@ int round_robin_dl(module_id_t Mod_id, LOG_D(MAC, "retransmission of UE %d needs %d RBs, but the last RBG %d is too small (%d, normal %d)\n", UE_id, nb_rb, N_RBG - 1, RBGlastsize, RBGsize); - continue; + goto skip_ue; } const uint8_t cqi = ue_ctrl->dl_cqi[CC_id]; const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi); if (idx < 0) - continue; // cannot allocate CCE + goto skip_ue; // cannot allocate CCE ue_ctrl->pre_dci_dl_pdu_idx = idx; // retransmissions: directly allocate n_rbg_sched -= nb_rbg; @@ -148,35 +155,32 @@ int round_robin_dl(module_id_t Mod_id, return n_rbg_sched; for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; } else { - if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total > 0) - num_ue_req++; + if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total > 0) { + *cur_UE = UE_id; + cur_UE = &UE_sched.next[UE_id]; + } } - } - if (num_ue_req == 0) +skip_ue: + UE_id = next_ue_list_looped(UE_list, UE_id); + } while (UE_id != g_start_ue_dl); + *cur_UE = -1; // mark end + + if (UE_sched.head < 0) return n_rbg_sched; // no UE has a transmission - // after allocating retransmissions: build list of UE to allocate. - // if start_UE does not exist anymore (detach etc), start at first UE - if (g_start_ue_dl == -1) - g_start_ue_dl = UE_list->head; - int UE_id = g_start_ue_dl; - UE_list_t UE_sched; - int *cur_UE = &UE_sched.head; - - int num_ue_sched = 0; - max_num_ue = min(min(max_num_ue, num_ue_req), n_rbg_sched); + // after allocating retransmissions: pre-allocate CCE, compute number of + // requested RBGs + max_num_ue = min(max_num_ue, n_rbg_sched); int rb_required[MAX_MOBILES_PER_ENB]; // how much UEs request - while (num_ue_sched < max_num_ue) { - while (UE_info->UE_template[CC_id][UE_id].dl_buffer_total <= 0) - UE_id = next_ue_list_looped(UE_list, UE_id); + cur_UE = &UE_sched.head; + while (*cur_UE >= 0 && max_num_ue > 0) { + const int UE_id = *cur_UE; + cur_UE = &UE_sched.next[UE_id]; // go to next const uint8_t cqi = UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]; const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi); if (idx < 0) { LOG_D(MAC, "cannot allocate CCE for UE %d, skipping\n", UE_id); - num_ue_req--; - max_num_ue = min(min(max_num_ue, num_ue_req), n_rbg_sched); - UE_id = next_ue_list_looped(UE_list, UE_id); // next candidate continue; } UE_info->UE_sched_ctrl[UE_id].pre_dci_dl_pdu_idx = idx; @@ -184,12 +188,9 @@ int round_robin_dl(module_id_t Mod_id, UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = mcs; const uint32_t B = UE_info->UE_template[CC_id][UE_id].dl_buffer_total; rb_required[UE_id] = find_nb_rb_DL(mcs, B, n_rbg_sched * RBGsize, RBGsize); - *cur_UE = UE_id; - cur_UE = &UE_sched.next[UE_id]; - num_ue_sched++; - UE_id = next_ue_list_looped(UE_list, UE_id); // next candidate + max_num_ue--; } - *cur_UE = -1; + *cur_UE = -1; // not all UEs might be allocated, mark end /* for one UE after the next: allocate resources */ cur_UE = &UE_sched.head; @@ -214,9 +215,6 @@ int round_robin_dl(module_id_t Mod_id, for (rbg++; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; } - /* just start with the next UE next time */ - g_start_ue_dl = next_ue_list_looped(UE_list, g_start_ue_dl); - return n_rbg_sched; } From 18a6961fcdc609b6f19017c9b9e8bb391aff522a Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 17 Jun 2020 11:05:35 +0200 Subject: [PATCH 47/66] Format to dynamically handle default DL SCHED algo --- openair2/LAYER2/MAC/mac.h | 15 +++++++ openair2/LAYER2/MAC/main.c | 6 ++- openair2/LAYER2/MAC/pre_processor.c | 69 +++++++++++++++++++---------- 3 files changed, 65 insertions(+), 25 deletions(-) diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h index 329e262c82..0264951683 100644 --- a/openair2/LAYER2/MAC/mac.h +++ b/openair2/LAYER2/MAC/mac.h @@ -1274,6 +1274,19 @@ typedef struct { int length; } contig_rbs_t; +/** + * definition of a scheduling algorithm implementation used in the + * default scheduler + */ +typedef struct { + char *name; + void *(*setup)(void); + void (*unset)(void **); + int (*run)( + module_id_t, int, int, int, UE_list_t *, int, int, uint8_t *, void *); + void *data; +} default_sched_dl_algo_t; + /*! \brief eNB common channels */ typedef struct { int physCellId; @@ -1432,6 +1445,8 @@ typedef struct eNB_MAC_INST_s { UE_free_list_t UE_free_list; /// for scheduling selection SCHEDULER_MODES scheduler_mode; + /// scheduling algorithm used in default scheduler + default_sched_dl_algo_t dl_algo; int32_t puSch10xSnr; int32_t puCch10xSnr; diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index 1a88623a1f..39e342cba0 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -128,7 +128,11 @@ void mac_top_init_eNB(void) } mac[i]->if_inst = IF_Module_init(i); - + char *s = "round_robin_dl"; + void *d = dlsym(NULL, s); + AssertFatal(d, "%s(): no scheduler algo '%s' found\n", __func__, s); + mac[i]->dl_algo = *(default_sched_dl_algo_t *) d; + mac[i]->dl_algo.data = mac[i]->dl_algo.setup(); init_UE_info(&mac[i]->UE_info); init_slice_info(&mac[i]->slice_info); } diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 8324969a9c..596e45ce2a 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -69,15 +69,26 @@ int get_rbg_size_last(module_id_t Mod_id, int CC_id) { return RBGsize; } -int g_start_ue_dl = -1; -int round_robin_dl(module_id_t Mod_id, - int CC_id, - int frame, - int subframe, - UE_list_t *UE_list, - int max_num_ue, - int n_rbg_sched, - uint8_t *rbgalloc_mask) { +void *rr_dl_setup(void) { + void *data = malloc(sizeof(int)); + *(int *) data = 0; + AssertFatal(data, "could not allocate data in %s()\n", __func__); + return data; +} +void rr_dl_unset(void **data) { + if (*data) + free(*data); + *data = NULL; +} +int rr_dl_run(module_id_t Mod_id, + int CC_id, + int frame, + int subframe, + UE_list_t *UE_list, + int max_num_ue, + int n_rbg_sched, + uint8_t *rbgalloc_mask, + void *data) { DevAssert(UE_list->head >= 0); DevAssert(n_rbg_sched > 0); const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); @@ -91,10 +102,10 @@ int round_robin_dl(module_id_t Mod_id, /* just start with the UE after the one we had last time. If it does not * exist, this will start at the head */ - int g_start_ue_dl = data; - g_start_ue_dl = next_ue_list_looped(UE_list, g_start_ue_dl); + int *start_ue = data; + *start_ue = next_ue_list_looped(UE_list, *start_ue); - int UE_id = g_start_ue_dl; + int UE_id = *start_ue; UE_list_t UE_sched; int *cur_UE = &UE_sched.head; // Allocate retransmissions, and mark UEs with new transmissions @@ -163,7 +174,7 @@ int round_robin_dl(module_id_t Mod_id, skip_ue: UE_id = next_ue_list_looped(UE_list, UE_id); - } while (UE_id != g_start_ue_dl); + } while (UE_id != *start_ue); *cur_UE = -1; // mark end if (UE_sched.head < 0) @@ -217,6 +228,14 @@ skip_ue: return n_rbg_sched; } +default_sched_dl_algo_t round_robin_dl = { + .name = "round_robin_dl", + .setup = rr_dl_setup, + .unset = rr_dl_unset, + .run = rr_dl_run, + .data = NULL +}; + // This function stores the downlink buffer for all the logical channels void @@ -306,8 +325,9 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, int CC_id, frame_t frameP, sub_frame_t subframeP) { - UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; - const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); + eNB_MAC_INST *mac = RC.mac[Mod_id]; + UE_info_t *UE_info = &mac->UE_info; + const int N_RBG = to_rbg(mac->common_channels[CC_id].mib->message.dl_Bandwidth); const int RBGsize = get_min_rb_unit(Mod_id, CC_id); store_dlsch_buffer(Mod_id, CC_id, frameP, subframeP); @@ -364,7 +384,7 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, if (UE_to_sched.head < 0) return; - uint8_t *vrb_map = RC.mac[Mod_id]->common_channels[CC_id].vrb_map; + uint8_t *vrb_map = mac->common_channels[CC_id].vrb_map; uint8_t rbgalloc_mask[N_RBG_MAX]; int n_rbg_sched = 0; for (int i = 0; i < N_RBG; i++) { @@ -376,14 +396,15 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, n_rbg_sched += rbgalloc_mask[i]; } - round_robin_dl(Mod_id, - CC_id, - frameP, - subframeP, - &UE_to_sched, - 4, // max_num_ue - n_rbg_sched, - rbgalloc_mask); + mac->dl_algo.run(Mod_id, + CC_id, + frameP, + subframeP, + &UE_to_sched, + 4, // max_num_ue + n_rbg_sched, + rbgalloc_mask, + mac->dl_algo.data); // the following block is meant for validation of the pre-processor to check // whether all UE allocations are non-overlapping and is not necessary for From 2de57fbc3658223daa0cd0aa21472a728b52a39b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 28 May 2020 16:17:52 +0200 Subject: [PATCH 48/66] Add Proportional Fair scheduler, wbCqi Selects UE with highest coefficient. Allocates until there are no more RBGs to allocate, or UE has no more data. In the latter case, continues with the next UE (second-highest coefficient). --- openair2/LAYER2/MAC/pre_processor.c | 164 ++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 596e45ce2a..dba6f3750f 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -237,6 +237,170 @@ default_sched_dl_algo_t round_robin_dl = { }; +void *pf_dl_setup(void) { + void *data = calloc(MAX_MOBILES_PER_ENB, sizeof(float)); + for (int i = 0; i < MAX_MOBILES_PER_ENB; i++) + *(float *) data = 0.0f; + AssertFatal(data, "could not allocate data in %s()\n", __func__); + return data; +} +void pf_dl_unset(void **data) { + if (*data) + free(*data); + *data = NULL; +} +int pf_wbcqi_dl_run(module_id_t Mod_id, + int CC_id, + int frame, + int subframe, + UE_list_t *UE_list, + int max_num_ue, + int n_rbg_sched, + uint8_t *rbgalloc_mask, + void *data) { + DevAssert(UE_list->head >= 0); + DevAssert(n_rbg_sched > 0); + const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); + const int RBGsize = get_min_rb_unit(Mod_id, CC_id); + const int RBGlastsize = get_rbg_size_last(Mod_id, CC_id); + UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; + + int rbg = 0; + for (; !rbgalloc_mask[rbg]; rbg++) + ; /* fast-forward to first allowed RBG */ + + UE_list_t UE_sched; // UEs that could be scheduled + int *uep = &UE_sched.head; + float *thr_ue = data; + float coeff_ue[MAX_MOBILES_PER_ENB]; + + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + const float a = 0.0005f; // corresponds to 200ms window + const uint32_t b = UE_info->eNB_UE_stats[CC_id][UE_id].TBS; + thr_ue[UE_id] = (1 - a) * thr_ue[UE_id] + a * b; + + // check whether there are HARQ retransmissions + const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id]; + const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, frame, subframe); + UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + const uint8_t round = ue_ctrl->round[CC_id][harq_pid]; + if (round != 8) { // retransmission: allocate + const int nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid]; + if (nb_rb == 0) + continue; + int nb_rbg = (nb_rb + (nb_rb % RBGsize)) / RBGsize; + // needs more RBGs than we can allocate + if (nb_rbg > n_rbg_sched) { + LOG_D(MAC, + "retransmission of UE %d needs more RBGs (%d) than we have (%d)\n", + UE_id, nb_rbg, n_rbg_sched); + continue; + } + // ensure that the number of RBs can be contained by the RBGs (!), i.e. + // if we allocate the last RBG this one should have the full RBGsize + if ((nb_rb % RBGsize) == 0 && nb_rbg == n_rbg_sched + && rbgalloc_mask[N_RBG - 1] && RBGlastsize != RBGsize) { + LOG_D(MAC, + "retransmission of UE %d needs %d RBs, but the last RBG %d is too small (%d, normal %d)\n", + UE_id, nb_rb, N_RBG - 1, RBGlastsize, RBGsize); + continue; + } + const uint8_t cqi = ue_ctrl->dl_cqi[CC_id]; + const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi); + if (idx < 0) + continue; // cannot allocate CCE + ue_ctrl->pre_dci_dl_pdu_idx = idx; + // retransmissions: directly allocate + n_rbg_sched -= nb_rbg; + ue_ctrl->pre_nb_available_rbs[CC_id] += nb_rb; + for (; nb_rbg > 0; rbg++) { + if (!rbgalloc_mask[rbg]) + continue; + ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1; + rbgalloc_mask[rbg] = 0; + nb_rbg--; + } + LOG_D(MAC, + "%4d.%d n_rbg_sched %d after retransmission reservation for UE %d " + "round %d retx nb_rb %d pre_nb_available_rbs %d\n", + frame, subframe, n_rbg_sched, UE_id, round, + UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid], + ue_ctrl->pre_nb_available_rbs[CC_id]); + /* if there are no more RBG to give, return */ + if (n_rbg_sched <= 0) + return 0; + max_num_ue--; + /* if there are no UEs that can be allocated anymore, return */ + if (max_num_ue == 0) + return n_rbg_sched; + for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; + } else { + if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total == 0) + continue; + + const int mcs = cqi_to_mcs[UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]]; + const uint32_t tbs = get_TBS_DL(mcs, RBGsize); + coeff_ue[UE_id] = (float) tbs / thr_ue[UE_id]; + //LOG_I(MAC, " pf UE %d: old TBS %d thr %f MCS %d TBS %d coeff %f\n", + // UE_id, b, thr_ue[UE_id], mcs, tbs, coeff_ue[UE_id]); + *uep = UE_id; + uep = &UE_sched.next[UE_id]; + } + } + *uep = -1; + + while (max_num_ue > 0 && n_rbg_sched > 0 && UE_sched.head >= 0) { + int *max = &UE_sched.head; /* assume head is max */ + int *p = &UE_sched.next[*max]; + while (*p >= 0) { + /* if the current one has larger coeff, save for later */ + if (coeff_ue[*p] > coeff_ue[*max]) + max = p; + p = &UE_sched.next[*p]; + } + /* remove the max one */ + const int UE_id = *max; + p = &UE_sched.next[*max]; + *max = UE_sched.next[*max]; + *p = -1; + + const uint8_t cqi = UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]; + const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi); + if (idx < 0) + continue; + UE_info->UE_sched_ctrl[UE_id].pre_dci_dl_pdu_idx = idx; + + max_num_ue--; + + /* allocate as much as possible */ + const int mcs = cqi_to_mcs[cqi]; + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = mcs; + int req = find_nb_rb_DL(mcs, + UE_info->UE_template[CC_id][UE_id].dl_buffer_total, + n_rbg_sched * RBGsize, + RBGsize); + UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + while (req > 0 && n_rbg_sched > 0) { + ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1; + rbgalloc_mask[rbg] = 0; + const int sRBG = rbg == N_RBG - 1 ? RBGlastsize : RBGsize; + ue_ctrl->pre_nb_available_rbs[CC_id] += sRBG; + req -= sRBG; + n_rbg_sched--; + for (rbg++; n_rbg_sched > 0 && !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; + } + } + + return n_rbg_sched; +} +default_sched_dl_algo_t proportional_fair_wbcqi_dl = { + .name = "proportional_fair_wbcqi_dl", + .setup = pf_dl_setup, + .unset = pf_dl_unset, + .run = pf_wbcqi_dl_run, + .data = NULL +}; + // This function stores the downlink buffer for all the logical channels void store_dlsch_buffer(module_id_t Mod_id, From fe7236d9c4bfd7f00508123075b367d18a210072 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 22 May 2020 16:43:24 +0200 Subject: [PATCH 49/66] Add Maximum Throughput scheduler, wbCqi Selects the UE with the highest CQI. If two UEs have the same CQI, choses the one with highest number of bytes in RLC queue. Allocates as many RBGs as possible, and potentially continues with the next UE. --- openair2/LAYER2/MAC/pre_processor.c | 150 ++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index dba6f3750f..436ec2435e 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -401,6 +401,156 @@ default_sched_dl_algo_t proportional_fair_wbcqi_dl = { .data = NULL }; +void *mt_dl_setup(void) { + return NULL; +} +void mt_dl_unset(void **data) { + *data = NULL; +} +int mt_wbcqi_dl_run(module_id_t Mod_id, + int CC_id, + int frame, + int subframe, + UE_list_t *UE_list, + int max_num_ue, + int n_rbg_sched, + uint8_t *rbgalloc_mask, + void *data) { + DevAssert(UE_list->head >= 0); + DevAssert(n_rbg_sched > 0); + const int N_RBG = to_rbg(RC.mac[Mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); + const int RBGsize = get_min_rb_unit(Mod_id, CC_id); + const int RBGlastsize = get_rbg_size_last(Mod_id, CC_id); + UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; + + int rbg = 0; + for (; !rbgalloc_mask[rbg]; rbg++) + ; /* fast-forward to first allowed RBG */ + + UE_list_t UE_sched; // UEs that could be scheduled + int *uep = &UE_sched.head; + + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) { + // check whether there are HARQ retransmissions + const COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id]; + const uint8_t harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config, frame, subframe); + UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + const uint8_t round = ue_ctrl->round[CC_id][harq_pid]; + if (round != 8) { // retransmission: allocate + const int nb_rb = UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid]; + if (nb_rb == 0) + continue; + int nb_rbg = (nb_rb + (nb_rb % RBGsize)) / RBGsize; + // needs more RBGs than we can allocate + if (nb_rbg > n_rbg_sched) { + LOG_D(MAC, + "retransmission of UE %d needs more RBGs (%d) than we have (%d)\n", + UE_id, nb_rbg, n_rbg_sched); + continue; + } + // ensure that the number of RBs can be contained by the RBGs (!), i.e. + // if we allocate the last RBG this one should have the full RBGsize + if ((nb_rb % RBGsize) == 0 && nb_rbg == n_rbg_sched + && rbgalloc_mask[N_RBG - 1] && RBGlastsize != RBGsize) { + LOG_D(MAC, + "retransmission of UE %d needs %d RBs, but the last RBG %d is too small (%d, normal %d)\n", + UE_id, nb_rb, N_RBG - 1, RBGlastsize, RBGsize); + continue; + } + const uint8_t cqi = ue_ctrl->dl_cqi[CC_id]; + const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi); + if (idx < 0) + continue; // cannot allocate CCE + ue_ctrl->pre_dci_dl_pdu_idx = idx; + // retransmissions: directly allocate + n_rbg_sched -= nb_rbg; + ue_ctrl->pre_nb_available_rbs[CC_id] += nb_rb; + for (; nb_rbg > 0; rbg++) { + if (!rbgalloc_mask[rbg]) + continue; + ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1; + rbgalloc_mask[rbg] = 0; + nb_rbg--; + } + LOG_D(MAC, + "%4d.%d n_rbg_sched %d after retransmission reservation for UE %d " + "round %d retx nb_rb %d pre_nb_available_rbs %d\n", + frame, subframe, n_rbg_sched, UE_id, round, + UE_info->UE_template[CC_id][UE_id].nb_rb[harq_pid], + ue_ctrl->pre_nb_available_rbs[CC_id]); + /* if there are no more RBG to give, return */ + if (n_rbg_sched <= 0) + return 0; + max_num_ue--; + /* if there are no UEs that can be allocated anymore, return */ + if (max_num_ue == 0) + return n_rbg_sched; + for (; !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; + } else { + if (UE_info->UE_template[CC_id][UE_id].dl_buffer_total == 0) + continue; + *uep = UE_id; + uep = &UE_sched.next[UE_id]; + } + } + *uep = -1; + + while (max_num_ue > 0 && n_rbg_sched > 0 && UE_sched.head >= 0) { + int *max = &UE_sched.head; /* assume head is max */ + int *p = &UE_sched.next[*max]; + while (*p >= 0) { + /* if the current one has better CQI, or the same and more data */ + const uint8_t maxCqi = UE_info->UE_sched_ctrl[*max].dl_cqi[CC_id]; + const uint32_t maxB = UE_info->UE_template[CC_id][*max].dl_buffer_total; + const uint8_t pCqi = UE_info->UE_sched_ctrl[*p].dl_cqi[CC_id]; + const uint32_t pB = UE_info->UE_template[CC_id][*p].dl_buffer_total; + if (pCqi > maxCqi || (pCqi == maxCqi && pB > maxB)) + max = p; + p = &UE_sched.next[*p]; + } + /* remove the max one */ + const int UE_id = *max; + p = &UE_sched.next[*max]; + *max = UE_sched.next[*max]; + *p = -1; + + const uint8_t cqi = UE_info->UE_sched_ctrl[UE_id].dl_cqi[CC_id]; + const int idx = CCE_try_allocate_dlsch(Mod_id, CC_id, subframe, UE_id, cqi); + if (idx < 0) + continue; + UE_info->UE_sched_ctrl[UE_id].pre_dci_dl_pdu_idx = idx; + + max_num_ue--; + + /* allocate as much as possible */ + const int mcs = cqi_to_mcs[cqi]; + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1 = mcs; + int req = find_nb_rb_DL(mcs, + UE_info->UE_template[CC_id][UE_id].dl_buffer_total, + n_rbg_sched * RBGsize, + RBGsize); + UE_sched_ctrl_t *ue_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + while (req > 0 && n_rbg_sched > 0) { + ue_ctrl->rballoc_sub_UE[CC_id][rbg] = 1; + rbgalloc_mask[rbg] = 0; + const int sRBG = rbg == N_RBG - 1 ? RBGlastsize : RBGsize; + ue_ctrl->pre_nb_available_rbs[CC_id] += sRBG; + req -= sRBG; + n_rbg_sched--; + for (rbg++; n_rbg_sched > 0 && !rbgalloc_mask[rbg]; rbg++) /* fast-forward */ ; + } + } + + return n_rbg_sched; +} +default_sched_dl_algo_t maximum_throughput_wbcqi_dl = { + .name = "maximum_throughput_wbcqi_dl", + .setup = mt_dl_setup, + .unset = mt_dl_unset, + .run = mt_wbcqi_dl_run, + .data = NULL +}; + // This function stores the downlink buffer for all the logical channels void store_dlsch_buffer(module_id_t Mod_id, From af89a6b780ce65ccb42f6b01b0a85d16450f0e58 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 17 Jun 2020 18:40:48 +0200 Subject: [PATCH 50/66] Configurable Default Scheduler DL Algo --- openair2/ENB_APP/MACRLC_paramdef.h | 3 +++ openair2/ENB_APP/enb_config.c | 10 ++++++++++ 2 files changed, 13 insertions(+) diff --git a/openair2/ENB_APP/MACRLC_paramdef.h b/openair2/ENB_APP/MACRLC_paramdef.h index 55ce9d5059..fcee6142f0 100644 --- a/openair2/ENB_APP/MACRLC_paramdef.h +++ b/openair2/ENB_APP/MACRLC_paramdef.h @@ -58,6 +58,7 @@ #define CONFIG_STRING_MACRLC_SCHED_MODE "scheduler_mode" #define CONFIG_MACRLC_PUSCH10xSNR "puSch10xSnr" #define CONFIG_MACRLC_PUCCH10xSNR "puCch10xSnr" +#define CONFIG_STRING_MACRLC_DEFAULT_SCHED_DL_ALGO "default_sched_dl_algo" /*-------------------------------------------------------------------------------------------------------------------------------------------------------*/ /* MacRLC configuration parameters */ @@ -84,6 +85,7 @@ {CONFIG_STRING_MACRLC_SCHED_MODE, NULL, 0, strptr:NULL, defstrval:"default", TYPE_STRING, 0}, \ {CONFIG_MACRLC_PUSCH10xSNR, NULL, 0, iptr:NULL, defintval:200, TYPE_INT, 0}, \ {CONFIG_MACRLC_PUCCH10xSNR, NULL, 0, iptr:NULL, defintval:200, TYPE_INT, 0}, \ +{CONFIG_STRING_MACRLC_DEFAULT_SCHED_DL_ALGO, NULL, 0, strptr:NULL, defstrval:"round_robin_dl", TYPE_STRING, 0}, \ } #define MACRLC_CC_IDX 0 #define MACRLC_TRANSPORT_N_PREFERENCE_IDX 1 @@ -105,6 +107,7 @@ #define MACRLC_SCHED_MODE_IDX 17 #define MACRLC_PUSCH10xSNR_IDX 18 #define MACRLC_PUCCH10xSNR_IDX 19 +#define MACRLC_DEFAULT_SCHED_DL_ALGO_IDX 20 /*---------------------------------------------------------------------------------------------------------------------------------------------------------*/ #endif diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 2200c8f013..0308c2fd79 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -29,6 +29,7 @@ #include #include +#include #include "common/utils/LOG/log.h" #include "assertions.h" @@ -260,6 +261,15 @@ void RCconfig_macrlc(int macrlc_has_f1[MAX_MAC_INST]) { global_scheduler_mode=SCHED_MODE_DEFAULT; printf("sched mode = default %d [%s]\n",global_scheduler_mode,*(MacRLC_ParamList.paramarray[j][MACRLC_SCHED_MODE_IDX].strptr)); } + + char *s = *MacRLC_ParamList.paramarray[j][MACRLC_DEFAULT_SCHED_DL_ALGO_IDX].strptr; + void *d = dlsym(NULL, s); + AssertFatal(d, "%s(): no default scheduler DL algo '%s' found\n", __func__, s); + // release default, add new + RC.mac[j]->dl_algo.unset(&RC.mac[j]->dl_algo.data); + RC.mac[j]->dl_algo = *(default_sched_dl_algo_t *) d; + RC.mac[j]->dl_algo.data = RC.mac[j]->dl_algo.setup(); + LOG_I(ENB_APP, "using default scheduler DL algo '%s'\n", RC.mac[j]->dl_algo.name); }// j=0..num_inst } /*else {// MacRLC_ParamList.numelt > 0 // ignore it From 6fcc4f59709708fc4f6862b9eb87264d1015a7fe Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 18 Jun 2020 17:32:01 +0200 Subject: [PATCH 51/66] Format to dynamically handle UL SCHED --- openair2/LAYER2/MAC/mac.h | 16 +++++- openair2/LAYER2/MAC/main.c | 5 ++ openair2/LAYER2/MAC/pre_processor.c | 79 ++++++++++++++++++----------- 3 files changed, 70 insertions(+), 30 deletions(-) diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h index 0264951683..09585fae55 100644 --- a/openair2/LAYER2/MAC/mac.h +++ b/openair2/LAYER2/MAC/mac.h @@ -1276,7 +1276,7 @@ typedef struct { /** * definition of a scheduling algorithm implementation used in the - * default scheduler + * default DL scheduler */ typedef struct { char *name; @@ -1287,6 +1287,19 @@ typedef struct { void *data; } default_sched_dl_algo_t; +/** + * definition of a scheduling algorithm implementation used in the + * default UL scheduler + */ +typedef struct { + char *name; + void *(*setup)(void); + void (*unset)(void **); + int (*run)( + module_id_t, int, int, int, int, int, UE_list_t *, int, int, contig_rbs_t *, void *); + void *data; +} default_sched_ul_algo_t; + /*! \brief eNB common channels */ typedef struct { int physCellId; @@ -1447,6 +1460,7 @@ typedef struct eNB_MAC_INST_s { SCHEDULER_MODES scheduler_mode; /// scheduling algorithm used in default scheduler default_sched_dl_algo_t dl_algo; + default_sched_ul_algo_t ul_algo; int32_t puSch10xSnr; int32_t puCch10xSnr; diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index 39e342cba0..294eb12159 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -133,6 +133,11 @@ void mac_top_init_eNB(void) AssertFatal(d, "%s(): no scheduler algo '%s' found\n", __func__, s); mac[i]->dl_algo = *(default_sched_dl_algo_t *) d; mac[i]->dl_algo.data = mac[i]->dl_algo.setup(); + s = "round_robin_ul"; + d = dlsym(NULL, s); + AssertFatal(d, "%s(): no scheduler algo '%s' found\n", __func__, s); + mac[i]->ul_algo = *(default_sched_ul_algo_t *) d; + mac[i]->ul_algo.data = mac[i]->ul_algo.setup(); init_UE_info(&mac[i]->UE_info); init_slice_info(&mac[i]->slice_info); } diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 436ec2435e..07bbed22c3 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -830,17 +830,28 @@ int pp_find_rb_table_index(int approximate) { return p + 1; } -int g_start_ue_ul = -1; -int round_robin_ul(module_id_t Mod_id, - int CC_id, - int frame, - int subframe, - int sched_frame, - int sched_subframe, - UE_list_t *UE_list, - int max_num_ue, - int num_contig_rb, - contig_rbs_t *rbs) { +void *rr_ul_setup(void) { + void *data = malloc(sizeof(int)); + *(int *) data = 0; + AssertFatal(data, "could not allocate data in %s()\n", __func__); + return data; +} +void rr_ul_unset(void **data) { + if (*data) + free(*data); + *data = NULL; +} +int rr_ul_run(module_id_t Mod_id, + int CC_id, + int frame, + int subframe, + int sched_frame, + int sched_subframe, + UE_list_t *UE_list, + int max_num_ue, + int num_contig_rb, + contig_rbs_t *rbs, + void *data) { AssertFatal(num_contig_rb <= 2, "cannot handle more than two contiguous RB regions\n"); UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; const int max_rb = num_contig_rb > 1 ? MAX(rbs[0].length, rbs[1].length) : rbs[0].length; @@ -980,9 +991,10 @@ int round_robin_ul(module_id_t Mod_id, end = la > lb ? 2 : -1; } - if (g_start_ue_ul == -1) - g_start_ue_ul = UE_list->head; - int sUE_id = g_start_ue_ul; + int *start_ue = data; + if (*start_ue == -1) + *start_ue = UE_list->head; + int sUE_id = *start_ue; int rb_idx_given[MAX_MOBILES_PER_ENB]; memset(rb_idx_given, 0, sizeof(rb_idx_given)); @@ -1061,10 +1073,17 @@ int round_robin_ul(module_id_t Mod_id, } /* just start with the next UE next time */ - g_start_ue_ul = next_ue_list_looped(UE_list, g_start_ue_ul); + *start_ue = next_ue_list_looped(UE_list, *start_ue); return rbs[0].length + (num_contig_rb > 1 ? rbs[1].length : 0); } +default_sched_ul_algo_t round_robin_ul = { + .name = "round_robin_ul", + .setup = rr_ul_setup, + .unset = rr_ul_unset, + .run = rr_ul_run, + .data = NULL +}; void ulsch_scheduler_pre_processor(module_id_t Mod_id, int CC_id, @@ -1072,9 +1091,10 @@ void ulsch_scheduler_pre_processor(module_id_t Mod_id, sub_frame_t subframeP, int sched_frameP, unsigned char sched_subframeP) { - UE_info_t *UE_info = &RC.mac[Mod_id]->UE_info; - const int N_RB_UL = to_prb(RC.mac[Mod_id]->common_channels[CC_id].ul_Bandwidth); - COMMON_channels_t *cc = &RC.mac[Mod_id]->common_channels[CC_id]; + eNB_MAC_INST *mac = RC.mac[Mod_id]; + UE_info_t *UE_info = &mac->UE_info; + const int N_RB_UL = to_prb(mac->common_channels[CC_id].ul_Bandwidth); + COMMON_channels_t *cc = &mac->common_channels[CC_id]; UE_list_t UE_to_sched; UE_to_sched.head = -1; @@ -1131,16 +1151,17 @@ void ulsch_scheduler_pre_processor(module_id_t Mod_id, } } - round_robin_ul(Mod_id, - CC_id, - frameP, - subframeP, - sched_frameP, - sched_subframeP, - &UE_to_sched, - 4, // max_num_ue - n_contig, - rbs); + mac->ul_algo.run(Mod_id, + CC_id, + frameP, + subframeP, + sched_frameP, + sched_subframeP, + &UE_to_sched, + 4, // max_num_ue + n_contig, + rbs, + mac->ul_algo.data); // the following block is meant for validation of the pre-processor to check // whether all UE allocations are non-overlapping and is not necessary for @@ -1159,7 +1180,7 @@ void ulsch_scheduler_pre_processor(module_id_t Mod_id, continue; print = 1; - uint8_t harq_pid = subframe2harqpid(&RC.mac[Mod_id]->common_channels[CC_id], + uint8_t harq_pid = subframe2harqpid(&mac->common_channels[CC_id], sched_frameP, sched_subframeP); LOG_D(MAC, "%4d.%d UE%d %d RBs (index %d) at start %d, pre MCS %d %s\n", frameP, From da09d63acdc1a4630ef683d2f7eabbb1952e0833 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 23 Jun 2020 10:27:45 +0200 Subject: [PATCH 52/66] Default pre-processor: efficiently build UE list --- openair2/LAYER2/MAC/pre_processor.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 07bbed22c3..d7dfc7816a 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -647,12 +647,10 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, store_dlsch_buffer(Mod_id, CC_id, frameP, subframeP); UE_list_t UE_to_sched; - UE_to_sched.head = -1; for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) UE_to_sched.next[i] = -1; + int *cur = &UE_to_sched.head; - int first = 1; - int last_UE_id = -1; for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; const UE_TEMPLATE *ue_template = &UE_info->UE_template[CC_id][UE_id]; @@ -685,15 +683,10 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, } /* define UEs to schedule */ - if (first) { - first = 0; - UE_to_sched.head = UE_id; - } else { - UE_to_sched.next[last_UE_id] = UE_id; - } - UE_to_sched.next[UE_id] = -1; - last_UE_id = UE_id; + *cur = UE_id; + cur = &UE_to_sched.next[UE_id]; } + *cur = -1; if (UE_to_sched.head < 0) return; @@ -1097,11 +1090,10 @@ void ulsch_scheduler_pre_processor(module_id_t Mod_id, COMMON_channels_t *cc = &mac->common_channels[CC_id]; UE_list_t UE_to_sched; - UE_to_sched.head = -1; for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) UE_to_sched.next[i] = -1; + int *cur = &UE_to_sched.head; - int last_UE_id = -1; for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { UE_TEMPLATE *UE_template = &UE_info->UE_template[CC_id][UE_id]; UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; @@ -1124,13 +1116,10 @@ void ulsch_scheduler_pre_processor(module_id_t Mod_id, continue; /* define UEs to schedule */ - if (UE_to_sched.head < 0) - UE_to_sched.head = UE_id; - else - UE_to_sched.next[last_UE_id] = UE_id; - UE_to_sched.next[UE_id] = -1; - last_UE_id = UE_id; + *cur = UE_id; + cur = &UE_to_sched.next[UE_id]; } + *cur = -1; if (UE_to_sched.head < 0) return; From 714a2df097f9792dc356d7033ed31374b09a289f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 12 Apr 2020 12:00:43 +0200 Subject: [PATCH 53/66] Remove any slice-related information from OAI --- .../CONTROL_MODULES/MAC/flexran_agent_mac.c | 13 - .../MAC/flexran_agent_mac_internal.c | 28 +- .../flexran_agent_mac_slice_verification.c | 4 +- openair2/ENB_APP/flexran_agent_ran_api.c | 314 ++---------------- openair2/LAYER2/MAC/mac.h | 104 ------ openair2/LAYER2/MAC/mac_proto.h | 2 - openair2/LAYER2/MAC/main.c | 27 -- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 2 - 8 files changed, 39 insertions(+), 455 deletions(-) diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c index 603ff25198..669eb33ea3 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c @@ -49,19 +49,6 @@ struct lfds700_misc_prng_state ps[NUM_MAX_ENB]; struct lfds700_ringbuffer_element *dl_mac_config_array[NUM_MAX_ENB]; struct lfds700_ringbuffer_state ringbuffer_state[NUM_MAX_ENB]; -/* the slice config as kept in the underlying system */ -Protocol__FlexSliceConfig *slice_config[MAX_NUM_SLICES]; -/* a structure that keeps updates which will be reflected in slice_config later */ -Protocol__FlexSliceConfig *sc_update[MAX_NUM_SLICES]; -/* indicates whether sc_update contains new data */ -int perform_slice_config_update_count = 1; -/* queue of incoming new UE<>slice association commands */ -Protocol__FlexUeConfig *ue_slice_assoc_update[MAX_NUM_SLICES]; -int n_ue_slice_assoc_updates = 0; -/* mutex for sc_update: do not receive new config and write it at the same time */ -pthread_mutex_t sc_update_mtx = PTHREAD_MUTEX_INITIALIZER; - - int flexran_agent_mac_stats_reply_ue(mid_t mod_id, Protocol__FlexUeStatsReport **ue_report, int n_ue, diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c index a85cbac543..84a28683b7 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c @@ -33,14 +33,6 @@ #include "flexran_agent_mac_internal.h" #include "flexran_agent_mac_slice_verification.h" -/* from flexran_agent_mac.c */ -extern Protocol__FlexSliceConfig *slice_config[MAX_NUM_SLICES]; -extern Protocol__FlexSliceConfig *sc_update[MAX_NUM_SLICES]; -extern int perform_slice_config_update_count; -extern Protocol__FlexUeConfig *ue_slice_assoc_update[MAX_NUM_SLICES]; -extern int n_ue_slice_assoc_updates; -extern pthread_mutex_t sc_update_mtx; - Protocol__FlexranMessage * flexran_agent_generate_diff_mac_stats_report(Protocol__FlexranMessage *new_message, Protocol__FlexranMessage *old_message) { @@ -1040,12 +1032,12 @@ Protocol__FlexSliceConfig *flexran_agent_create_slice_config(int n_dl, int m_ul) if (!fsc) return NULL; protocol__flex_slice_config__init(fsc); - /* say there are n_dl slices but reserve memory for up to MAX_NUM_SLICES so + /* say there are n_dl slices but reserve memory for up to 10 so * we don't need to reserve again later */ fsc->n_dl = n_dl; - fsc->dl = calloc(MAX_NUM_SLICES, sizeof(Protocol__FlexDlSlice *)); + fsc->dl = calloc(10, sizeof(Protocol__FlexDlSlice *)); if (!fsc->dl) fsc->n_dl = 0; - for (i = 0; i < MAX_NUM_SLICES; i++) { + for (i = 0; i < 10; i++) { fsc->dl[i] = malloc(sizeof(Protocol__FlexDlSlice)); if (!fsc->dl[i]) continue; protocol__flex_dl_slice__init(fsc->dl[i]); @@ -1053,9 +1045,9 @@ Protocol__FlexSliceConfig *flexran_agent_create_slice_config(int n_dl, int m_ul) /* as above */ fsc->n_ul = m_ul; - fsc->ul = calloc(MAX_NUM_SLICES, sizeof(Protocol__FlexUlSlice *)); + fsc->ul = calloc(10, sizeof(Protocol__FlexUlSlice *)); if (!fsc->ul) fsc->n_ul = 0; - for (i = 0; i < MAX_NUM_SLICES; i++) { + for (i = 0; i < 10; i++) { fsc->ul[i] = malloc(sizeof(Protocol__FlexUlSlice)); if (!fsc->ul[i]) continue; protocol__flex_ul_slice__init(fsc->ul[i]); @@ -1401,8 +1393,8 @@ Protocol__FlexDlSlice *create_new_dl_slice(mid_t mod_id, int id) mod_id, id); Protocol__FlexDlSlice *to = sc_update[mod_id]->dl[sc_update[mod_id]->n_dl]; sc_update[mod_id]->n_dl++; - AssertFatal(sc_update[mod_id]->n_dl <= MAX_NUM_SLICES, - "cannot create more than MAX_NUM_SLICES\n"); + AssertFatal(sc_update[mod_id]->n_dl <= 10, + "cannot create more than 10\n"); to->id = id; return to; } @@ -1468,8 +1460,8 @@ Protocol__FlexUlSlice *create_new_ul_slice(mid_t mod_id, int id) mod_id, id); Protocol__FlexUlSlice *to = sc_update[mod_id]->ul[sc_update[mod_id]->n_ul]; sc_update[mod_id]->n_ul++; - AssertFatal(sc_update[mod_id]->n_ul <= MAX_NUM_SLICES, - "cannot create more than MAX_NUM_SLICES\n"); + AssertFatal(sc_update[mod_id]->n_ul <= 10, + "cannot create more than 10\n"); to->id = id; return to; } @@ -1698,7 +1690,7 @@ int apply_new_slice_ul_config(mid_t mod_id, Protocol__FlexUlSlice *oldc, Protoco void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config) { - if (n_ue_slice_assoc_updates == MAX_NUM_SLICES) { + if (n_ue_slice_assoc_updates == 10) { LOG_E(FLEXRAN_AGENT, "[%d] can not handle flex_ue_config message, buffer is full; try again later\n", mod_id); diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c index 67329e91be..f7f60541f5 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c @@ -132,7 +132,7 @@ int flexran_verify_group_dl_slices(mid_t mod_id, Protocol__FlexDlSlice **existin /* else "only" an update */ } - if (n < 1 || n > MAX_NUM_SLICES) { + if (n < 1 || n > 10) { LOG_E(FLEXRAN_AGENT, "[%d] Illegal number of resulting DL slices (%d -> %d)\n", mod_id, n_ex, n); return 0; @@ -253,7 +253,7 @@ int flexran_verify_group_ul_slices(mid_t mod_id, Protocol__FlexUlSlice **existin /* else "only" an update */ } - if (n < 1 || n > MAX_NUM_SLICES) { + if (n < 1 || n > 10) { LOG_E(FLEXRAN_AGENT, "[%d] Illegal number of resulting UL slices (%d -> %d)\n", mod_id, n_ex, n); return 0; diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index 0fcc51782e..291c4dc7d8 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -3015,469 +3015,209 @@ uint32_t flexran_get_rrc_enb_ue_s1ap_id(mid_t mod_id, rnti_t rnti) /**************************** SLICING ****************************/ int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return -1; - - int slice_idx = 0; //RC.mac[mod_id]->UE_info.assoc_dl_slice_idx[ue_id]; - - if (slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_dl) - return RC.mac[mod_id]->slice_info.dl[slice_idx].id; - return 0; } void flexran_set_ue_dl_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx) { if (!mac_is_present(mod_id)) return; - - if (flexran_get_mac_ue_crnti(mod_id, ue_id) == NOT_A_RNTI) return; - - if (!flexran_dl_slice_exists(mod_id, slice_idx)) return; - - //RC.mac[mod_id]->UE_info.assoc_dl_slice_idx[ue_id] = slice_idx; } int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return -1; - - int slice_idx = 0; //RC.mac[mod_id]->UE_info.assoc_ul_slice_idx[ue_id]; - - if (slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_ul) - return RC.mac[mod_id]->slice_info.ul[slice_idx].id; - return 0; } void flexran_set_ue_ul_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx) { if (!mac_is_present(mod_id)) return; - - if (flexran_get_mac_ue_crnti(mod_id, ue_id) == NOT_A_RNTI) return; - - if (!flexran_ul_slice_exists(mod_id, slice_idx)) return; - - //RC.mac[mod_id]->UE_info.assoc_ul_slice_idx[ue_id] = slice_idx; } int flexran_dl_slice_exists(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - return slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_dl; + return 0; } int flexran_create_dl_slice(mid_t mod_id, slice_id_t slice_id) { if (!mac_is_present(mod_id)) return -1; - - int newidx = RC.mac[mod_id]->slice_info.n_dl; - - if (newidx >= MAX_NUM_SLICES) return -1; - - ++RC.mac[mod_id]->slice_info.n_dl; - flexran_set_dl_slice_id(mod_id, newidx, slice_id); - return newidx; + return -1; } int flexran_find_dl_slice(mid_t mod_id, slice_id_t slice_id) { if (!mac_is_present(mod_id)) return -1; - - slice_info_t *sli = &RC.mac[mod_id]->slice_info; - int n = sli->n_dl; - - for (int i = 0; i < n; i++) { - if (sli->dl[i].id == slice_id) return i; - } - return -1; } int flexran_remove_dl_slice(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - slice_info_t *sli = &RC.mac[mod_id]->slice_info; - - if (sli->n_dl <= 1) return -1; - - if (sli->dl[slice_idx].sched_name) free(sli->dl[slice_idx].sched_name); - - --sli->n_dl; - - /* move last element to the position of the removed one */ - if (slice_idx != sli->n_dl) - memcpy(&sli->dl[slice_idx], &sli->dl[sli->n_dl], sizeof(sli->dl[sli->n_dl])); - - memset(&sli->dl[sli->n_dl], 0, sizeof(sli->dl[sli->n_dl])); - /* all UEs that have been in the old slice are put into slice index 0 */ - //int *assoc_list = RC.mac[mod_id]->UE_info.assoc_dl_slice_idx; - - //for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) { - // if (assoc_list[i] == slice_idx) - // assoc_list[i] = 0; - //} - - return 1; + return -1; } int flexran_get_num_dl_slices(mid_t mod_id) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.n_dl; + return 0; } int flexran_get_intraslice_sharing_active(mid_t mod_id) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.intraslice_share_active; + return -1; } void flexran_set_intraslice_sharing_active(mid_t mod_id, int intraslice_active) { if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.intraslice_share_active = intraslice_active; } int flexran_get_interslice_sharing_active(mid_t mod_id) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.interslice_share_active; + return -1; } void flexran_set_interslice_sharing_active(mid_t mod_id, int interslice_active) { if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.interslice_share_active = interslice_active; } slice_id_t flexran_get_dl_slice_id(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.dl[slice_idx].id; + return -1; } void flexran_set_dl_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id) { if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.dl[slice_idx].id = slice_id; } int flexran_get_dl_slice_percentage(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.dl[slice_idx].pct * 100.0f; + return -1; } void flexran_set_dl_slice_percentage(mid_t mod_id, int slice_idx, int percentage) { if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.dl[slice_idx].pct = percentage / 100.0f; } int flexran_get_dl_slice_isolation(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.dl[slice_idx].isol; + return -1; } void flexran_set_dl_slice_isolation(mid_t mod_id, int slice_idx, int is_isolated) { if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.dl[slice_idx].isol = is_isolated; } int flexran_get_dl_slice_priority(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.dl[slice_idx].prio; + return -1; } void flexran_set_dl_slice_priority(mid_t mod_id, int slice_idx, int priority) { if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.dl[slice_idx].prio = priority; } int flexran_get_dl_slice_position_low(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.dl[slice_idx].pos_low; + return -1; } void flexran_set_dl_slice_position_low(mid_t mod_id, int slice_idx, int poslow) { if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.dl[slice_idx].pos_low = poslow; } int flexran_get_dl_slice_position_high(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.dl[slice_idx].pos_high; + return -1; } void flexran_set_dl_slice_position_high(mid_t mod_id, int slice_idx, int poshigh) { if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.dl[slice_idx].pos_high = poshigh; } int flexran_get_dl_slice_maxmcs(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.dl[slice_idx].maxmcs; + return -1; } void flexran_set_dl_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs) { if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.dl[slice_idx].maxmcs = maxmcs; } int flexran_get_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting **sorting_list) { if (!mac_is_present(mod_id)) return -1; - - if (!(*sorting_list)) { - *sorting_list = calloc(CR_NUM, sizeof(Protocol__FlexDlSorting)); - - if (!(*sorting_list)) return -1; - } - - uint32_t policy = RC.mac[mod_id]->slice_info.dl[slice_idx].sorting; - - for (int i = 0; i < CR_NUM; i++) { - switch (policy >> 4 * (CR_NUM - 1 - i) & 0xF) { - case CR_ROUND: - (*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_ROUND; - break; - - case CR_SRB12: - (*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_SRB12; - break; - - case CR_HOL: - (*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_HOL; - break; - - case CR_LC: - (*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_LC; - break; - - case CR_CQI: - (*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_CQI; - break; - - case CR_LCP: - (*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_LCP; - break; - - default: - /* this should not happen, but a "default" */ - (*sorting_list)[i] = PROTOCOL__FLEX_DL_SORTING__CR_ROUND; - break; - } - } - - return CR_NUM; + return -1; } void flexran_set_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting *sorting_list, int n) { if (!mac_is_present(mod_id)) return; - - uint32_t policy = 0; - - for (int i = 0; i < n && i < CR_NUM; i++) { - switch (sorting_list[i]) { - case PROTOCOL__FLEX_DL_SORTING__CR_ROUND: - policy = policy << 4 | CR_ROUND; - break; - - case PROTOCOL__FLEX_DL_SORTING__CR_SRB12: - policy = policy << 4 | CR_SRB12; - break; - - case PROTOCOL__FLEX_DL_SORTING__CR_HOL: - policy = policy << 4 | CR_HOL; - break; - - case PROTOCOL__FLEX_DL_SORTING__CR_LC: - policy = policy << 4 | CR_LC; - break; - - case PROTOCOL__FLEX_DL_SORTING__CR_CQI: - policy = policy << 4 | CR_CQI; - break; - - case PROTOCOL__FLEX_DL_SORTING__CR_LCP: - policy = policy << 4 | CR_LCP; - break; - - default: /* suppresses warnings */ - policy = policy << 4 | CR_ROUND; - break; - } - } - - /* fill up with 0 == CR_ROUND */ - if (CR_NUM > n) policy = policy << 4 * (CR_NUM - n); - - RC.mac[mod_id]->slice_info.dl[slice_idx].sorting = policy; } Protocol__FlexDlAccountingPolicy flexran_get_dl_slice_accounting_policy(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR; - - switch (RC.mac[mod_id]->slice_info.dl[slice_idx].accounting) { - case POL_FAIR: - return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR; - - case POL_GREEDY: - return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_GREEDY; - - default: - return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR; - } + return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR; } void flexran_set_dl_slice_accounting_policy(mid_t mod_id, int slice_idx, Protocol__FlexDlAccountingPolicy accounting) { if (!mac_is_present(mod_id)) return; - - switch (accounting) { - case PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR: - RC.mac[mod_id]->slice_info.dl[slice_idx].accounting = POL_FAIR; - return; - - case PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_GREEDY: - RC.mac[mod_id]->slice_info.dl[slice_idx].accounting = POL_GREEDY; - return; - - default: - RC.mac[mod_id]->slice_info.dl[slice_idx].accounting = POL_FAIR; - return; - } } char *flexran_get_dl_slice_scheduler(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return NULL; - - return RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name; + return NULL; } int flexran_set_dl_slice_scheduler(mid_t mod_id, int slice_idx, char *name) { if (!mac_is_present(mod_id)) return 0; - - if (RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name) - free(RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name); - - RC.mac[mod_id]->slice_info.dl[slice_idx].sched_name = strdup(name); - RC.mac[mod_id]->slice_info.dl[slice_idx].sched_cb = dlsym(NULL, name); - return RC.mac[mod_id]->slice_info.dl[slice_idx].sched_cb != NULL; + return 0; } int flexran_create_ul_slice(mid_t mod_id, slice_id_t slice_id) { if (!mac_is_present(mod_id)) return -1; - - int newidx = RC.mac[mod_id]->slice_info.n_ul; - - if (newidx >= MAX_NUM_SLICES) return -1; - - ++RC.mac[mod_id]->slice_info.n_ul; - flexran_set_ul_slice_id(mod_id, newidx, slice_id); - return newidx; + return -1; } int flexran_find_ul_slice(mid_t mod_id, slice_id_t slice_id) { if (!mac_is_present(mod_id)) return -1; - - slice_info_t *sli = &RC.mac[mod_id]->slice_info; - int n = sli->n_ul; - - for (int i = 0; i < n; i++) { - if (sli->ul[i].id == slice_id) return i; - } - return -1; } int flexran_remove_ul_slice(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - slice_info_t *sli = &RC.mac[mod_id]->slice_info; - - if (sli->n_ul <= 1) return -1; - - if (sli->ul[slice_idx].sched_name) free(sli->ul[slice_idx].sched_name); - - --sli->n_ul; - - /* move last element to the position of the removed one */ - if (slice_idx != sli->n_ul) - memcpy(&sli->ul[slice_idx], &sli->ul[sli->n_ul], sizeof(sli->ul[sli->n_ul])); - - memset(&sli->ul[sli->n_ul], 0, sizeof(sli->ul[sli->n_ul])); - /* all UEs that have been in the old slice are put into slice index 0 */ - //int *assoc_list = RC.mac[mod_id]->UE_info.assoc_ul_slice_idx; - - //for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) { - // if (assoc_list[i] == slice_idx) - // assoc_list[i] = 0; - //} - - return sli->n_ul; + return -1; } int flexran_get_num_ul_slices(mid_t mod_id) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.n_ul; + return 0; } int flexran_ul_slice_exists(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - return slice_idx >= 0 && slice_idx < RC.mac[mod_id]->slice_info.n_ul; + return 0; } slice_id_t flexran_get_ul_slice_id(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.ul[slice_idx].id; + return -1; } void flexran_set_ul_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id) { if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.ul[slice_idx].id = slice_id; } int flexran_get_ul_slice_percentage(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.ul[slice_idx].pct * 100.0f; + return -1; } void flexran_set_ul_slice_percentage(mid_t mod_id, int slice_idx, int percentage) { if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.ul[slice_idx].pct = percentage / 100.0f; } int flexran_get_ul_slice_first_rb(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.ul[slice_idx].first_rb; + return -1; } void flexran_set_ul_slice_first_rb(mid_t mod_id, int slice_idx, int first_rb) { if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.ul[slice_idx].first_rb = first_rb; } int flexran_get_ul_slice_maxmcs(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; - - return RC.mac[mod_id]->slice_info.ul[slice_idx].maxmcs; + return -1; } void flexran_set_ul_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs) { if (!mac_is_present(mod_id)) return; - - RC.mac[mod_id]->slice_info.ul[slice_idx].maxmcs = maxmcs; } char *flexran_get_ul_slice_scheduler(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return NULL; - - return RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name; + return ""; } int flexran_set_ul_slice_scheduler(mid_t mod_id, int slice_idx, char *name) { if (!mac_is_present(mod_id)) return 0; - - if (RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name) - free(RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name); - - RC.mac[mod_id]->slice_info.ul[slice_idx].sched_name = strdup(name); - RC.mac[mod_id]->slice_info.ul[slice_idx].sched_cb = dlsym(NULL, name); - return RC.mac[mod_id]->slice_info.ul[slice_idx].sched_cb != NULL; + return 0; } /************************** S1AP **************************/ diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h index 09585fae55..8349d84d48 100644 --- a/openair2/LAYER2/MAC/mac.h +++ b/openair2/LAYER2/MAC/mac.h @@ -155,9 +155,6 @@ /*!\brief minimum MAC data needed for transmitting 1 min RLC PDU size + 1 byte MAC subHeader */ #define MIN_MAC_HDR_RLC_SIZE (1 + MIN_RLC_PDU_SIZE) -/*!\brief maximum number of slices / groups */ -#define MAX_NUM_SLICES 10 - #define U_PLANE_INACTIVITY_VALUE 0 /* defined 10ms order (zero means infinity) */ @@ -1150,9 +1147,6 @@ typedef struct { UE_list_t list; int num_UEs; boolean_t active[MAX_MOBILES_PER_ENB]; - - /// Sorting criteria for the UE list in the MAC preprocessor - uint16_t sorting_criteria[MAX_NUM_SLICES][CR_NUM]; } UE_info_t; /*! \brief deleting control information*/ @@ -1171,101 +1165,6 @@ typedef struct { int tail_freelist; ///the tail position of the delete list } UE_free_list_t; -/** - * slice specific scheduler for the DL - */ -typedef void (*slice_scheduler_dl)(module_id_t mod_id, - int slice_idx, - frame_t frame, - sub_frame_t subframe, - int *mbsfn_flag); - -typedef struct { - slice_id_t id; - - /// RB share for each slice - float pct; - - /// whether this slice is isolated from the others - int isol; - - int prio; - - /// Frequency ranges for slice positioning - int pos_low; - int pos_high; - - // max mcs for each slice - int maxmcs; - - /// criteria for sorting policies of the slices - uint32_t sorting; - - /// Accounting policy (just greedy(1) or fair(0) setting for now) - int accounting; - - /// name of available scheduler - char *sched_name; - - /// pointer to the slice specific scheduler in DL - slice_scheduler_dl sched_cb; - -} slice_sched_conf_dl_t; - -typedef void (*slice_scheduler_ul)(module_id_t mod_id, - int slice_idx, - frame_t frame, - sub_frame_t subframe, - unsigned char sched_subframe, - uint16_t *first_rb); - -typedef struct { - slice_id_t id; - - /// RB share for each slice - float pct; - - // MAX MCS for each slice - int maxmcs; - - /// criteria for sorting policies of the slices - uint32_t sorting; - - /// starting RB (RB offset) of UL scheduling - int first_rb; - - /// name of available scheduler - char *sched_name; - - /// pointer to the slice specific scheduler in UL - slice_scheduler_ul sched_cb; - -} slice_sched_conf_ul_t; - - -typedef struct { - /// counter used to indicate when all slices have pre-allocated UEs - //int slice_counter; - - /// indicates whether remaining RBs after first intra-slice allocation will - /// be allocated to UEs of the same slice - int intraslice_share_active; - /// indicates whether remaining RBs after slice allocation will be - /// allocated to UEs of another slice. Isolated slices will be ignored - int interslice_share_active; - - /// number of active DL slices - int n_dl; - slice_sched_conf_dl_t dl[MAX_NUM_SLICES]; - - /// number of active UL slices - int n_ul; - slice_sched_conf_ul_t ul[MAX_NUM_SLICES]; - - /// common rb allocation list between slices - uint8_t rballoc_sub[NFAPI_CC_MAX][N_RBG_MAX]; -} slice_info_t; - /** * describes contiguous RBs */ @@ -1421,9 +1320,6 @@ typedef struct eNB_MAC_INST_s { uint32_t ul_handle; UE_info_t UE_info; - /// slice-related configuration - slice_info_t slice_info; - ///subband bitmap configuration SBMAP_CONF sbmap_conf; /// CCE table used to build DCI scheduling information diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index 2cb86c25af..61251ef088 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -187,8 +187,6 @@ void add_msg3(module_id_t module_idP, int CC_id, RA_t *ra, frame_t frameP, void init_UE_info(UE_info_t *UE_info); -void init_slice_info(slice_info_t *sli); - int mac_top_init(int eMBMS_active, char *uecap_xer, uint8_t cba_group_active, uint8_t HO_active); diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index 294eb12159..35b5136889 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -57,32 +57,6 @@ void init_UE_info(UE_info_t *UE_info) memset(UE_info->active, 0, sizeof(UE_info->active)); } -void init_slice_info(slice_info_t *sli) -{ - sli->intraslice_share_active = 1; - sli->interslice_share_active = 1; - - sli->n_dl = 1; - memset(sli->dl, 0, sizeof(slice_sched_conf_dl_t) * MAX_NUM_SLICES); - sli->dl[0].pct = 1.0; - sli->dl[0].prio = 10; - sli->dl[0].pos_high = N_RBG_MAX; - sli->dl[0].maxmcs = 28; - sli->dl[0].sorting = 0x012345; - sli->dl[0].sched_name = "schedule_ue_spec"; - sli->dl[0].sched_cb = dlsym(NULL, sli->dl[0].sched_name); - AssertFatal(sli->dl[0].sched_cb, "DLSCH scheduler callback is NULL\n"); - - sli->n_ul = 1; - memset(sli->ul, 0, sizeof(slice_sched_conf_ul_t) * MAX_NUM_SLICES); - sli->ul[0].pct = 1.0; - sli->ul[0].maxmcs = 20; - sli->ul[0].sorting = 0x0123; - sli->ul[0].sched_name = "schedule_ulsch_rnti"; - sli->ul[0].sched_cb = dlsym(NULL, sli->ul[0].sched_name); - AssertFatal(sli->ul[0].sched_cb, "ULSCH scheduler callback is NULL\n"); -} - void mac_top_init_eNB(void) { module_id_t i, j; @@ -139,7 +113,6 @@ void mac_top_init_eNB(void) mac[i]->ul_algo = *(default_sched_ul_algo_t *) d; mac[i]->ul_algo.data = mac[i]->ul_algo.setup(); init_UE_info(&mac[i]->UE_info); - init_slice_info(&mac[i]->slice_info); } RC.mac = mac; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index fc2a2e18cf..b73b074c37 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -68,8 +68,6 @@ extern RAN_CONTEXT_t RC; -extern int n_active_slices; - // Note the 2 scs values in the table names represent resp. scs_common and pdcch_scs /// LUT for the number of symbols in the coreset indexed by coreset index (4 MSB rmsi_pdcch_config) uint8_t nr_coreset_nsymb_pdcch_type_0_scs_15_15[15] = {2,2,2,3,3,3,1,1,2,2,3,3,1,2,3}; From a74f4c1238b03a31fafba5d1552f0b08ac184a3d Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 14 Apr 2020 16:17:56 +0200 Subject: [PATCH 54/66] Delete old protobuf slice types flex_slice_{dl,ul} --- .../CONTROL_MODULES/MAC/flexran_agent_mac.c | 206 +----- .../MAC/flexran_agent_mac_internal.c | 666 +----------------- .../MAC/flexran_agent_mac_internal.h | 20 - .../flexran_agent_mac_slice_verification.c | 343 --------- .../flexran_agent_mac_slice_verification.h | 6 - .../ENB_APP/MESSAGES/V2/config_common.proto | 77 -- .../ENB_APP/MESSAGES/V2/config_messages.proto | 8 - openair2/ENB_APP/flexran_agent_common.c | 20 +- openair2/ENB_APP/flexran_agent_ran_api.c | 178 +---- openair2/ENB_APP/flexran_agent_ran_api.h | 149 +--- 10 files changed, 47 insertions(+), 1626 deletions(-) diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c index 669eb33ea3..4800fccea9 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c @@ -1468,10 +1468,12 @@ void flexran_agent_fill_mac_ue_config(mid_t mod_id, mid_t ue_id, ue_conf->rnti = flexran_get_mac_ue_crnti(mod_id, ue_id); ue_conf->has_rnti = 1; - ue_conf->dl_slice_id = flexran_get_ue_dl_slice_id(mod_id, ue_id); - ue_conf->has_dl_slice_id = 1; - ue_conf->ul_slice_id = flexran_get_ue_ul_slice_id(mod_id, ue_id); - ue_conf->has_ul_slice_id = 1; + int dl_id = flexran_get_ue_dl_slice_id(mod_id, ue_id); + ue_conf->dl_slice_id = dl_id; + ue_conf->has_dl_slice_id = dl_id >= 0; + int ul_id = flexran_get_ue_ul_slice_id(mod_id, ue_id); + ue_conf->ul_slice_id = ul_id; + ue_conf->has_ul_slice_id = ul_id >= 0; ue_conf->ue_aggregated_max_bitrate_ul = flexran_get_ue_aggregated_max_bitrate_ul(mod_id, ue_id); ue_conf->has_ue_aggregated_max_bitrate_ul = 1; @@ -1576,149 +1578,24 @@ void flexran_create_config_structures(mid_t mod_id) sc_update[mod_id] = flexran_agent_create_slice_config(n_dl, m_ul); if (!slice_config[mod_id] || !sc_update[mod_id]) return; - flexran_agent_read_slice_config(mod_id, slice_config[mod_id]); - flexran_agent_read_slice_config(mod_id, sc_update[mod_id]); + //flexran_agent_read_slice_config(mod_id, slice_config[mod_id]); + //flexran_agent_read_slice_config(mod_id, sc_update[mod_id]); for (i = 0; i < n_dl; i++) { - flexran_agent_read_slice_dl_config(mod_id, i, slice_config[mod_id]->dl[i]); - flexran_agent_read_slice_dl_config(mod_id, i, sc_update[mod_id]->dl[i]); + //flexran_agent_read_slice_dl_config(mod_id, i, slice_config[mod_id]->dl[i]); + //flexran_agent_read_slice_dl_config(mod_id, i, sc_update[mod_id]->dl[i]); } for (i = 0; i < m_ul; i++) { - flexran_agent_read_slice_ul_config(mod_id, i, slice_config[mod_id]->ul[i]); - flexran_agent_read_slice_ul_config(mod_id, i, sc_update[mod_id]->ul[i]); + //flexran_agent_read_slice_ul_config(mod_id, i, slice_config[mod_id]->ul[i]); + //flexran_agent_read_slice_ul_config(mod_id, i, sc_update[mod_id]->ul[i]); } } void flexran_check_and_remove_slices(mid_t mod_id) { - Protocol__FlexDlSlice **dl = sc_update[mod_id]->dl; - Protocol__FlexDlSlice **dlreal = slice_config[mod_id]->dl; - int i = 0; - while (i < sc_update[mod_id]->n_dl) { - /* remove slices whose percentage is zero */ - if (dl[i]->percentage > 0) { - ++i; - continue; - } - if (flexran_remove_dl_slice(mod_id, i) < 1) { - LOG_W(FLEXRAN_AGENT, "[%d] can not remove slice index %d ID %d\n", - mod_id, i, dl[i]->id); - ++i; - continue; - } - LOG_I(FLEXRAN_AGENT, "[%d] removed slice index %d ID %d\n", - mod_id, i, dl[i]->id); - if (dl[i]->n_sorting > 0) free(dl[i]->sorting); - free(dl[i]->scheduler_name); - if (dlreal[i]->n_sorting > 0) { - dlreal[i]->n_sorting = 0; - free(dlreal[i]->sorting); - } - free(dlreal[i]->scheduler_name); - --sc_update[mod_id]->n_dl; - --slice_config[mod_id]->n_dl; - const size_t last = sc_update[mod_id]->n_dl; - /* we need to memcpy the higher slice to the position we just deleted */ - memcpy(dl[i], dl[last], sizeof(*dl[last])); - memset(dl[last], 0, sizeof(*dl[last])); - memcpy(dlreal[i], dlreal[last], sizeof(*dlreal[last])); - memset(dlreal[last], 0, sizeof(*dlreal[last])); - /* dont increase i but recheck the slice which has been copied to here */ - } - Protocol__FlexUlSlice **ul = sc_update[mod_id]->ul; - Protocol__FlexUlSlice **ulreal = slice_config[mod_id]->ul; - i = 0; - while (i < sc_update[mod_id]->n_ul) { - if (ul[i]->percentage > 0) { - ++i; - continue; - } - if (flexran_remove_ul_slice(mod_id, i) < 1) { - LOG_W(FLEXRAN_AGENT, "[%d] can not remove slice index %d ID %d\n", - mod_id, i, ul[i]->id); - ++i; - continue; - } - LOG_I(FLEXRAN_AGENT, "[%d] removed slice index %d ID %d\n", - mod_id, i, ul[i]->id); - free(ul[i]->scheduler_name); - free(ulreal[i]->scheduler_name); - --sc_update[mod_id]->n_ul; - --slice_config[mod_id]->n_ul; - const size_t last = sc_update[mod_id]->n_ul; - /* see DL remarks */ - memcpy(ul[i], ul[last], sizeof(*ul[last])); - memset(ul[last], 0, sizeof(*ul[last])); - memcpy(ulreal[i], ulreal[last], sizeof(*ulreal[last])); - memset(ulreal[last], 0, sizeof(*ulreal[last])); - /* dont increase i but recheck the slice which has been copied to here */ - } } void flexran_agent_slice_update(mid_t mod_id) { - int i; - int changes = 0; - - if (perform_slice_config_update_count <= 0) return; - perform_slice_config_update_count--; - - pthread_mutex_lock(&sc_update_mtx); - - if (!slice_config[mod_id]) { - /* if the configuration does not exist for agent, create from eNB structure - * and exit */ - flexran_create_config_structures(mod_id); - pthread_mutex_unlock(&sc_update_mtx); - return; - } - - /********* read existing config *********/ - /* simply update slice_config all the time and write new config - * (apply_new_slice_dl_config() only updates if changes are necessary) */ - slice_config[mod_id]->n_dl = flexran_get_num_dl_slices(mod_id); - slice_config[mod_id]->n_ul = flexran_get_num_ul_slices(mod_id); - for (i = 0; i < slice_config[mod_id]->n_dl; i++) { - flexran_agent_read_slice_dl_config(mod_id, i, slice_config[mod_id]->dl[i]); - } - for (i = 0; i < slice_config[mod_id]->n_ul; i++) { - flexran_agent_read_slice_ul_config(mod_id, i, slice_config[mod_id]->ul[i]); - } - - /********* write new config *********/ - /* check for removal (sc_update[X]->dl[Y].percentage == 0) - * and update sc_update & slice_config accordingly */ - flexran_check_and_remove_slices(mod_id); - - /* create new DL and UL slices if necessary */ - for (i = slice_config[mod_id]->n_dl; i < sc_update[mod_id]->n_dl; i++) { - flexran_create_dl_slice(mod_id, sc_update[mod_id]->dl[i]->id); - } - for (i = slice_config[mod_id]->n_ul; i < sc_update[mod_id]->n_ul; i++) { - flexran_create_ul_slice(mod_id, sc_update[mod_id]->ul[i]->id); - } - slice_config[mod_id]->n_dl = flexran_get_num_dl_slices(mod_id); - slice_config[mod_id]->n_ul = flexran_get_num_ul_slices(mod_id); - changes += apply_new_slice_config(mod_id, slice_config[mod_id], sc_update[mod_id]); - for (i = 0; i < slice_config[mod_id]->n_dl; i++) { - changes += apply_new_slice_dl_config(mod_id, - slice_config[mod_id]->dl[i], - sc_update[mod_id]->dl[i]); - flexran_agent_read_slice_dl_config(mod_id, i, slice_config[mod_id]->dl[i]); - } - for (i = 0; i < slice_config[mod_id]->n_ul; i++) { - changes += apply_new_slice_ul_config(mod_id, - slice_config[mod_id]->ul[i], - sc_update[mod_id]->ul[i]); - flexran_agent_read_slice_ul_config(mod_id, i, slice_config[mod_id]->ul[i]); - } - flexran_agent_read_slice_config(mod_id, slice_config[mod_id]); - if (n_ue_slice_assoc_updates > 0) { - changes += apply_ue_slice_assoc_update(mod_id); - } - if (changes > 0) - LOG_I(FLEXRAN_AGENT, "[%d] slice configuration: applied %d changes\n", mod_id, changes); - - pthread_mutex_unlock(&sc_update_mtx); } Protocol__FlexSliceConfig *flexran_agent_get_slice_config(mid_t mod_id) @@ -1727,69 +1604,10 @@ Protocol__FlexSliceConfig *flexran_agent_get_slice_config(mid_t mod_id) Protocol__FlexSliceConfig *config = NULL; pthread_mutex_lock(&sc_update_mtx); - config = flexran_agent_create_slice_config(slice_config[mod_id]->n_dl, - slice_config[mod_id]->n_ul); if (!config) { pthread_mutex_unlock(&sc_update_mtx); return NULL; } - config->has_intraslice_share_active = 1; - config->intraslice_share_active = slice_config[mod_id]->intraslice_share_active; - config->has_interslice_share_active = 1; - config->interslice_share_active = slice_config[mod_id]->interslice_share_active; - for (int i = 0; i < slice_config[mod_id]->n_dl; ++i) { - if (!config->dl[i]) continue; - config->dl[i]->has_id = 1; - config->dl[i]->id = slice_config[mod_id]->dl[i]->id; - config->dl[i]->has_label = 1; - config->dl[i]->label = slice_config[mod_id]->dl[i]->label; - config->dl[i]->has_percentage = 1; - config->dl[i]->percentage = slice_config[mod_id]->dl[i]->percentage; - config->dl[i]->has_isolation = 1; - config->dl[i]->isolation = slice_config[mod_id]->dl[i]->isolation; - config->dl[i]->has_priority = 1; - config->dl[i]->priority = slice_config[mod_id]->dl[i]->priority; - config->dl[i]->has_position_low = 1; - config->dl[i]->position_low = slice_config[mod_id]->dl[i]->position_low; - config->dl[i]->has_position_high = 1; - config->dl[i]->position_high = slice_config[mod_id]->dl[i]->position_high; - config->dl[i]->has_maxmcs = 1; - config->dl[i]->maxmcs = slice_config[mod_id]->dl[i]->maxmcs; - config->dl[i]->n_sorting = slice_config[mod_id]->dl[i]->n_sorting; - config->dl[i]->sorting = calloc(config->dl[i]->n_sorting, sizeof(Protocol__FlexDlSorting)); - if (!config->dl[i]->sorting) config->dl[i]->n_sorting = 0; - for (int j = 0; j < config->dl[i]->n_sorting; ++j) - config->dl[i]->sorting[j] = slice_config[mod_id]->dl[i]->sorting[j]; - config->dl[i]->has_accounting = 1; - config->dl[i]->accounting = slice_config[mod_id]->dl[i]->accounting; - config->dl[i]->scheduler_name = strdup(slice_config[mod_id]->dl[i]->scheduler_name); - } - for (int i = 0; i < slice_config[mod_id]->n_ul; ++i) { - if (!config->ul[i]) continue; - config->ul[i]->has_id = 1; - config->ul[i]->id = slice_config[mod_id]->ul[i]->id; - config->ul[i]->has_label = 1; - config->ul[i]->label = slice_config[mod_id]->ul[i]->label; - config->ul[i]->has_percentage = 1; - config->ul[i]->percentage = slice_config[mod_id]->ul[i]->percentage; - config->ul[i]->has_isolation = 1; - config->ul[i]->isolation = slice_config[mod_id]->ul[i]->isolation; - config->ul[i]->has_priority = 1; - config->ul[i]->priority = slice_config[mod_id]->ul[i]->priority; - config->ul[i]->has_first_rb = 1; - config->ul[i]->first_rb = slice_config[mod_id]->ul[i]->first_rb; - config->ul[i]->has_maxmcs = 1; - config->ul[i]->maxmcs = slice_config[mod_id]->ul[i]->maxmcs; - config->ul[i]->n_sorting = slice_config[mod_id]->ul[i]->n_sorting; - config->ul[i]->sorting = calloc(config->ul[i]->n_sorting, sizeof(Protocol__FlexUlSorting)); - if (!config->ul[i]->sorting) config->ul[i]->n_sorting = 0; - for (int j = 0; j < config->ul[i]->n_sorting; ++j) - config->ul[i]->sorting[j] = slice_config[mod_id]->ul[i]->sorting[j]; - config->ul[i]->has_accounting = 1; - config->ul[i]->accounting = slice_config[mod_id]->ul[i]->accounting; - config->ul[i]->scheduler_name = strdup(slice_config[mod_id]->ul[i]->scheduler_name); - } - pthread_mutex_unlock(&sc_update_mtx); return config; } diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c index 84a28683b7..4c80c561ee 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c @@ -1027,666 +1027,18 @@ int load_dl_scheduler_function(mid_t mod_id, const char *function_name) { Protocol__FlexSliceConfig *flexran_agent_create_slice_config(int n_dl, int m_ul) { - int i; Protocol__FlexSliceConfig *fsc = malloc(sizeof(Protocol__FlexSliceConfig)); if (!fsc) return NULL; protocol__flex_slice_config__init(fsc); - /* say there are n_dl slices but reserve memory for up to 10 so - * we don't need to reserve again later */ - fsc->n_dl = n_dl; - fsc->dl = calloc(10, sizeof(Protocol__FlexDlSlice *)); - if (!fsc->dl) fsc->n_dl = 0; - for (i = 0; i < 10; i++) { - fsc->dl[i] = malloc(sizeof(Protocol__FlexDlSlice)); - if (!fsc->dl[i]) continue; - protocol__flex_dl_slice__init(fsc->dl[i]); - } - - /* as above */ - fsc->n_ul = m_ul; - fsc->ul = calloc(10, sizeof(Protocol__FlexUlSlice *)); - if (!fsc->ul) fsc->n_ul = 0; - for (i = 0; i < 10; i++) { - fsc->ul[i] = malloc(sizeof(Protocol__FlexUlSlice)); - if (!fsc->ul[i]) continue; - protocol__flex_ul_slice__init(fsc->ul[i]); - } + /* TODO */ return fsc; } -void flexran_agent_read_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *s) -{ - s->intraslice_share_active = flexran_get_intraslice_sharing_active(mod_id); - s->has_intraslice_share_active = 1; - s->interslice_share_active = flexran_get_interslice_sharing_active(mod_id); - s->has_interslice_share_active = 1; -} - -void flexran_agent_read_slice_dl_config(mid_t mod_id, int slice_idx, Protocol__FlexDlSlice *dl_slice) -{ - dl_slice->id = flexran_get_dl_slice_id(mod_id, slice_idx); - dl_slice->has_id = 1; - /* read label from corresponding sc_update entry or give default */ - dl_slice->label = PROTOCOL__FLEX_SLICE_LABEL__xMBB; - dl_slice->has_label = 1; - for (int i = 0; i < sc_update[mod_id]->n_dl; i++) { - if (sc_update[mod_id]->dl[i]->id == dl_slice->id - && sc_update[mod_id]->dl[i]->has_label) { - dl_slice->label = sc_update[mod_id]->dl[i]->label; - break; - } - } - dl_slice->percentage = flexran_get_dl_slice_percentage(mod_id, slice_idx); - dl_slice->has_percentage = 1; - dl_slice->isolation = flexran_get_dl_slice_isolation(mod_id, slice_idx); - dl_slice->has_isolation = 1; - dl_slice->priority = flexran_get_dl_slice_priority(mod_id, slice_idx); - dl_slice->has_priority = 1; - dl_slice->position_low = flexran_get_dl_slice_position_low(mod_id, slice_idx); - dl_slice->has_position_low = 1; - dl_slice->position_high = flexran_get_dl_slice_position_high(mod_id, slice_idx); - dl_slice->has_position_high = 1; - dl_slice->maxmcs = flexran_get_dl_slice_maxmcs(mod_id, slice_idx); - dl_slice->has_maxmcs = 1; - dl_slice->n_sorting = flexran_get_dl_slice_sorting(mod_id, slice_idx, &dl_slice->sorting); - if (dl_slice->n_sorting < 1) dl_slice->sorting = NULL; - dl_slice->accounting = flexran_get_dl_slice_accounting_policy(mod_id, slice_idx); - dl_slice->has_accounting = 1; - const char *s_name = flexran_get_dl_slice_scheduler(mod_id, slice_idx); - if (!dl_slice->scheduler_name - || strcmp(dl_slice->scheduler_name, s_name) != 0) { - dl_slice->scheduler_name = realloc(dl_slice->scheduler_name, strlen(s_name) + 1); - strcpy(dl_slice->scheduler_name, s_name); - } -} - -void flexran_agent_read_slice_ul_config(mid_t mod_id, int slice_idx, Protocol__FlexUlSlice *ul_slice) -{ - ul_slice->id = flexran_get_ul_slice_id(mod_id, slice_idx); - ul_slice->has_id = 1; - /* read label from corresponding sc_update entry or give default */ - ul_slice->label = PROTOCOL__FLEX_SLICE_LABEL__xMBB; - ul_slice->has_label = 1; - for (int i = 0; i < sc_update[mod_id]->n_ul; i++) { - if (sc_update[mod_id]->ul[i]->id == ul_slice->id - && sc_update[mod_id]->ul[i]->has_label) { - ul_slice->label = sc_update[mod_id]->ul[i]->label; - break; - } - } - ul_slice->percentage = flexran_get_ul_slice_percentage(mod_id, slice_idx); - ul_slice->has_percentage = 1; - /*ul_slice->isolation = flexran_get_ul_slice_isolation(mod_id, slice_idx);*/ - ul_slice->has_isolation = 0; - /*ul_slice->priority = flexran_get_ul_slice_priority(mod_id, slice_idx);*/ - ul_slice->has_priority = 0; - ul_slice->first_rb = flexran_get_ul_slice_first_rb(mod_id, slice_idx); - ul_slice->has_first_rb = 1; - /*ul_slice-> = flexran_get_ul_slice_length_rb(mod_id, slice_idx); - ul_slice->has_length_rb = 0;*/ - ul_slice->maxmcs = flexran_get_ul_slice_maxmcs(mod_id, slice_idx); - ul_slice->has_maxmcs = 1; - ul_slice->n_sorting = 0; - /*if (ul_slice->sorting) { - free(ul_slice->sorting); - ul_slice->sorting = NULL; - } - ul_slice->n_sorting = flexran_get_ul_slice_sorting(mod_id, slice_idx, &ul_slice->sorting); - if (ul_slice->n_sorting < 1) ul_slice->sorting = NULL;*/ - /*ul_slice->accounting = flexran_get_ul_slice_accounting_policy(mod_id, slice_idx);*/ - ul_slice->has_accounting = 0; - const char *s_name = flexran_get_ul_slice_scheduler(mod_id, slice_idx); - if (!ul_slice->scheduler_name - || strcmp(ul_slice->scheduler_name, s_name) != 0) { - ul_slice->scheduler_name = realloc(ul_slice->scheduler_name, strlen(s_name) + 1); - strcpy(ul_slice->scheduler_name, s_name); - } -} - -int check_dl_sorting_update(Protocol__FlexDlSlice *old, Protocol__FlexDlSlice *new) -{ - /* sorting_update => true when old->n_sorting == 0 or different numbers of - * elements; otherwise will check * element-wise */ - int sorting_update = old->n_sorting == 0 || (old->n_sorting != new->n_sorting); - for (int i = 0; i < old->n_sorting && !sorting_update; ++i) { - sorting_update = sorting_update || (new->sorting[i] != old->sorting[i]); - } - return sorting_update; -} - -int check_ul_sorting_update(Protocol__FlexUlSlice *old, Protocol__FlexUlSlice *new) -{ - /* sorting_update => true when old->n_sorting == 0 or different numbers of - * elements; otherwise will check * element-wise */ - int sorting_update = old->n_sorting == 0 || (old->n_sorting != new->n_sorting); - for (int i = 0; i < old->n_sorting && !sorting_update; ++i) { - sorting_update = sorting_update || (new->sorting[i] != old->sorting[i]); - } - return sorting_update; -} - -void overwrite_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *exist, Protocol__FlexSliceConfig *update) -{ - if (update->has_intraslice_share_active - && exist->intraslice_share_active != update->intraslice_share_active) { - LOG_I(FLEXRAN_AGENT, "[%d] update intraslice_share_active: %d -> %d\n", - mod_id, exist->intraslice_share_active, update->intraslice_share_active); - exist->intraslice_share_active = update->intraslice_share_active; - exist->has_intraslice_share_active = 1; - } - if (update->has_interslice_share_active - && exist->interslice_share_active != update->interslice_share_active) { - LOG_I(FLEXRAN_AGENT, "[%d] update interslice_share_active: %d -> %d\n", - mod_id, exist->interslice_share_active, update->interslice_share_active); - exist->interslice_share_active = update->interslice_share_active; - exist->has_interslice_share_active = 1; - } -} - -void overwrite_slice_config_dl(mid_t mod_id, Protocol__FlexDlSlice *exist, Protocol__FlexDlSlice *update) -{ - if (update->label != exist->label) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update label: %d -> %d\n", - mod_id, update->id, exist->label, update->label); - exist->label = update->label; - exist->has_label = 1; - } - if (update->percentage != exist->percentage) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update percentage: %d -> %d\n", - mod_id, update->id, exist->percentage, update->percentage); - exist->percentage = update->percentage; - exist->has_percentage = 1; - } - if (update->isolation != exist->isolation) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update isolation: %d -> %d\n", - mod_id, update->id, exist->isolation, update->isolation); - exist->isolation = update->isolation; - exist->has_isolation = 1; - } - if (update->priority != exist->priority) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update priority: %d -> %d\n", - mod_id, update->id, exist->priority, update->priority); - exist->priority = update->priority; - exist->has_priority = 1; - } - if (update->position_low != exist->position_low) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update position_low: %d -> %d\n", - mod_id, update->id, exist->position_low, update->position_low); - exist->position_low = update->position_low; - exist->has_position_low = 1; - } - if (update->position_high != exist->position_high) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update position_high: %d -> %d\n", - mod_id, update->id, exist->position_high, update->position_high); - exist->position_high = update->position_high; - exist->has_position_high = 1; - } - if (update->maxmcs != exist->maxmcs) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update maxmcs: %d -> %d\n", - mod_id, update->id, exist->maxmcs, update->maxmcs); - exist->maxmcs = update->maxmcs; - exist->has_maxmcs = 1; - } - if (check_dl_sorting_update(exist, update)) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update sorting array\n", mod_id, update->id); - if (exist->n_sorting != update->n_sorting) { - exist->n_sorting = update->n_sorting; - exist->sorting = realloc(exist->sorting, exist->n_sorting * sizeof(Protocol__FlexDlSorting)); - if (!exist->sorting) exist->n_sorting = 0; - } - for (int i = 0; i < exist->n_sorting; i++) - exist->sorting[i] = update->sorting[i]; - } - if (update->accounting != exist->accounting) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update accounting: %d -> %d\n", - mod_id, update->id, exist->accounting, update->accounting); - exist->accounting = update->accounting; - exist->has_accounting = 1; - } - if (!exist->scheduler_name - || strcmp(update->scheduler_name, exist->scheduler_name) != 0) { - LOG_I(FLEXRAN_AGENT, "[%d][DL slice %d] update scheduler: %s -> %s\n", - mod_id, update->id, exist->scheduler_name, update->scheduler_name); - if (exist->scheduler_name) free(exist->scheduler_name); - exist->scheduler_name = strdup(update->scheduler_name); - } -} - -void overwrite_slice_config_ul(mid_t mod_id, Protocol__FlexUlSlice *exist, Protocol__FlexUlSlice *update) -{ - if (update->label != exist->label) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update label: %d -> %d\n", - mod_id, update->id, exist->label, update->label); - exist->label = update->label; - exist->has_label = 1; - } - if (update->percentage != exist->percentage) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update percentage: %d -> %d\n", - mod_id, update->id, exist->percentage, update->percentage); - exist->percentage = update->percentage; - exist->has_percentage = 1; - } - if (update->isolation != exist->isolation) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update isolation: %d -> %d\n", - mod_id, update->id, exist->isolation, update->isolation); - exist->isolation = update->isolation; - exist->has_isolation = 1; - } - if (update->priority != exist->priority) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update priority: %d -> %d\n", - mod_id, update->id, exist->priority, update->priority); - exist->priority = update->priority; - exist->has_priority = 1; - } - if (update->first_rb != exist->first_rb) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update first_rb: %d -> %d\n", - mod_id, update->id, exist->first_rb, update->first_rb); - exist->first_rb = update ->first_rb; - exist->has_first_rb = 1; - } - /*if (update->lenght_rb != exist->lenght_rb) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update lenght_rb: %d -> %d\n", - mod_id, update->id, exist->lenght_rb, update->lenght_rb); - exist->lenght_rb = update->lenght_rb; - }*/ - if (update->maxmcs != exist->maxmcs) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update maxmcs: %d -> %d\n", - mod_id, update->id, exist->maxmcs, update->maxmcs); - exist->maxmcs = update->maxmcs; - exist->has_maxmcs = 1; - } - /* TODO - int sorting_update = 0; - int n = min(exist->n_sorting, update->n_sorting); - int i = 0; - while (i < n && !sorting_update) { - sorting_update = sorting_update || (update->sorting[i] != exist->sorting[i]); - i++; - } - if (sorting_update) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update sorting array\n", update->id, mod_id); - if (exist->n_sorting != update->n_sorting) - LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] only writing %d elements\n", - mod_id, update->id, n); - for (i = 0; i < n; i++) - exist->sorting[i] = update->sorting[i]; - } - */ - if (update->accounting != exist->accounting) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update accounting: %d -> %d\n", - mod_id, update->id, exist->accounting, update->accounting); - exist->accounting = update->accounting; - exist->has_accounting = 1; - } - if (!exist->scheduler_name - || strcmp(update->scheduler_name, exist->scheduler_name) != 0) { - LOG_I(FLEXRAN_AGENT, "[%d][UL slice %d] update scheduler: %s -> %s\n", - mod_id, update->id, exist->scheduler_name, update->scheduler_name); - if (exist->scheduler_name) free(exist->scheduler_name); - exist->scheduler_name = strdup(update->scheduler_name); - } -} - -void fill_dl_slice(mid_t mod_id, Protocol__FlexDlSlice *s, Protocol__FlexDlSlice *from) -{ - /* function fills slice with information from another slice or with default - * values (currently slice 0) if from is NULL */ - /* TODO fill the slice depending on the chosen label */ - if (!s->has_label) { - s->has_label = 1; - s->label = from ? from->label : sc_update[mod_id]->dl[0]->label; - } - if (!s->has_percentage) { - s->has_percentage = 1; - s->percentage = from ? from->percentage : sc_update[mod_id]->dl[0]->percentage; - } - if (!s->has_isolation) { - s->has_isolation = 1; - s->isolation = from ? from->isolation : sc_update[mod_id]->dl[0]->isolation; - } - if (!s->has_priority) { - s->has_priority = 1; - s->priority = from ? from->priority : sc_update[mod_id]->dl[0]->priority; - } - if (!s->has_position_low) { - s->has_position_low = 1; - s->position_low = from ? from->position_low : sc_update[mod_id]->dl[0]->position_low; - } - if (!s->has_position_high) { - s->has_position_high = 1; - s->position_high = from ? from->position_high : sc_update[mod_id]->dl[0]->position_high; - } - if (!s->has_maxmcs) { - s->has_maxmcs = 1; - s->maxmcs = from ? from->maxmcs : sc_update[mod_id]->dl[0]->maxmcs; - } - if (s->n_sorting == 0) { - s->n_sorting = from ? from->n_sorting : sc_update[mod_id]->dl[0]->n_sorting; - s->sorting = calloc(s->n_sorting, sizeof(Protocol__FlexDlSorting)); - if (!s->sorting) s->n_sorting = 0; - for (int i = 0; i < s->n_sorting; ++i) - s->sorting[i] = from ? from->sorting[i] : sc_update[0]->dl[0]->sorting[i]; - } - if (!s->has_accounting) { - s->accounting = from ? from->accounting : sc_update[mod_id]->dl[0]->accounting; - } - if (!s->scheduler_name) { - s->scheduler_name = strdup(from ? from->scheduler_name : sc_update[mod_id]->dl[0]->scheduler_name); - } -} - -Protocol__FlexDlSlice *get_existing_dl_slice(mid_t mod_id, int id) -{ - for (int i = 0; i < sc_update[mod_id]->n_dl; ++i) { - if (id == sc_update[mod_id]->dl[i]->id) { - return sc_update[mod_id]->dl[i]; - } - } - return NULL; -} - -Protocol__FlexDlSlice *create_new_dl_slice(mid_t mod_id, int id) -{ - LOG_I(FLEXRAN_AGENT, - "[%d] Creating DL slice with ID %d, taking default values from DL slice 0\n", - mod_id, id); - Protocol__FlexDlSlice *to = sc_update[mod_id]->dl[sc_update[mod_id]->n_dl]; - sc_update[mod_id]->n_dl++; - AssertFatal(sc_update[mod_id]->n_dl <= 10, - "cannot create more than 10\n"); - to->id = id; - return to; -} - -void fill_ul_slice(mid_t mod_id, Protocol__FlexUlSlice *s, Protocol__FlexUlSlice *from) -{ - /* function fills slice with information from another slice or with default - * values (currently slice 0) if from is NULL */ - /* TODO fill the slice depending on the chosen label */ - if (!s->has_label) { - s->has_label = 1; - s->label = from ? from->label : sc_update[mod_id]->ul[0]->label; - } - if (!s->has_percentage) { - s->has_percentage = 1; - s->percentage = from ? from->percentage : sc_update[mod_id]->ul[0]->percentage; - } - if (!s->has_isolation) { - s->has_isolation = 1; - s->isolation = from ? from->isolation : sc_update[mod_id]->ul[0]->isolation; - } - if (!s->has_priority) { - s->has_priority = 1; - s->priority = from ? from->priority : sc_update[mod_id]->ul[0]->priority; - } - if (!s->has_first_rb) { - s->has_first_rb = 1; - s->first_rb = from ? from->first_rb : sc_update[mod_id]->ul[0]->first_rb; - } - if (!s->has_maxmcs) { - s->has_maxmcs = 1; - s->maxmcs = from ? from->maxmcs : sc_update[mod_id]->ul[0]->maxmcs; - } - if (s->n_sorting == 0) { - s->n_sorting = from ? from->n_sorting : sc_update[0]->ul[0]->n_sorting; - s->sorting = calloc(s->n_sorting, sizeof(Protocol__FlexUlSorting)); - if (!s->sorting) s->n_sorting = 0; - for (int i = 0; i < s->n_sorting; ++i) - s->sorting[i] = from ? from->sorting[i] : sc_update[0]->ul[0]->sorting[i]; - } - if (!s->has_accounting) { - s->accounting = from ? from->accounting : sc_update[0]->ul[0]->accounting; - } - if (!s->scheduler_name) { - s->scheduler_name = strdup(from ? from->scheduler_name : sc_update[mod_id]->ul[0]->scheduler_name); - } -} - -Protocol__FlexUlSlice *get_existing_ul_slice(mid_t mod_id, int id) -{ - for (int i = 0; i < sc_update[mod_id]->n_ul; ++i) { - if (id == sc_update[mod_id]->ul[i]->id) { - return sc_update[mod_id]->ul[i]; - } - } - return NULL; -} - -Protocol__FlexUlSlice *create_new_ul_slice(mid_t mod_id, int id) -{ - LOG_I(FLEXRAN_AGENT, - "[%d] Creating UL slice with ID %d, taking default values from UL slice 0\n", - mod_id, id); - Protocol__FlexUlSlice *to = sc_update[mod_id]->ul[sc_update[mod_id]->n_ul]; - sc_update[mod_id]->n_ul++; - AssertFatal(sc_update[mod_id]->n_ul <= 10, - "cannot create more than 10\n"); - to->id = id; - return to; -} - void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *sup) { - int verified = 1; - if (!sc_update[mod_id]) { - LOG_E(FLEXRAN_AGENT, "Can not update slice policy (no existing slice profile)\n"); - return; - } - - pthread_mutex_lock(&sc_update_mtx); - /* no need for tests in the current state as there are only two protobuf - * bools for intra-/interslice sharing. The function applies new values if - * applicable */ - overwrite_slice_config(mod_id, sc_update[mod_id], sup); - - if (sup->n_dl == 0) { - LOG_I(FLEXRAN_AGENT, "[%d] no DL slice configuration in flex_slice_config message\n", mod_id); - } else { - /* verify slice parameters */ - for (int i = 0; i < sup->n_dl; i++) { - if (!sup->dl[i]->has_id) { - verified = 0; - break; - } - Protocol__FlexDlSlice *dls = get_existing_dl_slice(mod_id, sup->dl[i]->id); - /* fill up so that the slice is complete. This way, we don't need to - * worry about it later */ - fill_dl_slice(mod_id, sup->dl[i], dls); - verified = verified && flexran_verify_dl_slice(mod_id, sup->dl[i]); - if (!verified) break; - } - - /* verify group-based parameters (e.g. sum percentage should not exceed - * 100%). Can be used to perform admission control */ - verified = verified && flexran_verify_group_dl_slices(mod_id, - sc_update[mod_id]->dl, sc_update[mod_id]->n_dl, sup->dl, sup->n_dl); - - if (verified) { - for (int i = 0; i < sup->n_dl; i++) { - /* if all verifications were successful, get existing slice for ID or - * create new one and overwrite with the update */ - Protocol__FlexDlSlice *dls = get_existing_dl_slice(mod_id, sup->dl[i]->id); - if (!dls) dls = create_new_dl_slice(mod_id, sup->dl[i]->id); - overwrite_slice_config_dl(mod_id, dls, sup->dl[i]); - } - } else { - LOG_E(FLEXRAN_AGENT, "[%d] DL slice verification failed, refusing application\n", mod_id); - } - } - - verified = 1; - if (sup->n_ul == 0) { - LOG_I(FLEXRAN_AGENT, "[%d] no UL slice configuration in flex_slice_config message\n", mod_id); - } else { - /* verify slice parameters */ - for (int i = 0; i < sup->n_ul; i++) { - if (!sup->ul[i]->has_id) { - verified = 0; - break; - } - Protocol__FlexUlSlice *uls = get_existing_ul_slice(mod_id, sup->ul[i]->id); - /* fill up so that the slice is complete. This way, we don't need to - * worry about it later */ - fill_ul_slice(mod_id, sup->ul[i], uls); - verified = verified && flexran_verify_ul_slice(mod_id, sup->ul[i]); - if (!verified) break; - } - - /* verify group-based parameters (e.g. sum percentage should not exceed - * 100%). Can be used to perform admission control */ - verified = verified && flexran_verify_group_ul_slices(mod_id, - sc_update[mod_id]->ul, sc_update[mod_id]->n_ul, sup->ul, sup->n_ul); - - if (verified) { - for (int i = 0; i < sup->n_ul; i++) { - /* if all verifications were successful, get existing slice for ID or - * create new one and overwrite with the update */ - Protocol__FlexUlSlice *uls = get_existing_ul_slice(mod_id, sup->ul[i]->id); - if (!uls) uls = create_new_ul_slice(mod_id, sup->ul[i]->id); - overwrite_slice_config_ul(mod_id, uls, sup->ul[i]); - } - } else { - LOG_E(FLEXRAN_AGENT, "[%d] UL slice verification failed, refusing application\n", mod_id); - } - } - pthread_mutex_unlock(&sc_update_mtx); - - perform_slice_config_update_count = 1; } -int apply_new_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *olds, Protocol__FlexSliceConfig *news) -{ - /* not setting the old configuration is intentional, as it will be picked up - * later when reading the configuration. There is thus a direct feedback - * whether it has been set. */ - int changes = 0; - if (olds->intraslice_share_active != news->intraslice_share_active) { - flexran_set_intraslice_sharing_active(mod_id, news->intraslice_share_active); - changes++; - } - if (olds->interslice_share_active != news->interslice_share_active) { - flexran_set_interslice_sharing_active(mod_id, news->interslice_share_active); - changes++; - } - return changes; -} - -int apply_new_slice_dl_config(mid_t mod_id, Protocol__FlexDlSlice *oldc, Protocol__FlexDlSlice *newc) -{ - /* not setting the old configuration is intentional, as it will be picked up - * later when reading the configuration. There is thus a direct feedback - * whether it has been set. */ - int changes = 0; - int slice_idx = flexran_find_dl_slice(mod_id, newc->id); - if (slice_idx < 0) { - LOG_W(FLEXRAN_AGENT, "[%d] cannot find index for slice ID %d\n", mod_id, newc->id); - return 0; - } - if (oldc->percentage != newc->percentage) { - flexran_set_dl_slice_percentage(mod_id, slice_idx, newc->percentage); - changes++; - } - if (oldc->isolation != newc->isolation) { - flexran_set_dl_slice_isolation(mod_id, slice_idx, newc->isolation); - changes++; - } - if (oldc->priority != newc->priority) { - flexran_set_dl_slice_priority(mod_id, slice_idx, newc->priority); - changes++; - } - if (oldc->position_low != newc->position_low) { - flexran_set_dl_slice_position_low(mod_id, slice_idx, newc->position_low); - changes++; - } - if (oldc->position_high != newc->position_high) { - flexran_set_dl_slice_position_high(mod_id, slice_idx, newc->position_high); - changes++; - } - if (oldc->maxmcs != newc->maxmcs) { - flexran_set_dl_slice_maxmcs(mod_id, slice_idx, newc->maxmcs); - changes++; - } - if (check_dl_sorting_update(oldc, newc)) { - flexran_set_dl_slice_sorting(mod_id, slice_idx, newc->sorting, newc->n_sorting); - changes++; - } - if (oldc->accounting != newc->accounting) { - flexran_set_dl_slice_accounting_policy(mod_id, slice_idx, newc->accounting); - changes++; - } - if (!oldc->scheduler_name - || strcmp(oldc->scheduler_name, newc->scheduler_name) != 0) { - int ret = flexran_set_dl_slice_scheduler(mod_id, slice_idx, newc->scheduler_name); - AssertFatal(ret, "could not set DL slice scheduler for slice %d idx %d\n", - newc->id, slice_idx); - changes++; - } - return changes; -} - -int apply_new_slice_ul_config(mid_t mod_id, Protocol__FlexUlSlice *oldc, Protocol__FlexUlSlice *newc) -{ - /* not setting the old configuration is intentional, as it will be picked up - * later when reading the configuration. There is thus a direct feedback - * whether it has been set. */ - int changes = 0; - int slice_idx = flexran_find_ul_slice(mod_id, newc->id); - if (slice_idx < 0) { - LOG_W(FLEXRAN_AGENT, "[%d] cannot find index for slice ID %d\n", mod_id, newc->id); - return 0; - } - if (oldc->percentage != newc->percentage) { - flexran_set_ul_slice_percentage(mod_id, slice_idx, newc->percentage); - changes++; - } - if (oldc->isolation != newc->isolation) { - /*flexran_set_ul_slice_isolation(mod_id, slice_idx, newc->isolation); - *changes++;*/ - LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting isolation is not supported\n", - mod_id, newc->id); - } - if (oldc->priority != newc->priority) { - /*flexran_set_ul_slice_priority(mod_id, slice_idx, newc->priority); - *changes++;*/ - LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting the priority is not supported\n", - mod_id, newc->id); - } - if (oldc->first_rb != newc->first_rb) { - flexran_set_ul_slice_first_rb(mod_id, slice_idx, newc->first_rb); - changes++; - } - /*if (oldc->length_rb != newc->length_rb) { - flexran_set_ul_slice_length_rb(mod_id, slice_idx, newc->length_rb); - changes++; - LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting length_rb is not supported\n", - mod_id, newc->id); - }*/ - if (oldc->maxmcs != newc->maxmcs) { - flexran_set_ul_slice_maxmcs(mod_id, slice_idx, newc->maxmcs); - changes++; - } - /*if (check_ul_sorting_update(oldc, newc)) { - flexran_set_ul_slice_sorting(mod_id, slice_idx, newc->sorting, n); - changes++; - LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting the sorting is not supported\n", - mod_id, newc->id); - }*/ - if (oldc->accounting != newc->accounting) { - /*flexran_set_ul_slice_accounting_policy(mod_id, slice_idx, newc->accounting); - *changes++;*/ - LOG_W(FLEXRAN_AGENT, "[%d][UL slice %d] setting the accounting is not supported\n", - mod_id, newc->id); - } - if (!oldc->scheduler_name - || strcmp(oldc->scheduler_name, newc->scheduler_name) != 0) { - int ret = flexran_set_ul_slice_scheduler(mod_id, slice_idx, newc->scheduler_name); - AssertFatal(ret, "could not set DL slice scheduler for slice %d idx %d\n", - newc->id, slice_idx); - changes++; - } - return changes; -} void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config) { @@ -1723,24 +1075,8 @@ int apply_ue_slice_assoc_update(mid_t mod_id) continue; } if (ue_slice_assoc_update[i]->has_dl_slice_id) { - int slice_idx = flexran_find_dl_slice(mod_id, ue_slice_assoc_update[i]->dl_slice_id); - if (flexran_dl_slice_exists(mod_id, slice_idx)) { - flexran_set_ue_dl_slice_idx(mod_id, ue_id, slice_idx); - changes++; - } else { - LOG_W(FLEXRAN_AGENT, "[%d] DL slice %d does not exist, refusing change\n", - mod_id, ue_slice_assoc_update[i]->dl_slice_id); - } } if (ue_slice_assoc_update[i]->has_ul_slice_id) { - int slice_idx = flexran_find_ul_slice(mod_id, ue_slice_assoc_update[i]->ul_slice_id); - if (flexran_ul_slice_exists(mod_id, slice_idx)) { - flexran_set_ue_ul_slice_idx(mod_id, ue_id, slice_idx); - changes++; - } else { - LOG_W(FLEXRAN_AGENT, "[%d] UL slice %d does not exist, refusing change\n", - mod_id, ue_slice_assoc_update[i]->ul_slice_id); - } } } n_ue_slice_assoc_updates = 0; diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h index 957fe6065e..ef2a7e40a9 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h @@ -111,30 +111,10 @@ Protocol__FlexSliceConfig *flexran_agent_create_slice_config(int n_dl, int m_ul) * Protocol__FlexSliceConfig struct */ void flexran_agent_read_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *s); -/* read the DL slice config via the RAN into a given Protocol__FlexDlSlice - * struct */ -void flexran_agent_read_slice_dl_config(mid_t mod_id, int slice_idx, Protocol__FlexDlSlice *dl_slice); - -/* read the UL slice config via the RAN into a given Protocol__FlexUlSlice - * struct */ -void flexran_agent_read_slice_ul_config(mid_t mod_id, int slice_idx, Protocol__FlexUlSlice *ul_slice); - /* reads content of slice over the sc_update structure, so that it can be * applied later by performing a diff between slice_config and sc_update */ void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *slice); -/* apply generic slice parameters (e.g. intra-/interslice sharing activated or - * not) if there are changes. Returns the number of changed parameters. */ -int apply_new_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *olds, Protocol__FlexSliceConfig *news); - -/* apply new configuration of slice in DL if there are changes between the - * parameters. Returns the number of changed parameters. */ -int apply_new_slice_dl_config(mid_t mod_id, Protocol__FlexDlSlice *oldc, Protocol__FlexDlSlice *newc); - -/* apply new configuration of slice in UL if there are changes between the - * parameters. Returns the number of changed parameters. */ -int apply_new_slice_ul_config(mid_t mod_id, Protocol__FlexUlSlice *oldc, Protocol__FlexUlSlice *newc); - /* inserts a new ue_config into the structure keeping ue to slice association * updates and marks so it can be applied */ void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config); diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c index f7f60541f5..6e54e155c2 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.c @@ -28,346 +28,3 @@ #include "flexran_agent_mac_slice_verification.h" - -/* overlap check for UL slices, helper type */ -struct sregion_s { - int start; - int length; -}; - -/* forward declaration of locally-used verification functions */ -int flexran_dl_slice_verify_pct(int pct); -int flexran_dl_slice_verify_priority(int prio); -int flexran_dl_slice_verify_position(int pos_low, int pos_high); -int flexran_dl_slice_verify_maxmcs(int maxmcs); -int flexran_ul_slice_verify_pct(int pct); -int flexran_ul_slice_verify_priority(int prio); -int flexran_ul_slice_verify_first_rb(int first_rb); -int flexran_ul_slice_verify_maxmcs(int maxmcs); -int check_ul_slice_overlap(mid_t mod_id, struct sregion_s *sr, int n); - -int flexran_verify_dl_slice(mid_t mod_id, Protocol__FlexDlSlice *dls) -{ - /* check mandatory parameters */ - if (!dls->has_id) { - LOG_E(FLEXRAN_AGENT, "[%d] Incoming DL slice configuration has no ID\n", mod_id); - return 0; - } - - /* verify parameters individualy */ - /* label is enum */ - if (!flexran_dl_slice_verify_pct(dls->percentage)) { - LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] illegal DL slice percentage (%d)\n", - mod_id, dls->id, dls->percentage); - return 0; - } - /* isolation is a protobuf bool */ - if (!flexran_dl_slice_verify_priority(dls->priority)) { - LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] illegal DL slice priority (%d)\n", - mod_id, dls->id, dls->priority); - return 0; - } - if (!flexran_dl_slice_verify_position(dls->position_low, dls->position_high)) { - LOG_E(FLEXRAN_AGENT, - "[%d][DL slice %d] illegal DL slice position low (%d) and/or high (%d)\n", - mod_id, dls->id, dls->position_low, dls->position_high); - return 0; - } - if (!flexran_dl_slice_verify_maxmcs(dls->maxmcs)) { - LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] illegal DL slice max mcs %d\n", - mod_id, dls->id, dls->maxmcs); - return 0; - } - if (dls->n_sorting == 0) { - LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] no sorting in DL slice\n", - mod_id, dls->id); - return 0; - } - if (!dls->sorting) { - LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] no sorting found in DL slice\n", - mod_id, dls->id); - return 0; - } - /* sorting is an enum */ - /* accounting is an enum */ - if (!dls->scheduler_name) { - LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] no scheduler name found\n", - mod_id, dls->id); - return 0; - } - if (strcmp(dls->scheduler_name, "schedule_ue_spec") != 0) { - LOG_E(FLEXRAN_AGENT, "[%d][DL slice %d] setting the scheduler to something " - "different than schedule_ue_spec is currently not allowed\n", - mod_id, dls->id); - return 0; - } - - return 1; -} - -int flexran_verify_group_dl_slices(mid_t mod_id, Protocol__FlexDlSlice **existing, - int n_ex, Protocol__FlexDlSlice **update, int n_up) -{ - int i, j, n; - int pct, pct_orig; - /* for every update, array points to existing slice, or NULL if update - * creates new slice */ - Protocol__FlexDlSlice *s[n_up]; - for (i = 0; i < n_up; i++) { - s[i] = NULL; - for (j = 0; j < n_ex; j++) { - if (existing[j]->id == update[i]->id) - s[i] = existing[j]; - } - } - - /* check that number of created and number of added slices in total matches - * [1,10] */ - n = n_ex; - for (i = 0; i < n_up; i++) { - /* new slice */ - if (!s[i]) n += 1; - /* slice will be deleted */ - else if (s[i]->percentage == 0) n -= 1; - /* else "only" an update */ - } - - if (n < 1 || n > 10) { - LOG_E(FLEXRAN_AGENT, "[%d] Illegal number of resulting DL slices (%d -> %d)\n", - mod_id, n_ex, n); - return 0; - } - - /* check that the sum of all slices percentages (including removed/added - * slices) matches [1,100] */ - pct = 0; - for (i = 0; i < n_ex; i++) { - pct += existing[i]->percentage; - } - pct_orig = pct; - for (i = 0; i < n_up; i++) { - /* if there is an existing slice, subtract its percentage and add the - * update's percentage */ - if (s[i]) - pct -= s[i]->percentage; - pct += update[i]->percentage; - } - if (pct < 1 || pct > 100) { - LOG_E(FLEXRAN_AGENT, - "[%d] invalid total RB share for DL slices (%d%% -> %d%%)\n", - mod_id, pct_orig, pct); - return 0; - } - - return 1; -} - -int flexran_verify_ul_slice(mid_t mod_id, Protocol__FlexUlSlice *uls) -{ - /* check mandatory parameters */ - if (!uls->has_id) { - LOG_E(FLEXRAN_AGENT, "[%d] Incoming UL slice configuration has no ID\n", mod_id); - return 0; - } - - /* verify parameters individually */ - /* label is enum */ - if (!flexran_ul_slice_verify_pct(uls->percentage)) { - LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] illegal UL slice percentage (%d)\n", - mod_id, uls->id, uls->percentage); - return 0; - } - /* isolation is a protobuf bool */ - if (!flexran_ul_slice_verify_priority(uls->priority)) { - LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] illegal UL slice percentage (%d)\n", - mod_id, uls->id, uls->priority); - return 0; - } - if (!flexran_ul_slice_verify_first_rb(uls->first_rb)) { - LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] illegal UL slice first RB (%d)\n", - mod_id, uls->id, uls->first_rb); - return 0; - } - if (!flexran_ul_slice_verify_maxmcs(uls->maxmcs)) { - LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] illegal UL slice max mcs (%d)\n", - mod_id, uls->id, uls->maxmcs); - return 0; - } - /* TODO - if (uls->n_sorting == 0) { - LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] no sorting in UL slice\n", - mod_id, uls->id); - return 0; - } - if (!uls->sorting) { - LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] no sorting found in UL slice\n", - mod_id, uls->id); - return 0; - } - */ - /* sorting is an enum */ - /* accounting is an enum */ - if (!uls->scheduler_name) { - LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] no scheduler name found\n", - mod_id, uls->id); - return 0; - } - if (strcmp(uls->scheduler_name, "schedule_ulsch_rnti") != 0) { - LOG_E(FLEXRAN_AGENT, "[%d][UL slice %d] setting the scheduler to something " - "different than schedule_ulsch_rnti is currently not allowed\n", - mod_id, uls->id); - return 0; - } - - return 1; -} - -int flexran_verify_group_ul_slices(mid_t mod_id, Protocol__FlexUlSlice **existing, - int n_ex, Protocol__FlexUlSlice **update, int n_up) -{ - int i, j, n; - int pct, pct_orig; - /* for every update, array "s" points to existing slice, or NULL if update - * creates new slice; array "offs" gives the offset of this slice */ - Protocol__FlexUlSlice *s[n_up]; - int offs[n_up]; - for (i = 0; i < n_up; i++) { - s[i] = NULL; - offs[i] = 0; - for (j = 0; j < n_ex; j++) { - if (existing[j]->id == update[i]->id) { - s[i] = existing[j]; - offs[i] = j; - } - } - } - - /* check that number of created and number of added slices in total matches - * [1,10] */ - n = n_ex; - for (i = 0; i < n_up; i++) { - /* new slice */ - if (!s[i]) n += 1; - /* slice will be deleted */ - else if (s[i]->percentage == 0) n -= 1; - /* else "only" an update */ - } - - if (n < 1 || n > 10) { - LOG_E(FLEXRAN_AGENT, "[%d] Illegal number of resulting UL slices (%d -> %d)\n", - mod_id, n_ex, n); - return 0; - } - - /* check that the sum of all slices percentages (including removed/added - * slices) matches [1,100] */ - pct = 0; - for (i = 0; i < n_ex; i++) { - pct += existing[i]->percentage; - } - pct_orig = pct; - for (i = 0; i < n_up; i++) { - /* if there is an existing slice, subtract its percentage and add the - * update's percentage */ - if (s[i]) - pct -= s[i]->percentage; - pct += update[i]->percentage; - } - if (pct < 1 || pct > 100) { - LOG_E(FLEXRAN_AGENT, "[%d] invalid total RB share (%d%% -> %d%%)\n", - mod_id, pct_orig, pct); - return 0; - } - - /* check that there is no overlap in slices resulting as the combination of - * first_rb and percentage */ - struct sregion_s sregion[n]; - const int N_RB = flexran_get_N_RB_UL(mod_id, 0); /* assume PCC */ - int k = n_ex; - for (i = 0; i < n_ex; i++) { - sregion[i].start = existing[i]->first_rb; - sregion[i].length = existing[i]->percentage * N_RB / 100; - } - for (i = 0; i < n_up; i++) { - ptrdiff_t d = s[i] ? offs[i] : k++; - AssertFatal(d >= 0 && d < k, "illegal pointer offset (%ld, k=%d)\n", d, k); - sregion[d].start = update[i]->first_rb; - sregion[d].length = update[i]->percentage * N_RB / 100; - } - AssertFatal(k == n, "illegal number of slices while calculating overlap\n"); - if (!check_ul_slice_overlap(mod_id, sregion, k)) { - LOG_E(FLEXRAN_AGENT, "[%d] UL slices are overlapping\n", mod_id); - return 0; - } - - return 1; -} - -int flexran_dl_slice_verify_pct(int pct) -{ - return pct >= 0 && pct <= 100; -} - -int flexran_dl_slice_verify_priority(int prio) -{ - return prio >= 0; -} - -int flexran_dl_slice_verify_position(int pos_low, int pos_high) -{ - return pos_low < pos_high && pos_low >= 0 && pos_high <= N_RBG_MAX; -} - -int flexran_dl_slice_verify_maxmcs(int maxmcs) -{ - return maxmcs >= 0 && maxmcs <= 28; -} - -int flexran_ul_slice_verify_pct(int pct) -{ - return pct >= 0 && pct <= 100; -} - -int flexran_ul_slice_verify_priority(int prio) -{ - return prio >= 0; -} - -int flexran_ul_slice_verify_first_rb(int first_rb) -{ - return first_rb >= 0 && first_rb < 100; -} - -int flexran_ul_slice_verify_maxmcs(int maxmcs) -{ - return maxmcs >= 0 && maxmcs <= 20; -} - -int sregion_compare(const void *_a, const void *_b) -{ - const struct sregion_s *a = (const struct sregion_s *)_a; - const struct sregion_s *b = (const struct sregion_s *)_b; - const int res = a->start - b->start; - if (res < 0) return -1; - else if (res == 0) return 0; - else return 1; -} - -int check_ul_slice_overlap(mid_t mod_id, struct sregion_s *sr, int n) -{ - int i; - int overlap, op, u; - const int N_RB = flexran_get_N_RB_UL(mod_id, 0); /* assume PCC */ - qsort(sr, n, sizeof(sr[0]), sregion_compare); - for (i = 0; i < n; i++) { - u = i == n-1 ? N_RB : sr[i+1].start; - AssertFatal(sr[i].start <= u, "unsorted slice list\n"); - overlap = sr[i].start + sr[i].length - u; - if (overlap <= 0) continue; - op = overlap * 100 / sr[i].length; - LOG_W(FLEXRAN_AGENT, "[%d] slice overlap of %d%% detected\n", mod_id, op); - if (op >= 10) /* more than 10% overlap -> refuse */ - return 0; - } - return 1; -} diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.h b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.h index a8f4030d36..c9e66b6f88 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.h +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_slice_verification.h @@ -29,9 +29,3 @@ #include "flexran_agent_common_internal.h" #include "flexran_agent_mac_internal.h" -int flexran_verify_dl_slice(mid_t mod_id, Protocol__FlexDlSlice *dls); -int flexran_verify_group_dl_slices(mid_t mod_id, Protocol__FlexDlSlice **existing, - int n_ex, Protocol__FlexDlSlice **update, int n_up); -int flexran_verify_ul_slice(mid_t mod_id, Protocol__FlexUlSlice *uls); -int flexran_verify_group_ul_slices(mid_t mod_id, Protocol__FlexUlSlice **existing, - int n_ex, Protocol__FlexUlSlice **update, int n_up); diff --git a/openair2/ENB_APP/MESSAGES/V2/config_common.proto b/openair2/ENB_APP/MESSAGES/V2/config_common.proto index 733d883c92..e5d01ebdc0 100644 --- a/openair2/ENB_APP/MESSAGES/V2/config_common.proto +++ b/openair2/ENB_APP/MESSAGES/V2/config_common.proto @@ -61,83 +61,6 @@ enum flex_qam { // // Slice config related structures and enums // -enum flex_dl_sorting { - - CR_ROUND = 0; // Highest HARQ first - CR_SRB12 = 1; // Highest SRB1+2 first - CR_HOL = 2; // Highest HOL first - CR_LC = 3; // Greatest RLC buffer first - CR_CQI = 4; // Highest CQI first - CR_LCP = 5; // Highest LC priority first -} - -enum flex_ul_sorting { - CRU_ROUND = 0; // Highest HARQ first - CRU_BUF = 1; // Highest BSR first - CRU_BTS = 2; // More bytes to schedule first - CRU_MCS = 3; // Highest MCS first - CRU_LCP = 4; // Highest LC priority first - CRU_HOL = 5; // Highest HOL first -} - -enum flex_dl_accounting_policy { - POL_FAIR = 0; - POL_GREEDY = 1; - POL_NUM = 2; -} - -enum flex_ul_accounting_policy { - POLU_FAIR = 0; - POLU_GREEDY = 1; - POLU_NUM = 2; -} - -enum flex_slice_label { - xMBB = 0; - URLLC = 1; - mMTC = 2; - xMTC = 3; - Other = 4; -} - -message flex_dl_slice { - optional uint32 id = 1; - optional flex_slice_label label = 2; - // should be between 0 and 100 - optional uint32 percentage = 3; - // whether this slice should be exempted form interslice sharing - optional bool isolation = 4; - // increasing value means increasing prio - optional uint32 priority = 5; - // min and max RB to use (in frequency) in the range [0, N_RBG_MAX] - optional uint32 position_low = 6; - optional uint32 position_high = 7; - // maximum MCS to be allowed in this slice - optional uint32 maxmcs = 8; - repeated flex_dl_sorting sorting = 9; - optional flex_dl_accounting_policy accounting = 10; - optional string scheduler_name = 11; -} - -message flex_ul_slice { - optional uint32 id = 1; - optional flex_slice_label label = 2; - // should be between 0 and 100 - optional uint32 percentage = 3; - // whether this slice should be exempted form interslice sharing - optional bool isolation = 4; - // increasing value means increasing prio - optional uint32 priority = 5; - // RB start to use (in frequency) in the range [0, N_RB_MAX] - optional uint32 first_rb = 6; - // TODO RB number - //optional uint32 length_rb = 7; - // maximum MCS to be allowed in this slice - optional uint32 maxmcs = 8; - repeated flex_ul_sorting sorting = 9; - optional flex_ul_accounting_policy accounting = 10; - optional string scheduler_name = 11; -} // // UE config related structures and enums diff --git a/openair2/ENB_APP/MESSAGES/V2/config_messages.proto b/openair2/ENB_APP/MESSAGES/V2/config_messages.proto index 324153613d..1a66a4f20f 100644 --- a/openair2/ENB_APP/MESSAGES/V2/config_messages.proto +++ b/openair2/ENB_APP/MESSAGES/V2/config_messages.proto @@ -49,14 +49,6 @@ message flex_cell_config { } message flex_slice_config { - // whether remaining RBs after first intra-slice allocation will - // be allocated to UEs of the same slice - optional bool intraslice_share_active = 3; - // whether remaining RBs after slice allocation will be allocated - // to UEs of another slice. Isolated slices will be ignored. - optional bool interslice_share_active = 4; - repeated flex_dl_slice dl = 1; - repeated flex_ul_slice ul = 2; } message flex_ue_config { diff --git a/openair2/ENB_APP/flexran_agent_common.c b/openair2/ENB_APP/flexran_agent_common.c index e77b2fb386..3dd9f5b957 100644 --- a/openair2/ENB_APP/flexran_agent_common.c +++ b/openair2/ENB_APP/flexran_agent_common.c @@ -316,25 +316,7 @@ int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg) { } if (reply->cell_config[i]->slice_config) { - for (int j = 0; j < reply->cell_config[i]->slice_config->n_dl; ++j) { - if (reply->cell_config[i]->slice_config->dl[j]->n_sorting > 0) - free(reply->cell_config[i]->slice_config->dl[j]->sorting); - - free(reply->cell_config[i]->slice_config->dl[j]->scheduler_name); - free(reply->cell_config[i]->slice_config->dl[j]); - } - - free(reply->cell_config[i]->slice_config->dl); - - for (int j = 0; j < reply->cell_config[i]->slice_config->n_ul; ++j) { - if (reply->cell_config[i]->slice_config->ul[j]->n_sorting > 0) - free(reply->cell_config[i]->slice_config->ul[j]->sorting); - - free(reply->cell_config[i]->slice_config->ul[j]->scheduler_name); - free(reply->cell_config[i]->slice_config->ul[j]); - } - - free(reply->cell_config[i]->slice_config->ul); + /* TODO */ free(reply->cell_config[i]->slice_config); } diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index 291c4dc7d8..cd8b0b8f67 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -3018,142 +3018,44 @@ int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) { return 0; } -void flexran_set_ue_dl_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx) { - if (!mac_is_present(mod_id)) return; -} - int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return -1; return 0; } -void flexran_set_ue_ul_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx) { - if (!mac_is_present(mod_id)) return; -} - -int flexran_dl_slice_exists(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return 0; -} - +/* TODO */ int flexran_create_dl_slice(mid_t mod_id, slice_id_t slice_id) { if (!mac_is_present(mod_id)) return -1; return -1; } +/* TODO */ +int flexran_remove_dl_slice(mid_t mod_id, int slice_idx) { + if (!mac_is_present(mod_id)) return -1; + return -1; +} + int flexran_find_dl_slice(mid_t mod_id, slice_id_t slice_id) { if (!mac_is_present(mod_id)) return -1; return -1; } -int flexran_remove_dl_slice(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} +//int flexran_get_dl_slice(mid_t mod_id, int slice_idx, Protocol__FlexSlice *s) { +//} int flexran_get_num_dl_slices(mid_t mod_id) { if (!mac_is_present(mod_id)) return -1; return 0; } -int flexran_get_intraslice_sharing_active(mid_t mod_id) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} -void flexran_set_intraslice_sharing_active(mid_t mod_id, int intraslice_active) { +/* TODO */ +void flexran_create_ul_slice(mid_t mod_id, slice_id_t slice_id) { if (!mac_is_present(mod_id)) return; + return; } -int flexran_get_interslice_sharing_active(mid_t mod_id) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} -void flexran_set_interslice_sharing_active(mid_t mod_id, int interslice_active) { - if (!mac_is_present(mod_id)) return; -} - -slice_id_t flexran_get_dl_slice_id(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} -void flexran_set_dl_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id) { - if (!mac_is_present(mod_id)) return; -} - -int flexran_get_dl_slice_percentage(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} -void flexran_set_dl_slice_percentage(mid_t mod_id, int slice_idx, int percentage) { - if (!mac_is_present(mod_id)) return; -} - -int flexran_get_dl_slice_isolation(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} -void flexran_set_dl_slice_isolation(mid_t mod_id, int slice_idx, int is_isolated) { - if (!mac_is_present(mod_id)) return; -} - -int flexran_get_dl_slice_priority(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} -void flexran_set_dl_slice_priority(mid_t mod_id, int slice_idx, int priority) { - if (!mac_is_present(mod_id)) return; -} - -int flexran_get_dl_slice_position_low(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} -void flexran_set_dl_slice_position_low(mid_t mod_id, int slice_idx, int poslow) { - if (!mac_is_present(mod_id)) return; -} - -int flexran_get_dl_slice_position_high(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} -void flexran_set_dl_slice_position_high(mid_t mod_id, int slice_idx, int poshigh) { - if (!mac_is_present(mod_id)) return; -} - -int flexran_get_dl_slice_maxmcs(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} -void flexran_set_dl_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs) { - if (!mac_is_present(mod_id)) return; -} - -int flexran_get_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting **sorting_list) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} -void flexran_set_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting *sorting_list, int n) { - if (!mac_is_present(mod_id)) return; -} - -Protocol__FlexDlAccountingPolicy flexran_get_dl_slice_accounting_policy(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR; - return PROTOCOL__FLEX_DL_ACCOUNTING_POLICY__POL_FAIR; -} -void flexran_set_dl_slice_accounting_policy(mid_t mod_id, int slice_idx, Protocol__FlexDlAccountingPolicy accounting) { - if (!mac_is_present(mod_id)) return; -} - -char *flexran_get_dl_slice_scheduler(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return NULL; - return NULL; -} -int flexran_set_dl_slice_scheduler(mid_t mod_id, int slice_idx, char *name) { - if (!mac_is_present(mod_id)) return 0; - return 0; -} - -int flexran_create_ul_slice(mid_t mod_id, slice_id_t slice_id) { +/* TODO */ +int flexran_remove_ul_slice(mid_t mod_id, int slice_idx) { if (!mac_is_present(mod_id)) return -1; return -1; } @@ -3163,62 +3065,14 @@ int flexran_find_ul_slice(mid_t mod_id, slice_id_t slice_id) { return -1; } -int flexran_remove_ul_slice(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} +//int flexran_get_ul_slice(mid_t mod_id, int slice_idx, Protocol__FlexSlice *s) { +//} int flexran_get_num_ul_slices(mid_t mod_id) { if (!mac_is_present(mod_id)) return -1; return 0; } -int flexran_ul_slice_exists(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return 0; -} - -slice_id_t flexran_get_ul_slice_id(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} -void flexran_set_ul_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id) { - if (!mac_is_present(mod_id)) return; -} - -int flexran_get_ul_slice_percentage(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} -void flexran_set_ul_slice_percentage(mid_t mod_id, int slice_idx, int percentage) { - if (!mac_is_present(mod_id)) return; -} - -int flexran_get_ul_slice_first_rb(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} - -void flexran_set_ul_slice_first_rb(mid_t mod_id, int slice_idx, int first_rb) { - if (!mac_is_present(mod_id)) return; -} - -int flexran_get_ul_slice_maxmcs(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; -} -void flexran_set_ul_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs) { - if (!mac_is_present(mod_id)) return; -} - -char *flexran_get_ul_slice_scheduler(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return NULL; - return ""; -} -int flexran_set_ul_slice_scheduler(mid_t mod_id, int slice_idx, char *name) { - if (!mac_is_present(mod_id)) return 0; - return 0; -} /************************** S1AP **************************/ int flexran_get_s1ap_mme_pending(mid_t mod_id){ diff --git a/openair2/ENB_APP/flexran_agent_ran_api.h b/openair2/ENB_APP/flexran_agent_ran_api.h index 9d1bfb9d3e..c29ba53c11 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.h +++ b/openair2/ENB_APP/flexran_agent_ran_api.h @@ -659,153 +659,38 @@ uint32_t flexran_get_rrc_enb_ue_s1ap_id(mid_t mod_id, rnti_t rnti); /* Get the DL slice ID for a UE */ int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id); - /* Set the DL slice index(!) for a UE */ -void flexran_set_ue_dl_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx); +//void flexran_set_ue_dl_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx); /* Get the UL slice ID for a UE */ int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id); - /* Set the UL slice index(!) for a UE */ -void flexran_set_ue_ul_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx); +//void flexran_set_ue_ul_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx); -/* Whether intraslice sharing is active, return boolean */ -int flexran_get_intraslice_sharing_active(mid_t mod_id); -/* Set whether intraslice sharing is active */ -void flexran_set_intraslice_sharing_active(mid_t mod_id, int intraslice_active); - -/* Whether intraslice sharing is active, return boolean */ -int flexran_get_interslice_sharing_active(mid_t mod_id); -/* Set whether intraslice sharing is active */ -void flexran_set_interslice_sharing_active(mid_t mod_id, int interslice_active); +/* Create slice in DL, returns the new slice index */ +//int flexran_create_dl_slice(mid_t mod_id, slice_id_t slice_id); +/* Remove slice in DL, returns new number of slices or -1 on error */ +//int flexran_remove_dl_slice(mid_t mod_id, int slice_idx); +/* Finds slice in DL with given slice_id and returns slice index */ +int flexran_find_dl_slice(mid_t mod_id, slice_id_t slice_id); +/* Return the parameters of slice at index slice_idx */ +//void flexran_get_dl_slice(mid_t mod_id, int slice_idx, Protocol__FlexSlice *s); /* Get the number of slices in DL */ int flexran_get_num_dl_slices(mid_t mod_id); -/* Query slice existence in DL. Return is boolean value */ -int flexran_dl_slice_exists(mid_t mod_id, int slice_idx); +/* Create slice in UL, returns the new slice index */ +//int flexran_create_ul_slice(mid_t mod_id, slice_id_t slice_id); +/* Remove slice in UL */ +//int flexran_remove_ul_slice(mid_t mod_id, int slice_idx); -/* Create slice in DL, returns the new slice index */ -int flexran_create_dl_slice(mid_t mod_id, slice_id_t slice_id); /* Finds slice in DL with given slice_id and returns slice index */ -int flexran_find_dl_slice(mid_t mod_id, slice_id_t slice_id); -/* Remove slice in DL, returns new number of slices or -1 on error */ -int flexran_remove_dl_slice(mid_t mod_id, int slice_idx); - -/* Get the ID of a slice in DL */ -slice_id_t flexran_get_dl_slice_id(mid_t mod_id, int slice_idx); -/* Set the ID of a slice in DL */ -void flexran_set_dl_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id); - -/* Get the RB share a slice in DL, value 0-100 */ -int flexran_get_dl_slice_percentage(mid_t mod_id, int slice_idx); -/* Set the RB share a slice in DL, value 0-100 */ -void flexran_set_dl_slice_percentage(mid_t mod_id, int slice_idx, int percentage); - -/* Whether a slice in DL is isolated */ -int flexran_get_dl_slice_isolation(mid_t mod_id, int slice_idx); -/* Set whether a slice in DL is isolated */ -void flexran_set_dl_slice_isolation(mid_t mod_id, int slice_idx, int is_isolated); - -/* Get the priority of a slice in DL */ -int flexran_get_dl_slice_priority(mid_t mod_id, int slice_idx); -/* Get the priority of a slice in DL */ -void flexran_set_dl_slice_priority(mid_t mod_id, int slice_idx, int priority); - -/* Get the lower end of the frequency range for the slice positioning in DL */ -int flexran_get_dl_slice_position_low(mid_t mod_id, int slice_idx); -/* Set the lower end of the frequency range for the slice positioning in DL */ -void flexran_set_dl_slice_position_low(mid_t mod_id, int slice_idx, int poslow); - -/* Get the higher end of the frequency range for the slice positioning in DL */ -int flexran_get_dl_slice_position_high(mid_t mod_id, int slice_idx); -/* Set the higher end of the frequency range for the slice positioning in DL */ -void flexran_set_dl_slice_position_high(mid_t mod_id, int slice_idx, int poshigh); - -/* Get the maximum MCS for slice in DL */ -int flexran_get_dl_slice_maxmcs(mid_t mod_id, int slice_idx); -/* Set the maximum MCS for slice in DL */ -void flexran_set_dl_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs); - -/* Get the sorting order of a slice in DL, return value is number of elements - * in sorting_list */ -int flexran_get_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting **sorting_list); -/* Set the sorting order of a slice in DL */ -void flexran_set_dl_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexDlSorting *sorting_list, int n); - -/* Get the accounting policy for a slice in DL */ -Protocol__FlexDlAccountingPolicy flexran_get_dl_slice_accounting_policy(mid_t mod_id, int slice_idx); -/* Set the accounting policy for a slice in DL */ -void flexran_set_dl_slice_accounting_policy(mid_t mod_id, int slice_idx, Protocol__FlexDlAccountingPolicy accounting); - -/* Get the scheduler name for a slice in DL */ -char *flexran_get_dl_slice_scheduler(mid_t mod_id, int slice_idx); -/* Set the scheduler name for a slice in DL */ -int flexran_set_dl_slice_scheduler(mid_t mod_id, int slice_idx, char *name); - +int flexran_find_ul_slice(mid_t mod_id, slice_id_t slice_id); +/* Return the parameters of slice at index slice_idx */ +//void flexran_get_ul_slice(mid_t mod_id, int slice_idx, Protocol__FlexSlice *s); /* Get the number of slices in UL */ int flexran_get_num_ul_slices(mid_t mod_id); -/* Query slice existence in UL. Return is boolean value */ -int flexran_ul_slice_exists(mid_t mod_id, int slice_idx); - -/* Create slice in UL, returns the new slice index */ -int flexran_create_ul_slice(mid_t mod_id, slice_id_t slice_id); -/* Finds slice in UL with given slice_id and returns slice index */ -int flexran_find_ul_slice(mid_t mod_id, slice_id_t slice_id); -/* Remove slice in UL */ -int flexran_remove_ul_slice(mid_t mod_id, int slice_idx); - -/* Get the ID of a slice in UL */ -slice_id_t flexran_get_ul_slice_id(mid_t mod_id, int slice_idx); -/* Set the ID of a slice in UL */ -void flexran_set_ul_slice_id(mid_t mod_id, int slice_idx, slice_id_t slice_id); - -/* Get the RB share a slice in UL, value 0-100 */ -int flexran_get_ul_slice_percentage(mid_t mod_id, int slice_idx); -/* Set the RB share a slice in UL, value 0-100 */ -void flexran_set_ul_slice_percentage(mid_t mod_id, int slice_idx, int percentage); - -/* TODO Whether a slice in UL is isolated */ -/*int flexran_get_ul_slice_isolation(mid_t mod_id, int slice_idx);*/ -/* TODO Set whether a slice in UL is isolated */ -/*void flexran_set_ul_slice_isolation(mid_t mod_id, int slice_idx, int is_isolated);*/ - -/* TODO Get the priority of a slice in UL */ -/*int flexran_get_ul_slice_priority(mid_t mod_id, int slice_idx);*/ -/* TODO Set the priority of a slice in UL */ -/*void flexran_set_ul_slice_priority(mid_t mod_id, int slice_idx, int priority);*/ - -/* Get the first RB for allocation in a slice in UL */ -int flexran_get_ul_slice_first_rb(mid_t mod_id, int slice_idx); -/* Set the first RB for allocation in a slice in UL */ -void flexran_set_ul_slice_first_rb(mid_t mod_id, int slice_idx, int first_rb); - -/* TODO Get the number of RB for the allocation in a slice in UL */ -/*int flexran_get_ul_slice_length_rb(mid_t mod_id, int slice_idx);*/ -/* TODO Set the of number of RB for the allocation in a slice in UL */ -/*void flexran_set_ul_slice_length_rb(mid_t mod_id, int slice_idx, int poshigh);*/ - -/* Get the maximum MCS for slice in UL */ -int flexran_get_ul_slice_maxmcs(mid_t mod_id, int slice_idx); -/* Set the maximum MCS for slice in UL */ -void flexran_set_ul_slice_maxmcs(mid_t mod_id, int slice_idx, int maxmcs); - -/* TODO Get the sorting order of a slice in UL, return value is number of elements - * in sorting_list */ -/*int flexran_get_ul_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexUlSorting **sorting_list);*/ -/* TODO Set the sorting order of a slice in UL */ -/*void flexran_set_ul_slice_sorting(mid_t mod_id, int slice_idx, Protocol__FlexUlSorting *sorting_list, int n);*/ - -/* TODO Get the accounting policy for a slice in UL */ -/*Protocol__UlAccountingPolicy flexran_get_ul_slice_accounting_policy(mid_t mod_id, int slice_idx);*/ -/* TODO Set the accounting policy for a slice in UL */ -/*void flexran_get_ul_slice_accounting_policy(mid_t mod_id, int slice_idx, Protocol__UlAccountingPolicy accountin);*/ - -/* Get the scheduler name for a slice in UL */ -char *flexran_get_ul_slice_scheduler(mid_t mod_id, int slice_idx); -/* Set the scheduler name for a slice in UL */ -int flexran_set_ul_slice_scheduler(mid_t mod_id, int slice_idx, char *name); /************************** S1AP **************************/ /* Get the number of MMEs to be connected */ From 2b4e52906879d1001380679aac92306121946793 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 12 Apr 2020 15:16:21 +0200 Subject: [PATCH 55/66] Simplify add_ue_list(), remove_ue_list(); add init_ue_list() --- .../LAYER2/MAC/eNB_scheduler_primitives.c | 43 ++++++++++--------- openair2/LAYER2/MAC/mac_proto.h | 1 + openair2/LAYER2/MAC/main.c | 5 +-- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index 78d6f6a3d7..b75ab774c6 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -2131,33 +2131,36 @@ dump_ue_list(UE_list_t *listP) { * Add a UE to UE_list listP */ inline void add_ue_list(UE_list_t *listP, int UE_id) { - if (listP->head == -1) { - listP->head = UE_id; - listP->next[UE_id] = -1; - } else { - int i = listP->head; - while (listP->next[i] >= 0) - i = listP->next[i]; - listP->next[i] = UE_id; - listP->next[UE_id] = -1; - } + int *cur = &listP->head; + while (*cur >= 0) + cur = &listP->next[*cur]; + *cur = UE_id; } //------------------------------------------------------------------------------ /* - * Remove a UE from the UE_list listP, return the previous element + * Remove a UE from the UE_list listP */ inline int remove_ue_list(UE_list_t *listP, int UE_id) { - listP->next[UE_id] = -1; - if (listP->head == UE_id) { - listP->head = listP->next[UE_id]; - return -1; - } + int *cur = &listP->head; + while (*cur != -1 && *cur != UE_id) + cur = &listP->next[*cur]; + if (*cur == -1) + return 0; + int *next = &listP->next[*cur]; + *cur = listP->next[*cur]; + *next = -1; + return 1; +} - int previous = prev(listP, UE_id); - if (previous != -1) - listP->next[previous] = listP->next[UE_id]; - return previous; +//------------------------------------------------------------------------------ +/* + * Initialize the UE_list listP + */ +inline void init_ue_list(UE_list_t *listP) { + listP->head = -1; + for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) + listP->next[i] = -1; } //------------------------------------------------------------------------------ diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index 61251ef088..818eb834fb 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -659,6 +659,7 @@ int prev(UE_list_t *listP, int nodeP); void add_ue_list(UE_list_t *listP, int UE_id); int remove_ue_list(UE_list_t *listP, int UE_id); void dump_ue_list(UE_list_t *listP); +void init_ue_list(UE_list_t *listP); int UE_num_active_CC(UE_info_t *listP, int ue_idP); int UE_PCCID(module_id_t mod_idP, int ue_idP); rnti_t UE_RNTI(module_id_t mod_idP, int ue_idP); diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index 35b5136889..659c7250e8 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -45,11 +45,8 @@ extern RAN_CONTEXT_t RC; void init_UE_info(UE_info_t *UE_info) { - int list_el; UE_info->num_UEs = 0; - UE_info->list.head = -1; - for (list_el = 0; list_el < MAX_MOBILES_PER_ENB; list_el++) - UE_info->list.next[list_el] = -1; + init_ue_list(&UE_info->list); memset(UE_info->DLSCH_pdu, 0, sizeof(UE_info->DLSCH_pdu)); memset(UE_info->UE_template, 0, sizeof(UE_info->UE_template)); memset(UE_info->eNB_UE_stats, 0, sizeof(UE_info->eNB_UE_stats)); From 9956b96049a32ec9ccb3aa9e78ff6aa0008044f8 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 12 Apr 2020 14:38:05 +0200 Subject: [PATCH 56/66] Use fptr for preproc and align UL PP definition --- openair2/ENB_APP/enb_config.c | 9 +-- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 5 +- .../LAYER2/MAC/eNB_scheduler_primitives.c | 12 ++++ openair2/LAYER2/MAC/eNB_scheduler_ulsch.c | 4 +- openair2/LAYER2/MAC/mac.h | 59 +++++++++++++++++-- openair2/LAYER2/MAC/mac_proto.h | 6 +- openair2/LAYER2/MAC/main.c | 13 ++-- openair2/LAYER2/MAC/pre_processor.c | 46 +++++++-------- 8 files changed, 110 insertions(+), 44 deletions(-) diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 0308c2fd79..1d189832b4 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -266,10 +266,11 @@ void RCconfig_macrlc(int macrlc_has_f1[MAX_MAC_INST]) { void *d = dlsym(NULL, s); AssertFatal(d, "%s(): no default scheduler DL algo '%s' found\n", __func__, s); // release default, add new - RC.mac[j]->dl_algo.unset(&RC.mac[j]->dl_algo.data); - RC.mac[j]->dl_algo = *(default_sched_dl_algo_t *) d; - RC.mac[j]->dl_algo.data = RC.mac[j]->dl_algo.setup(); - LOG_I(ENB_APP, "using default scheduler DL algo '%s'\n", RC.mac[j]->dl_algo.name); + pp_impl_param_t *dl_pp = &RC.mac[j]->pre_processor_dl; + dl_pp->dl_algo.unset(&dl_pp->dl_algo.data); + dl_pp->dl_algo = *(default_sched_dl_algo_t *) d; + dl_pp->dl_algo.data = dl_pp->dl_algo.setup(); + LOG_I(ENB_APP, "using default scheduler DL algo '%s'\n", dl_pp->dl_algo.name); }// j=0..num_inst } /*else {// MacRLC_ParamList.numelt > 0 // ignore it diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 783d4e8b1a..1f99f50ece 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -573,10 +573,7 @@ schedule_ue_spec(module_id_t module_idP, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR, VCD_FUNCTION_IN); start_meas(&eNB->schedule_dlsch_preprocessor); - dlsch_scheduler_pre_processor(module_idP, - CC_id, - frameP, - subframeP); + eNB->pre_processor_dl.dl(module_idP, CC_id, frameP, subframeP); stop_meas(&eNB->schedule_dlsch_preprocessor); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_PREPROCESSOR, VCD_FUNCTION_OUT); diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index b75ab774c6..89c2ecc83d 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -2199,6 +2199,12 @@ add_new_ue(module_id_t mod_idP, UE_info->active[UE_id] = TRUE; add_ue_list(&UE_info->list, UE_id); dump_ue_list(&UE_info->list); + pp_impl_param_t* dl = &RC.mac[mod_idP]->pre_processor_dl; + if (dl->slices) // inform slice implementation about new UE + dl->add_UE(dl->slices, UE_id); + pp_impl_param_t* ul = &RC.mac[mod_idP]->pre_processor_ul; + if (ul->slices) // inform slice implementation about new UE + ul->add_UE(ul->slices, UE_id); if (IS_SOFTMODEM_IQPLAYER)// not specific to record/playback ? UE_info->UE_template[cc_idP][UE_id].pre_assigned_mcs_ul = 0; UE_info->UE_template[cc_idP][UE_id].rach_resource_type = rach_resource_type; @@ -2262,6 +2268,12 @@ rrc_mac_remove_ue(module_id_t mod_idP, UE_info->num_UEs--; remove_ue_list(&UE_info->list, UE_id); + pp_impl_param_t* dl = &RC.mac[mod_idP]->pre_processor_dl; + if (dl->slices) // inform slice implementation about new UE + dl->remove_UE(dl->slices, UE_id); + pp_impl_param_t* ul = &RC.mac[mod_idP]->pre_processor_ul; + if (ul->slices) // inform slice implementation about new UE + ul->remove_UE(ul->slices, UE_id); /* Clear all remaining pending transmissions */ memset(&UE_info->UE_template[pCC_id][UE_id], 0, sizeof(UE_TEMPLATE)); diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index 3062e5c964..2de45db856 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -1301,11 +1301,11 @@ schedule_ulsch_rnti(module_id_t module_idP, /* * ULSCH preprocessor: set UE_template-> - * pre_allocated_nb_rb_ul[slice_idx] + * pre_allocated_nb_rb_ul * pre_assigned_mcs_ul * pre_allocated_rb_table_index_ul */ - ulsch_scheduler_pre_processor(module_idP, CC_id, frameP, subframeP, sched_frame, sched_subframeP); + mac->pre_processor_ul.ul(module_idP, CC_id, frameP, subframeP, sched_frame, sched_subframeP); for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { if (UE_info->UE_template[CC_id][UE_id].rach_resource_type > 0) diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h index 8349d84d48..faefc481f6 100644 --- a/openair2/LAYER2/MAC/mac.h +++ b/openair2/LAYER2/MAC/mac.h @@ -540,7 +540,6 @@ typedef enum { SCHED_MODE_FAIR_RR /// fair raund robin } SCHEDULER_MODES; - /*! \brief temporary struct for ULSCH sched */ typedef struct { rnti_t rnti; @@ -1199,6 +1198,56 @@ typedef struct { void *data; } default_sched_ul_algo_t; +typedef void (*pp_impl_dl)(module_id_t mod_id, + int CC_id, + frame_t frame, + sub_frame_t subframe); +typedef void (*pp_impl_ul)(module_id_t mod_id, + int CC_id, + frame_t frame, + sub_frame_t subframe, + frame_t sched_frame, + sub_frame_t sched_subframe); + +struct slice_info_s; +typedef struct { + int algorithm; + + /// inform the slice algorithm about a new UE + void (*add_UE)(struct slice_info_s *s, int UE_id); + /// inform the slice algorithm about a UE that disconnected + void (*remove_UE)(struct slice_info_s *s, int UE_id); + /// move a UE to a slice in DL/UL, -1 means don't move (no-op). + void (*move_UE)(struct slice_info_s *s, int UE_id, int idx); + + /// Adds a new slice through admission control. slice_params are + /// algorithm-specific parameters. sched is either a default_sched_ul_algo_t + /// or default_sched_dl_algo_t, depending on whether this implementation + /// handles UL/DL. If slice at index exists, updates existing + /// slice. Returns index of new slice or -1 on failure. + int (*addmod_slice)(struct slice_info_s *s, + int id, + char *label, + void *sched, + void *slice_params); + /// Returns slice through slice_idx. 1 if successful, 0 if not. + int (*remove_slice)(struct slice_info_s *s, uint8_t slice_idx); + + union { + pp_impl_dl dl; + pp_impl_ul ul; + }; + + union { + default_sched_ul_algo_t ul_algo; + default_sched_dl_algo_t dl_algo; + }; + + void (*destroy)(struct slice_info_s **s); + + struct slice_info_s *slices; +} pp_impl_param_t; + /*! \brief eNB common channels */ typedef struct { int physCellId; @@ -1354,9 +1403,11 @@ typedef struct eNB_MAC_INST_s { UE_free_list_t UE_free_list; /// for scheduling selection SCHEDULER_MODES scheduler_mode; - /// scheduling algorithm used in default scheduler - default_sched_dl_algo_t dl_algo; - default_sched_ul_algo_t ul_algo; + /// Default scheduler: Pre-processor implementation. Algorithms for UL/DL + /// are called by ULSCH/DLSCH, respectively. Pro-processor implementation can + /// encapsulate slicing. + pp_impl_param_t pre_processor_dl; + pp_impl_param_t pre_processor_ul; int32_t puSch10xSnr; int32_t puCch10xSnr; diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index 818eb834fb..9d49fdffd5 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -674,10 +674,10 @@ void set_ul_DAI(int module_idP, void ulsch_scheduler_pre_processor(module_id_t module_idP, int CC_id, - int frameP, + frame_t frameP, sub_frame_t subframeP, - int sched_frameP, - unsigned char sched_subframeP); + frame_t sched_frameP, + sub_frame_t sched_subframeP); int phy_stats_exist(module_id_t Mod_id, int rnti); diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index 659c7250e8..24038e60d5 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -99,16 +99,21 @@ void mac_top_init_eNB(void) } mac[i]->if_inst = IF_Module_init(i); + + mac[i]->pre_processor_dl.dl = dlsch_scheduler_pre_processor; char *s = "round_robin_dl"; void *d = dlsym(NULL, s); AssertFatal(d, "%s(): no scheduler algo '%s' found\n", __func__, s); - mac[i]->dl_algo = *(default_sched_dl_algo_t *) d; - mac[i]->dl_algo.data = mac[i]->dl_algo.setup(); + mac[i]->pre_processor_dl.dl_algo = *(default_sched_dl_algo_t *) d; + mac[i]->pre_processor_dl.dl_algo.data = mac[i]->pre_processor_dl.dl_algo.setup(); + + mac[i]->pre_processor_ul.ul = ulsch_scheduler_pre_processor; s = "round_robin_ul"; d = dlsym(NULL, s); AssertFatal(d, "%s(): no scheduler algo '%s' found\n", __func__, s); - mac[i]->ul_algo = *(default_sched_ul_algo_t *) d; - mac[i]->ul_algo.data = mac[i]->ul_algo.setup(); + mac[i]->pre_processor_ul.ul_algo = *(default_sched_ul_algo_t *) d; + mac[i]->pre_processor_ul.ul_algo.data = mac[i]->pre_processor_ul.ul_algo.setup(); + init_UE_info(&mac[i]->UE_info); } diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index d7dfc7816a..6477d60021 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -703,15 +703,15 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, n_rbg_sched += rbgalloc_mask[i]; } - mac->dl_algo.run(Mod_id, - CC_id, - frameP, - subframeP, - &UE_to_sched, - 4, // max_num_ue - n_rbg_sched, - rbgalloc_mask, - mac->dl_algo.data); + mac->pre_processor_dl.dl_algo.run(Mod_id, + CC_id, + frameP, + subframeP, + &UE_to_sched, + 4, // max_num_ue + n_rbg_sched, + rbgalloc_mask, + mac->pre_processor_dl.dl_algo.data); // the following block is meant for validation of the pre-processor to check // whether all UE allocations are non-overlapping and is not necessary for @@ -1080,10 +1080,10 @@ default_sched_ul_algo_t round_robin_ul = { void ulsch_scheduler_pre_processor(module_id_t Mod_id, int CC_id, - int frameP, + frame_t frameP, sub_frame_t subframeP, - int sched_frameP, - unsigned char sched_subframeP) { + frame_t sched_frameP, + sub_frame_t sched_subframeP) { eNB_MAC_INST *mac = RC.mac[Mod_id]; UE_info_t *UE_info = &mac->UE_info; const int N_RB_UL = to_prb(mac->common_channels[CC_id].ul_Bandwidth); @@ -1140,17 +1140,17 @@ void ulsch_scheduler_pre_processor(module_id_t Mod_id, } } - mac->ul_algo.run(Mod_id, - CC_id, - frameP, - subframeP, - sched_frameP, - sched_subframeP, - &UE_to_sched, - 4, // max_num_ue - n_contig, - rbs, - mac->ul_algo.data); + mac->pre_processor_ul.ul_algo.run(Mod_id, + CC_id, + frameP, + subframeP, + sched_frameP, + sched_subframeP, + &UE_to_sched, + 4, // max_num_ue + n_contig, + rbs, + mac->pre_processor_ul.ul_algo.data); // the following block is meant for validation of the pre-processor to check // whether all UE allocations are non-overlapping and is not necessary for From 872cfc03fe2323f708acbc7008f3d4294f3df2de Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 12 Apr 2020 18:33:55 +0200 Subject: [PATCH 57/66] Implement Static Slicing --- cmake_targets/CMakeLists.txt | 1 + openair2/LAYER2/MAC/slicing/slicing.c | 586 ++++++++++++++++++ openair2/LAYER2/MAC/slicing/slicing.h | 74 +++ .../LAYER2/MAC/slicing/slicing_internal.h | 46 ++ 4 files changed, 707 insertions(+) create mode 100644 openair2/LAYER2/MAC/slicing/slicing.c create mode 100644 openair2/LAYER2/MAC/slicing/slicing.h create mode 100644 openair2/LAYER2/MAC/slicing/slicing_internal.h diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 7e59f38e8d..0b60172747 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -1830,6 +1830,7 @@ set (MAC_SRC ${MAC_DIR}/eNB_scheduler_fairRR.c ${MAC_DIR}/eNB_scheduler_phytest.c ${MAC_DIR}/pre_processor.c + ${MAC_DIR}/slicing/slicing.c ${MAC_DIR}/config.c ${MAC_DIR}/config_ue.c ) diff --git a/openair2/LAYER2/MAC/slicing/slicing.c b/openair2/LAYER2/MAC/slicing/slicing.c new file mode 100644 index 0000000000..a1de326df0 --- /dev/null +++ b/openair2/LAYER2/MAC/slicing/slicing.c @@ -0,0 +1,586 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! + * \file slicing.c + * \brief Generic slicing helper functions and Static Slicing Implementation + * \author Robert Schmidt + * \date 2020 + * \email robert.schmidt@eurecom.fr + */ + +#define _GNU_SOURCE +#include +#include + +#include "assertions.h" +#include "common/utils/LOG/log.h" + +#include "slicing.h" +#include "slicing_internal.h" + +#include "common/ran_context.h" +extern RAN_CONTEXT_t RC; + +#define RET_FAIL(ret, x...) do { LOG_E(MAC, x); return ret; } while (0) + +int slicing_get_UE_slice_idx(slice_info_t *si, int UE_id) { + return si->UE_assoc_slice[UE_id]; +} + +void slicing_add_UE(slice_info_t *si, int UE_id) { + add_ue_list(&si->s[0]->UEs, UE_id); + si->UE_assoc_slice[UE_id] = 0; +} + +void _remove_UE(slice_t **s, uint8_t *assoc, int UE_id) { + const uint8_t i = assoc[UE_id]; + DevAssert(remove_ue_list(&s[i]->UEs, UE_id)); + assoc[UE_id] = -1; +} + +void slicing_remove_UE(slice_info_t *si, int UE_id) { + _remove_UE(si->s, si->UE_assoc_slice, UE_id); +} + +void _move_UE(slice_t **s, uint8_t *assoc, int UE_id, int to) { + const uint8_t i = assoc[UE_id]; + const int ri = remove_ue_list(&s[i]->UEs, UE_id); + if (!ri) + LOG_W(MAC, "did not find UE %d in DL slice index %d\n", UE_id, i); + add_ue_list(&s[to]->UEs, UE_id); + assoc[UE_id] = to; +} + +void slicing_move_UE(slice_info_t *si, int UE_id, int idx) { + DevAssert(idx >= -1 && idx < si->num); + if (idx >= 0) + _move_UE(si->s, si->UE_assoc_slice, UE_id, idx); +} + +int _exists_slice(uint8_t n, slice_t **s, int id) { + for (int i = 0; i < n; ++i) + if (s[i]->id == id) + return i; + return -1; +} + +slice_t *_add_slice(uint8_t *n, slice_t **s) { + s[*n] = calloc(1, sizeof(slice_t)); + if (!s[*n]) + return NULL; + init_ue_list(&s[*n]->UEs); + *n += 1; + return s[*n - 1]; +} + +slice_t *_remove_slice(uint8_t *n, slice_t **s, uint8_t *assoc, int idx) { + if (idx >= *n) + return NULL; + + slice_t *sr = s[idx]; + while (sr->UEs.head >= 0) + _move_UE(s, assoc, sr->UEs.head, 0); + + for (int i = idx + 1; i < *n; ++i) + s[i - 1] = s[i]; + *n -= 1; + s[*n] = NULL; + + for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) + if (assoc[i] > idx) + assoc[i] -= 1; + + if (sr->label) + free(sr->label); + + return sr; +} + +/************************ Static Slicing Implementation ************************/ + +int addmod_static_slice_dl(slice_info_t *si, + int id, + char *label, + void *algo, + void *slice_params_dl) { + static_slice_param_t *dl = slice_params_dl; + if (dl && dl->posLow > dl->posHigh) + RET_FAIL(-1, "%s(): slice id %d posLow > posHigh\n", __func__, id); + + uint8_t rbgMap[25] = { 0 }; + int index = _exists_slice(si->num, si->s, id); + if (index >= 0) { + for (int s = 0; s < si->num; ++s) { + static_slice_param_t *sd = dl && si->s[s]->id == id ? dl : si->s[s]->algo_data; + for (int i = sd->posLow; i <= sd->posHigh; ++i) { + if (rbgMap[i]) + RET_FAIL(-33, "%s(): overlap of slices detected at RBG %d\n", __func__, i); + rbgMap[i] = 1; + } + } + /* no problem, can allocate */ + slice_t *s = si->s[index]; + if (label) { + if (s->label) free(s->label); + s->label = label; + } + if (algo) { + s->dl_algo.unset(&s->dl_algo.data); + s->dl_algo = *(default_sched_dl_algo_t *) algo; + if (!s->dl_algo.data) + s->dl_algo.data = s->dl_algo.setup(); + } + if (dl) { + free(s->algo_data); + s->algo_data = dl; + } + return index; + } + + if (!dl) + RET_FAIL(-100, "%s(): no parameters for new slice %d, aborting\n", __func__, id); + + if (si->num >= MAX_STATIC_SLICES) + RET_FAIL(-2, "%s(): cannot have more than %d slices\n", __func__, MAX_STATIC_SLICES); + for (int s = 0; s < si->num; ++s) { + static_slice_param_t *sd = si->s[s]->algo_data; + for (int i = sd->posLow; i <= sd->posHigh; ++i) + rbgMap[i] = 1; + } + + for (int i = dl->posLow; i <= dl->posHigh; ++i) + if (rbgMap[i]) + RET_FAIL(-3, "%s(): overlap of slices detected at RBG %d\n", __func__, i); + + if (!algo) + RET_FAIL(-14, "%s(): no scheduler algorithm provided\n", __func__); + + slice_t *ns = _add_slice(&si->num, si->s); + if (!ns) + RET_FAIL(-4, "%s(): could not create new slice\n", __func__); + ns->id = id; + ns->label = label; + ns->dl_algo = *(default_sched_dl_algo_t *) algo; + if (!ns->dl_algo.data) + ns->dl_algo.data = ns->dl_algo.setup(); + ns->algo_data = dl; + + return si->num - 1; +} + +int addmod_static_slice_ul(slice_info_t *si, + int id, + char *label, + void *algo, + void *slice_params_ul) { + static_slice_param_t *ul = slice_params_ul; + /* Minimum 3RBs, because LTE stack requires this */ + if (ul && ul->posLow + 2 > ul->posHigh) + RET_FAIL(-1, "%s(): slice id %d posLow + 2 > posHigh\n", __func__, id); + + uint8_t rbMap[110] = { 0 }; + int index = _exists_slice(si->num, si->s, id); + if (index >= 0) { + for (int s = 0; s < si->num; ++s) { + static_slice_param_t *su = ul && si->s[s]->id == id && ul ? ul : si->s[s]->algo_data; + for (int i = su->posLow; i <= su->posHigh; ++i) { + if (rbMap[i]) + RET_FAIL(-33, "%s(): overlap of slices detected at RBG %d\n", __func__, i); + rbMap[i] = 1; + } + } + /* no problem, can allocate */ + slice_t *s = si->s[index]; + if (algo) { + s->ul_algo.unset(&s->ul_algo.data); + s->ul_algo = *(default_sched_ul_algo_t *) algo; + if (!s->ul_algo.data) + s->ul_algo.data = s->ul_algo.setup(); + } + if (label) { + if (s->label) free(s->label); + s->label = label; + } + if (ul) { + free(s->algo_data); + s->algo_data = ul; + } + return index; + } + + if (!ul) + RET_FAIL(-100, "%s(): no parameters for new slice %d, aborting\n", __func__, id); + + if (si->num >= MAX_STATIC_SLICES) + RET_FAIL(-2, "%s(): cannot have more than %d slices\n", __func__, MAX_STATIC_SLICES); + for (int s = 0; s < si->num; ++s) { + static_slice_param_t *sd = si->s[s]->algo_data; + for (int i = sd->posLow; i <= sd->posHigh; ++i) + rbMap[i] = 1; + } + + for (int i = ul->posLow; i <= ul->posHigh; ++i) + if (rbMap[i]) + RET_FAIL(-3, "%s(): overlap of slices detected at RBG %d\n", __func__, i); + + if (!algo) + RET_FAIL(-14, "%s(): no scheduler algorithm provided\n", __func__); + + slice_t *ns = _add_slice(&si->num, si->s); + if (!ns) + RET_FAIL(-4, "%s(): could not create new slice\n", __func__); + ns->id = id; + ns->label = label; + ns->ul_algo = *(default_sched_ul_algo_t *) algo; + if (!ns->ul_algo.data) + ns->ul_algo.data = ns->ul_algo.setup(); + ns->algo_data = ul; + + return si->num - 1; +} + +int remove_static_slice(slice_info_t *si, uint8_t slice_idx) { + if (slice_idx == 0) + return 0; + slice_t *sr = _remove_slice(&si->num, si->s, si->UE_assoc_slice, slice_idx); + if (!sr) + return 0; + free(sr->algo_data); + free(sr); + return 1; +} + +void static_dl(module_id_t mod_id, + int CC_id, + frame_t frame, + sub_frame_t subframe) { + UE_info_t *UE_info = &RC.mac[mod_id]->UE_info; + + store_dlsch_buffer(mod_id, CC_id, frame, subframe); + + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + + /* initialize per-UE scheduling information */ + ue_sched_ctrl->pre_nb_available_rbs[CC_id] = 0; + ue_sched_ctrl->dl_pow_off[CC_id] = 2; + memset(ue_sched_ctrl->rballoc_sub_UE[CC_id], 0, sizeof(ue_sched_ctrl->rballoc_sub_UE[CC_id])); + ue_sched_ctrl->pre_dci_dl_pdu_idx = -1; + } + + const int N_RBG = to_rbg(RC.mac[mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth); + const int RBGsize = get_min_rb_unit(mod_id, CC_id); + uint8_t *vrb_map = RC.mac[mod_id]->common_channels[CC_id].vrb_map; + uint8_t rbgalloc_mask[N_RBG_MAX]; + for (int i = 0; i < N_RBG; i++) { + // calculate mask: init to one + "AND" with vrb_map: + // if any RB in vrb_map is blocked (1), the current RBG will be 0 + rbgalloc_mask[i] = 1; + for (int j = 0; j < RBGsize; j++) + rbgalloc_mask[i] &= !vrb_map[RBGsize * i + j]; + } + + slice_info_t *s = RC.mac[mod_id]->pre_processor_dl.slices; + int max_num_ue; + switch (s->num) { + case 1: + max_num_ue = 4; + break; + case 2: + max_num_ue = 2; + break; + default: + max_num_ue = 1; + break; + } + for (int i = 0; i < s->num; ++i) { + if (s->s[i]->UEs.head < 0) + continue; + uint8_t rbgalloc_slice_mask[N_RBG_MAX]; + memset(rbgalloc_slice_mask, 0, sizeof(rbgalloc_slice_mask)); + static_slice_param_t *p = s->s[i]->algo_data; + int n_rbg_sched = 0; + for (int rbg = p->posLow; rbg <= p->posHigh && rbg <= N_RBG; ++rbg) { + rbgalloc_slice_mask[rbg] = rbgalloc_mask[rbg]; + n_rbg_sched += rbgalloc_mask[rbg]; + } + + s->s[i]->dl_algo.run(mod_id, + CC_id, + frame, + subframe, + &s->s[i]->UEs, + max_num_ue, // max_num_ue + n_rbg_sched, + rbgalloc_slice_mask, + s->s[i]->dl_algo.data); + } + + // the following block is meant for validation of the pre-processor to check + // whether all UE allocations are non-overlapping and is not necessary for + // scheduling functionality + char t[26] = "_________________________"; + t[N_RBG] = 0; + for (int i = 0; i < N_RBG; i++) + for (int j = 0; j < RBGsize; j++) + if (vrb_map[RBGsize*i+j] != 0) + t[i] = 'x'; + int print = 0; + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + const UE_sched_ctrl_t *ue_sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; + + if (ue_sched_ctrl->pre_nb_available_rbs[CC_id] == 0) + continue; + + LOG_D(MAC, + "%4d.%d UE%d %d RBs allocated, pre MCS %d\n", + frame, + subframe, + UE_id, + ue_sched_ctrl->pre_nb_available_rbs[CC_id], + UE_info->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1); + + print = 1; + + for (int i = 0; i < N_RBG; i++) { + if (!ue_sched_ctrl->rballoc_sub_UE[CC_id][i]) + continue; + for (int j = 0; j < RBGsize; j++) { + if (vrb_map[RBGsize*i+j] != 0) { + LOG_I(MAC, "%4d.%d DL scheduler allocation list: %s\n", frame, subframe, t); + LOG_E(MAC, "%4d.%d: UE %d allocated at locked RB %d/RBG %d\n", frame, + subframe, UE_id, RBGsize * i + j, i); + } + vrb_map[RBGsize*i+j] = 1; + } + t[i] = '0' + UE_id; + } + } + if (print) + LOG_D(MAC, "%4d.%d DL scheduler allocation list: %s\n", frame, subframe, t); +} + +void static_ul(module_id_t mod_id, + int CC_id, + frame_t frame, + sub_frame_t subframe, + frame_t sched_frame, + sub_frame_t sched_subframe) { + UE_info_t *UE_info = &RC.mac[mod_id]->UE_info; + const int N_RB_UL = to_prb(RC.mac[mod_id]->common_channels[CC_id].ul_Bandwidth); + COMMON_channels_t *cc = &RC.mac[mod_id]->common_channels[CC_id]; + + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + UE_TEMPLATE *UE_template = &UE_info->UE_template[CC_id][UE_id]; + UE_template->pre_assigned_mcs_ul = 0; + UE_template->pre_allocated_nb_rb_ul = 0; + UE_template->pre_allocated_rb_table_index_ul = -1; + UE_template->pre_first_nb_rb_ul = 0; + UE_template->pre_dci_ul_pdu_idx = -1; + } + + slice_info_t *s = RC.mac[mod_id]->pre_processor_ul.slices; + int max_num_ue; + switch (s->num) { + case 1: + max_num_ue = 4; + break; + case 2: + max_num_ue = 2; + break; + default: + max_num_ue = 1; + break; + } + for (int i = 0; i < s->num; ++i) { + if (s->s[i]->UEs.head < 0) + continue; + int last_rb_blocked = 1; + int n_contig = 0; + contig_rbs_t rbs[2]; // up to two contig RBs for PRACH in between + static_slice_param_t *p = s->s[i]->algo_data; + for (int rb = p->posLow; rb <= p->posHigh && rb < N_RB_UL; ++rb) { + if (cc->vrb_map_UL[rb] == 0 && last_rb_blocked) { + last_rb_blocked = 0; + n_contig++; + AssertFatal(n_contig <= 2, "cannot handle more than two contiguous RB regions\n"); + rbs[n_contig - 1].start = rb; + } + if (cc->vrb_map_UL[rb] == 1 && !last_rb_blocked) { + last_rb_blocked = 1; + rbs[n_contig - 1].length = rb - rbs[n_contig - 1].start; + } + } + if (!last_rb_blocked) + rbs[n_contig - 1].length = p->posHigh - rbs[n_contig - 1].start + 1; + + s->s[i]->ul_algo.run(mod_id, + CC_id, + frame, + subframe, + sched_frame, + sched_subframe, + &s->s[i]->UEs, + max_num_ue, // max_num_ue + n_contig, + rbs, + s->s[i]->ul_algo.data); + } + + // the following block is meant for validation of the pre-processor to check + // whether all UE allocations are non-overlapping and is not necessary for + // scheduling functionality + char t[101] = "__________________________________________________" + "__________________________________________________"; + t[N_RB_UL] = 0; + for (int j = 0; j < N_RB_UL; j++) + if (cc->vrb_map_UL[j] != 0) + t[j] = 'x'; + int print = 0; + for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) { + UE_TEMPLATE *UE_template = &UE_info->UE_template[CC_id][UE_id]; + if (UE_template->pre_allocated_nb_rb_ul == 0) + continue; + + print = 1; + uint8_t harq_pid = subframe2harqpid(&RC.mac[mod_id]->common_channels[CC_id], + sched_frame, sched_subframe); + LOG_D(MAC, "%4d.%d UE%d %d RBs (index %d) at start %d, pre MCS %d %s\n", + frame, + subframe, + UE_id, + UE_template->pre_allocated_nb_rb_ul, + UE_template->pre_allocated_rb_table_index_ul, + UE_template->pre_first_nb_rb_ul, + UE_template->pre_assigned_mcs_ul, + UE_info->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid] > 0 ? "(retx)" : ""); + + for (int i = 0; i < UE_template->pre_allocated_nb_rb_ul; ++i) { + /* only check if this is not a retransmission */ + if (UE_info->UE_sched_ctrl[UE_id].round_UL[CC_id][harq_pid] == 0 + && cc->vrb_map_UL[UE_template->pre_first_nb_rb_ul + i] == 1) { + + LOG_I(MAC, "%4d.%d UL scheduler allocation list: %s\n", frame, subframe, t); + LOG_E(MAC, + "%4d.%d: UE %d allocated at locked RB %d (is: allocated start " + "%d/length %d)\n", + frame, subframe, UE_id, UE_template->pre_first_nb_rb_ul + i, + UE_template->pre_first_nb_rb_ul, + UE_template->pre_allocated_nb_rb_ul); + } + cc->vrb_map_UL[UE_template->pre_first_nb_rb_ul + i] = 1; + t[UE_template->pre_first_nb_rb_ul + i] = UE_id + '0'; + } + } + if (print) + LOG_D(MAC, + "%4d.%d UL scheduler allocation list: %s\n", + sched_frame, + sched_subframe, + t); +} + +void static_destroy(slice_info_t **si) { + const int n = (*si)->num; + (*si)->num = 0; + for (int i = 0; i < n; ++i) { + slice_t *s = (*si)->s[i]; + if (s->label) + free(s->label); + free(s->algo_data); + free(s); + } + free((*si)->s); + free(*si); +} + +pp_impl_param_t static_dl_init(module_id_t mod_id, int CC_id) { + slice_info_t *si = calloc(1, sizeof(slice_info_t)); + DevAssert(si); + + si->num = 0; + si->s = calloc(MAX_STATIC_SLICES, sizeof(slice_t)); + DevAssert(si->s); + for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) + si->UE_assoc_slice[i] = -1; + + /* insert default slice, all resources */ + static_slice_param_t *dlp = malloc(sizeof(static_slice_param_t)); + dlp->posLow = 0; + dlp->posHigh = to_rbg(RC.mac[mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth) - 1; + default_sched_dl_algo_t *algo = &RC.mac[mod_id]->pre_processor_dl.dl_algo; + DevAssert(0 == addmod_static_slice_dl(si, 0, strdup("default"), algo, dlp)); + const UE_list_t *UE_list = &RC.mac[mod_id]->UE_info.list; + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) + slicing_add_UE(si, UE_id); + + pp_impl_param_t sttc; + sttc.algorithm = STATIC_SLICING; + sttc.add_UE = slicing_add_UE; + sttc.remove_UE = slicing_remove_UE; + sttc.move_UE = slicing_move_UE; + sttc.addmod_slice = addmod_static_slice_dl; + sttc.remove_slice = remove_static_slice; + sttc.dl = static_dl; + // current DL algo becomes default scheduler + sttc.dl_algo = *algo; + sttc.destroy = static_destroy; + sttc.slices = si; + + return sttc; +} + +pp_impl_param_t static_ul_init(module_id_t mod_id, int CC_id) { + slice_info_t *si = calloc(1, sizeof(slice_info_t)); + DevAssert(si); + + si->num = 0; + si->s = calloc(MAX_STATIC_SLICES, sizeof(slice_t)); + DevAssert(si->s); + for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i) + si->UE_assoc_slice[i] = -1; + + /* insert default slice, all resources */ + static_slice_param_t *ulp = malloc(sizeof(static_slice_param_t)); + ulp->posLow = 0; + ulp->posHigh = to_prb(RC.mac[mod_id]->common_channels[CC_id].ul_Bandwidth) - 1; + default_sched_ul_algo_t *algo = &RC.mac[mod_id]->pre_processor_ul.ul_algo; + DevAssert(0 == addmod_static_slice_ul(si, 0, strdup("default"), algo, ulp)); + const UE_list_t *UE_list = &RC.mac[mod_id]->UE_info.list; + for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) + slicing_add_UE(si, UE_id); + + pp_impl_param_t sttc; + sttc.algorithm = STATIC_SLICING; + sttc.add_UE = slicing_add_UE; + sttc.remove_UE = slicing_remove_UE; + sttc.move_UE = slicing_move_UE; + sttc.addmod_slice = addmod_static_slice_ul; + sttc.remove_slice = remove_static_slice; + sttc.ul = static_ul; + // current DL algo becomes default scheduler + sttc.ul_algo = *algo; + sttc.destroy = static_destroy; + sttc.slices = si; + + return sttc; +} diff --git a/openair2/LAYER2/MAC/slicing/slicing.h b/openair2/LAYER2/MAC/slicing/slicing.h new file mode 100644 index 0000000000..1099b50ea0 --- /dev/null +++ b/openair2/LAYER2/MAC/slicing/slicing.h @@ -0,0 +1,74 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! + * \file slicing.h + * \brief General slice definition and helper parameters + * \author Robert Schmidt + * \date 2020 + * \email robert.schmidt@eurecom.fr + */ + +#ifndef __SLICING_H__ +#define __SLICING_H__ + +#include "openair2/LAYER2/MAC/mac.h" + +typedef struct slice_s { + /// Arbitrary ID + slice_id_t id; + /// Arbitrary label + char *label; + + union { + default_sched_dl_algo_t dl_algo; + default_sched_ul_algo_t ul_algo; + }; + + /// A specific algorithm's implementation parameters + void *algo_data; + /// Internal data that might be kept alongside a slice's params + void *int_data; + + // list of users in this slice + UE_list_t UEs; +} slice_t; + +typedef struct slice_info_s { + uint8_t num; + slice_t **s; + uint8_t UE_assoc_slice[MAX_MOBILES_PER_ENB]; +} slice_info_t; + +int slicing_get_UE_slice_idx(slice_info_t *si, int UE_id); + +#define STATIC_SLICING 10 +/* only four static slices for UL, DL resp. (not enough DCIs) */ +#define MAX_STATIC_SLICES 4 +typedef struct { + uint16_t posLow; + uint16_t posHigh; +} static_slice_param_t; +pp_impl_param_t static_dl_init(module_id_t mod_id, int CC_id); +pp_impl_param_t static_ul_init(module_id_t mod_id, int CC_id); + + +#endif /* __SLICING_H__ */ diff --git a/openair2/LAYER2/MAC/slicing/slicing_internal.h b/openair2/LAYER2/MAC/slicing/slicing_internal.h new file mode 100644 index 0000000000..744f8924d9 --- /dev/null +++ b/openair2/LAYER2/MAC/slicing/slicing_internal.h @@ -0,0 +1,46 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! + * \file slicing_internal.h + * \brief Internal slice helper functions + * \author Robert Schmidt + * \date 2020 + * \email robert.schmidt@eurecom.fr + */ + +#ifndef __SLICING_INTERNAL_H__ +#define __SLICING_INTERNAL_H__ + +#include "slicing.h" + +void slicing_add_UE(slice_info_t *si, int UE_id); + +void _remove_UE(slice_t **s, uint8_t *assoc, int UE_id); +void slicing_remove_UE(slice_info_t *si, int UE_id); + +void _move_UE(slice_t **s, uint8_t *assoc, int UE_id, int to); +void slicing_move_UE(slice_info_t *si, int UE_id, int idx); + +slice_t *_add_slice(uint8_t *n, slice_t **s); +slice_t *_remove_slice(uint8_t *n, slice_t **s, uint8_t *assoc, int idx); + +#endif /* __SLICING_INTERNAL_H__ */ From 4901daf75901901d66df158bc10a10db471f53f3 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 18 Jun 2020 19:12:15 +0200 Subject: [PATCH 58/66] FlexRAN: New protobuf slice structure + Static Slice handling --- .../CONTROL_MODULES/MAC/flexran_agent_mac.c | 139 ++++++--- .../CONTROL_MODULES/MAC/flexran_agent_mac.h | 13 +- .../MAC/flexran_agent_mac_internal.c | 202 ++++++++++--- .../MAC/flexran_agent_mac_internal.h | 20 +- .../ENB_APP/MESSAGES/V2/config_common.proto | 25 ++ .../ENB_APP/MESSAGES/V2/config_messages.proto | 2 + openair2/ENB_APP/flexran_agent_common.c | 12 +- openair2/ENB_APP/flexran_agent_ran_api.c | 277 ++++++++++++++++-- openair2/ENB_APP/flexran_agent_ran_api.h | 45 ++- openair2/LAYER2/MAC/main.c | 2 + openair2/LAYER2/MAC/slicing/slicing.c | 21 +- 11 files changed, 614 insertions(+), 144 deletions(-) diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c index 4800fccea9..e5d1c94c95 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c @@ -1452,9 +1452,74 @@ void flexran_agent_fill_mac_cell_config(mid_t mod_id, uint8_t cc_id, conf->si_config->has_sfn = 1; } - /* get a pointer to the config which is maintained in the agent throughout - * its lifetime */ - conf->slice_config = flexran_agent_get_slice_config(mod_id); + conf->slice_config = malloc(sizeof(Protocol__FlexSliceConfig)); + if (conf->slice_config) { + protocol__flex_slice_config__init(conf->slice_config); + Protocol__FlexSliceConfig *sc = conf->slice_config; + + sc->dl = malloc(sizeof(Protocol__FlexSliceDlUlConfig)); + DevAssert(sc->dl); + protocol__flex_slice_dl_ul_config__init(sc->dl); + sc->dl->algorithm = flexran_get_dl_slice_algo(mod_id); + sc->dl->has_algorithm = 1; + sc->dl->n_slices = flexran_get_num_dl_slices(mod_id); + if (sc->dl->n_slices > 0) { + sc->dl->slices = calloc(sc->dl->n_slices, sizeof(Protocol__FlexSlice *)); + DevAssert(sc->dl->slices); + for (int i = 0; i < sc->dl->n_slices; ++i) { + sc->dl->slices[i] = malloc(sizeof(Protocol__FlexSlice)); + DevAssert(sc->dl->slices[i]); + protocol__flex_slice__init(sc->dl->slices[i]); + flexran_get_dl_slice(mod_id, i, sc->dl->slices[i], sc->dl->algorithm); + } + } else { + sc->dl->scheduler = flexran_get_dl_scheduler_name(mod_id); + } + + sc->ul = malloc(sizeof(Protocol__FlexSliceDlUlConfig)); + DevAssert(sc->ul); + protocol__flex_slice_dl_ul_config__init(sc->ul); + sc->ul->algorithm = flexran_get_ul_slice_algo(mod_id); + sc->ul->has_algorithm = 1; + sc->ul->n_slices = flexran_get_num_ul_slices(mod_id); + if (sc->ul->n_slices > 0) { + sc->ul->slices = calloc(sc->ul->n_slices, sizeof(Protocol__FlexSlice *)); + DevAssert(sc->ul->slices); + for (int i = 0; i < sc->ul->n_slices; ++i) { + sc->ul->slices[i] = malloc(sizeof(Protocol__FlexSlice)); + DevAssert(sc->ul->slices[i]); + protocol__flex_slice__init(sc->ul->slices[i]); + flexran_get_ul_slice(mod_id, i, sc->ul->slices[i], sc->ul->algorithm); + } + } else { + sc->ul->scheduler = flexran_get_ul_scheduler_name(mod_id); + } + } +} + +void flexran_agent_destroy_mac_slice_config(Protocol__FlexCellConfig *conf) { + Protocol__FlexSliceConfig *sc = conf->slice_config; + for (int i = 0; i < sc->dl->n_slices; ++i) { + free(sc->dl->slices[i]); + sc->dl->slices[i] = NULL; + /* scheduler names are not freed: we assume we read them directly from the + * underlying memory and do not dispose it */ + } + free(sc->dl->slices); + /* scheduler name is not freed */ + free(sc->dl); + sc->dl = NULL; + for (int i = 0; i < sc->ul->n_slices; ++i) { + free(sc->ul->slices[i]); + sc->ul->slices[i] = NULL; + /* scheduler names are not freed */ + } + free(sc->ul->slices); + /* scheduler name is not freed */ + free(sc->ul); + sc->ul = NULL; + free(conf->slice_config); + conf->slice_config = NULL; } void flexran_agent_fill_mac_ue_config(mid_t mod_id, mid_t ue_id, @@ -1568,46 +1633,46 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id) return 0; } - -void flexran_create_config_structures(mid_t mod_id) -{ - int i; - int n_dl = flexran_get_num_dl_slices(mod_id); - int m_ul = flexran_get_num_ul_slices(mod_id); - slice_config[mod_id] = flexran_agent_create_slice_config(n_dl, m_ul); - sc_update[mod_id] = flexran_agent_create_slice_config(n_dl, m_ul); - if (!slice_config[mod_id] || !sc_update[mod_id]) return; - - //flexran_agent_read_slice_config(mod_id, slice_config[mod_id]); - //flexran_agent_read_slice_config(mod_id, sc_update[mod_id]); - for (i = 0; i < n_dl; i++) { - //flexran_agent_read_slice_dl_config(mod_id, i, slice_config[mod_id]->dl[i]); - //flexran_agent_read_slice_dl_config(mod_id, i, sc_update[mod_id]->dl[i]); +void helper_destroy_mac_slice_config(Protocol__FlexSliceConfig *slice_config) { + if (slice_config->dl) { + if (slice_config->dl->scheduler) + free(slice_config->dl->scheduler); + for (int i = 0; i < slice_config->dl->n_slices; i++) + if (slice_config->dl->slices[i]->scheduler) + free(slice_config->dl->slices[i]->scheduler); } - for (i = 0; i < m_ul; i++) { - //flexran_agent_read_slice_ul_config(mod_id, i, slice_config[mod_id]->ul[i]); - //flexran_agent_read_slice_ul_config(mod_id, i, sc_update[mod_id]->ul[i]); + if (slice_config->ul) { + if (slice_config->ul->scheduler) + free(slice_config->ul->scheduler); + for (int i = 0; i < slice_config->ul->n_slices; i++) + if (slice_config->ul->slices[i]->scheduler) + free(slice_config->ul->slices[i]->scheduler); } + + Protocol__FlexCellConfig helper; + helper.slice_config = slice_config; + flexran_agent_destroy_mac_slice_config(&helper); } -void flexran_check_and_remove_slices(mid_t mod_id) -{ +void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig **slice_config) { + if (!*slice_config) return; + Protocol__FlexSliceConfig *sc = *slice_config; + *slice_config = NULL; + + /* TODO handle using lock-free queue */ + apply_update_dl_slice_config(mod_id, sc->dl); + apply_update_ul_slice_config(mod_id, sc->ul); + + helper_destroy_mac_slice_config(*slice_config); } -void flexran_agent_slice_update(mid_t mod_id) -{ +void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig **ue_config) { + /* TODO handle using lock-free queue */ + apply_ue_slice_assoc_update(mod_id, *ue_config); + + free(*ue_config); + *ue_config = NULL; } -Protocol__FlexSliceConfig *flexran_agent_get_slice_config(mid_t mod_id) -{ - if (!slice_config[mod_id]) return NULL; - Protocol__FlexSliceConfig *config = NULL; - - pthread_mutex_lock(&sc_update_mtx); - if (!config) { - pthread_mutex_unlock(&sc_update_mtx); - return NULL; - } - pthread_mutex_unlock(&sc_update_mtx); - return config; +void flexran_agent_slice_update(mid_t mod_id) { } diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h index 2f9f99c740..5a8d4f31aa 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h @@ -115,7 +115,16 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id); /* Inform controller about possibility to update slice configuration */ void flexran_agent_slice_update(mid_t mod_id); -/* return a pointer to the current config */ -Protocol__FlexSliceConfig *flexran_agent_get_slice_config(mid_t mod_id); +/* marks slice_config so that it can be applied later. Takes ownership of the + * FlexSliceConfig message */ +void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig **slice); + +/* inserts a new ue_config into the structure keeping ue to slice association + * updates and marks so it can be applied. Takes ownership of the FlexUeConfig message */ +void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig **ue_config); + +/* free slice_config part of flexCellConfig, filled in + * flexran_agent_fill_mac_cell_config() */ +void flexran_agent_destroy_mac_slice_config(Protocol__FlexCellConfig *conf); #endif diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c index 4c80c561ee..93de0b11ec 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.c @@ -1025,60 +1025,166 @@ int load_dl_scheduler_function(mid_t mod_id, const char *function_name) { } -Protocol__FlexSliceConfig *flexran_agent_create_slice_config(int n_dl, int m_ul) -{ - Protocol__FlexSliceConfig *fsc = malloc(sizeof(Protocol__FlexSliceConfig)); - if (!fsc) return NULL; - protocol__flex_slice_config__init(fsc); - - /* TODO */ - return fsc; -} - -void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *sup) -{ -} - - -void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config) -{ - if (n_ue_slice_assoc_updates == 10) { - LOG_E(FLEXRAN_AGENT, - "[%d] can not handle flex_ue_config message, buffer is full; try again later\n", - mod_id); - return; +void update_or_remove_dl(mid_t mod_id, Protocol__FlexSlice *s) { + if (s->params_case == PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET + && !s->label && !s->scheduler) { + LOG_I(FLEXRAN_AGENT, "remove DL slice ID %d\n", s->id); + const int rc = flexran_remove_dl_slice(mod_id, s); + if (!rc) + LOG_W(FLEXRAN_AGENT, "error while removing slice ID %d\n", s->id); + } else { + LOG_I(FLEXRAN_AGENT, "updating DL slice ID %d\n", s->id); + const int rc = flexran_create_dl_slice(mod_id, s); + if (rc < 0) + LOG_W(FLEXRAN_AGENT, + "error while update slice ID %d: flexran_create_dl_slice() -> %d\n", + s->id, rc); } +} + +void update_or_remove_ul(mid_t mod_id, Protocol__FlexSlice *s) { + if (s->params_case == PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET + && !s->label && !s->scheduler) { + LOG_I(FLEXRAN_AGENT, "remove UL slice ID %d\n", s->id); + const int rc = flexran_remove_ul_slice(mod_id, s); + if (!rc) + LOG_W(FLEXRAN_AGENT, "error while removing slice ID %d\n", s->id); + } else { + LOG_I(FLEXRAN_AGENT, "updating UL slice ID %d\n", s->id); + const int rc = flexran_create_ul_slice(mod_id, s); + if (rc < 0) + LOG_W(FLEXRAN_AGENT, + "error while updating slice ID %d: flexran_create_ul_slice() -> %d)\n", + s->id, rc); + } +} + +void apply_update_dl_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *dl) { + if (!dl) + return; + + Protocol__FlexSliceAlgorithm dl_algo = flexran_get_dl_slice_algo(mod_id); + if (dl->has_algorithm && dl_algo != dl->algorithm) { + LOG_I(FLEXRAN_AGENT, "loading new DL slice algorithm %d\n", dl->algorithm); + dl_algo = dl->algorithm; + flexran_set_dl_slice_algo(mod_id, dl_algo); + } + + /* first update existing slices, then create new. Thus, we go through the + * list twice. First round, if a slice exists, handle and mark as such. Then, + * apply all others in the second round */ + if (dl->n_slices > 0) { + if (dl_algo == PROTOCOL__FLEX_SLICE_ALGORITHM__None) { + LOG_E(FLEXRAN_AGENT, "cannot update slices: no algorithm loaded\n"); + return; + } + int handled_dl[dl->n_slices]; + for (int i = 0; i < dl->n_slices; ++i) { + if (flexran_find_dl_slice(mod_id, dl->slices[i]->id) < 0) { + handled_dl[i] = 0; + continue; + } + update_or_remove_dl(mod_id, dl->slices[i]); + handled_dl[i] = 1; + } + for (int i = 0; i < dl->n_slices; ++i) { + if (handled_dl[i]) + continue; + update_or_remove_dl(mod_id, dl->slices[i]); + } + } + + if (dl->scheduler) { + if (dl_algo != PROTOCOL__FLEX_SLICE_ALGORITHM__None) { + LOG_E(FLEXRAN_AGENT, "cannot update scheduling algorithm: slice algorithm loaded\n"); + return; + } + LOG_I(FLEXRAN_AGENT, "loading DL new scheduling algorithm '%s'\n", dl->scheduler); + const int rc = flexran_set_dl_scheduler(mod_id, dl->scheduler); + if (rc < 0) { + LOG_E(FLEXRAN_AGENT, + "error while updating scheduling algorithm: " + "flexran_update_dl_sched_algo() -> %d)\n", + rc); + return; + } + } +} + +void apply_update_ul_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *ul) { + if (!ul) + return; + + Protocol__FlexSliceAlgorithm ul_algo = flexran_get_ul_slice_algo(mod_id); + if (ul->has_algorithm && ul_algo != ul->algorithm) { + LOG_I(FLEXRAN_AGENT, "loading new UL slice algorithm %d\n", ul->algorithm); + ul_algo = ul->algorithm; + flexran_set_ul_slice_algo(mod_id, ul_algo); + } + if (ul->n_slices > 0) { + if (ul_algo == PROTOCOL__FLEX_SLICE_ALGORITHM__None) { + LOG_E(FLEXRAN_AGENT, "cannot update slices: no algorithm loaded\n"); + return; + } + int handled_ul[ul->n_slices]; + for (int i = 0; i < ul->n_slices; ++i) { + if (flexran_find_ul_slice(mod_id, ul->slices[i]->id) < 0) { + handled_ul[i] = 0; + continue; + } + update_or_remove_ul(mod_id, ul->slices[i]); + handled_ul[i] = 1; + } + for (int i = 0; i < ul->n_slices; ++i) { + if (handled_ul[i]) + continue; + update_or_remove_ul(mod_id, ul->slices[i]); + } + } + + if (ul->scheduler) { + if (ul_algo != PROTOCOL__FLEX_SLICE_ALGORITHM__None) { + LOG_E(FLEXRAN_AGENT, "cannot update scheduling algorithm: slice algorithm loaded\n"); + return; + } + LOG_I(FLEXRAN_AGENT, "loading new UL scheduling algorithm '%s'\n", ul->scheduler); + const int rc = flexran_set_ul_scheduler(mod_id, ul->scheduler); + if (rc < 0) { + LOG_E(FLEXRAN_AGENT, + "error while updating scheduling algorithm: " + "flexran_update_dl_sched_algo() -> %d)\n", + rc); + return; + } + } +} + +int apply_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config) +{ if (!ue_config->has_rnti) { LOG_E(FLEXRAN_AGENT, "[%d] cannot update UE to slice association, no RNTI in flex_ue_config message\n", mod_id); - return; + return 0; } - if (ue_config->has_dl_slice_id) - LOG_I(FLEXRAN_AGENT, "[%d] associating UE RNTI %#x to DL slice ID %d\n", - mod_id, ue_config->rnti, ue_config->dl_slice_id); - if (ue_config->has_ul_slice_id) - LOG_I(FLEXRAN_AGENT, "[%d] associating UE RNTI %#x to UL slice ID %d\n", - mod_id, ue_config->rnti, ue_config->ul_slice_id); - ue_slice_assoc_update[n_ue_slice_assoc_updates++] = ue_config; - perform_slice_config_update_count = 2; -} - -int apply_ue_slice_assoc_update(mid_t mod_id) -{ - int i; - int changes = 0; - for (i = 0; i < n_ue_slice_assoc_updates; i++) { - int ue_id = find_UE_id(mod_id, ue_slice_assoc_update[i]->rnti); - if (ue_id < 0 || ue_id > MAX_MOBILES_PER_ENB){ - LOG_E(FLEXRAN_AGENT,"UE_id %d is wrong!!\n",ue_id); - continue; - } - if (ue_slice_assoc_update[i]->has_dl_slice_id) { - } - if (ue_slice_assoc_update[i]->has_ul_slice_id) { + int UE_id = flexran_get_mac_ue_id_rnti(mod_id, ue_config->rnti); + if (ue_config->has_dl_slice_id) { + if (flexran_get_dl_slice_algo(mod_id) == PROTOCOL__FLEX_SLICE_ALGORITHM__None) { + LOG_E(FLEXRAN_AGENT, "no DL slice algorithm loaded\n"); + } else { + LOG_I(FLEXRAN_AGENT, "[%d] associating UE RNTI %04x - %d/UE %d to DL slice ID %d\n", + mod_id, ue_config->rnti, ue_config->rnti, UE_id, ue_config->dl_slice_id); + flexran_set_ue_dl_slice_id(mod_id, UE_id, ue_config->dl_slice_id); } } - n_ue_slice_assoc_updates = 0; - return changes; + if (ue_config->has_ul_slice_id) { + if (flexran_get_ul_slice_algo(mod_id) == PROTOCOL__FLEX_SLICE_ALGORITHM__None) { + LOG_E(FLEXRAN_AGENT, "no UL slice algorithm loaded\n"); + } else { + LOG_I(FLEXRAN_AGENT, "[%d] associating UE RNTI %04x - %d/UE %d to UL slice ID %d\n", + mod_id, ue_config->rnti, ue_config->rnti, UE_id, ue_config->ul_slice_id); + flexran_set_ue_ul_slice_id(mod_id, UE_id, ue_config->ul_slice_id); + } + } + return 0; } diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h index ef2a7e40a9..9db5d61a11 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac_internal.h @@ -103,23 +103,11 @@ int load_dl_scheduler_function(mid_t mod_id, const char *function_name); /*** Functions for handling a slice config ***/ -/* allocate memory for a Protocol__FlexSliceConfig structure with n_dl DL slice - * configs and m_ul UL slice configs */ -Protocol__FlexSliceConfig *flexran_agent_create_slice_config(int n_dl, int m_ul); - -/* read the general slice parameters via RAN into the given - * Protocol__FlexSliceConfig struct */ -void flexran_agent_read_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *s); - -/* reads content of slice over the sc_update structure, so that it can be - * applied later by performing a diff between slice_config and sc_update */ -void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig *slice); - -/* inserts a new ue_config into the structure keeping ue to slice association - * updates and marks so it can be applied */ -void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config); +/* Prepare the application of a slicing config */ +void apply_update_dl_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *slice); +void apply_update_ul_slice_config(mid_t mod_id, Protocol__FlexSliceDlUlConfig *slice); /* apply a new association between a UE and a slice (both DL and UL) */ -int apply_ue_slice_assoc_update(mid_t mod_id); +int apply_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig *ue_config); #endif /*FLEXRAN_AGENT_MAC_INTERNAL_H_*/ diff --git a/openair2/ENB_APP/MESSAGES/V2/config_common.proto b/openair2/ENB_APP/MESSAGES/V2/config_common.proto index e5d01ebdc0..2f2267b628 100644 --- a/openair2/ENB_APP/MESSAGES/V2/config_common.proto +++ b/openair2/ENB_APP/MESSAGES/V2/config_common.proto @@ -61,6 +61,31 @@ enum flex_qam { // // Slice config related structures and enums // +enum flex_slice_algorithm { + None = 0; + Static = 1; + NVS = 2; +} + +message flex_slice_static { + optional uint32 posLow = 1; + optional uint32 posHigh = 2; +} + +message flex_slice { + optional uint32 id = 1; + optional string label = 2; + optional string scheduler = 3; + oneof params { + flex_slice_static static = 10; + } +} + +message flex_slice_dl_ul_config { + optional flex_slice_algorithm algorithm = 1; + repeated flex_slice slices = 2; + optional string scheduler = 3; // if no slicing +} // // UE config related structures and enums diff --git a/openair2/ENB_APP/MESSAGES/V2/config_messages.proto b/openair2/ENB_APP/MESSAGES/V2/config_messages.proto index 1a66a4f20f..1a69deec71 100644 --- a/openair2/ENB_APP/MESSAGES/V2/config_messages.proto +++ b/openair2/ENB_APP/MESSAGES/V2/config_messages.proto @@ -49,6 +49,8 @@ message flex_cell_config { } message flex_slice_config { + optional flex_slice_dl_ul_config dl = 6; + optional flex_slice_dl_ul_config ul = 7; } message flex_ue_config { diff --git a/openair2/ENB_APP/flexran_agent_common.c b/openair2/ENB_APP/flexran_agent_common.c index 3dd9f5b957..7569ca1ac1 100644 --- a/openair2/ENB_APP/flexran_agent_common.c +++ b/openair2/ENB_APP/flexran_agent_common.c @@ -306,6 +306,7 @@ int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg) { if (reply->cell_config[i]->mbsfn_subframe_config_sfalloc) free(reply->cell_config[i]->mbsfn_subframe_config_sfalloc); + /* si_config is shared between MAC and RRC, free here */ if (reply->cell_config[i]->si_config) { for(int j = 0; j < reply->cell_config[i]->si_config->n_si_message; j++) { free(reply->cell_config[i]->si_config->si_message[j]); @@ -316,8 +317,7 @@ int flexran_agent_destroy_enb_config_reply(Protocol__FlexranMessage *msg) { } if (reply->cell_config[i]->slice_config) { - /* TODO */ - free(reply->cell_config[i]->slice_config); + flexran_agent_destroy_mac_slice_config(reply->cell_config[i]); } free(reply->cell_config[i]); @@ -880,7 +880,7 @@ int flexran_agent_handle_enb_config_reply(mid_t mod_id, const void *params, Prot if (enb_config->n_cell_config > 0) { if (flexran_agent_get_mac_xface(mod_id) && enb_config->cell_config[0]->slice_config) { - prepare_update_slice_config(mod_id, enb_config->cell_config[0]->slice_config); + prepare_update_slice_config(mod_id, &enb_config->cell_config[0]->slice_config); } if (enb_config->cell_config[0]->has_eutra_band && enb_config->cell_config[0]->has_dl_freq @@ -921,7 +921,11 @@ int flexran_agent_handle_ue_config_reply(mid_t mod_id, const void *params, Proto Protocol__FlexUeConfigReply *ue_config_reply = input->ue_config_reply_msg; for (i = 0; flexran_agent_get_mac_xface(mod_id) && i < ue_config_reply->n_ue_config; i++) - prepare_ue_slice_assoc_update(mod_id, ue_config_reply->ue_config[i]); + prepare_ue_slice_assoc_update(mod_id, &ue_config_reply->ue_config[i]); + /* prepare_ue_slice_assoc_update takes ownership of the individual + * FlexUeConfig messages. Therefore, mark zero messages to not accidentally + * free them twice */ + ue_config_reply->n_ue_config = 0; *msg = NULL; return 0; diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index cd8b0b8f67..79c992a4d7 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -30,6 +30,7 @@ #include "flexran_agent_ran_api.h" #include "s1ap_eNB_ue_context.h" #include "s1ap_eNB_management_procedures.h" +#include "openair2/LAYER2/MAC/slicing/slicing.h" static inline int phy_is_present(mid_t mod_id, uint8_t cc_id) { return RC.eNB && RC.eNB[mod_id] && RC.eNB[mod_id][cc_id]; @@ -3013,66 +3014,294 @@ uint32_t flexran_get_rrc_enb_ue_s1ap_id(mid_t mod_id, rnti_t rnti) } /**************************** SLICING ****************************/ +Protocol__FlexSliceAlgorithm flexran_get_dl_slice_algo(mid_t mod_id) { + if (!mac_is_present(mod_id)) return PROTOCOL__FLEX_SLICE_ALGORITHM__None; + + switch (RC.mac[mod_id]->pre_processor_dl.algorithm) { + case STATIC_SLICING: + return PROTOCOL__FLEX_SLICE_ALGORITHM__Static; + default: + return PROTOCOL__FLEX_SLICE_ALGORITHM__None; + } +} + +int flexran_set_dl_slice_algo(mid_t mod_id, Protocol__FlexSliceAlgorithm algo) { + if (!mac_is_present(mod_id)) return 0; + eNB_MAC_INST *mac = RC.mac[mod_id]; + const int cc_id = 0; + + pp_impl_param_t dl = mac->pre_processor_dl; + switch (algo) { + case PROTOCOL__FLEX_SLICE_ALGORITHM__Static: + mac->pre_processor_dl = static_dl_init(mod_id, cc_id); + break; + default: + mac->pre_processor_dl.algorithm = 0; + mac->pre_processor_dl.dl = dlsch_scheduler_pre_processor; + mac->pre_processor_dl.dl_algo.data = mac->pre_processor_dl.dl_algo.setup(); + mac->pre_processor_dl.slices = NULL; + break; + } + if (dl.slices) + dl.destroy(&dl.slices); + if (dl.dl_algo.data) + dl.dl_algo.unset(&dl.dl_algo.data); + return 1; +} + +Protocol__FlexSliceAlgorithm flexran_get_ul_slice_algo(mid_t mod_id) { + if (!mac_is_present(mod_id)) return PROTOCOL__FLEX_SLICE_ALGORITHM__None; + + switch (RC.mac[mod_id]->pre_processor_ul.algorithm) { + case STATIC_SLICING: + return PROTOCOL__FLEX_SLICE_ALGORITHM__Static; + default: + return PROTOCOL__FLEX_SLICE_ALGORITHM__None; + } +} + +int flexran_set_ul_slice_algo(mid_t mod_id, Protocol__FlexSliceAlgorithm algo) { + if (!mac_is_present(mod_id)) return 0; + eNB_MAC_INST *mac = RC.mac[mod_id]; + const int cc_id = 0; + + pp_impl_param_t ul = mac->pre_processor_ul; + switch (algo) { + case PROTOCOL__FLEX_SLICE_ALGORITHM__Static: + mac->pre_processor_ul = static_ul_init(mod_id, cc_id); + break; + default: + mac->pre_processor_ul.algorithm = 0; + mac->pre_processor_ul.ul = ulsch_scheduler_pre_processor; + mac->pre_processor_ul.ul_algo.data = mac->pre_processor_ul.ul_algo.setup(); + mac->pre_processor_ul.slices = NULL; + break; + } + if (ul.slices) + ul.destroy(&ul.slices); + if (ul.ul_algo.data) + ul.ul_algo.unset(&ul.ul_algo.data); + return 1; +} + int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return -1; - return 0; + slice_info_t *slices = RC.mac[mod_id]->pre_processor_dl.slices; + if (!slices) return -1; + const int idx = slices->UE_assoc_slice[ue_id]; + return slices->s[idx]->id; +} + +void flexran_set_ue_dl_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) { + if (!mac_is_present(mod_id)) return; + int idx = flexran_find_dl_slice(mod_id, slice_id); + if (idx < 0) return; + pp_impl_param_t *dl = &RC.mac[mod_id]->pre_processor_dl; + dl->move_UE(dl->slices, ue_id, idx); } int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id) { if (!mac_is_present(mod_id)) return -1; - return 0; + slice_info_t *slices = RC.mac[mod_id]->pre_processor_ul.slices; + if (!slices) return -1; + const int idx = slices->UE_assoc_slice[ue_id]; + return slices->s[idx]->id; } -/* TODO */ -int flexran_create_dl_slice(mid_t mod_id, slice_id_t slice_id) { - if (!mac_is_present(mod_id)) return -1; - return -1; +void flexran_set_ue_ul_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id) { + if (!mac_is_present(mod_id)) return; + int idx = flexran_find_ul_slice(mod_id, slice_id); + if (idx < 0) return; + pp_impl_param_t *ul = &RC.mac[mod_id]->pre_processor_ul; + ul->move_UE(ul->slices, ue_id, idx); } -/* TODO */ -int flexran_remove_dl_slice(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; +int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s) { + if (!mac_is_present(mod_id)) return 0; + void *params = NULL; + switch (s->params_case) { + case PROTOCOL__FLEX_SLICE__PARAMS_STATIC: + params = malloc(sizeof(static_slice_param_t)); + if (!params) return 0; + ((static_slice_param_t *)params)->posLow = s->static_->poslow; + ((static_slice_param_t *)params)->posHigh = s->static_->poshigh; + break; + default: + break; + } + pp_impl_param_t *dl = &RC.mac[mod_id]->pre_processor_dl; + char *l = s->label ? strdup(s->label) : NULL; + void *algo = &dl->dl_algo; // default scheduler + if (s->scheduler) { + algo = dlsym(NULL, s->scheduler); + if (!algo) { + free(params); + LOG_E(FLEXRAN_AGENT, "cannot locate scheduler '%s'\n", s->scheduler); + return -15; + } + } + return dl->addmod_slice(dl->slices, s->id, l, algo, params); +} + +int flexran_remove_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s) { + if (!mac_is_present(mod_id)) return 0; + const int idx = flexran_find_dl_slice(mod_id, s->id); + if (idx < 0) return 0; + pp_impl_param_t *dl = &RC.mac[mod_id]->pre_processor_dl; + return dl->remove_slice(dl->slices, idx); } int flexran_find_dl_slice(mid_t mod_id, slice_id_t slice_id) { if (!mac_is_present(mod_id)) return -1; + slice_info_t *si = RC.mac[mod_id]->pre_processor_dl.slices; + for (int i = 0; i < si->num; ++i) + if (si->s[i]->id == slice_id) + return i; return -1; } -//int flexran_get_dl_slice(mid_t mod_id, int slice_idx, Protocol__FlexSlice *s) { -//} +void flexran_get_dl_slice(mid_t mod_id, + int slice_idx, + Protocol__FlexSlice *slice, + Protocol__FlexSliceAlgorithm algo) { + if (!mac_is_present(mod_id)) return; + slice_t *s_ = RC.mac[mod_id]->pre_processor_dl.slices->s[slice_idx]; + slice->has_id = 1; + slice->id = s_->id; + slice->label = s_->label; + slice->scheduler = s_->dl_algo.name; + slice->params_case = PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET; + switch (algo) { + case PROTOCOL__FLEX_SLICE_ALGORITHM__Static: + slice->static_ = malloc(sizeof(Protocol__FlexSliceStatic)); + if (!slice->static_) return; + protocol__flex_slice_static__init(slice->static_); + slice->static_->has_poslow = 1; + slice->static_->poslow = ((static_slice_param_t *)s_->algo_data)->posLow; + slice->static_->has_poshigh = 1; + slice->static_->poshigh = ((static_slice_param_t *)s_->algo_data)->posHigh; + slice->params_case = PROTOCOL__FLEX_SLICE__PARAMS_STATIC; + break; + default: + break; + } +} int flexran_get_num_dl_slices(mid_t mod_id) { - if (!mac_is_present(mod_id)) return -1; - return 0; + if (!mac_is_present(mod_id)) return 0; + if (!RC.mac[mod_id]->pre_processor_dl.slices) return 0; + return RC.mac[mod_id]->pre_processor_dl.slices->num; } -/* TODO */ -void flexran_create_ul_slice(mid_t mod_id, slice_id_t slice_id) { - if (!mac_is_present(mod_id)) return; - return; +int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s) { + if (!mac_is_present(mod_id)) return -1; + void *params = NULL; + switch (s->params_case) { + case PROTOCOL__FLEX_SLICE__PARAMS_STATIC: + params = malloc(sizeof(static_slice_param_t)); + if (!params) return 0; + ((static_slice_param_t *)params)->posLow = s->static_->poslow; + ((static_slice_param_t *)params)->posHigh = s->static_->poshigh; + break; + default: + break; + } + pp_impl_param_t *ul = &RC.mac[mod_id]->pre_processor_ul; + char *l = s->label ? strdup(s->label) : NULL; + void *algo = &ul->ul_algo; // default scheduler + if (s->scheduler) { + algo = dlsym(NULL, s->scheduler); + if (!algo) { + free(params); + LOG_E(FLEXRAN_AGENT, "cannot locate scheduler '%s'\n", s->scheduler); + return -15; + } + } + return ul->addmod_slice(ul->slices, s->id, l, algo, params); } -/* TODO */ -int flexran_remove_ul_slice(mid_t mod_id, int slice_idx) { - if (!mac_is_present(mod_id)) return -1; - return -1; +int flexran_remove_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s) { + if (!mac_is_present(mod_id)) return 0; + const int idx = flexran_find_ul_slice(mod_id, s->id); + if (idx < 0) return 0; + pp_impl_param_t *ul = &RC.mac[mod_id]->pre_processor_ul; + return ul->remove_slice(ul->slices, idx); } int flexran_find_ul_slice(mid_t mod_id, slice_id_t slice_id) { if (!mac_is_present(mod_id)) return -1; + slice_info_t *si = RC.mac[mod_id]->pre_processor_ul.slices; + for (int i = 0; i < si->num; ++i) + if (si->s[i]->id == slice_id) + return i; return -1; } -//int flexran_get_ul_slice(mid_t mod_id, int slice_idx, Protocol__FlexSlice *s) { -//} +void flexran_get_ul_slice(mid_t mod_id, + int slice_idx, + Protocol__FlexSlice *slice, + Protocol__FlexSliceAlgorithm algo) { + if (!mac_is_present(mod_id)) return; + slice_t *s_ = RC.mac[mod_id]->pre_processor_ul.slices->s[slice_idx]; + slice->has_id = 1; + slice->id = s_->id; + slice->label = s_->label; + slice->scheduler = s_->ul_algo.name; + slice->params_case = PROTOCOL__FLEX_SLICE__PARAMS__NOT_SET; + switch (algo) { + case PROTOCOL__FLEX_SLICE_ALGORITHM__Static: + slice->static_ = malloc(sizeof(Protocol__FlexSliceStatic)); + if (!slice->static_) return; + protocol__flex_slice_static__init(slice->static_); + slice->static_->has_poslow = 1; + slice->static_->poslow = ((static_slice_param_t *)s_->algo_data)->posLow; + slice->static_->has_poshigh = 1; + slice->static_->poshigh = ((static_slice_param_t *)s_->algo_data)->posHigh; + slice->params_case = PROTOCOL__FLEX_SLICE__PARAMS_STATIC; + break; + default: + break; + } + +} int flexran_get_num_ul_slices(mid_t mod_id) { + if (!mac_is_present(mod_id)) return 0; + if (!RC.mac[mod_id]->pre_processor_ul.slices) return 0; + return RC.mac[mod_id]->pre_processor_ul.slices->num; +} + +char *flexran_get_dl_scheduler_name(mid_t mod_id) { + if (!mac_is_present(mod_id)) return NULL; + return RC.mac[mod_id]->pre_processor_dl.dl_algo.name; +} + +int flexran_set_dl_scheduler(mid_t mod_id, char *sched) { if (!mac_is_present(mod_id)) return -1; + void *d = dlsym(NULL, sched); + if (!d) return -2; + pp_impl_param_t *dl_pp = &RC.mac[mod_id]->pre_processor_dl; + dl_pp->dl_algo.unset(&dl_pp->dl_algo.data); + dl_pp->dl_algo = *(default_sched_dl_algo_t *) d; + dl_pp->dl_algo.data = dl_pp->dl_algo.setup(); return 0; } +char *flexran_get_ul_scheduler_name(mid_t mod_id) { + if (!mac_is_present(mod_id)) return NULL; + return RC.mac[mod_id]->pre_processor_ul.ul_algo.name; +} + +int flexran_set_ul_scheduler(mid_t mod_id, char *sched) { + if (!mac_is_present(mod_id)) return -1; + void *d = dlsym(NULL, sched); + if (!d) return -2; + pp_impl_param_t *ul_pp = &RC.mac[mod_id]->pre_processor_ul; + ul_pp->ul_algo.unset(&ul_pp->ul_algo.data); + ul_pp->ul_algo = *(default_sched_ul_algo_t *) d; + ul_pp->ul_algo.data = ul_pp->ul_algo.setup(); + return 0; +} /************************** S1AP **************************/ int flexran_get_s1ap_mme_pending(mid_t mod_id){ diff --git a/openair2/ENB_APP/flexran_agent_ran_api.h b/openair2/ENB_APP/flexran_agent_ran_api.h index c29ba53c11..2d8a86f7d0 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.h +++ b/openair2/ENB_APP/flexran_agent_ran_api.h @@ -656,41 +656,66 @@ int flexran_agent_rrc_gtp_get_teid_sgw(mid_t mod_id, rnti_t rnti, int index); uint32_t flexran_get_rrc_enb_ue_s1ap_id(mid_t mod_id, rnti_t rnti); /************************** Slice configuration **************************/ +/* Get the currently active DL slicing algorithm */ +Protocol__FlexSliceAlgorithm flexran_get_dl_slice_algo(mid_t mod_id); +/* Set the active DL slicing algorithm */ +int flexran_set_dl_slice_algo(mid_t mod_id, Protocol__FlexSliceAlgorithm algo); + +/* Get the currently active UL slicing algorithm */ +Protocol__FlexSliceAlgorithm flexran_get_ul_slice_algo(mid_t mod_id); +/* Set the active UL slicing algorithm */ +int flexran_set_ul_slice_algo(mid_t mod_id, Protocol__FlexSliceAlgorithm algo); /* Get the DL slice ID for a UE */ int flexran_get_ue_dl_slice_id(mid_t mod_id, mid_t ue_id); -/* Set the DL slice index(!) for a UE */ -//void flexran_set_ue_dl_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx); +/* Set the DL slice for a UE */ +void flexran_set_ue_dl_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id); /* Get the UL slice ID for a UE */ int flexran_get_ue_ul_slice_id(mid_t mod_id, mid_t ue_id); -/* Set the UL slice index(!) for a UE */ -//void flexran_set_ue_ul_slice_idx(mid_t mod_id, mid_t ue_id, int slice_idx); +/* Set the UL slice for a UE */ +void flexran_set_ue_ul_slice_id(mid_t mod_id, mid_t ue_id, slice_id_t slice_id); /* Create slice in DL, returns the new slice index */ -//int flexran_create_dl_slice(mid_t mod_id, slice_id_t slice_id); +int flexran_create_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s); /* Remove slice in DL, returns new number of slices or -1 on error */ -//int flexran_remove_dl_slice(mid_t mod_id, int slice_idx); +int flexran_remove_dl_slice(mid_t mod_id, const Protocol__FlexSlice *s); /* Finds slice in DL with given slice_id and returns slice index */ int flexran_find_dl_slice(mid_t mod_id, slice_id_t slice_id); /* Return the parameters of slice at index slice_idx */ -//void flexran_get_dl_slice(mid_t mod_id, int slice_idx, Protocol__FlexSlice *s); +void flexran_get_dl_slice(mid_t mod_id, + int slice_idx, + Protocol__FlexSlice *slice, + Protocol__FlexSliceAlgorithm algo); /* Get the number of slices in DL */ int flexran_get_num_dl_slices(mid_t mod_id); /* Create slice in UL, returns the new slice index */ -//int flexran_create_ul_slice(mid_t mod_id, slice_id_t slice_id); +int flexran_create_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s); /* Remove slice in UL */ -//int flexran_remove_ul_slice(mid_t mod_id, int slice_idx); +int flexran_remove_ul_slice(mid_t mod_id, const Protocol__FlexSlice *s); /* Finds slice in DL with given slice_id and returns slice index */ int flexran_find_ul_slice(mid_t mod_id, slice_id_t slice_id); /* Return the parameters of slice at index slice_idx */ -//void flexran_get_ul_slice(mid_t mod_id, int slice_idx, Protocol__FlexSlice *s); +void flexran_get_ul_slice(mid_t mod_id, + int slice_idx, + Protocol__FlexSlice *slice, + Protocol__FlexSliceAlgorithm algo); /* Get the number of slices in UL */ int flexran_get_num_ul_slices(mid_t mod_id); +/* Get the name of/Set the DL scheduling algorithm. If slicing is active, this + * corresponds to the default algorithm for slices, otherwise the currently + * used one. */ +char *flexran_get_dl_scheduler_name(mid_t mod_id); +int flexran_set_dl_scheduler(mid_t mod_id, char *sched); + +/* Get the name of/Set the UL scheduler algorithm. Same applies as for the DL + * case */ +char *flexran_get_ul_scheduler_name(mid_t mod_id); +int flexran_set_ul_scheduler(mid_t mod_id, char *sched); /************************** S1AP **************************/ /* Get the number of MMEs to be connected */ diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index 24038e60d5..af6d1a7ac3 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -100,6 +100,7 @@ void mac_top_init_eNB(void) mac[i]->if_inst = IF_Module_init(i); + mac[i]->pre_processor_dl.algorithm = 0; mac[i]->pre_processor_dl.dl = dlsch_scheduler_pre_processor; char *s = "round_robin_dl"; void *d = dlsym(NULL, s); @@ -107,6 +108,7 @@ void mac_top_init_eNB(void) mac[i]->pre_processor_dl.dl_algo = *(default_sched_dl_algo_t *) d; mac[i]->pre_processor_dl.dl_algo.data = mac[i]->pre_processor_dl.dl_algo.setup(); + mac[i]->pre_processor_ul.algorithm = 0; mac[i]->pre_processor_ul.ul = ulsch_scheduler_pre_processor; s = "round_robin_ul"; d = dlsym(NULL, s); diff --git a/openair2/LAYER2/MAC/slicing/slicing.c b/openair2/LAYER2/MAC/slicing/slicing.c index a1de326df0..9c88f6cffb 100644 --- a/openair2/LAYER2/MAC/slicing/slicing.c +++ b/openair2/LAYER2/MAC/slicing/slicing.c @@ -258,13 +258,26 @@ int addmod_static_slice_ul(slice_info_t *si, return si->num - 1; } -int remove_static_slice(slice_info_t *si, uint8_t slice_idx) { +int remove_static_slice_dl(slice_info_t *si, uint8_t slice_idx) { if (slice_idx == 0) return 0; slice_t *sr = _remove_slice(&si->num, si->s, si->UE_assoc_slice, slice_idx); if (!sr) return 0; free(sr->algo_data); + sr->dl_algo.unset(&sr->dl_algo.data); + free(sr); + return 1; +} + +int remove_static_slice_ul(slice_info_t *si, uint8_t slice_idx) { + if (slice_idx == 0) + return 0; + slice_t *sr = _remove_slice(&si->num, si->s, si->UE_assoc_slice, slice_idx); + if (!sr) + return 0; + free(sr->algo_data); + sr->ul_algo.unset(&sr->ul_algo.data); free(sr); return 1; } @@ -528,6 +541,7 @@ pp_impl_param_t static_dl_init(module_id_t mod_id, int CC_id) { dlp->posLow = 0; dlp->posHigh = to_rbg(RC.mac[mod_id]->common_channels[CC_id].mib->message.dl_Bandwidth) - 1; default_sched_dl_algo_t *algo = &RC.mac[mod_id]->pre_processor_dl.dl_algo; + algo->data = NULL; DevAssert(0 == addmod_static_slice_dl(si, 0, strdup("default"), algo, dlp)); const UE_list_t *UE_list = &RC.mac[mod_id]->UE_info.list; for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) @@ -539,7 +553,7 @@ pp_impl_param_t static_dl_init(module_id_t mod_id, int CC_id) { sttc.remove_UE = slicing_remove_UE; sttc.move_UE = slicing_move_UE; sttc.addmod_slice = addmod_static_slice_dl; - sttc.remove_slice = remove_static_slice; + sttc.remove_slice = remove_static_slice_dl; sttc.dl = static_dl; // current DL algo becomes default scheduler sttc.dl_algo = *algo; @@ -564,6 +578,7 @@ pp_impl_param_t static_ul_init(module_id_t mod_id, int CC_id) { ulp->posLow = 0; ulp->posHigh = to_prb(RC.mac[mod_id]->common_channels[CC_id].ul_Bandwidth) - 1; default_sched_ul_algo_t *algo = &RC.mac[mod_id]->pre_processor_ul.ul_algo; + algo->data = NULL; DevAssert(0 == addmod_static_slice_ul(si, 0, strdup("default"), algo, ulp)); const UE_list_t *UE_list = &RC.mac[mod_id]->UE_info.list; for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) @@ -575,7 +590,7 @@ pp_impl_param_t static_ul_init(module_id_t mod_id, int CC_id) { sttc.remove_UE = slicing_remove_UE; sttc.move_UE = slicing_move_UE; sttc.addmod_slice = addmod_static_slice_ul; - sttc.remove_slice = remove_static_slice; + sttc.remove_slice = remove_static_slice_ul; sttc.ul = static_ul; // current DL algo becomes default scheduler sttc.ul_algo = *algo; From 07313fd96d2b598ca5deb7574b2b7124fe9a0019 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 23 Jun 2020 13:25:28 +0200 Subject: [PATCH 59/66] FlexRAN Bugfix: Free Ringbuffer on exit --- openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c index e5d1c94c95..4c5f3e5609 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c @@ -1619,6 +1619,11 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id) LOG_E(FLEXRAN_AGENT, "MAC agent CM for eNB %d is not registered\n", mod_id); return -1; } + + lfds700_ringbuffer_cleanup(&ringbuffer_state[mod_id], NULL ); + free(dl_mac_config_array[mod_id]); + lfds700_misc_library_cleanup(); + AGENT_MAC_xface *xface = agent_mac_xface[mod_id]; xface->flexran_agent_send_sr_info = NULL; xface->flexran_agent_send_sf_trigger = NULL; From 33b860f1b4a5eab264548281596cae53d03da414 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 23 Jun 2020 13:50:59 +0200 Subject: [PATCH 60/66] FlexRAN: use lock-free ringbuffers for slice conf Use LFDS 7.0.0 Ringbuffer implementation to handle * Slice Configuration * UE slice association which is then uploaded through MAC scheduling thread --- .../CONTROL_MODULES/MAC/flexran_agent_mac.c | 100 ++++++++++++++++-- 1 file changed, 92 insertions(+), 8 deletions(-) diff --git a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c index 4c5f3e5609..f1daacbb65 100644 --- a/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c +++ b/openair2/ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.c @@ -49,6 +49,14 @@ struct lfds700_misc_prng_state ps[NUM_MAX_ENB]; struct lfds700_ringbuffer_element *dl_mac_config_array[NUM_MAX_ENB]; struct lfds700_ringbuffer_state ringbuffer_state[NUM_MAX_ENB]; +/* Ringbuffer-related to slice configuration */ +struct lfds700_ringbuffer_element *slice_config_array[NUM_MAX_ENB]; +struct lfds700_ringbuffer_state slice_config_ringbuffer_state[NUM_MAX_ENB]; + +/* Ringbuffer-related to slice configuration */ +struct lfds700_ringbuffer_element *ue_assoc_array[NUM_MAX_ENB]; +struct lfds700_ringbuffer_state ue_assoc_ringbuffer_state[NUM_MAX_ENB]; + int flexran_agent_mac_stats_reply_ue(mid_t mod_id, Protocol__FlexUeStatsReport **ue_report, int n_ue, @@ -1341,6 +1349,33 @@ void flexran_agent_init_mac_agent(mid_t mod_id) { AssertFatal(i == 0, "posix_memalign(): could not allocate aligned memory for lfds library\n"); lfds700_ringbuffer_init_valid_on_current_logical_core(&ringbuffer_state[mod_id], dl_mac_config_array[mod_id], num_elements, &ps[mod_id], NULL); + + struct lfds700_misc_prng_state scrng; + i = posix_memalign((void **) &slice_config_array[mod_id], + LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES, + sizeof(struct lfds700_ringbuffer_element) * num_elements); + AssertFatal(i == 0, + "posix_memalign(): could not allocate aligned memory\n"); + lfds700_ringbuffer_init_valid_on_current_logical_core( + &slice_config_ringbuffer_state[mod_id], + slice_config_array[mod_id], + num_elements, + &scrng, + NULL); + + struct lfds700_misc_prng_state uarng; + i = posix_memalign((void **) &ue_assoc_array[mod_id], + LFDS700_PAL_ATOMIC_ISOLATION_IN_BYTES, + sizeof(struct lfds700_ringbuffer_element) * num_elements); + AssertFatal(i == 0, + "posix_memalign(): could not allocate aligned memory\n"); + lfds700_ringbuffer_init_valid_on_current_logical_core( + &ue_assoc_ringbuffer_state[mod_id], + ue_assoc_array[mod_id], + num_elements, + &uarng, + NULL); + for (i = 0; i < MAX_MOBILES_PER_ENB; i++) { for (j = 0; j < 8; j++) { if (RC.mac && RC.mac[mod_id]) @@ -1622,6 +1657,10 @@ int flexran_agent_unregister_mac_xface(mid_t mod_id) lfds700_ringbuffer_cleanup(&ringbuffer_state[mod_id], NULL ); free(dl_mac_config_array[mod_id]); + lfds700_ringbuffer_cleanup(&slice_config_ringbuffer_state[mod_id], NULL ); + free(slice_config_array[mod_id]); + lfds700_ringbuffer_cleanup(&ue_assoc_ringbuffer_state[mod_id], NULL ); + free(ue_assoc_array[mod_id]); lfds700_misc_library_cleanup(); AGENT_MAC_xface *xface = agent_mac_xface[mod_id]; @@ -1661,23 +1700,68 @@ void helper_destroy_mac_slice_config(Protocol__FlexSliceConfig *slice_config) { void prepare_update_slice_config(mid_t mod_id, Protocol__FlexSliceConfig **slice_config) { if (!*slice_config) return; + /* just use the memory and set to NULL in original */ Protocol__FlexSliceConfig *sc = *slice_config; *slice_config = NULL; - /* TODO handle using lock-free queue */ - apply_update_dl_slice_config(mod_id, sc->dl); - apply_update_ul_slice_config(mod_id, sc->ul); + struct lfds700_misc_prng_state ls; + LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE; + lfds700_misc_prng_init(&ls); + enum lfds700_misc_flag overwrite_occurred_flag; - helper_destroy_mac_slice_config(*slice_config); + Protocol__FlexSliceConfig *overwritten_sc; + lfds700_ringbuffer_write(&slice_config_ringbuffer_state[mod_id], + NULL, + (void *)sc, + &overwrite_occurred_flag, + NULL, + (void **)&overwritten_sc, + &ls); + + if (overwrite_occurred_flag == LFDS700_MISC_FLAG_RAISED) { + helper_destroy_mac_slice_config(overwritten_sc); + LOG_E(FLEXRAN_AGENT, "lost slice config: too many reconfigurations at once\n"); + } } void prepare_ue_slice_assoc_update(mid_t mod_id, Protocol__FlexUeConfig **ue_config) { - /* TODO handle using lock-free queue */ - apply_ue_slice_assoc_update(mod_id, *ue_config); + struct lfds700_misc_prng_state ls; + LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE; + lfds700_misc_prng_init(&ls); + enum lfds700_misc_flag overwrite_occurred_flag; - free(*ue_config); - *ue_config = NULL; + Protocol__FlexUeConfig *overwritten_ue_config; + lfds700_ringbuffer_write(&ue_assoc_ringbuffer_state[mod_id], + NULL, + (void *) *ue_config, + &overwrite_occurred_flag, + NULL, + (void **)&overwritten_ue_config, + &ls); + + if (overwrite_occurred_flag == LFDS700_MISC_FLAG_RAISED) { + free(overwritten_ue_config); + LOG_E(FLEXRAN_AGENT, "lost UE-slice association: too many UE-slice associations at once\n"); + } } void flexran_agent_slice_update(mid_t mod_id) { + struct lfds700_misc_prng_state ls; + LFDS700_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE; + lfds700_misc_prng_init(&ls); + + Protocol__FlexSliceConfig *sc = NULL; + struct lfds700_ringbuffer_state *state = &slice_config_ringbuffer_state[mod_id]; + if (lfds700_ringbuffer_read(state, NULL, (void **) &sc, &ls) != 0) { + apply_update_dl_slice_config(mod_id, sc->dl); + apply_update_ul_slice_config(mod_id, sc->ul); + helper_destroy_mac_slice_config(sc); + } + + Protocol__FlexUeConfig *ue_config = NULL; + state = &ue_assoc_ringbuffer_state[mod_id]; + if (lfds700_ringbuffer_read(state, NULL, (void **) &ue_config, &ls) != 0) { + apply_ue_slice_assoc_update(mod_id, ue_config); + free(ue_config); + } } From 6eb00a0895e2c6a9e9da94161c46cf8a060041ed Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 20 Jul 2020 09:33:35 +0200 Subject: [PATCH 61/66] Enable multi-module support in pdcp_fifo_flush_sdus() --- openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c index 6c23332687..6c6bd30070 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c @@ -114,7 +114,9 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t *const ctxt_pP) { int ret=0; while ((sdu_p = pollNotifiedFIFO(&pdcp_sdu_list)) != NULL ) { pdcp_data_ind_header_t * pdcpHead=(pdcp_data_ind_header_t *)NotifiedFifoData(sdu_p); - AssertFatal(pdcpHead->inst==ctxt_pP->module_id, "To implement correctly multi module id\n"); + + /* Note: we ignore the instance ID in the context and use the one in the + * PDCP packet to pick the right socket below */ int rb_id = pdcpHead->rb_id; int sizeToWrite= sizeof (pdcp_data_ind_header_t) + @@ -130,19 +132,19 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t *const ctxt_pP) { sizeof(sidelink_pc5s_element), 0, (struct sockaddr *)&prose_pdcp_addr,sizeof(prose_pdcp_addr) ); } else if (UE_NAS_USE_TUN) { - //ret = write(nas_sock_fd[ctxt_pP->module_id], &(sdu_p->data[sizeof(pdcp_data_ind_header_t)]),sizeToWrite ); + //ret = write(nas_sock_fd[pdcpHead->inst], &(sdu_p->data[sizeof(pdcp_data_ind_header_t)]),sizeToWrite ); if(rb_id == mbms_rab_id){ ret = write(nas_sock_mbms_fd, pdcpData,sizeToWrite ); LOG_I(PDCP,"[PDCP_FIFOS] ret %d TRIED TO PUSH MBMS DATA TO rb_id %d handle %d sizeToWrite %d\n", - ret,rb_id,nas_sock_fd[ctxt_pP->module_id],sizeToWrite); + ret,rb_id,nas_sock_fd[pdcpHead->inst],sizeToWrite); } else { if( LOG_DEBUGFLAG(DEBUG_PDCP) ) log_dump(PDCP, pdcpData, sizeToWrite, LOG_DUMP_CHAR,"PDCP output to be sent to TUN interface: \n"); - ret = write(nas_sock_fd[ctxt_pP->module_id], pdcpData,sizeToWrite ); + ret = write(nas_sock_fd[pdcpHead->inst], pdcpData,sizeToWrite ); LOG_T(PDCP,"[UE PDCP_FIFOS] ret %d TRIED TO PUSH DATA TO rb_id %d handle %d sizeToWrite %d\n", - ret,rb_id,nas_sock_fd[ctxt_pP->module_id],sizeToWrite); + ret,rb_id,nas_sock_fd[pdcpHead->inst],sizeToWrite); } } else if (ENB_NAS_USE_TUN) { if( LOG_DEBUGFLAG(DEBUG_PDCP) ) From 0f0ede038d0148bd7f1aa35d6b49834feb21f965 Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Mon, 20 Jul 2020 16:25:04 +0200 Subject: [PATCH 62/66] removing a printf in pusch scheduling --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 11a2f8d2a5..3a003ab1c6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -918,8 +918,8 @@ void nr_schedule_uss_ulsch_phytest(int Mod_idP, pusch_pdu->pusch_identity = *scc->physCellId; } pusch_dmrs_AdditionalPosition_t additional_pos; - if (NR_DMRS_UplinkConfig->dmrs_AdditionalPosition == NULL){printf("%d\n",2); - additional_pos = 2;} + if (NR_DMRS_UplinkConfig->dmrs_AdditionalPosition == NULL) + additional_pos = 2; else { if (*NR_DMRS_UplinkConfig->dmrs_AdditionalPosition == NR_DMRS_UplinkConfig__dmrs_AdditionalPosition_pos3) additional_pos = 3; From 5331189c8b78568a035f91f3000ab37cad5d4c57 Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Wed, 22 Jul 2020 15:07:04 +0200 Subject: [PATCH 63/66] bugfixes --- openair1/SCHED_NR/fapi_nr_l1.c | 1 + openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c index ddebcc3e06..2870f1d42e 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ b/openair1/SCHED_NR/fapi_nr_l1.c @@ -160,6 +160,7 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){ gNB->dlsch[i][0]->harq_mask=0; } gNB->pdcch_pdu = NULL; + gNB->ul_dci_pdu = NULL; gNB->pbch_configured=0; for (int i=0;irv = pusch_pdu->pusch_data.rv_index; dci_pdu_rel15->harq_pid = pusch_pdu->pusch_data.harq_process_id; dci_pdu_rel15->frequency_hopping_flag.val = pusch_pdu->frequency_hopping; - //dci_pdu_rel15->dai[0].val = ???; //TODO + dci_pdu_rel15->dai[0].val = 0; //TODO // bwp indicator if (n_ubwp < 4) dci_pdu_rel15->bwp_indicator.val = bwp_id; From 39b22f17b330332621a0572c7e2717c94cd821ab Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Wed, 22 Jul 2020 15:11:17 +0200 Subject: [PATCH 64/66] calloc for dci_pdu --- openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c | 1 - openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 7 ++++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c index 10d4e9ab3c..f40d822b6b 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -2010,7 +2010,6 @@ uint16_t nr_dci_size(NR_ServingCellConfigCommon_t *scc, } // Precoding info and number of layers long transformPrecoder; - dci_pdu->precoding_information.nbits = 0; if (pusch_Config->transformPrecoder == NULL){ // if transform precoder is null, apply the values from msg3 if(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index c1565bd408..89de2da0e5 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -1052,9 +1052,10 @@ void nr_schedule_uss_ulsch_phytest(int Mod_idP, return; } else { - dci_pdu_rel15_t dci_pdu_rel15[MAX_DCI_CORESET]; - config_uldci(ubwp,pusch_pdu,pdcch_pdu_rel15,&dci_pdu_rel15[0],dci_formats,rnti_types,n_ubwp,bwp_id); - fill_dci_pdu_rel15(scc,secondaryCellGroup,pdcch_pdu_rel15,dci_pdu_rel15,dci_formats,rnti_types,pusch_pdu->bwp_size,bwp_id); + dci_pdu_rel15_t *dci_pdu_rel15 = calloc(MAX_DCI_CORESET,sizeof(dci_pdu_rel15_t)); + config_uldci(ubwp,pusch_pdu,pdcch_pdu_rel15,&dci_pdu_rel15[0],dci_formats,rnti_types,time_domain_assignment,n_ubwp,bwp_id); + fill_dci_pdu_rel15(scc,secondaryCellGroup,pdcch_pdu_rel15,dci_pdu_rel15,dci_formats,rnti_types,pusch_pdu->bwp_size,bwp_id); + free(dci_pdu_rel15); } } From 390c648a81ee2b209b73dbdb5b5dce7a7d51a4e4 Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Wed, 22 Jul 2020 09:13:04 +0200 Subject: [PATCH 65/66] bugfix in time domain assigment --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 5 +++-- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 89de2da0e5..8841083796 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -474,6 +474,7 @@ void config_uldci(NR_BWP_Uplink_t *ubwp, nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, dci_pdu_rel15_t *dci_pdu_rel15, int *dci_formats, int *rnti_types, + int time_domain_assignment, int n_ubwp, int bwp_id) { switch(dci_formats[(pdcch_pdu_rel15->numDlDci)-1]) { @@ -482,7 +483,7 @@ void config_uldci(NR_BWP_Uplink_t *ubwp, pusch_pdu->rb_start, NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275)); - dci_pdu_rel15->time_domain_assignment.val = 2; // row index used here instead of SLIV; + dci_pdu_rel15->time_domain_assignment.val = time_domain_assignment; dci_pdu_rel15->frequency_hopping_flag.val = pusch_pdu->frequency_hopping; dci_pdu_rel15->mcs = 9; @@ -511,7 +512,7 @@ void config_uldci(NR_BWP_Uplink_t *ubwp, else AssertFatal(1==0,"Only frequency resource allocation type 1 is currently supported\n"); // time domain assignment - dci_pdu_rel15->time_domain_assignment.val = 2; + dci_pdu_rel15->time_domain_assignment.val = time_domain_assignment; // mcs dci_pdu_rel15->mcs = pusch_pdu->mcs_index; // tpc command for pusch diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 8b38c357c6..74c6841a3a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -137,6 +137,7 @@ void config_uldci(NR_BWP_Uplink_t *ubwp, nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15, dci_pdu_rel15_t *dci_pdu_rel15, int *dci_formats, int *rnti_types, + int time_domain_assignment, int n_ubwp, int bwp_id); void configure_fapi_dl_Tx(module_id_t Mod_idP, From 1f74524d0dc72e357872c25a4431d46f926a17dc Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Thu, 23 Jul 2020 10:10:19 +0200 Subject: [PATCH 66/66] fix for prepare dci 0_1 --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index a22d4988df..876f1b5396 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -820,7 +820,7 @@ void fill_dci_pdu_rel15(NR_ServingCellConfigCommon_t *scc, pdcch_pdu_rel15->dci_pdu.PayloadSizeBits[d] = dci_size; AssertFatal(pdcch_pdu_rel15->dci_pdu.PayloadSizeBits[d]<=64, "DCI sizes above 64 bits not yet supported"); - if(dci_formats[d]==NR_DL_DCI_FORMAT_1_1) + if(dci_formats[d]==NR_DL_DCI_FORMAT_1_1 || dci_formats[d]==NR_UL_DCI_FORMAT_0_1) prepare_dci(secondaryCellGroup,&dci_pdu_rel15[d],dci_formats[d],bwp_id); /// Payload generation