diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container index 118eb844d49855cbbee175e7c29b6deb93fba8ed..ebb2fbd5e0aebd2a9a45206e3954912db62b19dd 100644 --- a/ci-scripts/Jenkinsfile-GitLab-Container +++ b/ci-scripts/Jenkinsfile-GitLab-Container @@ -425,28 +425,26 @@ pipeline { } } } - - //avra is offline, re-enable once it is available - //stage ("T1-Offload-Test") { - // when { expression {do5Gtest} } - // steps { - // script { - // triggerSlaveJob ('RAN-T1-Offload-Test', 'T1-Offload-Test') - // } - // } - // post { - // always { - // script { - // finalizeSlaveJob('RAN-T1-Offload-Test') - // } - // } - // failure { - // script { - // currentBuild.result = 'FAILURE' - // } - // } - // } - //} + stage ("Interop-F1") { + when { expression {do5Gtest} } + steps { + script { + triggerSlaveJob ('RAN-Interop-F1', 'Interop-F1') + } + } + post { + always { + script { + finalizeSlaveJob('RAN-Interop-F1') + } + } + failure { + script { + currentBuild.result = 'FAILURE' + } + } + } + } } } stage ("DockerHub-Push") { diff --git a/ci-scripts/xml_files/container_5g_rfsim_f1_accelleran.xml b/ci-scripts/xml_files/container_5g_rfsim_f1_accelleran.xml new file mode 100644 index 0000000000000000000000000000000000000000..d727fdfd1e1f342a5dfbea13a4d8e5fc12cadd05 --- /dev/null +++ b/ci-scripts/xml_files/container_5g_rfsim_f1_accelleran.xml @@ -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 + +--> +<testCaseList> + <htmlTabRef>rfsim-5gnr-f1-accelleran</htmlTabRef> + <htmlTabName>F1 DU Interop Accelleran CU</htmlTabName> + <htmlTabIcon>wrench</htmlTabIcon> + <TestCaseRequestedList> + 111111 + 000020 + 000021 + 020021 + 100021 + 100022 + </TestCaseRequestedList> + <TestCaseExclusionList></TestCaseExclusionList> + + <testCase id="111111"> + <class>Pull_Local_Registry</class> + <desc>Pull Images from Local Registry</desc> + <test_svr_id>0</test_svr_id> + <images_to_pull>oai-gnb oai-nr-ue</images_to_pull> + </testCase> + + <testCase id="000020"> + <class>DeployGenObject</class> + <desc>Deploy OAI-DU</desc> + <yaml_path>yaml_files/5g_rfsimulator_accelleran</yaml_path> + <services>oai-du</services> + <nb_healthy>1</nb_healthy> + </testCase> + + <testCase id="000021"> + <class>DeployGenObject</class> + <desc>Deploy nrUE</desc> + <yaml_path>yaml_files/5g_rfsimulator_accelleran</yaml_path> + <services>oai-nr-ue</services> + <nb_healthy>2</nb_healthy> + </testCase> + + <testCase id="020021"> + <class>PingFromContainer</class> + <desc>Test Connectivity (ping)</desc> + <container_name>rfsim5g-oai-nr-ue</container_name> + <options>-I oaitun_ue1 -c 20 12.1.1.1</options> + <loss_threshold>0</loss_threshold> + </testCase> + + <testCase id="100022"> + <class>UndeployGenObject</class> + <desc>Undeploy all OAI 5G stack</desc> + <yaml_path>yaml_files/5g_rfsimulator_accelleran</yaml_path> + </testCase> + +</testCaseList> diff --git a/ci-scripts/xml_files/container_5g_rfsim_f1_accelleran_down.xml b/ci-scripts/xml_files/container_5g_rfsim_f1_accelleran_down.xml new file mode 100644 index 0000000000000000000000000000000000000000..0a4f9fcbfaa87cc8859b49603d47abec1df9c079 --- /dev/null +++ b/ci-scripts/xml_files/container_5g_rfsim_f1_accelleran_down.xml @@ -0,0 +1,45 @@ +<!-- + + 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 + +--> +<testCaseList> + <htmlTabRef>rfsim-5gnr-down-f1-accelleran</htmlTabRef> + <htmlTabName>CleanUp</htmlTabName> + <htmlTabIcon>trash</htmlTabIcon> + <TestCaseRequestedList> + 100022 + 222222 + </TestCaseRequestedList> + <TestCaseExclusionList></TestCaseExclusionList> + + <testCase id="100022"> + <class>UndeployGenObject</class> + <desc>Undeploy all OAI 5G stack</desc> + <yaml_path>yaml_files/5g_rfsimulator_accelleran</yaml_path> + </testCase> + + <testCase id="222222"> + <class>Clean_Test_Server_Images</class> + <desc>Clean Test Images on Test Server</desc> + <test_svr_id>0</test_svr_id> + </testCase> + +</testCaseList> diff --git a/ci-scripts/yaml_files/5g_rfsimulator_accelleran/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_accelleran/docker-compose.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3551cc27c62b90fb42fbc5a48106c0e4beb9ad06 --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator_accelleran/docker-compose.yaml @@ -0,0 +1,38 @@ +version: '3.8' +services: + oai-du: + image: oaisoftwarealliance/oai-gnb:develop + privileged: true + container_name: rfsim5g-oai-du + network_mode: "host" + environment: + RFSIMULATOR: server + USE_VOLUMED_CONF: 'yes' + USE_ADDITIONAL_OPTIONS: --sa --rfsim --MACRLCs.[0].local_n_address 172.21.16.109 --MACRLCs.[0].remote_n_address 172.21.6.22 --log_config.global_log_options level,nocolor,time + volumes: + - ../../conf_files/gnb-du.band78.106prb.rfsim.conf:/opt/oai-gnb/etc/mounted.conf + healthcheck: + test: /bin/bash -c "pgrep nr-softmodem" + interval: 10s + timeout: 5s + retries: 5 + oai-nr-ue: + image: oaisoftwarealliance/oai-nr-ue:develop + privileged: true + container_name: rfsim5g-oai-nr-ue + network_mode: "host" + environment: + RFSIMULATOR: 127.0.0.1 + FULL_IMSI: '208990100001140' + FULL_KEY: 'fec86ba6eb707ed08905757b1bb44b8f' + OPC: 'C42449363BBAD02B66D16BC975D77CC1' + DNN: oai + NSSAI_SST: 1 + USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 106 --numerology 1 -C 3619200000 --log_config.global_log_options level,nocolor,time + depends_on: + - oai-du + healthcheck: + test: /bin/bash -c "pgrep nr-uesoftmodem" + interval: 10s + timeout: 5s + retries: 5 diff --git a/doc/F1-design.md b/doc/F1-design.md index 80417b1ae3e73c20d52f590ecde03fd505fb2284..7e491f53461d37b2827243a3206bd72a004abba0 100644 --- a/doc/F1-design.md +++ b/doc/F1-design.md @@ -11,6 +11,7 @@ </td> </tr> </table> + # 1. Introduction We use OpenAirInterface source code, and it's regular deployment scheme. @@ -208,3 +209,46 @@ DU rlc north output goes to du_pdcp_data_ind() that push a outgoing packet reque CU pdcp south output calls cu_rlc_data_ind() that do the same symetric processing. +# High-level F1-C code structure + +The F1 interface is used internally between CU (mostly RRC) and DU (mostly MAC) +to exchange information. In DL, the CU sends messages as defined by the +callbacks in `mac_rrc_dl.h`, whose implementation is defined in files +`mac_rrc_dl_direct.c` (monolithic) and `mac_rrc_dl_f1ap.c` (for F1AP). In the +monolithic case, the RRC calls directly into the message handler on the DU side +(`mac_rrc_dl_handler.c`). In the F1 case, an ITTI message is sent to the CU +task, sending an ASN.1-encoded F1AP message. The DU side's DU task decodes the +message, and then calls the corresponding handler in `mac_rrc_dl_handler.c`. +Thus, the message flow is the same in both F1 and monolithic cases, with the +difference that F1AP encodes the messages using ASN.1 and sends over a socket. + +In UL, the callbacks defined in `mac_rrc_ul.h` are implemented by +`mac_rrc_ul_direct.c` (monolithic) and `mac_rrc_ul_f1ap.c` (F1). In the direct +case, an ITTI message is directly sent to the RRC task (hence, there is no +dedicated handler). In F1, the DU task receives the ITTI message, encodes using +ASN.1, and sends it over a network socket. The CU task decodes, and sends the +same ITTI message to the RRC task as done directly in the monolithic case. + +``` + +-------------+ + | | + | CU/RRC | + | | + +-------------+ + | ^ + Callback def: mac_rrc_dl.h | | No handler needed: + F1 impl: mac_rrc_dl_f1ap.c | | RRC has ITTI +Monolithic: mac_rrc_dl_direct.c | | + | | + DL | | UL + | | + | | Callback def: mac_rrc_ul.h + Message handler: | | F1 impl: mac_rrc_ul_f1ap.c + mac_rrc_dl_handler.c | | Monolithic: mac_rrc_ul_direct.c + v | + +-------------+ + | | + | DU/MAC | + | | + +-------------+ +``` diff --git a/doc/TESTBenches.md b/doc/TESTBenches.md index aef3a7f63e7e63934cc279645e21d56da866d6de..3f50abaa115ff5c89bb469326f5c2dc4d47bacfe 100644 --- a/doc/TESTBenches.md +++ b/doc/TESTBenches.md @@ -82,6 +82,9 @@ Webhook - [RAN-gNB-N300-Timing-Phytest-LDPC](https://jenkins-oai.eurecom.fr/view/RAN/job/RAN-gNB-N300-Timing-Phytest-LDPC/) - caracal + N310 - pure performance test through phy-test scheduler, see command line for more details +- [RAN-Interop-F1](https://jenkins-oai.eurecom.fr/job/RAN-Interop-F1/) + - ofqot (DU, 1x UE) + - F1 interoperability testing: sets up connection to Accelleran CU, UE connection and connectivity test - [RAN-L2-Sim-Test-5G](https://jenkins-oai.eurecom.fr/job/RAN-L2-Sim-Test-4G/) - obelix (eNB, 1x UE, OAI EPC) - L2simulator: skips physical layer and uses proxy between eNB and UE diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index a7465ad99b7cbff6a9678dc29cfb73ef3536c1cf..0007a3b4d109dd6b3e8ad97863e046d67f306049 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -1010,7 +1010,10 @@ int main(int argc, char **argv) UE_info->UE_sched_ctrl.harq_processes[harq_pid].ndi = !(trial&1); UE_info->UE_sched_ctrl.harq_processes[harq_pid].round = round; + // nr_schedule_ue_spec() requires the mutex to be locked + NR_SCHED_LOCK(&gNB_mac->sched_lock); nr_schedule_ue_spec(0, frame, slot, &Sched_INFO->DL_req, &Sched_INFO->TX_req); + NR_SCHED_UNLOCK(&gNB_mac->sched_lock); Sched_INFO->module_id = 0; Sched_INFO->CC_id = 0; Sched_INFO->frame = frame; diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index fbe838871415710e1fcd8b26950111e837292d37..4c119dd8ad3787d4703df1070a5b0cb7649ac788 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -35,6 +35,7 @@ #include "f1ap_decoder.h" #include "f1ap_itti_messaging.h" #include "f1ap_du_ue_context_management.h" +#include "openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h" #include "rrc_extern.h" #include "openair2/RRC/NR/rrc_gNB_UE_context.h" @@ -65,13 +66,13 @@ bool lteDURecvCb(protocol_ctxt_t *ctxt_pP, int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, uint32_t assoc_id, uint32_t stream, - F1AP_F1AP_PDU_t *pdu) { - MessageDef *msg_p; // message to RRC + F1AP_F1AP_PDU_t *pdu) +{ F1AP_UEContextSetupRequest_t *container; int i; DevAssert(pdu); - msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_UE_CONTEXT_SETUP_REQ); - f1ap_ue_context_setup_t *f1ap_ue_context_setup_req = &F1AP_UE_CONTEXT_SETUP_REQ(msg_p); + f1ap_ue_context_setup_t ue_context_setup = {0}; + f1ap_ue_context_setup_t *f1ap_ue_context_setup_req = &ue_context_setup; container = &pdu->choice.initiatingMessage->value.choice.UEContextSetupRequest; /* GNB_CU_UE_F1AP_ID */ F1AP_UEContextSetupRequestIEs_t *ieCU; @@ -224,8 +225,7 @@ int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, LOG_W(F1AP, "can't find RRCContainer in UEContextSetupRequestIEs by id %ld \n", F1AP_ProtocolIE_ID_id_RRCContainer); } - itti_send_msg_to_task(TASK_RRC_GNB, instance, msg_p); - + ue_context_setup_request(f1ap_ue_context_setup_req); return 0; } diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 1a72fa951d39bcb809149fed01b15fdfc88cddb1..4ba189c4bdd10a532fc0631f68fa8fbfd6927423 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -99,73 +99,52 @@ static void process_rlcBearerConfig(struct NR_CellGroupConfig__rlc_BearerToAddMo static void process_drx_Config(NR_UE_sched_ctrl_t *sched_ctrl, NR_SetupRelease_DRX_Config_t *drx_Config) { - - if (!drx_Config) return; - AssertFatal(drx_Config->present != NR_SetupRelease_DRX_Config_PR_NOTHING, "Cannot have NR_SetupRelease_DRX_Config_PR_NOTHING\n"); - - if (drx_Config->present == NR_SetupRelease_DRX_Config_PR_setup) { - LOG_I(NR_MAC,"Adding DRX config\n"); - } - else { - LOG_I(NR_MAC,"Removing DRX config\n"); - } + AssertFatal(false, "%s() not implemented\n", __func__); + AssertFatal(drx_Config->present != NR_SetupRelease_DRX_Config_PR_NOTHING, "Cannot have NR_SetupRelease_DRX_Config_PR_NOTHING\n"); } static void process_schedulingRequestConfig(NR_UE_sched_ctrl_t *sched_ctrl, NR_SchedulingRequestConfig_t *schedulingRequestConfig) { - if (!schedulingRequestConfig) return; - - LOG_I(NR_MAC,"Adding SchedulingRequestconfig\n"); + AssertFatal(false, "%s() not implemented\n", __func__); } static void process_bsrConfig(NR_UE_sched_ctrl_t *sched_ctrl, NR_BSR_Config_t *bsr_Config) { - if (!bsr_Config) return; - LOG_I(NR_MAC,"Adding BSR config\n"); + AssertFatal(false, "%s() not implemented\n", __func__); } static void process_tag_Config(NR_UE_sched_ctrl_t *sched_ctrl, NR_TAG_Config_t *tag_Config) { - if (!tag_Config) return; - LOG_I(NR_MAC,"Adding TAG config\n"); + AssertFatal(false, "%s() not implemented\n", __func__); } static void process_phr_Config(NR_UE_sched_ctrl_t *sched_ctrl, NR_SetupRelease_PHR_Config_t *phr_Config) { - if (!phr_Config) return; - AssertFatal(phr_Config->present != NR_SetupRelease_PHR_Config_PR_NOTHING, "Cannot have NR_SetupRelease_PHR_Config_PR_NOTHING\n"); - - if (phr_Config->present == NR_SetupRelease_PHR_Config_PR_setup) { - LOG_I(NR_MAC,"Adding PHR config\n"); - } - else { - LOG_I(NR_MAC,"Removing PHR config\n"); - } + AssertFatal(false, "%s() not implemented\n", __func__); } void process_CellGroup(NR_CellGroupConfig_t *CellGroup, NR_UE_sched_ctrl_t *sched_ctrl) { + /* we assume that this function is mutex-protected from outside */ + NR_SCHED_ENSURE_LOCKED(&RC.nrmac[0]->sched_lock); + AssertFatal(CellGroup, "CellGroup is null\n"); NR_MAC_CellGroupConfig_t *mac_CellGroupConfig = CellGroup->mac_CellGroupConfig; if (mac_CellGroupConfig) { - process_drx_Config(sched_ctrl,mac_CellGroupConfig->drx_Config); - process_schedulingRequestConfig(sched_ctrl,mac_CellGroupConfig->schedulingRequestConfig); - process_bsrConfig(sched_ctrl,mac_CellGroupConfig->bsr_Config); - process_tag_Config(sched_ctrl,mac_CellGroupConfig->tag_Config); - process_phr_Config(sched_ctrl,mac_CellGroupConfig->phr_Config); - } - else { - // apply defaults - + //process_drx_Config(sched_ctrl,mac_CellGroupConfig->drx_Config); + //process_schedulingRequestConfig(sched_ctrl,mac_CellGroupConfig->schedulingRequestConfig); + //process_bsrConfig(sched_ctrl,mac_CellGroupConfig->bsr_Config); + //process_tag_Config(sched_ctrl,mac_CellGroupConfig->tag_Config); + //process_phr_Config(sched_ctrl,mac_CellGroupConfig->phr_Config); } process_rlcBearerConfig(CellGroup->rlc_BearerToAddModList,CellGroup->rlc_BearerToReleaseList,sched_ctrl); } -void config_common(gNB_MAC_INST *nrmac, int pdsch_AntennaPorts, int pusch_AntennaPorts, NR_ServingCellConfigCommon_t *scc) { - +static void config_common(gNB_MAC_INST *nrmac, int pdsch_AntennaPorts, int pusch_AntennaPorts, NR_ServingCellConfigCommon_t *scc) +{ nfapi_nr_config_request_scf_t *cfg = &nrmac->config[0]; nrmac->common_channels[0].ServingCellConfigCommon = scc; @@ -460,19 +439,23 @@ void config_common(gNB_MAC_INST *nrmac, int pdsch_AntennaPorts, int pusch_Antenn } } -int nr_mac_enable_ue_rrc_processing_timer(module_id_t Mod_idP, rnti_t rnti, NR_SubcarrierSpacing_t subcarrierSpacing, uint32_t rrc_reconfiguration_delay) { - +int nr_mac_enable_ue_rrc_processing_timer(module_id_t Mod_idP, rnti_t rnti, NR_SubcarrierSpacing_t subcarrierSpacing, uint32_t rrc_reconfiguration_delay) +{ if (rrc_reconfiguration_delay == 0) { return -1; } - NR_UE_info_t *UE_info = find_nr_UE(&RC.nrmac[Mod_idP]->UE_info,rnti); + gNB_MAC_INST *nrmac = RC.nrmac[Mod_idP]; + NR_SCHED_LOCK(&nrmac->sched_lock); + + NR_UE_info_t *UE_info = find_nr_UE(&nrmac->UE_info,rnti); if (!UE_info) { LOG_W(NR_MAC, "Could not find UE for RNTI 0x%04x\n", rnti); + NR_SCHED_UNLOCK(&nrmac->sched_lock); return -1; } NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl; - const uint16_t sl_ahead = RC.nrmac[Mod_idP]->if_inst->sl_ahead; + const uint16_t sl_ahead = nrmac->if_inst->sl_ahead; sched_ctrl->rrc_processing_timer = (rrc_reconfiguration_delay<<subcarrierSpacing) + sl_ahead; LOG_I(NR_MAC, "Activating RRC processing timer for UE %04x with %d ms\n", UE_info->rnti, rrc_reconfiguration_delay); @@ -480,8 +463,9 @@ int nr_mac_enable_ue_rrc_processing_timer(module_id_t Mod_idP, rnti_t rnti, NR_S // processing timer. To prevent this, set a variable as if we would have just // sent it. This way, another TA command will for sure be sent in some // frames, after RRC processing timer. - sched_ctrl->ta_frame = (RC.nrmac[Mod_idP]->frame - 1 + 1024) % 1024; + sched_ctrl->ta_frame = (nrmac->frame - 1 + 1024) % 1024; + NR_SCHED_UNLOCK(&nrmac->sched_lock); return 0; } @@ -494,6 +478,7 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, { DevAssert(nrmac != NULL); AssertFatal(nrmac->common_channels[0].ServingCellConfigCommon == NULL, "logic error: multiple configurations of SCC\n"); + NR_SCHED_LOCK(&nrmac->sched_lock); DevAssert(scc != NULL); AssertFatal(scc->ssb_PositionsInBurst->present > 0 && scc->ssb_PositionsInBurst->present < 4, @@ -573,26 +558,31 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, ra->preambles.preamble_list[i] = i; } } + NR_SCHED_UNLOCK(&nrmac->sched_lock); } void nr_mac_config_mib(gNB_MAC_INST *nrmac, NR_BCCH_BCH_Message_t *mib) { DevAssert(nrmac != NULL); DevAssert(mib != NULL); + NR_SCHED_LOCK(&nrmac->sched_lock); NR_COMMON_channels_t *cc = &nrmac->common_channels[0]; AssertFatal(cc->mib == NULL, "logic bug: updated MIB multiple times\n"); cc->mib = mib; + NR_SCHED_UNLOCK(&nrmac->sched_lock); } void nr_mac_config_sib1(gNB_MAC_INST *nrmac, NR_BCCH_DL_SCH_Message_t *sib1) { DevAssert(nrmac != NULL); DevAssert(sib1 != NULL); + NR_SCHED_LOCK(&nrmac->sched_lock); NR_COMMON_channels_t *cc = &nrmac->common_channels[0]; AssertFatal(cc->sib1 == NULL, "logic bug: updated SIB1 multiple times\n"); cc->sib1 = sib1; + NR_SCHED_UNLOCK(&nrmac->sched_lock); } bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup) @@ -600,16 +590,17 @@ bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t DevAssert(nrmac != NULL); DevAssert(CellGroup != NULL); DevAssert(get_softmodem_params()->phy_test); + NR_SCHED_LOCK(&nrmac->sched_lock); NR_UE_info_t* UE = add_new_nr_ue(nrmac, rnti, CellGroup); if (UE) { LOG_I(NR_MAC,"Force-added new UE %x with initial CellGroup\n", rnti); + process_CellGroup(CellGroup,&UE->UE_sched_ctrl); } else { LOG_E(NR_MAC,"Error adding UE %04x\n", rnti); - return false; } - process_CellGroup(CellGroup,&UE->UE_sched_ctrl); - return true; + NR_SCHED_UNLOCK(&nrmac->sched_lock); + return UE != NULL; } bool nr_mac_prepare_ra_nsa_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup) @@ -617,6 +608,7 @@ bool nr_mac_prepare_ra_nsa_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupCo DevAssert(nrmac != NULL); DevAssert(CellGroup != NULL); DevAssert(!get_softmodem_params()->phy_test); + NR_SCHED_LOCK(&nrmac->sched_lock); // NSA case: need to pre-configure CFRA const int CC_id = 0; @@ -628,6 +620,7 @@ bool nr_mac_prepare_ra_nsa_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupCo } if (ra_index == NR_NB_RA_PROC_MAX) { LOG_E(NR_MAC, "RA processes are not available for CFRA RNTI %04x\n", rnti); + NR_SCHED_UNLOCK(&nrmac->sched_lock); return false; } NR_RA_t *ra = &cc->ra[ra_index]; @@ -656,12 +649,16 @@ bool nr_mac_prepare_ra_nsa_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupCo } } LOG_I(NR_MAC,"Added new RA process for UE RNTI %04x with initial CellGroup\n", rnti); + NR_SCHED_UNLOCK(&nrmac->sched_lock); return true; } bool nr_mac_update_cellgroup(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup) { DevAssert(nrmac != NULL); + /* we assume that this function is mutex-protected from outside */ + NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); + DevAssert(CellGroup != NULL); NR_UE_info_t *UE = find_nr_UE(&nrmac->UE_info, rnti); @@ -677,58 +674,7 @@ bool nr_mac_update_cellgroup(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupCon exit(1); } - nr_mac_update_RA(nrmac, rnti, CellGroup); process_CellGroup(CellGroup, &UE->UE_sched_ctrl); return true; } - -bool nr_mac_update_RA(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup) -{ - // Checking for free RA process - NR_COMMON_channels_t *cc = &nrmac->common_channels[0]; - uint8_t ra_index = 0; - for (; ra_index < NR_NB_RA_PROC_MAX; ra_index++) { - if ((cc->ra[ra_index].state == RA_IDLE) && (!cc->ra[ra_index].cfra)) - break; - } - if (ra_index == NR_NB_RA_PROC_MAX) { - LOG_E(NR_MAC, "%s() %s:%d RA processes are not available for CFRA RNTI :%x\n", __FUNCTION__, __FILE__, __LINE__, rnti); - return -1; - } - - NR_RA_t *ra = &cc->ra[ra_index]; - if (CellGroup->spCellConfig && CellGroup->spCellConfig->reconfigurationWithSync - && CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated != NULL) { - if (CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra != NULL) { - ra->cfra = true; - ra->rnti = rnti; - ra->CellGroup = CellGroup; - struct NR_CFRA *cfra = CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra; - uint8_t num_preamble = cfra->resources.choice.ssb->ssb_ResourceList.list.count; - ra->preambles.num_preambles = num_preamble; - ra->preambles.preamble_list = (uint8_t *)malloc(num_preamble * sizeof(uint8_t)); - for (int i = 0; i < cc->num_active_ssb; i++) { - for (int j = 0; j < num_preamble; j++) { - if (cc->ssb_index[i] == cfra->resources.choice.ssb->ssb_ResourceList.list.array[j]->ssb) { - // One dedicated preamble for each beam - ra->preambles.preamble_list[i] = cfra->resources.choice.ssb->ssb_ResourceList.list.array[j]->ra_PreambleIndex; - break; - } - } - } - } - } else { - ra->cfra = false; - ra->rnti = 0; - if (ra->preambles.preamble_list == NULL) { - ra->preambles.num_preambles = MAX_NUM_NR_PRACH_PREAMBLES; - ra->preambles.preamble_list = (uint8_t *)malloc(MAX_NUM_NR_PRACH_PREAMBLES * sizeof(uint8_t)); - for (int i = 0; i < MAX_NUM_NR_PRACH_PREAMBLES; i++) - ra->preambles.preamble_list[i] = i; - } - } - LOG_I(NR_MAC, "Added new %s process for UE RNTI %04x with initial CellGroup\n", ra->cfra ? "CFRA" : "CBRA", rnti); - - return true; -} diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index e831f6d4a86b4e687e208a97865d65a287358914..2d4cd16eb4a9998e9513969de1049e8adf8ca09b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -63,6 +63,7 @@ void clear_nr_nfapi_information(gNB_MAC_INST *gNB, nfapi_nr_tx_data_request_t *TX_req, nfapi_nr_ul_dci_request_t *UL_dci_req) { + /* called below and in simulators, so we assume a lock but don't require it */ NR_ServingCellConfigCommon_t *scc = gNB->common_channels->ServingCellConfigCommon; const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; @@ -149,6 +150,8 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, sub_frame_ NR_COMMON_channels_t *cc = gNB->common_channels; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; + NR_SCHED_LOCK(&gNB->sched_lock); + if (slot==0 && (*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]>=257)) { //FR2 const NR_TDD_UL_DL_Pattern_t *tdd = &scc->tdd_UL_DL_ConfigurationCommon->pattern1; @@ -254,6 +257,6 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, sub_frame_ copy_ul_tti_req(&sched_info->UL_tti_req, &gNB->UL_tti_req_ahead[0][current_index]); stop_meas(&gNB->eNB_scheduler); - + NR_SCHED_UNLOCK(&gNB->sched_lock); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_OUT); } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 2461d9618d988b4d8e3a7e04c8fc0e9dfcb743be..fb78ff0d1339c2193b7cea426730af864be6dd22 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -49,17 +49,32 @@ extern RAN_CONTEXT_t RC; extern const uint8_t nr_slots_per_frame[5]; extern uint16_t sl_ahead; +// forward declaration of functions used in this file +static void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, + NR_ServingCellConfigCommon_t *scc, + int round, + int startSymbolAndLength, + rnti_t rnti, + int scs, + int bwp_size, + int bwp_start, + int mappingtype, + int fh, + int msg3_first_rb, + int msg3_nb_rb); +static void nr_fill_rar(uint8_t Mod_idP, NR_RA_t *ra, uint8_t *dlsch_buffer, nfapi_nr_pusch_pdu_t *pusch_pdu); + static const uint8_t DELTA[4] = {2, 3, 4, 6}; static const float ssb_per_rach_occasion[8] = {0.125, 0.25, 0.5, 1, 2, 4, 8}; -int16_t ssb_index_from_prach(module_id_t module_idP, - frame_t frameP, - sub_frame_t slotP, - uint16_t preamble_index, - uint8_t freq_index, - uint8_t symbol) { - +static int16_t ssb_index_from_prach(module_id_t module_idP, + frame_t frameP, + sub_frame_t slotP, + uint16_t preamble_index, + uint8_t freq_index, + uint8_t symbol) +{ gNB_MAC_INST *gNB = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &gNB->common_channels[0]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; @@ -139,10 +154,12 @@ int16_t ssb_index_from_prach(module_id_t module_idP, return index; } - //Compute Total active SSBs and RO available void find_SSB_and_RO_available(gNB_MAC_INST *nrmac) { + /* already mutex protected through nr_mac_config_scc() */ + NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); + NR_COMMON_channels_t *cc = &nrmac->common_channels[0]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; nfapi_nr_config_request_scf_t *cfg = &nrmac->config[0]; @@ -242,6 +259,9 @@ void find_SSB_and_RO_available(gNB_MAC_INST *nrmac) void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { gNB_MAC_INST *gNB = RC.nrmac[module_idP]; + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ + NR_SCHED_ENSURE_LOCKED(&gNB->sched_lock); + NR_COMMON_channels_t *cc = gNB->common_channels; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; int mu; @@ -399,15 +419,20 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP } } -void nr_schedule_msg2(uint16_t rach_frame, uint16_t rach_slot, - uint16_t *msg2_frame, uint16_t *msg2_slot, - int mu, NR_ServingCellConfigCommon_t *scc, - frame_type_t frame_type, - uint16_t monitoring_slot_period, - uint16_t monitoring_offset,uint8_t beam_index, - uint8_t num_active_ssb, - int16_t *tdd_beam_association, int sl_ahead){ - +static void nr_schedule_msg2(uint16_t rach_frame, + uint16_t rach_slot, + uint16_t *msg2_frame, + uint16_t *msg2_slot, + int mu, + NR_ServingCellConfigCommon_t *scc, + frame_type_t frame_type, + uint16_t monitoring_slot_period, + uint16_t monitoring_offset, + uint8_t beam_index, + uint8_t num_active_ssb, + int16_t *tdd_beam_association, + int sl_ahead) +{ // preferentially we schedule the msg2 in the mixed slot or in the last dl slot // if they are allowed by search space configuration uint8_t response_window = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.ra_ResponseWindow; @@ -516,12 +541,13 @@ void nr_initiate_ra_proc(module_id_t module_idP, uint16_t preamble_index, uint8_t freq_index, uint8_t symbol, - int16_t timing_offset){ + int16_t timing_offset) +{ + gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; + NR_SCHED_LOCK(&nr_mac->sched_lock); uint8_t ul_carrier_id = 0; // 0 for NUL 1 for SUL - uint16_t msg2_frame, msg2_slot,monitoring_slot_period,monitoring_offset; - gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; frame_type_t frame_type = cc->frame_type; @@ -655,57 +681,22 @@ void nr_initiate_ra_proc(module_id_t module_idP, cc->ssb_index[beam_index], i); + NR_SCHED_UNLOCK(&nr_mac->sched_lock); return; } + + NR_SCHED_UNLOCK(&nr_mac->sched_lock); LOG_E(NR_MAC, "[gNB %d][RAPROC] FAILURE: CC_id %d Frame %d initiating RA procedure for preamble index %d\n", module_idP, CC_id, frameP, preamble_index); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 0); } -void nr_schedule_RA(module_id_t module_idP, - frame_t frameP, - sub_frame_t slotP, - nfapi_nr_ul_dci_request_t *ul_dci_req, - nfapi_nr_dl_tti_request_t *DL_req, - nfapi_nr_tx_data_request_t *TX_req) -{ - gNB_MAC_INST *mac = RC.nrmac[module_idP]; - - start_meas(&mac->schedule_ra); - for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { - NR_COMMON_channels_t *cc = &mac->common_channels[CC_id]; - for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { - NR_RA_t *ra = &cc->ra[i]; - LOG_D(NR_MAC, "RA[state:%d]\n", ra->state); - switch (ra->state) { - case Msg2: - nr_generate_Msg2(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); - break; - case Msg3_retransmission: - nr_generate_Msg3_retransmission(module_idP, CC_id, frameP, slotP, ra, ul_dci_req); - break; - case Msg3_dcch_dtch: - nr_generate_Msg3_dcch_dtch_response(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); - case Msg4: - nr_generate_Msg4(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); - break; - case WAIT_Msg4_ACK: - nr_check_Msg4_Ack(module_idP, CC_id, frameP, slotP, ra); - break; - default: - break; - } - } - } - stop_meas(&mac->schedule_ra); -} - -void nr_generate_Msg3_retransmission(module_id_t module_idP, - int CC_id, - frame_t frame, - sub_frame_t slot, - NR_RA_t *ra, - nfapi_nr_ul_dci_request_t *ul_dci_req) +static void nr_generate_Msg3_retransmission(module_id_t module_idP, + int CC_id, + frame_t frame, + sub_frame_t slot, + NR_RA_t *ra, + nfapi_nr_ul_dci_request_t *ul_dci_req) { gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; @@ -877,15 +868,14 @@ void nr_generate_Msg3_retransmission(module_id_t module_idP, } } -void nr_get_Msg3alloc(module_id_t module_id, - int CC_id, - NR_ServingCellConfigCommon_t *scc, - sub_frame_t current_slot, - frame_t current_frame, - NR_RA_t *ra, - int16_t *tdd_beam_association) +static void nr_get_Msg3alloc(module_id_t module_id, + int CC_id, + NR_ServingCellConfigCommon_t *scc, + sub_frame_t current_slot, + frame_t current_frame, + NR_RA_t *ra, + int16_t *tdd_beam_association) { - // msg3 is scheduled in mixed slot in the following TDD period uint16_t msg3_nb_rb = 8; // sdu has 6 or 8 bytes @@ -999,16 +989,19 @@ void nr_get_Msg3alloc(module_id_t module_id, ra->msg3_bwp_start = bwpStart; } - -void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, - NR_ServingCellConfigCommon_t *scc, - int round, - int startSymbolAndLength, - rnti_t rnti, int scs, - int bwp_size, int bwp_start, - int mappingtype, int fh, - int msg3_first_rb, int msg3_nb_rb) { - +static void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, + NR_ServingCellConfigCommon_t *scc, + int round, + int startSymbolAndLength, + rnti_t rnti, + int scs, + int bwp_size, + int bwp_start, + int mappingtype, + int fh, + int msg3_first_rb, + int msg3_nb_rb) +{ int start_symbol_index,nr_of_symbols; SLIV2SL(startSymbolAndLength, &start_symbol_index, &nr_of_symbols); @@ -1087,7 +1080,7 @@ void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, } } -void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra, uint8_t *RAR_pdu) +static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra, uint8_t *RAR_pdu) { gNB_MAC_INST *mac = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &mac->common_channels[CC_id]; @@ -1155,13 +1148,14 @@ void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t nr_fill_rar(module_idP, ra, RAR_pdu, pusch_pdu); } -void nr_generate_Msg2(module_id_t module_idP, - int CC_id, - frame_t frameP, - sub_frame_t slotP, - NR_RA_t *ra, - nfapi_nr_dl_tti_request_t *DL_req, - nfapi_nr_tx_data_request_t *TX_req) + +static void nr_generate_Msg2(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t slotP, + NR_RA_t *ra, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req) { gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; @@ -1427,22 +1421,29 @@ void nr_generate_Msg2(module_id_t module_idP, } } -void prepare_dl_pdus(gNB_MAC_INST *nr_mac, - NR_RA_t *ra, - NR_UE_DL_BWP_t *dl_bwp, - nfapi_nr_dl_tti_request_body_t *dl_req, - NR_sched_pucch_t *pucch, - NR_pdsch_dmrs_t dmrs_info, - NR_tda_info_t tda, - int aggregation_level, - int CCEIndex, - int tb_size, int ndi, - int tpc, int delta_PRI, - int current_harq_pid, - int time_domain_assignment, - int CC_id, int rnti, int round, - int mcsIndex, int tb_scaling, - int pduindex, int rbStart, int rbSize) +static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, + NR_RA_t *ra, + NR_UE_DL_BWP_t *dl_bwp, + nfapi_nr_dl_tti_request_body_t *dl_req, + NR_sched_pucch_t *pucch, + NR_pdsch_dmrs_t dmrs_info, + NR_tda_info_t tda, + int aggregation_level, + int CCEIndex, + int tb_size, + int ndi, + int tpc, + int delta_PRI, + int current_harq_pid, + int time_domain_assignment, + int CC_id, + int rnti, + int round, + int mcsIndex, + int tb_scaling, + int pduindex, + int rbStart, + int rbSize) { // look up the PDCCH PDU for this CC, BWP, and CORESET. If it does not exist, create it. This is especially // important if we have multiple RAs, and the DLSCH has to reuse them, so we need to mark them @@ -1613,13 +1614,13 @@ void prepare_dl_pdus(gNB_MAC_INST *nr_mac, LOG_D(NR_MAC,"numDlDci: %i\n", pdcch_pdu_rel15->numDlDci); } -void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, - int CC_id, - frame_t frameP, - sub_frame_t slotP, - NR_RA_t *ra, - nfapi_nr_dl_tti_request_t *DL_req, - nfapi_nr_tx_data_request_t *TX_req) +static void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t slotP, + NR_RA_t *ra, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req) { gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; @@ -1799,13 +1800,13 @@ void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, sched_ctrl->ul_failure = 0; } -void nr_generate_Msg4(module_id_t module_idP, - int CC_id, - frame_t frameP, - sub_frame_t slotP, - NR_RA_t *ra, - nfapi_nr_dl_tti_request_t *DL_req, - nfapi_nr_tx_data_request_t *TX_req) +static void nr_generate_Msg4(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t slotP, + NR_RA_t *ra, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req) { gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; @@ -2056,8 +2057,8 @@ void nr_generate_Msg4(module_id_t module_idP, } } -void nr_check_Msg4_Ack(module_id_t module_id, int CC_id, frame_t frame, sub_frame_t slot, NR_RA_t *ra) { - +static void nr_check_Msg4_Ack(module_id_t module_id, int CC_id, frame_t frame, sub_frame_t slot, NR_RA_t *ra) +{ NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[module_id]->UE_info, ra->rnti); const int current_harq_pid = ra->harq_pid; @@ -2098,7 +2099,10 @@ void nr_check_Msg4_Ack(module_id_t module_id, int CC_id, frame_t frame, sub_fram } } -void nr_clear_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP, NR_RA_t *ra){ +void nr_clear_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP, NR_RA_t *ra) +{ + /* we assume that this function is mutex-protected from outside */ + NR_SCHED_ENSURE_LOCKED(&RC.nrmac[module_idP]->sched_lock); LOG_D(NR_MAC,"[gNB %d][RAPROC] CC_id %d Frame %d Clear Random access information rnti %x\n", module_idP, CC_id, frameP, ra->rnti); ra->state = RA_IDLE; ra->timing_offset = 0; @@ -2141,11 +2145,8 @@ void nr_clear_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP, NR_RA_t // - sending only 1 RAR subPDU // - UL Grant: hardcoded CSI, TPC, time alloc // - padding -void nr_fill_rar(uint8_t Mod_idP, - NR_RA_t * ra, - uint8_t * dlsch_buffer, - nfapi_nr_pusch_pdu_t *pusch_pdu){ - +static void nr_fill_rar(uint8_t Mod_idP, NR_RA_t *ra, uint8_t *dlsch_buffer, nfapi_nr_pusch_pdu_t *pusch_pdu) +{ LOG_D(NR_MAC, "[gNB] Generate RAR MAC PDU frame %d slot %d preamble index %u TA command %d \n", ra->Msg2_frame, ra-> Msg2_slot, ra->preamble_index, ra->timing_offset); NR_RA_HEADER_BI *rarbi = (NR_RA_HEADER_BI *) dlsch_buffer; NR_RA_HEADER_RAPID *rarh = (NR_RA_HEADER_RAPID *) (dlsch_buffer + 1); @@ -2239,3 +2240,43 @@ void nr_fill_rar(uint8_t Mod_idP, csi_req, t_crnti); } + +void nr_schedule_RA(module_id_t module_idP, + frame_t frameP, + sub_frame_t slotP, + nfapi_nr_ul_dci_request_t *ul_dci_req, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req) +{ + gNB_MAC_INST *mac = RC.nrmac[module_idP]; + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ + NR_SCHED_ENSURE_LOCKED(&mac->sched_lock); + + start_meas(&mac->schedule_ra); + for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { + NR_COMMON_channels_t *cc = &mac->common_channels[CC_id]; + for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { + NR_RA_t *ra = &cc->ra[i]; + LOG_D(NR_MAC, "RA[state:%d]\n", ra->state); + switch (ra->state) { + case Msg2: + nr_generate_Msg2(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); + break; + case Msg3_retransmission: + nr_generate_Msg3_retransmission(module_idP, CC_id, frameP, slotP, ra, ul_dci_req); + break; + case Msg3_dcch_dtch: + nr_generate_Msg3_dcch_dtch_response(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); + case Msg4: + nr_generate_Msg4(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); + break; + case WAIT_Msg4_ACK: + nr_check_Msg4_Ack(module_idP, CC_id, frameP, slotP, ra); + break; + default: + break; + } + } + } + stop_meas(&mac->schedule_ra); +} diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index f6d1f83e351d8e57c8279e2f64b43a7273589b8e..0d66ec0842e1bef67b8aea453ed00b326ef33769 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -51,11 +51,15 @@ extern RAN_CONTEXT_t RC; -void schedule_ssb(frame_t frame, sub_frame_t slot, - NR_ServingCellConfigCommon_t *scc, - nfapi_nr_dl_tti_request_body_t *dl_req, - int i_ssb, uint8_t scoffset, uint16_t offset_pointa, uint32_t payload) { - +static void schedule_ssb(frame_t frame, + sub_frame_t slot, + NR_ServingCellConfigCommon_t *scc, + nfapi_nr_dl_tti_request_body_t *dl_req, + int i_ssb, + uint8_t scoffset, + uint16_t offset_pointa, + uint32_t payload) +{ uint8_t beam_index = 0; nfapi_nr_dl_tti_request_pdu_t *dl_config_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; memset((void *) dl_config_pdu, 0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); @@ -86,12 +90,25 @@ void schedule_ssb(frame_t frame, sub_frame_t slot, dl_req->nPDUs++; LOG_D(MAC,"Scheduling ssb %d at frame %d and slot %d\n",i_ssb,frame,slot); +} +static void fill_ssb_vrb_map(NR_COMMON_channels_t *cc, int rbStart, int ssb_subcarrier_offset, uint16_t symStart, int CC_id) +{ + AssertFatal(*cc->ServingCellConfigCommon->ssbSubcarrierSpacing != + NR_SubcarrierSpacing_kHz240, + "240kHZ subcarrier won't work with current VRB map because a single SSB might be across 2 slots\n"); + + uint16_t *vrb_map = cc[CC_id].vrb_map; + + const int extra_prb = ssb_subcarrier_offset > 0; + for (int rb = 0; rb < 20+extra_prb; rb++) + vrb_map[rbStart + rb] = SL_to_bitmap(symStart, 4); } void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP, nfapi_nr_dl_tti_request_t *DL_req) { gNB_MAC_INST *gNB = RC.nrmac[module_idP]; + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ NR_COMMON_channels_t *cc; nfapi_nr_dl_tti_request_body_t *dl_req; NR_MIB_t *mib = RC.nrrrc[module_idP]->carrier.mib->message.choice.mib; @@ -254,33 +271,15 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP, } } -void schedule_nr_SI(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) { -//---------------------------------------- -} - -void fill_ssb_vrb_map (NR_COMMON_channels_t *cc, int rbStart, int ssb_subcarrier_offset, uint16_t symStart, int CC_id) { - - AssertFatal(*cc->ServingCellConfigCommon->ssbSubcarrierSpacing != - NR_SubcarrierSpacing_kHz240, - "240kHZ subcarrier won't work with current VRB map because a single SSB might be across 2 slots\n"); - - uint16_t *vrb_map = cc[CC_id].vrb_map; - - const int extra_prb = ssb_subcarrier_offset > 0; - for (int rb = 0; rb < 20+extra_prb; rb++) - vrb_map[rbStart + rb] = SL_to_bitmap(symStart, 4); - -} - -uint32_t schedule_control_sib1(module_id_t module_id, - int CC_id, - NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, - int time_domain_allocation, - NR_pdsch_dmrs_t *dmrs_parms, - NR_tda_info_t *tda_info, - uint8_t candidate_idx, - uint16_t num_total_bytes) { - +static uint32_t schedule_control_sib1(module_id_t module_id, + int CC_id, + NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, + int time_domain_allocation, + NR_pdsch_dmrs_t *dmrs_parms, + NR_tda_info_t *tda_info, + uint8_t candidate_idx, + uint16_t num_total_bytes) +{ gNB_MAC_INST *gNB_mac = RC.nrmac[module_id]; NR_COMMON_channels_t *cc = &gNB_mac->common_channels[CC_id]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; @@ -377,14 +376,14 @@ uint32_t schedule_control_sib1(module_id_t module_id, return TBS; } -void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP, - nfapi_nr_dl_tti_request_body_t *dl_req, - int pdu_index, - NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, - uint32_t TBS, - int StartSymbolIndex, - int NrOfSymbols) { - +static void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP, + nfapi_nr_dl_tti_request_body_t *dl_req, + int pdu_index, + NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, + uint32_t TBS, + int StartSymbolIndex, + int NrOfSymbols) +{ gNB_MAC_INST *gNB_mac = RC.nrmac[Mod_idP]; NR_COMMON_channels_t *cc = gNB_mac->common_channels; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; @@ -515,7 +514,6 @@ void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP, LOG_D(MAC,"ShiftIndex: %i\n", pdcch_pdu_rel15->ShiftIndex); LOG_D(MAC,"precoderGranularity: %i\n", pdcch_pdu_rel15->precoderGranularity); LOG_D(MAC,"numDlDci: %i\n", pdcch_pdu_rel15->numDlDci); - } void schedule_nr_sib1(module_id_t module_idP, @@ -524,6 +522,7 @@ void schedule_nr_sib1(module_id_t module_idP, nfapi_nr_dl_tti_request_t *DL_req, nfapi_nr_tx_data_request_t *TX_req) { + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ // TODO: Get these values from RRC const int CC_id = 0; uint8_t candidate_idx = 0; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 71b4499c55a86923e4a849adb030967f9f2eae04..4d3d59c12efd5044c140fb4af1e6cd8deb63b08c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -55,6 +55,7 @@ const int get_dl_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot) { + /* we assume that this function is mutex-protected from outside */ const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; AssertFatal(tdd || nrmac->common_channels->frame_type == FDD, "Dynamic TDD not handled yet\n"); @@ -76,8 +77,12 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP, const NR_UE_sched_ctrl_t *ue_sched_ctl, unsigned char *mac_pdu, unsigned char drx_cmd, - unsigned char *ue_cont_res_id) { + unsigned char *ue_cont_res_id) +{ gNB_MAC_INST *gNB = RC.nrmac[module_idP]; + /* already mutex protected: called below and in _RA.c */ + NR_SCHED_ENSURE_LOCKED(&gNB->sched_lock); + NR_MAC_SUBHEADER_FIXED *mac_pdu_ptr = (NR_MAC_SUBHEADER_FIXED *) mac_pdu; uint8_t last_size = 0; int offset = 0, mac_ce_size, i, timing_advance_cmd, tag_id = 0; @@ -311,10 +316,8 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP, return offset; } -void nr_store_dlsch_buffer(module_id_t module_id, - frame_t frame, - sub_frame_t slot) { - +static void nr_store_dlsch_buffer(module_id_t module_id, frame_t frame, sub_frame_t slot) +{ UE_iterator(RC.nrmac[module_id]->UE_info.list, UE) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; sched_ctrl->num_total_bytes = 0; @@ -363,8 +366,9 @@ void nr_store_dlsch_buffer(module_id_t module_id, } } -void abort_nr_dl_harq(NR_UE_info_t* UE, int8_t harq_pid) { - +void abort_nr_dl_harq(NR_UE_info_t* UE, int8_t harq_pid) +{ + /* already mutex protected through handle_dl_harq() */ NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_harq_t *harq = &sched_ctrl->harq_processes[harq_pid]; @@ -375,13 +379,13 @@ void abort_nr_dl_harq(NR_UE_info_t* UE, int8_t harq_pid) { } -bool allocate_dl_retransmission(module_id_t module_id, - frame_t frame, - sub_frame_t slot, - uint16_t *rballoc_mask, - int *n_rb_sched, - NR_UE_info_t *UE, - int current_harq_pid) +static bool allocate_dl_retransmission(module_id_t module_id, + frame_t frame, + sub_frame_t slot, + uint16_t *rballoc_mask, + int *n_rb_sched, + NR_UE_info_t *UE, + int current_harq_pid) { int CC_id = 0; @@ -549,15 +553,14 @@ static int comparator(const void *p, const void *q) { return ((UEsched_t*)p)->coef < ((UEsched_t*)q)->coef; } -void pf_dl(module_id_t module_id, - frame_t frame, - sub_frame_t slot, - NR_UE_info_t **UE_list, - int max_num_ue, - int n_rb_sched, - uint16_t *rballoc_mask) +static void pf_dl(module_id_t module_id, + frame_t frame, + sub_frame_t slot, + NR_UE_info_t **UE_list, + int max_num_ue, + int n_rb_sched, + uint16_t *rballoc_mask) { - gNB_MAC_INST *mac = RC.nrmac[module_id]; NR_ServingCellConfigCommon_t *scc=mac->common_channels[0].ServingCellConfigCommon; // UEs that could be scheduled @@ -784,7 +787,7 @@ void pf_dl(module_id_t module_id, } } -void nr_fr1_dlsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t slot) +static void nr_fr1_dlsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t slot) { NR_UEs_t *UE_info = &RC.nrmac[module_id]->UE_info; @@ -843,6 +846,7 @@ void nr_fr1_dlsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t } nr_pp_impl_dl nr_init_fr1_dlsch_preprocessor(int CC_id) { + /* during initialization: no mutex needed */ /* in the PF algorithm, we have to use the TBsize to compute the coefficient. * This would include the number of DMRS symbols, which in turn depends on * the time domain allocation. In case we are in a mixed slot, we do not want @@ -876,6 +880,9 @@ void nr_schedule_ue_spec(module_id_t module_id, nfapi_nr_tx_data_request_t *TX_req) { gNB_MAC_INST *gNB_mac = RC.nrmac[module_id]; + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ + AssertFatal(pthread_mutex_trylock(&gNB_mac->sched_lock) == EBUSY, + "this function should be called with the scheduler mutex locked\n"); if (!is_xlsch_in_slot(gNB_mac->dlsch_slot_bitmap[slot / 64], slot)) return; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 96756d41cdfee6b9cee3a14bde31f9f646b5c00f..d59efafdc24c0c47a51e2d753adf7d7fa40f4de3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -50,6 +50,7 @@ void nr_preprocessor_phytest(module_id_t module_id, frame_t frame, sub_frame_t slot) { + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ if (!is_xlsch_in_slot(dlsch_slot_bitmap, slot)) return; NR_UE_info_t *UE = RC.nrmac[module_id]->UE_info.list[0]; @@ -192,6 +193,7 @@ uint64_t ulsch_slot_bitmap = (1 << 8); bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, sub_frame_t slot) { gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ NR_COMMON_channels_t *cc = nr_mac->common_channels; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; NR_UE_info_t *UE = nr_mac->UE_info.list[0]; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 0deb86a5dbd7e64ced31c33f677cedb542138f09..2a8457356a76bd47db720eff56cd5978fbcba414 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -509,7 +509,7 @@ void fill_pdcch_vrb_map(gNB_MAC_INST *mac, } } -bool multiple_2_3_5(int rb) +static bool multiple_2_3_5(int rb) { while (rb % 2 == 0) rb /= 2; @@ -2369,7 +2369,7 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf reset_srs_stats(UE); - pthread_mutex_lock(&UE_info->mutex); + NR_SCHED_LOCK(&UE_info->mutex); int i; for(i=0; i<MAX_MOBILES_PER_GNB; i++) { if (UE_info->list[i] == NULL) { @@ -2380,10 +2380,10 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf if (i == MAX_MOBILES_PER_GNB) { LOG_E(NR_MAC,"Try to add UE %04x but the list is full\n", rntiP); delete_nr_ue_data(UE, nr_mac->common_channels, &UE_info->uid_allocator); - pthread_mutex_unlock(&UE_info->mutex); + NR_SCHED_UNLOCK(&UE_info->mutex); return NULL; } - pthread_mutex_unlock(&UE_info->mutex); + NR_SCHED_UNLOCK(&UE_info->mutex); LOG_D(NR_MAC, "Add NR rnti %x\n", rntiP); dump_nr_list(UE_info->list); @@ -2487,8 +2487,11 @@ void reset_ul_harq_list(NR_UE_sched_ctrl_t *sched_ctrl) { void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti) { + /* already mutex protected */ + NR_SCHED_ENSURE_LOCKED(&nr_mac->sched_lock); + NR_UEs_t *UE_info = &nr_mac->UE_info; - pthread_mutex_lock(&UE_info->mutex); + NR_SCHED_LOCK(&UE_info->mutex); UE_iterator(UE_info->list, UE) { if (UE->rnti==rnti) break; @@ -2496,7 +2499,7 @@ void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti) if (!UE) { LOG_W(NR_MAC,"Call to del rnti %04x, but not existing\n", rnti); - pthread_mutex_unlock(&UE_info->mutex); + NR_SCHED_UNLOCK(&UE_info->mutex); return; } @@ -2506,7 +2509,7 @@ void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti) if(UE_info->list[i] && UE_info->list[i]->rnti != rnti) newUEs[newListIdx++]=UE_info->list[i]; memcpy(UE_info->list, newUEs, sizeof(UE_info->list)); - pthread_mutex_unlock(&UE_info->mutex); + NR_SCHED_UNLOCK(&UE_info->mutex); delete_nr_ue_data(UE, nr_mac->common_channels, &UE_info->uid_allocator); } @@ -2525,6 +2528,7 @@ uint8_t nr_get_tpc(int target, uint8_t cqi, int incr) { int get_pdsch_to_harq_feedback(NR_PUCCH_Config_t *pucch_Config, nr_dci_format_t dci_format, uint8_t *pdsch_to_harq_feedback) { + /* already mutex protected: held in nr_acknack_scheduling() */ if (dci_format == NR_DL_DCI_FORMAT_1_0) { for (int i = 0; i < 8; i++) @@ -2545,6 +2549,9 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, sub_frame_t slot, int n_slo int CC_id = 0; NR_UEs_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; gNB_MAC_INST *gNB_mac = RC.nrmac[Mod_idP]; + + NR_SCHED_ENSURE_LOCKED(&gNB_mac->sched_lock); + uint16_t *vrb_map = gNB_mac->common_channels[CC_id].vrb_map; UE_info->sched_csirs = false; @@ -2770,7 +2777,10 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, sub_frame_t slot, int n_slo void nr_mac_update_timers(module_id_t module_id, frame_t frame, - sub_frame_t slot) { + sub_frame_t slot) +{ + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ + NR_SCHED_ENSURE_LOCKED(&RC.nrmac[module_id]->sched_lock); NR_UEs_t *UE_info = &RC.nrmac[module_id]->UE_info; UE_iterator(UE_info->list, UE) { @@ -2824,7 +2834,10 @@ void nr_mac_update_timers(module_id_t module_id, void schedule_nr_bwp_switch(module_id_t module_id, frame_t frame, - sub_frame_t slot) { + sub_frame_t slot) +{ + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ + NR_SCHED_ENSURE_LOCKED(&RC.nrmac[module_id]->sched_lock); NR_UEs_t *UE_info = &RC.nrmac[module_id]->UE_info; @@ -2887,6 +2900,7 @@ void send_initial_ul_rrc_message(gNB_MAC_INST *mac, int rnti, const uint8_t *sdu LOG_W(MAC, "[RAPROC] Received SDU for CCCH length %d for UE %04x\n", sdu_len, rnti); NR_UE_info_t *UE = (NR_UE_info_t *)rawUE; + NR_SCHED_ENSURE_LOCKED(&mac->sched_lock); uint8_t du2cu[1024]; int encoded = encode_cellGroupConfig(UE->CellGroup, du2cu, sizeof(du2cu)); @@ -2904,6 +2918,7 @@ void send_initial_ul_rrc_message(gNB_MAC_INST *mac, int rnti, const uint8_t *sdu void prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE) { + NR_SCHED_ENSURE_LOCKED(&mac->sched_lock); /* create this UE's initial CellGroup */ /* Note: relying on the RRC is a hack, as we are in the DU; there should be * no RRC, remove in the future */ diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c index 8a85448c7fb23f415910bf07acfe0f1179d69d3a..3309e1af34fad78f8623bc79bbe18e35a24baa53 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c @@ -42,7 +42,8 @@ const uint16_t m_SRS[64] = { 4, 8, 12, 16, 16, 20, 24, 24, 28, 32, 36, 40, 48, 4 160, 160, 168, 176, 184, 192, 192, 192, 192, 208, 216, 224, 240, 240, 240, 240, 256, 256, 256, 264, 272, 272, 272 }; -uint32_t max4(uint32_t a, uint32_t b,uint32_t c,uint32_t d) { +static uint32_t max4(uint32_t a, uint32_t b, uint32_t c, uint32_t d) +{ int x = max(a, b); x = max(x, c); x = max(x, d); @@ -53,6 +54,9 @@ void nr_srs_ri_computation(const nfapi_nr_srs_normalized_channel_iq_matrix_t *nr const NR_UE_UL_BWP_t *current_BWP, uint8_t *ul_ri) { + /* already mutex protected: held in handle_nr_srs_measurements() */ + NR_SCHED_ENSURE_LOCKED(&RC.nrmac[0]->sched_lock); + // If the gNB or UE has 1 antenna, the rank is always 1, i.e., *ul_ri = 0. // For 2x2 scenario, we compute the rank of channel. // The computation for 2x4, 4x2, 4x4, ... scenarios are not implemented yet. In these cases, the function sets *ul_ri = 0, which is always a valid value. @@ -137,7 +141,14 @@ void nr_srs_ri_computation(const nfapi_nr_srs_normalized_channel_iq_matrix_t *nr } -void nr_configure_srs(nfapi_nr_srs_pdu_t *srs_pdu, int slot, int module_id, int CC_id, NR_UE_info_t *UE, NR_SRS_ResourceSet_t *srs_resource_set, NR_SRS_Resource_t *srs_resource, int buffer_index) +static void nr_configure_srs(nfapi_nr_srs_pdu_t *srs_pdu, + int slot, + int module_id, + int CC_id, + NR_UE_info_t *UE, + NR_SRS_ResourceSet_t *srs_resource_set, + NR_SRS_Resource_t *srs_resource, + int buffer_index) { NR_UE_UL_BWP_t *current_BWP = &UE->current_UL_BWP; @@ -196,7 +207,13 @@ void nr_configure_srs(nfapi_nr_srs_pdu_t *srs_pdu, int slot, int module_id, int vrb_map_UL[i + srs_pdu->bwp_start] |= mask; } -void nr_fill_nfapi_srs(int module_id, int CC_id, NR_UE_info_t* UE, int frame, int slot, NR_SRS_ResourceSet_t *srs_resource_set, NR_SRS_Resource_t *srs_resource) +static void nr_fill_nfapi_srs(int module_id, + int CC_id, + NR_UE_info_t *UE, + int frame, + int slot, + NR_SRS_ResourceSet_t *srs_resource_set, + NR_SRS_Resource_t *srs_resource) { int index = ul_buffer_index(frame, slot, UE->current_UL_BWP.scs, RC.nrmac[module_id]->UL_tti_req_ahead_size); @@ -226,8 +243,10 @@ void nr_fill_nfapi_srs(int module_id, int CC_id, NR_UE_info_t* UE, int frame, in *********************************************************************/ void nr_schedule_srs(int module_id, frame_t frame, int slot) { - + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ gNB_MAC_INST *nrmac = RC.nrmac[module_id]; + NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); + NR_UEs_t *UE_info = &nrmac->UE_info; UE_iterator(UE_info->list, UE) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index bc1796a6dc5933ab70b85ef01466387092666057..e1716458d23ad5195536247bcef2285099cd8ba5 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -144,7 +144,7 @@ static const int diff_rsrp_ssb_csi_meas_10_1_6_1_2[16] = { -30 // 10 - 15 }; -int get_pucch_index(int frame, int slot, int n_slots_frame, const NR_TDD_UL_DL_Pattern_t *tdd, int sched_pucch_size) +static int get_pucch_index(int frame, int slot, int n_slots_frame, const NR_TDD_UL_DL_Pattern_t *tdd, int sched_pucch_size) { // PUCCH structures are indexed by slot in the PUCCH period determined by sched_pucch_size number of UL slots // this functions return the index to the structure for slot passed to the function @@ -167,6 +167,9 @@ void nr_schedule_pucch(gNB_MAC_INST *nrmac, frame_t frameP, sub_frame_t slotP) { + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ + NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); + if (!is_xlsch_in_slot(nrmac->ulsch_slot_bitmap[slotP / 64], slotP)) return; @@ -198,7 +201,10 @@ void nr_csi_meas_reporting(int Mod_idP, frame_t frame, sub_frame_t slot) { + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ gNB_MAC_INST *nrmac = RC.nrmac[Mod_idP]; + NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); + UE_iterator(nrmac->UE_info.list, UE ) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; @@ -324,8 +330,8 @@ static void handle_dl_harq(NR_UE_info_t * UE, } } -int checkTargetSSBInFirst64TCIStates_pdschConfig(int ssb_index_t, NR_UE_info_t * UE) { - +static int checkTargetSSBInFirst64TCIStates_pdschConfig(int ssb_index_t, NR_UE_info_t *UE) +{ const NR_PDSCH_Config_t *pdsch_Config = UE->current_DL_BWP.pdsch_Config; int nb_tci_states = pdsch_Config ? pdsch_Config->tci_StatesToAddModList->list.count : 0; NR_TCI_State_t *tci =NULL; @@ -350,8 +356,8 @@ int checkTargetSSBInFirst64TCIStates_pdschConfig(int ssb_index_t, NR_UE_info_t * return -1; } -int checkTargetSSBInTCIStates_pdcchConfig(int ssb_index_t, NR_UE_info_t *UE) { - +static int checkTargetSSBInTCIStates_pdcchConfig(int ssb_index_t, NR_UE_info_t *UE) +{ NR_TCI_State_t *tci =NULL; NR_TCI_StateId_t *tci_id = NULL; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; @@ -390,7 +396,8 @@ int checkTargetSSBInTCIStates_pdcchConfig(int ssb_index_t, NR_UE_info_t *UE) { } //returns the measured RSRP value (upper limit) -int get_measured_rsrp(uint8_t index) { +static int get_measured_rsrp(uint8_t index) +{ //if index is invalid returning minimum rsrp -140 if(index <= 15 || index >= 114) return MIN_RSRP_VALUE; @@ -399,7 +406,7 @@ int get_measured_rsrp(uint8_t index) { } //returns the differential RSRP value (upper limit) -int get_diff_rsrp(uint8_t index, int strongest_rsrp) { +static int get_diff_rsrp(uint8_t index, int strongest_rsrp) { if(strongest_rsrp != -1) { return strongest_rsrp + diff_rsrp_ssb_csi_meas_10_1_6_1_2[index]; } else @@ -409,8 +416,8 @@ int get_diff_rsrp(uint8_t index, int strongest_rsrp) { //identifies the target SSB Beam index //keeps the required date for PDCCH and PDSCH TCI state activation/deactivation CE consutruction globally //handles triggering of PDCCH and PDSCH MAC CEs -void tci_handling(NR_UE_info_t *UE, frame_t frame, slot_t slot) { - +static void tci_handling(NR_UE_info_t *UE, frame_t frame, slot_t slot) +{ int strongest_ssb_rsrp = 0; int cqi_idx = 0; int curr_ssb_beam_index = 0; //ToDo: yet to know how to identify the serving ssb beam index @@ -583,24 +590,23 @@ void tci_handling(NR_UE_info_t *UE, frame_t frame, slot_t slot) { } }//tci_presentInDCI }//is-triggering_beam_switch -}//tci handling +} // tci handling - -uint8_t pickandreverse_bits(uint8_t *payload, uint16_t bitlen, uint8_t start_bit) { +static uint8_t pickandreverse_bits(uint8_t *payload, uint16_t bitlen, uint8_t start_bit) +{ uint8_t rev_bits = 0; for (int i=0; i<bitlen; i++) rev_bits |= ((payload[(start_bit+i)/8]>>((start_bit+i)%8))&0x01)<<(bitlen-i-1); return rev_bits; } - -void evaluate_rsrp_report(NR_UE_info_t *UE, - NR_UE_sched_ctrl_t *sched_ctrl, - uint8_t csi_report_id, - uint8_t *payload, - int *cumul_bits, - NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type){ - +static void evaluate_rsrp_report(NR_UE_info_t *UE, + NR_UE_sched_ctrl_t *sched_ctrl, + uint8_t csi_report_id, + uint8_t *payload, + int *cumul_bits, + NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type) +{ nr_csi_report_t *csi_report = &UE->csi_report_template[csi_report_id]; uint8_t cri_ssbri_bitlen = csi_report->CSI_report_bitlen.cri_ssbri_bitlen; uint16_t curr_payload; @@ -659,21 +665,18 @@ void evaluate_rsrp_report(NR_UE_info_t *UE, stats->num_rsrp_meas++; } -void evaluate_cri_report(uint8_t *payload, - uint8_t cri_bitlen, - int cumul_bits, - NR_UE_sched_ctrl_t *sched_ctrl){ - +static void evaluate_cri_report(uint8_t *payload, uint8_t cri_bitlen, int cumul_bits, NR_UE_sched_ctrl_t *sched_ctrl) +{ uint8_t temp_cri = pickandreverse_bits(payload, cri_bitlen, cumul_bits); sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.cri = temp_cri; } -int evaluate_ri_report(uint8_t *payload, - uint8_t ri_bitlen, - uint8_t ri_restriction, - int cumul_bits, - NR_UE_sched_ctrl_t *sched_ctrl){ - +static int evaluate_ri_report(uint8_t *payload, + uint8_t ri_bitlen, + uint8_t ri_restriction, + int cumul_bits, + NR_UE_sched_ctrl_t *sched_ctrl) +{ uint8_t ri_index = pickandreverse_bits(payload, ri_bitlen, cumul_bits); int count=0; for (int i=0; i<8; i++) { @@ -689,13 +692,12 @@ int evaluate_ri_report(uint8_t *payload, AssertFatal(1==0, "Decoded ri %d does not correspond to any valid value in ri_restriction %d\n",ri_index,ri_restriction); } - -void evaluate_cqi_report(uint8_t *payload, - nr_csi_report_t *csi_report, - int cumul_bits, - uint8_t ri, - NR_UE_info_t *UE, - uint8_t cqi_Table) +static void evaluate_cqi_report(uint8_t *payload, + nr_csi_report_t *csi_report, + int cumul_bits, + uint8_t ri, + NR_UE_info_t *UE, + uint8_t cqi_Table) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; @@ -723,13 +725,12 @@ void evaluate_cqi_report(uint8_t *payload, sched_ctrl->dl_max_mcs = get_mcs_from_cqi(mcs_table, cqi_Table, cqi_idx); } - -uint8_t evaluate_pmi_report(uint8_t *payload, - nr_csi_report_t *csi_report, - int cumul_bits, - uint8_t ri, - NR_UE_sched_ctrl_t *sched_ctrl){ - +static uint8_t evaluate_pmi_report(uint8_t *payload, + nr_csi_report_t *csi_report, + int cumul_bits, + uint8_t ri, + NR_UE_sched_ctrl_t *sched_ctrl) +{ int x1_bitlen = csi_report->csi_meas_bitlen.pmi_x1_bitlen[ri]; int x2_bitlen = csi_report->csi_meas_bitlen.pmi_x2_bitlen[ri]; int tot_bitlen = x1_bitlen + x2_bitlen; @@ -744,16 +745,14 @@ uint8_t evaluate_pmi_report(uint8_t *payload, sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.pmi_x2); return tot_bitlen; - } - -int evaluate_li_report(uint8_t *payload, - nr_csi_report_t *csi_report, - int cumul_bits, - uint8_t ri, - NR_UE_sched_ctrl_t *sched_ctrl){ - +static int evaluate_li_report(uint8_t *payload, + nr_csi_report_t *csi_report, + int cumul_bits, + uint8_t ri, + NR_UE_sched_ctrl_t *sched_ctrl) +{ int li_bitlen = csi_report->csi_meas_bitlen.li_bitlen[ri]; if (li_bitlen>0) { @@ -762,14 +761,10 @@ int evaluate_li_report(uint8_t *payload, sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.li = temp_li; } return li_bitlen; - } -void skip_zero_padding(int *cumul_bits, - nr_csi_report_t *csi_report, - uint8_t ri, - uint16_t max_bitlen) { - +static void skip_zero_padding(int *cumul_bits, nr_csi_report_t *csi_report, uint8_t ri, uint16_t max_bitlen) +{ // actual number of reported bits depends on the reported rank // zero padding bits are added to have a predetermined max bit length to decode @@ -783,13 +778,12 @@ void skip_zero_padding(int *cumul_bits, *cumul_bits+=(max_bitlen-reported_bitlen); } - -void extract_pucch_csi_report(NR_CSI_MeasConfig_t *csi_MeasConfig, - const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu, - frame_t frame, - slot_t slot, - NR_UE_info_t *UE, - NR_ServingCellConfigCommon_t *scc) +static void extract_pucch_csi_report(NR_CSI_MeasConfig_t *csi_MeasConfig, + const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu, + frame_t frame, + slot_t slot, + NR_UE_info_t *UE, + NR_ServingCellConfigCommon_t *scc) { /** From Table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel */ uint8_t *payload = uci_pdu->csi_part1.csi_part1_payload; @@ -929,9 +923,12 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, sub_frame_t slot, const nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_01) { - NR_UE_info_t * UE = find_nr_UE(&RC.nrmac[mod_id]->UE_info, uci_01->rnti); + gNB_MAC_INST *nrmac = RC.nrmac[mod_id]; + NR_SCHED_LOCK(&nrmac->sched_lock); + NR_UE_info_t * UE = find_nr_UE(&nrmac->UE_info, uci_01->rnti); if (!UE) { LOG_E(NR_MAC, "%s(): unknown RNTI %04x in PUCCH UCI\n", __func__, uci_01->rnti); + NR_SCHED_UNLOCK(&nrmac->sched_lock); return; } NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; @@ -941,7 +938,7 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) { const uint8_t harq_value = uci_01->harq->harq_list[harq_bit].harq_value; const uint8_t harq_confidence = uci_01->harq->harq_confidence_level; - NR_UE_harq_t *harq = find_harq(frame, slot, UE, RC.nrmac[mod_id]->dl_bler.harq_round_max); + NR_UE_harq_t *harq = find_harq(frame, slot, UE, nrmac->dl_bler.harq_round_max); if (!harq) { LOG_E(NR_MAC, "Oh no! Could not find a harq in %s!\n", __FUNCTION__); break; @@ -950,13 +947,13 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, const int8_t pid = sched_ctrl->feedback_dl_harq.head; remove_front_nr_list(&sched_ctrl->feedback_dl_harq); LOG_D(NR_MAC,"%4d.%2d bit %d pid %d ack/nack %d\n",frame, slot, harq_bit,pid,harq_value); - handle_dl_harq(UE, pid, harq_value == 0 && harq_confidence == 0, RC.nrmac[mod_id]->dl_bler.harq_round_max); + handle_dl_harq(UE, pid, harq_value == 0 && harq_confidence == 0, nrmac->dl_bler.harq_round_max); if (harq_confidence == 1) UE->mac_stats.pucch0_DTX++; } // tpc (power control) only if we received AckNack if (uci_01->harq->harq_confidence_level==0) - sched_ctrl->tpc1 = nr_get_tpc(RC.nrmac[mod_id]->pucch_target_snrx10, uci_01->ul_cqi, 30); + sched_ctrl->tpc1 = nr_get_tpc(nrmac->pucch_target_snrx10, uci_01->ul_cqi, 30); else sched_ctrl->tpc1 = 3; sched_ctrl->pucch_snrx10 = uci_01->ul_cqi * 5 - 640; @@ -974,6 +971,7 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, } free(uci_01->sr); } + NR_SCHED_UNLOCK(&nrmac->sched_lock); } void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, @@ -981,15 +979,21 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, sub_frame_t slot, const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_234) { - NR_UE_info_t * UE = find_nr_UE(&RC.nrmac[mod_id]->UE_info, uci_234->rnti); + gNB_MAC_INST *nrmac = RC.nrmac[mod_id]; + NR_SCHED_LOCK(&nrmac->sched_lock); + + NR_UE_info_t * UE = find_nr_UE(&nrmac->UE_info, uci_234->rnti); if (!UE) { + NR_SCHED_UNLOCK(&nrmac->sched_lock); LOG_E(NR_MAC, "%s(): unknown RNTI %04x in PUCCH UCI\n", __func__, uci_234->rnti); return; } NR_CSI_MeasConfig_t *csi_MeasConfig = UE->current_UL_BWP.csi_MeasConfig; - if (csi_MeasConfig==NULL) + if (csi_MeasConfig==NULL) { + NR_SCHED_UNLOCK(&nrmac->sched_lock); return; + } NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; // tpc (power control) @@ -1014,13 +1018,13 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, DevAssert(harq->is_waiting); const int8_t pid = sched_ctrl->feedback_dl_harq.head; remove_front_nr_list(&sched_ctrl->feedback_dl_harq); - handle_dl_harq(UE, pid, uci_234->harq.harq_crc != 1 && acknack, RC.nrmac[mod_id]->dl_bler.harq_round_max); + handle_dl_harq(UE, pid, uci_234->harq.harq_crc != 1 && acknack, nrmac->dl_bler.harq_round_max); } free(uci_234->harq.harq_payload); } if ((uci_234->pduBitmap >> 2) & 0x01) { //API to parse the csi report and store it into sched_ctrl - extract_pucch_csi_report(csi_MeasConfig, uci_234, frame, slot, UE, RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon); + extract_pucch_csi_report(csi_MeasConfig, uci_234, frame, slot, UE, nrmac->common_channels->ServingCellConfigCommon); //TCI handling function tci_handling(UE,frame, slot); free(uci_234->csi_part1.csi_part1_payload); @@ -1029,9 +1033,10 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, //@TODO:Handle CSI Report 2 // nothing to free (yet) } + NR_SCHED_UNLOCK(&nrmac->sched_lock); } -void set_pucch_allocation(const NR_UE_UL_BWP_t *ul_bwp, const int r_pucch, const int bwp_size, NR_sched_pucch_t *pucch) +static void set_pucch_allocation(const NR_UE_UL_BWP_t *ul_bwp, const int r_pucch, const int bwp_size, NR_sched_pucch_t *pucch) { if(r_pucch<0){ const NR_PUCCH_Resource_t *resource = ul_bwp->pucch_Config->resourceToAddModList->list.array[0]; @@ -1053,11 +1058,8 @@ void set_pucch_allocation(const NR_UE_UL_BWP_t *ul_bwp, const int r_pucch, const } } -bool test_pucch0_vrb_occupation(const NR_sched_pucch_t *pucch, - uint16_t *vrb_map_UL, - const int bwp_start, - const int bwp_size) { - +static bool test_pucch0_vrb_occupation(const NR_sched_pucch_t *pucch, uint16_t *vrb_map_UL, const int bwp_start, const int bwp_size) +{ // We assume initial cyclic shift is always 0 so different pucch resources can't overlap // verifying occupation of PRBs for ACK/NACK on dedicated pucch @@ -1076,9 +1078,7 @@ bool test_pucch0_vrb_occupation(const NR_sched_pucch_t *pucch, return true; } -void set_pucch0_vrb_occupation(const NR_sched_pucch_t *pucch, - uint16_t *vrb_map_UL, - const int bwp_start) +static void set_pucch0_vrb_occupation(const NR_sched_pucch_t *pucch, uint16_t *vrb_map_UL, const int bwp_start) { for (int l=0; l<pucch->nr_of_symb; l++) { uint16_t symb = SL_to_bitmap(pucch->start_symb+l, 1); @@ -1100,6 +1100,8 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac, int r_pucch, int is_common) { + /* we assume that this function is mutex-protected from outside. Since it is + * called often, don't try to lock every time */ const int CC_id = 0; const int minfbtime = mac->minRXTXTIMEpdsch; @@ -1204,6 +1206,9 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac, void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot) { + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ + NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); + if (!is_xlsch_in_slot(nrmac->ulsch_slot_bitmap[slot / 64], slot)) return; const int CC_id = 0; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index e1a4e716efe4acd0f76df9d660b0a88fbf83c70a..80c1652b61caa1aeb3d41c2f13d02e18619e86de 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -39,7 +39,10 @@ //#define SRS_IND_DEBUG -const int get_ul_tda(gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int frame, int slot) { +const int get_ul_tda(gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int frame, int slot) +{ + /* we assume that this function is mutex-protected from outside */ + NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); /* there is a mixed slot only when in TDD */ const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; @@ -61,14 +64,8 @@ const int get_ul_tda(gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *sc return 0; // if FDD or not mixed slot in TDD, for now use default TDA (TODO handle CSI-RS slots) } -int compute_ph_factor(int mu, - int tbs_bits, - int rb, - int n_layers, - int n_symbols, - int n_dmrs, - long *deltaMCS) { - +static int compute_ph_factor(int mu, int tbs_bits, int rb, int n_layers, int n_symbols, int n_dmrs, long *deltaMCS) +{ // 38.213 7.1.1 // if the PUSCH transmission is over more than one layer delta_tf = 0 int delta_tf = 0; @@ -109,14 +106,14 @@ int compute_ph_factor(int mu, // F: length of L is 0:8 or 1:16 bits wide // R: Reserved bit, set to zero. -int nr_process_mac_pdu(instance_t module_idP, - NR_UE_info_t* UE, - uint8_t CC_id, - frame_t frameP, - sub_frame_t slot, - uint8_t *pduP, - int pdu_len, - const int8_t harq_pid) +static int nr_process_mac_pdu(instance_t module_idP, + NR_UE_info_t *UE, + uint8_t CC_id, + frame_t frameP, + sub_frame_t slot, + uint8_t *pduP, + int pdu_len, + const int8_t harq_pid) { uint8_t done = 0; @@ -462,7 +459,7 @@ int nr_process_mac_pdu(instance_t module_idP, return 0; } -void abort_nr_ul_harq(NR_UE_info_t *UE, int8_t harq_pid) +static void abort_nr_ul_harq(NR_UE_info_t *UE, int8_t harq_pid) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_ul_harq_t *harq = &sched_ctrl->ul_harq_processes[harq_pid]; @@ -479,7 +476,7 @@ void abort_nr_ul_harq(NR_UE_info_t *UE, int8_t harq_pid) sched_ctrl->sched_ul_bytes = 0; } -bool get_UE_waiting_CFRA_msg3(const gNB_MAC_INST *gNB_mac, const int CC_id, const frame_t frame, const sub_frame_t slot) +static bool get_UE_waiting_CFRA_msg3(const gNB_MAC_INST *gNB_mac, const int CC_id, const frame_t frame, const sub_frame_t slot) { bool UE_waiting_CFRA_msg3 = false; for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { @@ -498,17 +495,22 @@ void handle_nr_ul_harq(const int CC_idP, sub_frame_t slot, const nfapi_nr_crc_t *crc_pdu) { - NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[mod_id]->UE_info, crc_pdu->rnti); - bool UE_waiting_CFRA_msg3 = get_UE_waiting_CFRA_msg3(RC.nrmac[mod_id], CC_idP, frame, slot); + gNB_MAC_INST *nrmac = RC.nrmac[mod_id]; + NR_SCHED_LOCK(&nrmac->sched_lock); + + NR_UE_info_t *UE = find_nr_UE(&nrmac->UE_info, crc_pdu->rnti); + bool UE_waiting_CFRA_msg3 = get_UE_waiting_CFRA_msg3(nrmac, CC_idP, frame, slot); if (!UE || UE_waiting_CFRA_msg3 == true) { LOG_W(NR_MAC, "handle harq for rnti %04x, in RA process\n", crc_pdu->rnti); for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) { - NR_RA_t *ra = &RC.nrmac[mod_id]->common_channels[CC_idP].ra[i]; - if (ra->state >= WAIT_Msg3 && - ra->rnti == crc_pdu->rnti) + NR_RA_t *ra = &nrmac->common_channels[CC_idP].ra[i]; + if (ra->state >= WAIT_Msg3 && ra->rnti == crc_pdu->rnti) { + NR_SCHED_UNLOCK(&nrmac->sched_lock); return; + } } + NR_SCHED_UNLOCK(&nrmac->sched_lock); LOG_E(NR_MAC, "%s(): unknown RNTI 0x%04x in PUSCH\n", __func__, crc_pdu->rnti); return; } @@ -521,8 +523,10 @@ void handle_nr_ul_harq(const int CC_idP, crc_pdu->harq_id, harq_pid, crc_pdu->rnti); - if (harq_pid < 0) + if (harq_pid < 0) { + NR_SCHED_UNLOCK(&nrmac->sched_lock); return; + } remove_front_nr_list(&sched_ctrl->feedback_ul_harq); sched_ctrl->ul_harq_processes[harq_pid].is_waiting = false; @@ -562,22 +566,23 @@ void handle_nr_ul_harq(const int CC_idP, crc_pdu->rnti); add_tail_nr_list(&sched_ctrl->retrans_ul_harq, harq_pid); } + NR_SCHED_UNLOCK(&nrmac->sched_lock); } /* * When data are received on PHY and transmitted to MAC */ -void nr_rx_sdu(const module_id_t gnb_mod_idP, - const int CC_idP, - const frame_t frameP, - const sub_frame_t slotP, - const rnti_t rntiP, - uint8_t *sduP, - const uint16_t sdu_lenP, - const uint16_t timing_advance, - const uint8_t ul_cqi, - const uint16_t rssi){ - +static void _nr_rx_sdu(const module_id_t gnb_mod_idP, + const int CC_idP, + const frame_t frameP, + const sub_frame_t slotP, + const rnti_t rntiP, + uint8_t *sduP, + const uint16_t sdu_lenP, + const uint16_t timing_advance, + const uint8_t ul_cqi, + const uint16_t rssi) +{ gNB_MAC_INST *gNB_mac = RC.nrmac[gnb_mod_idP]; const int current_rnti = rntiP; @@ -841,8 +846,25 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, } } -uint32_t calc_power_complex(const int16_t *x, const int16_t *y, const uint32_t size) { +void nr_rx_sdu(const module_id_t gnb_mod_idP, + const int CC_idP, + const frame_t frameP, + const sub_frame_t slotP, + const rnti_t rntiP, + uint8_t *sduP, + const uint16_t sdu_lenP, + const uint16_t timing_advance, + const uint8_t ul_cqi, + const uint16_t rssi) +{ + gNB_MAC_INST *gNB_mac = RC.nrmac[gnb_mod_idP]; + NR_SCHED_LOCK(&gNB_mac->sched_lock); + _nr_rx_sdu(gnb_mod_idP, CC_idP, frameP, slotP, rntiP, sduP, sdu_lenP, timing_advance, ul_cqi, rssi); + NR_SCHED_UNLOCK(&gNB_mac->sched_lock); +} +static uint32_t calc_power_complex(const int16_t *x, const int16_t *y, const uint32_t size) +{ // Real part value int64_t sum_x = 0; int64_t sum_x2 = 0; @@ -864,7 +886,8 @@ uint32_t calc_power_complex(const int16_t *x, const int16_t *y, const uint32_t s return power_re+power_im; } -c16_t nr_h_times_w(c16_t h, char w) { +static c16_t nr_h_times_w(c16_t h, char w) +{ c16_t output; switch (w) { case '0': // 0 @@ -893,11 +916,11 @@ c16_t nr_h_times_w(c16_t h, char w) { return output; } -uint8_t get_max_tpmi(const NR_PUSCH_Config_t *pusch_Config, - const uint16_t num_ue_srs_ports, - const uint8_t *nrOfLayers, - int *additional_max_tpmi) { - +static uint8_t get_max_tpmi(const NR_PUSCH_Config_t *pusch_Config, + const uint16_t num_ue_srs_ports, + const uint8_t *nrOfLayers, + int *additional_max_tpmi) +{ uint8_t max_tpmi = 0; if ((pusch_Config && pusch_Config->txConfig != NULL && *pusch_Config->txConfig == NR_PUSCH_Config__txConfig_nonCodebook) || @@ -1056,13 +1079,13 @@ uint8_t get_max_tpmi(const NR_PUSCH_Config_t *pusch_Config, return max_tpmi; } -void get_precoder_matrix_coef(char *w, - const uint8_t ul_ri, - const uint16_t num_ue_srs_ports, - const long transform_precoding, - const uint8_t tpmi, - const uint8_t uI, - int layer_idx) +static void get_precoder_matrix_coef(char *w, + const uint8_t ul_ri, + const uint16_t num_ue_srs_ports, + const long transform_precoding, + const uint8_t tpmi, + const uint8_t uI, + int layer_idx) { if (ul_ri == 0) { if (num_ue_srs_ports == 2) { @@ -1085,15 +1108,16 @@ void get_precoder_matrix_coef(char *w, } } -int nr_srs_tpmi_estimation(const NR_PUSCH_Config_t *pusch_Config, - const long transform_precoding, - const uint8_t *channel_matrix, - const uint8_t normalized_iq_representation, - const uint16_t num_gnb_antenna_elements, - const uint16_t num_ue_srs_ports, - const uint16_t prg_size, - const uint16_t num_prgs, - const uint8_t ul_ri) { +static int nr_srs_tpmi_estimation(const NR_PUSCH_Config_t *pusch_Config, + const long transform_precoding, + const uint8_t *channel_matrix, + const uint8_t normalized_iq_representation, + const uint16_t num_gnb_antenna_elements, + const uint16_t num_ue_srs_ports, + const uint16_t prg_size, + const uint16_t num_prgs, + const uint8_t ul_ri) +{ if (ul_ri > 1) { LOG_D(NR_MAC, "TPMI computation for ul_ri %i is not implemented yet!\n", ul_ri); return 0; @@ -1173,6 +1197,8 @@ void handle_nr_srs_measurements(const module_id_t module_id, const sub_frame_t slot, nfapi_nr_srs_indication_pdu_t *srs_ind) { + gNB_MAC_INST *nrmac = RC.nrmac[module_id]; + NR_SCHED_LOCK(&nrmac->sched_lock); LOG_D(NR_MAC, "(%d.%d) Received SRS indication for UE %04x\n", frame, slot, srs_ind->rnti); #ifdef SRS_IND_DEBUG @@ -1188,11 +1214,13 @@ void handle_nr_srs_measurements(const module_id_t module_id, NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[module_id]->UE_info, srs_ind->rnti); if (!UE) { LOG_W(NR_MAC, "Could not find UE for RNTI %04x\n", srs_ind->rnti); + NR_SCHED_UNLOCK(&nrmac->sched_lock); return; } if (srs_ind->timing_advance_offset == 0xFFFF) { LOG_W(NR_MAC, "Invalid timing advance offset for RNTI %04x\n", srs_ind->rnti); + NR_SCHED_UNLOCK(&nrmac->sched_lock); return; } @@ -1210,6 +1238,7 @@ void handle_nr_srs_measurements(const module_id_t module_id, if (nr_srs_bf_report.wide_band_snr == 0xFF) { LOG_W(NR_MAC, "Invalid wide_band_snr for RNTI %04x\n", srs_ind->rnti); + NR_SCHED_UNLOCK(&nrmac->sched_lock); return; } @@ -1308,12 +1337,14 @@ void handle_nr_srs_measurements(const module_id_t module_id, default: AssertFatal(1 == 0, "Invalid SRS usage\n"); } + NR_SCHED_UNLOCK(&nrmac->sched_lock); } long get_K2(NR_PUSCH_TimeDomainResourceAllocationList_t *tdaList, int time_domain_assignment, int mu) { + /* we assume that this function is mutex-protected from outside */ NR_PUSCH_TimeDomainResourceAllocation_t *tda = tdaList->list.array[time_domain_assignment]; if (tda->k2) @@ -1363,7 +1394,7 @@ static bool nr_UE_is_to_be_scheduled(const NR_ServingCellConfigCommon_t *scc, in return has_data || sched_ctrl->SR || high_inactivity; } -void update_ul_ue_R_Qm(int mcs, int mcs_table, const NR_PUSCH_Config_t *pusch_Config, uint16_t *R, uint8_t *Qm) +static void update_ul_ue_R_Qm(int mcs, int mcs_table, const NR_PUSCH_Config_t *pusch_Config, uint16_t *R, uint8_t *Qm) { *R = nr_get_code_rate_ul(mcs, mcs_table); *Qm = nr_get_Qm_ul(mcs, mcs_table); @@ -1374,7 +1405,14 @@ void update_ul_ue_R_Qm(int mcs, int mcs_table, const NR_PUSCH_Config_t *pusch_Co } } -void nr_ue_max_mcs_min_rb(int mu, int ph_limit, NR_sched_pusch_t *sched_pusch, NR_UE_UL_BWP_t *ul_bwp, uint16_t minRb, uint32_t tbs, uint16_t *Rb, uint8_t *mcs) +static void nr_ue_max_mcs_min_rb(int mu, + int ph_limit, + NR_sched_pusch_t *sched_pusch, + NR_UE_UL_BWP_t *ul_bwp, + uint16_t minRb, + uint32_t tbs, + uint16_t *Rb, + uint8_t *mcs) { AssertFatal(*Rb >= minRb, "illegal Rb %d < minRb %d\n", *Rb, minRb); AssertFatal(*mcs >= 0 && *mcs <= 28, "illegal MCS %d\n", *mcs); @@ -1577,13 +1615,13 @@ static int comparator(const void *p, const void *q) { return ((UEsched_t*)p)->coef < ((UEsched_t*)q)->coef; } -void pf_ul(module_id_t module_id, - frame_t frame, - sub_frame_t slot, - NR_UE_info_t *UE_list[], - int max_num_ue, - int n_rb_sched, - uint16_t *rballoc_mask) +static void pf_ul(module_id_t module_id, + frame_t frame, + sub_frame_t slot, + NR_UE_info_t *UE_list[], + int max_num_ue, + int n_rb_sched, + uint16_t *rballoc_mask) { const int CC_id = 0; @@ -1870,7 +1908,7 @@ void pf_ul(module_id_t module_id, } } -bool nr_fr1_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t slot) +static bool nr_fr1_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t slot) { gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; NR_COMMON_channels_t *cc = nr_mac->common_channels; @@ -1971,6 +2009,7 @@ bool nr_fr1_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t nr_pp_impl_ul nr_init_fr1_ulsch_preprocessor(int CC_id) { + /* during initialization: no mutex needed */ /* in the PF algorithm, we have to use the TBsize to compute the coefficient. * This would include the number of DMRS symbols, which in turn depends on * the time domain allocation. In case we are in a mixed slot, we do not want @@ -2002,6 +2041,9 @@ nr_pp_impl_ul nr_init_fr1_ulsch_preprocessor(int CC_id) void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot, nfapi_nr_ul_dci_request_t *ul_dci_req) { gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ + NR_SCHED_ENSURE_LOCKED(&nr_mac->sched_lock); + /* Uplink data ONLY can be scheduled when the current slot is downlink slot, * because we have to schedule the DCI0 first before schedule uplink data */ if (!is_xlsch_in_slot(nr_mac->dlsch_slot_bitmap[slot / 64], slot)) { diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index a700c5c652b003f431c8da0335234170c42c03c6..c2cbe8799dc2c501b302ebeccddcd29f3c5cb8a7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -40,8 +40,6 @@ void set_cset_offset(uint16_t); void mac_top_init_gNB(ngran_node_t node_type); -void config_common(gNB_MAC_INST *nrmac, int pdsch_AntennaPorts, int pusch_AntennaPorts, NR_ServingCellConfigCommon_t *scc); - int nr_mac_enable_ue_rrc_processing_timer(module_id_t Mod_idP, rnti_t rnti, NR_SubcarrierSpacing_t subcarrierSpacing, @@ -58,7 +56,6 @@ void nr_mac_config_sib1(gNB_MAC_INST *nrmac, NR_BCCH_DL_SCH_Message_t *sib1); bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup); bool nr_mac_prepare_ra_nsa_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup); bool nr_mac_update_cellgroup(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup); -bool nr_mac_update_RA(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup); void clear_nr_nfapi_information(gNB_MAC_INST *gNB, int CC_idP, @@ -87,15 +84,6 @@ void nr_schedule_ue_spec(module_id_t module_id, nfapi_nr_dl_tti_request_t *DL_req, nfapi_nr_tx_data_request_t *TX_req); -uint32_t schedule_control_sib1(module_id_t module_id, - int CC_id, - NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, - int time_domain_allocation, - NR_pdsch_dmrs_t *dmrs_parms, - NR_tda_info_t *tda_info, - uint8_t candidate_idx, - uint16_t num_total_bytes); - /* \brief default FR1 DL preprocessor init routine, returns preprocessor to call */ nr_pp_impl_dl nr_init_fr1_dlsch_preprocessor(int CC_id); @@ -139,41 +127,6 @@ void nr_clear_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP, NR_RA_t int nr_allocate_CCEs(int module_idP, int CC_idP, frame_t frameP, sub_frame_t slotP, int test_only); -void nr_get_Msg3alloc(module_id_t module_id, - int CC_id, - NR_ServingCellConfigCommon_t *scc, - sub_frame_t current_subframe, - frame_t current_frame, - NR_RA_t *ra, - int16_t *tdd_beam_association); - -void nr_generate_Msg3_retransmission(module_id_t module_idP, - int CC_id, - frame_t frameP, - sub_frame_t slotP, - NR_RA_t *ra, - nfapi_nr_ul_dci_request_t *ul_dci_req); - -/* \brief Function in gNB to fill RAR pdu when requested by PHY. -@param ra Instance of RA resources of gNB -@param dlsch_buffer Pointer to RAR input buffer -@param N_RB_UL Number of UL resource blocks -*/ -void nr_fill_rar(uint8_t Mod_idP, - NR_RA_t * ra, - uint8_t * dlsch_buffer, - nfapi_nr_pusch_pdu_t *pusch_pdu); - -void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, - NR_ServingCellConfigCommon_t *scc, - int round, - int startSymbolAndLength, - rnti_t rnti, int scs, - int bwp_size, int bwp_start, - int mappingtype, int fh, - int msg3_first_rb, int msg3_nb_rb); - - void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP); uint16_t nr_mac_compute_RIV(uint16_t N_RB_DL, uint16_t RBstart, uint16_t Lcrbs); @@ -380,39 +333,10 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP, unsigned char drx_cmd, unsigned char *ue_cont_res_id); -void nr_generate_Msg2(module_id_t module_idP, - int CC_id, - frame_t frameP, - sub_frame_t slotP, - NR_RA_t *ra, - nfapi_nr_dl_tti_request_t *dl_req, - nfapi_nr_tx_data_request_t *TX_req); - -void nr_generate_Msg4(module_id_t module_idP, - int CC_id, - frame_t frameP, - sub_frame_t slotP, - NR_RA_t *ra, - nfapi_nr_dl_tti_request_t *DL_req, - nfapi_nr_tx_data_request_t *TX_req); - -void nr_check_Msg4_Ack(module_id_t module_id, int CC_id, frame_t frame, sub_frame_t slot, NR_RA_t *ra); - -void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, - int CC_id, - frame_t frameP, - sub_frame_t slotP, - NR_RA_t *ra, - nfapi_nr_dl_tti_request_t *DL_req, - nfapi_nr_tx_data_request_t *TX_req); - int binomial(int n, int k); bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot); -void fill_ssb_vrb_map (NR_COMMON_channels_t *cc, int rbStart, int ssb_subcarrier_offset, uint16_t symStart, int CC_id); - - /* \brief Function to indicate a received SDU on ULSCH. @param Mod_id Instance ID of gNB @param CC_id Component carrier index @@ -451,13 +375,6 @@ void handle_nr_srs_measurements(const module_id_t module_id, const sub_frame_t slot, nfapi_nr_srs_indication_pdu_t *srs_ind); -int16_t ssb_index_from_prach(module_id_t module_idP, - frame_t frameP, - sub_frame_t slotP, - uint16_t preamble_index, - uint8_t freq_index, - uint8_t symbol); - void find_SSB_and_RO_available(gNB_MAC_INST *nrmac); NR_pdsch_dmrs_t get_dl_dmrs_params(const NR_ServingCellConfigCommon_t *scc, diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 0a47699591de0670766db89972f695578a541e14..4fdad6fb8151072b9d71a7b4d4d30e473bfea49e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -22,12 +22,130 @@ #include "mac_rrc_dl_handler.h" #include "mac_proto.h" -#include "openair2/RRC/NR/rrc_gNB_UE_context.h" #include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h" +#include "openair2/RRC/NR/MESSAGES/asn1_msg.h" -#include "NR_RRCSetup.h" -#include "NR_DL-CCCH-Message.h" -#include "NR_CellGroupConfig.h" +static NR_RLC_BearerConfig_t *get_bearerconfig_from_srb(const f1ap_srb_to_be_setup_t *srb) +{ + long priority = srb->srb_id; // high priority for SRB + e_NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration bucket = + NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms5; + return get_SRB_RLC_BearerConfig(srb->srb_id, priority, bucket); +} + +static void handle_ue_context_srbs_setup(const f1ap_ue_context_setup_t *req, + f1ap_ue_context_setup_t *resp, + NR_CellGroupConfig_t *cellGroupConfig) +{ + DevAssert(req != NULL && resp != NULL && cellGroupConfig != NULL); + + resp->srbs_to_be_setup_length = req->srbs_to_be_setup_length; + resp->srbs_to_be_setup = calloc(req->srbs_to_be_setup_length, sizeof(*resp->srbs_to_be_setup)); + AssertFatal(resp->srbs_to_be_setup != NULL, "out of memory\n"); + for (int i = 0; i < req->srbs_to_be_setup_length; i++) { + f1ap_srb_to_be_setup_t *srb = &req->srbs_to_be_setup[i]; + NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_srb(srb); + nr_rlc_add_srb(req->rnti, srb->srb_id, rlc_BearerConfig); + + resp->srbs_to_be_setup[i] = *srb; + + int ret = ASN_SEQUENCE_ADD(&cellGroupConfig->rlc_BearerToAddModList->list, rlc_BearerConfig); + DevAssert(ret == 0); + } +} + +static NR_RLC_BearerConfig_t *get_bearerconfig_from_drb(const f1ap_drb_to_be_setup_t *drb) +{ + const NR_RLC_Config_PR rlc_conf = drb->rlc_mode == RLC_MODE_UM ? NR_RLC_Config_PR_um_Bi_Directional : NR_RLC_Config_PR_am; + long priority = 13; // hardcoded for the moment + return get_DRB_RLC_BearerConfig(3 + drb->drb_id, drb->drb_id, rlc_conf, priority); +} + +static void handle_ue_context_drbs_setup(const f1ap_ue_context_setup_t *req, + f1ap_ue_context_setup_t *resp, + NR_CellGroupConfig_t *cellGroupConfig) +{ + DevAssert(req != NULL && resp != NULL && cellGroupConfig != NULL); + + /* Note: the actual GTP tunnels are created in the F1AP breanch of + * ue_context_*_response() */ + resp->drbs_to_be_setup_length = req->drbs_to_be_setup_length; + resp->drbs_to_be_setup = calloc(req->drbs_to_be_setup_length, sizeof(*resp->drbs_to_be_setup)); + AssertFatal(resp->drbs_to_be_setup != NULL, "out of memory\n"); + for (int i = 0; i < req->drbs_to_be_setup_length; i++) { + f1ap_drb_to_be_setup_t *drb = &req->drbs_to_be_setup[i]; + NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_drb(drb); + nr_rlc_add_drb(req->rnti, drb->drb_id, rlc_BearerConfig); + + resp->drbs_to_be_setup[i] = *drb; + + int ret = ASN_SEQUENCE_ADD(&cellGroupConfig->rlc_BearerToAddModList->list, rlc_BearerConfig); + DevAssert(ret == 0); + } +} + +void ue_context_setup_request(const f1ap_ue_context_setup_t *req) +{ + gNB_MAC_INST *mac = RC.nrmac[0]; + /* response has same type as request... */ + f1ap_ue_context_setup_t resp = { + .gNB_CU_ue_id = req->gNB_CU_ue_id, + .gNB_DU_ue_id = req->gNB_DU_ue_id, + .rnti = req->rnti, + }; + + if (req->cu_to_du_rrc_information != NULL) { + AssertFatal(req->cu_to_du_rrc_information->cG_ConfigInfo == NULL, "CG-ConfigInfo not handled\n"); + AssertFatal(req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList == NULL, "UE capabilities not handled yet\n"); + AssertFatal(req->cu_to_du_rrc_information->measConfig == NULL, "MeasConfig not handled\n"); + } + + NR_SCHED_LOCK(&mac->sched_lock); + + NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[0]->UE_info, req->rnti); + AssertFatal(UE != NULL, "did not find UE with RNTI %04x, but UE Context Setup Failed not implemented\n", UE->rnti); + + if (req->srbs_to_be_setup_length > 0) + handle_ue_context_srbs_setup(req, &resp, UE->CellGroup); + + if (req->drbs_to_be_setup_length > 0) { + handle_ue_context_drbs_setup(req, &resp, NULL); + } + + if (req->rrc_container != NULL) + nr_rlc_srb_recv_sdu(req->rnti, DCCH, req->rrc_container, req->rrc_container_length); + + //nr_mac_update_cellgroup() + resp.du_to_cu_rrc_information = calloc(1, sizeof(du_to_cu_rrc_information_t)); + AssertFatal(resp.du_to_cu_rrc_information != NULL, "out of memory\n"); + resp.du_to_cu_rrc_information->cellGroupConfig = calloc(1,1024); + AssertFatal(resp.du_to_cu_rrc_information->cellGroupConfig != NULL, "out of memory\n"); + asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, + NULL, + UE->CellGroup, + resp.du_to_cu_rrc_information->cellGroupConfig, + 1024); + AssertFatal(enc_rval.encoded > 0, "Could not encode CellGroup, failed element %s\n", enc_rval.failed_type->name); + resp.du_to_cu_rrc_information->cellGroupConfig_length = (enc_rval.encoded + 7) >> 3; + + /* TODO: need to apply after UE context reconfiguration confirmed? */ + process_CellGroup(UE->CellGroup, &UE->UE_sched_ctrl); + + NR_SCHED_UNLOCK(&mac->sched_lock); + + /* some sanity checks, since we use the same type for request and response */ + DevAssert(resp.cu_to_du_rrc_information == NULL); + DevAssert(resp.du_to_cu_rrc_information != NULL); + DevAssert(resp.rrc_container == NULL && resp.rrc_container_length == 0); + + mac->mac_rrc.ue_context_setup_response(req, &resp); + + /* free the memory we allocated above */ + free(resp.srbs_to_be_setup); + free(resp.drbs_to_be_setup); + free(resp.du_to_cu_rrc_information->cellGroupConfig); + free(resp.du_to_cu_rrc_information); +} int dl_rrc_message(module_id_t module_id, const f1ap_dl_rrc_message_t *dl_rrc) { diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h index ecbc95eef07190ea4fee1976f2a953c4e3040894..25b51c2d845924eda11e211943f71d66fd894c90 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h @@ -25,6 +25,8 @@ #include "platform_types.h" #include "f1ap_messages_types.h" +void ue_context_setup_request(const f1ap_ue_context_setup_t *req); + int dl_rrc_message(module_id_t module_id, const f1ap_dl_rrc_message_t *dl_rrc); #endif /* MAC_RRC_DL_HANDLER_H */ diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h index cb80ba4fa55c1f5c3a6ba9df5e6a41b546a3a850..53736a1695145c0a7f5c1b6f870712251e86dfb4 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h @@ -25,6 +25,8 @@ #include "platform_types.h" #include "f1ap_messages_types.h" +typedef void (*ue_context_setup_response_func_t)(const f1ap_ue_context_setup_t* req, const f1ap_ue_context_setup_t *resp); + typedef void (*initial_ul_rrc_message_transfer_func_t)(module_id_t module_id, const f1ap_initial_ul_rrc_message_t *ul_rrc); struct nr_mac_rrc_ul_if_s; diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c index ace8b17f4912d7e14f7dacc719fc4d5b1e4aaab0..eafa54418567f30d65fa0e30a4d39890521ceb17 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c @@ -24,6 +24,37 @@ #include "mac_rrc_ul.h" +static void ue_context_setup_response_direct(const f1ap_ue_context_setup_t *req, const f1ap_ue_context_setup_t *resp) +{ + DevAssert(req->drbs_to_be_setup_length == resp->drbs_to_be_setup_length); + AssertFatal(req->drbs_to_be_setup_length == 0, "not implemented\n"); + + (void) req; /* we don't need the request -- it is to set up GTP in F1 case */ + MessageDef *msg = itti_alloc_new_message (TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_SETUP_RESP); + f1ap_ue_context_setup_t *f1ap_msg = &F1AP_UE_CONTEXT_SETUP_RESP(msg); + /* copy all fields, but reallocate memory buffers! */ + *f1ap_msg = *resp; + + if (resp->srbs_to_be_setup_length > 0) { + DevAssert(resp->srbs_to_be_setup != NULL); + f1ap_msg->srbs_to_be_setup_length = resp->srbs_to_be_setup_length; + f1ap_msg->srbs_to_be_setup = calloc(f1ap_msg->srbs_to_be_setup_length, sizeof(*f1ap_msg->srbs_to_be_setup)); + for (int i = 0; i < f1ap_msg->srbs_to_be_setup_length; ++i) + f1ap_msg->srbs_to_be_setup[i] = resp->srbs_to_be_setup[i]; + } + + f1ap_msg->du_to_cu_rrc_information = malloc(sizeof(*resp->du_to_cu_rrc_information)); + AssertFatal(f1ap_msg->du_to_cu_rrc_information != NULL, "out of memory\n"); + f1ap_msg->du_to_cu_rrc_information_length = resp->du_to_cu_rrc_information_length; + du_to_cu_rrc_information_t *du2cu = f1ap_msg->du_to_cu_rrc_information; + du2cu->cellGroupConfig_length = resp->du_to_cu_rrc_information->cellGroupConfig_length; + du2cu->cellGroupConfig = calloc(du2cu->cellGroupConfig_length, sizeof(*du2cu->cellGroupConfig)); + AssertFatal(du2cu->cellGroupConfig != NULL, "out of memory\n"); + memcpy(du2cu->cellGroupConfig, resp->du_to_cu_rrc_information->cellGroupConfig, du2cu->cellGroupConfig_length); + + itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); +} + static void initial_ul_rrc_message_transfer_direct(module_id_t module_id, const f1ap_initial_ul_rrc_message_t *ul_rrc) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_INITIAL_UL_RRC_MESSAGE); @@ -46,5 +77,6 @@ static void initial_ul_rrc_message_transfer_direct(module_id_t module_id, const void mac_rrc_ul_direct_init(struct nr_mac_rrc_ul_if_s *mac_rrc) { + mac_rrc->ue_context_setup_response = ue_context_setup_response_direct; mac_rrc->initial_ul_rrc_message_transfer = initial_ul_rrc_message_transfer_direct; } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c index 13547c5291ed0314e6cdaffa3de5a0409a45d660..c5bcb8814a4ffc936844f32f0961952421707f89 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -19,11 +19,47 @@ * conmnc_digit_lengtht@openairinterface.org */ +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + #include "nr_mac_gNB.h" #include "intertask_interface.h" +#include "openair3/ocp-gtpu/gtp_itf.h" #include "mac_rrc_ul.h" +static void ue_context_setup_response_f1ap(const f1ap_ue_context_setup_t *req, const f1ap_ue_context_setup_t *resp) +{ + DevAssert(req->drbs_to_be_setup_length == resp->drbs_to_be_setup_length); + AssertFatal(req->drbs_to_be_setup_length == 0, "not implmented\n"); + + DevAssert(req->srbs_to_be_setup_length == resp->srbs_to_be_setup_length); + MessageDef *msg = itti_alloc_new_message (TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_SETUP_RESP); + f1ap_ue_context_setup_t *f1ap_msg = &F1AP_UE_CONTEXT_SETUP_RESP(msg); + /* copy all fields, but reallocate rrc_containers! */ + *f1ap_msg = *resp; + + if (resp->srbs_to_be_setup_length > 0) { + DevAssert(resp->srbs_to_be_setup != NULL); + f1ap_msg->srbs_to_be_setup_length = resp->srbs_to_be_setup_length; + f1ap_msg->srbs_to_be_setup = calloc(f1ap_msg->srbs_to_be_setup_length, sizeof(*f1ap_msg->srbs_to_be_setup)); + for (int i = 0; i < f1ap_msg->srbs_to_be_setup_length; ++i) + f1ap_msg->srbs_to_be_setup[i] = resp->srbs_to_be_setup[i]; + } + + f1ap_msg->du_to_cu_rrc_information = malloc(sizeof(*resp->du_to_cu_rrc_information)); + AssertFatal(f1ap_msg->du_to_cu_rrc_information != NULL, "out of memory\n"); + f1ap_msg->du_to_cu_rrc_information_length = resp->du_to_cu_rrc_information_length; + du_to_cu_rrc_information_t *du2cu = f1ap_msg->du_to_cu_rrc_information; + du2cu->cellGroupConfig_length = resp->du_to_cu_rrc_information->cellGroupConfig_length; + du2cu->cellGroupConfig = calloc(du2cu->cellGroupConfig_length, sizeof(*du2cu->cellGroupConfig)); + AssertFatal(du2cu->cellGroupConfig != NULL, "out of memory\n"); + memcpy(du2cu->cellGroupConfig, resp->du_to_cu_rrc_information->cellGroupConfig, du2cu->cellGroupConfig_length); + + itti_send_msg_to_task(TASK_DU_F1, 0, msg); +} + static void initial_ul_rrc_message_transfer_f1ap(module_id_t module_id, const f1ap_initial_ul_rrc_message_t *ul_rrc) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_INITIAL_UL_RRC_MESSAGE); @@ -46,6 +82,7 @@ static void initial_ul_rrc_message_transfer_f1ap(module_id_t module_id, const f1 void mac_rrc_ul_f1ap_init(struct nr_mac_rrc_ul_if_s *mac_rrc) { + mac_rrc->ue_context_setup_response = ue_context_setup_response_f1ap; mac_rrc->initial_ul_rrc_message_transfer = initial_ul_rrc_message_transfer_f1ap; } diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index cd8e16c48b9ead19a33ae62d6a9bdfa8b440df48..d7cd8e1b4babfd95fe84a54cfc8cc6d753add63e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -60,7 +60,9 @@ void *nrmac_stats_thread(void *arg) { while (oai_exit == 0) { char *p = output; + NR_SCHED_LOCK(&gNB->sched_lock); p += dump_mac_stats(gNB, p, end - p, false); + NR_SCHED_UNLOCK(&gNB->sched_lock); p += snprintf(p, end - p, "\n"); p += print_meas_log(&gNB->eNB_scheduler, "DL & UL scheduling timing", NULL, NULL, p, end - p); p += print_meas_log(&gNB->schedule_dlsch, "dlsch scheduler", NULL, NULL, p, end - p); @@ -87,7 +89,11 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset const char *begin = output; const char *end = output + strlen; - pthread_mutex_lock(&gNB->UE_info.mutex); + /* this function is called from gNB_dlsch_ulsch_scheduler(), so assumes the + * scheduler to be locked*/ + NR_SCHED_ENSURE_LOCKED(&gNB->sched_lock); + + NR_SCHED_LOCK(&gNB->UE_info.mutex); UE_iterator(gNB->UE_info.list, UE) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_mac_stats_t *stats = &UE->mac_stats; @@ -175,7 +181,7 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset stats->ul.lc_bytes[lc_id]); } } - pthread_mutex_unlock(&gNB->UE_info.mutex); + NR_SCHED_UNLOCK(&gNB->UE_info.mutex); return output - begin; } @@ -233,6 +239,8 @@ void mac_top_init_gNB(ngran_node_t node_type) RC.nrmac[i]->first_MIB = true; + pthread_mutex_init(&RC.nrmac[i]->sched_lock, NULL); + pthread_mutex_init(&RC.nrmac[i]->UE_info.mutex, NULL); uid_linear_allocator_init(&RC.nrmac[i]->UE_info.uid_allocator); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index b8517da55e44214125234ed59e953de6ee4b8702..5f25713650a7ec1a3f8fcdf49c2c2b29d8e36b1b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -41,6 +41,25 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <pthread.h> + +#define NR_SCHED_LOCK(lock) \ + do { \ + int rc = pthread_mutex_lock(lock); \ + AssertFatal(rc == 0, "error while locking scheduler mutex\n"); \ + } while (0) + +#define NR_SCHED_UNLOCK(lock) \ + do { \ + int rc = pthread_mutex_unlock(lock); \ + AssertFatal(rc == 0, "error while locking scheduler mutex\n"); \ + } while (0) + +#define NR_SCHED_ENSURE_LOCKED(lock)\ + do {\ + int rc = pthread_mutex_trylock(lock); \ + AssertFatal(rc == EBUSY, "this function should be called with the scheduler mutex locked\n");\ + } while (0) /* Commmon */ #include "radio/COMMON/common_lib.h" @@ -641,6 +660,7 @@ typedef struct NR_bler_options { typedef struct nr_mac_rrc_ul_if_s { /* TODO add other message types as necessary */ + ue_context_setup_response_func_t ue_context_setup_response; initial_ul_rrc_message_transfer_func_t initial_ul_rrc_message_transfer; } nr_mac_rrc_ul_if_t; @@ -795,6 +815,8 @@ typedef struct gNB_MAC_INST_s { int16_t frame; int16_t slot; + pthread_mutex_t sched_lock; + } gNB_MAC_INST; #endif /*__LAYER2_NR_MAC_GNB_H__ */ diff --git a/openair2/RRC/NR/L2_nr_interface.c b/openair2/RRC/NR/L2_nr_interface.c index 2e83c69af28f7ed6fd499e0c124ae9d02c7b0fed..4e9c077afaa1d4a8ea951afe528e4bf3399d022e 100644 --- a/openair2/RRC/NR/L2_nr_interface.c +++ b/openair2/RRC/NR/L2_nr_interface.c @@ -55,12 +55,17 @@ void nr_rrc_mac_remove_ue(rnti_t rntiMaybeUEid) nr_rlc_remove_ue(rntiMaybeUEid); gNB_MAC_INST *nrmac = RC.nrmac[0]; + NR_SCHED_LOCK(&nrmac->sched_lock); mac_remove_nr_ue(nrmac, rntiMaybeUEid); + NR_SCHED_UNLOCK(&nrmac->sched_lock); } void nr_rrc_mac_update_cellgroup(rnti_t rntiMaybeUEid, NR_CellGroupConfig_t *cgc) { - nr_mac_update_cellgroup(RC.nrmac[0], rntiMaybeUEid, cgc); + gNB_MAC_INST *nrmac = RC.nrmac[0]; + NR_SCHED_LOCK(&nrmac->sched_lock); + nr_mac_update_cellgroup(nrmac, rntiMaybeUEid, cgc); + NR_SCHED_UNLOCK(&nrmac->sched_lock); } uint16_t mac_rrc_nr_data_req(const module_id_t Mod_idP, diff --git a/openair2/RRC/NR/mac_rrc_dl.h b/openair2/RRC/NR/mac_rrc_dl.h index 1943490cd6accb206de4cda7a66ab2c9f2409079..49ffccd4a7e6ba1a2d16b905bf65a50493f89b84 100644 --- a/openair2/RRC/NR/mac_rrc_dl.h +++ b/openair2/RRC/NR/mac_rrc_dl.h @@ -25,6 +25,8 @@ #include "platform_types.h" #include "f1ap_messages_types.h" +typedef void (*ue_context_setup_request_func_t)(const f1ap_ue_context_setup_t *req); + typedef void (*dl_rrc_message_transfer_func_t)(module_id_t module_id, const f1ap_dl_rrc_message_t *dl_rrc); struct nr_mac_rrc_dl_if_s; diff --git a/openair2/RRC/NR/mac_rrc_dl_direct.c b/openair2/RRC/NR/mac_rrc_dl_direct.c index 5c8d9d9d5bd1b759a8a0e3997986afc695539b8c..be416d69215a9c4002603a2cc5187f1a17d9f0eb 100644 --- a/openair2/RRC/NR/mac_rrc_dl_direct.c +++ b/openair2/RRC/NR/mac_rrc_dl_direct.c @@ -33,5 +33,6 @@ static void dl_rrc_message_transfer_direct(module_id_t module_id, const f1ap_dl_ void mac_rrc_dl_direct_init(nr_mac_rrc_dl_if_t *mac_rrc) { + mac_rrc->ue_context_setup_request = ue_context_setup_request; mac_rrc->dl_rrc_message_transfer = dl_rrc_message_transfer_direct; } diff --git a/openair2/RRC/NR/mac_rrc_dl_f1ap.c b/openair2/RRC/NR/mac_rrc_dl_f1ap.c index 40f3b4b6eaa70bc170ce3c112c854b7bb5ba3327..9bbddaf4768e568898ab484f661a07c57541b7fb 100644 --- a/openair2/RRC/NR/mac_rrc_dl_f1ap.c +++ b/openair2/RRC/NR/mac_rrc_dl_f1ap.c @@ -19,9 +19,27 @@ * conmnc_digit_lengtht@openairinterface.org */ +#include <stdlib.h> + #include "mac_rrc_dl.h" #include "nr_rrc_defs.h" +static void ue_context_setup_request_f1ap(const f1ap_ue_context_setup_t *req) +{ + MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_SETUP_REQ); + f1ap_ue_context_setup_t *f1ap_msg = &F1AP_UE_CONTEXT_SETUP_REQ(msg); + *f1ap_msg = *req; + AssertFatal(req->cu_to_du_rrc_information == NULL, "cu_to_du_rrc_information not supported yet\n"); + f1ap_msg->cu_to_du_rrc_information = malloc(sizeof(*f1ap_msg->cu_to_du_rrc_information)); + if (req->rrc_container_length > 0) { + f1ap_msg->rrc_container = calloc(req->rrc_container_length, sizeof(*f1ap_msg->rrc_container)); + AssertFatal(f1ap_msg->rrc_container != NULL, "out of memory\n"); + f1ap_msg->rrc_container_length = req->rrc_container_length; + memcpy(f1ap_msg->rrc_container, req->rrc_container, req->rrc_container_length); + } + itti_send_msg_to_task(TASK_CU_F1, 0, msg); +} + static void dl_rrc_message_transfer_f1ap(module_id_t module_id, const f1ap_dl_rrc_message_t *dl_rrc) { /* TODO call F1AP function directly? no real-time constraint here */ @@ -40,5 +58,6 @@ static void dl_rrc_message_transfer_f1ap(module_id_t module_id, const f1ap_dl_rr void mac_rrc_dl_f1ap_init(nr_mac_rrc_dl_if_t *mac_rrc) { + mac_rrc->ue_context_setup_request = ue_context_setup_request_f1ap; mac_rrc->dl_rrc_message_transfer = dl_rrc_message_transfer_f1ap; } diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index c739b174b670e60508aa2a9884a09266860ebebe..20ba902244e309daa2e8b7596bafa2537991e092 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -2323,6 +2323,8 @@ NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid, return cellGroupConfig; } +#include "common/ran_context.h" +#include "nr_rrc_defs.h" void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, const int uid, NR_UE_NR_Capability_t *uecap, @@ -2338,6 +2340,13 @@ void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, return; DevAssert(configuration->scc != NULL); + /* This is a hack and will be removed once the CellGroupConfig is fully + * handled at the DU */ + if (NODE_IS_CU(RC.nrrrc[0]->node_type)) { + LOG_W(RRC, "update of CellGroupConfig not yet supported in F1\n"); + return; + } + NR_SpCellConfig_t *SpCellConfig = cellGroupConfig->spCellConfig; NR_ServingCellConfigCommon_t *scc = configuration->scc; diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 93acdeac7bd94c681b9e959f20066849cfcf49f2..942e9ffb1f1889c9e05b3eb5301c20b63942bfb4 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -481,6 +481,7 @@ typedef struct { typedef struct nr_mac_rrc_dl_if_s { /* TODO add other message types as necessary */ + ue_context_setup_request_func_t ue_context_setup_request; dl_rrc_message_transfer_func_t dl_rrc_message_transfer; } nr_mac_rrc_dl_if_t; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 2d3628f7651301eabf2095ef5d1781430722224f..81a17afab1fcf81ec396838a66ab216790e9a90b 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -363,7 +363,6 @@ static void rrc_gNB_generate_RRCSetup(instance_t instance, // remove UE after 10 frames after RRCConnectionRelease is triggered ue_context_pP->ue_context.ue_release_timer_thres = 1000; - /* TODO: this should go through the E1 interface */ nr_pdcp_add_srbs(true, rnti, ue_context_pP->ue_context.SRB_configList, 0, NULL, NULL); f1ap_dl_rrc_message_t dl_rrc = { @@ -497,6 +496,7 @@ static void rrc_gNB_generate_defaultRRCReconfiguration(const protocol_ctxt_t *co /******************** Radio Bearer Config ********************/ gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; + AssertFatal(ue_p->nb_of_pdusessions == 0, "logic bug: PDU sessions present before RRC Connection established\n"); struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList = CALLOC(1, sizeof(*dedicatedNAS_MessageList)); @@ -2285,72 +2285,12 @@ rrc_gNB_decode_dcch( ul_dcch_msg); } - if (!NODE_IS_CU(gnb_rrc_inst->node_type)) { - if (UE->established_pdu_sessions_flag == 1) { - rrc_gNB_generate_dedicatedRRCReconfiguration(ctxt_pP, ue_context_p, NULL); - } else { - rrc_gNB_generate_defaultRRCReconfiguration(ctxt_pP, ue_context_p); - } - } else { - /*Generate a UE context setup request message towards the DU to provide the UE - *capability info and get the updates on master cell group config from the DU*/ - MessageDef *message_p; - message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_SETUP_REQ); - f1ap_ue_context_setup_t *req=&F1AP_UE_CONTEXT_SETUP_REQ (message_p); - //UE_IDs will be extracted from F1AP layer - req->gNB_CU_ue_id = 0; - req->gNB_DU_ue_id = 0; - req->rnti = UE->rnti; - req->mcc = gnb_rrc_inst->configuration.mcc[0]; - req->mnc = gnb_rrc_inst->configuration.mnc[0]; - req->mnc_digit_length = gnb_rrc_inst->configuration.mnc_digit_length[0]; - req->nr_cellid = gnb_rrc_inst->nr_cellid; - - if (UE->established_pdu_sessions_flag == 1) { - /*Instruction towards the DU for SRB2 configuration*/ - req->srbs_to_be_setup = malloc(1*sizeof(f1ap_srb_to_be_setup_t)); - req->srbs_to_be_setup_length = 1; - f1ap_srb_to_be_setup_t *SRBs=req->srbs_to_be_setup; - SRBs[0].srb_id = 2; - SRBs[0].lcid = 2; - - /*Instruction towards the DU for DRB configuration and tunnel creation*/ - req->drbs_to_be_setup = malloc(1*sizeof(f1ap_drb_to_be_setup_t)); - req->drbs_to_be_setup_length = 1; - f1ap_drb_to_be_setup_t *DRBs=req->drbs_to_be_setup; - LOG_I(RRC, "Length of DRB list:%d \n", req->drbs_to_be_setup_length); - DRBs[0].drb_id = 1; - DRBs[0].rlc_mode = RLC_MODE_AM; - DRBs[0].up_ul_tnl[0].tl_address = inet_addr(gnb_rrc_inst->eth_params_s.my_addr); - DRBs[0].up_ul_tnl[0].port = gnb_rrc_inst->eth_params_s.my_portd; - DRBs[0].up_ul_tnl_length = 1; - DRBs[0].up_dl_tnl[0].tl_address = inet_addr(gnb_rrc_inst->eth_params_s.remote_addr); - DRBs[0].up_dl_tnl[0].port = gnb_rrc_inst->eth_params_s.remote_portd; - DRBs[0].up_dl_tnl_length = 1; - } - if( ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.present == - NR_UECapabilityInformation__criticalExtensions_PR_ueCapabilityInformation ) { - struct NR_UE_CapabilityRAT_ContainerList *ue_CapabilityRAT_ContainerList = - ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList; - if(ue_CapabilityRAT_ContainerList!=NULL){ - LOG_I(NR_RRC, "ue_CapabilityRAT_ContainerList is present \n"); - req->cu_to_du_rrc_information = calloc(1,sizeof(cu_to_du_rrc_information_t)); - req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList = calloc(1,4096); - asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UE_CapabilityRAT_ContainerList, - NULL, - ue_CapabilityRAT_ContainerList, - req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList, - 4096); - AssertFatal (enc_rval.encoded > 0, "ASN1 ue_CapabilityRAT_ContainerList encoding failed (%s, %jd)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length = (enc_rval.encoded+7)>>3; - } - else{ - LOG_I(NR_RRC, "ue_CapabilityRAT_ContainerList is not present \n"); - } - } - itti_send_msg_to_task (TASK_CU_F1, ctxt_pP->module_id, message_p); - } + // we send the UE capabilities request before RRC connection is complete, + // so we cannot have a PDU session yet + AssertFatal(UE->established_pdu_sessions_flag == 0, "logic bug: received capabilities while PDU session established\n"); + // TODO: send UE context modification response with UE capabilities to + // allow DU configure CellGroupConfig + rrc_gNB_generate_defaultRRCReconfiguration(ctxt_pP, ue_context_p); break; @@ -2525,233 +2465,6 @@ void rrc_gNB_process_dc_overall_timeout(const module_id_t gnb_mod_idP, x2ap_ENDC rrc_remove_nsa_user(rrc, m->rnti); } -static void rrc_DU_process_ue_context_setup_request(MessageDef *msg_p, instance_t instance) -{ - f1ap_ue_context_setup_t * req=&F1AP_UE_CONTEXT_SETUP_REQ(msg_p); - gNB_RRC_INST *rrc = RC.nrrrc[instance]; - gNB_MAC_INST *mac = RC.nrmac[instance]; - rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(rrc, req->rnti); - gNB_RRC_UE_t *UE = &ue_context_p->ue_context; - MessageDef *message_p; - message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_SETUP_RESP); - f1ap_ue_context_setup_t * resp=&F1AP_UE_CONTEXT_SETUP_RESP(message_p); - uint32_t incoming_teid = 0; - - if(req->cu_to_du_rrc_information!=NULL){ - if(req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList!=NULL){ - LOG_I(NR_RRC, "Length of ue_CapabilityRAT_ContainerList is: %d \n", (int) req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length); - struct NR_UE_CapabilityRAT_ContainerList *ue_CapabilityRAT_ContainerList = NULL; - asn_dec_rval_t dec_rval = uper_decode_complete( NULL, - &asn_DEF_NR_UE_CapabilityRAT_ContainerList, - (void **)&ue_CapabilityRAT_ContainerList, - (uint8_t *)req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList, - (int) req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length); - - if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - AssertFatal(1==0,"UE Capability RAT ContainerList decode error\n"); - // free the memory - SEQUENCE_free( &asn_DEF_NR_UE_CapabilityRAT_ContainerList, ue_CapabilityRAT_ContainerList, 1 ); - return; - } - //To fill ue_context.UE_Capability_MRDC, ue_context.UE_Capability_nr ... - int NR_index = -1; - for(int i = 0;i < ue_CapabilityRAT_ContainerList->list.count; i++){ - if(ue_CapabilityRAT_ContainerList->list.array[i]->rat_Type == - NR_RAT_Type_nr){ - LOG_I(NR_RRC, "DU received NR_RAT_Type_nr UE capabilities Info through the UE Context Setup Request from the CU \n"); - if (UE->UE_Capability_nr) { - ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->UE_Capability_nr); - UE->UE_Capability_nr = 0; - } - - dec_rval = uper_decode(NULL, - &asn_DEF_NR_UE_NR_Capability, - (void **)&UE->UE_Capability_nr, - ue_CapabilityRAT_ContainerList->list.array[i]->ue_CapabilityRAT_Container.buf, - ue_CapabilityRAT_ContainerList->list.array[i]->ue_CapabilityRAT_Container.size, - 0, - 0); - if(LOG_DEBUGFLAG(DEBUG_ASN1)){ - xer_fprint(stdout, &asn_DEF_NR_UE_NR_Capability, UE->UE_Capability_nr); - } - - if((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)){ - LOG_E(NR_RRC, "UE %04x Failed to decode nr UE capabilities (%zu bytes)\n", req->rnti, dec_rval.consumed); - ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->UE_Capability_nr); - UE->UE_Capability_nr = 0; - } - - UE->UE_Capability_size = ue_CapabilityRAT_ContainerList->list.array[i]->ue_CapabilityRAT_Container.size; - if(NR_index != -1){ - LOG_E(NR_RRC,"fatal: more than 1 eutra capability\n"); - exit(1); - } - NR_index = i; - } - - if(ue_CapabilityRAT_ContainerList->list.array[i]->rat_Type == - NR_RAT_Type_eutra_nr){ - LOG_I(NR_RRC, "DU received NR_RAT_Type_eutra_nr UE capabilities Info through the UE Context Setup Request from the CU \n"); - if (UE->UE_Capability_MRDC) { - ASN_STRUCT_FREE(asn_DEF_NR_UE_MRDC_Capability, UE->UE_Capability_MRDC); - UE->UE_Capability_MRDC = 0; - } - dec_rval = uper_decode(NULL, - &asn_DEF_NR_UE_MRDC_Capability, - (void **)&UE->UE_Capability_MRDC, - ue_CapabilityRAT_ContainerList->list.array[i]->ue_CapabilityRAT_Container.buf, - ue_CapabilityRAT_ContainerList->list.array[i]->ue_CapabilityRAT_Container.size, - 0, - 0); - if(LOG_DEBUGFLAG(DEBUG_ASN1)){ - xer_fprint(stdout, &asn_DEF_NR_UE_MRDC_Capability, UE->UE_Capability_MRDC); - } - - if((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)){ - LOG_E(NR_RRC, "UE %04x Failed to decode nr UE capabilities (%zu bytes)\n", req->rnti, dec_rval.consumed); - ASN_STRUCT_FREE(asn_DEF_NR_UE_MRDC_Capability, UE->UE_Capability_MRDC); - UE->UE_Capability_MRDC = 0; - } - UE->UE_MRDC_Capability_size = ue_CapabilityRAT_ContainerList->list.array[i]->ue_CapabilityRAT_Container.size; - } - - if(ue_CapabilityRAT_ContainerList->list.array[i]->rat_Type == - NR_RAT_Type_eutra){ - //TODO - } - } - } - } - - - /* Configure SRB2 */ - NR_SRB_ToAddMod_t *SRB2_config = NULL; - NR_SRB_ToAddModList_t *SRB_configList = NULL; - uint8_t SRBs_before_new_addition = 0; - - if(req->srbs_to_be_setup_length>0){ - if (UE->SRB_configList == NULL) { - LOG_W(NR_RRC, "The SRB list of the UE context is empty before the addition of new SRB at the DU \n"); - UE->SRB_configList = CALLOC(1, sizeof(*UE->SRB_configList)); - } - SRB_configList = UE->SRB_configList; - SRBs_before_new_addition = SRB_configList->list.count; - for (int i=0; i<req->srbs_to_be_setup_length; i++){ - SRB2_config = CALLOC(1, sizeof(*SRB2_config)); - SRB2_config->srb_Identity = req->srbs_to_be_setup[i].srb_id; - asn1cSeqAdd(&SRB_configList->list, SRB2_config); - } - } - - /* Configure DRB */ - NR_DRB_ToAddMod_t *DRB_config = NULL; - NR_DRB_ToAddModList_t *DRB_configList = NULL; - uint8_t drb_id_to_setup_start = 0; - uint8_t nb_drb_to_setup = 0; - long drb_priority[NGAP_MAX_DRBS_PER_UE]; - if(req->drbs_to_be_setup_length>0){ - if (UE->DRB_configList == NULL) { - UE->DRB_configList = CALLOC(1, sizeof(*UE->DRB_configList)); - } - DRB_configList = UE->DRB_configList; - nb_drb_to_setup = req->drbs_to_be_setup_length; - for (int i=0; i<req->drbs_to_be_setup_length; i++){ - DRB_config = CALLOC(1, sizeof(*DRB_config)); - DRB_config->drb_Identity = req->drbs_to_be_setup[i].drb_id; - if (drb_id_to_setup_start == 0) drb_id_to_setup_start = DRB_config->drb_Identity; - asn1cSeqAdd(&DRB_configList->list, DRB_config); - f1ap_drb_to_be_setup_t drb_p = req->drbs_to_be_setup[i]; - transport_layer_addr_t addr; - memcpy(addr.buffer, &drb_p.up_ul_tnl[0].tl_address, sizeof(drb_p.up_ul_tnl[0].tl_address)); - addr.length=sizeof(drb_p.up_ul_tnl[0].tl_address)*8; - extern instance_t DUuniqInstance; - incoming_teid = newGtpuCreateTunnel(DUuniqInstance, - req->rnti, - drb_p.drb_id, - drb_p.drb_id, - drb_p.up_ul_tnl[0].teid, - -1, // no qfi - addr, - drb_p.up_ul_tnl[0].port, - DURecvCb, - NULL); - /* TODO: hardcoded to 13 for the time being, to be changed? */ - drb_priority[DRB_config->drb_Identity-1] = 13; - } - } - - NR_CellGroupConfig_t *cellGroupConfig = calloc(1, sizeof(NR_CellGroupConfig_t)); - if (req->srbs_to_be_setup_length > 0 || req->drbs_to_be_setup_length>0) - // FIXME: fill_mastercellGroupConfig() won't fill the right priorities or - // bearer IDs for the DRBs - fill_mastercellGroupConfig(cellGroupConfig, UE->masterCellGroup, rrc->um_on_default_drb, SRB2_config ? 1 : 0, drb_id_to_setup_start, nb_drb_to_setup, drb_priority); - protocol_ctxt_t ctxt = {.rntiMaybeUEid = req->rnti, .module_id = instance, .instance = instance, .enb_flag = 1, .eNB_index = instance}; - apply_macrlc_config(rrc, ue_context_p, &ctxt); - - if(req->rrc_container_length > 0){ - mem_block_t *pdcp_pdu_p = get_free_mem_block(req->rrc_container_length, __func__); - memcpy(&pdcp_pdu_p->data[0], req->rrc_container, req->rrc_container_length); - du_rlc_data_req(&ctxt, 1, 0x00, 1, 1, 0, req->rrc_container_length, pdcp_pdu_p); - LOG_I(F1AP, "Printing RRC Container of UE context setup request: \n"); - for (int j=0; j<req->rrc_container_length; j++){ - printf("%02x ", pdcp_pdu_p->data[j]); - } - printf("\n"); - } - - /* Fill the UE context setup response ITTI message to send to F1AP */ - resp->gNB_CU_ue_id = req->gNB_CU_ue_id; - resp->rnti = req->rnti; - if(DRB_configList){ - if(DRB_configList->list.count > 0){ - resp->drbs_to_be_setup = calloc(1,DRB_configList->list.count*sizeof(f1ap_drb_to_be_setup_t)); - resp->drbs_to_be_setup_length = DRB_configList->list.count; - for (int i=0; i<DRB_configList->list.count; i++){ - resp->drbs_to_be_setup[i].drb_id = DRB_configList->list.array[i]->drb_Identity; - resp->drbs_to_be_setup[i].rlc_mode = RLC_MODE_AM; - resp->drbs_to_be_setup[i].up_dl_tnl[0].teid = incoming_teid; - resp->drbs_to_be_setup[i].up_dl_tnl[0].tl_address = inet_addr(mac->eth_params_n.my_addr); - resp->drbs_to_be_setup[i].up_dl_tnl_length = 1; - } - } - else{ - LOG_W(NR_RRC, "No DRB added upon reception of F1 UE context setup request with a DRB to setup list\n"); - } - } - if(SRB_configList){ - if(SRB_configList->list.count >0 && SRBs_before_new_addition < SRB_configList->list.count){ - resp->srbs_to_be_setup = calloc(1,req->srbs_to_be_setup_length*sizeof(f1ap_srb_to_be_setup_t)); - resp->srbs_to_be_setup_length = req->srbs_to_be_setup_length; - for (int i=SRBs_before_new_addition; i<SRB_configList->list.count; i++){ - resp->srbs_to_be_setup[i-SRBs_before_new_addition].srb_id = SRB_configList->list.array[i]->srb_Identity; - } - } - else{ - LOG_W(NR_RRC, "No SRB added upon reception of F1 UE Context setup request at the DU\n"); - } - } - else{ - LOG_W(NR_RRC, "No SRB added upon reception of F1 UE Context setup request at the DU\n"); - } - /* fixme: - * Here we should be encoding the updates on cellgroupconfig based on the content of UE capabilities - */ - resp->du_to_cu_rrc_information = calloc(1, sizeof(du_to_cu_rrc_information_t)); - resp->du_to_cu_rrc_information->cellGroupConfig = calloc(1,1024); - asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, - NULL, - UE->masterCellGroup, //(void *)cellGroupConfig, - resp->du_to_cu_rrc_information->cellGroupConfig, - 1024); - if (enc_rval.encoded == -1) { - LOG_E(F1AP,"Could not encode ue_context.masterCellGroup, failed element %s\n",enc_rval.failed_type->name); - exit(-1); - } - resp->du_to_cu_rrc_information->cellGroupConfig_length = (enc_rval.encoded+7)>>3; - free(cellGroupConfig); - itti_send_msg_to_task(TASK_DU_F1, instance, message_p); -} - static void rrc_DU_process_ue_context_modification_request(MessageDef *msg_p, instance_t instance) { f1ap_ue_context_setup_t * req=&F1AP_UE_CONTEXT_MODIFICATION_REQ(msg_p); @@ -2899,54 +2612,29 @@ static void rrc_DU_process_ue_context_modification_request(MessageDef *msg_p, in static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance_t instance) { f1ap_ue_context_setup_t * resp=&F1AP_UE_CONTEXT_SETUP_RESP(msg_p); - protocol_ctxt_t ctxt = {.rntiMaybeUEid = resp->rnti, .module_id = instance, .instance = instance, .enb_flag = 1, .eNB_index = instance}; - gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id]; + gNB_RRC_INST *rrc = RC.nrrrc[instance]; rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(rrc, resp->rnti); gNB_RRC_UE_t *UE = &ue_context_p->ue_context; - NR_CellGroupConfig_t *cellGroupConfig = NULL; - - asn_dec_rval_t dec_rval = uper_decode_complete( NULL, - &asn_DEF_NR_CellGroupConfig, - (void **)&cellGroupConfig, - (uint8_t *)resp->du_to_cu_rrc_information->cellGroupConfig, - (int) resp->du_to_cu_rrc_information->cellGroupConfig_length); - if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - AssertFatal(1==0,"Cell group config decode error\n"); - // free the memory - SEQUENCE_free( &asn_DEF_NR_CellGroupConfig, cellGroupConfig, 1 ); - return; - } - //xer_fprint(stdout,&asn_DEF_NR_CellGroupConfig, cellGroupConfig); + NR_CellGroupConfig_t *cellGroupConfig = NULL; + asn_dec_rval_t dec_rval = uper_decode_complete(NULL, + &asn_DEF_NR_CellGroupConfig, + (void **)&cellGroupConfig, + (uint8_t *)resp->du_to_cu_rrc_information->cellGroupConfig, + resp->du_to_cu_rrc_information->cellGroupConfig_length); + AssertFatal(dec_rval.code == RC_OK && dec_rval.consumed > 0, "Cell group config decode error\n"); - if (UE->masterCellGroup == NULL) { - UE->masterCellGroup = calloc(1, sizeof(NR_CellGroupConfig_t)); - } - if(cellGroupConfig->rlc_BearerToAddModList!=NULL){ - if (UE->masterCellGroup->rlc_BearerToAddModList != NULL) { - int ue_ctxt_rlc_Bearers = UE->masterCellGroup->rlc_BearerToAddModList->list.count; - for(int i=ue_ctxt_rlc_Bearers; i<ue_ctxt_rlc_Bearers + cellGroupConfig->rlc_BearerToAddModList->list.count; i++){ - asn1cSeqAdd(&UE->masterCellGroup->rlc_BearerToAddModList->list, cellGroupConfig->rlc_BearerToAddModList->list.array[i - ue_ctxt_rlc_Bearers]); - } - } else { - LOG_W(NR_RRC, "Empty rlc_BearerToAddModList at ue_context of the CU before filling the updates from UE context setup response \n"); - UE->masterCellGroup->rlc_BearerToAddModList = calloc(1, sizeof(*cellGroupConfig->rlc_BearerToAddModList)); - memcpy(UE->masterCellGroup->rlc_BearerToAddModList, cellGroupConfig->rlc_BearerToAddModList, sizeof(*cellGroupConfig->rlc_BearerToAddModList)); - } + if (UE->masterCellGroup) { + ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->masterCellGroup); + LOG_I(RRC, "UE %04x replacing existing CellGroupConfig with new one received from DU\n", UE->rnti); } - if (LOG_DEBUGFLAG(DEBUG_ASN1)) { + UE->masterCellGroup = cellGroupConfig; + if (LOG_DEBUGFLAG(DEBUG_ASN1)) xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, UE->masterCellGroup); - } - if (UE->established_pdu_sessions_flag == 1) { - fill_DRB_configList(&ctxt, ue_context_p); - rrc_gNB_generate_dedicatedRRCReconfiguration(&ctxt, ue_context_p, cellGroupConfig); - } else { - rrc_gNB_generate_defaultRRCReconfiguration(&ctxt, ue_context_p); - } - - free(cellGroupConfig->rlc_BearerToAddModList); - free(cellGroupConfig); + /* at this point, we don't have to do anything: the UE context setup request + * includes the Security Command, whose response will trigger the following + * messages (UE capability, to be specific) */ } static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, instance_t instance) @@ -3508,10 +3196,6 @@ void *rrc_gnb_task(void *args_p) { AssertFatal(NODE_IS_CU(RC.nrrrc[instance]->node_type), "should not receive F1AP_SETUP_REQUEST, need call by CU!\n"); rrc_gNB_process_f1_setup_req(&F1AP_SETUP_REQ(msg_p)); break; - - case F1AP_UE_CONTEXT_SETUP_REQ: - rrc_DU_process_ue_context_setup_request(msg_p, instance); - break; case F1AP_UE_CONTEXT_SETUP_RESP: rrc_CU_process_ue_context_setup_response(msg_p, instance); @@ -3583,6 +3267,27 @@ void *rrc_gnb_task(void *args_p) { } } +static void rrc_deliver_ue_ctxt_setup_req(void *deliver_pdu_data, ue_id_t ue_id, int srb_id, char *buf, int size, int sdu_id) +{ + DevAssert(deliver_pdu_data != NULL); + gNB_RRC_INST *rrc = deliver_pdu_data; + f1ap_ue_context_setup_t ue_context_setup_req = { + .gNB_CU_ue_id = 0xffffffff, /* filled by F1 for the moment */ + .gNB_DU_ue_id = 0xffffffff, /* filled by F1 for the moment */ + .rnti = ue_id, + .mcc = rrc->configuration.mcc[0], + .mnc = rrc->configuration.mnc[0], + .mnc_digit_length = rrc->configuration.mnc_digit_length[0], + .nr_cellid = rrc->nr_cellid, + .servCellId = 0, /* TODO: correct value? */ + .srbs_to_be_setup = 0, /* no new SRBs */ + .drbs_to_be_setup = 0, /* no new DRBs */ + .rrc_container = (uint8_t*) buf, /* security mode command */ + .rrc_container_length = size, + }; + rrc->mac_rrc.ue_context_setup_request(&ue_context_setup_req); +} + //----------------------------------------------------------------------------- void rrc_gNB_generate_SecurityModeCommand( @@ -3604,7 +3309,8 @@ rrc_gNB_generate_SecurityModeCommand( gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; AssertFatal(!NODE_IS_DU(rrc->node_type), "illegal node type DU!\n"); - nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, deliver_pdu_srb_f1, rrc); + /* the callback will fill the UE context setup request and forward it */ + nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, rrc_deliver_ue_ctxt_setup_req, rrc); } void diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index bf69aa703b69c3afee51c12a2d60dd5172685c2c..250402a2cfa3ce97c0ee3db982dd05c3c8673a8b 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -401,8 +401,11 @@ void rrc_remove_nsa_user(gNB_RRC_INST *rrc, int rnti) { rrc_rlc_remove_ue(&ctxt); - // WHAT A RACE CONDITION + // lock the scheduler before removing the UE. Note: mac_remove_nr_ue() checks + // that the scheduler is actually locked! + NR_SCHED_LOCK(&RC.nrmac[rrc->module_id]->sched_lock); mac_remove_nr_ue(RC.nrmac[rrc->module_id], rnti); + NR_SCHED_UNLOCK(&RC.nrmac[rrc->module_id]->sched_lock); gtpv1u_enb_delete_tunnel_req_t tmp={0}; tmp.rnti=rnti; tmp.from_gnb=1;