mirror of https://github.com/PentHertz/srsLTE.git
Merge branch 'next' into agpl_next
# Conflicts: # lib/include/srsran/common/basic_pnf.h # lib/include/srsran/common/basic_vnf.h # lib/include/srsran/common/basic_vnf_api.h # lib/src/common/basic_vnf.cc # lib/test/common/pnf_bridge.cc # lib/test/common/pnf_dummy.cc # srsenb/hdr/phy/vnf_phy_nr.h # srsenb/hdr/stack/mac/nr/sched_nr_common.h # srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h # srsenb/src/phy/vnf_phy_nr.cc # srsenb/src/stack/mac/nr/sched_nr_common.cc # srsenb/src/stack/mac/nr/sched_nr_phy_helpers.cc # srsue/hdr/phy/vnf_phy_nr.h # srsue/src/phy/vnf_phy_nr.cc
This commit is contained in:
commit
ccf8cfb65f
|
@ -24,4 +24,4 @@ set(CTEST_DROP_METHOD "http")
|
|||
set(CTEST_DROP_SITE "my.cdash.org")
|
||||
set(CTEST_DROP_LOCATION "/submit.php?project=srsRAN")
|
||||
set(CTEST_DROP_SITE_CDASH TRUE)
|
||||
set(VALGRIND_COMMAND_OPTIONS "--error-exitcode=1 --trace-children=yes --leak-check=full --show-reachable=yes --vex-guest-max-insns=25")
|
||||
set(VALGRIND_COMMAND_OPTIONS "--error-exitcode=1 --trace-children=yes --leak-check=full --show-leak-kinds=all --track-origins=yes --show-reachable=yes --vex-guest-max-insns=25")
|
||||
|
|
|
@ -105,7 +105,7 @@ install_file "ue.conf.example"
|
|||
install_file "enb.conf.example"
|
||||
install_file "sib.conf.example"
|
||||
install_file "rr.conf.example"
|
||||
install_file "drb.conf.example"
|
||||
install_file "rb.conf.example"
|
||||
install_file "epc.conf.example"
|
||||
install_file "mbms.conf.example"
|
||||
install_file "user_db.csv.example"
|
||||
|
|
|
@ -2127,265 +2127,353 @@ public:
|
|||
registration_request_t& set_registration_request()
|
||||
{
|
||||
set(msg_types::options::registration_request);
|
||||
msg_container = srslog::detail::any{registration_request_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
msg_container = srslog::detail::any{registration_request_t()};
|
||||
return *srslog::detail::any_cast<registration_request_t>(&msg_container);
|
||||
}
|
||||
registration_accept_t& set_registration_accept()
|
||||
{
|
||||
set(msg_types::options::registration_accept);
|
||||
msg_container = srslog::detail::any{registration_accept_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
msg_container = srslog::detail::any{registration_accept_t()};
|
||||
return *srslog::detail::any_cast<registration_accept_t>(&msg_container);
|
||||
}
|
||||
registration_complete_t& set_registration_complete()
|
||||
{
|
||||
set(msg_types::options::registration_complete);
|
||||
msg_container = srslog::detail::any{registration_complete_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
msg_container = srslog::detail::any{registration_complete_t()};
|
||||
return *srslog::detail::any_cast<registration_complete_t>(&msg_container);
|
||||
}
|
||||
registration_reject_t& set_registration_reject()
|
||||
{
|
||||
set(msg_types::options::registration_reject);
|
||||
msg_container = srslog::detail::any{registration_reject_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
msg_container = srslog::detail::any{registration_reject_t()};
|
||||
return *srslog::detail::any_cast<registration_reject_t>(&msg_container);
|
||||
}
|
||||
deregistration_request_ue_originating_t& set_deregistration_request_ue_originating()
|
||||
{
|
||||
set(msg_types::options::deregistration_request_ue_originating);
|
||||
msg_container = srslog::detail::any{deregistration_request_ue_originating_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
msg_container = srslog::detail::any{deregistration_request_ue_originating_t()};
|
||||
return *srslog::detail::any_cast<deregistration_request_ue_originating_t>(&msg_container);
|
||||
}
|
||||
deregistration_accept_ue_originating_t& set_deregistration_accept_ue_originating()
|
||||
{
|
||||
set(msg_types::options::deregistration_accept_ue_originating);
|
||||
msg_container = srslog::detail::any{deregistration_accept_ue_originating_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
msg_container = srslog::detail::any{deregistration_accept_ue_originating_t()};
|
||||
return *srslog::detail::any_cast<deregistration_accept_ue_originating_t>(&msg_container);
|
||||
}
|
||||
deregistration_request_ue_terminated_t& set_deregistration_request_ue_terminated()
|
||||
{
|
||||
set(msg_types::options::deregistration_request_ue_terminated);
|
||||
msg_container = srslog::detail::any{deregistration_request_ue_terminated_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
msg_container = srslog::detail::any{deregistration_request_ue_terminated_t()};
|
||||
return *srslog::detail::any_cast<deregistration_request_ue_terminated_t>(&msg_container);
|
||||
}
|
||||
deregistration_accept_ue_terminated_t& set_deregistration_accept_ue_terminated()
|
||||
{
|
||||
set(msg_types::options::deregistration_accept_ue_terminated);
|
||||
msg_container = srslog::detail::any{deregistration_accept_ue_terminated_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
msg_container = srslog::detail::any{deregistration_accept_ue_terminated_t()};
|
||||
return *srslog::detail::any_cast<deregistration_accept_ue_terminated_t>(&msg_container);
|
||||
}
|
||||
service_request_t& set_service_request()
|
||||
{
|
||||
set(msg_types::options::service_request);
|
||||
msg_container = srslog::detail::any{service_request_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
msg_container = srslog::detail::any{service_request_t()};
|
||||
return *srslog::detail::any_cast<service_request_t>(&msg_container);
|
||||
}
|
||||
service_reject_t& set_service_reject()
|
||||
{
|
||||
set(msg_types::options::service_reject);
|
||||
msg_container = srslog::detail::any{service_reject_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
msg_container = srslog::detail::any{service_reject_t()};
|
||||
return *srslog::detail::any_cast<service_reject_t>(&msg_container);
|
||||
}
|
||||
service_accept_t& set_service_accept()
|
||||
{
|
||||
set(msg_types::options::service_accept);
|
||||
msg_container = srslog::detail::any{service_accept_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
msg_container = srslog::detail::any{service_accept_t()};
|
||||
return *srslog::detail::any_cast<service_accept_t>(&msg_container);
|
||||
}
|
||||
configuration_update_command_t& set_configuration_update_command()
|
||||
{
|
||||
set(msg_types::options::configuration_update_command);
|
||||
msg_container = srslog::detail::any{configuration_update_command_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
msg_container = srslog::detail::any{configuration_update_command_t()};
|
||||
return *srslog::detail::any_cast<configuration_update_command_t>(&msg_container);
|
||||
}
|
||||
configuration_update_complete_t& set_configuration_update_complete()
|
||||
{
|
||||
set(msg_types::options::configuration_update_complete);
|
||||
msg_container = srslog::detail::any{configuration_update_complete_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
msg_container = srslog::detail::any{configuration_update_complete_t()};
|
||||
return *srslog::detail::any_cast<configuration_update_complete_t>(&msg_container);
|
||||
}
|
||||
authentication_request_t& set_authentication_request()
|
||||
{
|
||||
set(msg_types::options::authentication_request);
|
||||
msg_container = srslog::detail::any{authentication_request_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
msg_container = srslog::detail::any{authentication_request_t()};
|
||||
return *srslog::detail::any_cast<authentication_request_t>(&msg_container);
|
||||
}
|
||||
authentication_response_t& set_authentication_response()
|
||||
{
|
||||
set(msg_types::options::authentication_response);
|
||||
msg_container = srslog::detail::any{authentication_response_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
msg_container = srslog::detail::any{authentication_response_t()};
|
||||
return *srslog::detail::any_cast<authentication_response_t>(&msg_container);
|
||||
}
|
||||
authentication_reject_t& set_authentication_reject()
|
||||
{
|
||||
set(msg_types::options::authentication_reject);
|
||||
msg_container = srslog::detail::any{authentication_reject_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
msg_container = srslog::detail::any{authentication_reject_t()};
|
||||
return *srslog::detail::any_cast<authentication_reject_t>(&msg_container);
|
||||
}
|
||||
authentication_failure_t& set_authentication_failure()
|
||||
{
|
||||
set(msg_types::options::authentication_failure);
|
||||
msg_container = srslog::detail::any{authentication_failure_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
msg_container = srslog::detail::any{authentication_failure_t()};
|
||||
return *srslog::detail::any_cast<authentication_failure_t>(&msg_container);
|
||||
}
|
||||
authentication_result_t& set_authentication_result()
|
||||
{
|
||||
set(msg_types::options::authentication_result);
|
||||
msg_container = srslog::detail::any{authentication_result_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
msg_container = srslog::detail::any{authentication_result_t()};
|
||||
return *srslog::detail::any_cast<authentication_result_t>(&msg_container);
|
||||
}
|
||||
identity_request_t& set_identity_request()
|
||||
{
|
||||
set(msg_types::options::identity_request);
|
||||
msg_container = srslog::detail::any{identity_request_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
msg_container = srslog::detail::any{identity_request_t()};
|
||||
return *srslog::detail::any_cast<identity_request_t>(&msg_container);
|
||||
}
|
||||
identity_response_t& set_identity_response()
|
||||
{
|
||||
set(msg_types::options::identity_response);
|
||||
msg_container = srslog::detail::any{identity_response_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
msg_container = srslog::detail::any{identity_response_t()};
|
||||
return *srslog::detail::any_cast<identity_response_t>(&msg_container);
|
||||
}
|
||||
security_mode_command_t& set_security_mode_command()
|
||||
{
|
||||
set(msg_types::options::security_mode_command);
|
||||
msg_container = srslog::detail::any{security_mode_command_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
msg_container = srslog::detail::any{security_mode_command_t()};
|
||||
return *srslog::detail::any_cast<security_mode_command_t>(&msg_container);
|
||||
}
|
||||
security_mode_complete_t& set_security_mode_complete()
|
||||
{
|
||||
set(msg_types::options::security_mode_complete);
|
||||
msg_container = srslog::detail::any{security_mode_complete_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
msg_container = srslog::detail::any{security_mode_complete_t()};
|
||||
return *srslog::detail::any_cast<security_mode_complete_t>(&msg_container);
|
||||
}
|
||||
security_mode_reject_t& set_security_mode_reject()
|
||||
{
|
||||
set(msg_types::options::security_mode_reject);
|
||||
msg_container = srslog::detail::any{security_mode_reject_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
msg_container = srslog::detail::any{security_mode_reject_t()};
|
||||
return *srslog::detail::any_cast<security_mode_reject_t>(&msg_container);
|
||||
}
|
||||
status_5gmm_t& set_status_5gmm()
|
||||
{
|
||||
set(msg_types::options::status_5gmm);
|
||||
msg_container = srslog::detail::any{status_5gmm_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
msg_container = srslog::detail::any{status_5gmm_t()};
|
||||
return *srslog::detail::any_cast<status_5gmm_t>(&msg_container);
|
||||
}
|
||||
notification_t& set_notification()
|
||||
{
|
||||
set(msg_types::options::notification);
|
||||
msg_container = srslog::detail::any{notification_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
msg_container = srslog::detail::any{notification_t()};
|
||||
return *srslog::detail::any_cast<notification_t>(&msg_container);
|
||||
}
|
||||
notification_response_t& set_notification_response()
|
||||
{
|
||||
set(msg_types::options::notification_response);
|
||||
msg_container = srslog::detail::any{notification_response_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
msg_container = srslog::detail::any{notification_response_t()};
|
||||
return *srslog::detail::any_cast<notification_response_t>(&msg_container);
|
||||
}
|
||||
ul_nas_transport_t& set_ul_nas_transport()
|
||||
{
|
||||
set(msg_types::options::ul_nas_transport);
|
||||
msg_container = srslog::detail::any{ul_nas_transport_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
msg_container = srslog::detail::any{ul_nas_transport_t()};
|
||||
return *srslog::detail::any_cast<ul_nas_transport_t>(&msg_container);
|
||||
}
|
||||
dl_nas_transport_t& set_dl_nas_transport()
|
||||
{
|
||||
set(msg_types::options::dl_nas_transport);
|
||||
msg_container = srslog::detail::any{dl_nas_transport_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gmm;
|
||||
msg_container = srslog::detail::any{dl_nas_transport_t()};
|
||||
return *srslog::detail::any_cast<dl_nas_transport_t>(&msg_container);
|
||||
}
|
||||
pdu_session_establishment_request_t& set_pdu_session_establishment_request()
|
||||
{
|
||||
set(msg_types::options::pdu_session_establishment_request);
|
||||
msg_container = srslog::detail::any{pdu_session_establishment_request_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
msg_container = srslog::detail::any{pdu_session_establishment_request_t()};
|
||||
return *srslog::detail::any_cast<pdu_session_establishment_request_t>(&msg_container);
|
||||
}
|
||||
pdu_session_establishment_accept_t& set_pdu_session_establishment_accept()
|
||||
{
|
||||
set(msg_types::options::pdu_session_establishment_accept);
|
||||
msg_container = srslog::detail::any{pdu_session_establishment_accept_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
msg_container = srslog::detail::any{pdu_session_establishment_accept_t()};
|
||||
return *srslog::detail::any_cast<pdu_session_establishment_accept_t>(&msg_container);
|
||||
}
|
||||
pdu_session_establishment_reject_t& set_pdu_session_establishment_reject()
|
||||
{
|
||||
set(msg_types::options::pdu_session_establishment_reject);
|
||||
msg_container = srslog::detail::any{pdu_session_establishment_reject_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
msg_container = srslog::detail::any{pdu_session_establishment_reject_t()};
|
||||
return *srslog::detail::any_cast<pdu_session_establishment_reject_t>(&msg_container);
|
||||
}
|
||||
pdu_session_authentication_command_t& set_pdu_session_authentication_command()
|
||||
{
|
||||
set(msg_types::options::pdu_session_authentication_command);
|
||||
msg_container = srslog::detail::any{pdu_session_authentication_command_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
msg_container = srslog::detail::any{pdu_session_authentication_command_t()};
|
||||
return *srslog::detail::any_cast<pdu_session_authentication_command_t>(&msg_container);
|
||||
}
|
||||
pdu_session_authentication_complete_t& set_pdu_session_authentication_complete()
|
||||
{
|
||||
set(msg_types::options::pdu_session_authentication_complete);
|
||||
msg_container = srslog::detail::any{pdu_session_authentication_complete_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
msg_container = srslog::detail::any{pdu_session_authentication_complete_t()};
|
||||
return *srslog::detail::any_cast<pdu_session_authentication_complete_t>(&msg_container);
|
||||
}
|
||||
pdu_session_authentication_result_t& set_pdu_session_authentication_result()
|
||||
{
|
||||
set(msg_types::options::pdu_session_authentication_result);
|
||||
msg_container = srslog::detail::any{pdu_session_authentication_result_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
msg_container = srslog::detail::any{pdu_session_authentication_result_t()};
|
||||
return *srslog::detail::any_cast<pdu_session_authentication_result_t>(&msg_container);
|
||||
}
|
||||
pdu_session_modification_request_t& set_pdu_session_modification_request()
|
||||
{
|
||||
set(msg_types::options::pdu_session_modification_request);
|
||||
msg_container = srslog::detail::any{pdu_session_modification_request_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
msg_container = srslog::detail::any{pdu_session_modification_request_t()};
|
||||
return *srslog::detail::any_cast<pdu_session_modification_request_t>(&msg_container);
|
||||
}
|
||||
pdu_session_modification_reject_t& set_pdu_session_modification_reject()
|
||||
{
|
||||
set(msg_types::options::pdu_session_modification_reject);
|
||||
msg_container = srslog::detail::any{pdu_session_modification_reject_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
msg_container = srslog::detail::any{pdu_session_modification_reject_t()};
|
||||
return *srslog::detail::any_cast<pdu_session_modification_reject_t>(&msg_container);
|
||||
}
|
||||
pdu_session_modification_command_t& set_pdu_session_modification_command()
|
||||
{
|
||||
set(msg_types::options::pdu_session_modification_command);
|
||||
msg_container = srslog::detail::any{pdu_session_modification_command_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
msg_container = srslog::detail::any{pdu_session_modification_command_t()};
|
||||
return *srslog::detail::any_cast<pdu_session_modification_command_t>(&msg_container);
|
||||
}
|
||||
pdu_session_modification_complete_t& set_pdu_session_modification_complete()
|
||||
{
|
||||
set(msg_types::options::pdu_session_modification_complete);
|
||||
msg_container = srslog::detail::any{pdu_session_modification_complete_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
msg_container = srslog::detail::any{pdu_session_modification_complete_t()};
|
||||
return *srslog::detail::any_cast<pdu_session_modification_complete_t>(&msg_container);
|
||||
}
|
||||
pdu_session_modification_command_reject_t& set_pdu_session_modification_command_reject()
|
||||
{
|
||||
set(msg_types::options::pdu_session_modification_command_reject);
|
||||
msg_container = srslog::detail::any{pdu_session_modification_command_reject_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
msg_container = srslog::detail::any{pdu_session_modification_command_reject_t()};
|
||||
return *srslog::detail::any_cast<pdu_session_modification_command_reject_t>(&msg_container);
|
||||
}
|
||||
pdu_session_release_request_t& set_pdu_session_release_request()
|
||||
{
|
||||
set(msg_types::options::pdu_session_release_request);
|
||||
msg_container = srslog::detail::any{pdu_session_release_request_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
msg_container = srslog::detail::any{pdu_session_release_request_t()};
|
||||
return *srslog::detail::any_cast<pdu_session_release_request_t>(&msg_container);
|
||||
}
|
||||
pdu_session_release_reject_t& set_pdu_session_release_reject()
|
||||
{
|
||||
set(msg_types::options::pdu_session_release_reject);
|
||||
msg_container = srslog::detail::any{pdu_session_release_reject_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
msg_container = srslog::detail::any{pdu_session_release_reject_t()};
|
||||
return *srslog::detail::any_cast<pdu_session_release_reject_t>(&msg_container);
|
||||
}
|
||||
pdu_session_release_command_t& set_pdu_session_release_command()
|
||||
{
|
||||
set(msg_types::options::pdu_session_release_command);
|
||||
msg_container = srslog::detail::any{pdu_session_release_command_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
msg_container = srslog::detail::any{pdu_session_release_command_t()};
|
||||
return *srslog::detail::any_cast<pdu_session_release_command_t>(&msg_container);
|
||||
}
|
||||
pdu_session_release_complete_t& set_pdu_session_release_complete()
|
||||
{
|
||||
set(msg_types::options::pdu_session_release_complete);
|
||||
msg_container = srslog::detail::any{pdu_session_release_complete_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
msg_container = srslog::detail::any{pdu_session_release_complete_t()};
|
||||
return *srslog::detail::any_cast<pdu_session_release_complete_t>(&msg_container);
|
||||
}
|
||||
status_5gsm_t& set_status_5gsm()
|
||||
{
|
||||
set(msg_types::options::status_5gsm);
|
||||
msg_container = srslog::detail::any{status_5gsm_t()};
|
||||
hdr.extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
hdr.inner_extended_protocol_discriminator = nas_5gs_hdr::extended_protocol_discriminator_5gsm;
|
||||
msg_container = srslog::detail::any{status_5gsm_t()};
|
||||
return *srslog::detail::any_cast<status_5gsm_t>(&msg_container);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,558 +0,0 @@
|
|||
/**
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* This file is part of srsRAN.
|
||||
*
|
||||
* srsRAN is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* srsRAN is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* A copy of the GNU Affero General Public License can be found in
|
||||
* the LICENSE file in the top-level directory of this distribution
|
||||
* and at http://www.gnu.org/licenses/.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSRAN_BASIC_PNF_H
|
||||
#define SRSRAN_BASIC_PNF_H
|
||||
|
||||
#include "basic_vnf_api.h"
|
||||
#include "common.h"
|
||||
#include "srsran/adt/choice_type.h"
|
||||
#include "srsran/common/block_queue.h"
|
||||
#include "srsran/common/buffer_pool.h"
|
||||
#include "srsran/srslog/srslog.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <atomic>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <netinet/in.h>
|
||||
#include <poll.h>
|
||||
#include <random>
|
||||
#include <strings.h>
|
||||
#include <sys/socket.h>
|
||||
#include <thread>
|
||||
#include <unistd.h>
|
||||
|
||||
#define RAND_SEED (12384)
|
||||
#define RX_TIMEOUT_MS (500)
|
||||
|
||||
#define MIN_TB_LEN (100) // MAX_TB_LEN defined in api.h
|
||||
|
||||
#define PING_REQUEST_PDU 1
|
||||
|
||||
namespace srsran {
|
||||
|
||||
struct pnf_metrics_t {
|
||||
uint32_t avg_rtt_us;
|
||||
uint32_t num_timing_errors;
|
||||
uint32_t num_pdus;
|
||||
uint32_t tb_size;
|
||||
};
|
||||
|
||||
class srsran_basic_pnf
|
||||
{
|
||||
using msg_header_t = basic_vnf_api::msg_header_t;
|
||||
const static size_t buffer_size =
|
||||
srsran::static_max<sizeof(basic_vnf_api::dl_conf_msg_t), sizeof(basic_vnf_api::tx_request_msg_t)>::value;
|
||||
using msg_buffer_t = std::array<uint8_t, buffer_size>;
|
||||
|
||||
public:
|
||||
srsran_basic_pnf(const std::string& type_,
|
||||
const std::string& vnf_p5_addr,
|
||||
const uint16_t& vnf_p5_port,
|
||||
const uint32_t& sf_interval,
|
||||
const int32_t& num_sf_,
|
||||
const uint32_t& tb_len_) :
|
||||
running(false),
|
||||
type(type_),
|
||||
tti(100), ///< Random start TTI
|
||||
vnf_addr(vnf_p5_addr),
|
||||
vnf_port(vnf_p5_port),
|
||||
sf_interval_us(sf_interval),
|
||||
num_sf(num_sf_),
|
||||
tb_len(tb_len_),
|
||||
rand_gen(RAND_SEED),
|
||||
rand_dist(MIN_TB_LEN, MAX_TB_LEN)
|
||||
{
|
||||
logger.set_level(srslog::basic_levels::warning);
|
||||
logger.set_hex_dump_max_size(-1);
|
||||
}
|
||||
|
||||
~srsran_basic_pnf() { stop(); };
|
||||
|
||||
bool start()
|
||||
{
|
||||
// create socket
|
||||
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sockfd < 0) {
|
||||
perror("socket");
|
||||
return false;
|
||||
}
|
||||
|
||||
int enable = 1;
|
||||
#if defined(SO_REUSEADDR)
|
||||
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0) {
|
||||
perror("setsockopt(SO_REUSEADDR) failed");
|
||||
}
|
||||
#endif
|
||||
#if defined(SO_REUSEPORT)
|
||||
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(int)) < 0) {
|
||||
perror("setsockopt(SO_REUSEPORT) failed");
|
||||
}
|
||||
#endif
|
||||
|
||||
bzero(&servaddr, sizeof(servaddr));
|
||||
servaddr.sin_family = AF_INET;
|
||||
servaddr.sin_addr.s_addr = inet_addr(vnf_addr.c_str());
|
||||
servaddr.sin_port = htons(vnf_port);
|
||||
|
||||
// start main thread
|
||||
running = true;
|
||||
|
||||
if (type == "gnb") {
|
||||
rx_thread = std::unique_ptr<std::thread>(new std::thread(&srsran_basic_pnf::dl_handler_thread, this));
|
||||
tx_thread = std::unique_ptr<std::thread>(new std::thread(&srsran_basic_pnf::ul_handler_thread, this));
|
||||
} else {
|
||||
tx_thread = std::unique_ptr<std::thread>(new std::thread(&srsran_basic_pnf::ue_dl_handler_thread, this));
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
bool stop()
|
||||
{
|
||||
running = false;
|
||||
|
||||
if (rx_thread) {
|
||||
if (rx_thread->joinable()) {
|
||||
rx_thread->join();
|
||||
}
|
||||
}
|
||||
|
||||
if (tx_thread) {
|
||||
if (tx_thread->joinable()) {
|
||||
tx_thread->join();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
pnf_metrics_t get_metrics()
|
||||
{
|
||||
pnf_metrics_t tmp = metrics;
|
||||
metrics = {};
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void connect_out_rf_queue(srsran::block_queue<srsran::unique_byte_buffer_t>* rf_queue_)
|
||||
{
|
||||
rf_out_queue = rf_queue_;
|
||||
policy = bridge;
|
||||
}
|
||||
srsran::block_queue<srsran::unique_byte_buffer_t>* get_in_rf_queue()
|
||||
{
|
||||
policy = bridge;
|
||||
return &rf_in_queue;
|
||||
}
|
||||
|
||||
private:
|
||||
//! Waits for DL Config or Tx Request Msg from VNF and forwards to RF
|
||||
void dl_handler_thread()
|
||||
{
|
||||
pthread_setname_np(pthread_self(), rx_thread_name.c_str());
|
||||
|
||||
// set_rt_prio();
|
||||
|
||||
struct pollfd fd;
|
||||
fd.fd = sockfd;
|
||||
fd.events = POLLIN;
|
||||
|
||||
std::unique_ptr<msg_buffer_t> rx_buffer{new msg_buffer_t{}};
|
||||
|
||||
while (running) {
|
||||
// receive response
|
||||
int ret = poll(&fd, 1, RX_TIMEOUT_MS);
|
||||
switch (ret) {
|
||||
case -1:
|
||||
printf("Error occurred.\n");
|
||||
running = false;
|
||||
break;
|
||||
case 0:
|
||||
// Timeout
|
||||
printf("Error: Didn't receive response after %dms\n", RX_TIMEOUT_MS);
|
||||
break;
|
||||
default:
|
||||
int recv_ret = recv(sockfd, rx_buffer->data(), sizeof(*rx_buffer), 0);
|
||||
handle_msg(rx_buffer->data(), recv_ret);
|
||||
break;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
auto rtt =
|
||||
std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now() - tti_start_time)
|
||||
.count();
|
||||
|
||||
// TODO: add averaging
|
||||
metrics.avg_rtt_us = rtt;
|
||||
}
|
||||
};
|
||||
|
||||
void ul_handler_thread()
|
||||
{
|
||||
pthread_setname_np(pthread_self(), tx_thread_name.c_str());
|
||||
|
||||
// set_rt_prio();
|
||||
|
||||
struct pollfd fd;
|
||||
fd.fd = sockfd;
|
||||
fd.events = POLLIN;
|
||||
|
||||
const uint32_t max_basic_api_pdu = sizeof(basic_vnf_api::dl_conf_msg_t) + 32; // larger than biggest message
|
||||
std::unique_ptr<std::array<uint8_t, max_basic_api_pdu> > rx_buffer =
|
||||
std::unique_ptr<std::array<uint8_t, max_basic_api_pdu> >(new std::array<uint8_t, max_basic_api_pdu>);
|
||||
|
||||
int32_t sf_counter = 0;
|
||||
while (running && (num_sf > 0 ? sf_counter < num_sf : true)) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
|
||||
// Increase TTI
|
||||
tti = (tti + 1) % 10240;
|
||||
|
||||
// Take time before sending the SF indication
|
||||
tti_start_time = std::chrono::steady_clock::now();
|
||||
|
||||
// Send request
|
||||
send_sf_ind(tti);
|
||||
|
||||
if (policy == bridge) {
|
||||
// send_rx_data_ind(tti);
|
||||
} else {
|
||||
// provide UL data every 2nd TTI
|
||||
if (tti % 2 == 0) {
|
||||
send_rx_data_ind(tti);
|
||||
}
|
||||
}
|
||||
|
||||
sf_counter++;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(sf_interval_us));
|
||||
}
|
||||
|
||||
printf("Leaving Tx thread after %d subframes\n", sf_counter);
|
||||
};
|
||||
|
||||
void ue_dl_handler_thread()
|
||||
{
|
||||
pthread_setname_np(pthread_self(), tx_thread_name.c_str());
|
||||
|
||||
// set_rt_prio();
|
||||
|
||||
struct pollfd fd;
|
||||
fd.fd = sockfd;
|
||||
fd.events = POLLIN;
|
||||
|
||||
const uint32_t max_basic_api_pdu = sizeof(basic_vnf_api::dl_conf_msg_t) + 32; // larger than biggest message
|
||||
std::unique_ptr<std::array<uint8_t, max_basic_api_pdu> > rx_buffer =
|
||||
std::unique_ptr<std::array<uint8_t, max_basic_api_pdu> >(new std::array<uint8_t, max_basic_api_pdu>);
|
||||
|
||||
int32_t sf_counter = 0;
|
||||
while (running && (num_sf > 0 ? sf_counter < num_sf : true)) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
|
||||
// Increase TTI
|
||||
tti = (tti + 1) % 10240;
|
||||
|
||||
// Take time before sending the SF indication
|
||||
tti_start_time = std::chrono::steady_clock::now();
|
||||
|
||||
// Send SF indication
|
||||
send_sf_ind(tti);
|
||||
|
||||
if (policy == bridge) {
|
||||
srsran::unique_byte_buffer_t tb;
|
||||
if (rf_in_queue.try_pop(&tb)) {
|
||||
send_dl_ind(tti, std::move(tb));
|
||||
}
|
||||
} else {
|
||||
// provide DL grant every even TTI, and UL grant every odd
|
||||
if (tti % 2 == 0) {
|
||||
send_dl_ind(tti);
|
||||
} else {
|
||||
send_ul_ind(tti);
|
||||
}
|
||||
}
|
||||
|
||||
sf_counter++;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(sf_interval_us));
|
||||
}
|
||||
|
||||
printf("Leaving Tx thread after %d subframes\n", sf_counter);
|
||||
};
|
||||
|
||||
void send_sf_ind(uint32_t tti_)
|
||||
{
|
||||
basic_vnf_api::sf_ind_msg_t sf_ind;
|
||||
bzero(&sf_ind, sizeof(sf_ind));
|
||||
sf_ind.header.type = basic_vnf_api::SF_IND;
|
||||
sf_ind.header.msg_len = sizeof(sf_ind) - sizeof(basic_vnf_api::msg_header_t);
|
||||
sf_ind.tti = tti_;
|
||||
sf_ind.t1 = 0;
|
||||
sf_ind.tb_len = tb_len > 0 ? tb_len : rand_dist(rand_gen);
|
||||
|
||||
int n = 0;
|
||||
if ((n = sendto(sockfd, &sf_ind, sizeof(sf_ind), 0, (struct sockaddr*)&servaddr, sizeof(servaddr))) < 0) {
|
||||
printf("sendto failed, ret=%d\n", n);
|
||||
}
|
||||
}
|
||||
|
||||
int handle_msg(const uint8_t* buffer, const uint32_t len)
|
||||
{
|
||||
basic_vnf_api::msg_header_t* header = (basic_vnf_api::msg_header_t*)buffer;
|
||||
|
||||
logger.debug("Received %s (%d B) in TTI", basic_vnf_api::msg_type_text[header->type], len);
|
||||
|
||||
switch (header->type) {
|
||||
case basic_vnf_api::SF_IND:
|
||||
printf("Error: %s not handled by VNF\n", basic_vnf_api::msg_type_text[header->type]);
|
||||
break;
|
||||
case basic_vnf_api::DL_CONFIG:
|
||||
handle_dl_config((basic_vnf_api::dl_conf_msg_t*)header);
|
||||
break;
|
||||
case basic_vnf_api::TX_REQUEST:
|
||||
handle_tx_request((basic_vnf_api::tx_request_msg_t*)header);
|
||||
break;
|
||||
default:
|
||||
printf("Unknown msg type.\n");
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int handle_dl_config(basic_vnf_api::dl_conf_msg_t* msg)
|
||||
{
|
||||
// printf("Received DL config for TTI=%d\n", msg->tti);
|
||||
|
||||
if (msg->tti != tti) {
|
||||
metrics.num_timing_errors++;
|
||||
// printf("Received DL config for TTI=%d but current TTI is %d\n", msg->tti, tti.load());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int handle_tx_request(basic_vnf_api::tx_request_msg_t* msg)
|
||||
{
|
||||
if (msg->tti != tti) {
|
||||
metrics.num_timing_errors++;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < msg->nof_pdus; ++i) {
|
||||
metrics.tb_size += msg->pdus[i].length;
|
||||
}
|
||||
|
||||
metrics.num_pdus += msg->nof_pdus;
|
||||
|
||||
if (rf_out_queue != nullptr) {
|
||||
uint32_t len = sizeof(*msg) - sizeof(msg->pdus->data) + msg->pdus->length;
|
||||
|
||||
srsran::unique_byte_buffer_t tx = srsran::make_byte_buffer();
|
||||
if (tx == nullptr) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(tx->msg, msg, len);
|
||||
rf_out_queue->push(std::move(tx));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void send_rx_data_ind(const uint32_t tti_)
|
||||
{
|
||||
// MAC PDU for UL-SCH with IPv6 router solicitation
|
||||
static uint8_t tv[] = {0x04, 0x38, 0x00, 0x80, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x08, 0x3a, 0xff, 0xfe,
|
||||
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x44, 0x4b, 0x0f, 0x2c, 0x33, 0x98, 0xf2,
|
||||
0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x02, 0x85, 0x00, 0x4b, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x7f, 0x00, 0x00, 0x3f, 0x00};
|
||||
|
||||
basic_vnf_api::rx_data_ind_msg_t rx_ind = {};
|
||||
|
||||
rx_ind.header.type = basic_vnf_api::RX_DATA_IND;
|
||||
rx_ind.header.msg_len = sizeof(rx_ind) - sizeof(basic_vnf_api::msg_header_t);
|
||||
rx_ind.sfn = tti_;
|
||||
rx_ind.t1 = 0;
|
||||
|
||||
rx_ind.nof_pdus = 1;
|
||||
rx_ind.pdus[0].type = basic_vnf_api::PUSCH;
|
||||
rx_ind.pdus[0].length = tb_len > 0 ? tb_len : rand_dist(rand_gen);
|
||||
|
||||
if (rx_ind.pdus[0].length >= sizeof(tv)) {
|
||||
// copy TV
|
||||
memcpy(rx_ind.pdus[0].data, tv, sizeof(tv));
|
||||
// set remaining bytes to zero
|
||||
memset(rx_ind.pdus[0].data + sizeof(tv), 0xaa, rx_ind.pdus[0].length - sizeof(tv));
|
||||
} else {
|
||||
// just fill with dummy bytes
|
||||
memset(rx_ind.pdus[0].data, 0xab, rx_ind.pdus[0].length);
|
||||
}
|
||||
|
||||
int n = 0;
|
||||
if ((n = sendto(sockfd, &rx_ind, sizeof(rx_ind), 0, (struct sockaddr*)&servaddr, sizeof(servaddr))) < 0) {
|
||||
printf("sendto failed, ret=%d\n", n);
|
||||
}
|
||||
}
|
||||
|
||||
void send_dl_ind(uint32_t tti_, srsran::unique_byte_buffer_t tb = {})
|
||||
{
|
||||
#if PING_REQUEST_PDU
|
||||
static uint8_t tv[] = {
|
||||
0x04, 0x5c, 0x00, 0x80, 0x00, 0x00, 0x45, 0x00, 0x00, 0x54, 0x15, 0x02, 0x40, 0x00, 0x40, 0x01, 0xa2, 0x52,
|
||||
0xc0, 0xa8, 0x01, 0x01, 0xc0, 0xa8, 0x01, 0x03, 0x08, 0x00, 0x26, 0x40, 0x5e, 0x8f, 0x00, 0xb3, 0x04, 0x55,
|
||||
0xc4, 0x5d, 0x00, 0x00, 0x00, 0x00, 0xe4, 0xf7, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x12, 0x13,
|
||||
0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
|
||||
0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||||
0x4f, 0x7f, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
#else
|
||||
// MAC PDU with a single LCID with padding only
|
||||
static uint8_t tv[] = {
|
||||
0x01,
|
||||
0x08,
|
||||
0x11,
|
||||
0x22,
|
||||
0x33,
|
||||
0x44,
|
||||
0x55,
|
||||
0x66,
|
||||
0x77,
|
||||
0x88,
|
||||
0x3f,
|
||||
};
|
||||
#endif // PING_REQUEST_PDU
|
||||
basic_vnf_api::dl_ind_msg_t dl_ind = {};
|
||||
|
||||
dl_ind.header.type = basic_vnf_api::DL_IND;
|
||||
dl_ind.header.msg_len = sizeof(dl_ind) - sizeof(basic_vnf_api::msg_header_t);
|
||||
dl_ind.tti = tti_;
|
||||
dl_ind.t1 = 0;
|
||||
|
||||
uint32_t tot_bytes = 0;
|
||||
uint32_t tb_size = tb_len > 0 ? tb_len : rand_dist(rand_gen);
|
||||
|
||||
if (tb != nullptr) {
|
||||
auto* header = (basic_vnf_api::msg_header_t*)tb->msg;
|
||||
|
||||
if (header->type == basic_vnf_api::TX_REQUEST) {
|
||||
auto* tx_req = (basic_vnf_api::tx_request_msg_t*)tb->msg;
|
||||
dl_ind.nof_pdus = tx_req->nof_pdus;
|
||||
// dl_ind.tti = tx_req->tti;
|
||||
for (uint32_t i = 0; i < dl_ind.nof_pdus; ++i) {
|
||||
dl_ind.pdus[i].length = tx_req->pdus[i].length;
|
||||
dl_ind.pdus[i].type = tx_req->pdus[i].type;
|
||||
memcpy(dl_ind.pdus[i].data, tx_req->pdus[i].data, dl_ind.pdus[i].length);
|
||||
tot_bytes += dl_ind.pdus[i].length;
|
||||
logger.info(
|
||||
dl_ind.pdus[i].data, dl_ind.pdus[i].length, "Sending to UE a PDU (%d bytes)", dl_ind.pdus[i].length);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uint32_t N_bytes = sizeof(tv);
|
||||
|
||||
// Create default
|
||||
dl_ind.nof_pdus = 1;
|
||||
dl_ind.pdus[0].type = basic_vnf_api::PDSCH;
|
||||
dl_ind.pdus[0].length = tb_size;
|
||||
|
||||
if (dl_ind.pdus[0].length >= N_bytes) {
|
||||
// copy TV
|
||||
memcpy(dl_ind.pdus[0].data, tv, N_bytes);
|
||||
tot_bytes = N_bytes;
|
||||
}
|
||||
|
||||
logger.info(dl_ind.pdus[0].data, N_bytes, "Sending to UE a TB (%d bytes)", N_bytes);
|
||||
}
|
||||
|
||||
if (tot_bytes > 0 and tot_bytes < tb_size) {
|
||||
uint8_t* offset = &dl_ind.pdus[dl_ind.nof_pdus - 1].data[dl_ind.pdus[dl_ind.nof_pdus - 1].length];
|
||||
memset(offset, 0xaa, tb_size - tot_bytes);
|
||||
} else if (tot_bytes == 0) {
|
||||
// just fill with dummy bytes
|
||||
dl_ind.nof_pdus = 1;
|
||||
memset(dl_ind.pdus[0].data, 0xab, tb_size);
|
||||
}
|
||||
|
||||
int n = 0;
|
||||
if ((n = sendto(sockfd, &dl_ind, sizeof(dl_ind), 0, (struct sockaddr*)&servaddr, sizeof(servaddr))) < 0) {
|
||||
printf("sendto failed, ret=%d\n", n);
|
||||
}
|
||||
}
|
||||
|
||||
void send_ul_ind(uint32_t tti_)
|
||||
{
|
||||
basic_vnf_api::ul_ind_msg_t ul_ind = {};
|
||||
|
||||
ul_ind.header.type = basic_vnf_api::UL_IND;
|
||||
ul_ind.header.msg_len = sizeof(ul_ind) - sizeof(basic_vnf_api::msg_header_t);
|
||||
ul_ind.tti = tti_;
|
||||
ul_ind.t1 = 0;
|
||||
|
||||
ul_ind.pdus.type = basic_vnf_api::PUSCH;
|
||||
ul_ind.pdus.length = tb_len > 0 ? tb_len : rand_dist(rand_gen);
|
||||
|
||||
int n = 0;
|
||||
if ((n = sendto(sockfd, &ul_ind, sizeof(ul_ind), 0, (struct sockaddr*)&servaddr, sizeof(servaddr))) < 0) {
|
||||
printf("sendto failed, ret=%d\n", n);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<std::thread> tx_thread, rx_thread;
|
||||
std::string tx_thread_name = "TX_PNF", rx_thread_name = "RX_PNF";
|
||||
bool running = false;
|
||||
srslog::basic_logger& logger = srslog::fetch_basic_logger("PNF", false);
|
||||
|
||||
std::mutex mutex;
|
||||
std::atomic<std::uint32_t> tti;
|
||||
std::chrono::steady_clock::time_point tti_start_time;
|
||||
|
||||
std::string type;
|
||||
|
||||
std::string vnf_addr;
|
||||
uint16_t vnf_port = 3333;
|
||||
|
||||
uint32_t sf_interval_us = 1000;
|
||||
int32_t num_sf = -1;
|
||||
uint32_t tb_len = 100;
|
||||
|
||||
pnf_metrics_t metrics = {};
|
||||
|
||||
int sockfd = 0;
|
||||
struct sockaddr_in servaddr = {};
|
||||
|
||||
// For random number generation
|
||||
std::mt19937 rand_gen;
|
||||
std::uniform_int_distribution<uint16_t> rand_dist;
|
||||
|
||||
// two policies possible: dummy packets generated by the PNF class, or bridge between UE and gNB PNFs with TBs
|
||||
// entering/exiting each PNF via the rf_in_queue/rf_out_queue.
|
||||
srsran::block_queue<srsran::unique_byte_buffer_t>* rf_out_queue = nullptr;
|
||||
srsran::block_queue<srsran::unique_byte_buffer_t> rf_in_queue;
|
||||
enum data_policy_t { self_gen, bridge } policy = self_gen;
|
||||
};
|
||||
|
||||
} // namespace srsran
|
||||
|
||||
#endif // SRSRAN_BASIC_PNF_H
|
|
@ -1,90 +0,0 @@
|
|||
/**
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* This file is part of srsRAN.
|
||||
*
|
||||
* srsRAN is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* srsRAN is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* A copy of the GNU Affero General Public License can be found in
|
||||
* the LICENSE file in the top-level directory of this distribution
|
||||
* and at http://www.gnu.org/licenses/.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSRAN_BASIC_VNF_H
|
||||
#define SRSRAN_BASIC_VNF_H
|
||||
|
||||
#include "basic_vnf_api.h"
|
||||
#include "common.h"
|
||||
#include "srsran/common/threads.h"
|
||||
#include "srsran/interfaces/gnb_interfaces.h"
|
||||
#include "srsran/interfaces/ue_nr_interfaces.h"
|
||||
#include "srsran/srslog/srslog.h"
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <iostream>
|
||||
#include <netinet/in.h>
|
||||
#include <random>
|
||||
#include <strings.h>
|
||||
#include <sys/socket.h>
|
||||
#include <thread>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace srsran {
|
||||
|
||||
class srsran_basic_vnf : public thread
|
||||
{
|
||||
public:
|
||||
srsran_basic_vnf(const vnf_args_t& args_, stack_interface_phy_nr* stack_);
|
||||
~srsran_basic_vnf();
|
||||
|
||||
bool stop();
|
||||
|
||||
int dl_config_request(const srsenb::phy_interface_stack_nr::dl_config_request_t& request);
|
||||
int tx_request(const srsenb::phy_interface_stack_nr::tx_request_t& request);
|
||||
int tx_request(const srsue::phy_interface_stack_nr::tx_request_t& request);
|
||||
|
||||
private:
|
||||
void run_thread();
|
||||
|
||||
// handlers
|
||||
int handle_msg(const uint8_t* buffer, const uint32_t len);
|
||||
int handle_sf_ind(basic_vnf_api::sf_ind_msg_t* msg);
|
||||
int handle_dl_ind(basic_vnf_api::dl_ind_msg_t* msg);
|
||||
int handle_ul_ind(basic_vnf_api::ul_ind_msg_t* msg);
|
||||
int handle_rx_data_ind(basic_vnf_api::rx_data_ind_msg_t* msg);
|
||||
|
||||
// senders
|
||||
int send_dl_config_request();
|
||||
|
||||
// helpers
|
||||
uint32_t calc_full_msg_len(const basic_vnf_api::tx_request_msg_t& msg);
|
||||
|
||||
srslog::basic_logger& logger = srslog::fetch_basic_logger("VNF", false);
|
||||
srsenb::stack_interface_phy_nr* m_gnb_stack = nullptr;
|
||||
srsue::stack_interface_phy_nr* m_ue_stack = nullptr;
|
||||
|
||||
std::unique_ptr<basic_vnf_api::tx_request_msg_t> m_tx_req_msg;
|
||||
|
||||
bool running = false;
|
||||
|
||||
vnf_args_t m_args = {};
|
||||
|
||||
int sockfd = 0;
|
||||
struct sockaddr_in servaddr = {}, client_addr = {};
|
||||
|
||||
uint32_t last_sf_indication_time = 0;
|
||||
};
|
||||
|
||||
} // namespace srsran
|
||||
|
||||
#endif // SRSRAN_BASIC_VNF_H
|
|
@ -1,168 +0,0 @@
|
|||
/**
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* This file is part of srsRAN.
|
||||
*
|
||||
* srsRAN is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* srsRAN is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* A copy of the GNU Affero General Public License can be found in
|
||||
* the LICENSE file in the top-level directory of this distribution
|
||||
* and at http://www.gnu.org/licenses/.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSRAN_BASIC_VNF_API_H
|
||||
#define SRSRAN_BASIC_VNF_API_H
|
||||
|
||||
#include <thread>
|
||||
|
||||
namespace basic_vnf_api {
|
||||
|
||||
// PNF (the PHY) VNF (the L2/L3)
|
||||
// | |
|
||||
// | |
|
||||
// | - |
|
||||
// | \ sf_ind_msg_t
|
||||
// | \ |
|
||||
// | \ |
|
||||
// | \ |
|
||||
// | \ |
|
||||
// | \ |
|
||||
// | \|
|
||||
// | |
|
||||
// | | DL_CONFIG.request
|
||||
// | /|
|
||||
// | / |
|
||||
// | / |
|
||||
// | / |
|
||||
// | / |
|
||||
// | / dl_conf_msg_t
|
||||
// | / |
|
||||
// |/ | TX.request
|
||||
// | /|
|
||||
// | / |
|
||||
// | / |
|
||||
// | / |
|
||||
// | / |
|
||||
// | / tx_request_msg_t
|
||||
// | / |
|
||||
// |/ |
|
||||
// | |
|
||||
|
||||
// Primitive API messages for basic testing basic VNF/PNF interaction
|
||||
enum msg_type_t {
|
||||
SF_IND, ///< To signal start of new subframe (later slot) for both UE and gNB
|
||||
DL_CONFIG, ///< To configure the DL for gNB
|
||||
TX_REQUEST, ///< For DL data for gNB
|
||||
RX_DATA_IND, ///< For UL Data for gNB
|
||||
DL_IND, ///< For the UE for DL data
|
||||
UL_IND, ///< For the UE for UL Data
|
||||
MSG_TYPE_NITEMS
|
||||
};
|
||||
static const char* msg_type_text[MSG_TYPE_NITEMS] =
|
||||
{"SF Indication", "DL_CONFIG.Request", "TX.Request", "RX_Data.indication", "DL_Indication", "UL_Indication"};
|
||||
enum pdu_type_t { MAC_PBCH, PHY_PBCH, PDCCH, PDSCH, PUSCH };
|
||||
|
||||
struct msg_header_t {
|
||||
msg_type_t type;
|
||||
uint32_t msg_len;
|
||||
};
|
||||
|
||||
struct sf_ind_msg_t {
|
||||
msg_header_t header;
|
||||
uint32_t t1; // Timestamp taken at PNF
|
||||
uint32_t tti; // TTI of requested subframe
|
||||
uint32_t tb_len; // Length of the TB
|
||||
};
|
||||
|
||||
#define MAX_TB_LEN (16 * 1024)
|
||||
#define MAX_PDU_SIZE (16 * 1024)
|
||||
#define MAX_NUM_PDUS (1)
|
||||
|
||||
struct phy_pbch_pdu_t {
|
||||
uint16_t phy_cell_id; // 0 - 1007
|
||||
uint8_t ss_block_index; // 0-63
|
||||
uint8_t ssb_sc_offset; // 0-15
|
||||
uint8_t dmrs_pos; // 0-1
|
||||
uint8_t pdcch_config; // 0-255
|
||||
};
|
||||
|
||||
struct dl_conf_msg_t {
|
||||
msg_header_t header;
|
||||
uint32_t t1; // Replayed timestamp
|
||||
uint32_t t2; // Timestamp taken at VNF
|
||||
uint32_t tti; // TTI
|
||||
uint16_t beam_id; // tx beam id for the slot
|
||||
};
|
||||
|
||||
struct tx_request_pdu_t {
|
||||
uint16_t length;
|
||||
uint16_t index; // index indicated in dl_config
|
||||
pdu_type_t type; // physical chan of pdu/tb
|
||||
uint8_t data[MAX_PDU_SIZE];
|
||||
};
|
||||
|
||||
struct tx_request_msg_t {
|
||||
msg_header_t header;
|
||||
uint32_t tti; // TTI
|
||||
uint32_t tb_len; // actual TB len
|
||||
uint32_t nof_pdus;
|
||||
tx_request_pdu_t pdus[MAX_NUM_PDUS];
|
||||
};
|
||||
|
||||
struct rx_data_ind_pdu_t {
|
||||
uint16_t length;
|
||||
pdu_type_t type; // physical chan of pdu/tb
|
||||
uint8_t data[MAX_PDU_SIZE];
|
||||
};
|
||||
|
||||
struct rx_data_ind_msg_t {
|
||||
msg_header_t header;
|
||||
uint32_t t1; // Timestamp taken at PNF
|
||||
uint32_t sfn; ///< SFN (0-1023)
|
||||
uint32_t slot; ///< Slot (0-319)
|
||||
uint32_t tb_len; ///< actual TB len
|
||||
uint32_t nof_pdus; //
|
||||
rx_data_ind_pdu_t pdus[MAX_NUM_PDUS];
|
||||
};
|
||||
|
||||
// UE specific messages
|
||||
struct dl_ind_pdu_t {
|
||||
pdu_type_t type; // physical chan of pdu/tb
|
||||
uint16_t length;
|
||||
uint8_t data[MAX_PDU_SIZE];
|
||||
};
|
||||
|
||||
struct dl_ind_msg_t {
|
||||
msg_header_t header;
|
||||
uint32_t t1; // Timestamp taken at PNF
|
||||
uint32_t tti; // tti or slot?
|
||||
uint32_t nof_pdus;
|
||||
dl_ind_pdu_t pdus[MAX_NUM_PDUS];
|
||||
};
|
||||
|
||||
///< Messages for UL (only one PDU)
|
||||
struct ul_ind_pdu_t {
|
||||
pdu_type_t type; // physical chan of pdu/tb
|
||||
uint16_t length;
|
||||
};
|
||||
|
||||
struct ul_ind_msg_t {
|
||||
msg_header_t header;
|
||||
uint32_t t1; // Timestamp taken at PNF
|
||||
uint32_t tti; // tti or slot?
|
||||
uint32_t rnti; ///< RNTI of this grant
|
||||
ul_ind_pdu_t pdus;
|
||||
};
|
||||
|
||||
} // namespace basic_vnf_api
|
||||
|
||||
#endif // SRSRAN_BASIC_VNF_API_H
|
|
@ -40,7 +40,7 @@ extern "C" {
|
|||
|
||||
// static vars required by signal handling
|
||||
static srslog::sink* log_sink = nullptr;
|
||||
static bool running = true;
|
||||
static std::atomic<bool> running = {true};
|
||||
|
||||
static void srsran_signal_handler(int signal)
|
||||
{
|
||||
|
|
|
@ -34,6 +34,7 @@ struct mac_args_t {
|
|||
int nr_tb_size = -1;
|
||||
uint32_t nof_prealloc_ues; ///< Number of UE resources to pre-allocate at eNB startup
|
||||
uint32_t max_nof_kos;
|
||||
int rlf_min_ul_snr_estim;
|
||||
};
|
||||
|
||||
/* Interface PHY -> MAC */
|
||||
|
|
|
@ -171,42 +171,31 @@ public:
|
|||
virtual void notify_pdcp_integrity_error(uint16_t rnti, uint32_t lcid) = 0;
|
||||
};
|
||||
|
||||
class phy_interface_stack_nr
|
||||
class phy_interface_rrc_nr
|
||||
{
|
||||
public:
|
||||
const static int MAX_DL_GRANTS = 4;
|
||||
/**
|
||||
* @brief Describes physical layer configuration common among all the UEs for a given cell
|
||||
*/
|
||||
struct common_cfg_t {
|
||||
srsran_carrier_nr_t carrier;
|
||||
srsran_pdcch_cfg_nr_t pdcch;
|
||||
srsran_prach_cfg_t prach;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
// TODO: include NR related fields
|
||||
} dl_sched_grant_t;
|
||||
virtual int set_common_cfg(const common_cfg_t& common_cfg) = 0;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
bool mib_present;
|
||||
} bch_sched_t;
|
||||
class phy_interface_mac_nr
|
||||
{
|
||||
public:
|
||||
// TBD
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t tti;
|
||||
uint32_t nof_grants;
|
||||
dl_sched_grant_t pdsch[MAX_DL_GRANTS];
|
||||
int beam_id;
|
||||
} dl_config_request_t;
|
||||
|
||||
typedef struct {
|
||||
bch_sched_t pbch;
|
||||
uint16_t length;
|
||||
uint16_t index; // index indicated in dl_config
|
||||
uint8_t* data[SRSRAN_MAX_TB]; // always a pointer in our case
|
||||
} tx_request_pdu_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t tti;
|
||||
uint32_t tb_len;
|
||||
uint32_t nof_pdus;
|
||||
tx_request_pdu_t pdus[MAX_DL_GRANTS];
|
||||
} tx_request_t;
|
||||
|
||||
virtual int dl_config_request(const dl_config_request_t& request) = 0;
|
||||
virtual int tx_request(const tx_request_t& request) = 0;
|
||||
class phy_interface_stack_nr : public phy_interface_rrc_nr, public phy_interface_mac_nr
|
||||
{
|
||||
public:
|
||||
// TBD
|
||||
};
|
||||
|
||||
class stack_interface_mac
|
||||
|
@ -280,11 +269,17 @@ public:
|
|||
// ... add signal measurements here
|
||||
};
|
||||
|
||||
virtual int slot_indication(const srsran_slot_cfg_t& slot_cfg) = 0;
|
||||
virtual int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) = 0;
|
||||
virtual int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) = 0;
|
||||
virtual int pucch_info(const srsran_slot_cfg_t& slot_cfg, const pucch_info_t& pucch_info) = 0;
|
||||
virtual int pusch_info(const srsran_slot_cfg_t& slot_cfg, const pusch_info_t& pusch_info) = 0;
|
||||
struct rach_info_t {
|
||||
uint32_t preamble;
|
||||
uint32_t time_adv;
|
||||
};
|
||||
|
||||
virtual int slot_indication(const srsran_slot_cfg_t& slot_cfg) = 0;
|
||||
virtual int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) = 0;
|
||||
virtual int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) = 0;
|
||||
virtual int pucch_info(const srsran_slot_cfg_t& slot_cfg, const pucch_info_t& pucch_info) = 0;
|
||||
virtual int pusch_info(const srsran_slot_cfg_t& slot_cfg, const pusch_info_t& pusch_info) = 0;
|
||||
virtual void rach_detected(const rach_info_t& rach_info) = 0;
|
||||
};
|
||||
|
||||
class stack_interface_phy_nr : public mac_interface_phy_nr, public srsran::stack_interface_phy_nr
|
||||
|
|
|
@ -75,6 +75,7 @@ public:
|
|||
int init_ul_snr_value = 5;
|
||||
int init_dl_cqi = 5;
|
||||
float max_sib_coderate = 0.8;
|
||||
int pdcch_cqi_offset = 0;
|
||||
};
|
||||
|
||||
struct cell_cfg_t {
|
||||
|
|
|
@ -48,6 +48,17 @@ public:
|
|||
virtual bool connection_request_completed(bool outcome) = 0;
|
||||
};
|
||||
|
||||
class nas_5g_interface_rrc_nr
|
||||
{
|
||||
public:
|
||||
};
|
||||
|
||||
class nas_5g_interface_procedures
|
||||
{
|
||||
public:
|
||||
virtual int send_registration_request() = 0;
|
||||
};
|
||||
|
||||
} // namespace srsue
|
||||
|
||||
#endif // SRSRAN_UE_NAS_INTERFACES_H
|
||||
|
|
|
@ -184,6 +184,7 @@ struct phy_args_nr_t {
|
|||
srsran_ue_ul_nr_args_t ul = {};
|
||||
std::set<uint32_t> fixed_sr = {1};
|
||||
uint32_t fix_wideband_cqi = 15; // Set to a non-zero value for fixing the wide-band CQI report
|
||||
bool store_pdsch_ko = false;
|
||||
|
||||
phy_args_nr_t()
|
||||
{
|
||||
|
|
|
@ -95,6 +95,8 @@ struct phy_args_t {
|
|||
float force_ul_amplitude = 0.0f;
|
||||
bool detect_cp = false;
|
||||
|
||||
bool nr_store_pdsch_ko = false;
|
||||
|
||||
float in_sync_rsrp_dbm_th = -130.0f;
|
||||
float in_sync_snr_db_th = 1.0f;
|
||||
uint32_t nof_in_sync_events = 10;
|
||||
|
@ -138,8 +140,8 @@ public:
|
|||
} prach_info_t;
|
||||
|
||||
virtual void
|
||||
prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm, float ta_base_sec = 0.0f) = 0;
|
||||
virtual prach_info_t prach_get_info() = 0;
|
||||
prach_send(uint32_t preamble_idx, int allowed_subframe, float target_power_dbm, float ta_base_sec = 0.0f) = 0;
|
||||
virtual prach_info_t prach_get_info() = 0;
|
||||
|
||||
/* Indicates the transmission of a SR signal in the next opportunity */
|
||||
virtual void sr_send() = 0;
|
||||
|
|
|
@ -122,6 +122,10 @@ public:
|
|||
virtual bool is_config_pending() = 0;
|
||||
};
|
||||
|
||||
class rrc_nr_interface_nas_5g
|
||||
{
|
||||
public:
|
||||
};
|
||||
} // namespace srsue
|
||||
|
||||
#endif // SRSRAN_UE_RRC_INTERFACES_H
|
||||
|
|
|
@ -156,8 +156,14 @@ typedef struct SRSRAN_API {
|
|||
uint32_t pid; ///< HARQ process number
|
||||
uint32_t dai; ///< Downlink assignment index
|
||||
uint32_t tpc; ///< TPC command for scheduled PUCCH
|
||||
uint32_t pucch_resource; ///< PUCCH resource indicator
|
||||
uint32_t pucch_resource; ///< PUCCH resource indicator for HARQ feedback
|
||||
///< @note PUCCH resource is selected from PUCCH-ResourceSet if available, otherwise the UE
|
||||
///< shall pick a pucch-ResourceCommon from Table 9.2.1-1.
|
||||
uint32_t harq_feedback; ///< PDSCH-to-HARQ_feedback timing indicator
|
||||
///< @note harq_feedback for format 1_0 indicates the delay between the PDSCH reception and
|
||||
///< the UL transmission timing
|
||||
///< @note harq_feedback for format 1_1 is index of the delay indicated in DL data to UL ACK
|
||||
///< dedicated configuration table
|
||||
|
||||
// P-RNTI specific fields
|
||||
uint32_t smi; ///< Short Messages Indicator
|
||||
|
|
|
@ -44,12 +44,11 @@
|
|||
* @brief Uplink Control Information bits configuration for PUCCH transmission
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t rnti; ///< RNTI
|
||||
uint32_t resource_id; ///< PUCCH resource indicator field in the DCI format 1_0 or DCI format 1_1
|
||||
uint32_t n_cce_0; ///< index of a first CCE for the PDCCH reception
|
||||
uint32_t N_cce; ///< number of CCEs in a CORESET of a PDCCH reception with DCI format 1_0 or 1_1
|
||||
uint32_t sr_resource_id; ///< Scheduling request resource identifier, only valid if positive SR
|
||||
bool sr_positive_present; ///< Set to true if there is at least one positive SR
|
||||
uint16_t rnti; ///< RNTI
|
||||
uint32_t resource_id; ///< PUCCH resource indicator field in the DCI format 1_0 or DCI format 1_1
|
||||
uint32_t n_cce_0; ///< index of a first CCE for the PDCCH reception
|
||||
uint32_t N_cce; ///< number of CCEs in a CORESET of a PDCCH reception with DCI format 1_0 or 1_1
|
||||
uint32_t sr_resource_id; ///< Scheduling request resource identifier, only valid if positive SR
|
||||
} srsran_uci_nr_pucch_cfg_t;
|
||||
|
||||
/**
|
||||
|
@ -79,6 +78,7 @@ typedef struct SRSRAN_API {
|
|||
/// Common Parameters
|
||||
srsran_harq_ack_cfg_t ack; ///< HARQ-ACK configuration
|
||||
uint32_t o_sr; ///< Number of SR bits
|
||||
bool sr_positive_present; ///< Set to true if there is at least one positive SR
|
||||
srsran_csi_report_cfg_t csi[SRSRAN_CSI_MAX_NOF_REPORT]; ///< CSI report configuration
|
||||
uint32_t nof_csi; ///< Number of CSI reports
|
||||
union {
|
||||
|
|
|
@ -99,6 +99,7 @@ private:
|
|||
std::vector<srsran_rf_info_t> rf_info = {};
|
||||
std::vector<int32_t> rx_offset_n = {};
|
||||
rf_metrics_t rf_metrics = {};
|
||||
std::mutex metrics_mutex;
|
||||
srslog::basic_logger& logger = srslog::fetch_basic_logger("RF", false);
|
||||
phy_interface_radio* phy = nullptr;
|
||||
cf_t* zeros = nullptr;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#define SRSLOG_SHARED_TYPES_H
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
namespace srslog {
|
||||
|
||||
|
@ -30,8 +31,7 @@ namespace srslog {
|
|||
using error_handler = std::function<void(const std::string&)>;
|
||||
|
||||
/// Backend priority levels.
|
||||
enum class backend_priority
|
||||
{
|
||||
enum class backend_priority {
|
||||
/// Default priority of the operating system.
|
||||
normal,
|
||||
/// Thread will be given a high priority.
|
||||
|
@ -40,6 +40,18 @@ enum class backend_priority
|
|||
very_high
|
||||
};
|
||||
|
||||
/// syslog log local types
|
||||
enum class syslog_local_type {
|
||||
local0,
|
||||
local1,
|
||||
local2,
|
||||
local3,
|
||||
local4,
|
||||
local5,
|
||||
local6,
|
||||
local7,
|
||||
};
|
||||
|
||||
} // namespace srslog
|
||||
|
||||
#endif // SRSLOG_SHARED_TYPES_H
|
||||
|
|
|
@ -193,6 +193,14 @@ sink& fetch_file_sink(const std::string& path,
|
|||
size_t max_size = 0,
|
||||
std::unique_ptr<log_formatter> f = get_default_log_formatter());
|
||||
|
||||
/// Returns an instance of a sink that writes into syslog
|
||||
/// preamble: The string prepended to every message, If ident is "", the program name is used.
|
||||
/// log_local: custom unused facilities that syslog provides which can be used by the user
|
||||
/// NOTE: Any '#' characters in the path will get removed.
|
||||
sink& fetch_syslog_sink(const std::string& preamble_ = "",
|
||||
syslog_local_type log_local_ = syslog_local_type::local0,
|
||||
std::unique_ptr<log_formatter> f = get_default_log_formatter());
|
||||
|
||||
/// Installs a custom user defined sink in the framework getting associated to
|
||||
/// the specified id. Returns true on success, otherwise false.
|
||||
/// WARNING: This function is an advanced feature and users should really know
|
||||
|
|
|
@ -441,7 +441,7 @@ SRSASN_CODE capability_5gmm_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(bref.pack(cag, 1));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length < 1 || length > 13) {
|
||||
asn1::log_error("Encoding Failed (5GMM capability): Packed length (%d) is not in range of min: 1 and max 13 bytes",
|
||||
|
@ -541,7 +541,7 @@ SRSASN_CODE ue_security_capability_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(bref.pack(eia7_supported, 1));
|
||||
}
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length < 2 || length > 8) {
|
||||
asn1::log_error(
|
||||
|
@ -617,7 +617,7 @@ SRSASN_CODE nssai_t::pack(asn1::bit_ref& bref)
|
|||
}
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length < 2 || length > 144) {
|
||||
asn1::log_error("Encoding Failed (NSSAI): Packed length (%d) is not in range of min: 2 and max 144 bytes", length);
|
||||
|
@ -742,7 +742,7 @@ SRSASN_CODE s1_ue_network_capability_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(bref.pack(racs_supported, 1));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length < 2 || length > 13) {
|
||||
asn1::log_error(
|
||||
|
@ -887,7 +887,7 @@ SRSASN_CODE uplink_data_status_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(bref.pack(psi_8, 1));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length < 2 || length > 32) {
|
||||
asn1::log_error(
|
||||
|
@ -957,7 +957,7 @@ SRSASN_CODE pdu_session_status_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(bref.pack(psi_8, 1));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length < 2 || length > 32) {
|
||||
asn1::log_error(
|
||||
|
@ -1037,7 +1037,7 @@ SRSASN_CODE ue_status_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(bref.pack(s1_mode_reg, 1));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length != 1) {
|
||||
asn1::log_error("Encoding Failed (UE status): Packed length (%d) does not equal expected length 1", length);
|
||||
|
@ -1089,7 +1089,7 @@ SRSASN_CODE allowed_pdu_session_status_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(bref.pack(psi_8, 1));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length < 2 || length > 32) {
|
||||
asn1::log_error(
|
||||
|
@ -1147,7 +1147,7 @@ SRSASN_CODE ue_usage_setting_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(ue_usage_setting.pack(bref));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length != 1) {
|
||||
asn1::log_error("Encoding Failed (UE usage setting): Packed length (%d) does not equal expected length 1", length);
|
||||
|
@ -1185,7 +1185,7 @@ SRSASN_CODE drx_parameters_5gs_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(drx_value.pack(bref));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length != 1) {
|
||||
asn1::log_error("Encoding Failed (5GS DRX parameters): Packed length (%d) does not equal expected length 1",
|
||||
|
@ -1221,7 +1221,7 @@ SRSASN_CODE eps_nas_message_container_t::pack(asn1::bit_ref& bref)
|
|||
|
||||
HANDLE_CODE(bref.pack_bytes(eps_nas_message_container.data(), eps_nas_message_container.size()));
|
||||
bref.align_bytes_zero();
|
||||
uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2);
|
||||
uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2);
|
||||
|
||||
HANDLE_CODE(bref_length.pack(length, 16));
|
||||
return SRSASN_SUCCESS;
|
||||
|
@ -1250,7 +1250,7 @@ SRSASN_CODE ladn_indication_t::pack(asn1::bit_ref& bref)
|
|||
}
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2);
|
||||
uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2);
|
||||
|
||||
// MIN 0 not check because auf uint underflow
|
||||
if (length > 808) {
|
||||
|
@ -1306,7 +1306,7 @@ SRSASN_CODE payload_container_t::pack(asn1::bit_ref& bref)
|
|||
|
||||
HANDLE_CODE(bref.pack_bytes(payload_container_contents.data(), payload_container_contents.size()));
|
||||
bref.align_bytes_zero();
|
||||
uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2);
|
||||
uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2);
|
||||
|
||||
// MAX 65535 not check because auf uint overflow
|
||||
if (length < 1) {
|
||||
|
@ -1370,7 +1370,7 @@ SRSASN_CODE update_type_5gs_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(sms_requested.pack(bref));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
HANDLE_CODE(bref_length.pack(length, 8));
|
||||
return SRSASN_SUCCESS;
|
||||
|
@ -1400,7 +1400,7 @@ SRSASN_CODE mobile_station_classmark_2_t::pack(asn1::bit_ref& bref)
|
|||
// TODO proper packing
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length != 3) {
|
||||
asn1::log_error("Encoding Failed (Mobile station classmark 2): Packed length (%d) does not equal expected length 3",
|
||||
|
@ -1438,7 +1438,7 @@ SRSASN_CODE supported_codec_list_t::pack(asn1::bit_ref& bref)
|
|||
// TODO proper packing
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length < 3) {
|
||||
asn1::log_error("Encoding Failed (Supported codec list): Packed length (%d) is not in range of min: 3 bytes",
|
||||
|
@ -1474,7 +1474,7 @@ SRSASN_CODE message_container_t::pack(asn1::bit_ref& bref)
|
|||
|
||||
HANDLE_CODE(bref.pack_bytes(nas_message_container.data(), nas_message_container.size()));
|
||||
bref.align_bytes_zero();
|
||||
uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2);
|
||||
uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2);
|
||||
|
||||
if (length < 1 || length > 65532) {
|
||||
asn1::log_error(
|
||||
|
@ -1527,7 +1527,7 @@ SRSASN_CODE eps_bearer_context_status_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(bref.pack(ebi_8, 1));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length != 2) {
|
||||
asn1::log_error("Encoding Failed (EPS bearer context status): Packed length (%d) does not equal expected length 2",
|
||||
|
@ -1579,7 +1579,7 @@ SRSASN_CODE extended_drx_parameters_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(e_drx_value.pack(bref));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length != 1) {
|
||||
asn1::log_error("Encoding Failed (Extended DRX parameters): Packed length (%d) does not equal expected length 1",
|
||||
|
@ -1616,7 +1616,7 @@ SRSASN_CODE gprs_timer_3_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(bref.pack(timer_value, 5));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length != 1) {
|
||||
asn1::log_error("Encoding Failed (GPRS timer 3): Packed length (%d) does not equal expected length 1", length);
|
||||
|
@ -1650,7 +1650,7 @@ SRSASN_CODE ue_radio_capability_id_t::pack(asn1::bit_ref& bref)
|
|||
|
||||
HANDLE_CODE(bref.pack_bytes(ue_radio_capability_id.data(), ue_radio_capability_id.size()));
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
HANDLE_CODE(bref_length.pack(length, 8));
|
||||
return SRSASN_SUCCESS;
|
||||
|
@ -1677,7 +1677,7 @@ SRSASN_CODE mapped_nssai_t::pack(asn1::bit_ref& bref)
|
|||
// TODO proper packing
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length < 2 || length > 40) {
|
||||
asn1::log_error("Encoding Failed (Mapped NSSAI): Packed length (%d) is not in range of min: 2 and max 40 bytes",
|
||||
|
@ -1716,7 +1716,7 @@ SRSASN_CODE additional_information_requested_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(bref.pack(cipher_key, 1));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
HANDLE_CODE(bref_length.pack(length, 8));
|
||||
return SRSASN_SUCCESS;
|
||||
|
@ -1743,7 +1743,7 @@ SRSASN_CODE wus_assistance_information_t::pack(asn1::bit_ref& bref)
|
|||
// TODO proper packing
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length < 1) {
|
||||
asn1::log_error("Encoding Failed (WUS assistance information): Packed length (%d) is not in range of min: 1 bytes",
|
||||
|
@ -1803,7 +1803,7 @@ SRSASN_CODE nb_n1_mode_drx_parameters_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(nb_n1_mode_drx_value.pack(bref));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length != 1) {
|
||||
asn1::log_error("Encoding Failed (NB-N1 mode DRX parameters): Packed length (%d) does not equal expected length 1",
|
||||
|
@ -1846,7 +1846,7 @@ SRSASN_CODE registration_result_5gs_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(registration_result.pack(bref));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length != 1) {
|
||||
asn1::log_error("Encoding Failed (5GS registration result): Packed length (%d) does not equal expected length 1",
|
||||
|
@ -1886,7 +1886,7 @@ SRSASN_CODE plmn_list_t::pack(asn1::bit_ref& bref)
|
|||
// TODO proper packing
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
HANDLE_CODE(bref_length.pack(length, 8));
|
||||
return SRSASN_SUCCESS;
|
||||
|
@ -1913,7 +1913,7 @@ SRSASN_CODE tracking_area_identity_list_5gs_t::pack(asn1::bit_ref& bref)
|
|||
// TODO proper packing
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length != 7) {
|
||||
asn1::log_error(
|
||||
|
@ -1952,7 +1952,7 @@ SRSASN_CODE rejected_nssai_t::pack(asn1::bit_ref& bref)
|
|||
// TODO proper packing
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
HANDLE_CODE(bref_length.pack(length, 8));
|
||||
return SRSASN_SUCCESS;
|
||||
|
@ -1979,7 +1979,7 @@ SRSASN_CODE network_feature_support_5gs_t::pack(asn1::bit_ref& bref)
|
|||
// TODO proper packing
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length < 1 || length > 3) {
|
||||
asn1::log_error(
|
||||
|
@ -2033,7 +2033,7 @@ SRSASN_CODE pdu_session_reactivation_result_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(bref.pack(psi_8, 1));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length < 2 || length > 32) {
|
||||
asn1::log_error("Encoding Failed (PDU session reactivation result): Packed length (%d) is not in range of min: 2 "
|
||||
|
@ -2092,7 +2092,7 @@ SRSASN_CODE pdu_session_reactivation_result_error_cause_t::pack(asn1::bit_ref& b
|
|||
// TODO proper packing
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2);
|
||||
uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2);
|
||||
|
||||
if (length < 2 || length > 512) {
|
||||
asn1::log_error("Encoding Failed (PDU session reactivation result error cause): Packed length (%d) is not in range "
|
||||
|
@ -2132,7 +2132,7 @@ SRSASN_CODE ladn_information_t::pack(asn1::bit_ref& bref)
|
|||
// TODO proper packing
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2);
|
||||
uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2);
|
||||
|
||||
// MIN 0 not check because auf uint underflow
|
||||
if (length > 1712) {
|
||||
|
@ -2170,7 +2170,7 @@ SRSASN_CODE service_area_list_t::pack(asn1::bit_ref& bref)
|
|||
// TODO proper packing
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
HANDLE_CODE(bref_length.pack(length, 8));
|
||||
return SRSASN_SUCCESS;
|
||||
|
@ -2197,7 +2197,7 @@ SRSASN_CODE gprs_timer_2_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(bref.pack(timer_value, 8));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length != 1) {
|
||||
asn1::log_error("Encoding Failed (GPRS timer 2): Packed length (%d) does not equal expected length 1", length);
|
||||
|
@ -2231,7 +2231,7 @@ SRSASN_CODE emergency_number_list_t::pack(asn1::bit_ref& bref)
|
|||
// TODO proper packing
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length < 3 || length > 48) {
|
||||
asn1::log_error(
|
||||
|
@ -2270,7 +2270,7 @@ SRSASN_CODE extended_emergency_number_list_t::pack(asn1::bit_ref& bref)
|
|||
// TODO proper packing
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2);
|
||||
uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2);
|
||||
|
||||
// MAX 65535 not check because auf uint overflow
|
||||
if (length < 4) {
|
||||
|
@ -2310,7 +2310,7 @@ SRSASN_CODE sor_transparent_container_t::pack(asn1::bit_ref& bref)
|
|||
// TODO proper packing
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2);
|
||||
uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2);
|
||||
|
||||
if (length < 17) {
|
||||
asn1::log_error("Encoding Failed (SOR transparent container): Packed length (%d) is not in range of min: 17 bytes",
|
||||
|
@ -2347,7 +2347,7 @@ SRSASN_CODE eap_message_t::pack(asn1::bit_ref& bref)
|
|||
|
||||
HANDLE_CODE(bref.pack_bytes(eap_message.data(), eap_message.size()));
|
||||
bref.align_bytes_zero();
|
||||
uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2);
|
||||
uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2);
|
||||
|
||||
if (length < 4 || length > 1500) {
|
||||
asn1::log_error("Encoding Failed (EAP message): Packed length (%d) is not in range of min: 4 and max 1500 bytes",
|
||||
|
@ -2403,7 +2403,7 @@ SRSASN_CODE operator_defined_access_category_definitions_t::pack(asn1::bit_ref&
|
|||
// TODO proper packing
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2);
|
||||
uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2);
|
||||
|
||||
HANDLE_CODE(bref_length.pack(length, 16));
|
||||
return SRSASN_SUCCESS;
|
||||
|
@ -2470,7 +2470,7 @@ SRSASN_CODE ciphering_key_data_t::pack(asn1::bit_ref& bref)
|
|||
// TODO proper packing
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2);
|
||||
uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2);
|
||||
|
||||
if (length < 31 || length > 2672) {
|
||||
asn1::log_error(
|
||||
|
@ -2509,7 +2509,7 @@ SRSASN_CODE cag_information_list_t::pack(asn1::bit_ref& bref)
|
|||
// TODO proper packing
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2);
|
||||
uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2);
|
||||
|
||||
HANDLE_CODE(bref_length.pack(length, 16));
|
||||
return SRSASN_SUCCESS;
|
||||
|
@ -2537,7 +2537,7 @@ SRSASN_CODE truncated_5g_s_tmsi_configuration_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(bref.pack(truncated_amf__pointer_value, 4));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length != 1) {
|
||||
asn1::log_error(
|
||||
|
@ -2665,7 +2665,7 @@ SRSASN_CODE network_name_t::pack(asn1::bit_ref& bref)
|
|||
// TODO proper packing
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
HANDLE_CODE(bref_length.pack(length, 8));
|
||||
return SRSASN_SUCCESS;
|
||||
|
@ -2734,7 +2734,7 @@ SRSASN_CODE daylight_saving_time_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(value.pack(bref));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length != 1) {
|
||||
asn1::log_error("Encoding Failed (Daylight saving time): Packed length (%d) does not equal expected length 1",
|
||||
|
@ -2808,7 +2808,7 @@ SRSASN_CODE abba_t::pack(asn1::bit_ref& bref)
|
|||
|
||||
HANDLE_CODE(bref.pack_bytes(abba_contents.data(), abba_contents.size()));
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length < 2) {
|
||||
asn1::log_error("Encoding Failed (ABBA): Packed length (%d) is not in range of min: 2 bytes", length);
|
||||
|
@ -2858,7 +2858,7 @@ SRSASN_CODE authentication_parameter_autn_t::pack(asn1::bit_ref& bref)
|
|||
|
||||
HANDLE_CODE(bref.pack_bytes(autn.data(), autn.size()));
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length != 16) {
|
||||
asn1::log_error(
|
||||
|
@ -2895,7 +2895,7 @@ SRSASN_CODE authentication_response_parameter_t::pack(asn1::bit_ref& bref)
|
|||
|
||||
HANDLE_CODE(bref.pack_bytes(res.data(), res.size()));
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length != 16) {
|
||||
asn1::log_error(
|
||||
|
@ -2932,7 +2932,7 @@ SRSASN_CODE authentication_failure_parameter_t::pack(asn1::bit_ref& bref)
|
|||
|
||||
HANDLE_CODE(bref.pack_bytes(auth_failure.data(), auth_failure.size()));
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length != 14) {
|
||||
asn1::log_error(
|
||||
|
@ -3058,7 +3058,7 @@ SRSASN_CODE additional_5g_security_information_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(bref.pack(hdp, 1));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length != 1) {
|
||||
asn1::log_error(
|
||||
|
@ -3141,7 +3141,7 @@ SRSASN_CODE s1_ue_security_capability_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(bref.pack(gea7, 1));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length < 2 || length > 5) {
|
||||
asn1::log_error(
|
||||
|
@ -3305,7 +3305,7 @@ SRSASN_CODE s_nssai_t::pack(asn1::bit_ref& bref)
|
|||
}
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length < 1 || length > 8) {
|
||||
asn1::log_error("Encoding Failed (S-NSSAI): Packed length (%d) is not in range of min: 1 and max 8 bytes", length);
|
||||
|
@ -3354,7 +3354,7 @@ SRSASN_CODE dnn_t::pack(asn1::bit_ref& bref)
|
|||
|
||||
HANDLE_CODE(bref.pack_bytes(dnn_value.data(), dnn_value.size()));
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length < 1 || length > 100) {
|
||||
asn1::log_error("Encoding Failed (DNN): Packed length (%d) is not in range of min: 1 and max 100 bytes", length);
|
||||
|
@ -3388,7 +3388,7 @@ SRSASN_CODE additional_information_t::pack(asn1::bit_ref& bref)
|
|||
|
||||
HANDLE_CODE(bref.pack_bytes(additional_information_value.data(), additional_information_value.size()));
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length < 1) {
|
||||
asn1::log_error("Encoding Failed (Additional information): Packed length (%d) is not in range of min: 1 bytes",
|
||||
|
@ -3518,7 +3518,7 @@ SRSASN_CODE capability_5gsm_t::pack(asn1::bit_ref& bref)
|
|||
// TODO proper packing
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length < 1 || length > 13) {
|
||||
asn1::log_error("Encoding Failed (5GSM capability): Packed length (%d) is not in range of min: 1 and max 13 bytes",
|
||||
|
@ -3596,7 +3596,7 @@ SRSASN_CODE sm_pdu_dn_request_container_t::pack(asn1::bit_ref& bref)
|
|||
|
||||
HANDLE_CODE(bref.pack_bytes(dn_specific_identity.data(), dn_specific_identity.size()));
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length < 1 || length > 253) {
|
||||
asn1::log_error(
|
||||
|
@ -3635,7 +3635,7 @@ SRSASN_CODE extended_protocol_configuration_options_t::pack(asn1::bit_ref& bref)
|
|||
// TODO proper packing
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2);
|
||||
uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2);
|
||||
|
||||
// MAX 65535 not check because auf uint overflow
|
||||
if (length < 1) {
|
||||
|
@ -3677,7 +3677,7 @@ SRSASN_CODE ip_header_compression_configuration_t::pack(asn1::bit_ref& bref)
|
|||
// TODO proper packing
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
// MAX 255 not check because auf uint overflow
|
||||
if (length < 3) {
|
||||
|
@ -3718,7 +3718,7 @@ SRSASN_CODE ds_tt__ethernet_port_mac_address_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(bref.pack_bytes(ds_tt__ethernet_port_mac_address_contents.data(), 6));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length != 6) {
|
||||
asn1::log_error(
|
||||
|
@ -3755,7 +3755,7 @@ SRSASN_CODE ue_ds_tt_residence_time_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(bref.pack_bytes(ue_ds_tt_residence_time_contents.data(), 8));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length != 8) {
|
||||
asn1::log_error("Encoding Failed (UE-DS-TT residence time): Packed length (%d) does not equal expected length 8",
|
||||
|
@ -3790,7 +3790,7 @@ SRSASN_CODE port_management_information_container_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(
|
||||
bref.pack_bytes(port_management_information_container.data(), port_management_information_container.size()));
|
||||
bref.align_bytes_zero();
|
||||
uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2);
|
||||
uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2);
|
||||
|
||||
// MAX 65535 not check because auf uint overflow
|
||||
if (length < 1) {
|
||||
|
@ -3832,7 +3832,7 @@ SRSASN_CODE ethernet_header_compression_configuration_t::pack(asn1::bit_ref& bre
|
|||
HANDLE_CODE(cid__length.pack(bref));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length != 1) {
|
||||
asn1::log_error("Encoding Failed (Ethernet header compression configuration): Packed length (%d) does not equal "
|
||||
|
@ -3888,7 +3888,7 @@ SRSASN_CODE pdu_address_t::pack(asn1::bit_ref& bref)
|
|||
}
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length < 5 || length > 29) {
|
||||
asn1::log_error("Encoding Failed (PDU address): Packed length (%d) is not in range of min: 5 and max 29 bytes",
|
||||
|
@ -3947,7 +3947,7 @@ SRSASN_CODE qo_s_rules_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(bref.advance_bits(16));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2);
|
||||
uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2);
|
||||
|
||||
// MAX 65535 not check because auf uint overflow
|
||||
if (length < 4) {
|
||||
|
@ -3986,7 +3986,7 @@ SRSASN_CODE session_ambr_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(bref.pack(session_ambr_for_uplink, 16));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length != 6) {
|
||||
asn1::log_error("Encoding Failed (Session-AMBR): Packed length (%d) does not equal expected length 6", length);
|
||||
|
@ -4077,7 +4077,7 @@ SRSASN_CODE mapped_eps_bearer_contexts_t::pack(asn1::bit_ref& bref)
|
|||
// TODO proper packing
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2);
|
||||
uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2);
|
||||
|
||||
// MAX 65535 not check because auf uint overflow
|
||||
if (length < 4) {
|
||||
|
@ -4117,7 +4117,7 @@ SRSASN_CODE qo_s_flow_descriptions_t::pack(asn1::bit_ref& bref)
|
|||
// TODO proper packing
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2);
|
||||
uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2);
|
||||
|
||||
// MAX 65535 not check because auf uint overflow
|
||||
if (length < 3) {
|
||||
|
@ -4158,7 +4158,7 @@ SRSASN_CODE network_feature_support_5gsm_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(ept_s1.pack(bref));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length < 1 || length > 13) {
|
||||
asn1::log_error(
|
||||
|
@ -4201,7 +4201,7 @@ SRSASN_CODE serving_plmn_rate_control_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(bref.pack(serving_plmn_rate_control_value, 16));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length != 2) {
|
||||
asn1::log_error("Encoding Failed (Serving PLMN rate control): Packed length (%d) does not equal expected length 2",
|
||||
|
@ -4236,7 +4236,7 @@ SRSASN_CODE atsss_container_t::pack(asn1::bit_ref& bref)
|
|||
|
||||
HANDLE_CODE(bref.pack_bytes(nas_message_container.data(), nas_message_container.size()));
|
||||
bref.align_bytes_zero();
|
||||
uint16_t length = (uint16_t)(ceilf(bref.distance(bref_length) / 8) - 2);
|
||||
uint16_t length = (uint16_t)(ceilf((float)bref.distance(bref_length) / 8) - 2);
|
||||
|
||||
// MIN 0 not check because auf uint underflow
|
||||
// MAX 65535 not check because auf uint overflow
|
||||
|
@ -4337,7 +4337,7 @@ SRSASN_CODE re_attempt_indicator_t::pack(asn1::bit_ref& bref)
|
|||
HANDLE_CODE(bref.pack(ratc, 1));
|
||||
|
||||
bref.align_bytes_zero();
|
||||
uint8_t length = (uint8_t)(ceilf(bref.distance(bref_length) / 8) - 1);
|
||||
uint8_t length = (uint8_t)(ceilf((float)bref.distance(bref_length) / 8) - 1);
|
||||
|
||||
if (length != 1) {
|
||||
asn1::log_error("Encoding Failed (Re-attempt indicator): Packed length (%d) does not equal expected length 1",
|
||||
|
|
|
@ -141,7 +141,9 @@ srsran::rlc_config_t make_rlc_config_t(const asn1::rrc::rlc_cfg_c& asn1_type)
|
|||
rlc_cfg.rlc_mode = rlc_mode_t::am;
|
||||
rlc_cfg.am.t_poll_retx = asn1_type.am().ul_am_rlc.t_poll_retx.to_number();
|
||||
rlc_cfg.am.poll_pdu = asn1_type.am().ul_am_rlc.poll_pdu.to_number();
|
||||
rlc_cfg.am.poll_byte = asn1_type.am().ul_am_rlc.poll_byte.to_number() * 1000; // KB
|
||||
rlc_cfg.am.poll_byte = asn1_type.am().ul_am_rlc.poll_byte.to_number() < 0
|
||||
? -1
|
||||
: asn1_type.am().ul_am_rlc.poll_byte.to_number() * 1000; // KB
|
||||
rlc_cfg.am.max_retx_thresh = asn1_type.am().ul_am_rlc.max_retx_thres.to_number();
|
||||
rlc_cfg.am.t_reordering = asn1_type.am().dl_am_rlc.t_reordering.to_number();
|
||||
rlc_cfg.am.t_status_prohibit = asn1_type.am().dl_am_rlc.t_status_prohibit.to_number();
|
||||
|
|
|
@ -46,8 +46,7 @@ set(SOURCES arch_select.cc
|
|||
time_prof.cc
|
||||
version.c
|
||||
zuc.cc
|
||||
s3g.cc
|
||||
basic_vnf.cc)
|
||||
s3g.cc)
|
||||
|
||||
# Avoid warnings caused by libmbedtls about deprecated functions
|
||||
set_source_files_properties(security.cc PROPERTIES COMPILE_FLAGS -Wno-deprecated-declarations)
|
||||
|
|
|
@ -1,408 +0,0 @@
|
|||
/**
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* This file is part of srsRAN.
|
||||
*
|
||||
* srsRAN is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* srsRAN is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* A copy of the GNU Affero General Public License can be found in
|
||||
* the LICENSE file in the top-level directory of this distribution
|
||||
* and at http://www.gnu.org/licenses/.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "srsran/common/basic_vnf.h"
|
||||
#include "srsran/common/buffer_pool.h"
|
||||
#include "srsran/interfaces/ue_nr_interfaces.h"
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <poll.h>
|
||||
|
||||
#define RAND_SEED (12314)
|
||||
#define RX_TIMEOUT_MS (1000)
|
||||
|
||||
namespace srsran {
|
||||
|
||||
struct srsran_pnf_info_t {
|
||||
// TODO: fill when needed
|
||||
};
|
||||
|
||||
struct srsran_vnf_info_t {};
|
||||
|
||||
srsran_basic_vnf::srsran_basic_vnf(const vnf_args_t& args_, stack_interface_phy_nr* stack_) :
|
||||
m_args(args_), thread("BASIC_VNF_P7"), m_tx_req_msg(new basic_vnf_api::tx_request_msg_t)
|
||||
{
|
||||
logger.set_level(srslog::str_to_basic_level(m_args.log_level));
|
||||
logger.set_hex_dump_max_size(m_args.log_hex_limit);
|
||||
|
||||
if (m_args.type == "gnb" || m_args.type == "ue") {
|
||||
if (m_args.type == "gnb") {
|
||||
m_gnb_stack = (srsenb::stack_interface_phy_nr*)stack_;
|
||||
} else {
|
||||
m_ue_stack = (srsue::stack_interface_phy_nr*)stack_;
|
||||
}
|
||||
|
||||
logger.info("Initializing VNF for gNB");
|
||||
start();
|
||||
} else {
|
||||
logger.error("Unknown VNF type. Exiting.");
|
||||
}
|
||||
}
|
||||
|
||||
srsran_basic_vnf::~srsran_basic_vnf()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
void srsran_basic_vnf::run_thread()
|
||||
{
|
||||
// Bind to UDP socket
|
||||
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sockfd < 0) {
|
||||
perror("socket");
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sockets reusable
|
||||
int enable = 1;
|
||||
#if defined(SO_REUSEADDR)
|
||||
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0) {
|
||||
perror("setsockopt(SO_REUSEADDR) failed");
|
||||
}
|
||||
#endif
|
||||
#if defined(SO_REUSEPORT)
|
||||
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(int)) < 0) {
|
||||
perror("setsockopt(SO_REUSEPORT) failed");
|
||||
}
|
||||
#endif
|
||||
|
||||
servaddr.sin_family = AF_INET;
|
||||
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
servaddr.sin_port = htons(m_args.bind_port);
|
||||
|
||||
if (bind(sockfd, (struct sockaddr*)&servaddr, sizeof(struct sockaddr_in))) {
|
||||
perror("bind");
|
||||
return;
|
||||
}
|
||||
|
||||
struct pollfd fd;
|
||||
fd.fd = sockfd;
|
||||
fd.events = POLLIN;
|
||||
|
||||
const uint32_t max_basic_api_pdu = sizeof(basic_vnf_api::dl_ind_msg_t) + 32; // larger than biggest message
|
||||
std::unique_ptr<std::array<uint8_t, max_basic_api_pdu> > rx_buffer =
|
||||
std::unique_ptr<std::array<uint8_t, max_basic_api_pdu> >(new std::array<uint8_t, max_basic_api_pdu>);
|
||||
|
||||
running = true;
|
||||
|
||||
logger.info("Started VNF handler listening on %s:%d", m_args.bind_addr.c_str(), m_args.bind_port);
|
||||
|
||||
while (running) {
|
||||
int ret = poll(&fd, 1, RX_TIMEOUT_MS);
|
||||
switch (ret) {
|
||||
case -1:
|
||||
printf("Error occured.\n");
|
||||
break;
|
||||
case 0:
|
||||
// Timeout
|
||||
break;
|
||||
default:
|
||||
|
||||
socklen_t len = sizeof(client_addr);
|
||||
ret = recvfrom(sockfd, rx_buffer->data(), rx_buffer->size(), MSG_WAITALL, (struct sockaddr*)&client_addr, &len);
|
||||
|
||||
handle_msg(rx_buffer->data(), ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
logger.info("VNF thread stopped");
|
||||
}
|
||||
|
||||
int srsran_basic_vnf::handle_msg(const uint8_t* buffer, const uint32_t len)
|
||||
{
|
||||
basic_vnf_api::msg_header_t* header = (basic_vnf_api::msg_header_t*)buffer;
|
||||
|
||||
logger.info("Received %s (%d B)", basic_vnf_api::msg_type_text[header->type], len);
|
||||
|
||||
switch (header->type) {
|
||||
case basic_vnf_api::SF_IND:
|
||||
handle_sf_ind((basic_vnf_api::sf_ind_msg_t*)header);
|
||||
break;
|
||||
case basic_vnf_api::DL_CONFIG:
|
||||
printf("Error: %s not handled by VNF\n", basic_vnf_api::msg_type_text[header->type]);
|
||||
break;
|
||||
case basic_vnf_api::DL_IND:
|
||||
handle_dl_ind((basic_vnf_api::dl_ind_msg_t*)header);
|
||||
break;
|
||||
case basic_vnf_api::UL_IND:
|
||||
handle_ul_ind((basic_vnf_api::ul_ind_msg_t*)header);
|
||||
break;
|
||||
case basic_vnf_api::RX_DATA_IND:
|
||||
handle_rx_data_ind((basic_vnf_api::rx_data_ind_msg_t*)header);
|
||||
break;
|
||||
default:
|
||||
printf("Unknown msg type.\n");
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int srsran_basic_vnf::handle_sf_ind(basic_vnf_api::sf_ind_msg_t* msg)
|
||||
{
|
||||
int ret = SRSRAN_SUCCESS;
|
||||
logger.info("Received %s for TTI=%d", basic_vnf_api::msg_type_text[msg->header.type], msg->tti);
|
||||
|
||||
// store Rx timestamp
|
||||
last_sf_indication_time = msg->t1;
|
||||
|
||||
if (m_gnb_stack != nullptr) {
|
||||
srsran_slot_cfg_t slot_cfg = {};
|
||||
slot_cfg.idx = msg->tti;
|
||||
m_gnb_stack->slot_indication(slot_cfg);
|
||||
} else if (m_ue_stack != nullptr) {
|
||||
m_ue_stack->sf_indication(msg->tti);
|
||||
} else {
|
||||
ret = SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int srsran_basic_vnf::handle_dl_ind(basic_vnf_api::dl_ind_msg_t* msg)
|
||||
{
|
||||
int ret = SRSRAN_ERROR;
|
||||
logger.info("Received %s for TTI=%d", basic_vnf_api::msg_type_text[msg->header.type], msg->tti);
|
||||
|
||||
uint32_t cc_idx = 0;
|
||||
|
||||
// fill DL struct
|
||||
srsue::stack_interface_phy_nr::mac_nr_grant_dl_t dl_grant = {};
|
||||
dl_grant.tti = msg->tti;
|
||||
|
||||
if (msg->nof_pdus > SRSRAN_MAX_TB) {
|
||||
logger.error("Too many TBs (%d > %d)", msg->nof_pdus, SRSRAN_MAX_TB);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < msg->nof_pdus; ++i) {
|
||||
srsue::stack_interface_phy_nr::tb_action_dl_result_t result = {};
|
||||
result.payload = srsran::make_byte_buffer();
|
||||
if (result.payload != nullptr && result.payload->get_tailroom() >= msg->pdus[i].length) {
|
||||
result.ack = true;
|
||||
memcpy(result.payload->msg, msg->pdus[i].data, msg->pdus[i].length);
|
||||
result.payload->N_bytes = msg->pdus[i].length;
|
||||
if (msg->pdus[i].type == basic_vnf_api::PDSCH) {
|
||||
m_ue_stack->tb_decoded(cc_idx, dl_grant, std::move(result));
|
||||
}
|
||||
} else {
|
||||
logger.error("TB too big to fit into buffer (%d)", msg->pdus[i].length);
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
ret = SRSRAN_SUCCESS;
|
||||
|
||||
exit:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int srsran_basic_vnf::handle_ul_ind(basic_vnf_api::ul_ind_msg_t* msg)
|
||||
{
|
||||
logger.info("Received %s for TTI=%d", basic_vnf_api::msg_type_text[msg->header.type], msg->tti);
|
||||
|
||||
if (msg->pdus.type != basic_vnf_api::PUSCH) {
|
||||
logger.error("Received UL indication for wrong PDU type");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
uint32_t cc_idx = 0;
|
||||
|
||||
// fill DL struct
|
||||
srsue::stack_interface_phy_nr::mac_nr_grant_ul_t ul_grant = {};
|
||||
ul_grant.tti = msg->tti;
|
||||
ul_grant.tbs = msg->pdus.length;
|
||||
ul_grant.rnti = msg->rnti;
|
||||
|
||||
srsue::stack_interface_phy_nr::tb_action_ul_t ul_action = {};
|
||||
m_ue_stack->new_grant_ul(cc_idx, ul_grant, &ul_action);
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int srsran_basic_vnf::handle_rx_data_ind(basic_vnf_api::rx_data_ind_msg_t* msg)
|
||||
{
|
||||
logger.info("Received %s for TTI=%d", basic_vnf_api::msg_type_text[msg->header.type], msg->sfn);
|
||||
|
||||
if (msg->nof_pdus != 1 || msg->pdus[0].type != basic_vnf_api::PUSCH) {
|
||||
logger.error("Received UL indication for wrong PDU type");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// fill struct
|
||||
srsenb::stack_interface_phy_nr::rx_data_ind_t rx_data = {};
|
||||
rx_data.tti = msg->sfn;
|
||||
rx_data.tb = srsran::make_byte_buffer();
|
||||
if (rx_data.tb->get_tailroom() >= msg->pdus[0].length) {
|
||||
// copy actual data
|
||||
memcpy(rx_data.tb->msg, msg->pdus[0].data, msg->pdus[0].length);
|
||||
rx_data.tb->N_bytes = msg->pdus[0].length;
|
||||
if (msg->pdus[0].type == basic_vnf_api::PUSCH) {
|
||||
m_gnb_stack->rx_data_indication(rx_data);
|
||||
}
|
||||
}
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int srsran_basic_vnf::dl_config_request(const srsenb::phy_interface_stack_nr::dl_config_request_t& request)
|
||||
{
|
||||
// Generate DL Config
|
||||
basic_vnf_api::dl_conf_msg_t dl_conf = {};
|
||||
dl_conf.header.type = basic_vnf_api::DL_CONFIG;
|
||||
dl_conf.header.msg_len = sizeof(dl_conf) - sizeof(basic_vnf_api::msg_header_t);
|
||||
|
||||
dl_conf.t1 = last_sf_indication_time; // play back the time
|
||||
dl_conf.t2 = 0xaa; // TODO: add timestamp
|
||||
dl_conf.tti = request.tti;
|
||||
dl_conf.beam_id = request.beam_id;
|
||||
|
||||
// Send entire struct
|
||||
uint32_t len = sizeof(dl_conf);
|
||||
|
||||
// Send it to PNF
|
||||
logger.info("Sending %s (%d B)", basic_vnf_api::msg_type_text[dl_conf.header.type], len);
|
||||
int n = 0;
|
||||
if ((n = sendto(sockfd, &dl_conf, len, MSG_CONFIRM, (struct sockaddr*)&client_addr, sizeof(client_addr))) < 0) {
|
||||
logger.error("sendto failed, ret=%d", n);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Tx request from UE, i.e. UL transmission
|
||||
int srsran_basic_vnf::tx_request(const srsue::phy_interface_stack_nr::tx_request_t& request)
|
||||
{
|
||||
// Generate Tx request
|
||||
m_tx_req_msg->header.type = basic_vnf_api::TX_REQUEST;
|
||||
m_tx_req_msg->header.msg_len = 0; // set further down
|
||||
|
||||
m_tx_req_msg->tti = request.tti;
|
||||
|
||||
m_tx_req_msg->nof_pdus = 1;
|
||||
m_tx_req_msg->pdus[0].index = 0;
|
||||
m_tx_req_msg->pdus[0].type = basic_vnf_api::PUSCH;
|
||||
m_tx_req_msg->pdus[0].length = request.tb_len;
|
||||
|
||||
if (request.tb_len <= MAX_PDU_SIZE) {
|
||||
// copy data from TB0
|
||||
memcpy(m_tx_req_msg->pdus[0].data, request.data, request.tb_len);
|
||||
} else {
|
||||
logger.error("Trying to send %d B PDU. Maximum size is %d B", request.tb_len, MAX_PDU_SIZE);
|
||||
}
|
||||
|
||||
// calculate actual length of
|
||||
uint32_t len = calc_full_msg_len(*m_tx_req_msg.get());
|
||||
|
||||
// update msg header length field
|
||||
m_tx_req_msg->header.msg_len = len - sizeof(basic_vnf_api::msg_header_t);
|
||||
|
||||
// Send it to PNF
|
||||
logger.info("Sending %s (%d B)", basic_vnf_api::msg_type_text[m_tx_req_msg->header.type], len);
|
||||
int n = 0;
|
||||
if ((n = sendto(sockfd, m_tx_req_msg.get(), len, MSG_CONFIRM, (struct sockaddr*)&client_addr, sizeof(client_addr))) <
|
||||
0) {
|
||||
logger.error("sendto failed, ret=%d", n);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int srsran_basic_vnf::tx_request(const srsenb::phy_interface_stack_nr::tx_request_t& request)
|
||||
{
|
||||
if (request.nof_pdus > MAX_NUM_PDUS) {
|
||||
logger.error("Trying to send %d PDUs but only %d supported", request.nof_pdus, MAX_NUM_PDUS);
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
if (request.nof_pdus == 0) {
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
// Generate Tx request
|
||||
m_tx_req_msg->header.type = basic_vnf_api::TX_REQUEST;
|
||||
m_tx_req_msg->header.msg_len = 0; // set further down
|
||||
|
||||
m_tx_req_msg->nof_pdus = request.nof_pdus;
|
||||
m_tx_req_msg->tti = request.tti;
|
||||
|
||||
for (uint32_t i = 0; i < m_tx_req_msg->nof_pdus; ++i) {
|
||||
if (request.pdus[i].length <= MAX_PDU_SIZE) {
|
||||
m_tx_req_msg->pdus[i].index = i;
|
||||
m_tx_req_msg->pdus[i].type = request.pdus[i].pbch.mib_present ? basic_vnf_api::MAC_PBCH : basic_vnf_api::PDSCH;
|
||||
m_tx_req_msg->pdus[i].length = request.pdus[i].length;
|
||||
// copy data from TB0
|
||||
memcpy(m_tx_req_msg->pdus[i].data, request.pdus[i].data[0], m_tx_req_msg->pdus[i].length);
|
||||
} else {
|
||||
logger.error("Trying to send %d B PDU. Maximum size is %d B", request.pdus[i].length, MAX_PDU_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
// calculate actual length of message
|
||||
uint32_t len = calc_full_msg_len(*m_tx_req_msg.get());
|
||||
|
||||
// update msg header length field
|
||||
m_tx_req_msg->header.msg_len = len - sizeof(basic_vnf_api::msg_header_t);
|
||||
|
||||
// Send it to PNF
|
||||
logger.info("Sending %s (%d B)", basic_vnf_api::msg_type_text[m_tx_req_msg->header.type], len);
|
||||
if (logger.debug.enabled()) {
|
||||
for (uint32_t i = 0; i < m_tx_req_msg->nof_pdus; ++i) {
|
||||
logger.debug(m_tx_req_msg->pdus[i].data,
|
||||
m_tx_req_msg->pdus[i].length,
|
||||
"Sending PDU %s:%d (%d bytes)",
|
||||
basic_vnf_api::msg_type_text[m_tx_req_msg->header.type],
|
||||
m_tx_req_msg->pdus[i].index,
|
||||
m_tx_req_msg->pdus[i].length);
|
||||
}
|
||||
}
|
||||
int n = 0;
|
||||
if ((n = sendto(sockfd, m_tx_req_msg.get(), len, MSG_CONFIRM, (struct sockaddr*)&client_addr, sizeof(client_addr))) <
|
||||
0) {
|
||||
logger.error("sendto failed, ret=%d", n);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t srsran_basic_vnf::calc_full_msg_len(const basic_vnf_api::tx_request_msg_t& msg)
|
||||
{
|
||||
// start with mandatory part
|
||||
uint32_t len = sizeof(basic_vnf_api::msg_header_t) + 3 * sizeof(uint32_t);
|
||||
|
||||
// add all PDUs
|
||||
for (uint32_t i = 0; i < msg.nof_pdus; ++i) {
|
||||
len += 2 * sizeof(uint16_t) + sizeof(basic_vnf_api::pdu_type_t) + msg.pdus[i].length;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
bool srsran_basic_vnf::stop()
|
||||
{
|
||||
if (running) {
|
||||
running = false;
|
||||
wait_thread_finish();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace srsran
|
|
@ -172,7 +172,7 @@ void phy_cfg_nr_default_t::make_harq_auto(srsran_harq_ack_cfg_hl_t& harq,
|
|||
const srsran_tdd_config_nr_t& tdd_cfg)
|
||||
{
|
||||
// Generate as many entries as DL slots
|
||||
harq.nof_dl_data_to_ul_ack = SRSRAN_MAX(tdd_cfg.pattern1.nof_dl_slots, SRSRAN_MAX_NOF_DL_DATA_TO_UL);
|
||||
harq.nof_dl_data_to_ul_ack = SRSRAN_MIN(tdd_cfg.pattern1.nof_dl_slots, SRSRAN_MAX_NOF_DL_DATA_TO_UL);
|
||||
|
||||
// Set PDSCH to ACK timing delay to 4 or more
|
||||
for (uint32_t n = 0; n < harq.nof_dl_data_to_ul_ack; n++) {
|
||||
|
@ -206,6 +206,7 @@ void phy_cfg_nr_default_t::make_prach_default_lte(srsran_prach_cfg_t& prach)
|
|||
prach.config_idx = 0;
|
||||
prach.freq_offset = 2;
|
||||
prach.root_seq_idx = 0;
|
||||
prach.is_nr = true;
|
||||
}
|
||||
|
||||
phy_cfg_nr_default_t::phy_cfg_nr_default_t(const reference_cfg_t& reference_cfg)
|
||||
|
|
|
@ -848,6 +848,13 @@ static inline int pusch_nr_decode_codeword(srsran_pusch_nr_t* q,
|
|||
|
||||
// Demultiplex UCI only if necessary
|
||||
if (q->uci_mux) {
|
||||
// As it can be HARQ-ACK takes LLRs from ULSCH, demultiplex HARQ-ACK first
|
||||
int8_t* g_ack = (int8_t*)q->g_ack;
|
||||
for (uint32_t i = 0; i < q->G_ack; i++) {
|
||||
g_ack[i] = llr[q->pos_ack[i]];
|
||||
llr[q->pos_ack[i]] = 0;
|
||||
}
|
||||
|
||||
// Demultiplex UL-SCH, change sign
|
||||
int8_t* g_ulsch = (int8_t*)q->g_ulsch;
|
||||
for (uint32_t i = 0; i < q->G_ulsch; i++) {
|
||||
|
@ -857,12 +864,6 @@ static inline int pusch_nr_decode_codeword(srsran_pusch_nr_t* q,
|
|||
g_ulsch[i] = 0;
|
||||
}
|
||||
|
||||
// Demultiplex HARQ-ACK
|
||||
int8_t* g_ack = (int8_t*)q->g_ack;
|
||||
for (uint32_t i = 0; i < q->G_ack; i++) {
|
||||
g_ack[i] = llr[q->pos_ack[i]];
|
||||
}
|
||||
|
||||
// Demultiplex CSI part 1
|
||||
int8_t* g_csi1 = (int8_t*)q->g_csi1;
|
||||
for (uint32_t i = 0; i < q->G_csi1; i++) {
|
||||
|
|
|
@ -1049,6 +1049,12 @@ int srsran_ra_ul_set_grant_uci_nr(const srsran_carrier_nr_t* carrier,
|
|||
for (uint32_t i = 0; i < SRSRAN_MAX_TB; i++) {
|
||||
pusch_cfg->grant.tb[i].nof_bits =
|
||||
pusch_cfg->grant.tb[i].nof_re * srsran_mod_bits_x_symbol(pusch_cfg->grant.tb[i].mod) - Gack - Gcsi1 - Gcsi2;
|
||||
|
||||
if (pusch_cfg->grant.tb[i].nof_bits > 0) {
|
||||
pusch_cfg->grant.tb[i].R_prime = (double)pusch_cfg->grant.tb[i].tbs / (double)pusch_cfg->grant.tb[i].nof_bits;
|
||||
} else {
|
||||
pusch_cfg->grant.tb[i].R_prime = NAN;
|
||||
}
|
||||
}
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
|
|
|
@ -539,7 +539,7 @@ int srsran_ra_ul_nr_pucch_resource(const srsran_pucch_nr_hl_cfg_t* pucch_cfg,
|
|||
// - At least one positive SR
|
||||
// - up to 2 HARQ-ACK
|
||||
// - No CSI report
|
||||
if (uci_cfg->pucch.sr_positive_present > 0 && uci_cfg->ack.count <= SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS &&
|
||||
if (uci_cfg->sr_positive_present > 0 && uci_cfg->ack.count <= SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS &&
|
||||
uci_cfg->nof_csi == 0) {
|
||||
uint32_t sr_resource_id = uci_cfg->pucch.sr_resource_id;
|
||||
if (sr_resource_id >= SRSRAN_PUCCH_MAX_NOF_SR_RESOURCES) {
|
||||
|
|
|
@ -655,19 +655,10 @@ static int sch_nr_decode(srsran_sch_nr_t* q,
|
|||
nof_iter_sum += n_iter_cb;
|
||||
|
||||
// Check if CB is all zeros
|
||||
uint32_t cb_len = cfg.Kp - cfg.L_cb;
|
||||
bool all_zeros = true;
|
||||
for (uint32_t i = 0; i < cb_len && all_zeros; i++) {
|
||||
all_zeros = (q->temp_cb[i] == 0);
|
||||
}
|
||||
uint32_t cb_len = cfg.Kp - cfg.L_cb;
|
||||
|
||||
tb->softbuffer.rx->cb_crc[r] = (ret != 0) && (!all_zeros);
|
||||
SCH_INFO_RX("CB %d/%d iter=%d CRC=%s all_zeros=%s",
|
||||
r,
|
||||
cfg.C,
|
||||
n_iter_cb,
|
||||
tb->softbuffer.rx->cb_crc[r] ? "OK" : "KO",
|
||||
all_zeros ? "yes" : "no");
|
||||
tb->softbuffer.rx->cb_crc[r] = (ret != 0);
|
||||
SCH_INFO_RX("CB %d/%d iter=%d CRC=%s", r, cfg.C, n_iter_cb, tb->softbuffer.rx->cb_crc[r] ? "OK" : "KO");
|
||||
|
||||
// CB Debug trace
|
||||
if (SRSRAN_DEBUG_ENABLED && srsran_verbose >= SRSRAN_VERBOSE_DEBUG && !handler_registered) {
|
||||
|
@ -789,7 +780,7 @@ int srsran_sch_nr_tb_info(const srsran_sch_tb_t* tb, const srsran_sch_tb_res_nr_
|
|||
tb->cw_idx,
|
||||
srsran_mod_string(tb->mod),
|
||||
tb->tbs / 8,
|
||||
tb->R,
|
||||
tb->R_prime,
|
||||
tb->rv);
|
||||
|
||||
if (res != NULL) {
|
||||
|
|
|
@ -286,25 +286,47 @@ int main(int argc, char** argv)
|
|||
goto clean_exit;
|
||||
}
|
||||
|
||||
float mse = 0.0f;
|
||||
// Check symbols Mean Square Error (MSE)
|
||||
uint32_t nof_re = srsran_ra_dl_nr_slot_nof_re(&pusch_cfg, &pusch_cfg.grant);
|
||||
for (uint32_t i = 0; i < pusch_cfg.grant.nof_layers; i++) {
|
||||
for (uint32_t j = 0; j < nof_re; j++) {
|
||||
mse += cabsf(pusch_tx.d[i][j] - pusch_rx.d[i][j]);
|
||||
}
|
||||
}
|
||||
if (nof_re * pusch_cfg.grant.nof_layers > 0) {
|
||||
mse = mse / (nof_re * pusch_cfg.grant.nof_layers);
|
||||
}
|
||||
if (mse > 0.001) {
|
||||
ERROR("MSE error (%f) is too high", mse);
|
||||
float mse = 0.0f;
|
||||
for (uint32_t i = 0; i < pusch_cfg.grant.nof_layers; i++) {
|
||||
printf("d_tx[%d]=", i);
|
||||
srsran_vec_fprint_c(stdout, pusch_tx.d[i], nof_re);
|
||||
printf("d_rx[%d]=", i);
|
||||
srsran_vec_fprint_c(stdout, pusch_rx.d[i], nof_re);
|
||||
for (uint32_t j = 0; j < nof_re; j++) {
|
||||
mse += cabsf(pusch_tx.d[i][j] - pusch_rx.d[i][j]);
|
||||
}
|
||||
}
|
||||
mse = mse / (nof_re * pusch_cfg.grant.nof_layers);
|
||||
if (mse > 0.001) {
|
||||
ERROR("MSE error (%f) is too high", mse);
|
||||
for (uint32_t i = 0; i < pusch_cfg.grant.nof_layers; i++) {
|
||||
printf("d_tx[%d]=", i);
|
||||
srsran_vec_fprint_c(stdout, pusch_tx.d[i], nof_re);
|
||||
printf("d_rx[%d]=", i);
|
||||
srsran_vec_fprint_c(stdout, pusch_rx.d[i], nof_re);
|
||||
}
|
||||
goto clean_exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Check Received SCH LLR match
|
||||
if (pusch_rx.G_ulsch > 0) {
|
||||
for (uint32_t i = 0; i < pusch_rx.G_ulsch; i++) {
|
||||
uint8_t rx_bit = (((int8_t*)pusch_rx.g_ulsch)[i]) < 0 ? 1 : 0;
|
||||
if (rx_bit == 0) {
|
||||
pusch_rx.g_ulsch[i] = pusch_tx.g_ulsch[i];
|
||||
} else {
|
||||
pusch_rx.g_ulsch[i] = rx_bit;
|
||||
}
|
||||
}
|
||||
if (memcmp(pusch_tx.g_ulsch, pusch_rx.g_ulsch, pusch_tx.G_ulsch) != 0) {
|
||||
printf("g_ulsch_tx=");
|
||||
srsran_vec_fprint_byte(stdout, pusch_tx.g_ulsch, pusch_tx.G_ulsch);
|
||||
printf("g_ulsch_rx=");
|
||||
srsran_vec_fprint_byte(stdout, pusch_rx.g_ulsch, pusch_tx.G_ulsch);
|
||||
// srsran_vec_fprint_bs(stdout, (int8_t*)pusch_rx.g_ulsch, pusch_rx.G_ulsch);
|
||||
|
||||
goto clean_exit;
|
||||
}
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
// Validate UL-SCH CRC check
|
||||
|
|
|
@ -989,7 +989,16 @@ uint32_t srsran_uci_nr_total_bits(const srsran_uci_cfg_nr_t* uci_cfg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
return uci_cfg->ack.count + uci_cfg->o_sr + srsran_csi_part1_nof_bits(uci_cfg->csi, uci_cfg->nof_csi);
|
||||
uint32_t o_csi = srsran_csi_part1_nof_bits(uci_cfg->csi, uci_cfg->nof_csi);
|
||||
|
||||
// According to 38.213 9.2.4 UE procedure for reporting SR
|
||||
// The UE transmits a PUCCH in the PUCCH resource for the corresponding SR configuration only when the UE transmits a
|
||||
// positive SR
|
||||
if (uci_cfg->ack.count == 0 && o_csi == 0 && !uci_cfg->sr_positive_present) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return uci_cfg->ack.count + uci_cfg->o_sr + o_csi;
|
||||
}
|
||||
|
||||
uint32_t srsran_uci_nr_info(const srsran_uci_data_nr_t* uci_data, char* str, uint32_t str_len)
|
||||
|
|
|
@ -183,13 +183,13 @@ int srsran_rf_open_multi(srsran_rf_t* h, char* args, uint32_t nof_channels)
|
|||
int srsran_rf_close(srsran_rf_t* rf)
|
||||
{
|
||||
// Stop gain thread
|
||||
pthread_mutex_lock(&rf->mutex);
|
||||
if (rf->thread_gain_run) {
|
||||
pthread_mutex_lock(&rf->mutex);
|
||||
rf->thread_gain_run = false;
|
||||
pthread_mutex_unlock(&rf->mutex);
|
||||
pthread_cond_signal(&rf->cond);
|
||||
pthread_join(rf->thread_gain, NULL);
|
||||
}
|
||||
pthread_mutex_unlock(&rf->mutex);
|
||||
pthread_cond_signal(&rf->cond);
|
||||
pthread_join(rf->thread_gain, NULL);
|
||||
|
||||
return ((rf_dev_t*)rf->dev)->srsran_rf_close(rf->handler);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "rf_helper.h"
|
||||
#include "srsran/phy/utils/debug.h"
|
||||
#include "srsran/phy/utils/vector.h"
|
||||
|
||||
#include "rf_uhd_generic.h"
|
||||
#include "rf_uhd_imp.h"
|
||||
|
@ -197,10 +198,12 @@ void suppress_handler(const char* x)
|
|||
// do nothing
|
||||
}
|
||||
|
||||
static cf_t zero_mem[64 * 1024] = {};
|
||||
static std::array<cf_t, 64 * 1024> zero_mem = {}; // For transmitting zeros
|
||||
static std::array<cf_t, 64 * 1024> dummy_mem = {}; // For receiving
|
||||
|
||||
static void log_overflow(rf_uhd_handler_t* h)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(h->tx_mutex);
|
||||
if (h->tx_state == RF_UHD_IMP_TX_STATE_BURST) {
|
||||
h->tx_state = RF_UHD_IMP_TX_STATE_END_OF_BURST;
|
||||
}
|
||||
|
@ -215,6 +218,7 @@ static void log_overflow(rf_uhd_handler_t* h)
|
|||
|
||||
static void log_late(rf_uhd_handler_t* h, bool is_rx)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(h->tx_mutex);
|
||||
if (h->tx_state == RF_UHD_IMP_TX_STATE_BURST) {
|
||||
h->tx_state = RF_UHD_IMP_TX_STATE_END_OF_BURST;
|
||||
}
|
||||
|
@ -563,13 +567,14 @@ void rf_uhd_flush_buffer(void* h)
|
|||
|
||||
// Set all pointers to zero buffer
|
||||
for (auto& i : data) {
|
||||
i = zero_mem;
|
||||
i = dummy_mem.data();
|
||||
}
|
||||
|
||||
// Receive until time out
|
||||
uhd::rx_metadata_t md;
|
||||
do {
|
||||
if (handler->uhd->receive(data, handler->rx_nof_samples, md, 0.0, false, rxd_samples) != UHD_ERROR_NONE) {
|
||||
uint32_t nsamples = SRSRAN_MIN(handler->rx_nof_samples, (uint32_t)dummy_mem.size());
|
||||
if (handler->uhd->receive(data, nsamples, md, 0.0, false, rxd_samples) != UHD_ERROR_NONE) {
|
||||
log_rx_error(handler);
|
||||
return;
|
||||
}
|
||||
|
@ -958,7 +963,7 @@ static inline int rf_uhd_imp_end_burst(rf_uhd_handler_t* handler)
|
|||
|
||||
// Set buffer pointers
|
||||
for (int i = 0; i < SRSRAN_MAX_CHANNELS; i++) {
|
||||
buffs_ptr[i] = zero_mem;
|
||||
buffs_ptr[i] = zero_mem.data();
|
||||
}
|
||||
|
||||
// Set metadata
|
||||
|
@ -1270,13 +1275,19 @@ int rf_uhd_recv_with_time_multi(void* h,
|
|||
// Receive stream in multiple blocks
|
||||
while (rxd_samples_total < nsamples and trials < RF_UHD_IMP_MAX_RX_TRIALS) {
|
||||
void* buffs_ptr[SRSRAN_MAX_CHANNELS] = {};
|
||||
for (uint32_t i = 0; i < handler->nof_rx_channels; i++) {
|
||||
cf_t* data_c = (cf_t*)data[i];
|
||||
buffs_ptr[i] = &data_c[rxd_samples_total];
|
||||
}
|
||||
|
||||
size_t num_samps_left = nsamples - rxd_samples_total;
|
||||
size_t num_rx_samples = (num_samps_left > handler->rx_nof_samples) ? handler->rx_nof_samples : num_samps_left;
|
||||
size_t num_rx_samples = SRSRAN_MIN(handler->rx_nof_samples, num_samps_left);
|
||||
|
||||
for (uint32_t i = 0; i < handler->nof_rx_channels; i++) {
|
||||
if (data[i] != nullptr) {
|
||||
cf_t* data_c = (cf_t*)data[i];
|
||||
buffs_ptr[i] = &data_c[rxd_samples_total];
|
||||
} else {
|
||||
buffs_ptr[i] = dummy_mem.data();
|
||||
num_rx_samples = SRSRAN_MIN(num_rx_samples, (uint32_t)dummy_mem.size());
|
||||
}
|
||||
}
|
||||
|
||||
if (handler->uhd->receive(buffs_ptr, num_rx_samples, md, 1.0, false, rxd_samples) != UHD_ERROR_NONE) {
|
||||
log_rx_error(handler);
|
||||
|
@ -1388,9 +1399,9 @@ int rf_uhd_send_timed_multi(void* h,
|
|||
cf_t* data_c[SRSRAN_MAX_CHANNELS] = {};
|
||||
for (uint32_t i = 0; i < SRSRAN_MAX_CHANNELS; i++) {
|
||||
if (i < handler->nof_tx_channels) {
|
||||
data_c[i] = (data[i] != nullptr) ? (cf_t*)(data[i]) : zero_mem;
|
||||
data_c[i] = (data[i] != nullptr) ? (cf_t*)(data[i]) : zero_mem.data();
|
||||
} else {
|
||||
data_c[i] = zero_mem;
|
||||
data_c[i] = zero_mem.data();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -988,6 +988,7 @@ srsran_rf_info_t* radio::get_info()
|
|||
|
||||
bool radio::get_metrics(rf_metrics_t* metrics)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(metrics_mutex);
|
||||
*metrics = rf_metrics;
|
||||
rf_metrics = {};
|
||||
return true;
|
||||
|
@ -999,8 +1000,11 @@ void radio::handle_rf_msg(srsran_rf_error_t error)
|
|||
return;
|
||||
}
|
||||
if (error.type == srsran_rf_error_t::SRSRAN_RF_ERROR_OVERFLOW) {
|
||||
rf_metrics.rf_o++;
|
||||
rf_metrics.rf_error = true;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(metrics_mutex);
|
||||
rf_metrics.rf_o++;
|
||||
rf_metrics.rf_error = true;
|
||||
}
|
||||
logger.info("Overflow");
|
||||
|
||||
// inform PHY about overflow
|
||||
|
@ -1008,13 +1012,15 @@ void radio::handle_rf_msg(srsran_rf_error_t error)
|
|||
phy->radio_overflow();
|
||||
}
|
||||
} else if (error.type == srsran_rf_error_t::SRSRAN_RF_ERROR_UNDERFLOW) {
|
||||
logger.info("Underflow");
|
||||
std::lock_guard<std::mutex> lock(metrics_mutex);
|
||||
rf_metrics.rf_u++;
|
||||
rf_metrics.rf_error = true;
|
||||
logger.info("Underflow");
|
||||
} else if (error.type == srsran_rf_error_t::SRSRAN_RF_ERROR_LATE) {
|
||||
logger.info("Late (detected in %s)", error.opt ? "rx call" : "asynchronous thread");
|
||||
std::lock_guard<std::mutex> lock(metrics_mutex);
|
||||
rf_metrics.rf_l++;
|
||||
rf_metrics.rf_error = true;
|
||||
logger.info("Late (detected in %s)", error.opt ? "rx call" : "asynchronous thread");
|
||||
} else if (error.type == srsran_rf_error_t::SRSRAN_RF_ERROR_RX) {
|
||||
logger.error("Fatal radio error occured.");
|
||||
phy->radio_failure();
|
||||
|
|
|
@ -52,7 +52,7 @@ static void format_metadata(const detail::log_entry_metadata& metadata, fmt::mem
|
|||
std::tm current_time = fmt::gmtime(std::chrono::high_resolution_clock::to_time_t(metadata.tp));
|
||||
auto us_fraction =
|
||||
std::chrono::duration_cast<std::chrono::microseconds>(metadata.tp.time_since_epoch()).count() % 1000000u;
|
||||
fmt::format_to(buffer, "{:%H:%M:%S}.{:06} ", current_time, us_fraction);
|
||||
fmt::format_to(buffer, "{:%F}T{:%H:%M:%S}.{:06} ", current_time, current_time, us_fraction);
|
||||
|
||||
// Format optional fields if present.
|
||||
if (!metadata.log_name.empty()) {
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSLOG_SYSLOG_SINK_H
|
||||
#define SRSLOG_SYSLOG_SINK_H
|
||||
|
||||
#include "srsran/srslog/shared_types.h"
|
||||
#include "srsran/srslog/sink.h"
|
||||
#include <syslog.h>
|
||||
|
||||
namespace srslog {
|
||||
|
||||
/// This sink implementation writes to syslog.
|
||||
class syslog_sink : public sink
|
||||
{
|
||||
public:
|
||||
syslog_sink(std::unique_ptr<log_formatter> f,
|
||||
std::string preamble_ = "",
|
||||
syslog_local_type log_local_ = syslog_local_type::local0) :
|
||||
sink(std::move(f))
|
||||
{
|
||||
create_syslog(preamble_, syslog_translate(log_local_));
|
||||
}
|
||||
|
||||
syslog_sink(const syslog_sink& other) = delete;
|
||||
syslog_sink& operator=(const syslog_sink& other) = delete;
|
||||
|
||||
detail::error_string write(detail::memory_buffer buffer) override
|
||||
{
|
||||
std::string entry(buffer.data(), buffer.size());
|
||||
if (entry.find("[E]") != std::string::npos) {
|
||||
syslog(LOG_ERR, "%s", buffer.data());
|
||||
} else if (entry.find("[W]") != std::string::npos) {
|
||||
syslog(LOG_WARNING, "%s", buffer.data());
|
||||
} else if (entry.find("[I]") != std::string::npos) {
|
||||
syslog(LOG_INFO, "%s", buffer.data());
|
||||
} else if (entry.find("[D]") != std::string::npos) {
|
||||
syslog(LOG_DEBUG, "%s", buffer.data());
|
||||
} else {
|
||||
syslog(LOG_ERR, "%s", buffer.data());
|
||||
}
|
||||
// openlog syslog does not return any value.
|
||||
return {};
|
||||
}
|
||||
|
||||
detail::error_string flush() override { return {}; }
|
||||
|
||||
private:
|
||||
/// Creates a new syslog
|
||||
detail::error_string create_syslog(std::string preamble, int log_local)
|
||||
{
|
||||
if (preamble == "") {
|
||||
openlog(NULL, LOG_CONS | LOG_PID | LOG_NDELAY, log_local);
|
||||
} else {
|
||||
openlog(preamble.c_str(), LOG_CONS | LOG_PID | LOG_NDELAY, log_local);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
static int syslog_translate(syslog_local_type log_local)
|
||||
{
|
||||
switch (log_local) {
|
||||
case syslog_local_type::local0:
|
||||
return LOG_LOCAL0;
|
||||
case syslog_local_type::local1:
|
||||
return LOG_LOCAL1;
|
||||
case syslog_local_type::local2:
|
||||
return LOG_LOCAL2;
|
||||
case syslog_local_type::local3:
|
||||
return LOG_LOCAL3;
|
||||
case syslog_local_type::local4:
|
||||
return LOG_LOCAL4;
|
||||
case syslog_local_type::local5:
|
||||
return LOG_LOCAL5;
|
||||
case syslog_local_type::local6:
|
||||
return LOG_LOCAL6;
|
||||
case syslog_local_type::local7:
|
||||
return LOG_LOCAL7;
|
||||
default:
|
||||
return LOG_LOCAL0;
|
||||
break;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace srslog
|
||||
|
||||
#endif // SRSLOG_SYSLOG_SINK_H
|
|
@ -22,6 +22,7 @@
|
|||
#include "srsran/srslog/srslog.h"
|
||||
#include "formatters/json_formatter.h"
|
||||
#include "sinks/file_sink.h"
|
||||
#include "sinks/syslog_sink.h"
|
||||
#include "srslog_instance.h"
|
||||
|
||||
using namespace srslog;
|
||||
|
@ -174,6 +175,25 @@ sink& srslog::fetch_file_sink(const std::string& path, size_t max_size, std::uni
|
|||
return *s;
|
||||
}
|
||||
|
||||
sink& srslog::fetch_syslog_sink(const std::string& preamble_,
|
||||
syslog_local_type log_local_,
|
||||
std::unique_ptr<log_formatter> f)
|
||||
{
|
||||
std::string sink_id = preamble_ + std::to_string(static_cast<int>(log_local_));
|
||||
if (auto* s = find_sink(sink_id)) {
|
||||
return *s;
|
||||
}
|
||||
|
||||
//: TODO: GCC5 or lower versions emits an error if we use the new() expression
|
||||
// directly, use redundant piecewise_construct instead.
|
||||
auto& s = srslog_instance::get().get_sink_repo().emplace(
|
||||
std::piecewise_construct,
|
||||
std::forward_as_tuple(sink_id),
|
||||
std::forward_as_tuple(new syslog_sink(std::move(f), preamble_, log_local_)));
|
||||
|
||||
return *s;
|
||||
}
|
||||
|
||||
bool srslog::install_custom_sink(const std::string& id, std::unique_ptr<sink> s)
|
||||
{
|
||||
assert(!id.empty() && "Empty path string");
|
||||
|
|
|
@ -85,11 +85,5 @@ add_executable(task_scheduler_test task_scheduler_test.cc)
|
|||
target_link_libraries(task_scheduler_test srsran_common ${ATOMIC_LIBS})
|
||||
add_test(task_scheduler_test task_scheduler_test)
|
||||
|
||||
add_executable(pnf_dummy pnf_dummy.cc)
|
||||
target_link_libraries(pnf_dummy srsran_common ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||
|
||||
add_executable(pnf_bridge pnf_bridge.cc)
|
||||
target_link_libraries(pnf_bridge srsran_common ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||
|
||||
add_executable(mac_pcap_net_test mac_pcap_net_test.cc)
|
||||
target_link_libraries(mac_pcap_net_test srsran_common ${SCTP_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
|
||||
|
|
|
@ -1,127 +0,0 @@
|
|||
/**
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* This file is part of srsRAN.
|
||||
*
|
||||
* srsRAN is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* srsRAN is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* A copy of the GNU Affero General Public License can be found in
|
||||
* the LICENSE file in the top-level directory of this distribution
|
||||
* and at http://www.gnu.org/licenses/.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/program_options/parsers.hpp>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <signal.h>
|
||||
#include <thread>
|
||||
|
||||
#include "srsran/common/basic_pnf.h"
|
||||
|
||||
using namespace std;
|
||||
namespace bpo = boost::program_options;
|
||||
|
||||
struct pnf_args_t {
|
||||
std::string gnb_vnf_addr;
|
||||
std::string ue_vnf_addr;
|
||||
uint16_t gnb_vnf_port;
|
||||
uint16_t ue_vnf_port;
|
||||
uint32_t sf_interval;
|
||||
int32_t num_sf;
|
||||
uint32_t tb_len;
|
||||
};
|
||||
|
||||
void parse_args(pnf_args_t* args, int argc, char* argv[])
|
||||
{
|
||||
// Command line only options
|
||||
bpo::options_description general("General options");
|
||||
|
||||
general.add_options()("help,h", "Produce help message")("version,v", "Print version information and exit");
|
||||
|
||||
// Command line or config file options
|
||||
bpo::options_description common("Configuration options");
|
||||
|
||||
// clang-format off
|
||||
common.add_options()
|
||||
("vnf.gnb_addr", bpo::value<string>(&args->gnb_vnf_addr)->default_value("127.0.0.1"), "VNF address")
|
||||
("vnf.ue_addr", bpo::value<string>(&args->ue_vnf_addr)->default_value("127.0.0.1"), "VNF address")
|
||||
("vnf.gnb_port", bpo::value<uint16_t>(&args->gnb_vnf_port)->default_value(3333), "gNB VNF port")
|
||||
("vnf.ue_port", bpo::value<uint16_t>(&args->ue_vnf_port)->default_value(3334), "UE VNF port")
|
||||
("sf_interval", bpo::value<uint32_t>(&args->sf_interval)->default_value(1000), "Interval between subframes in us")
|
||||
("num_sf", bpo::value<int32_t>(&args->num_sf)->default_value(-1), "Number of subframes to signal (-1 infinity)")
|
||||
("tb_len", bpo::value<uint32_t>(&args->tb_len)->default_value(1600), "TB lenth (0 for random size)");
|
||||
// clang-format on
|
||||
|
||||
// these options are allowed on the command line
|
||||
bpo::options_description cmdline_options;
|
||||
cmdline_options.add(common).add(general);
|
||||
|
||||
// parse the command line and store result in vm
|
||||
bpo::variables_map vm;
|
||||
bpo::store(bpo::command_line_parser(argc, argv).options(cmdline_options).run(), vm);
|
||||
bpo::notify(vm);
|
||||
|
||||
// help option was given - print usage and exit
|
||||
if (vm.count("help")) {
|
||||
cout << "Usage: " << argv[0] << " [OPTIONS] config_file" << endl << endl;
|
||||
cout << common << endl << general << endl;
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
bool running = true;
|
||||
void sig_int_handler(int signo)
|
||||
{
|
||||
printf("SIGINT received. Exiting...\n");
|
||||
if (signo == SIGINT) {
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
signal(SIGINT, sig_int_handler);
|
||||
|
||||
pnf_args_t args;
|
||||
parse_args(&args, argc, argv);
|
||||
|
||||
srsran::srsran_basic_pnf ue_pnf("ue", args.ue_vnf_addr, args.ue_vnf_port, args.sf_interval, args.num_sf, args.tb_len);
|
||||
srsran::srsran_basic_pnf gnb_pnf(
|
||||
"gnb", args.gnb_vnf_addr, args.gnb_vnf_port, args.sf_interval, args.num_sf, args.tb_len);
|
||||
|
||||
gnb_pnf.connect_out_rf_queue(ue_pnf.get_in_rf_queue());
|
||||
|
||||
ue_pnf.start();
|
||||
gnb_pnf.start();
|
||||
|
||||
while (running) {
|
||||
for (uint32_t i = 0; i < 2; ++i) {
|
||||
srsran::pnf_metrics_t metrics = (i == 0) ? ue_pnf.get_metrics() : gnb_pnf.get_metrics();
|
||||
printf("%s: RTT=%d, #Error=%d, #PDUs=%d, Total TB size=%d, Rate=%.2f Mbit/s\n",
|
||||
i == 0 ? "UE" : "gNB",
|
||||
metrics.avg_rtt_us,
|
||||
metrics.num_timing_errors,
|
||||
metrics.num_pdus,
|
||||
metrics.tb_size,
|
||||
metrics.tb_size * 8 / 1.0e6);
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
|
||||
ue_pnf.stop();
|
||||
gnb_pnf.stop();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,117 +0,0 @@
|
|||
/**
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* This file is part of srsRAN.
|
||||
*
|
||||
* srsRAN is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* srsRAN is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* A copy of the GNU Affero General Public License can be found in
|
||||
* the LICENSE file in the top-level directory of this distribution
|
||||
* and at http://www.gnu.org/licenses/.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/program_options/parsers.hpp>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <signal.h>
|
||||
#include <thread>
|
||||
|
||||
#include "srsran/common/basic_pnf.h"
|
||||
|
||||
using namespace std;
|
||||
namespace bpo = boost::program_options;
|
||||
|
||||
struct pnf_args_t {
|
||||
std::string type;
|
||||
std::string vnf_addr;
|
||||
uint16_t vnf_port;
|
||||
uint32_t sf_interval;
|
||||
int32_t num_sf;
|
||||
uint32_t tb_len;
|
||||
};
|
||||
|
||||
void parse_args(pnf_args_t* args, int argc, char* argv[])
|
||||
{
|
||||
// Command line only options
|
||||
bpo::options_description general("General options");
|
||||
|
||||
general.add_options()("help,h", "Produce help message")("version,v", "Print version information and exit");
|
||||
|
||||
// Command line or config file options
|
||||
bpo::options_description common("Configuration options");
|
||||
|
||||
// clang-format off
|
||||
common.add_options()
|
||||
("vnf.type", bpo::value<string>(&args->type)->default_value("gnb"), "VNF instance type [gnb,ue]")
|
||||
("vnf.addr", bpo::value<string>(&args->vnf_addr)->default_value("127.0.0.1"), "VNF address")
|
||||
("vnf.port", bpo::value<uint16_t>(&args->vnf_port)->default_value(3333), "VNF port")
|
||||
("sf_interval", bpo::value<uint32_t>(&args->sf_interval)->default_value(1000), "Interval between subframes in us")
|
||||
("num_sf", bpo::value<int32_t>(&args->num_sf)->default_value(-1), "Number of subframes to signal (-1 infinity)")
|
||||
("tb_len", bpo::value<uint32_t>(&args->tb_len)->default_value(0), "TB lenth (0 for random size)");
|
||||
|
||||
// clang-format on
|
||||
|
||||
// these options are allowed on the command line
|
||||
bpo::options_description cmdline_options;
|
||||
cmdline_options.add(common).add(general);
|
||||
|
||||
// parse the command line and store result in vm
|
||||
bpo::variables_map vm;
|
||||
bpo::store(bpo::command_line_parser(argc, argv).options(cmdline_options).run(), vm);
|
||||
bpo::notify(vm);
|
||||
|
||||
// help option was given - print usage and exit
|
||||
if (vm.count("help")) {
|
||||
cout << "Usage: " << argv[0] << " [OPTIONS] config_file" << endl << endl;
|
||||
cout << common << endl << general << endl;
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
bool running = true;
|
||||
void sig_int_handler(int signo)
|
||||
{
|
||||
printf("SIGINT received. Exiting...\n");
|
||||
if (signo == SIGINT) {
|
||||
running = false;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
signal(SIGINT, sig_int_handler);
|
||||
|
||||
pnf_args_t args;
|
||||
parse_args(&args, argc, argv);
|
||||
|
||||
srsran::srsran_basic_pnf pnf(args.type, args.vnf_addr, args.vnf_port, args.sf_interval, args.num_sf, args.tb_len);
|
||||
|
||||
pnf.start();
|
||||
|
||||
while (running) {
|
||||
srsran::pnf_metrics_t metrics = pnf.get_metrics();
|
||||
printf("RTT=%d, #Error=%d, #PDUs=%d, Total TB size=%d, Rate=%.2f Mbit/s\n",
|
||||
metrics.avg_rtt_us,
|
||||
metrics.num_timing_errors,
|
||||
metrics.num_pdus,
|
||||
metrics.tb_size,
|
||||
metrics.tb_size * 8 / 1e6);
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
|
||||
pnf.stop();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -47,6 +47,10 @@ target_include_directories(file_sink_test PUBLIC ../../)
|
|||
target_link_libraries(file_sink_test srslog)
|
||||
add_test(file_sink_test file_sink_test)
|
||||
|
||||
add_executable(syslog_sink_test syslog_sink_test.cpp)
|
||||
target_include_directories(syslog_sink_test PUBLIC ../../)
|
||||
target_link_libraries(syslog_sink_test srslog)
|
||||
|
||||
add_executable(file_utils_test file_utils_test.cpp)
|
||||
target_include_directories(file_utils_test PUBLIC ../../)
|
||||
target_link_libraries(file_utils_test srslog)
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "src/srslog/sinks/syslog_sink.h"
|
||||
#include "srsran/srslog/srslog.h"
|
||||
#include "test_dummies.h"
|
||||
#include "testing_helpers.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
using namespace srslog;
|
||||
|
||||
/// Syslog sink name.
|
||||
static constexpr char sink_name[] = "srslog_syslog_sink";
|
||||
|
||||
static bool find_string_infile(std::string filename, std::string pattern)
|
||||
{
|
||||
std::ifstream file(filename);
|
||||
std::string line;
|
||||
bool found = false;
|
||||
|
||||
if (file.is_open()) {
|
||||
while (std::getline(file, line)) {
|
||||
if (line.find(pattern) != std::string::npos) { // WILL SEARCH 2015-1113 in file
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("WARNING: Could not open file %s", filename.c_str());
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
static bool syslog_basic_test()
|
||||
{
|
||||
syslog_sink syslog_sink(get_default_log_formatter());
|
||||
|
||||
// Build a 1000 byte entry.
|
||||
std::string entry(1000, 'a');
|
||||
|
||||
syslog_sink.write(detail::memory_buffer(entry));
|
||||
|
||||
syslog_sink.flush();
|
||||
|
||||
ASSERT_EQ(find_string_infile("/var/log/syslog", entry), true);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
TEST_FUNCTION(syslog_basic_test);
|
||||
return 0;
|
||||
}
|
|
@ -46,7 +46,7 @@ static bool when_fully_filled_log_entry_then_everything_is_formatted()
|
|||
fmt::dynamic_format_arg_store<fmt::printf_context> store;
|
||||
text_formatter{}.format(build_log_entry_metadata(&store), buffer);
|
||||
std::string result = fmt::to_string(buffer);
|
||||
std::string expected = "00:00:00.050000 [ABC ] [Z] [ 10] Text 88\n";
|
||||
std::string expected = "1970-01-01T00:00:00.050000 [ABC ] [Z] [ 10] Text 88\n";
|
||||
|
||||
ASSERT_EQ(result, expected);
|
||||
|
||||
|
@ -62,7 +62,7 @@ static bool when_log_entry_without_name_is_passed_then_name_is_not_formatted()
|
|||
fmt::memory_buffer buffer;
|
||||
text_formatter{}.format(std::move(entry), buffer);
|
||||
std::string result = fmt::to_string(buffer);
|
||||
std::string expected = "00:00:00.050000 [Z] [ 10] Text 88\n";
|
||||
std::string expected = "1970-01-01T00:00:00.050000 [Z] [ 10] Text 88\n";
|
||||
|
||||
ASSERT_EQ(result, expected);
|
||||
|
||||
|
@ -78,7 +78,7 @@ static bool when_log_entry_without_tag_is_passed_then_tag_is_not_formatted()
|
|||
fmt::memory_buffer buffer;
|
||||
text_formatter{}.format(std::move(entry), buffer);
|
||||
std::string result = fmt::to_string(buffer);
|
||||
std::string expected = "00:00:00.050000 [ABC ] [ 10] Text 88\n";
|
||||
std::string expected = "1970-01-01T00:00:00.050000 [ABC ] [ 10] Text 88\n";
|
||||
|
||||
ASSERT_EQ(result, expected);
|
||||
|
||||
|
@ -94,7 +94,7 @@ static bool when_log_entry_without_context_is_passed_then_context_is_not_formatt
|
|||
fmt::memory_buffer buffer;
|
||||
text_formatter{}.format(std::move(entry), buffer);
|
||||
std::string result = fmt::to_string(buffer);
|
||||
std::string expected = "00:00:00.050000 [ABC ] [Z] Text 88\n";
|
||||
std::string expected = "1970-01-01T00:00:00.050000 [ABC ] [Z] Text 88\n";
|
||||
|
||||
ASSERT_EQ(result, expected);
|
||||
|
||||
|
@ -111,7 +111,7 @@ static bool when_log_entry_with_hex_dump_is_passed_then_hex_dump_is_formatted()
|
|||
fmt::memory_buffer buffer;
|
||||
text_formatter{}.format(std::move(entry), buffer);
|
||||
std::string result = fmt::to_string(buffer);
|
||||
std::string expected = "00:00:00.050000 [ABC ] [Z] [ 10] Text 88\n"
|
||||
std::string expected = "1970-01-01T00:00:00.050000 [ABC ] [Z] [ 10] Text 88\n"
|
||||
" 0000: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n"
|
||||
" 0010: 10 11 12 13\n";
|
||||
|
||||
|
@ -185,7 +185,7 @@ static bool when_log_entry_with_only_context_is_passed_then_context_is_formatted
|
|||
fmt::memory_buffer buffer;
|
||||
text_formatter{}.format_ctx(ctx, std::move(entry), buffer);
|
||||
std::string result = fmt::to_string(buffer);
|
||||
std::string expected = "00:00:00.050000 [ABC ] [Z] [ 10] Context dump for "
|
||||
std::string expected = "1970-01-01T00:00:00.050000 [ABC ] [Z] [ 10] Context dump for "
|
||||
"\"Complex Context\"\n"
|
||||
" > List: sector_list\n"
|
||||
" > Set: sector_metrics\n"
|
||||
|
@ -227,7 +227,7 @@ static bool when_log_entry_with_context_and_message_is_passed_then_context_is_fo
|
|||
fmt::memory_buffer buffer;
|
||||
text_formatter{}.format_ctx(ctx, std::move(entry), buffer);
|
||||
std::string result = fmt::to_string(buffer);
|
||||
std::string expected = "00:00:00.050000 [ABC ] [Z] [ 10] [[sector_metrics_type: event, "
|
||||
std::string expected = "1970-01-01T00:00:00.050000 [ABC ] [Z] [ 10] [[sector_metrics_type: event, "
|
||||
"sector_metrics_sector_id: 1, [ue_container_Throughput: 1.2 MB/s, "
|
||||
"ue_container_Address: 10.20.30.40, [RF_SNR: 5.1 dB, RF_PWR: -11 "
|
||||
"dBm][RF_SNR: 10.1 dB, RF_PWR: -20 dBm]][ue_container_Throughput: 10.2 "
|
||||
|
|
|
@ -53,6 +53,6 @@ add_subdirectory(test)
|
|||
# Default configuration files
|
||||
########################################################################
|
||||
install(FILES enb.conf.example DESTINATION ${DATA_DIR})
|
||||
install(FILES drb.conf.example DESTINATION ${DATA_DIR})
|
||||
install(FILES rr.conf.example DESTINATION ${DATA_DIR})
|
||||
install(FILES rb.conf.example DESTINATION ${DATA_DIR})
|
||||
install(FILES rr.conf.example DESTINATION ${DATA_DIR})
|
||||
install(FILES sib.conf.example DESTINATION ${DATA_DIR})
|
|
@ -36,12 +36,12 @@ n_prb = 50
|
|||
# sib_config: SIB1, SIB2 and SIB3 configuration file
|
||||
# note: when enabling mbms, use the sib.conf.mbsfn configuration file which includes SIB13
|
||||
# rr_config: Radio Resources configuration file
|
||||
# drb_config: DRB configuration file
|
||||
# rb_config: SRB/DRB configuration file
|
||||
#####################################################################
|
||||
[enb_files]
|
||||
sib_config = sib.conf
|
||||
rr_config = rr.conf
|
||||
drb_config = drb.conf
|
||||
rb_config = rb.conf
|
||||
|
||||
#####################################################################
|
||||
# RF configuration
|
||||
|
@ -180,6 +180,7 @@ enable = false
|
|||
# init_ul_snr_value: Initial UL SNR value used for computing MCS in the first UL grant
|
||||
# init_dl_cqi: DL CQI value used before any CQI report is available to the eNB
|
||||
# max_sib_coderate: Upper bound on SIB and RAR grants coderate
|
||||
# pdcch_cqi_offset: CQI offset in derivation of PDCCH aggregation level
|
||||
#
|
||||
#####################################################################
|
||||
[scheduler]
|
||||
|
@ -204,6 +205,7 @@ enable = false
|
|||
#init_ul_snr_value=5
|
||||
#init_dl_cqi=5
|
||||
#max_sib_coderate=0.3
|
||||
#pdcch_cqi_offset=0
|
||||
|
||||
#####################################################################
|
||||
# eMBMS configuration options
|
||||
|
@ -324,6 +326,7 @@ enable = false
|
|||
# tracing_enable: Write source code tracing information to a file.
|
||||
# tracing_filename: File path to use for tracing information.
|
||||
# tracing_buffcapacity: Maximum capacity in bytes the tracing framework can store.
|
||||
# stdout_ts_enable: Prints once per second the timestamp into stdout.
|
||||
# pregenerate_signals: Pregenerate uplink signals after attach. Improves CPU performance.
|
||||
# tx_amplitude: Transmit amplitude factor (set 0-1 to reduce PAPR)
|
||||
# rrc_inactivity_timer Inactivity timeout used to remove UE context from RRC (in milliseconds).
|
||||
|
@ -335,6 +338,8 @@ enable = false
|
|||
# gtpu_tunnel_timeout: Time that GTPU takes to release indirect forwarding tunnel since the last received GTPU PDU (0 for no timer).
|
||||
#ts1_reloc_prep_timeout: S1AP TS 36.413 TS1RelocPrep Expiry Timeout value in milliseconds
|
||||
#ts1_reloc_overall_timeout: S1AP TS 36.413 TS1RelocOverall Expiry Timeout value in milliseconds
|
||||
# rlf_release_timer_ms: Time taken by eNB to release UE context after it detects an RLF
|
||||
# rlf_min_ul_snr_estim: SNR threshold in dB below which the enb is notified with rlf ko
|
||||
#
|
||||
#####################################################################
|
||||
[expert]
|
||||
|
@ -351,6 +356,7 @@ enable = false
|
|||
#tracing_enable = true
|
||||
#tracing_filename = /tmp/enb_tracing.log
|
||||
#tracing_buffcapacity = 1000000
|
||||
#stdout_ts_enable = false
|
||||
#pregenerate_signals = false
|
||||
#tx_amplitude = 0.6
|
||||
#rrc_inactivity_timer = 30000
|
||||
|
@ -365,3 +371,5 @@ enable = false
|
|||
#extended_cp = false
|
||||
#ts1_reloc_prep_timeout = 10000
|
||||
#ts1_reloc_overall_timeout = 10000
|
||||
#rlf_release_timer_ms = 4000
|
||||
#rlf_min_ul_snr_estim = -2
|
||||
|
|
|
@ -71,7 +71,7 @@ struct enb_args_t {
|
|||
struct enb_files_t {
|
||||
std::string sib_config;
|
||||
std::string rr_config;
|
||||
std::string drb_config;
|
||||
std::string rb_config;
|
||||
};
|
||||
|
||||
struct log_args_t {
|
||||
|
|
|
@ -41,12 +41,11 @@ class slot_worker final : public srsran::thread_pool::worker
|
|||
{
|
||||
public:
|
||||
struct args_t {
|
||||
uint32_t cell_index = 0;
|
||||
srsran_carrier_nr_t carrier = {};
|
||||
uint32_t nof_tx_ports = 1;
|
||||
uint32_t nof_rx_ports = 1;
|
||||
uint32_t pusch_max_nof_iter = 10;
|
||||
srsran_pdcch_cfg_nr_t pdcch_cfg = {}; ///< PDCCH configuration
|
||||
uint32_t cell_index = 0;
|
||||
uint32_t nof_max_prb = SRSRAN_MAX_PRB_NR;
|
||||
uint32_t nof_tx_ports = 1;
|
||||
uint32_t nof_rx_ports = 1;
|
||||
uint32_t pusch_max_nof_iter = 10;
|
||||
};
|
||||
|
||||
slot_worker(srsran::phy_common_interface& common_, stack_interface_phy_nr& stack_, srslog::basic_logger& logger);
|
||||
|
@ -54,6 +53,8 @@ public:
|
|||
|
||||
bool init(const args_t& args);
|
||||
|
||||
bool set_common_cfg(const srsran_carrier_nr_t& carrier, const srsran_pdcch_cfg_nr_t& pdcch_cfg_);
|
||||
|
||||
/* Functions used by main PHY thread */
|
||||
cf_t* get_buffer_rx(uint32_t antenna_idx);
|
||||
cf_t* get_buffer_tx(uint32_t antenna_idx);
|
||||
|
|
|
@ -24,7 +24,9 @@
|
|||
|
||||
#include "slot_worker.h"
|
||||
#include "srsenb/hdr/phy/phy_interfaces.h"
|
||||
#include "srsenb/hdr/phy/prach_worker.h"
|
||||
#include "srsran/common/thread_pool.h"
|
||||
#include "srsran/interfaces/enb_mac_interfaces.h"
|
||||
#include "srsran/interfaces/gnb_interfaces.h"
|
||||
|
||||
namespace srsenb {
|
||||
|
@ -32,20 +34,71 @@ namespace nr {
|
|||
|
||||
class worker_pool
|
||||
{
|
||||
private:
|
||||
class prach_stack_adaptor_t : public stack_interface_phy_lte
|
||||
{
|
||||
private:
|
||||
stack_interface_phy_nr& stack;
|
||||
|
||||
public:
|
||||
prach_stack_adaptor_t(stack_interface_phy_nr& stack_) : stack(stack_)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
int sr_detected(uint32_t tti, uint16_t rnti) override { return 0; }
|
||||
void rach_detected(uint32_t tti, uint32_t primary_cc_idx, uint32_t preamble_idx, uint32_t time_adv) override
|
||||
{
|
||||
stack_interface_phy_nr::rach_info_t rach_info = {};
|
||||
rach_info.preamble = preamble_idx;
|
||||
rach_info.time_adv = time_adv;
|
||||
|
||||
stack.rach_detected(rach_info);
|
||||
}
|
||||
int ri_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t ri_value) override { return 0; }
|
||||
int pmi_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t pmi_value) override { return 0; }
|
||||
int cqi_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t cqi_value) override { return 0; }
|
||||
int snr_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, float snr_db, ul_channel_t ch) override { return 0; }
|
||||
int ta_info(uint32_t tti, uint16_t rnti, float ta_us) override { return 0; }
|
||||
int ack_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t tb_idx, bool ack) override { return 0; }
|
||||
int crc_info(uint32_t tti, uint16_t rnti, uint32_t cc_idx, uint32_t nof_bytes, bool crc_res) override { return 0; }
|
||||
int push_pdu(uint32_t tti_rx,
|
||||
uint16_t rnti,
|
||||
uint32_t enb_cc_idx,
|
||||
uint32_t nof_bytes,
|
||||
bool crc_res,
|
||||
uint32_t ul_nof_prbs) override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int get_dl_sched(uint32_t tti, dl_sched_list_t& dl_sched_res) override { return 0; }
|
||||
int get_mch_sched(uint32_t tti, bool is_mcch, dl_sched_list_t& dl_sched_res) override { return 0; }
|
||||
int get_ul_sched(uint32_t tti, ul_sched_list_t& ul_sched_res) override { return 0; }
|
||||
void set_sched_dl_tti_mask(uint8_t* tti_mask, uint32_t nof_sfs) override {}
|
||||
void tti_clock() override {}
|
||||
};
|
||||
|
||||
srsran::phy_common_interface& common;
|
||||
stack_interface_phy_nr& stack;
|
||||
srslog::sink& log_sink;
|
||||
srsran::thread_pool pool;
|
||||
std::vector<std::unique_ptr<slot_worker> > workers;
|
||||
prach_worker_pool prach;
|
||||
uint32_t current_tti = 0; ///< Current TTI, read and write from same thread
|
||||
srslog::basic_logger& logger;
|
||||
prach_stack_adaptor_t prach_stack_adaptor;
|
||||
|
||||
// Current configuration
|
||||
std::mutex common_cfg_mutex;
|
||||
srsran_carrier_nr_t carrier = {};
|
||||
srsran_pdcch_cfg_nr_t pdcch_cfg = {};
|
||||
|
||||
public:
|
||||
struct args_t {
|
||||
uint32_t nof_phy_threads = 3;
|
||||
uint32_t prio = 52;
|
||||
std::string log_level = "info";
|
||||
uint32_t log_hex_limit = 64;
|
||||
std::string log_id_preamble = "";
|
||||
uint32_t pusch_max_nof_iter = 10;
|
||||
uint32_t nof_phy_threads = 3;
|
||||
uint32_t prio = 52;
|
||||
uint32_t pusch_max_nof_iter = 10;
|
||||
srsran::phy_log_args_t log = {};
|
||||
};
|
||||
slot_worker* operator[](std::size_t pos) { return workers.at(pos).get(); }
|
||||
|
||||
|
@ -58,6 +111,7 @@ public:
|
|||
slot_worker* wait_worker_id(uint32_t id);
|
||||
void start_worker(slot_worker* w);
|
||||
void stop();
|
||||
int set_common_cfg(const phy_interface_rrc_nr::common_cfg_t& common_cfg);
|
||||
};
|
||||
|
||||
} // namespace nr
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
/**
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* This file is part of srsRAN.
|
||||
*
|
||||
* srsRAN is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* srsRAN is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* A copy of the GNU Affero General Public License can be found in
|
||||
* the LICENSE file in the top-level directory of this distribution
|
||||
* and at http://www.gnu.org/licenses/.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSGNB_NR_VNF_PHY_H
|
||||
#define SRSGNB_NR_VNF_PHY_H
|
||||
|
||||
#include "srsenb/hdr/phy/enb_phy_base.h"
|
||||
#include "srsenb/hdr/phy/phy_common.h"
|
||||
#include "srsran/common/basic_vnf.h"
|
||||
#include "srsran/interfaces/enb_metrics_interface.h"
|
||||
#include "srsran/interfaces/gnb_interfaces.h"
|
||||
#include "srsran/interfaces/radio_interfaces.h"
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
struct nr_phy_cfg_t {
|
||||
// TODO: add cell and RRC configs
|
||||
};
|
||||
|
||||
class vnf_phy_nr : public srsenb::enb_phy_base, public srsenb::phy_interface_stack_nr
|
||||
{
|
||||
public:
|
||||
vnf_phy_nr() = default;
|
||||
~vnf_phy_nr();
|
||||
|
||||
int init(const srsenb::phy_args_t& args, const nr_phy_cfg_t& cfg, srsenb::stack_interface_phy_nr* stack_);
|
||||
void stop() override;
|
||||
|
||||
std::string get_type() override { return "vnf"; };
|
||||
|
||||
void start_plot() override;
|
||||
|
||||
void get_metrics(std::vector<srsenb::phy_metrics_t>& metrics) override;
|
||||
|
||||
// MAC interface
|
||||
int dl_config_request(const dl_config_request_t& request) override;
|
||||
int tx_request(const tx_request_t& request) override;
|
||||
|
||||
void cmd_cell_gain(uint32_t cell_idx, float gain_db) override
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<srsran::srsran_basic_vnf> vnf = nullptr;
|
||||
|
||||
bool initialized = false;
|
||||
|
||||
void parse_config(const nr_phy_cfg_t& cfg);
|
||||
};
|
||||
|
||||
} // namespace srsenb
|
||||
|
||||
#endif // SRSGNB_NR_VNF_PHY_H
|
|
@ -86,6 +86,7 @@ public:
|
|||
int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) override;
|
||||
int pucch_info(const srsran_slot_cfg_t& slot_cfg, const pucch_info_t& pucch_info) override;
|
||||
int pusch_info(const srsran_slot_cfg_t& slot_cfg, const pusch_info_t& pusch_info) override;
|
||||
void rach_detected(const rach_info_t& rach_info) override;
|
||||
|
||||
private:
|
||||
void run_thread() final;
|
||||
|
|
|
@ -80,12 +80,9 @@ public:
|
|||
int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) override;
|
||||
int pucch_info(const srsran_slot_cfg_t& slot_cfg, const pucch_info_t& pucch_info) override;
|
||||
int pusch_info(const srsran_slot_cfg_t& slot_cfg, const pusch_info_t& pusch_info) override;
|
||||
void rach_detected(const rach_info_t& rach_info) override;
|
||||
|
||||
private:
|
||||
void get_dl_config(const uint32_t tti,
|
||||
phy_interface_stack_nr::dl_config_request_t& config_request,
|
||||
phy_interface_stack_nr::tx_request_t& tx_request);
|
||||
|
||||
// PDU processing
|
||||
int handle_pdu(srsran::unique_byte_buffer_t pdu);
|
||||
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSRAN_HARQ_SOFTBUFFER_H
|
||||
#define SRSRAN_HARQ_SOFTBUFFER_H
|
||||
|
||||
#include "srsran/adt/pool/pool_interface.h"
|
||||
#include "srsran/adt/span.h"
|
||||
extern "C" {
|
||||
#include "srsran/phy/common/phy_common_nr.h"
|
||||
#include "srsran/phy/fec/softbuffer.h"
|
||||
}
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
class tx_harq_softbuffer
|
||||
{
|
||||
public:
|
||||
tx_harq_softbuffer() { bzero(&buffer, sizeof(buffer)); }
|
||||
explicit tx_harq_softbuffer(uint32_t nof_prb_) { srsran_softbuffer_tx_init(&buffer, nof_prb_); }
|
||||
tx_harq_softbuffer(const tx_harq_softbuffer&) = delete;
|
||||
tx_harq_softbuffer(tx_harq_softbuffer&& other) noexcept
|
||||
{
|
||||
memcpy(&buffer, &other.buffer, sizeof(other.buffer));
|
||||
bzero(&other.buffer, sizeof(other.buffer));
|
||||
}
|
||||
tx_harq_softbuffer& operator=(const tx_harq_softbuffer&) = delete;
|
||||
tx_harq_softbuffer& operator =(tx_harq_softbuffer&& other) noexcept
|
||||
{
|
||||
if (this != &other) {
|
||||
destroy();
|
||||
memcpy(&buffer, &other.buffer, sizeof(other.buffer));
|
||||
bzero(&other.buffer, sizeof(other.buffer));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
~tx_harq_softbuffer() { destroy(); }
|
||||
|
||||
void reset() { srsran_softbuffer_tx_reset(&buffer); }
|
||||
|
||||
srsran_softbuffer_tx_t& operator*() { return buffer; }
|
||||
const srsran_softbuffer_tx_t& operator*() const { return buffer; }
|
||||
srsran_softbuffer_tx_t* operator->() { return &buffer; }
|
||||
const srsran_softbuffer_tx_t* operator->() const { return &buffer; }
|
||||
srsran_softbuffer_tx_t* get() { return &buffer; }
|
||||
const srsran_softbuffer_tx_t* get() const { return &buffer; }
|
||||
|
||||
private:
|
||||
void destroy() { srsran_softbuffer_tx_free(&buffer); }
|
||||
|
||||
srsran_softbuffer_tx_t buffer;
|
||||
};
|
||||
|
||||
class rx_harq_softbuffer
|
||||
{
|
||||
public:
|
||||
rx_harq_softbuffer() { bzero(&buffer, sizeof(buffer)); }
|
||||
explicit rx_harq_softbuffer(uint32_t nof_prb_) { srsran_softbuffer_rx_init(&buffer, nof_prb_); }
|
||||
rx_harq_softbuffer(const rx_harq_softbuffer&) = delete;
|
||||
rx_harq_softbuffer(rx_harq_softbuffer&& other) noexcept
|
||||
{
|
||||
memcpy(&buffer, &other.buffer, sizeof(other.buffer));
|
||||
bzero(&other.buffer, sizeof(other.buffer));
|
||||
}
|
||||
rx_harq_softbuffer& operator=(const rx_harq_softbuffer&) = delete;
|
||||
rx_harq_softbuffer& operator =(rx_harq_softbuffer&& other) noexcept
|
||||
{
|
||||
if (this != &other) {
|
||||
destroy();
|
||||
memcpy(&buffer, &other.buffer, sizeof(other.buffer));
|
||||
bzero(&other.buffer, sizeof(other.buffer));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
~rx_harq_softbuffer() { destroy(); }
|
||||
|
||||
void reset() { srsran_softbuffer_rx_reset(&buffer); }
|
||||
void reset(uint32_t tbs_bits) { srsran_softbuffer_rx_reset_tbs(&buffer, tbs_bits); }
|
||||
|
||||
srsran_softbuffer_rx_t& operator*() { return buffer; }
|
||||
const srsran_softbuffer_rx_t& operator*() const { return buffer; }
|
||||
srsran_softbuffer_rx_t* operator->() { return &buffer; }
|
||||
const srsran_softbuffer_rx_t* operator->() const { return &buffer; }
|
||||
srsran_softbuffer_rx_t* get() { return &buffer; }
|
||||
const srsran_softbuffer_rx_t* get() const { return &buffer; }
|
||||
|
||||
private:
|
||||
void destroy() { srsran_softbuffer_rx_free(&buffer); }
|
||||
|
||||
srsran_softbuffer_rx_t buffer;
|
||||
};
|
||||
|
||||
class harq_softbuffer_pool
|
||||
{
|
||||
public:
|
||||
harq_softbuffer_pool(const harq_softbuffer_pool&) = delete;
|
||||
harq_softbuffer_pool(harq_softbuffer_pool&&) = delete;
|
||||
harq_softbuffer_pool& operator=(const harq_softbuffer_pool&) = delete;
|
||||
harq_softbuffer_pool& operator=(harq_softbuffer_pool&&) = delete;
|
||||
|
||||
void init_pool(uint32_t nof_prb, uint32_t batch_size = MAX_HARQ * 4, uint32_t thres = 0, uint32_t init_size = 0);
|
||||
|
||||
srsran::unique_pool_ptr<tx_harq_softbuffer> get_tx(uint32_t nof_prb);
|
||||
srsran::unique_pool_ptr<rx_harq_softbuffer> get_rx(uint32_t nof_prb);
|
||||
|
||||
static harq_softbuffer_pool& get_instance()
|
||||
{
|
||||
static harq_softbuffer_pool pool;
|
||||
return pool;
|
||||
}
|
||||
|
||||
private:
|
||||
const static uint32_t MAX_HARQ = 16;
|
||||
|
||||
harq_softbuffer_pool() = default;
|
||||
|
||||
std::array<std::unique_ptr<srsran::obj_pool_itf<tx_harq_softbuffer> >, SRSRAN_MAX_PRB_NR> tx_pool;
|
||||
std::array<std::unique_ptr<srsran::obj_pool_itf<rx_harq_softbuffer> >, SRSRAN_MAX_PRB_NR> rx_pool;
|
||||
};
|
||||
|
||||
} // namespace srsenb
|
||||
|
||||
#endif // SRSRAN_HARQ_SOFTBUFFER_H
|
|
@ -22,7 +22,7 @@
|
|||
#ifndef SRSRAN_SCHED_NR_H
|
||||
#define SRSRAN_SCHED_NR_H
|
||||
|
||||
#include "sched_nr_common.h"
|
||||
#include "sched_nr_cfg.h"
|
||||
#include "sched_nr_interface.h"
|
||||
#include "sched_nr_ue.h"
|
||||
#include "srsran/adt/pool/cached_alloc.h"
|
||||
|
@ -36,9 +36,11 @@ namespace srsenb {
|
|||
|
||||
namespace sched_nr_impl {
|
||||
class sched_worker_manager;
|
||||
}
|
||||
class serv_cell_ctxt;
|
||||
} // namespace sched_nr_impl
|
||||
|
||||
class ue_event_manager;
|
||||
class sched_result_manager;
|
||||
|
||||
class sched_nr final : public sched_nr_interface
|
||||
{
|
||||
|
@ -48,17 +50,19 @@ public:
|
|||
int cell_cfg(srsran::const_span<cell_cfg_t> cell_list) override;
|
||||
void ue_cfg(uint16_t rnti, const ue_cfg_t& cfg) override;
|
||||
|
||||
void slot_indication(tti_point tti_rx) override;
|
||||
int generate_sched_result(tti_point tti_rx, uint32_t cc, tti_request_t& tti_req) override;
|
||||
|
||||
void dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) override;
|
||||
void ul_sr_info(tti_point tti_rx, uint16_t rnti) override;
|
||||
|
||||
int get_dl_sched(tti_point pdsch_tti, uint32_t cc, dl_sched_t& result) override;
|
||||
int get_ul_sched(tti_point pdcch_tti, uint32_t cc, ul_sched_t& result) override;
|
||||
|
||||
private:
|
||||
int generate_slot_result(tti_point pdcch_tti, uint32_t cc);
|
||||
void ue_cfg_impl(uint16_t rnti, const ue_cfg_t& cfg);
|
||||
|
||||
// args
|
||||
sched_nr_impl::sched_params cfg;
|
||||
srslog::basic_logger& logger;
|
||||
|
||||
using sched_worker_manager = sched_nr_impl::sched_worker_manager;
|
||||
std::unique_ptr<sched_worker_manager> sched_workers;
|
||||
|
@ -67,8 +71,14 @@ private:
|
|||
std::mutex ue_db_mutex;
|
||||
ue_map_t ue_db;
|
||||
|
||||
// management of PHY UE feedback
|
||||
// management of UE feedback
|
||||
std::unique_ptr<ue_event_manager> pending_events;
|
||||
|
||||
// management of Sched Result buffering
|
||||
std::unique_ptr<sched_result_manager> pending_results;
|
||||
|
||||
// management of cell resources
|
||||
std::vector<std::unique_ptr<sched_nr_impl::serv_cell_ctxt> > cells;
|
||||
};
|
||||
|
||||
} // namespace srsenb
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSRAN_SCHED_NR_BWP_H
|
||||
#define SRSRAN_SCHED_NR_BWP_H
|
||||
|
||||
#include "sched_nr_cfg.h"
|
||||
#include "sched_nr_rb_grid.h"
|
||||
#include "srsran/adt/pool/cached_alloc.h"
|
||||
|
||||
namespace srsenb {
|
||||
namespace sched_nr_impl {
|
||||
|
||||
using dl_sched_rar_info_t = sched_nr_interface::dl_sched_rar_info_t;
|
||||
|
||||
struct pending_rar_t {
|
||||
uint16_t ra_rnti = 0;
|
||||
tti_point prach_tti;
|
||||
srsran::bounded_vector<dl_sched_rar_info_t, sched_interface::MAX_RAR_LIST> msg3_grant;
|
||||
};
|
||||
|
||||
/// RAR/Msg3 scheduler
|
||||
class ra_sched
|
||||
{
|
||||
public:
|
||||
explicit ra_sched(const bwp_params& bwp_cfg_);
|
||||
|
||||
int dl_rach_info(const dl_sched_rar_info_t& rar_info);
|
||||
void run_slot(bwp_slot_allocator& slot_grid);
|
||||
size_t empty() const { return pending_rars.empty(); }
|
||||
|
||||
private:
|
||||
alloc_result
|
||||
allocate_pending_rar(bwp_slot_allocator& slot_grid, const pending_rar_t& rar, uint32_t& nof_grants_alloc);
|
||||
|
||||
const bwp_params* bwp_cfg = nullptr;
|
||||
srslog::basic_logger& logger;
|
||||
|
||||
srsran::deque<pending_rar_t> pending_rars;
|
||||
};
|
||||
|
||||
class bwp_ctxt
|
||||
{
|
||||
public:
|
||||
explicit bwp_ctxt(const bwp_params& bwp_cfg);
|
||||
|
||||
const bwp_params* cfg;
|
||||
|
||||
// channel-specific schedulers
|
||||
ra_sched ra;
|
||||
|
||||
// Stores pending allocations and PRB bitmaps
|
||||
bwp_res_grid grid;
|
||||
};
|
||||
|
||||
class serv_cell_ctxt
|
||||
{
|
||||
public:
|
||||
srsran::bounded_vector<bwp_ctxt, SCHED_NR_MAX_BWP_PER_CELL> bwps;
|
||||
|
||||
explicit serv_cell_ctxt(const sched_cell_params& cell_cfg_);
|
||||
|
||||
const sched_cell_params* cfg;
|
||||
};
|
||||
|
||||
} // namespace sched_nr_impl
|
||||
} // namespace srsenb
|
||||
|
||||
#endif // SRSRAN_SCHED_NR_BWP_H
|
|
@ -0,0 +1,190 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSRAN_SCHED_NR_CFG_H
|
||||
#define SRSRAN_SCHED_NR_CFG_H
|
||||
|
||||
#include "sched_nr_interface.h"
|
||||
#include "sched_nr_rb.h"
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
const static size_t SCHED_NR_MAX_USERS = 4;
|
||||
const static size_t SCHED_NR_NOF_SUBFRAMES = 10;
|
||||
const static size_t SCHED_NR_NOF_HARQS = 16;
|
||||
static const size_t MAX_NOF_AGGR_LEVELS = 5;
|
||||
|
||||
namespace sched_nr_impl {
|
||||
|
||||
const static size_t MAX_GRANTS = sched_nr_interface::MAX_GRANTS;
|
||||
|
||||
using pucch_t = mac_interface_phy_nr::pucch_t;
|
||||
using pucch_list_t = srsran::bounded_vector<pucch_t, MAX_GRANTS>;
|
||||
using pusch_t = mac_interface_phy_nr::pusch_t;
|
||||
using pusch_list_t = srsran::bounded_vector<pusch_t, MAX_GRANTS>;
|
||||
|
||||
using sched_cfg_t = sched_nr_interface::sched_cfg_t;
|
||||
using cell_cfg_t = sched_nr_interface::cell_cfg_t;
|
||||
using bwp_cfg_t = sched_nr_interface::bwp_cfg_t;
|
||||
|
||||
struct bwp_params {
|
||||
const uint32_t bwp_id;
|
||||
const uint32_t cc;
|
||||
const bwp_cfg_t& cfg;
|
||||
const cell_cfg_t& cell_cfg;
|
||||
const sched_cfg_t& sched_cfg;
|
||||
|
||||
// derived params
|
||||
uint32_t P;
|
||||
uint32_t N_rbg;
|
||||
|
||||
bwp_params(const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_, uint32_t cc, uint32_t bwp_id);
|
||||
};
|
||||
|
||||
struct sched_cell_params {
|
||||
const uint32_t cc;
|
||||
const cell_cfg_t cell_cfg;
|
||||
const sched_cfg_t& sched_cfg;
|
||||
std::vector<bwp_params> bwps;
|
||||
|
||||
sched_cell_params(uint32_t cc_, const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_);
|
||||
|
||||
uint32_t nof_prb() const { return cell_cfg.carrier.nof_prb; }
|
||||
};
|
||||
|
||||
struct sched_params {
|
||||
const sched_cfg_t sched_cfg;
|
||||
std::vector<sched_cell_params> cells;
|
||||
|
||||
explicit sched_params(const sched_cfg_t& sched_cfg_);
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
using prb_bitmap = srsran::bounded_bitset<SRSRAN_MAX_PRB_NR, true>;
|
||||
using rbgmask_t = srsran::bounded_bitset<SCHED_NR_MAX_NOF_RBGS, true>;
|
||||
|
||||
using pdcchmask_t = srsran::bounded_bitset<SCHED_NR_MAX_NOF_RBGS, true>;
|
||||
|
||||
using pdcch_cce_pos_list = srsran::bounded_vector<uint32_t, SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR>;
|
||||
using bwp_cce_pos_list = std::array<std::array<pdcch_cce_pos_list, MAX_NOF_AGGR_LEVELS>, SRSRAN_NOF_SF_X_FRAME>;
|
||||
void get_dci_locs(const srsran_coreset_t& coreset,
|
||||
const srsran_search_space_t& search_space,
|
||||
uint16_t rnti,
|
||||
bwp_cce_pos_list& cce_locs);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
using ue_cfg_t = sched_nr_interface::ue_cfg_t;
|
||||
using ue_cc_cfg_t = sched_nr_interface::ue_cc_cfg_t;
|
||||
|
||||
class bwp_ue_cfg
|
||||
{
|
||||
public:
|
||||
bwp_ue_cfg() = default;
|
||||
explicit bwp_ue_cfg(uint16_t rnti, const bwp_params& bwp_cfg, const ue_cfg_t& uecfg_);
|
||||
|
||||
const ue_cfg_t* ue_cfg() const { return cfg_; }
|
||||
const srsran::phy_cfg_nr_t& phy() const { return cfg_->phy_cfg; }
|
||||
const bwp_params& active_bwp() const { return *bwp_cfg; }
|
||||
const bwp_cce_pos_list& cce_pos_list(uint32_t search_id) const
|
||||
{
|
||||
return cce_positions_list[ss_id_to_cce_idx[search_id]];
|
||||
}
|
||||
|
||||
private:
|
||||
uint16_t rnti = SRSRAN_INVALID_RNTI;
|
||||
const ue_cfg_t* cfg_ = nullptr;
|
||||
const bwp_params* bwp_cfg = nullptr;
|
||||
|
||||
std::vector<bwp_cce_pos_list> cce_positions_list;
|
||||
std::array<uint32_t, SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE> ss_id_to_cce_idx;
|
||||
};
|
||||
|
||||
class ue_cfg_extended : public ue_cfg_t
|
||||
{
|
||||
public:
|
||||
struct search_space_params {
|
||||
const srsran_search_space_t* cfg;
|
||||
bwp_cce_pos_list cce_positions;
|
||||
};
|
||||
struct coreset_params {
|
||||
srsran_coreset_t* cfg = nullptr;
|
||||
std::vector<uint32_t> ss_list;
|
||||
};
|
||||
struct bwp_params {
|
||||
std::array<srsran::optional<search_space_params>, SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE> ss_list;
|
||||
std::vector<coreset_params> coresets;
|
||||
};
|
||||
struct cc_params {
|
||||
srsran::bounded_vector<bwp_params, SCHED_NR_MAX_BWP_PER_CELL> bwps;
|
||||
};
|
||||
|
||||
ue_cfg_extended() = default;
|
||||
explicit ue_cfg_extended(uint16_t rnti, const ue_cfg_t& uecfg);
|
||||
|
||||
const bwp_cce_pos_list& get_dci_pos_list(uint32_t cc, uint32_t bwp_id, uint32_t search_space_id) const
|
||||
{
|
||||
return cc_params[cc].bwps[bwp_id].ss_list[search_space_id]->cce_positions;
|
||||
}
|
||||
|
||||
uint16_t rnti;
|
||||
std::vector<cc_params> cc_params;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct resource_guard {
|
||||
public:
|
||||
resource_guard() = default;
|
||||
resource_guard(const resource_guard& other) = delete;
|
||||
resource_guard(resource_guard&& other) = delete;
|
||||
resource_guard& operator=(const resource_guard& other) = delete;
|
||||
resource_guard& operator=(resource_guard&& other) = delete;
|
||||
bool busy() const { return flag; }
|
||||
|
||||
struct token {
|
||||
token() = default;
|
||||
token(resource_guard& parent) : flag(parent.busy() ? nullptr : &parent.flag)
|
||||
{
|
||||
if (flag != nullptr) {
|
||||
*flag = true;
|
||||
}
|
||||
}
|
||||
token(token&&) noexcept = default;
|
||||
token& operator=(token&&) noexcept = default;
|
||||
void release() { flag.reset(); }
|
||||
bool owns_token() const { return flag != nullptr; }
|
||||
bool empty() const { return flag == nullptr; }
|
||||
|
||||
private:
|
||||
struct release_deleter {
|
||||
void operator()(bool* ptr)
|
||||
{
|
||||
if (ptr != nullptr) {
|
||||
srsran_assert(*ptr == true, "resource token: detected inconsistency token state");
|
||||
*ptr = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
std::unique_ptr<bool, release_deleter> flag;
|
||||
};
|
||||
|
||||
private:
|
||||
bool flag = false;
|
||||
};
|
||||
|
||||
} // namespace sched_nr_impl
|
||||
|
||||
} // namespace srsenb
|
||||
|
||||
#endif // SRSRAN_SCHED_NR_CFG_H
|
|
@ -1,111 +0,0 @@
|
|||
/**
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* This file is part of srsRAN.
|
||||
*
|
||||
* srsRAN is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* srsRAN is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* A copy of the GNU Affero General Public License can be found in
|
||||
* the LICENSE file in the top-level directory of this distribution
|
||||
* and at http://www.gnu.org/licenses/.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSRAN_SCHED_NR_COMMON_H
|
||||
#define SRSRAN_SCHED_NR_COMMON_H
|
||||
|
||||
#include "sched_nr_interface.h"
|
||||
#include "srsran/adt/bounded_bitset.h"
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
const static size_t SCHED_NR_MAX_USERS = 4;
|
||||
const static size_t SCHED_NR_NOF_SUBFRAMES = 10;
|
||||
const static size_t SCHED_NR_NOF_HARQS = 16;
|
||||
static const size_t MAX_NOF_AGGR_LEVELS = 5;
|
||||
|
||||
namespace sched_nr_impl {
|
||||
|
||||
const static size_t MAX_GRANTS = sched_nr_interface::MAX_GRANTS;
|
||||
|
||||
using sched_cfg_t = sched_nr_interface::sched_cfg_t;
|
||||
using cell_cfg_t = sched_nr_interface::cell_cfg_t;
|
||||
|
||||
struct sched_cell_params {
|
||||
const uint32_t cc;
|
||||
const cell_cfg_t cell_cfg;
|
||||
const sched_cfg_t& sched_cfg;
|
||||
|
||||
sched_cell_params(uint32_t cc_, const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_);
|
||||
};
|
||||
|
||||
struct sched_params {
|
||||
const sched_cfg_t sched_cfg;
|
||||
std::vector<sched_cell_params> cells;
|
||||
|
||||
explicit sched_params(const sched_cfg_t& sched_cfg_);
|
||||
};
|
||||
|
||||
using pdcchmask_t = srsran::bounded_bitset<SCHED_NR_MAX_NOF_RBGS, true>;
|
||||
using rbgmask_t = srsran::bounded_bitset<SCHED_NR_MAX_NOF_RBGS, true>;
|
||||
|
||||
struct resource_guard {
|
||||
public:
|
||||
resource_guard() = default;
|
||||
resource_guard(const resource_guard& other) = delete;
|
||||
resource_guard(resource_guard&& other) = delete;
|
||||
resource_guard& operator=(const resource_guard& other) = delete;
|
||||
resource_guard& operator=(resource_guard&& other) = delete;
|
||||
bool busy() const { return flag; }
|
||||
|
||||
struct token {
|
||||
token() = default;
|
||||
token(resource_guard& parent) : flag(parent.busy() ? nullptr : &parent.flag)
|
||||
{
|
||||
if (flag != nullptr) {
|
||||
*flag = true;
|
||||
}
|
||||
}
|
||||
token(token&&) noexcept = default;
|
||||
token& operator=(token&&) noexcept = default;
|
||||
void release() { flag.reset(); }
|
||||
bool owns_token() const { return flag != nullptr; }
|
||||
bool empty() const { return flag == nullptr; }
|
||||
|
||||
private:
|
||||
struct release_deleter {
|
||||
void operator()(bool* ptr)
|
||||
{
|
||||
if (ptr != nullptr) {
|
||||
srsran_assert(*ptr == true, "resource token: detected inconsistency token state");
|
||||
*ptr = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
std::unique_ptr<bool, release_deleter> flag;
|
||||
};
|
||||
|
||||
private:
|
||||
bool flag = false;
|
||||
};
|
||||
|
||||
using pdcch_cce_pos_list = srsran::bounded_vector<uint32_t, SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR>;
|
||||
using bwp_cce_pos_list = std::array<std::array<pdcch_cce_pos_list, MAX_NOF_AGGR_LEVELS>, SRSRAN_NOF_SF_X_FRAME>;
|
||||
void get_dci_locs(const srsran_coreset_t& coreset,
|
||||
const srsran_search_space_t& search_space,
|
||||
uint16_t rnti,
|
||||
bwp_cce_pos_list& cce_locs);
|
||||
|
||||
} // namespace sched_nr_impl
|
||||
|
||||
} // namespace srsenb
|
||||
|
||||
#endif // SRSRAN_SCHED_NR_COMMON_H
|
|
@ -22,7 +22,8 @@
|
|||
#ifndef SRSRAN_SCHED_NR_HARQ_H
|
||||
#define SRSRAN_SCHED_NR_HARQ_H
|
||||
|
||||
#include "sched_nr_common.h"
|
||||
#include "sched_nr_cfg.h"
|
||||
#include "srsenb/hdr/stack/mac/nr/harq_softbuffer.h"
|
||||
#include "srsran/common/tti_point.h"
|
||||
#include <array>
|
||||
|
||||
|
@ -40,19 +41,25 @@ public:
|
|||
}
|
||||
bool empty(uint32_t tb_idx) const { return not tb[tb_idx].active; }
|
||||
bool has_pending_retx(tti_point tti_rx) const { return not empty() and not tb[0].ack_state and tti_ack <= tti_rx; }
|
||||
uint32_t nof_retx() const { return tb[0].n_rtx; }
|
||||
uint32_t max_nof_retx() const { return max_retx; }
|
||||
uint32_t tbs() const { return tb[0].tbs; }
|
||||
uint32_t ndi() const { return tb[0].ndi; }
|
||||
uint32_t mcs() const { return tb[0].mcs; }
|
||||
uint32_t nof_retx() const { return tb[0].n_rtx; }
|
||||
uint32_t max_nof_retx() const { return max_retx; }
|
||||
uint32_t tbs() const { return tb[0].tbs; }
|
||||
uint32_t ndi() const { return tb[0].ndi; }
|
||||
uint32_t mcs() const { return tb[0].mcs; }
|
||||
const prb_grant& prbs() const { return prbs_; }
|
||||
tti_point harq_tti_ack() const { return tti_ack; }
|
||||
|
||||
bool ack_info(uint32_t tb_idx, bool ack);
|
||||
|
||||
void new_tti(tti_point tti_rx);
|
||||
void reset();
|
||||
bool
|
||||
new_tx(tti_point tti_tx, tti_point tti_ack, const rbgmask_t& rbgmask, uint32_t mcs, uint32_t tbs, uint32_t max_retx);
|
||||
bool new_retx(tti_point tti_tx, tti_point tti_ack, const rbgmask_t& rbgmask, int* mcs, int* tbs);
|
||||
new_tx(tti_point tti_tx, tti_point tti_ack, const prb_grant& grant, uint32_t mcs, uint32_t tbs, uint32_t max_retx);
|
||||
bool new_retx(tti_point tti_tx, tti_point tti_ack, const prb_grant& grant);
|
||||
bool new_retx(tti_point tti_tx, tti_point tti_ack);
|
||||
|
||||
// NOTE: Has to be used before first tx is dispatched
|
||||
bool set_tbs(uint32_t tbs);
|
||||
|
||||
const uint32_t pid;
|
||||
|
||||
|
@ -69,27 +76,59 @@ private:
|
|||
uint32_t max_retx = 1;
|
||||
tti_point tti_tx;
|
||||
tti_point tti_ack;
|
||||
rbgmask_t rbgmask;
|
||||
prb_grant prbs_;
|
||||
std::array<tb_t, SCHED_NR_MAX_TB> tb;
|
||||
};
|
||||
|
||||
class dl_harq_proc : public harq_proc
|
||||
{
|
||||
public:
|
||||
dl_harq_proc(uint32_t id_, uint32_t nprb) :
|
||||
harq_proc(id_), softbuffer(harq_softbuffer_pool::get_instance().get_tx(nprb))
|
||||
{}
|
||||
|
||||
tx_harq_softbuffer& get_softbuffer() { return *softbuffer; }
|
||||
|
||||
private:
|
||||
srsran::unique_pool_ptr<tx_harq_softbuffer> softbuffer;
|
||||
};
|
||||
|
||||
class ul_harq_proc : public harq_proc
|
||||
{
|
||||
public:
|
||||
ul_harq_proc(uint32_t id_, uint32_t nprb) :
|
||||
harq_proc(id_), softbuffer(harq_softbuffer_pool::get_instance().get_rx(nprb))
|
||||
{}
|
||||
|
||||
rx_harq_softbuffer& get_softbuffer() { return *softbuffer; }
|
||||
|
||||
bool set_tbs(uint32_t tbs)
|
||||
{
|
||||
softbuffer->reset(tbs * 8u);
|
||||
return harq_proc::set_tbs(tbs);
|
||||
}
|
||||
|
||||
private:
|
||||
srsran::unique_pool_ptr<rx_harq_softbuffer> softbuffer;
|
||||
};
|
||||
|
||||
class harq_entity
|
||||
{
|
||||
public:
|
||||
explicit harq_entity(uint32_t nof_harq_procs = SCHED_NR_MAX_HARQ);
|
||||
explicit harq_entity(uint32_t nprb, uint32_t nof_harq_procs = SCHED_NR_MAX_HARQ);
|
||||
void new_tti(tti_point tti_rx_);
|
||||
|
||||
void dl_ack_info(uint32_t pid, uint32_t tb_idx, bool ack) { dl_harqs[pid].ack_info(tb_idx, ack); }
|
||||
|
||||
harq_proc* find_pending_dl_retx()
|
||||
dl_harq_proc* find_pending_dl_retx()
|
||||
{
|
||||
return find_dl([this](const harq_proc& h) { return h.has_pending_retx(tti_rx); });
|
||||
return find_dl([this](const dl_harq_proc& h) { return h.has_pending_retx(tti_rx); });
|
||||
}
|
||||
harq_proc* find_pending_ul_retx()
|
||||
{
|
||||
return find_ul([this](const harq_proc& h) { return h.has_pending_retx(tti_rx); });
|
||||
}
|
||||
harq_proc* find_empty_dl_harq()
|
||||
dl_harq_proc* find_empty_dl_harq()
|
||||
{
|
||||
return find_dl([](const harq_proc& h) { return h.empty(); });
|
||||
}
|
||||
|
@ -100,7 +139,7 @@ public:
|
|||
|
||||
private:
|
||||
template <typename Predicate>
|
||||
harq_proc* find_dl(Predicate p)
|
||||
dl_harq_proc* find_dl(Predicate p)
|
||||
{
|
||||
auto it = std::find_if(dl_harqs.begin(), dl_harqs.end(), p);
|
||||
return (it == dl_harqs.end()) ? nullptr : &(*it);
|
||||
|
@ -112,9 +151,9 @@ private:
|
|||
return (it == ul_harqs.end()) ? nullptr : &(*it);
|
||||
}
|
||||
|
||||
tti_point tti_rx;
|
||||
std::vector<harq_proc> dl_harqs;
|
||||
std::vector<harq_proc> ul_harqs;
|
||||
tti_point tti_rx;
|
||||
std::vector<dl_harq_proc> dl_harqs;
|
||||
std::vector<ul_harq_proc> ul_harqs;
|
||||
};
|
||||
|
||||
} // namespace sched_nr_impl
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSRAN_SCHED_NR_HELPERS_H
|
||||
#define SRSRAN_SCHED_NR_HELPERS_H
|
||||
|
||||
#include "sched_nr_cfg.h"
|
||||
|
||||
namespace srsenb {
|
||||
namespace sched_nr_impl {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool fill_dci_rar(prb_interval interv, const bwp_params& bwp_cfg, srsran_dci_dl_nr_t& dci);
|
||||
|
||||
class slot_ue;
|
||||
|
||||
/// Generate PDCCH DL DCI fields
|
||||
void fill_dl_dci_ue_fields(const slot_ue& ue,
|
||||
const bwp_params& bwp_cfg,
|
||||
uint32_t ss_id,
|
||||
srsran_dci_location_t dci_pos,
|
||||
srsran_dci_dl_nr_t& dci);
|
||||
|
||||
/// Generate PDCCH UL DCI fields
|
||||
void fill_ul_dci_ue_fields(const slot_ue& ue,
|
||||
const bwp_params& bwp_cfg,
|
||||
uint32_t ss_id,
|
||||
srsran_dci_location_t dci_pos,
|
||||
srsran_dci_ul_nr_t& dci);
|
||||
|
||||
} // namespace sched_nr_impl
|
||||
} // namespace srsenb
|
||||
|
||||
#endif // SRSRAN_SCHED_NR_HELPERS_H
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "srsran/adt/bounded_bitset.h"
|
||||
#include "srsran/adt/bounded_vector.h"
|
||||
#include "srsran/adt/optional.h"
|
||||
#include "srsran/adt/span.h"
|
||||
#include "srsran/common/phy_cfg_nr.h"
|
||||
#include "srsran/common/tti_point.h"
|
||||
|
@ -34,18 +35,15 @@ namespace srsenb {
|
|||
|
||||
const static size_t SCHED_NR_MAX_CARRIERS = 4;
|
||||
const static uint16_t SCHED_NR_INVALID_RNTI = 0;
|
||||
const static size_t SCHED_NR_MAX_PDSCH_DATA = 16;
|
||||
const static size_t SCHED_NR_MAX_NOF_RBGS = 25;
|
||||
const static size_t SCHED_NR_MAX_UL_ALLOCS = 16;
|
||||
const static size_t SCHED_NR_MAX_NOF_RBGS = 18;
|
||||
const static size_t SCHED_NR_MAX_TB = 1;
|
||||
const static size_t SCHED_NR_MAX_HARQ = 16;
|
||||
const static size_t SCHED_NR_MAX_BWP_PER_CELL = 1;
|
||||
const static size_t SCHED_NR_MAX_BWP_PER_CELL = 2;
|
||||
|
||||
class sched_nr_interface
|
||||
{
|
||||
public:
|
||||
using pdcch_bitmap = srsran::bounded_bitset<SCHED_NR_MAX_NOF_RBGS, true>;
|
||||
using rbg_bitmap = srsran::bounded_bitset<SCHED_NR_MAX_NOF_RBGS, true>;
|
||||
static const size_t MAX_GRANTS = mac_interface_phy_nr::MAX_GRANTS;
|
||||
|
||||
///// Configuration /////
|
||||
|
||||
|
@ -53,21 +51,25 @@ public:
|
|||
uint8_t k0 = 0; // 0..32
|
||||
uint8_t k1 = 4; // 0..32
|
||||
};
|
||||
using pdsch_td_res_alloc_list = srsran::bounded_vector<pdsch_td_res_alloc, SCHED_NR_MAX_UL_ALLOCS>;
|
||||
using pdsch_td_res_alloc_list = srsran::bounded_vector<pdsch_td_res_alloc, MAX_GRANTS>;
|
||||
struct pusch_td_res_alloc {
|
||||
uint8_t k2 = 4; // 0..32
|
||||
};
|
||||
using pusch_td_res_alloc_list = srsran::bounded_vector<pusch_td_res_alloc, SCHED_NR_MAX_UL_ALLOCS>;
|
||||
using pusch_td_res_alloc_list = srsran::bounded_vector<pusch_td_res_alloc, MAX_GRANTS>;
|
||||
|
||||
struct bwp_cfg_t {
|
||||
uint32_t start_rb = 0;
|
||||
uint32_t rb_width = 100;
|
||||
uint32_t start_rb = 0;
|
||||
uint32_t rb_width = 100;
|
||||
srsran_pdcch_cfg_nr_t pdcch = {};
|
||||
srsran_sch_hl_cfg_nr_t pdsch = {};
|
||||
srsran_sch_hl_cfg_nr_t pusch = {};
|
||||
uint32_t rar_window_size = 3;
|
||||
};
|
||||
|
||||
struct cell_cfg_t {
|
||||
uint32_t nof_prb = 100;
|
||||
uint32_t nof_rbg = 25;
|
||||
srsran::bounded_vector<bwp_cfg_t, SCHED_NR_MAX_BWP_PER_CELL> bwps{1};
|
||||
srsran_carrier_nr_t carrier = {};
|
||||
srsran_tdd_config_nr_t tdd = {};
|
||||
srsran::bounded_vector<bwp_cfg_t, SCHED_NR_MAX_BWP_PER_CELL> bwps{1}; // idx0 for BWP-common
|
||||
};
|
||||
|
||||
struct sched_cfg_t {
|
||||
|
@ -75,9 +77,8 @@ public:
|
|||
};
|
||||
|
||||
struct ue_cc_cfg_t {
|
||||
bool active = false;
|
||||
pdsch_td_res_alloc_list pdsch_res_list{1};
|
||||
pusch_td_res_alloc_list pusch_res_list{1};
|
||||
bool active = false;
|
||||
uint32_t cc = 0;
|
||||
};
|
||||
|
||||
struct ue_cfg_t {
|
||||
|
@ -86,47 +87,26 @@ public:
|
|||
srsran::phy_cfg_nr_t phy_cfg = {};
|
||||
};
|
||||
|
||||
////// RACH //////
|
||||
|
||||
struct dl_sched_rar_info_t {
|
||||
uint32_t preamble_idx;
|
||||
uint32_t ta_cmd;
|
||||
uint16_t temp_crnti;
|
||||
uint32_t msg3_size;
|
||||
uint32_t prach_tti;
|
||||
};
|
||||
|
||||
///// Sched Result /////
|
||||
|
||||
const static int MAX_GRANTS = 64;
|
||||
using dl_sched_t = mac_interface_phy_nr::dl_sched_t;
|
||||
using ul_sched_t = mac_interface_phy_nr::ul_sched_t;
|
||||
|
||||
using pdcch_dl_t = mac_interface_phy_nr::pdcch_dl_t;
|
||||
using pdcch_ul_t = mac_interface_phy_nr::pdcch_ul_t;
|
||||
using pdcch_dl_list_t = srsran::bounded_vector<pdcch_dl_t, MAX_GRANTS>;
|
||||
using pdcch_ul_list_t = srsran::bounded_vector<pdcch_ul_t, MAX_GRANTS>;
|
||||
|
||||
struct pdsch_t {
|
||||
srsran_sch_cfg_nr_t sch = {}; ///< PDSCH configuration
|
||||
};
|
||||
using pdsch_list_t = srsran::bounded_vector<pdsch_t, SCHED_NR_MAX_PDSCH_DATA>;
|
||||
|
||||
struct dl_tti_request_t {
|
||||
tti_point pdsch_tti;
|
||||
pdcch_dl_list_t pdcchs;
|
||||
pdsch_list_t pdschs;
|
||||
};
|
||||
|
||||
struct pusch_grant {
|
||||
srsran_dci_ul_nr_t dci;
|
||||
rbg_bitmap bitmap;
|
||||
};
|
||||
using pusch_list = srsran::bounded_vector<pusch_grant, SCHED_NR_MAX_PDSCH_DATA>;
|
||||
|
||||
struct ul_tti_request_t {
|
||||
tti_point pusch_tti;
|
||||
srsran::bounded_vector<pusch_grant, SCHED_NR_MAX_UL_ALLOCS> pusch;
|
||||
};
|
||||
|
||||
struct tti_request_t {
|
||||
dl_tti_request_t dl_res;
|
||||
ul_tti_request_t ul_res;
|
||||
};
|
||||
|
||||
virtual ~sched_nr_interface() = default;
|
||||
virtual int cell_cfg(srsran::const_span<sched_nr_interface::cell_cfg_t> ue_cfg) = 0;
|
||||
virtual void ue_cfg(uint16_t rnti, const ue_cfg_t& ue_cfg) = 0;
|
||||
virtual void slot_indication(tti_point tti_rx) = 0;
|
||||
virtual int generate_sched_result(tti_point tti_rx, uint32_t cc, tti_request_t& result) = 0;
|
||||
virtual ~sched_nr_interface() = default;
|
||||
virtual int cell_cfg(srsran::const_span<sched_nr_interface::cell_cfg_t> ue_cfg) = 0;
|
||||
virtual void ue_cfg(uint16_t rnti, const ue_cfg_t& ue_cfg) = 0;
|
||||
virtual int get_dl_sched(tti_point tti_rx, uint32_t cc, dl_sched_t& result) = 0;
|
||||
virtual int get_ul_sched(tti_point tti_rx, uint32_t cc, ul_sched_t& result) = 0;
|
||||
|
||||
virtual void dl_ack_info(uint16_t rnti, uint32_t cc, uint32_t pid, uint32_t tb_idx, bool ack) = 0;
|
||||
virtual void ul_sr_info(tti_point, uint16_t rnti) = 0;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#ifndef SRSRAN_SCHED_NR_PDCCH_H
|
||||
#define SRSRAN_SCHED_NR_PDCCH_H
|
||||
|
||||
#include "srsenb/hdr/stack/mac/nr/sched_nr_common.h"
|
||||
#include "srsenb/hdr/stack/mac/nr/sched_nr_cfg.h"
|
||||
#include "srsran/adt/bounded_bitset.h"
|
||||
#include "srsran/adt/bounded_vector.h"
|
||||
#include "srsran/phy/common/phy_common_nr.h"
|
||||
|
@ -34,23 +34,24 @@ namespace sched_nr_impl {
|
|||
|
||||
using coreset_bitmap = srsran::bounded_bitset<SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE * SRSRAN_CORESET_DURATION_MAX, true>;
|
||||
|
||||
enum class pdcch_grant_type_t { sib, dl_data, ul_data };
|
||||
enum class pdcch_grant_type_t { sib, rar, dl_data, ul_data };
|
||||
|
||||
class slot_ue;
|
||||
|
||||
using pdcch_dl_t = sched_nr_interface::pdcch_dl_t;
|
||||
using pdcch_dl_list_t = sched_nr_interface::pdcch_dl_list_t;
|
||||
using pdcch_ul_t = sched_nr_interface::pdcch_ul_t;
|
||||
using pdcch_ul_list_t = sched_nr_interface::pdcch_ul_list_t;
|
||||
using bwp_cfg_t = sched_nr_interface::bwp_cfg_t;
|
||||
using pdcch_dl_t = mac_interface_phy_nr::pdcch_dl_t;
|
||||
using pdcch_ul_t = mac_interface_phy_nr::pdcch_ul_t;
|
||||
using pdcch_dl_list_t = srsran::bounded_vector<pdcch_dl_t, MAX_GRANTS>;
|
||||
using pdcch_ul_list_t = srsran::bounded_vector<pdcch_ul_t, MAX_GRANTS>;
|
||||
|
||||
class coreset_region
|
||||
{
|
||||
public:
|
||||
coreset_region(uint32_t bwp_id_,
|
||||
uint32_t slot_idx,
|
||||
uint32_t nof_td_symbols,
|
||||
uint32_t nof_freq_resources,
|
||||
pdcch_dl_list_t& pdcch_list);
|
||||
coreset_region(const bwp_params& bwp_cfg_,
|
||||
uint32_t coreset_id_,
|
||||
uint32_t slot_idx,
|
||||
pdcch_dl_list_t& pdcch_dl_list,
|
||||
pdcch_ul_list_t& pdcch_ul_list);
|
||||
void reset();
|
||||
|
||||
/**
|
||||
|
@ -60,31 +61,32 @@ public:
|
|||
* @param user UE object or null in case of broadcast/RAR/paging allocation
|
||||
* @return if the allocation was successful
|
||||
*/
|
||||
bool alloc_dci(pdcch_grant_type_t alloc_type, uint32_t aggr_idx, uint32_t coreset_id, slot_ue* user = nullptr);
|
||||
bool alloc_dci(pdcch_grant_type_t alloc_type, uint32_t aggr_idx, uint32_t search_space_id, slot_ue* user = nullptr);
|
||||
|
||||
void rem_last_dci();
|
||||
|
||||
uint32_t get_td_symbols() const { return nof_symbols; }
|
||||
uint32_t get_td_symbols() const { return coreset_cfg->duration; }
|
||||
uint32_t get_freq_resources() const { return nof_freq_res; }
|
||||
uint32_t nof_cces() const { return nof_freq_res * nof_symbols; }
|
||||
uint32_t nof_cces() const { return nof_freq_res * get_td_symbols(); }
|
||||
size_t nof_allocs() const { return dfs_tree.size(); }
|
||||
|
||||
private:
|
||||
uint32_t bwp_id;
|
||||
uint32_t slot_idx;
|
||||
uint32_t nof_symbols;
|
||||
uint32_t nof_freq_res;
|
||||
const srsran_coreset_t* coreset_cfg;
|
||||
uint32_t coreset_id;
|
||||
uint32_t slot_idx;
|
||||
uint32_t nof_freq_res = 0;
|
||||
|
||||
// List of PDCCH grants
|
||||
struct alloc_record {
|
||||
uint32_t coreset_id;
|
||||
uint32_t aggr_idx;
|
||||
uint32_t ss_id;
|
||||
uint32_t idx;
|
||||
pdcch_grant_type_t alloc_type;
|
||||
slot_ue* ue;
|
||||
};
|
||||
srsran::bounded_vector<alloc_record, MAX_GRANTS> dci_list;
|
||||
pdcch_dl_list_t& pdcch_dl_list;
|
||||
pdcch_ul_list_t& pdcch_ul_list;
|
||||
|
||||
// DFS decision tree of PDCCH grants
|
||||
struct tree_node {
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
/**
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* This file is part of srsRAN.
|
||||
*
|
||||
* srsRAN is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* srsRAN is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* A copy of the GNU Affero General Public License can be found in
|
||||
* the LICENSE file in the top-level directory of this distribution
|
||||
* and at http://www.gnu.org/licenses/.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSRAN_SCHED_NR_PHY_HELPERS_H
|
||||
#define SRSRAN_SCHED_NR_PHY_HELPERS_H
|
||||
|
||||
#include "sched_nr_common.h"
|
||||
|
||||
namespace srsenb {
|
||||
namespace sched_nr_impl {
|
||||
|
||||
uint32_t get_P(uint32_t bwp_nof_prb, bool config_1_or_2);
|
||||
uint32_t get_nof_rbgs(uint32_t bwp_nof_prb, uint32_t bwp_start, bool config1_or_2);
|
||||
|
||||
void bitmap_to_prb_array(const rbgmask_t& bitmap, uint32_t bwp_nof_prb, srsran_sch_grant_nr_t& grant);
|
||||
|
||||
class slot_ue;
|
||||
void fill_dci_ue_cfg(const slot_ue& ue, srsran_dci_dl_nr_t& dci);
|
||||
void fill_dci_ue_cfg(const slot_ue& ue, srsran_dci_ul_nr_t& dci);
|
||||
|
||||
} // namespace sched_nr_impl
|
||||
} // namespace srsenb
|
||||
|
||||
#endif // SRSRAN_SCHED_NR_PHY_HELPERS_H
|
|
@ -0,0 +1,237 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSRAN_SCHED_NR_RB_H
|
||||
#define SRSRAN_SCHED_NR_RB_H
|
||||
|
||||
#include "srsenb/hdr/stack/mac/nr/sched_nr_interface.h"
|
||||
#include "srsran/adt/bounded_bitset.h"
|
||||
#include "srsran/phy/common/phy_common_nr.h"
|
||||
|
||||
namespace srsenb {
|
||||
namespace sched_nr_impl {
|
||||
|
||||
using prb_bitmap = srsran::bounded_bitset<SRSRAN_MAX_PRB_NR, true>;
|
||||
using rbg_bitmap = srsran::bounded_bitset<SCHED_NR_MAX_NOF_RBGS, true>;
|
||||
|
||||
/// TS 38.214, Table 6.1.2.2.1-1 - Nominal RBG size P
|
||||
uint32_t get_P(uint32_t bwp_nof_prb, bool config_1_or_2);
|
||||
|
||||
/// TS 38.214 - total number of RBGs for a uplink bandwidth part of size "bwp_nof_prb" PRBs
|
||||
uint32_t get_nof_rbgs(uint32_t bwp_nof_prb, uint32_t bwp_start, bool config1_or_2);
|
||||
|
||||
/// Struct to express a {min,...,max} range of PRBs
|
||||
struct prb_interval : public srsran::interval<uint32_t> {
|
||||
using interval::interval;
|
||||
};
|
||||
|
||||
struct prb_grant {
|
||||
prb_grant() = default;
|
||||
prb_grant(const prb_interval& other) noexcept : alloc_type_0(false), alloc(other) {}
|
||||
prb_grant(const rbg_bitmap& other) noexcept : alloc_type_0(true), alloc(other) {}
|
||||
prb_grant(const prb_grant& other) noexcept : alloc_type_0(other.alloc_type_0), alloc(other.alloc_type_0, other.alloc)
|
||||
{}
|
||||
prb_grant& operator=(const prb_grant& other) noexcept
|
||||
{
|
||||
if (this == &other) {
|
||||
return *this;
|
||||
}
|
||||
if (other.alloc_type_0) {
|
||||
*this = other.rbgs();
|
||||
} else {
|
||||
*this = other.prbs();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
prb_grant& operator=(const prb_interval& prbs)
|
||||
{
|
||||
if (alloc_type_0) {
|
||||
alloc_type_0 = false;
|
||||
alloc.rbgs.~rbg_bitmap();
|
||||
new (&alloc.interv) prb_interval(prbs);
|
||||
} else {
|
||||
alloc.interv = alloc.interv;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
prb_grant& operator=(const rbg_bitmap& rbgs)
|
||||
{
|
||||
if (alloc_type_0) {
|
||||
alloc.rbgs = rbgs;
|
||||
} else {
|
||||
alloc_type_0 = true;
|
||||
alloc.interv.~prb_interval();
|
||||
new (&alloc.rbgs) rbg_bitmap(rbgs);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
~prb_grant()
|
||||
{
|
||||
if (is_alloc_type0()) {
|
||||
alloc.rbgs.~rbg_bitmap();
|
||||
} else {
|
||||
alloc.interv.~prb_interval();
|
||||
}
|
||||
}
|
||||
|
||||
bool is_alloc_type0() const { return alloc_type_0; }
|
||||
bool is_alloc_type1() const { return not is_alloc_type0(); }
|
||||
const rbg_bitmap& rbgs() const
|
||||
{
|
||||
srsran_assert(is_alloc_type0(), "Invalid access to rbgs() field of grant with alloc type 1");
|
||||
return alloc.rbgs;
|
||||
}
|
||||
const prb_interval& prbs() const
|
||||
{
|
||||
srsran_assert(is_alloc_type1(), "Invalid access to prbs() field of grant with alloc type 0");
|
||||
return alloc.interv;
|
||||
}
|
||||
rbg_bitmap& rbgs()
|
||||
{
|
||||
srsran_assert(is_alloc_type0(), "Invalid access to rbgs() field of grant with alloc type 1");
|
||||
return alloc.rbgs;
|
||||
}
|
||||
prb_interval& prbs()
|
||||
{
|
||||
srsran_assert(is_alloc_type1(), "Invalid access to prbs() field of grant with alloc type 0");
|
||||
return alloc.interv;
|
||||
}
|
||||
|
||||
private:
|
||||
bool alloc_type_0 = false;
|
||||
union alloc_t {
|
||||
rbg_bitmap rbgs;
|
||||
prb_interval interv;
|
||||
|
||||
alloc_t() : interv(0, 0) {}
|
||||
explicit alloc_t(const prb_interval& prbs) : interv(prbs) {}
|
||||
explicit alloc_t(const rbg_bitmap& rbgs_) : rbgs(rbgs_) {}
|
||||
alloc_t(bool type0, const alloc_t& other)
|
||||
{
|
||||
if (type0) {
|
||||
new (&rbgs) rbg_bitmap(other.rbgs);
|
||||
} else {
|
||||
new (&interv) prb_interval(other.interv);
|
||||
}
|
||||
}
|
||||
} alloc;
|
||||
};
|
||||
|
||||
struct bwp_rb_bitmap {
|
||||
public:
|
||||
bwp_rb_bitmap() = default;
|
||||
bwp_rb_bitmap(uint32_t bwp_nof_prbs, uint32_t bwp_prb_start_, bool config1_or_2);
|
||||
|
||||
void reset()
|
||||
{
|
||||
prbs_.reset();
|
||||
rbgs_.reset();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void operator|=(const T& grant)
|
||||
{
|
||||
add(grant);
|
||||
}
|
||||
|
||||
void add(const prb_interval& prbs)
|
||||
{
|
||||
prbs_.fill(prbs.start(), prbs.stop());
|
||||
add_prbs_to_rbgs(prbs);
|
||||
}
|
||||
void add(const prb_bitmap& grant)
|
||||
{
|
||||
prbs_ |= grant;
|
||||
add_prbs_to_rbgs(grant);
|
||||
}
|
||||
void add(const rbg_bitmap& grant)
|
||||
{
|
||||
rbgs_ |= grant;
|
||||
add_rbgs_to_prbs(grant);
|
||||
}
|
||||
void add(const prb_grant& grant)
|
||||
{
|
||||
if (grant.is_alloc_type0()) {
|
||||
add(grant.rbgs());
|
||||
} else {
|
||||
add(grant.prbs());
|
||||
}
|
||||
}
|
||||
bool collides(const prb_grant& grant) const
|
||||
{
|
||||
if (grant.is_alloc_type0()) {
|
||||
return (rbgs() & grant.rbgs()).any();
|
||||
}
|
||||
return prbs().any(grant.prbs().start(), grant.prbs().stop());
|
||||
}
|
||||
bool test(uint32_t prb_idx) { return prbs().test(prb_idx); }
|
||||
void set(uint32_t prb_idx)
|
||||
{
|
||||
prbs_.set(prb_idx);
|
||||
rbgs_.set(prb_to_rbg_idx(prb_idx));
|
||||
}
|
||||
|
||||
const prb_bitmap& prbs() const { return prbs_; }
|
||||
const rbg_bitmap& rbgs() const { return rbgs_; }
|
||||
uint32_t P() const { return P_; }
|
||||
uint32_t nof_prbs() const { return prbs_.size(); }
|
||||
uint32_t nof_rbgs() const { return rbgs_.size(); }
|
||||
|
||||
uint32_t prb_to_rbg_idx(uint32_t prb_idx) const;
|
||||
|
||||
private:
|
||||
prb_bitmap prbs_;
|
||||
rbg_bitmap rbgs_;
|
||||
uint32_t P_ = 0;
|
||||
uint32_t Pnofbits = 0;
|
||||
uint32_t first_rbg_size = 0;
|
||||
|
||||
void add_prbs_to_rbgs(const prb_bitmap& grant);
|
||||
void add_prbs_to_rbgs(const prb_interval& grant);
|
||||
void add_rbgs_to_prbs(const rbg_bitmap& grant);
|
||||
};
|
||||
|
||||
inline prb_interval
|
||||
find_next_empty_interval(const prb_bitmap& mask, size_t start_prb_idx = 0, size_t last_prb_idx = SRSRAN_MAX_PRB_NR)
|
||||
{
|
||||
int rb_start = mask.find_lowest(start_prb_idx, std::min(mask.size(), last_prb_idx), false);
|
||||
if (rb_start != -1) {
|
||||
int rb_end = mask.find_lowest(rb_start + 1, std::min(mask.size(), last_prb_idx), true);
|
||||
return {(uint32_t)rb_start, (uint32_t)(rb_end < 0 ? mask.size() : rb_end)};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
inline prb_interval find_empty_interval_of_length(const prb_bitmap& mask, size_t nof_prbs, uint32_t start_prb_idx = 0)
|
||||
{
|
||||
prb_interval max_interv;
|
||||
do {
|
||||
prb_interval interv = find_next_empty_interval(mask, start_prb_idx, mask.size());
|
||||
if (interv.empty()) {
|
||||
break;
|
||||
}
|
||||
if (interv.length() >= nof_prbs) {
|
||||
max_interv.set(interv.start(), interv.start() + nof_prbs);
|
||||
break;
|
||||
}
|
||||
if (interv.length() > max_interv.length()) {
|
||||
max_interv = interv;
|
||||
}
|
||||
start_prb_idx = interv.stop() + 1;
|
||||
} while (start_prb_idx < mask.size());
|
||||
return max_interv;
|
||||
}
|
||||
|
||||
} // namespace sched_nr_impl
|
||||
} // namespace srsenb
|
||||
|
||||
#endif // SRSRAN_SCHED_NR_RB_H
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "../sched_common.h"
|
||||
#include "lib/include/srsran/adt/circular_array.h"
|
||||
#include "sched_nr_helpers.h"
|
||||
#include "sched_nr_interface.h"
|
||||
#include "sched_nr_pdcch.h"
|
||||
#include "sched_nr_ue.h"
|
||||
|
@ -31,71 +32,76 @@
|
|||
namespace srsenb {
|
||||
namespace sched_nr_impl {
|
||||
|
||||
using pdsch_bitmap = srsran::bounded_bitset<25, true>;
|
||||
using pusch_bitmap = srsran::bounded_bitset<25, true>;
|
||||
struct pending_rar_t;
|
||||
|
||||
using pdsch_t = sched_nr_interface::pdsch_t;
|
||||
using pdsch_list_t = sched_nr_interface::pdsch_list_t;
|
||||
|
||||
using pusch_list = sched_nr_interface::pusch_list;
|
||||
|
||||
struct pucch_t {};
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const static size_t MAX_CORESET_PER_BWP = 3;
|
||||
using slot_coreset_list = srsran::bounded_vector<coreset_region, MAX_CORESET_PER_BWP>;
|
||||
using slot_coreset_list = std::array<srsran::optional<coreset_region>, MAX_CORESET_PER_BWP>;
|
||||
|
||||
using pdsch_t = mac_interface_phy_nr::pdsch_t;
|
||||
using pdsch_list_t = srsran::bounded_vector<pdsch_t, MAX_GRANTS>;
|
||||
|
||||
struct harq_ack_t {
|
||||
const srsran::phy_cfg_nr_t* phy_cfg;
|
||||
srsran_harq_ack_resource_t res;
|
||||
};
|
||||
using harq_ack_list_t = srsran::bounded_vector<harq_ack_t, MAX_GRANTS>;
|
||||
|
||||
struct bwp_slot_grid {
|
||||
pdcch_dl_list_t pdcch_dl_list;
|
||||
pdcch_ul_list_t pdcch_ul_list;
|
||||
slot_coreset_list coresets;
|
||||
pdsch_bitmap dl_rbgs;
|
||||
pdsch_list_t pdsch_grants;
|
||||
pusch_bitmap ul_rbgs;
|
||||
pusch_list pusch_grants;
|
||||
srsran::bounded_vector<pucch_t, SCHED_NR_MAX_PDSCH_DATA> pucch_grants;
|
||||
uint32_t slot_idx;
|
||||
const bwp_params* cfg;
|
||||
|
||||
bool is_dl, is_ul;
|
||||
bwp_rb_bitmap dl_prbs;
|
||||
bwp_rb_bitmap ul_prbs;
|
||||
pdcch_dl_list_t dl_pdcchs;
|
||||
pdcch_ul_list_t ul_pdcchs;
|
||||
pdsch_list_t pdschs;
|
||||
slot_coreset_list coresets;
|
||||
pusch_list_t puschs;
|
||||
harq_ack_list_t pending_acks;
|
||||
|
||||
bwp_slot_grid() = default;
|
||||
explicit bwp_slot_grid(const sched_cell_params& cell_params, uint32_t bwp_id_, uint32_t slot_idx_);
|
||||
explicit bwp_slot_grid(const bwp_params& bwp_params, uint32_t slot_idx_);
|
||||
void reset();
|
||||
};
|
||||
|
||||
struct bwp_res_grid {
|
||||
bwp_res_grid(const sched_cell_params& cell_cfg_, uint32_t bwp_id_);
|
||||
bwp_res_grid(const bwp_params& bwp_cfg_);
|
||||
|
||||
bwp_slot_grid& operator[](tti_point tti) { return slots[tti.sf_idx()]; };
|
||||
const bwp_slot_grid& operator[](tti_point tti) const { return slots[tti.sf_idx()]; };
|
||||
uint32_t id() const { return bwp_id; }
|
||||
uint32_t nof_prbs() const { return cell_cfg->cell_cfg.nof_prb; }
|
||||
bwp_slot_grid& operator[](tti_point tti) { return slots[tti.to_uint() % slots.capacity()]; };
|
||||
const bwp_slot_grid& operator[](tti_point tti) const { return slots[tti.to_uint() % slots.capacity()]; };
|
||||
uint32_t id() const { return cfg->bwp_id; }
|
||||
uint32_t nof_prbs() const { return cfg->cfg.rb_width; }
|
||||
|
||||
const bwp_params* cfg = nullptr;
|
||||
|
||||
private:
|
||||
uint32_t bwp_id;
|
||||
const sched_cell_params* cell_cfg = nullptr;
|
||||
|
||||
srsran::bounded_vector<bwp_slot_grid, TTIMOD_SZ> slots;
|
||||
};
|
||||
|
||||
struct cell_res_grid {
|
||||
const sched_cell_params* cell_cfg = nullptr;
|
||||
srsran::bounded_vector<bwp_res_grid, SCHED_NR_MAX_BWP_PER_CELL> bwps;
|
||||
|
||||
explicit cell_res_grid(const sched_cell_params& cell_cfg);
|
||||
};
|
||||
|
||||
class slot_bwp_sched
|
||||
class bwp_slot_allocator
|
||||
{
|
||||
public:
|
||||
explicit slot_bwp_sched(uint32_t bwp_id, cell_res_grid& phy_grid_);
|
||||
explicit bwp_slot_allocator(bwp_res_grid& bwp_grid_);
|
||||
|
||||
alloc_result alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask);
|
||||
void new_slot(tti_point pdcch_tti_) { pdcch_tti = pdcch_tti_; }
|
||||
|
||||
alloc_result alloc_rar(uint32_t aggr_idx, const pending_rar_t& rar, prb_interval interv, uint32_t max_nof_grants);
|
||||
alloc_result alloc_pdsch(slot_ue& ue, const prb_grant& dl_grant);
|
||||
alloc_result alloc_pusch(slot_ue& ue, const rbgmask_t& dl_mask);
|
||||
|
||||
const sched_cell_params& cfg;
|
||||
tti_point get_pdcch_tti() const { return pdcch_tti; }
|
||||
const bwp_res_grid& res_grid() const { return bwp_grid; }
|
||||
|
||||
const bwp_params& cfg;
|
||||
|
||||
private:
|
||||
srslog::basic_logger& logger;
|
||||
bwp_res_grid& bwp_grid;
|
||||
|
||||
tti_point tti_rx;
|
||||
tti_point pdcch_tti;
|
||||
};
|
||||
|
||||
} // namespace sched_nr_impl
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#ifndef SRSRAN_SCHED_NR_UE_H
|
||||
#define SRSRAN_SCHED_NR_UE_H
|
||||
|
||||
#include "sched_nr_common.h"
|
||||
#include "sched_nr_cfg.h"
|
||||
#include "sched_nr_harq.h"
|
||||
#include "sched_nr_interface.h"
|
||||
#include "srsran/adt/circular_map.h"
|
||||
|
@ -33,35 +33,6 @@ namespace srsenb {
|
|||
|
||||
namespace sched_nr_impl {
|
||||
|
||||
using ue_cfg_t = sched_nr_interface::ue_cfg_t;
|
||||
using ue_cc_cfg_t = sched_nr_interface::ue_cc_cfg_t;
|
||||
|
||||
class ue_cfg_extended : public ue_cfg_t
|
||||
{
|
||||
public:
|
||||
struct search_space_params {
|
||||
srsran_search_space_t* cfg = nullptr;
|
||||
};
|
||||
struct coreset_params {
|
||||
srsran_coreset_t* cfg = nullptr;
|
||||
std::vector<search_space_params*> ss_list;
|
||||
bwp_cce_pos_list cce_positions;
|
||||
};
|
||||
struct bwp_params {
|
||||
std::vector<search_space_params> search_spaces;
|
||||
std::vector<coreset_params> coresets;
|
||||
};
|
||||
struct cc_params {
|
||||
srsran::bounded_vector<bwp_params, SCHED_NR_MAX_BWP_PER_CELL> bwps;
|
||||
};
|
||||
|
||||
uint16_t rnti;
|
||||
std::vector<cc_params> cc_params;
|
||||
|
||||
ue_cfg_extended() = default;
|
||||
explicit ue_cfg_extended(uint16_t rnti, const ue_cfg_t& uecfg);
|
||||
};
|
||||
|
||||
class ue_carrier;
|
||||
|
||||
class slot_ue
|
||||
|
@ -79,19 +50,18 @@ public:
|
|||
uint32_t cc = SCHED_NR_MAX_CARRIERS;
|
||||
|
||||
// UE parameters common to all sectors
|
||||
const ue_cfg_extended* cfg = nullptr;
|
||||
bool pending_sr;
|
||||
const bwp_ue_cfg* cfg = nullptr;
|
||||
bool pending_sr;
|
||||
|
||||
// UE parameters that are sector specific
|
||||
const ue_cc_cfg_t* cc_cfg = nullptr;
|
||||
uint32_t bwp_id;
|
||||
tti_point pdcch_tti;
|
||||
tti_point pdsch_tti;
|
||||
tti_point pusch_tti;
|
||||
tti_point uci_tti;
|
||||
uint32_t dl_cqi;
|
||||
uint32_t ul_cqi;
|
||||
harq_proc* h_dl = nullptr;
|
||||
dl_harq_proc* h_dl = nullptr;
|
||||
harq_proc* h_ul = nullptr;
|
||||
|
||||
private:
|
||||
|
@ -101,8 +71,8 @@ private:
|
|||
class ue_carrier
|
||||
{
|
||||
public:
|
||||
ue_carrier(uint16_t rnti, uint32_t cc, const ue_cfg_t& cfg);
|
||||
slot_ue try_reserve(tti_point pdcch_tti, const ue_cfg_extended& cfg);
|
||||
ue_carrier(uint16_t rnti, const ue_cfg_t& cfg, const sched_cell_params& cell_params_);
|
||||
slot_ue try_reserve(tti_point pdcch_tti, const ue_cfg_t& cfg);
|
||||
void push_feedback(srsran::move_callback<void(ue_carrier&)> callback);
|
||||
|
||||
const uint16_t rnti;
|
||||
|
@ -115,7 +85,8 @@ public:
|
|||
harq_entity harq_ent;
|
||||
|
||||
private:
|
||||
const ue_cfg_t* cfg = nullptr;
|
||||
bwp_ue_cfg bwp_cfg;
|
||||
const sched_cell_params& cell_params;
|
||||
|
||||
resource_guard busy;
|
||||
tti_point last_tti_rx;
|
||||
|
@ -126,7 +97,7 @@ private:
|
|||
class ue
|
||||
{
|
||||
public:
|
||||
ue(uint16_t rnti, const ue_cfg_t& cfg);
|
||||
ue(uint16_t rnti, const ue_cfg_t& cfg, const sched_params& sched_cfg_);
|
||||
|
||||
slot_ue try_reserve(tti_point tti_rx, uint32_t cc);
|
||||
|
||||
|
@ -137,12 +108,13 @@ public:
|
|||
std::array<std::unique_ptr<ue_carrier>, SCHED_NR_MAX_CARRIERS> carriers;
|
||||
|
||||
private:
|
||||
const uint16_t rnti;
|
||||
const uint16_t rnti;
|
||||
const sched_params& sched_cfg;
|
||||
|
||||
bool pending_sr = false;
|
||||
|
||||
int current_idx = 0;
|
||||
std::array<ue_cfg_extended, 4> ue_cfgs;
|
||||
int current_idx = 0;
|
||||
std::array<ue_cfg_t, 4> ue_cfgs;
|
||||
};
|
||||
|
||||
using ue_map_t = srsran::static_circular_map<uint16_t, std::unique_ptr<ue>, SCHED_NR_MAX_USERS>;
|
||||
|
|
|
@ -22,7 +22,8 @@
|
|||
#ifndef SRSRAN_SCHED_NR_WORKER_H
|
||||
#define SRSRAN_SCHED_NR_WORKER_H
|
||||
|
||||
#include "sched_nr_common.h"
|
||||
#include "sched_nr_bwp.h"
|
||||
#include "sched_nr_cfg.h"
|
||||
#include "sched_nr_rb_grid.h"
|
||||
#include "sched_nr_ue.h"
|
||||
#include "srsran/adt/circular_array.h"
|
||||
|
@ -31,19 +32,17 @@
|
|||
#include "srsran/adt/span.h"
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <semaphore.h>
|
||||
|
||||
namespace srsenb {
|
||||
namespace sched_nr_impl {
|
||||
|
||||
using slot_res_t = sched_nr_interface::tti_request_t;
|
||||
using dl_sched_t = sched_nr_interface::dl_sched_t;
|
||||
using ul_sched_t = sched_nr_interface::ul_sched_t;
|
||||
|
||||
class slot_cc_worker
|
||||
{
|
||||
public:
|
||||
explicit slot_cc_worker(const sched_cell_params& cell_params, cell_res_grid& phy_grid) :
|
||||
cfg(cell_params), res_grid(0, phy_grid)
|
||||
{}
|
||||
explicit slot_cc_worker(serv_cell_ctxt& sched);
|
||||
|
||||
void start(tti_point tti_rx_, ue_map_t& ue_db_);
|
||||
void run();
|
||||
|
@ -53,41 +52,50 @@ public:
|
|||
private:
|
||||
void alloc_dl_ues();
|
||||
void alloc_ul_ues();
|
||||
void log_result() const;
|
||||
|
||||
const sched_cell_params& cfg;
|
||||
serv_cell_ctxt& cell;
|
||||
srslog::basic_logger& logger;
|
||||
|
||||
tti_point tti_rx;
|
||||
slot_bwp_sched res_grid;
|
||||
tti_point tti_rx;
|
||||
bwp_slot_allocator bwp_alloc;
|
||||
|
||||
srsran::static_circular_map<uint16_t, slot_ue, SCHED_NR_MAX_USERS> slot_ues;
|
||||
};
|
||||
|
||||
class sched_worker_manager
|
||||
{
|
||||
struct slot_worker_ctxt {
|
||||
std::mutex slot_mutex; // lock of all workers of the same slot.
|
||||
std::condition_variable cvar;
|
||||
tti_point tti_rx;
|
||||
int nof_workers_waiting = 0;
|
||||
std::atomic<int> worker_count{0}; // variable shared across slot_cc_workers
|
||||
std::vector<slot_cc_worker> workers;
|
||||
};
|
||||
|
||||
public:
|
||||
explicit sched_worker_manager(ue_map_t& ue_db_, const sched_params& cfg_);
|
||||
sched_worker_manager(const sched_worker_manager&) = delete;
|
||||
sched_worker_manager(sched_worker_manager&&) = delete;
|
||||
~sched_worker_manager();
|
||||
|
||||
void reserve_workers(tti_point tti_rx);
|
||||
void start_tti(tti_point tti_rx);
|
||||
bool run_tti(tti_point tti_rx, uint32_t cc, sched_nr_interface::tti_request_t& req);
|
||||
void end_tti(tti_point tti_rx);
|
||||
void start_slot(tti_point tti_rx, srsran::move_callback<void()> process_feedback);
|
||||
bool run_slot(tti_point tti_rx, uint32_t cc);
|
||||
void release_slot(tti_point tti_rx);
|
||||
bool save_sched_result(tti_point pdcch_tti, uint32_t cc, dl_sched_t& dl_res, ul_sched_t& ul_res);
|
||||
|
||||
private:
|
||||
const sched_params& cfg;
|
||||
ue_map_t& ue_db;
|
||||
const sched_params& cfg;
|
||||
ue_map_t& ue_db;
|
||||
srslog::basic_logger& logger;
|
||||
|
||||
struct slot_worker_ctxt {
|
||||
sem_t sf_sem; // lock of all workers of the same slot. unlocked by last slot_cc_worker
|
||||
tti_point tti_rx;
|
||||
std::atomic<int> worker_count{0}; // variable shared across slot_cc_workers
|
||||
std::vector<slot_cc_worker> workers;
|
||||
};
|
||||
std::vector<std::unique_ptr<slot_worker_ctxt> > slot_ctxts;
|
||||
std::mutex ue_db_mutex;
|
||||
|
||||
srsran::bounded_vector<cell_res_grid, SCHED_NR_MAX_CARRIERS> cell_grid_list;
|
||||
std::vector<std::unique_ptr<slot_worker_ctxt> > slot_worker_ctxts;
|
||||
|
||||
srsran::bounded_vector<serv_cell_ctxt, SCHED_NR_MAX_CARRIERS> cell_grid_list;
|
||||
|
||||
slot_worker_ctxt& get_sf(tti_point tti_rx);
|
||||
};
|
||||
|
|
|
@ -90,6 +90,7 @@ public:
|
|||
|
||||
private:
|
||||
srslog::basic_logger* logger;
|
||||
std::mutex mutex;
|
||||
|
||||
srsran::static_circular_map<uint32_t, srsran::unique_byte_buffer_t, SRSRAN_FDD_NOF_HARQ * 8> pdu_map;
|
||||
};
|
||||
|
@ -224,7 +225,6 @@ private:
|
|||
|
||||
// Mutexes
|
||||
std::mutex mutex;
|
||||
std::mutex rx_buffers_mutex;
|
||||
};
|
||||
|
||||
} // namespace srsenb
|
||||
|
|
|
@ -40,12 +40,18 @@ struct rrc_cfg_sr_t {
|
|||
};
|
||||
|
||||
struct rrc_cfg_qci_t {
|
||||
bool configured = false;
|
||||
bool configured = false;
|
||||
int enb_dl_max_retx_thres = -1;
|
||||
asn1::rrc::lc_ch_cfg_s::ul_specific_params_s_ lc_cfg;
|
||||
asn1::rrc::pdcp_cfg_s pdcp_cfg;
|
||||
asn1::rrc::rlc_cfg_c rlc_cfg;
|
||||
};
|
||||
|
||||
struct srb_cfg_t {
|
||||
int enb_dl_max_retx_thres = -1;
|
||||
asn1::rrc::srb_to_add_mod_s::rlc_cfg_c_ rlc_cfg;
|
||||
};
|
||||
|
||||
struct rrc_cfg_t {
|
||||
uint32_t enb_id; ///< Required to pack SIB1
|
||||
// Per eNB SIBs
|
||||
|
@ -71,6 +77,8 @@ struct rrc_cfg_t {
|
|||
uint32_t max_mac_dl_kos;
|
||||
uint32_t max_mac_ul_kos;
|
||||
uint32_t rlf_release_timer_ms;
|
||||
srb_cfg_t srb1_cfg;
|
||||
srb_cfg_t srb2_cfg;
|
||||
};
|
||||
|
||||
constexpr uint32_t UE_PCELL_CC_IDX = 0;
|
||||
|
|
|
@ -40,6 +40,8 @@ struct rrc_cfg_cqi_t {
|
|||
uint32_t nof_prb;
|
||||
uint32_t period;
|
||||
uint32_t m_ri;
|
||||
bool is_subband_enabled;
|
||||
uint32_t subband_k;
|
||||
bool simultaneousAckCQI;
|
||||
rrc_cfg_cqi_mode_t mode;
|
||||
};
|
||||
|
|
|
@ -1,6 +1,41 @@
|
|||
|
||||
// All times are in ms. Use -1 for infinity, where available
|
||||
|
||||
// srb1_config = {
|
||||
// rlc_config = {
|
||||
// ul_am = {
|
||||
// t_poll_retx = 45;
|
||||
// poll_pdu = -1;
|
||||
// poll_byte = -1;
|
||||
// max_retx_thresh = 4;
|
||||
// };
|
||||
// dl_am = {
|
||||
// t_reordering = 35;
|
||||
// t_status_prohibit = 0;
|
||||
// };
|
||||
// };
|
||||
// enb_specific = {
|
||||
// dl_max_retx_thresh = 32;
|
||||
// };
|
||||
// }
|
||||
|
||||
// srb2_config = {
|
||||
// rlc_config = {
|
||||
// ul_am = {
|
||||
// t_poll_retx = 45;
|
||||
// poll_pdu = -1;
|
||||
// poll_byte = -1;
|
||||
// max_retx_thresh = 4;
|
||||
// };
|
||||
// dl_am = {
|
||||
// t_reordering = 35;
|
||||
// t_status_prohibit = 0;
|
||||
// };
|
||||
// };
|
||||
// enb_specific = {
|
||||
// dl_max_retx_thresh = 32;
|
||||
// };
|
||||
// }
|
||||
|
||||
qci_config = (
|
||||
|
||||
{
|
||||
|
@ -24,6 +59,9 @@ qci_config = (
|
|||
bucket_size_duration = 100;
|
||||
log_chan_group = 2;
|
||||
};
|
||||
enb_specific = {
|
||||
dl_max_retx_thresh = 32;
|
||||
};
|
||||
},
|
||||
{
|
||||
qci=9;
|
||||
|
@ -49,6 +87,9 @@ qci_config = (
|
|||
bucket_size_duration = 100;
|
||||
log_chan_group = 3;
|
||||
};
|
||||
enb_specific = {
|
||||
dl_max_retx_thresh = 32;
|
||||
};
|
||||
}
|
||||
|
||||
);
|
|
@ -47,6 +47,7 @@ phy_cnfg =
|
|||
//subframe = [0, 10, 20, 30]; // Optional vector of subframe indices every period where CQI resources will be allocated (default uses all)
|
||||
nof_prb = 1;
|
||||
m_ri = 8; // RI period in CQI period
|
||||
//subband_k = 1; // If enabled and > 0, configures sub-band CQI reporting and defines K (see 36.213 7.2.2). If disabled, configures wideband CQI
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ add_executable(srsenb main.cc enb.cc metrics_stdout.cc metrics_csv.cc metrics_js
|
|||
set(SRSENB_SOURCES srsenb_phy srsenb_stack srsenb_common srsenb_s1ap srsenb_upper srsenb_mac srsenb_rrc srslog system)
|
||||
set(SRSRAN_SOURCES srsran_common srsran_mac srsran_phy srsran_gtpu srsran_rlc srsran_pdcp srsran_radio rrc_asn1 s1ap_asn1 enb_cfg_parser srslog system)
|
||||
|
||||
set(SRSENB_SOURCES ${SRSENB_SOURCES} srsgnb_phy srsgnb_stack srsgnb_ngap srsgnb_upper srsgnb_mac srsgnb_rrc)
|
||||
set(SRSENB_SOURCES ${SRSENB_SOURCES} srsgnb_stack srsgnb_ngap srsgnb_upper srsgnb_mac srsgnb_rrc)
|
||||
set(SRSRAN_SOURCES ${SRSRAN_SOURCES} rrc_nr_asn1 ngap_nr_asn1)
|
||||
|
||||
target_link_libraries(srsenb ${SRSENB_SOURCES}
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
*/
|
||||
|
||||
#include "srsenb/hdr/enb.h"
|
||||
#include "srsenb/hdr/phy/vnf_phy_nr.h"
|
||||
#include "srsenb/hdr/stack/enb_stack_lte.h"
|
||||
#include "srsenb/hdr/stack/gnb_stack_nr.h"
|
||||
#include "srsenb/src/enb_cfg_parser.h"
|
||||
|
@ -104,40 +103,9 @@ int enb::init(const all_args_t& args_)
|
|||
phy = std::move(lte_phy);
|
||||
radio = std::move(lte_radio);
|
||||
|
||||
} else if (args.stack.type == "nr") {
|
||||
std::unique_ptr<srsenb::gnb_stack_nr> nr_stack(new srsenb::gnb_stack_nr);
|
||||
std::unique_ptr<srsran::radio_null> nr_radio(new srsran::radio_null);
|
||||
std::unique_ptr<srsenb::vnf_phy_nr> nr_phy(new srsenb::vnf_phy_nr);
|
||||
|
||||
// Init layers
|
||||
if (nr_radio->init(args.rf, nullptr)) {
|
||||
srsran::console("Error initializing radio.\n");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// TODO: where do we put this?
|
||||
srsenb::nr_phy_cfg_t nr_phy_cfg = {};
|
||||
|
||||
args.phy.vnf_args.type = "gnb";
|
||||
args.phy.vnf_args.log_level = args.phy.log.phy_level;
|
||||
args.phy.vnf_args.log_hex_limit = args.phy.log.phy_hex_limit;
|
||||
if (nr_phy->init(args.phy, nr_phy_cfg, nr_stack.get())) {
|
||||
srsran::console("Error initializing PHY.\n");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Same here, where do we put this?
|
||||
srsenb::rrc_nr_cfg_t rrc_nr_cfg = {};
|
||||
rrc_nr_cfg.coreless = args.stack.coreless;
|
||||
|
||||
if (nr_stack->init(args.stack, rrc_nr_cfg, nr_phy.get())) {
|
||||
srsran::console("Error initializing stack.\n");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
stack = std::move(nr_stack);
|
||||
phy = std::move(nr_phy);
|
||||
radio = std::move(nr_radio);
|
||||
} else {
|
||||
srsran::console("Stack type %s not supported.\n", args.stack.type.c_str());
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
started = true; // set to true in any case to allow stopping the eNB if an error happened
|
||||
|
|
|
@ -82,7 +82,7 @@ int field_sched_info::parse(libconfig::Setting& root)
|
|||
for (uint32_t i = 0; i < data->sched_info_list.size(); i++) {
|
||||
if (not parse_enum_by_number(data->sched_info_list[i].si_periodicity, "si_periodicity", root[i])) {
|
||||
fprintf(stderr, "Missing field si_periodicity in sched_info=%d\n", i);
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
if (root[i].exists("si_mapping_info")) {
|
||||
data->sched_info_list[i].sib_map_info.resize((uint32_t)root[i]["si_mapping_info"].getLength());
|
||||
|
@ -93,12 +93,12 @@ int field_sched_info::parse(libconfig::Setting& root)
|
|||
data->sched_info_list[i].sib_map_info[j].value = (sib_type_e::options)(sib_index - 3);
|
||||
} else {
|
||||
fprintf(stderr, "Invalid SIB index %d for si_mapping_info=%d in sched_info=%d\n", sib_index, j, i);
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Number of si_mapping_info values exceeds maximum (%d)\n", ASN1_RRC_MAX_SIB);
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
} else {
|
||||
data->sched_info_list[i].sib_map_info.resize(0);
|
||||
|
@ -114,13 +114,13 @@ int field_intra_neigh_cell_list::parse(libconfig::Setting& root)
|
|||
for (uint32_t i = 0; i < data->intra_freq_neigh_cell_list.size() && i < ASN1_RRC_MAX_CELL_INTRA; i++) {
|
||||
if (not parse_enum_by_number(data->intra_freq_neigh_cell_list[i].q_offset_cell, "q_offset_range", root[i])) {
|
||||
fprintf(stderr, "Missing field q_offset_range in neigh_cell=%d\n", i);
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
int phys_cell_id = 0;
|
||||
if (!root[i].lookupValue("phys_cell_id", phys_cell_id)) {
|
||||
fprintf(stderr, "Missing field phys_cell_id in neigh_cell=%d\n", i);
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
data->intra_freq_neigh_cell_list[i].pci = (uint16)phys_cell_id;
|
||||
}
|
||||
|
@ -134,14 +134,14 @@ int field_intra_black_cell_list::parse(libconfig::Setting& root)
|
|||
for (uint32_t i = 0; i < data->intra_freq_black_cell_list.size() && i < ASN1_RRC_MAX_CELL_BLACK; i++) {
|
||||
if (not parse_enum_by_number(data->intra_freq_black_cell_list[i].range, "range", root[i])) {
|
||||
fprintf(stderr, "Missing field range in black_cell=%d\n", i);
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
data->intra_freq_black_cell_list[i].range_present = true;
|
||||
|
||||
int start = 0;
|
||||
if (!root[i].lookupValue("start", start)) {
|
||||
fprintf(stderr, "Missing field start in black_cell=%d\n", i);
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
data->intra_freq_black_cell_list[i].start = (uint16)start;
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ int field_carrier_freqs_info_list::parse(libconfig::Setting& root)
|
|||
data->carrier_freqs_info_list_present = data->carrier_freqs_info_list.size() > 0;
|
||||
if (data->carrier_freqs_info_list.size() > ASN1_RRC_MAX_GNFG) {
|
||||
ERROR("CarrierFreqsInfoGERAN cannot have more than %d entries", ASN1_RRC_MAX_GNFG);
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
for (uint32_t i = 0; i < data->carrier_freqs_info_list.size(); i++) {
|
||||
int cell_resel_prio;
|
||||
|
@ -173,27 +173,27 @@ int field_carrier_freqs_info_list::parse(libconfig::Setting& root)
|
|||
"ncc_permitted", &data->carrier_freqs_info_list[i].common_info.ncc_permitted);
|
||||
if (ncc_permitted.parse(root[i])) {
|
||||
ERROR("Error parsing `ncc_permitted` in carrier_freqs_info_lsit=%d", i);
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
int q_rx_lev_min = 0;
|
||||
if (!root[i].lookupValue("q_rx_lev_min", q_rx_lev_min)) {
|
||||
ERROR("Missing field `q_rx_lev_min` in carrier_freqs_info_list=%d", i);
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
data->carrier_freqs_info_list[i].common_info.q_rx_lev_min = q_rx_lev_min;
|
||||
|
||||
int thresh_x_high = 0;
|
||||
if (!root[i].lookupValue("thresh_x_high", thresh_x_high)) {
|
||||
ERROR("Missing field `thresh_x_high` in carrier_freqs_info_list=%d", i);
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
data->carrier_freqs_info_list[i].common_info.thresh_x_high = thresh_x_high;
|
||||
|
||||
int thresh_x_low = 0;
|
||||
if (!root[i].lookupValue("thresh_x_low", thresh_x_low)) {
|
||||
ERROR("Missing field `thresh_x_low` in carrier_freqs_info_list=%d", i);
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
data->carrier_freqs_info_list[i].common_info.thresh_x_low = thresh_x_low;
|
||||
|
||||
|
@ -206,7 +206,7 @@ int field_carrier_freqs_info_list::parse(libconfig::Setting& root)
|
|||
&data->carrier_freqs_info_list[i].carrier_freqs.band_ind);
|
||||
if (band_ind.parse(root[i])) {
|
||||
ERROR("Error parsing `band_ind` in carrier_freqs_info_list=%d", i);
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
data->carrier_freqs_info_list[i].carrier_freqs.following_arfcns.set_explicit_list_of_arfcns();
|
||||
|
@ -222,12 +222,12 @@ int field_carrier_freqs_info_list::parse(libconfig::Setting& root)
|
|||
exp_l[j] = (short unsigned int)arfcn;
|
||||
} else {
|
||||
fprintf(stderr, "Invalid ARFCN %d in for carrier_freqs_info_list=%d explicit_list_of_arfcns\n", i, j);
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Number of ARFCN in explicit_list_of_arfcns exceeds maximum (%d)\n", 31);
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
} else {
|
||||
exp_l.resize(0);
|
||||
|
@ -273,7 +273,7 @@ int mbsfn_sf_cfg_list_parser::parse(Setting& root)
|
|||
}
|
||||
if (len > 1) {
|
||||
fprintf(stderr, "Only mbsfnSubframeConfigListLengths of size 1 are supported\n");
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
*enabled = true;
|
||||
mbsfn_list->resize(len);
|
||||
|
@ -315,53 +315,53 @@ int mbsfn_area_info_list_parser::parse(Setting& root)
|
|||
&mbsfn_item->non_mbsfn_region_len);
|
||||
if (fieldlen.parse(root["mbsfn_area_info_list"])) {
|
||||
fprintf(stderr, "Error parsing non_mbsfn_region_length\n");
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
field_asn1_enum_str<mbsfn_area_info_r9_s::mcch_cfg_r9_s_::mcch_repeat_period_r9_e_> repeat(
|
||||
"mcch_repetition_period", &mbsfn_item->mcch_cfg_r9.mcch_repeat_period_r9);
|
||||
if (repeat.parse(root["mbsfn_area_info_list"])) {
|
||||
fprintf(stderr, "Error parsing mcch_repetition_period\n");
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
field_asn1_enum_str<mbsfn_area_info_r9_s::mcch_cfg_r9_s_::mcch_mod_period_r9_e_> mod(
|
||||
"mcch_modification_period", &mbsfn_item->mcch_cfg_r9.mcch_mod_period_r9);
|
||||
if (mod.parse(root["mbsfn_area_info_list"])) {
|
||||
fprintf(stderr, "Error parsing mcch_modification_period\n");
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
field_asn1_enum_str<mbsfn_area_info_r9_s::mcch_cfg_r9_s_::sig_mcs_r9_e_> sig("signalling_mcs",
|
||||
&mbsfn_item->mcch_cfg_r9.sig_mcs_r9);
|
||||
if (sig.parse(root["mbsfn_area_info_list"])) {
|
||||
fprintf(stderr, "Error parsing signalling_mcs\n");
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
parser::field<uint16_t> areaid("mbsfn_area_id", &mbsfn_item->mbsfn_area_id_r9);
|
||||
if (areaid.parse(root["mbsfn_area_info_list"])) {
|
||||
fprintf(stderr, "Error parsing mbsfn_area_id\n");
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
parser::field<uint8_t> notif_ind("notification_indicator", &mbsfn_item->notif_ind_r9);
|
||||
if (notif_ind.parse(root["mbsfn_area_info_list"])) {
|
||||
fprintf(stderr, "Error parsing notification_indicator\n");
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
parser::field<uint8_t> offset("mcch_offset", &mbsfn_item->mcch_cfg_r9.mcch_offset_r9);
|
||||
if (offset.parse(root["mbsfn_area_info_list"])) {
|
||||
fprintf(stderr, "Error parsing mcch_offset\n");
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
field_asn1_bitstring_number<asn1::fixed_bitstring<6>, uint8_t> alloc_info("sf_alloc_info",
|
||||
&mbsfn_item->mcch_cfg_r9.sf_alloc_info_r9);
|
||||
if (alloc_info.parse(root["mbsfn_area_info_list"])) {
|
||||
fprintf(stderr, "Error parsing mbsfn_area_info_list\n");
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -395,17 +395,83 @@ int phr_cnfg_parser::parse(libconfig::Setting& root)
|
|||
mac_main_cfg_s::phr_cfg_c_::setup_s_& s = phr_cfg->setup();
|
||||
|
||||
if (not parse_enum_by_str(s.dl_pathloss_change, "dl_pathloss_change", root["phr_cnfg"])) {
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
if (not parse_enum_by_number(s.periodic_phr_timer, "periodic_phr_timer", root["phr_cnfg"])) {
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
if (not parse_enum_by_number(s.prohibit_phr_timer, "prohibit_phr_timer", root["phr_cnfg"])) {
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int field_srb::parse(libconfig::Setting& root)
|
||||
{
|
||||
// Parse RLC AM section
|
||||
rlc_cfg_c* rlc_cfg = &cfg.rlc_cfg.set_explicit_value();
|
||||
if (root.exists("ul_am") && root.exists("dl_am")) {
|
||||
rlc_cfg->set_am();
|
||||
}
|
||||
|
||||
// RLC-UM Should not exist section
|
||||
if (root.exists("ul_um") || root.exists("dl_um")) {
|
||||
ERROR("Error SRBs must be AM.");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Parse RLC-AM section
|
||||
if (root.exists("ul_am")) {
|
||||
ul_am_rlc_s* am_rlc = &rlc_cfg->am().ul_am_rlc;
|
||||
|
||||
field_asn1_enum_number<t_poll_retx_e> t_poll_retx("t_poll_retx", &am_rlc->t_poll_retx);
|
||||
if (t_poll_retx.parse(root["ul_am"])) {
|
||||
ERROR("Error can't find t_poll_retx in section ul_am");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
field_asn1_enum_number<poll_pdu_e> poll_pdu("poll_pdu", &am_rlc->poll_pdu);
|
||||
if (poll_pdu.parse(root["ul_am"])) {
|
||||
ERROR("Error can't find poll_pdu in section ul_am");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
field_asn1_enum_number<poll_byte_e> poll_byte("poll_byte", &am_rlc->poll_byte);
|
||||
if (poll_byte.parse(root["ul_am"])) {
|
||||
ERROR("Error can't find poll_byte in section ul_am");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
field_asn1_enum_number<ul_am_rlc_s::max_retx_thres_e_> max_retx_thresh("max_retx_thresh", &am_rlc->max_retx_thres);
|
||||
if (max_retx_thresh.parse(root["ul_am"])) {
|
||||
ERROR("Error can't find max_retx_thresh in section ul_am");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (root.exists("dl_am")) {
|
||||
dl_am_rlc_s* am_rlc = &rlc_cfg->am().dl_am_rlc;
|
||||
|
||||
field_asn1_enum_number<t_reordering_e> t_reordering("t_reordering", &am_rlc->t_reordering);
|
||||
if (t_reordering.parse(root["dl_am"])) {
|
||||
ERROR("Error can't find t_reordering in section dl_am");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
field_asn1_enum_number<t_status_prohibit_e> t_status_prohibit("t_status_prohibit", &am_rlc->t_status_prohibit);
|
||||
if (t_status_prohibit.parse(root["dl_am"])) {
|
||||
ERROR("Error can't find t_status_prohibit in section dl_am");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (root.exists("enb_specific")) {
|
||||
cfg.enb_dl_max_retx_thres = (int)root["enb_specific"]["dl_max_retx_thresh"];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int field_qci::parse(libconfig::Setting& root)
|
||||
{
|
||||
auto nof_qci = (uint32_t)root.getLength();
|
||||
|
@ -418,7 +484,7 @@ int field_qci::parse(libconfig::Setting& root)
|
|||
// Parse PDCP section
|
||||
if (!q.exists("pdcp_config")) {
|
||||
fprintf(stderr, "Error section pdcp_config not found for qci=%d\n", qci);
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
rrc_cfg_qci_t qcicfg;
|
||||
|
@ -447,7 +513,7 @@ int field_qci::parse(libconfig::Setting& root)
|
|||
rlc_cfg->set_um_uni_dir_dl();
|
||||
} else {
|
||||
fprintf(stderr, "Invalid combination of UL/DL UM/AM for qci=%d\n", qci);
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Parse RLC-UM section
|
||||
|
@ -462,7 +528,7 @@ int field_qci::parse(libconfig::Setting& root)
|
|||
field_asn1_enum_number<sn_field_len_e> sn_field_len("sn_field_length", &um_rlc->sn_field_len);
|
||||
if (sn_field_len.parse(q["rlc_config"]["ul_um"])) {
|
||||
ERROR("Error can't find sn_field_length in section ul_um");
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -477,13 +543,13 @@ int field_qci::parse(libconfig::Setting& root)
|
|||
field_asn1_enum_number<sn_field_len_e> sn_field_len("sn_field_length", &um_rlc->sn_field_len);
|
||||
if (sn_field_len.parse(q["rlc_config"]["dl_um"])) {
|
||||
ERROR("Error can't find sn_field_length in section dl_um");
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
field_asn1_enum_number<t_reordering_e> t_reordering("t_reordering", &um_rlc->t_reordering);
|
||||
if (t_reordering.parse(q["rlc_config"]["dl_um"])) {
|
||||
ERROR("Error can't find t_reordering in section dl_um");
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -494,26 +560,26 @@ int field_qci::parse(libconfig::Setting& root)
|
|||
field_asn1_enum_number<t_poll_retx_e> t_poll_retx("t_poll_retx", &am_rlc->t_poll_retx);
|
||||
if (t_poll_retx.parse(q["rlc_config"]["ul_am"])) {
|
||||
ERROR("Error can't find t_poll_retx in section ul_am");
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
field_asn1_enum_number<poll_pdu_e> poll_pdu("poll_pdu", &am_rlc->poll_pdu);
|
||||
if (poll_pdu.parse(q["rlc_config"]["ul_am"])) {
|
||||
ERROR("Error can't find poll_pdu in section ul_am");
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
field_asn1_enum_number<poll_byte_e> poll_byte("poll_byte", &am_rlc->poll_byte);
|
||||
if (poll_byte.parse(q["rlc_config"]["ul_am"])) {
|
||||
ERROR("Error can't find poll_byte in section ul_am");
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
field_asn1_enum_number<ul_am_rlc_s::max_retx_thres_e_> max_retx_thresh("max_retx_thresh",
|
||||
&am_rlc->max_retx_thres);
|
||||
if (max_retx_thresh.parse(q["rlc_config"]["ul_am"])) {
|
||||
ERROR("Error can't find max_retx_thresh in section ul_am");
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -523,20 +589,20 @@ int field_qci::parse(libconfig::Setting& root)
|
|||
field_asn1_enum_number<t_reordering_e> t_reordering("t_reordering", &am_rlc->t_reordering);
|
||||
if (t_reordering.parse(q["rlc_config"]["dl_am"])) {
|
||||
ERROR("Error can't find t_reordering in section dl_am");
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
field_asn1_enum_number<t_status_prohibit_e> t_status_prohibit("t_status_prohibit", &am_rlc->t_status_prohibit);
|
||||
if (t_status_prohibit.parse(q["rlc_config"]["dl_am"])) {
|
||||
ERROR("Error can't find t_status_prohibit in section dl_am");
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse logical channel configuration section
|
||||
if (!q.exists("logical_channel_config")) {
|
||||
fprintf(stderr, "Error section logical_channel_config not found for qci=%d\n", qci);
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
lc_ch_cfg_s::ul_specific_params_s_* lc_cfg = &qcicfg.lc_cfg;
|
||||
|
@ -544,26 +610,31 @@ int field_qci::parse(libconfig::Setting& root)
|
|||
parser::field<uint8> priority("priority", &lc_cfg->prio);
|
||||
if (priority.parse(q["logical_channel_config"])) {
|
||||
ERROR("Error can't find logical_channel_config in section priority");
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
field_asn1_enum_number<lc_ch_cfg_s::ul_specific_params_s_::prioritised_bit_rate_e_> prioritised_bit_rate(
|
||||
"prioritized_bit_rate", &lc_cfg->prioritised_bit_rate);
|
||||
if (prioritised_bit_rate.parse(q["logical_channel_config"])) {
|
||||
fprintf(stderr, "Error can't find prioritized_bit_rate in section logical_channel_config\n");
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
field_asn1_enum_number<lc_ch_cfg_s::ul_specific_params_s_::bucket_size_dur_e_> bucket_size_duration(
|
||||
"bucket_size_duration", &lc_cfg->bucket_size_dur);
|
||||
if (bucket_size_duration.parse(q["logical_channel_config"])) {
|
||||
ERROR("Error can't find bucket_size_duration in section logical_channel_config");
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
parser::field<uint8> log_chan_group("log_chan_group", &lc_cfg->lc_ch_group);
|
||||
lc_cfg->lc_ch_group_present = not log_chan_group.parse(q["logical_channel_config"]);
|
||||
qcicfg.configured = true;
|
||||
|
||||
if (q.exists("enb_specific")) {
|
||||
qcicfg.enb_dl_max_retx_thres = (int)q["enb_specific"]["dl_max_retx_thresh"];
|
||||
}
|
||||
|
||||
cfg.insert(std::make_pair(qci, qcicfg));
|
||||
}
|
||||
|
||||
|
@ -674,6 +745,8 @@ int parse_rr(all_args_t* args_, rrc_cfg_t* rrc_cfg_)
|
|||
cqi_report_cnfg.add_field(new parser::field<uint32>("period", &rrc_cfg_->cqi_cfg.period));
|
||||
cqi_report_cnfg.add_field(new parser::field<uint32>("m_ri", &rrc_cfg_->cqi_cfg.m_ri));
|
||||
cqi_report_cnfg.add_field(new parser::field<uint32>("nof_prb", &rrc_cfg_->cqi_cfg.nof_prb));
|
||||
cqi_report_cnfg.add_field(
|
||||
new parser::field<uint32>("subband_k", &rrc_cfg_->cqi_cfg.subband_k, &rrc_cfg_->cqi_cfg.is_subband_enabled));
|
||||
cqi_report_cnfg.add_field(new parser::field<bool>("simultaneousAckCQI", &rrc_cfg_->cqi_cfg.simultaneousAckCQI));
|
||||
cqi_report_cnfg.add_field(new field_sf_mapping(rrc_cfg_->cqi_cfg.sf_mapping, &rrc_cfg_->cqi_cfg.nof_subframes, 1));
|
||||
|
||||
|
@ -789,7 +862,7 @@ static int parse_cell_list(all_args_t* args, rrc_cfg_t* rrc_cfg, Setting& root)
|
|||
HANDLEPARSERCODE(parse_meas_cell_list(&cell_cfg.meas_cfg, cellroot["meas_cell_list"]));
|
||||
if (not cellroot.exists("meas_report_desc")) {
|
||||
ERROR("PARSER ERROR: \"ho_active\" is set to true, but field \"meas_report_desc\" doesn't exist.\n");
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
HANDLEPARSERCODE(parse_meas_report_desc(&cell_cfg.meas_cfg, cellroot["meas_report_desc"]));
|
||||
}
|
||||
|
@ -815,13 +888,13 @@ static int parse_cell_list(all_args_t* args, rrc_cfg_t* rrc_cfg, Setting& root)
|
|||
// Check RF port is not repeated
|
||||
if (it->rf_port == it2->rf_port) {
|
||||
ERROR("Repeated RF port for multiple cells");
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Check cell ID is not repeated
|
||||
if (it->cell_id == it2->cell_id) {
|
||||
ERROR("Repeated Cell identifier");
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1535,7 +1608,7 @@ int parse_sib9(std::string filename, sib_type9_s* data)
|
|||
}
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1581,19 +1654,19 @@ int parse_sibs(all_args_t* args_, rrc_cfg_t* rrc_cfg_, srsenb::phy_cfg_t* phy_co
|
|||
std::string mnc_str;
|
||||
if (not srsran::mnc_to_string(args_->stack.s1ap.mnc, &mnc_str)) {
|
||||
ERROR("The provided mnc=%d is not valid", args_->stack.s1ap.mnc);
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
std::string mcc_str;
|
||||
if (not srsran::mcc_to_string(args_->stack.s1ap.mcc, &mcc_str)) {
|
||||
ERROR("The provided mnc=%d is not valid", args_->stack.s1ap.mcc);
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
sib_type1_s::cell_access_related_info_s_* cell_access = &sib1->cell_access_related_info;
|
||||
cell_access->plmn_id_list.resize(1);
|
||||
srsran::plmn_id_t plmn;
|
||||
if (plmn.from_string(mcc_str + mnc_str) == SRSRAN_ERROR) {
|
||||
ERROR("Could not convert %s to a plmn_id", (mcc_str + mnc_str).c_str());
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
srsran::to_asn1(&cell_access->plmn_id_list[0].plmn_id, plmn);
|
||||
cell_access->plmn_id_list[0].cell_reserved_for_oper = plmn_id_info_s::cell_reserved_for_oper_e_::not_reserved;
|
||||
|
@ -1619,7 +1692,7 @@ int parse_sibs(all_args_t* args_, rrc_cfg_t* rrc_cfg_, srsenb::phy_cfg_t* phy_co
|
|||
// verify SIB13 is available
|
||||
if (not sib_is_present(sib1->sched_info_list, sib_type_e::sib_type13_v920)) {
|
||||
fprintf(stderr, "SIB13 not present in sched_info.\n");
|
||||
return -1;
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1673,9 +1746,40 @@ namespace drb_sections {
|
|||
|
||||
int parse_drb(all_args_t* args_, rrc_cfg_t* rrc_cfg_)
|
||||
{
|
||||
parser::section srb1("srb1_config");
|
||||
bool srb1_present = false;
|
||||
srb1.set_optional(&srb1_present);
|
||||
|
||||
parser::section srb1_rlc_cfg("rlc_config");
|
||||
srb1.add_subsection(&srb1_rlc_cfg);
|
||||
srb1_rlc_cfg.add_field(new field_srb(rrc_cfg_->srb1_cfg));
|
||||
|
||||
parser::section srb2("srb2_config");
|
||||
bool srb2_present = false;
|
||||
srb2.set_optional(&srb2_present);
|
||||
|
||||
parser::section srb2_rlc_cfg("rlc_config");
|
||||
srb2.add_subsection(&srb2_rlc_cfg);
|
||||
srb2_rlc_cfg.add_field(new field_srb(rrc_cfg_->srb2_cfg));
|
||||
|
||||
parser::section qci("qci_config");
|
||||
qci.add_field(new field_qci(rrc_cfg_->qci_cfg));
|
||||
return parser::parse_section(args_->enb_files.drb_config, &qci);
|
||||
|
||||
// Run parser with two sections
|
||||
parser p(args_->enb_files.rb_config);
|
||||
p.add_section(&srb1);
|
||||
p.add_section(&srb2);
|
||||
p.add_section(&qci);
|
||||
|
||||
int ret = p.parse();
|
||||
if (not srb1_present) {
|
||||
rrc_cfg_->srb1_cfg.rlc_cfg.set_default_value();
|
||||
}
|
||||
if (not srb2_present) {
|
||||
rrc_cfg_->srb2_cfg.rlc_cfg.set_default_value();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace drb_sections
|
||||
|
|
|
@ -155,6 +155,18 @@ private:
|
|||
uint32_t default_offset;
|
||||
};
|
||||
|
||||
class field_srb final : public parser::field_itf
|
||||
{
|
||||
public:
|
||||
explicit field_srb(srb_cfg_t& cfg_) : cfg(cfg_) {}
|
||||
const char* get_name() override { return "field_srb"; }
|
||||
|
||||
int parse(Setting& root) override;
|
||||
|
||||
private:
|
||||
srb_cfg_t& cfg;
|
||||
};
|
||||
|
||||
class field_qci final : public parser::field_itf
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -54,7 +54,8 @@ namespace bpo = boost::program_options;
|
|||
/**********************************************************************
|
||||
* Program arguments processing
|
||||
***********************************************************************/
|
||||
string config_file;
|
||||
string config_file;
|
||||
static bool stdout_ts_enable = false;
|
||||
|
||||
void parse_args(all_args_t* args, int argc, char* argv[])
|
||||
{
|
||||
|
@ -92,7 +93,7 @@ void parse_args(all_args_t* args, int argc, char* argv[])
|
|||
|
||||
("enb_files.sib_config", bpo::value<string>(&args->enb_files.sib_config)->default_value("sib.conf"), "SIB configuration files")
|
||||
("enb_files.rr_config", bpo::value<string>(&args->enb_files.rr_config)->default_value("rr.conf"), "RR configuration files")
|
||||
("enb_files.drb_config", bpo::value<string>(&args->enb_files.drb_config)->default_value("drb.conf"), "DRB configuration files")
|
||||
("enb_files.rb_config", bpo::value<string>(&args->enb_files.rb_config)->default_value("rb.conf"), "SRB/DRB configuration files")
|
||||
|
||||
("rf.dl_earfcn", bpo::value<uint32_t>(&args->enb.dl_earfcn)->default_value(0), "Force Downlink EARFCN for single cell")
|
||||
("rf.srate", bpo::value<double>(&args->rf.srate_hz)->default_value(0.0), "Force Tx and Rx sampling rate in Hz")
|
||||
|
@ -171,6 +172,8 @@ void parse_args(all_args_t* args, int argc, char* argv[])
|
|||
("scheduler.init_ul_snr_value", bpo::value<int>(&args->stack.mac.sched.init_ul_snr_value)->default_value(5), "Initial UL SNR value used for computing MCS in the first UL grant")
|
||||
("scheduler.init_dl_cqi", bpo::value<int>(&args->stack.mac.sched.init_dl_cqi)->default_value(5), "DL CQI value used before any CQI report is available to the eNB")
|
||||
("scheduler.max_sib_coderate", bpo::value<float>(&args->stack.mac.sched.max_sib_coderate)->default_value(0.8), "Upper bound on SIB and RAR grants coderate")
|
||||
("scheduler.pdcch_cqi_offset", bpo::value<int>(&args->stack.mac.sched.pdcch_cqi_offset)->default_value(0), "CQI offset in derivation of PDCCH aggregation level")
|
||||
|
||||
|
||||
|
||||
/* Downlink Channel emulator section */
|
||||
|
@ -233,6 +236,7 @@ void parse_args(all_args_t* args, int argc, char* argv[])
|
|||
("expert.tracing_enable", bpo::value<bool>(&args->general.tracing_enable)->default_value(false), "Events tracing")
|
||||
("expert.tracing_filename", bpo::value<string>(&args->general.tracing_filename)->default_value("/tmp/enb_tracing.log"), "Tracing events filename")
|
||||
("expert.tracing_buffcapacity", bpo::value<std::size_t>(&args->general.tracing_buffcapacity)->default_value(1000000), "Tracing buffer capcity")
|
||||
("expert.stdout_ts_enable", bpo::value<bool>(&stdout_ts_enable)->default_value(false), "Prints once per second the timestamp into stdout")
|
||||
("expert.rrc_inactivity_timer", bpo::value<uint32_t>(&args->general.rrc_inactivity_timer)->default_value(30000), "Inactivity timer in ms.")
|
||||
("expert.print_buffer_state", bpo::value<bool>(&args->general.print_buffer_state)->default_value(false), "Prints on the console the buffer state every 10 seconds")
|
||||
("expert.eea_pref_list", bpo::value<string>(&args->general.eea_pref_list)->default_value("EEA0, EEA2, EEA1"), "Ordered preference list for the selection of encryption algorithm (EEA) (default: EEA0, EEA2, EEA1).")
|
||||
|
@ -246,6 +250,7 @@ void parse_args(all_args_t* args, int argc, char* argv[])
|
|||
("expert.extended_cp", bpo::value<bool>(&args->phy.extended_cp)->default_value(false), "Use extended cyclic prefix")
|
||||
("expert.ts1_reloc_prep_timeout", bpo::value<uint32_t>(&args->stack.s1ap.ts1_reloc_prep_timeout)->default_value(10000), "S1AP TS 36.413 TS1RelocPrep Expiry Timeout value in milliseconds")
|
||||
("expert.ts1_reloc_overall_timeout", bpo::value<uint32_t>(&args->stack.s1ap.ts1_reloc_overall_timeout)->default_value(10000), "S1AP TS 36.413 TS1RelocOverall Expiry Timeout value in milliseconds")
|
||||
("expert.rlf_min_ul_snr_estim", bpo::value<int>(&args->stack.mac.rlf_min_ul_snr_estim)->default_value(-2), "SNR threshold in dB below which the eNB is notified with rlf ko.")
|
||||
|
||||
|
||||
// eMBMS section
|
||||
|
@ -445,8 +450,8 @@ void parse_args(all_args_t* args, int argc, char* argv[])
|
|||
exit(1);
|
||||
}
|
||||
|
||||
if (!config_exists(args->enb_files.drb_config, "drb.conf")) {
|
||||
cout << "Failed to read DRB configuration file " << args->enb_files.drb_config << " - exiting" << endl;
|
||||
if (!config_exists(args->enb_files.rb_config, "rb.conf")) {
|
||||
cout << "Failed to read DRB configuration file " << args->enb_files.rb_config << " - exiting" << endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -629,7 +634,8 @@ int main(int argc, char* argv[])
|
|||
enb->start_plot();
|
||||
}
|
||||
}
|
||||
int cnt = 0;
|
||||
int cnt = 0;
|
||||
int ts_cnt = 0;
|
||||
while (running) {
|
||||
if (args.general.print_buffer_state) {
|
||||
cnt++;
|
||||
|
@ -638,6 +644,16 @@ int main(int argc, char* argv[])
|
|||
enb->print_pool();
|
||||
}
|
||||
}
|
||||
if (stdout_ts_enable) {
|
||||
if (++ts_cnt == 100) {
|
||||
ts_cnt = 0;
|
||||
char buff[64];
|
||||
std::time_t t = std::time(nullptr);
|
||||
if (std::strftime(buff, sizeof(buff), "%FT%T", std::gmtime(&t))) {
|
||||
std::cout << buff << '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
input.join();
|
||||
|
|
|
@ -31,8 +31,6 @@ set(SOURCES
|
|||
txrx.cc)
|
||||
add_library(srsenb_phy STATIC ${SOURCES})
|
||||
|
||||
add_library(srsgnb_phy STATIC vnf_phy_nr.cc)
|
||||
|
||||
if (ENABLE_GUI AND SRSGUI_FOUND)
|
||||
target_link_libraries(srsenb_phy ${SRSGUI_LIBRARIES})
|
||||
endif ()
|
||||
|
|
|
@ -35,11 +35,12 @@ slot_worker::slot_worker(srsran::phy_common_interface& common_,
|
|||
bool slot_worker::init(const args_t& args)
|
||||
{
|
||||
// Calculate subframe length
|
||||
sf_len = SRSRAN_SF_LEN_PRB_NR(args.carrier.nof_prb);
|
||||
sf_len = SRSRAN_SF_LEN_PRB_NR(args.nof_max_prb);
|
||||
|
||||
// Copy common configurations
|
||||
cell_index = args.cell_index;
|
||||
pdcch_cfg = args.pdcch_cfg;
|
||||
// FIXME:
|
||||
// pdcch_cfg = args.pdcch_cfg;
|
||||
|
||||
// Allocate Tx buffers
|
||||
tx_buffer.resize(args.nof_tx_ports);
|
||||
|
@ -64,10 +65,10 @@ bool slot_worker::init(const args_t& args)
|
|||
// Prepare DL arguments
|
||||
srsran_gnb_dl_args_t dl_args = {};
|
||||
dl_args.pdsch.measure_time = true;
|
||||
dl_args.pdsch.max_layers = args.carrier.max_mimo_layers;
|
||||
dl_args.pdsch.max_prb = args.carrier.nof_prb;
|
||||
dl_args.pdsch.max_layers = args.nof_tx_ports;
|
||||
dl_args.pdsch.max_prb = args.nof_max_prb;
|
||||
dl_args.nof_tx_antennas = args.nof_tx_ports;
|
||||
dl_args.nof_max_prb = args.carrier.nof_prb;
|
||||
dl_args.nof_max_prb = args.nof_max_prb;
|
||||
|
||||
// Initialise DL
|
||||
if (srsran_gnb_dl_init(&gnb_dl, tx_buffer.data(), &dl_args) < SRSRAN_SUCCESS) {
|
||||
|
@ -75,18 +76,13 @@ bool slot_worker::init(const args_t& args)
|
|||
return false;
|
||||
}
|
||||
|
||||
// Set gNb DL carrier
|
||||
if (srsran_gnb_dl_set_carrier(&gnb_dl, &args.carrier) < SRSRAN_SUCCESS) {
|
||||
logger.error("Error setting DL carrier");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Prepare UL arguments
|
||||
srsran_gnb_ul_args_t ul_args = {};
|
||||
ul_args.pusch.measure_time = true;
|
||||
ul_args.pusch.max_layers = args.carrier.max_mimo_layers;
|
||||
ul_args.pusch.max_prb = args.carrier.nof_prb;
|
||||
ul_args.nof_max_prb = args.carrier.nof_prb;
|
||||
ul_args.pusch.max_layers = args.nof_rx_ports;
|
||||
ul_args.pusch.max_prb = args.nof_max_prb;
|
||||
ul_args.nof_max_prb = args.nof_max_prb;
|
||||
|
||||
// Initialise UL
|
||||
if (srsran_gnb_ul_init(&gnb_ul, rx_buffer[0], &ul_args) < SRSRAN_SUCCESS) {
|
||||
|
@ -94,12 +90,6 @@ bool slot_worker::init(const args_t& args)
|
|||
return false;
|
||||
}
|
||||
|
||||
// Set gNb UL carrier
|
||||
if (srsran_gnb_ul_set_carrier(&gnb_ul, &args.carrier) < SRSRAN_SUCCESS) {
|
||||
logger.error("Error setting UL carrier");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -166,7 +156,7 @@ bool slot_worker::work_ul()
|
|||
return false;
|
||||
}
|
||||
|
||||
// Decode PUCCH
|
||||
// For each PUCCH...
|
||||
for (stack_interface_phy_nr::pucch_t& pucch : ul_sched.pucch) {
|
||||
stack_interface_phy_nr::pucch_info_t pucch_info = {};
|
||||
pucch_info.uci_data.cfg = pucch.uci_cfg;
|
||||
|
@ -197,7 +187,7 @@ bool slot_worker::work_ul()
|
|||
}
|
||||
}
|
||||
|
||||
// Decode PUSCH
|
||||
// For each PUSCH...
|
||||
for (stack_interface_phy_nr::pusch_t& pusch : ul_sched.pusch) {
|
||||
// Get payload PDU
|
||||
stack_interface_phy_nr::pusch_info_t pusch_info = {};
|
||||
|
@ -206,7 +196,7 @@ bool slot_worker::work_ul()
|
|||
pusch_info.pusch_data.tb[0].payload = pusch.data[0];
|
||||
pusch_info.pusch_data.tb[1].payload = pusch.data[1];
|
||||
|
||||
// Decode PUCCH
|
||||
// Decode PUSCH
|
||||
if (srsran_gnb_ul_get_pusch(&gnb_ul, &ul_slot_cfg, &pusch.sch, &pusch.sch.grant, &pusch_info.pusch_data) <
|
||||
SRSRAN_SUCCESS) {
|
||||
logger.error("Error getting PUSCH");
|
||||
|
@ -349,6 +339,27 @@ void slot_worker::work_imp()
|
|||
|
||||
common.worker_end(this, true, tx_rf_buffer, tx_time, true);
|
||||
}
|
||||
bool slot_worker::set_common_cfg(const srsran_carrier_nr_t& carrier, const srsran_pdcch_cfg_nr_t& pdcch_cfg_)
|
||||
{
|
||||
// Set gNb DL carrier
|
||||
if (srsran_gnb_dl_set_carrier(&gnb_dl, &carrier) < SRSRAN_SUCCESS) {
|
||||
logger.error("Error setting DL carrier");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set gNb UL carrier
|
||||
if (srsran_gnb_ul_set_carrier(&gnb_ul, &carrier) < SRSRAN_SUCCESS) {
|
||||
logger.error("Error setting UL carrier");
|
||||
return false;
|
||||
}
|
||||
|
||||
pdcch_cfg = pdcch_cfg_;
|
||||
|
||||
// Update subframe length
|
||||
sf_len = SRSRAN_SF_LEN_PRB_NR(carrier.nof_prb);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace nr
|
||||
} // namespace srsenb
|
|
@ -27,19 +27,27 @@ worker_pool::worker_pool(srsran::phy_common_interface& common_,
|
|||
stack_interface_phy_nr& stack_,
|
||||
srslog::sink& log_sink_,
|
||||
uint32_t max_workers) :
|
||||
pool(max_workers), common(common_), stack(stack_), log_sink(log_sink_)
|
||||
pool(max_workers),
|
||||
common(common_),
|
||||
stack(stack_),
|
||||
log_sink(log_sink_),
|
||||
logger(srslog::fetch_basic_logger("PHY-NR", log_sink)),
|
||||
prach_stack_adaptor(stack_)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
bool worker_pool::init(const args_t& args, const phy_cell_cfg_list_nr_t& cell_list)
|
||||
{
|
||||
// Configure logger
|
||||
srslog::basic_levels log_level = srslog::str_to_basic_level(args.log.phy_level);
|
||||
logger.set_level(log_level);
|
||||
|
||||
// Add workers to workers pool and start threads
|
||||
srslog::basic_levels log_level = srslog::str_to_basic_level(args.log_level);
|
||||
for (uint32_t i = 0; i < args.nof_phy_threads; i++) {
|
||||
auto& log = srslog::fetch_basic_logger(fmt::format("{}PHY{}-NR", args.log_id_preamble, i), log_sink);
|
||||
auto& log = srslog::fetch_basic_logger(fmt::format("{}PHY{}-NR", args.log.id_preamble, i), log_sink);
|
||||
log.set_level(log_level);
|
||||
log.set_hex_dump_max_size(args.log_hex_limit);
|
||||
log.set_hex_dump_max_size(args.log.phy_hex_limit);
|
||||
|
||||
auto w = new slot_worker(common, stack, log);
|
||||
pool.init_worker(i, w, args.prio);
|
||||
|
@ -48,11 +56,10 @@ bool worker_pool::init(const args_t& args, const phy_cell_cfg_list_nr_t& cell_li
|
|||
slot_worker::args_t w_args = {};
|
||||
uint32_t cell_index = 0;
|
||||
w_args.cell_index = cell_index;
|
||||
w_args.carrier = cell_list[cell_index].carrier;
|
||||
w_args.nof_max_prb = cell_list[cell_index].carrier.nof_prb;
|
||||
w_args.nof_tx_ports = cell_list[cell_index].carrier.max_mimo_layers;
|
||||
w_args.nof_rx_ports = cell_list[cell_index].carrier.max_mimo_layers;
|
||||
w_args.pusch_max_nof_iter = args.pusch_max_nof_iter;
|
||||
w_args.pdcch_cfg = cell_list[cell_index].pdcch;
|
||||
|
||||
if (not w->init(w_args)) {
|
||||
return false;
|
||||
|
@ -64,12 +71,41 @@ bool worker_pool::init(const args_t& args, const phy_cell_cfg_list_nr_t& cell_li
|
|||
|
||||
void worker_pool::start_worker(slot_worker* w)
|
||||
{
|
||||
// Feed PRACH detection before start processing
|
||||
prach.new_tti(0, current_tti, w->get_buffer_rx(0));
|
||||
|
||||
// Start actual worker
|
||||
pool.start_worker(w);
|
||||
}
|
||||
|
||||
slot_worker* worker_pool::wait_worker(uint32_t tti)
|
||||
{
|
||||
return (slot_worker*)pool.wait_worker(tti);
|
||||
slot_worker* w = (slot_worker*)pool.wait_worker(tti);
|
||||
|
||||
// Only if a worker was available
|
||||
if (w != nullptr) {
|
||||
srsran_carrier_nr_t carrier_;
|
||||
srsran_pdcch_cfg_nr_t pdcch_cfg_;
|
||||
|
||||
// Copy configuration
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(common_cfg_mutex);
|
||||
carrier_ = carrier;
|
||||
pdcch_cfg_ = pdcch_cfg;
|
||||
}
|
||||
|
||||
// Set worker configuration
|
||||
if (not w->set_common_cfg(carrier_, pdcch_cfg_)) {
|
||||
logger.error("Error setting common config");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Save current TTI
|
||||
current_tti = tti;
|
||||
|
||||
// Return worker
|
||||
return w;
|
||||
}
|
||||
|
||||
slot_worker* worker_pool::wait_worker_id(uint32_t id)
|
||||
|
@ -80,6 +116,41 @@ slot_worker* worker_pool::wait_worker_id(uint32_t id)
|
|||
void worker_pool::stop()
|
||||
{
|
||||
pool.stop();
|
||||
prach.stop();
|
||||
}
|
||||
|
||||
int worker_pool::set_common_cfg(const phy_interface_rrc_nr::common_cfg_t& common_cfg)
|
||||
{
|
||||
// Best effort to convert NR carrier into LTE cell
|
||||
srsran_cell_t cell = {};
|
||||
int ret = srsran_carrier_to_cell(&common_cfg.carrier, &cell);
|
||||
if (ret < SRSRAN_SUCCESS) {
|
||||
logger.error("Converting carrier to cell for PRACH (%d)", ret);
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
// Best effort to set up NR-PRACH config reused for NR
|
||||
srsran_prach_cfg_t prach_cfg = common_cfg.prach;
|
||||
uint32_t lte_nr_prach_offset = (common_cfg.carrier.nof_prb - cell.nof_prb) / 2;
|
||||
if (prach_cfg.freq_offset < lte_nr_prach_offset) {
|
||||
logger.error("prach_cfg.freq_offset=%d is not compatible with LTE", prach_cfg.freq_offset);
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
prach_cfg.freq_offset -= lte_nr_prach_offset;
|
||||
prach_cfg.is_nr = true;
|
||||
|
||||
// Set the PRACH configuration
|
||||
prach.init(0, cell, prach_cfg, &prach_stack_adaptor, logger, 0, 1);
|
||||
prach.set_max_prach_offset_us(1000);
|
||||
|
||||
// Save current configuration
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(common_cfg_mutex);
|
||||
carrier = common_cfg.carrier;
|
||||
pdcch_cfg = common_cfg.pdcch;
|
||||
}
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace nr
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
/**
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* This file is part of srsRAN.
|
||||
*
|
||||
* srsRAN is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* srsRAN is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* A copy of the GNU Affero General Public License can be found in
|
||||
* the LICENSE file in the top-level directory of this distribution
|
||||
* and at http://www.gnu.org/licenses/.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "srsenb/hdr/phy/vnf_phy_nr.h"
|
||||
#include "srsran/common/basic_vnf_api.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
vnf_phy_nr::~vnf_phy_nr()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
void vnf_phy_nr::parse_config(const nr_phy_cfg_t& cfg) {}
|
||||
|
||||
int vnf_phy_nr::init(const srsenb::phy_args_t& args, const nr_phy_cfg_t& cfg, srsenb::stack_interface_phy_nr* stack_)
|
||||
{
|
||||
mlockall(MCL_CURRENT | MCL_FUTURE);
|
||||
|
||||
// create VNF
|
||||
vnf = std::unique_ptr<srsran::srsran_basic_vnf>(new srsran::srsran_basic_vnf(args.vnf_args, stack_));
|
||||
|
||||
initialized = true;
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
void vnf_phy_nr::stop()
|
||||
{
|
||||
if (initialized) {
|
||||
vnf->stop();
|
||||
initialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Start GUI
|
||||
void vnf_phy_nr::start_plot() {}
|
||||
|
||||
void vnf_phy_nr::get_metrics(std::vector<srsenb::phy_metrics_t>& metrics) {}
|
||||
|
||||
int vnf_phy_nr::dl_config_request(const dl_config_request_t& request)
|
||||
{
|
||||
// prepare DL config request over basic API and send
|
||||
return vnf->dl_config_request(request);
|
||||
}
|
||||
|
||||
int vnf_phy_nr::tx_request(const tx_request_t& request)
|
||||
{
|
||||
// send Tx request over basic API
|
||||
return vnf->tx_request(request);
|
||||
}
|
||||
|
||||
} // namespace srsenb
|
|
@ -207,4 +207,6 @@ int gnb_stack_nr::pusch_info(const srsran_slot_cfg_t& slot_cfg, const mac_interf
|
|||
return m_mac->pusch_info(slot_cfg, pusch_info);
|
||||
}
|
||||
|
||||
void gnb_stack_nr::rach_detected(const rach_info_t& rach_info) {}
|
||||
|
||||
} // namespace srsenb
|
||||
|
|
|
@ -410,7 +410,7 @@ int mac::snr_info(uint32_t tti_rx, uint16_t rnti, uint32_t enb_cc_idx, float snr
|
|||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
rrc_h->set_radiolink_ul_state(rnti, snr > 0);
|
||||
rrc_h->set_radiolink_ul_state(rnti, snr >= args.rlf_min_ul_snr_estim);
|
||||
|
||||
return scheduler.ul_snr_info(tti_rx, rnti, enb_cc_idx, snr, (uint32_t)ch);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
# and at http://www.gnu.org/licenses/.
|
||||
#
|
||||
|
||||
set(SOURCES mac_nr.cc sched_nr.cc sched_nr_ue.cc sched_nr_worker.cc sched_nr_rb_grid.cc sched_nr_harq.cc sched_nr_pdcch.cc sched_nr_common.cc sched_nr_phy_helpers.cc)
|
||||
set(SOURCES mac_nr.cc sched_nr.cc sched_nr_ue.cc sched_nr_worker.cc sched_nr_rb_grid.cc sched_nr_harq.cc
|
||||
sched_nr_pdcch.cc sched_nr_cfg.cc sched_nr_helpers.cc sched_nr_bwp.cc sched_nr_rb.cc harq_softbuffer.cc)
|
||||
|
||||
add_library(srsgnb_mac STATIC ${SOURCES})
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "srsenb/hdr/stack/mac/nr/harq_softbuffer.h"
|
||||
#include "srsran/adt/pool/obj_pool.h"
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
void harq_softbuffer_pool::init_pool(uint32_t nof_prb, uint32_t batch_size, uint32_t thres, uint32_t init_size)
|
||||
{
|
||||
srsran_assert(nof_prb <= SRSRAN_MAX_PRB_NR, "Invalid nof prb=%d", nof_prb);
|
||||
size_t idx = nof_prb - 1;
|
||||
if (tx_pool[idx] != nullptr) {
|
||||
return;
|
||||
}
|
||||
if (thres == 0) {
|
||||
thres = batch_size;
|
||||
}
|
||||
if (init_size == 0) {
|
||||
init_size = batch_size;
|
||||
}
|
||||
auto init_tx_softbuffers = [nof_prb](void* ptr) { new (ptr) tx_harq_softbuffer(nof_prb); };
|
||||
auto recycle_tx_softbuffers = [](tx_harq_softbuffer& softbuffer) { softbuffer.reset(); };
|
||||
tx_pool[idx].reset(new srsran::background_obj_pool<tx_harq_softbuffer>(
|
||||
batch_size, thres, init_size, init_tx_softbuffers, recycle_tx_softbuffers));
|
||||
|
||||
auto init_rx_softbuffers = [nof_prb](void* ptr) { new (ptr) rx_harq_softbuffer(nof_prb); };
|
||||
auto recycle_rx_softbuffers = [](rx_harq_softbuffer& softbuffer) { softbuffer.reset(); };
|
||||
rx_pool[idx].reset(new srsran::background_obj_pool<rx_harq_softbuffer>(
|
||||
batch_size, thres, init_size, init_rx_softbuffers, recycle_rx_softbuffers));
|
||||
}
|
||||
|
||||
srsran::unique_pool_ptr<tx_harq_softbuffer> harq_softbuffer_pool::get_tx(uint32_t nof_prb)
|
||||
{
|
||||
srsran_assert(nof_prb <= SRSRAN_MAX_PRB_NR, "Invalid Nprb=%d", nof_prb);
|
||||
size_t idx = nof_prb - 1;
|
||||
if (tx_pool[idx] == nullptr) {
|
||||
init_pool(nof_prb);
|
||||
}
|
||||
return tx_pool[idx]->make();
|
||||
}
|
||||
|
||||
srsran::unique_pool_ptr<rx_harq_softbuffer> harq_softbuffer_pool::get_rx(uint32_t nof_prb)
|
||||
{
|
||||
srsran_assert(nof_prb <= SRSRAN_MAX_PRB_NR, "Invalid Nprb=%d", nof_prb);
|
||||
size_t idx = nof_prb - 1;
|
||||
if (rx_pool[idx] == nullptr) {
|
||||
init_pool(nof_prb);
|
||||
}
|
||||
return rx_pool[idx]->make();
|
||||
}
|
||||
|
||||
} // namespace srsenb
|
|
@ -98,114 +98,6 @@ void mac_nr::stop()
|
|||
|
||||
void mac_nr::get_metrics(srsenb::mac_metrics_t& metrics) {}
|
||||
|
||||
// Fills both, DL_CONFIG.request and TX.request structs
|
||||
void mac_nr::get_dl_config(const uint32_t tti,
|
||||
phy_interface_stack_nr::dl_config_request_t& config_request,
|
||||
phy_interface_stack_nr::tx_request_t& tx_request)
|
||||
{
|
||||
// send MIB over BCH every 80ms
|
||||
if (tti % 80 == 0) {
|
||||
// try to read BCH PDU from RRC
|
||||
if (rrc_h->read_pdu_bcch_bch(tti, bcch_bch_payload) == SRSRAN_SUCCESS) {
|
||||
logger.info("Adding BCH in TTI=%d", tti);
|
||||
tx_request.pdus[tx_request.nof_pdus].pbch.mib_present = true;
|
||||
tx_request.pdus[tx_request.nof_pdus].data[0] = bcch_bch_payload->msg;
|
||||
tx_request.pdus[tx_request.nof_pdus].length = bcch_bch_payload->N_bytes;
|
||||
tx_request.pdus[tx_request.nof_pdus].index = tx_request.nof_pdus;
|
||||
tx_request.nof_pdus++;
|
||||
|
||||
if (pcap) {
|
||||
pcap->write_dl_bch(bcch_bch_payload->msg, bcch_bch_payload->N_bytes, 0xffff, 0, tti);
|
||||
}
|
||||
} else {
|
||||
logger.error("Couldn't read BCH payload from RRC");
|
||||
}
|
||||
}
|
||||
|
||||
// Schedule SIBs
|
||||
for (auto& sib : bcch_dlsch_payload) {
|
||||
if (sib.payload->N_bytes > 0) {
|
||||
if (tti % (sib.periodicity * 10) == 0) {
|
||||
logger.info("Adding SIB %d in TTI=%d", sib.index, tti);
|
||||
|
||||
tx_request.pdus[tx_request.nof_pdus].data[0] = sib.payload->msg;
|
||||
tx_request.pdus[tx_request.nof_pdus].length = sib.payload->N_bytes;
|
||||
tx_request.pdus[tx_request.nof_pdus].index = tx_request.nof_pdus;
|
||||
|
||||
if (pcap) {
|
||||
pcap->write_dl_si_rnti_nr(sib.payload->msg, sib.payload->N_bytes, 0xffff, 0, tti);
|
||||
}
|
||||
|
||||
tx_request.nof_pdus++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add MAC padding if TTI is empty
|
||||
if (tx_request.nof_pdus == 0) {
|
||||
uint32_t buffer_index = tti % SRSRAN_FDD_NOF_HARQ;
|
||||
|
||||
ue_tx_buffer.at(buffer_index)->clear();
|
||||
ue_tx_pdu.init_tx(ue_tx_buffer.at(buffer_index).get(), args.tb_size);
|
||||
|
||||
// read RLC PDU
|
||||
ue_rlc_buffer->clear();
|
||||
int pdu_len = rlc_h->read_pdu(args.rnti, 4, ue_rlc_buffer->msg, args.tb_size - 2);
|
||||
|
||||
// Only create PDU if RLC has something to tx
|
||||
if (pdu_len > 0) {
|
||||
logger.info("Adding MAC PDU for RNTI=%d", args.rnti);
|
||||
ue_rlc_buffer->N_bytes = pdu_len;
|
||||
logger.info(ue_rlc_buffer->msg, ue_rlc_buffer->N_bytes, "Read %d B from RLC", ue_rlc_buffer->N_bytes);
|
||||
|
||||
// add to MAC PDU and pack
|
||||
ue_tx_pdu.add_sdu(4, ue_rlc_buffer->msg, ue_rlc_buffer->N_bytes);
|
||||
ue_tx_pdu.pack();
|
||||
|
||||
logger.debug(ue_tx_buffer.at(buffer_index)->msg,
|
||||
ue_tx_buffer.at(buffer_index)->N_bytes,
|
||||
"Generated MAC PDU (%d B)",
|
||||
ue_tx_buffer.at(buffer_index)->N_bytes);
|
||||
|
||||
tx_request.pdus[tx_request.nof_pdus].data[0] = ue_tx_buffer.at(buffer_index)->msg;
|
||||
tx_request.pdus[tx_request.nof_pdus].length = ue_tx_buffer.at(buffer_index)->N_bytes;
|
||||
tx_request.pdus[tx_request.nof_pdus].index = tx_request.nof_pdus;
|
||||
|
||||
if (pcap) {
|
||||
pcap->write_dl_crnti_nr(tx_request.pdus[tx_request.nof_pdus].data[0],
|
||||
tx_request.pdus[tx_request.nof_pdus].length,
|
||||
args.rnti,
|
||||
buffer_index,
|
||||
tti);
|
||||
}
|
||||
|
||||
tx_request.nof_pdus++;
|
||||
}
|
||||
}
|
||||
|
||||
config_request.tti = tti;
|
||||
tx_request.tti = tti;
|
||||
}
|
||||
|
||||
int mac_nr::slot_indication(const srsran_slot_cfg_t& slot_cfg)
|
||||
{
|
||||
phy_interface_stack_nr::dl_config_request_t config_request = {};
|
||||
phy_interface_stack_nr::tx_request_t tx_request = {};
|
||||
|
||||
// step MAC TTI
|
||||
logger.set_context(slot_cfg.idx);
|
||||
|
||||
get_dl_config(slot_cfg.idx, config_request, tx_request);
|
||||
|
||||
// send DL_CONFIG.request
|
||||
phy_h->dl_config_request(config_request);
|
||||
|
||||
// send TX.request
|
||||
phy_h->tx_request(tx_request);
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int mac_nr::rx_data_indication(stack_interface_phy_nr::rx_data_ind_t& rx_data)
|
||||
{
|
||||
// push received PDU on queue
|
||||
|
@ -279,6 +171,11 @@ int mac_nr::cell_cfg(srsenb::sched_interface::cell_cfg_t* cell_cfg)
|
|||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int mac_nr::slot_indication(const srsran_slot_cfg_t& slot_cfg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mac_nr::get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched)
|
||||
{
|
||||
return 0;
|
||||
|
@ -295,5 +192,6 @@ int mac_nr::pusch_info(const srsran_slot_cfg_t& slot_cfg, const mac_interface_ph
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
void mac_nr::rach_detected(const mac_interface_phy_nr::rach_info_t& rach_info) {}
|
||||
|
||||
} // namespace srsenb
|
||||
|
|
|
@ -20,15 +20,14 @@
|
|||
*/
|
||||
|
||||
#include "srsenb/hdr/stack/mac/nr/sched_nr.h"
|
||||
#include "srsenb/hdr/stack/mac/nr/harq_softbuffer.h"
|
||||
#include "srsenb/hdr/stack/mac/nr/sched_nr_bwp.h"
|
||||
#include "srsenb/hdr/stack/mac/nr/sched_nr_worker.h"
|
||||
#include "srsran/common/thread_pool.h"
|
||||
|
||||
namespace srsenb {
|
||||
|
||||
using sched_nr_impl::sched_worker_manager;
|
||||
using sched_nr_impl::ue;
|
||||
using sched_nr_impl::ue_carrier;
|
||||
using sched_nr_impl::ue_map_t;
|
||||
using namespace sched_nr_impl;
|
||||
|
||||
static int assert_ue_cfg_valid(uint16_t rnti, const sched_nr_interface::ue_cfg_t& uecfg);
|
||||
|
||||
|
@ -53,7 +52,7 @@ public:
|
|||
feedback_list.back().cc = cc;
|
||||
feedback_list.back().callback = std::move(event);
|
||||
}
|
||||
void new_tti()
|
||||
void new_slot()
|
||||
{
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(common_mutex);
|
||||
|
@ -90,7 +89,71 @@ private:
|
|||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
sched_nr::sched_nr(const sched_cfg_t& sched_cfg) : cfg(sched_cfg), pending_events(new ue_event_manager(ue_db)) {}
|
||||
class sched_result_manager
|
||||
{
|
||||
public:
|
||||
explicit sched_result_manager(uint32_t nof_cc_)
|
||||
{
|
||||
for (auto& v : results) {
|
||||
v.resize(nof_cc_);
|
||||
}
|
||||
}
|
||||
|
||||
dl_sched_t& add_dl_result(tti_point tti, uint32_t cc)
|
||||
{
|
||||
if (not has_dl_result(tti, cc)) {
|
||||
results[tti.to_uint()][cc].tti_dl = tti;
|
||||
results[tti.to_uint()][cc].dl_res = {};
|
||||
}
|
||||
return results[tti.to_uint()][cc].dl_res;
|
||||
}
|
||||
ul_sched_t& add_ul_result(tti_point tti, uint32_t cc)
|
||||
{
|
||||
if (not has_ul_result(tti, cc)) {
|
||||
results[tti.to_uint()][cc].tti_ul = tti;
|
||||
results[tti.to_uint()][cc].ul_res = {};
|
||||
}
|
||||
return results[tti.to_uint()][cc].ul_res;
|
||||
}
|
||||
|
||||
bool has_dl_result(tti_point tti, uint32_t cc) const { return results[tti.to_uint()][cc].tti_dl == tti; }
|
||||
|
||||
bool has_ul_result(tti_point tti, uint32_t cc) const { return results[tti.to_uint()][cc].tti_ul == tti; }
|
||||
|
||||
dl_sched_t pop_dl_result(tti_point tti, uint32_t cc)
|
||||
{
|
||||
if (has_dl_result(tti, cc)) {
|
||||
results[tti.to_uint()][cc].tti_dl.reset();
|
||||
return results[tti.to_uint()][cc].dl_res;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
ul_sched_t pop_ul_result(tti_point tti, uint32_t cc)
|
||||
{
|
||||
if (has_ul_result(tti, cc)) {
|
||||
results[tti.to_uint()][cc].tti_ul.reset();
|
||||
return results[tti.to_uint()][cc].ul_res;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
private:
|
||||
struct slot_result_t {
|
||||
tti_point tti_dl;
|
||||
tti_point tti_ul;
|
||||
dl_sched_t dl_res;
|
||||
ul_sched_t ul_res;
|
||||
};
|
||||
|
||||
srsran::circular_array<std::vector<slot_result_t>, TTIMOD_SZ> results;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
sched_nr::sched_nr(const sched_cfg_t& sched_cfg) :
|
||||
cfg(sched_cfg), pending_events(new ue_event_manager(ue_db)), logger(srslog::fetch_basic_logger("MAC"))
|
||||
{}
|
||||
|
||||
sched_nr::~sched_nr() {}
|
||||
|
||||
|
@ -101,7 +164,9 @@ int sched_nr::cell_cfg(srsran::const_span<cell_cfg_t> cell_list)
|
|||
cfg.cells.emplace_back(cc, cell_list[cc], cfg.sched_cfg);
|
||||
}
|
||||
|
||||
pending_results.reset(new sched_result_manager(cell_list.size()));
|
||||
sched_workers.reset(new sched_nr_impl::sched_worker_manager(ue_db, cfg));
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -114,39 +179,56 @@ void sched_nr::ue_cfg(uint16_t rnti, const ue_cfg_t& uecfg)
|
|||
void sched_nr::ue_cfg_impl(uint16_t rnti, const ue_cfg_t& uecfg)
|
||||
{
|
||||
if (not ue_db.contains(rnti)) {
|
||||
ue_db.insert(rnti, std::unique_ptr<ue>(new ue{rnti, uecfg}));
|
||||
ue_db.insert(rnti, std::unique_ptr<ue>(new ue{rnti, uecfg, cfg}));
|
||||
} else {
|
||||
ue_db[rnti]->set_cfg(uecfg);
|
||||
}
|
||||
}
|
||||
|
||||
void sched_nr::slot_indication(tti_point tti_rx)
|
||||
{
|
||||
// Lock slot workers for provided tti_rx
|
||||
sched_workers->reserve_workers(tti_rx);
|
||||
|
||||
{
|
||||
// synchronize {tti,cc} state. e.g. reserve UE resources for {tti,cc} decision, process feedback
|
||||
std::lock_guard<std::mutex> lock(ue_db_mutex);
|
||||
// Process pending events
|
||||
pending_events->new_tti();
|
||||
|
||||
sched_workers->start_tti(tti_rx);
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate {tti,cc} scheduling decision
|
||||
int sched_nr::generate_sched_result(tti_point tti_rx, uint32_t cc, tti_request_t& req)
|
||||
int sched_nr::generate_slot_result(tti_point pdcch_tti, uint32_t cc)
|
||||
{
|
||||
tti_point tti_rx = pdcch_tti - TX_ENB_DELAY;
|
||||
|
||||
// Lock carrier workers for provided tti_rx
|
||||
sched_workers->start_slot(tti_rx, [this]() {
|
||||
// In case it is first worker for the given slot
|
||||
// synchronize {tti,cc} state. e.g. reserve UE resources for {tti,cc} decision, process feedback
|
||||
pending_events->new_slot();
|
||||
});
|
||||
|
||||
// unlocked, parallel region
|
||||
bool all_workers_finished = sched_workers->run_tti(tti_rx, cc, req);
|
||||
bool all_workers_finished = sched_workers->run_slot(tti_rx, cc);
|
||||
|
||||
if (all_workers_finished) {
|
||||
// once all workers of the same subframe finished, synchronize sched outcome with ue_db
|
||||
std::lock_guard<std::mutex> lock(ue_db_mutex);
|
||||
sched_workers->end_tti(tti_rx);
|
||||
sched_workers->release_slot(tti_rx);
|
||||
}
|
||||
|
||||
// Copy results to intermediate buffer
|
||||
dl_sched_t& dl_res = pending_results->add_dl_result(pdcch_tti, cc);
|
||||
ul_sched_t& ul_res = pending_results->add_ul_result(pdcch_tti, cc);
|
||||
sched_workers->save_sched_result(pdcch_tti, cc, dl_res, ul_res);
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int sched_nr::get_dl_sched(tti_point tti_tx, uint32_t cc, dl_sched_t& result)
|
||||
{
|
||||
if (not pending_results->has_dl_result(tti_tx, cc)) {
|
||||
generate_slot_result(tti_tx, cc);
|
||||
}
|
||||
|
||||
result = pending_results->pop_dl_result(tti_tx, cc);
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
int sched_nr::get_ul_sched(tti_point tti_rx, uint32_t cc, ul_sched_t& result)
|
||||
{
|
||||
if (not pending_results->has_ul_result(tti_rx, cc)) {
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
|
||||
result = pending_results->pop_ul_result(tti_rx, cc);
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -165,15 +247,21 @@ void sched_nr::ul_sr_info(tti_point tti_rx, uint16_t rnti)
|
|||
});
|
||||
}
|
||||
|
||||
#define VERIFY_INPUT(cond, msg, ...) \
|
||||
do { \
|
||||
if (not(cond)) { \
|
||||
srslog::fetch_basic_logger("MAC").warning(msg, ##__VA_ARGS__); \
|
||||
return SRSRAN_ERROR; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
int assert_ue_cfg_valid(uint16_t rnti, const sched_nr_interface::ue_cfg_t& uecfg)
|
||||
{
|
||||
const srslog::basic_logger& logger = srslog::fetch_basic_logger("MAC");
|
||||
if (std::count(&uecfg.phy_cfg.pdcch.coreset_present[0],
|
||||
&uecfg.phy_cfg.pdcch.coreset_present[SRSRAN_UE_DL_NR_MAX_NOF_CORESET],
|
||||
true) == 0) {
|
||||
logger.warning("Provided rnti=0x%x configuration does not contain any coreset", rnti);
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
VERIFY_INPUT(std::count(&uecfg.phy_cfg.pdcch.coreset_present[0],
|
||||
&uecfg.phy_cfg.pdcch.coreset_present[SRSRAN_UE_DL_NR_MAX_NOF_CORESET],
|
||||
true) > 0,
|
||||
"Provided rnti=0x%x configuration does not contain any coreset",
|
||||
rnti);
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "srsenb/hdr/stack/mac/nr/sched_nr_bwp.h"
|
||||
#include "srsran/common/standard_streams.h"
|
||||
#include "srsran/common/string_helpers.h"
|
||||
|
||||
namespace srsenb {
|
||||
namespace sched_nr_impl {
|
||||
|
||||
ra_sched::ra_sched(const bwp_params& bwp_cfg_) : bwp_cfg(&bwp_cfg_), logger(srslog::fetch_basic_logger("MAC")) {}
|
||||
|
||||
alloc_result
|
||||
ra_sched::allocate_pending_rar(bwp_slot_allocator& slot_grid, const pending_rar_t& rar, uint32_t& nof_grants_alloc)
|
||||
{
|
||||
const uint32_t rar_aggr_level = 2;
|
||||
const prb_bitmap& prbs = slot_grid.res_grid()[slot_grid.get_pdcch_tti()].dl_prbs.prbs();
|
||||
|
||||
alloc_result ret = alloc_result::other_cause;
|
||||
for (nof_grants_alloc = rar.msg3_grant.size(); nof_grants_alloc > 0; nof_grants_alloc--) {
|
||||
ret = alloc_result::invalid_coderate;
|
||||
uint32_t start_prb_idx = 0;
|
||||
for (uint32_t nprb = 1; nprb < bwp_cfg->cfg.rb_width and ret == alloc_result::invalid_coderate; ++nprb) {
|
||||
prb_interval interv = find_empty_interval_of_length(prbs, nprb, start_prb_idx);
|
||||
start_prb_idx = interv.stop();
|
||||
if (interv.length() == nprb) {
|
||||
ret = slot_grid.alloc_rar(rar_aggr_level, rar, interv, nof_grants_alloc);
|
||||
} else {
|
||||
ret = alloc_result::no_sch_space;
|
||||
}
|
||||
}
|
||||
|
||||
// If allocation was not successful because there were not enough RBGs, try allocating fewer Msg3 grants
|
||||
if (ret != alloc_result::invalid_coderate and ret != alloc_result::no_sch_space) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret != alloc_result::success) {
|
||||
logger.info("SCHED: RAR allocation for L=%d was postponed. Cause=%s", rar_aggr_level, to_string(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ra_sched::run_slot(bwp_slot_allocator& slot_grid)
|
||||
{
|
||||
static const uint32_t PRACH_RAR_OFFSET = 3;
|
||||
tti_point pdcch_tti = slot_grid.get_pdcch_tti();
|
||||
|
||||
for (auto it = pending_rars.begin(); it != pending_rars.end();) {
|
||||
pending_rar_t& rar = *it;
|
||||
|
||||
// In case of RAR outside RAR window:
|
||||
// - if window has passed, discard RAR
|
||||
// - if window hasn't started, stop loop, as RARs are ordered by TTI
|
||||
tti_interval rar_window{rar.prach_tti + PRACH_RAR_OFFSET,
|
||||
rar.prach_tti + PRACH_RAR_OFFSET + bwp_cfg->cfg.rar_window_size};
|
||||
if (not rar_window.contains(pdcch_tti)) {
|
||||
if (pdcch_tti >= rar_window.stop()) {
|
||||
fmt::memory_buffer str_buffer;
|
||||
fmt::format_to(str_buffer,
|
||||
"SCHED: Could not transmit RAR within the window (RA={}, Window={}, RAR={}",
|
||||
rar.prach_tti,
|
||||
rar_window,
|
||||
pdcch_tti);
|
||||
srsran::console("%s\n", srsran::to_c_str(str_buffer));
|
||||
logger.warning("%s", srsran::to_c_str(str_buffer));
|
||||
it = pending_rars.erase(it);
|
||||
continue;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to schedule DCI + RBGs for RAR Grant
|
||||
uint32_t nof_rar_allocs = 0;
|
||||
alloc_result ret = allocate_pending_rar(slot_grid, rar, nof_rar_allocs);
|
||||
|
||||
if (ret == alloc_result::success) {
|
||||
// If RAR allocation was successful:
|
||||
// - in case all Msg3 grants were allocated, remove pending RAR, and continue with following RAR
|
||||
// - otherwise, erase only Msg3 grants that were allocated, and stop iteration
|
||||
|
||||
if (nof_rar_allocs == rar.msg3_grant.size()) {
|
||||
it = pending_rars.erase(it);
|
||||
} else {
|
||||
std::copy(rar.msg3_grant.begin() + nof_rar_allocs, rar.msg3_grant.end(), rar.msg3_grant.begin());
|
||||
rar.msg3_grant.resize(rar.msg3_grant.size() - nof_rar_allocs);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// If RAR allocation was not successful:
|
||||
// - in case of unavailable PDCCH space, try next pending RAR allocation
|
||||
// - otherwise, stop iteration
|
||||
if (ret != alloc_result::no_cch_space) {
|
||||
break;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ra_sched::dl_rach_info(const dl_sched_rar_info_t& rar_info)
|
||||
{
|
||||
logger.info("SCHED: New PRACH tti=%d, preamble=%d, temp_crnti=0x%x, ta_cmd=%d, msg3_size=%d",
|
||||
rar_info.prach_tti,
|
||||
rar_info.preamble_idx,
|
||||
rar_info.temp_crnti,
|
||||
rar_info.ta_cmd,
|
||||
rar_info.msg3_size);
|
||||
|
||||
// RA-RNTI = 1 + t_id + f_id
|
||||
// t_id = index of first subframe specified by PRACH (0<=t_id<10)
|
||||
// f_id = index of the PRACH within subframe, in ascending order of freq domain (0<=f_id<6) (for FDD, f_id=0)
|
||||
uint16_t ra_rnti = 1 + (uint16_t)(rar_info.prach_tti % 10u);
|
||||
|
||||
// find pending rar with same RA-RNTI
|
||||
for (pending_rar_t& r : pending_rars) {
|
||||
if (r.prach_tti.to_uint() == rar_info.prach_tti and ra_rnti == r.ra_rnti) {
|
||||
if (r.msg3_grant.size() >= sched_interface::MAX_RAR_LIST) {
|
||||
logger.warning("PRACH ignored, as the the maximum number of RAR grants per tti has been reached");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
r.msg3_grant.push_back(rar_info);
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
// create new RAR
|
||||
pending_rar_t p;
|
||||
p.ra_rnti = ra_rnti;
|
||||
p.prach_tti = tti_point{rar_info.prach_tti};
|
||||
p.msg3_grant.push_back(rar_info);
|
||||
pending_rars.push_back(p);
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
bwp_ctxt::bwp_ctxt(const bwp_params& bwp_cfg) : cfg(&bwp_cfg), ra(bwp_cfg), grid(bwp_cfg) {}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
serv_cell_ctxt::serv_cell_ctxt(const sched_cell_params& cell_cfg_) : cfg(&cell_cfg_)
|
||||
{
|
||||
for (uint32_t bwp_id = 0; bwp_id < cfg->cell_cfg.bwps.size(); ++bwp_id) {
|
||||
bwps.emplace_back(cell_cfg_.bwps[bwp_id]);
|
||||
}
|
||||
|
||||
// Pre-allocate HARQs in common pool of softbuffers
|
||||
harq_softbuffer_pool::get_instance().init_pool(cfg->nof_prb());
|
||||
}
|
||||
|
||||
} // namespace sched_nr_impl
|
||||
} // namespace srsenb
|
|
@ -0,0 +1,110 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "srsenb/hdr/stack/mac/nr/sched_nr_cfg.h"
|
||||
#include "srsenb/hdr/stack/mac/nr/sched_nr_helpers.h"
|
||||
|
||||
namespace srsenb {
|
||||
namespace sched_nr_impl {
|
||||
|
||||
bwp_params::bwp_params(const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_, uint32_t cc_, uint32_t bwp_id_) :
|
||||
cell_cfg(cell), sched_cfg(sched_cfg_), cc(cc_), bwp_id(bwp_id_), cfg(cell.bwps[bwp_id_])
|
||||
{
|
||||
P = get_P(cfg.rb_width, cfg.pdsch.rbg_size_cfg_1);
|
||||
N_rbg = get_nof_rbgs(cfg.rb_width, cfg.start_rb, cfg.pdsch.rbg_size_cfg_1);
|
||||
|
||||
srsran_assert(bwp_id != 0 or cfg.pdcch.coreset_present[0], "CORESET#0 has to be active for initial BWP");
|
||||
}
|
||||
|
||||
sched_cell_params::sched_cell_params(uint32_t cc_, const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_) :
|
||||
cc(cc_), cell_cfg(cell), sched_cfg(sched_cfg_)
|
||||
{
|
||||
bwps.reserve(cell.bwps.size());
|
||||
for (uint32_t i = 0; i < cell.bwps.size(); ++i) {
|
||||
bwps.emplace_back(cell, sched_cfg_, cc, i);
|
||||
}
|
||||
srsran_assert(not bwps.empty(), "No BWPs were configured");
|
||||
}
|
||||
|
||||
sched_params::sched_params(const sched_cfg_t& sched_cfg_) : sched_cfg(sched_cfg_) {}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void get_dci_locs(const srsran_coreset_t& coreset,
|
||||
const srsran_search_space_t& search_space,
|
||||
uint16_t rnti,
|
||||
bwp_cce_pos_list& cce_locs)
|
||||
{
|
||||
for (uint32_t sl = 0; sl < SRSRAN_NOF_SF_X_FRAME; ++sl) {
|
||||
for (uint32_t agg_idx = 0; agg_idx < MAX_NOF_AGGR_LEVELS; ++agg_idx) {
|
||||
pdcch_cce_pos_list pdcch_locs;
|
||||
cce_locs[sl][agg_idx].resize(pdcch_locs.capacity());
|
||||
uint32_t n =
|
||||
srsran_pdcch_nr_locations_coreset(&coreset, &search_space, rnti, agg_idx, sl, cce_locs[sl][agg_idx].data());
|
||||
cce_locs[sl][agg_idx].resize(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bwp_ue_cfg::bwp_ue_cfg(uint16_t rnti_, const bwp_params& bwp_cfg_, const ue_cfg_t& uecfg_) :
|
||||
rnti(rnti_), cfg_(&uecfg_), bwp_cfg(&bwp_cfg_)
|
||||
{
|
||||
std::fill(ss_id_to_cce_idx.begin(), ss_id_to_cce_idx.end(), SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE);
|
||||
const auto& pdcch = phy().pdcch;
|
||||
for (uint32_t i = 0; i < SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE; ++i) {
|
||||
if (pdcch.search_space_present[i]) {
|
||||
const auto& ss = pdcch.search_space[i];
|
||||
srsran_assert(pdcch.coreset_present[ss.coreset_id],
|
||||
"Invalid mapping search space id=%d to coreset id=%d",
|
||||
ss.id,
|
||||
ss.coreset_id);
|
||||
const auto& coreset = pdcch.coreset[ss.coreset_id];
|
||||
cce_positions_list.emplace_back();
|
||||
get_dci_locs(coreset, ss, rnti, cce_positions_list.back());
|
||||
ss_id_to_cce_idx[ss.id] = cce_positions_list.size() - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ue_cfg_extended::ue_cfg_extended(uint16_t rnti_, const ue_cfg_t& uecfg) : ue_cfg_t(uecfg), rnti(rnti_)
|
||||
{
|
||||
cc_params.resize(carriers.size());
|
||||
for (uint32_t cc = 0; cc < cc_params.size(); ++cc) {
|
||||
cc_params[cc].bwps.resize(1);
|
||||
auto& bwp = cc_params[cc].bwps[0];
|
||||
for (uint32_t ssid = 0; ssid < SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE; ++ssid) {
|
||||
if (phy_cfg.pdcch.search_space_present[ssid]) {
|
||||
auto& ss = phy_cfg.pdcch.search_space[ssid];
|
||||
bwp.ss_list[ss.id].emplace();
|
||||
bwp.ss_list[ss.id]->cfg = &ss;
|
||||
get_dci_locs(phy_cfg.pdcch.coreset[ss.coreset_id], ss, rnti, bwp.ss_list[ss.id]->cce_positions);
|
||||
}
|
||||
}
|
||||
for (uint32_t idx = 0; idx < SRSRAN_UE_DL_NR_MAX_NOF_CORESET; ++idx) {
|
||||
if (phy_cfg.pdcch.coreset_present[idx]) {
|
||||
bwp.coresets.emplace_back();
|
||||
auto& coreset = bwp.coresets.back();
|
||||
coreset.cfg = &phy_cfg.pdcch.coreset[idx];
|
||||
for (auto& ss : bwp.ss_list) {
|
||||
if (ss.has_value() and ss->cfg->coreset_id == coreset.cfg->id) {
|
||||
coreset.ss_list.push_back(ss->cfg->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sched_nr_impl
|
||||
} // namespace srsenb
|
|
@ -1,52 +0,0 @@
|
|||
/**
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* This file is part of srsRAN.
|
||||
*
|
||||
* srsRAN is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* srsRAN is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* A copy of the GNU Affero General Public License can be found in
|
||||
* the LICENSE file in the top-level directory of this distribution
|
||||
* and at http://www.gnu.org/licenses/.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "srsenb/hdr/stack/mac/nr/sched_nr_common.h"
|
||||
|
||||
namespace srsenb {
|
||||
namespace sched_nr_impl {
|
||||
|
||||
sched_cell_params::sched_cell_params(uint32_t cc_, const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_) :
|
||||
cc(cc_), cell_cfg(cell), sched_cfg(sched_cfg_)
|
||||
{}
|
||||
|
||||
sched_params::sched_params(const sched_cfg_t& sched_cfg_) : sched_cfg(sched_cfg_) {}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void get_dci_locs(const srsran_coreset_t& coreset,
|
||||
const srsran_search_space_t& search_space,
|
||||
uint16_t rnti,
|
||||
bwp_cce_pos_list& cce_locs)
|
||||
{
|
||||
for (uint32_t sl = 0; sl < SRSRAN_NOF_SF_X_FRAME; ++sl) {
|
||||
for (uint32_t agg_idx = 0; agg_idx < MAX_NOF_AGGR_LEVELS; ++agg_idx) {
|
||||
pdcch_cce_pos_list pdcch_locs;
|
||||
cce_locs[sl][agg_idx].resize(pdcch_locs.capacity());
|
||||
uint32_t n =
|
||||
srsran_pdcch_nr_locations_coreset(&coreset, &search_space, rnti, agg_idx, sl, cce_locs[sl][agg_idx].data());
|
||||
cce_locs[sl][agg_idx].resize(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sched_nr_impl
|
||||
} // namespace srsenb
|
|
@ -54,7 +54,7 @@ void harq_proc::reset()
|
|||
|
||||
bool harq_proc::new_tx(tti_point tti_tx_,
|
||||
tti_point tti_ack_,
|
||||
const rbgmask_t& rbgmask_,
|
||||
const prb_grant& grant,
|
||||
uint32_t mcs,
|
||||
uint32_t tbs,
|
||||
uint32_t max_retx_)
|
||||
|
@ -66,7 +66,7 @@ bool harq_proc::new_tx(tti_point tti_tx_,
|
|||
max_retx = max_retx_;
|
||||
tti_tx = tti_tx_;
|
||||
tti_ack = tti_ack_;
|
||||
rbgmask = rbgmask_;
|
||||
prbs_ = grant;
|
||||
tb[0].ndi = !tb[0].ndi;
|
||||
tb[0].mcs = mcs;
|
||||
tb[0].tbs = tbs;
|
||||
|
@ -74,32 +74,49 @@ bool harq_proc::new_tx(tti_point tti_tx_,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool harq_proc::new_retx(tti_point tti_tx_, tti_point tti_ack_, const rbgmask_t& rbgmask_, int* mcs, int* tbs)
|
||||
bool harq_proc::set_tbs(uint32_t tbs)
|
||||
{
|
||||
if (empty() or rbgmask.count() != rbgmask.count()) {
|
||||
if (empty() or nof_retx() > 0) {
|
||||
return false;
|
||||
}
|
||||
tb[0].tbs = tbs;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool harq_proc::new_retx(tti_point tti_tx_, tti_point tti_ack_, const prb_grant& grant)
|
||||
{
|
||||
if (grant.is_alloc_type0() != prbs_.is_alloc_type0() or
|
||||
(grant.is_alloc_type0() and grant.rbgs().count() != prbs_.rbgs().count()) or
|
||||
(grant.is_alloc_type1() and grant.prbs().length() == prbs_.prbs().length())) {
|
||||
return false;
|
||||
}
|
||||
if (new_retx(tti_tx_, tti_ack_)) {
|
||||
prbs_ = grant;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool harq_proc::new_retx(tti_point tti_tx_, tti_point tti_ack_)
|
||||
{
|
||||
if (empty()) {
|
||||
return false;
|
||||
}
|
||||
tti_tx = tti_tx_;
|
||||
tti_ack = tti_ack_;
|
||||
rbgmask = rbgmask_;
|
||||
tb[0].ack_state = false;
|
||||
tb[0].n_rtx++;
|
||||
if (mcs != nullptr) {
|
||||
*mcs = tb[0].mcs;
|
||||
}
|
||||
if (tbs != nullptr) {
|
||||
*tbs = tb[0].tbs;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
harq_entity::harq_entity(uint32_t nof_harq_procs)
|
||||
harq_entity::harq_entity(uint32_t nprb, uint32_t nof_harq_procs)
|
||||
{
|
||||
// Create HARQs
|
||||
dl_harqs.reserve(nof_harq_procs);
|
||||
ul_harqs.reserve(nof_harq_procs);
|
||||
for (uint32_t pid = 0; pid < nof_harq_procs; ++pid) {
|
||||
dl_harqs.emplace_back(pid);
|
||||
ul_harqs.emplace_back(pid);
|
||||
dl_harqs.emplace_back(pid, nprb);
|
||||
ul_harqs.emplace_back(pid, nprb);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "srsenb/hdr/stack/mac/nr/sched_nr_helpers.h"
|
||||
#include "srsenb/hdr/stack/mac/nr/sched_nr_harq.h"
|
||||
#include "srsenb/hdr/stack/mac/nr/sched_nr_ue.h"
|
||||
|
||||
namespace srsenb {
|
||||
namespace sched_nr_impl {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool fill_dci_rar(prb_interval interv, const bwp_params& cell, srsran_dci_dl_nr_t& dci)
|
||||
{
|
||||
dci.mcs = 5;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename DciDlOrUl>
|
||||
void fill_dci_common(const slot_ue& ue, const bwp_params& bwp_cfg, DciDlOrUl& dci)
|
||||
{
|
||||
const static uint32_t rv_idx[4] = {0, 2, 3, 1};
|
||||
|
||||
dci.bwp_id = ue.cfg->active_bwp().bwp_id;
|
||||
dci.cc_id = ue.cc;
|
||||
dci.tpc = 1;
|
||||
// harq
|
||||
harq_proc* h = std::is_same<DciDlOrUl, srsran_dci_dl_nr_t>::value ? ue.h_dl : ue.h_ul;
|
||||
dci.pid = h->pid;
|
||||
dci.ndi = h->ndi();
|
||||
dci.mcs = h->mcs();
|
||||
dci.rv = rv_idx[h->nof_retx() % 4];
|
||||
// PRB assignment
|
||||
const prb_grant& grant = h->prbs();
|
||||
if (grant.is_alloc_type0()) {
|
||||
dci.freq_domain_assigment = grant.rbgs().to_uint64();
|
||||
} else {
|
||||
dci.freq_domain_assigment =
|
||||
srsran_ra_nr_type1_riv(bwp_cfg.cfg.rb_width, grant.prbs().start(), grant.prbs().length());
|
||||
}
|
||||
dci.time_domain_assigment = 0;
|
||||
}
|
||||
|
||||
void fill_dl_dci_ue_fields(const slot_ue& ue,
|
||||
const bwp_params& bwp_cfg,
|
||||
uint32_t ss_id,
|
||||
srsran_dci_location_t dci_pos,
|
||||
srsran_dci_dl_nr_t& dci)
|
||||
{
|
||||
// Note: DCI location may not be the final one, as scheduler may rellocate the UE PDCCH. However, the remaining DCI
|
||||
// params are independent of the exact DCI location
|
||||
bool ret = ue.cfg->phy().get_dci_ctx_pdsch_rnti_c(ss_id, dci_pos, ue.rnti, dci.ctx);
|
||||
srsran_assert(ret, "Invalid DL DCI format");
|
||||
|
||||
fill_dci_common(ue, bwp_cfg, dci);
|
||||
if (dci.ctx.format == srsran_dci_format_nr_1_0) {
|
||||
dci.harq_feedback = ue.cfg->phy().harq_ack.dl_data_to_ul_ack[ue.pdsch_tti.sf_idx()] - 1;
|
||||
} else {
|
||||
dci.harq_feedback = ue.pdsch_tti.sf_idx();
|
||||
}
|
||||
}
|
||||
|
||||
void fill_ul_dci_ue_fields(const slot_ue& ue,
|
||||
const bwp_params& bwp_cfg,
|
||||
uint32_t ss_id,
|
||||
srsran_dci_location_t dci_pos,
|
||||
srsran_dci_ul_nr_t& dci)
|
||||
{
|
||||
bool ret = ue.cfg->phy().get_dci_ctx_pdsch_rnti_c(ss_id, dci_pos, ue.rnti, dci.ctx);
|
||||
srsran_assert(ret, "Invalid DL DCI format");
|
||||
|
||||
fill_dci_common(ue, bwp_cfg, dci);
|
||||
}
|
||||
|
||||
} // namespace sched_nr_impl
|
||||
} // namespace srsenb
|
|
@ -25,22 +25,25 @@
|
|||
namespace srsenb {
|
||||
namespace sched_nr_impl {
|
||||
|
||||
coreset_region::coreset_region(uint32_t bwp_id_,
|
||||
uint32_t slot_idx_,
|
||||
uint32_t nof_td_symbols,
|
||||
uint32_t nof_freq_resources,
|
||||
pdcch_dl_list_t& pdcch_list_) :
|
||||
bwp_id(bwp_id_),
|
||||
coreset_region::coreset_region(const bwp_params& bwp_cfg_,
|
||||
uint32_t coreset_id_,
|
||||
uint32_t slot_idx_,
|
||||
pdcch_dl_list_t& dl_list_,
|
||||
pdcch_ul_list_t& ul_list_) :
|
||||
coreset_cfg(&bwp_cfg_.cfg.pdcch.coreset[coreset_id_]),
|
||||
coreset_id(coreset_id_),
|
||||
slot_idx(slot_idx_),
|
||||
nof_symbols(nof_td_symbols),
|
||||
nof_freq_res(nof_freq_resources),
|
||||
pdcch_dl_list(pdcch_list_)
|
||||
pdcch_dl_list(dl_list_),
|
||||
pdcch_ul_list(ul_list_)
|
||||
{
|
||||
srsran_assert(nof_td_symbols <= SRSRAN_CORESET_DURATION_MAX,
|
||||
const bool* res_active = &coreset_cfg->freq_resources[0];
|
||||
nof_freq_res = std::count(res_active, res_active + SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE, true);
|
||||
srsran_assert(get_td_symbols() <= SRSRAN_CORESET_DURATION_MAX,
|
||||
"Possible number of time-domain OFDM symbols in CORESET must be within {1,2,3}");
|
||||
srsran_assert(nof_freq_resources <= SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE,
|
||||
"Provided number of CORESET freq domain resources=%d is too high",
|
||||
nof_freq_resources);
|
||||
srsran_assert(nof_freq_res <= bwp_cfg_.cell_cfg.carrier.nof_prb,
|
||||
"The number of frequency resources=%d of coreset_id=%d exceeds BWP bandwidth",
|
||||
nof_freq_res,
|
||||
coreset_id);
|
||||
}
|
||||
|
||||
void coreset_region::reset()
|
||||
|
@ -49,9 +52,13 @@ void coreset_region::reset()
|
|||
saved_dfs_tree.clear();
|
||||
dci_list.clear();
|
||||
pdcch_dl_list.clear();
|
||||
pdcch_ul_list.clear();
|
||||
}
|
||||
|
||||
bool coreset_region::alloc_dci(pdcch_grant_type_t alloc_type, uint32_t aggr_idx, uint32_t coreset_id, slot_ue* user)
|
||||
bool coreset_region::alloc_dci(pdcch_grant_type_t alloc_type,
|
||||
uint32_t aggr_idx,
|
||||
uint32_t search_space_id,
|
||||
slot_ue* user)
|
||||
{
|
||||
srsran_assert(aggr_idx <= 4, "Invalid DCI aggregation level=%d", 1U << aggr_idx);
|
||||
srsran_assert((user == nullptr) xor
|
||||
|
@ -62,10 +69,15 @@ bool coreset_region::alloc_dci(pdcch_grant_type_t alloc_type, uint32_t aggr_idx,
|
|||
alloc_record record;
|
||||
record.ue = user;
|
||||
record.aggr_idx = aggr_idx;
|
||||
record.ss_id = search_space_id;
|
||||
record.alloc_type = alloc_type;
|
||||
record.idx = pdcch_dl_list.size();
|
||||
record.coreset_id = coreset_id;
|
||||
pdcch_dl_list.emplace_back();
|
||||
if (record.alloc_type == pdcch_grant_type_t::ul_data) {
|
||||
record.idx = pdcch_ul_list.size();
|
||||
pdcch_ul_list.emplace_back();
|
||||
} else {
|
||||
record.idx = pdcch_dl_list.size();
|
||||
pdcch_dl_list.emplace_back();
|
||||
}
|
||||
|
||||
// Try to allocate grant. If it fails, attempt the same grant, but using a different permutation of past grant DCI
|
||||
// positions
|
||||
|
@ -83,7 +95,11 @@ bool coreset_region::alloc_dci(pdcch_grant_type_t alloc_type, uint32_t aggr_idx,
|
|||
|
||||
// Revert steps to initial state, before dci record allocation was attempted
|
||||
dfs_tree = saved_dfs_tree;
|
||||
pdcch_dl_list.pop_back();
|
||||
if (record.alloc_type == pdcch_grant_type_t::ul_data) {
|
||||
pdcch_ul_list.pop_back();
|
||||
} else {
|
||||
pdcch_dl_list.pop_back();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -93,8 +109,12 @@ void coreset_region::rem_last_dci()
|
|||
|
||||
// Remove DCI record
|
||||
dfs_tree.pop_back();
|
||||
if (dci_list.back().alloc_type == pdcch_grant_type_t::ul_data) {
|
||||
pdcch_ul_list.pop_back();
|
||||
} else {
|
||||
pdcch_dl_list.pop_back();
|
||||
}
|
||||
dci_list.pop_back();
|
||||
pdcch_dl_list.pop_back();
|
||||
}
|
||||
|
||||
bool coreset_region::get_next_dfs()
|
||||
|
@ -150,8 +170,13 @@ bool coreset_region::alloc_dfs_node(const alloc_record& record, uint32_t start_d
|
|||
// Allocation successful
|
||||
node.total_mask |= node.current_mask;
|
||||
alloc_dfs.push_back(node);
|
||||
pdcch_dl_t& pdcch_dl = pdcch_dl_list[record.idx];
|
||||
pdcch_dl.dci.ctx.location = node.dci_pos;
|
||||
if (record.alloc_type == pdcch_grant_type_t::ul_data) {
|
||||
pdcch_ul_t& pdcch_ul = pdcch_ul_list[record.idx];
|
||||
pdcch_ul.dci.ctx.location = node.dci_pos;
|
||||
} else {
|
||||
pdcch_dl_t& pdcch_dl = pdcch_dl_list[record.idx];
|
||||
pdcch_dl.dci.ctx.location = node.dci_pos;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -162,10 +187,9 @@ srsran::span<const uint32_t> coreset_region::get_cce_loc_table(const alloc_recor
|
|||
{
|
||||
switch (record.alloc_type) {
|
||||
case pdcch_grant_type_t::dl_data:
|
||||
return record.ue->cfg->cc_params[record.ue->cc]
|
||||
.bwps[bwp_id]
|
||||
.coresets[record.coreset_id]
|
||||
.cce_positions[slot_idx][record.aggr_idx];
|
||||
return record.ue->cfg->cce_pos_list(record.ss_id)[slot_idx][record.aggr_idx];
|
||||
case pdcch_grant_type_t::ul_data:
|
||||
return record.ue->cfg->cce_pos_list(record.ss_id)[slot_idx][record.aggr_idx];
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1,111 +0,0 @@
|
|||
/**
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* This file is part of srsRAN.
|
||||
*
|
||||
* srsRAN is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* srsRAN is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* A copy of the GNU Affero General Public License can be found in
|
||||
* the LICENSE file in the top-level directory of this distribution
|
||||
* and at http://www.gnu.org/licenses/.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h"
|
||||
#include "srsenb/hdr/stack/mac/nr/sched_nr_harq.h"
|
||||
#include "srsenb/hdr/stack/mac/nr/sched_nr_ue.h"
|
||||
|
||||
namespace srsenb {
|
||||
namespace sched_nr_impl {
|
||||
|
||||
/// Table 6.1.2.2.1-1 - Nominal RBG size P
|
||||
uint32_t get_P(uint32_t bwp_nof_prb, bool config_1_or_2)
|
||||
{
|
||||
srsran_assert(bwp_nof_prb > 0 and bwp_nof_prb <= 275, "Invalid BWP size");
|
||||
if (bwp_nof_prb <= 36) {
|
||||
return config_1_or_2 ? 2 : 4;
|
||||
}
|
||||
if (bwp_nof_prb <= 72) {
|
||||
return config_1_or_2 ? 4 : 8;
|
||||
}
|
||||
if (bwp_nof_prb <= 144) {
|
||||
return config_1_or_2 ? 8 : 16;
|
||||
}
|
||||
return 16;
|
||||
}
|
||||
|
||||
uint32_t get_nof_rbgs(uint32_t bwp_nof_prb, uint32_t bwp_start, bool config1_or_2)
|
||||
{
|
||||
uint32_t P = get_P(bwp_nof_prb, config1_or_2);
|
||||
return srsran::ceil_div(bwp_nof_prb + (bwp_start % P), P);
|
||||
}
|
||||
|
||||
uint32_t get_rbg_size(uint32_t bwp_nof_prb, uint32_t bwp_start, bool config1_or_2, uint32_t rbg_idx)
|
||||
{
|
||||
uint32_t P = get_P(bwp_nof_prb, config1_or_2);
|
||||
uint32_t nof_rbgs = get_nof_rbgs(bwp_nof_prb, bwp_start, config1_or_2);
|
||||
if (rbg_idx == 0) {
|
||||
return P - (bwp_start % P);
|
||||
}
|
||||
if (rbg_idx == nof_rbgs - 1) {
|
||||
uint32_t ret = (bwp_start + bwp_nof_prb) % P;
|
||||
return ret > 0 ? ret : P;
|
||||
}
|
||||
return P;
|
||||
}
|
||||
|
||||
void bitmap_to_prb_array(const rbgmask_t& bitmap, uint32_t bwp_nof_prb, srsran_sch_grant_nr_t& grant)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
grant.nof_prb = bwp_nof_prb;
|
||||
for (uint32_t rbg = 0; rbg < bitmap.size(); ++rbg) {
|
||||
bool val = bitmap.test(rbg);
|
||||
uint32_t rbg_size = get_rbg_size(bwp_nof_prb, 0, true, rbg);
|
||||
for (uint32_t prb = count; prb < count + rbg_size; ++prb) {
|
||||
grant.prb_idx[prb] = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fill_dci_harq(const harq_proc& h, srsran_dci_dl_nr_t& dci)
|
||||
{
|
||||
dci.pid = h.pid;
|
||||
dci.ndi = h.ndi();
|
||||
dci.mcs = h.mcs();
|
||||
}
|
||||
|
||||
void fill_dci_ue_cfg(const slot_ue& ue, srsran_dci_dl_nr_t& dci)
|
||||
{
|
||||
dci.bwp_id = ue.bwp_id;
|
||||
dci.cc_id = ue.cc;
|
||||
dci.ctx.rnti = ue.rnti;
|
||||
dci.tpc = 1;
|
||||
fill_dci_harq(*ue.h_dl, dci);
|
||||
}
|
||||
|
||||
void fill_dci_harq(const harq_proc& h, srsran_dci_ul_nr_t& dci)
|
||||
{
|
||||
dci.pid = h.pid;
|
||||
dci.ndi = h.ndi();
|
||||
dci.mcs = h.mcs();
|
||||
}
|
||||
|
||||
void fill_dci_ue_cfg(const slot_ue& ue, srsran_dci_ul_nr_t& dci)
|
||||
{
|
||||
dci.bwp_id = ue.bwp_id;
|
||||
dci.cc_id = ue.cc;
|
||||
dci.ctx.rnti = ue.rnti;
|
||||
dci.tpc = 1;
|
||||
fill_dci_harq(*ue.h_ul, dci);
|
||||
}
|
||||
|
||||
} // namespace sched_nr_impl
|
||||
} // namespace srsenb
|
|
@ -0,0 +1,105 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "srsenb/hdr/stack/mac/nr/sched_nr_rb.h"
|
||||
|
||||
namespace srsenb {
|
||||
namespace sched_nr_impl {
|
||||
|
||||
/// TS 38.214, Table 6.1.2.2.1-1 - Nominal RBG size P
|
||||
uint32_t get_P(uint32_t bwp_nof_prb, bool config_1_or_2)
|
||||
{
|
||||
srsran_assert(bwp_nof_prb > 0 and bwp_nof_prb <= 275, "Invalid BWP size");
|
||||
if (bwp_nof_prb <= 36) {
|
||||
return config_1_or_2 ? 2 : 4;
|
||||
}
|
||||
if (bwp_nof_prb <= 72) {
|
||||
return config_1_or_2 ? 4 : 8;
|
||||
}
|
||||
if (bwp_nof_prb <= 144) {
|
||||
return config_1_or_2 ? 8 : 16;
|
||||
}
|
||||
return 16;
|
||||
}
|
||||
|
||||
/// TS 38.214 - total number of RBGs for a uplink bandwidth part of size "bwp_nof_prb" PRBs
|
||||
uint32_t get_nof_rbgs(uint32_t bwp_nof_prb, uint32_t bwp_start, bool config1_or_2)
|
||||
{
|
||||
uint32_t P = get_P(bwp_nof_prb, config1_or_2);
|
||||
return srsran::ceil_div(bwp_nof_prb + (bwp_start % P), P);
|
||||
}
|
||||
|
||||
uint32_t get_rbg_size(uint32_t bwp_nof_prb, uint32_t bwp_start, bool config1_or_2, uint32_t rbg_idx)
|
||||
{
|
||||
uint32_t P = get_P(bwp_nof_prb, config1_or_2);
|
||||
uint32_t nof_rbgs = get_nof_rbgs(bwp_nof_prb, bwp_start, config1_or_2);
|
||||
if (rbg_idx == 0) {
|
||||
return P - (bwp_start % P);
|
||||
}
|
||||
if (rbg_idx == nof_rbgs - 1) {
|
||||
uint32_t ret = (bwp_start + bwp_nof_prb) % P;
|
||||
return ret > 0 ? ret : P;
|
||||
}
|
||||
return P;
|
||||
}
|
||||
|
||||
bwp_rb_bitmap::bwp_rb_bitmap(uint32_t bwp_nof_prbs, uint32_t bwp_prb_start_, bool config1_or_2) :
|
||||
prbs_(bwp_nof_prbs),
|
||||
rbgs_(get_nof_rbgs(bwp_nof_prbs, bwp_prb_start_, config1_or_2)),
|
||||
P_(get_P(bwp_nof_prbs, config1_or_2)),
|
||||
Pnofbits(log2(P_)),
|
||||
first_rbg_size(get_rbg_size(bwp_nof_prbs, bwp_prb_start_, config1_or_2, 0))
|
||||
{}
|
||||
|
||||
uint32_t bwp_rb_bitmap::prb_to_rbg_idx(uint32_t prb_idx) const
|
||||
{
|
||||
return ((prb_idx + P_ - first_rbg_size) >> Pnofbits);
|
||||
}
|
||||
|
||||
void bwp_rb_bitmap::add_prbs_to_rbgs(const prb_bitmap& grant)
|
||||
{
|
||||
int idx = 0;
|
||||
do {
|
||||
idx = grant.find_lowest(idx, grant.size(), true);
|
||||
if (idx < 0) {
|
||||
return;
|
||||
}
|
||||
uint32_t rbg_idx = prb_to_rbg_idx(idx);
|
||||
rbgs_.set(rbg_idx, true);
|
||||
idx++;
|
||||
} while (idx != (int)prbs_.size());
|
||||
}
|
||||
|
||||
void bwp_rb_bitmap::add_prbs_to_rbgs(const prb_interval& grant)
|
||||
{
|
||||
uint32_t rbg_start = prb_to_rbg_idx(grant.start());
|
||||
uint32_t rbg_stop = std::min(prb_to_rbg_idx(grant.stop() - 1) + 1u, (uint32_t)rbgs_.size());
|
||||
rbgs_.fill(rbg_start, rbg_stop);
|
||||
}
|
||||
|
||||
void bwp_rb_bitmap::add_rbgs_to_prbs(const rbg_bitmap& grant)
|
||||
{
|
||||
int idx = 0;
|
||||
do {
|
||||
idx = grant.find_lowest(idx, grant.size(), true);
|
||||
if (idx < 0) {
|
||||
return;
|
||||
}
|
||||
uint32_t prb_idx = (idx - 1) * P_ + first_rbg_size;
|
||||
uint32_t prb_end = std::min(prb_idx + ((idx == 0) ? first_rbg_size : P_), (uint32_t)prbs_.size());
|
||||
prbs_.fill(prb_idx, prb_end);
|
||||
idx++;
|
||||
} while (idx != (int)prbs_.size());
|
||||
}
|
||||
|
||||
} // namespace sched_nr_impl
|
||||
} // namespace srsenb
|
|
@ -20,138 +20,239 @@
|
|||
*/
|
||||
|
||||
#include "srsenb/hdr/stack/mac/nr/sched_nr_rb_grid.h"
|
||||
#include "srsenb/hdr/stack/mac/nr/sched_nr_phy_helpers.h"
|
||||
#include "srsenb/hdr/stack/mac/nr/sched_nr_helpers.h"
|
||||
|
||||
namespace srsenb {
|
||||
namespace sched_nr_impl {
|
||||
|
||||
using pusch_grant = sched_nr_interface::pusch_grant;
|
||||
#define NUMEROLOGY_IDX 0
|
||||
|
||||
bwp_slot_grid::bwp_slot_grid(const sched_cell_params& cell_params, uint32_t bwp_id_, uint32_t slot_idx_) :
|
||||
dl_rbgs(cell_params.cell_cfg.nof_rbg), ul_rbgs(cell_params.cell_cfg.nof_rbg)
|
||||
bwp_slot_grid::bwp_slot_grid(const bwp_params& bwp_cfg_, uint32_t slot_idx_) :
|
||||
dl_prbs(bwp_cfg_.cfg.rb_width, bwp_cfg_.cfg.start_rb, bwp_cfg_.cfg.pdsch.rbg_size_cfg_1),
|
||||
ul_prbs(bwp_cfg_.cfg.rb_width, bwp_cfg_.cfg.start_rb, bwp_cfg_.cfg.pdsch.rbg_size_cfg_1),
|
||||
slot_idx(slot_idx_),
|
||||
cfg(&bwp_cfg_),
|
||||
is_dl(srsran_tdd_nr_is_dl(&bwp_cfg_.cell_cfg.tdd, NUMEROLOGY_IDX, slot_idx_)),
|
||||
is_ul(srsran_tdd_nr_is_ul(&bwp_cfg_.cell_cfg.tdd, NUMEROLOGY_IDX, slot_idx_))
|
||||
{
|
||||
coresets.emplace_back(bwp_id_, slot_idx_, 1, cell_params.cell_cfg.bwps[bwp_id_].rb_width / 6, pdcch_dl_list);
|
||||
for (uint32_t cs_idx = 0; cs_idx < SRSRAN_UE_DL_NR_MAX_NOF_CORESET; ++cs_idx) {
|
||||
if (cfg->cfg.pdcch.coreset_present[cs_idx]) {
|
||||
uint32_t cs_id = cfg->cfg.pdcch.coreset[cs_idx].id;
|
||||
coresets[cs_id].emplace(*cfg, cs_id, slot_idx_, dl_pdcchs, ul_pdcchs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bwp_slot_grid::reset()
|
||||
{
|
||||
for (auto& coreset : coresets) {
|
||||
coreset.reset();
|
||||
if (coreset.has_value()) {
|
||||
coreset->reset();
|
||||
}
|
||||
}
|
||||
dl_rbgs.reset();
|
||||
ul_rbgs.reset();
|
||||
pdsch_grants.clear();
|
||||
pdcch_dl_list.clear();
|
||||
pusch_grants.clear();
|
||||
pucch_grants.clear();
|
||||
dl_prbs.reset();
|
||||
ul_prbs.reset();
|
||||
dl_pdcchs.clear();
|
||||
ul_pdcchs.clear();
|
||||
pending_acks.clear();
|
||||
}
|
||||
|
||||
bwp_res_grid::bwp_res_grid(const sched_cell_params& cell_cfg_, uint32_t bwp_id_) : bwp_id(bwp_id_), cell_cfg(&cell_cfg_)
|
||||
bwp_res_grid::bwp_res_grid(const bwp_params& bwp_cfg_) : cfg(&bwp_cfg_)
|
||||
{
|
||||
for (uint32_t sl = 0; sl < SCHED_NR_NOF_SUBFRAMES; ++sl) {
|
||||
slots.emplace_back(cell_cfg_, bwp_id, sl);
|
||||
}
|
||||
}
|
||||
|
||||
cell_res_grid::cell_res_grid(const sched_cell_params& cell_cfg_) : cell_cfg(&cell_cfg_)
|
||||
{
|
||||
for (uint32_t bwp_id = 0; bwp_id < cell_cfg->cell_cfg.bwps.size(); ++bwp_id) {
|
||||
bwps.emplace_back(cell_cfg_, bwp_id);
|
||||
for (uint32_t sl = 0; sl < slots.capacity(); ++sl) {
|
||||
slots.emplace_back(*cfg, sl % static_cast<uint32_t>(SRSRAN_NSLOTS_PER_FRAME_NR(0u)));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
slot_bwp_sched::slot_bwp_sched(uint32_t bwp_id, cell_res_grid& phy_grid_) :
|
||||
logger(srslog::fetch_basic_logger("MAC")), cfg(*phy_grid_.cell_cfg), bwp_grid(phy_grid_.bwps[bwp_id])
|
||||
bwp_slot_allocator::bwp_slot_allocator(bwp_res_grid& bwp_grid_) :
|
||||
logger(srslog::fetch_basic_logger("MAC")), cfg(*bwp_grid_.cfg), bwp_grid(bwp_grid_)
|
||||
{}
|
||||
|
||||
alloc_result slot_bwp_sched::alloc_pdsch(slot_ue& ue, const rbgmask_t& dl_mask)
|
||||
alloc_result bwp_slot_allocator::alloc_rar(uint32_t aggr_idx,
|
||||
const srsenb::sched_nr_impl::pending_rar_t& rar,
|
||||
prb_interval interv,
|
||||
uint32_t nof_grants)
|
||||
{
|
||||
if (ue.h_dl == nullptr) {
|
||||
logger.warning("SCHED: Trying to allocate PDSCH for rnti=0x%x with no available HARQs", ue.rnti);
|
||||
return alloc_result::no_rnti_opportunity;
|
||||
}
|
||||
pdsch_list_t& pdsch_grants = bwp_grid[ue.pdsch_tti].pdsch_grants;
|
||||
if (pdsch_grants.full()) {
|
||||
static const uint32_t msg3_nof_prbs = 3;
|
||||
|
||||
bwp_slot_grid& bwp_pdcch_slot = bwp_grid[pdcch_tti];
|
||||
bwp_slot_grid& bwp_msg3_slot = bwp_grid[pdcch_tti + 4];
|
||||
|
||||
if (bwp_pdcch_slot.dl_pdcchs.full()) {
|
||||
logger.warning("SCHED: Maximum number of DL allocations reached");
|
||||
return alloc_result::no_grant_space;
|
||||
}
|
||||
rbgmask_t& pdsch_mask = bwp_grid[ue.pdsch_tti].dl_rbgs;
|
||||
|
||||
// Check DL RB collision
|
||||
const prb_bitmap& pdsch_mask = bwp_pdcch_slot.dl_prbs.prbs();
|
||||
prb_bitmap dl_mask(pdsch_mask.size());
|
||||
dl_mask.fill(interv.start(), interv.stop());
|
||||
if ((pdsch_mask & dl_mask).any()) {
|
||||
logger.debug("SCHED: Provided RBG mask collides with allocation previously made.");
|
||||
return alloc_result::sch_collision;
|
||||
}
|
||||
const uint32_t aggr_idx = 3, coreset_id = 0;
|
||||
if (not bwp_grid[ue.pdcch_tti].coresets[coreset_id].alloc_dci(
|
||||
pdcch_grant_type_t::dl_data, aggr_idx, coreset_id, &ue)) {
|
||||
|
||||
// Check Msg3 RB collision
|
||||
uint32_t total_ul_nof_prbs = msg3_nof_prbs * nof_grants;
|
||||
uint32_t total_ul_nof_rbgs = srsran::ceil_div(total_ul_nof_prbs, get_P(bwp_grid.nof_prbs(), false));
|
||||
prb_interval msg3_rbgs = find_empty_interval_of_length(bwp_msg3_slot.ul_prbs.prbs(), total_ul_nof_rbgs);
|
||||
if (msg3_rbgs.length() < total_ul_nof_rbgs) {
|
||||
logger.debug("SCHED: No space in PUSCH for Msg3.");
|
||||
return alloc_result::sch_collision;
|
||||
}
|
||||
|
||||
// Find PDCCH position
|
||||
const uint32_t coreset_id = cfg.cfg.pdcch.ra_search_space.coreset_id;
|
||||
const uint32_t search_space_id = cfg.cfg.pdcch.ra_search_space.id;
|
||||
if (not bwp_pdcch_slot.coresets[coreset_id]->alloc_dci(pdcch_grant_type_t::rar, aggr_idx, search_space_id, nullptr)) {
|
||||
// Could not find space in PDCCH
|
||||
logger.debug("SCHED: No space in PDCCH for DL tx.");
|
||||
return alloc_result::no_cch_space;
|
||||
}
|
||||
|
||||
int mcs = -1, tbs = -1;
|
||||
if (ue.h_dl->empty()) {
|
||||
mcs = 20;
|
||||
tbs = 100;
|
||||
bool ret = ue.h_dl->new_tx(ue.pdsch_tti, ue.uci_tti, dl_mask, mcs, tbs, 4);
|
||||
srsran_assert(ret, "Failed to allocate DL HARQ");
|
||||
} else {
|
||||
bool ret = ue.h_dl->new_retx(ue.pdsch_tti, ue.uci_tti, dl_mask, &mcs, &tbs);
|
||||
srsran_assert(ret, "Failed to allocate DL HARQ retx");
|
||||
// Generate DCI for RAR
|
||||
pdcch_dl_t& pdcch = bwp_pdcch_slot.dl_pdcchs.back();
|
||||
if (not fill_dci_rar(interv, *bwp_grid.cfg, pdcch.dci)) {
|
||||
// Cancel on-going PDCCH allocation
|
||||
bwp_pdcch_slot.coresets[coreset_id]->rem_last_dci();
|
||||
return alloc_result::invalid_coderate;
|
||||
}
|
||||
|
||||
// Allocation Successful
|
||||
pdcch_dl_t& pdcch = bwp_grid[ue.pdcch_tti].pdcch_dl_list.back();
|
||||
fill_dci_ue_cfg(ue, pdcch.dci);
|
||||
pdsch_grants.emplace_back();
|
||||
pdsch_t& grant = pdsch_grants.back();
|
||||
grant.sch.grant.rnti = ue.rnti;
|
||||
bitmap_to_prb_array(dl_mask, bwp_grid.nof_prbs(), grant.sch.grant);
|
||||
pdsch_mask |= dl_mask;
|
||||
// RAR allocation successful.
|
||||
bwp_pdcch_slot.dl_prbs.add(interv);
|
||||
|
||||
return alloc_result::success;
|
||||
}
|
||||
|
||||
alloc_result slot_bwp_sched::alloc_pusch(slot_ue& ue, const rbgmask_t& ul_mask)
|
||||
alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, const prb_grant& dl_grant)
|
||||
{
|
||||
if (ue.cfg->active_bwp().bwp_id != bwp_grid.cfg->bwp_id) {
|
||||
logger.warning(
|
||||
"SCHED: Trying to allocate PDSCH for rnti=0x%x in inactive BWP id=%d", ue.rnti, ue.cfg->active_bwp().bwp_id);
|
||||
return alloc_result::no_rnti_opportunity;
|
||||
}
|
||||
if (ue.h_dl == nullptr) {
|
||||
logger.warning("SCHED: Trying to allocate PDSCH for rnti=0x%x with no available HARQs", ue.rnti);
|
||||
return alloc_result::no_rnti_opportunity;
|
||||
}
|
||||
bwp_slot_grid& bwp_pdcch_slot = bwp_grid[ue.pdcch_tti];
|
||||
bwp_slot_grid& bwp_pdsch_slot = bwp_grid[ue.pdsch_tti];
|
||||
bwp_slot_grid& bwp_uci_slot = bwp_grid[ue.uci_tti];
|
||||
if (not bwp_pdsch_slot.is_dl) {
|
||||
logger.warning("SCHED: Trying to allocate PDSCH in TDD non-DL slot index=%d", bwp_pdsch_slot.slot_idx);
|
||||
return alloc_result::no_sch_space;
|
||||
}
|
||||
pdcch_dl_list_t& pdsch_grants = bwp_pdsch_slot.dl_pdcchs;
|
||||
if (pdsch_grants.full()) {
|
||||
logger.warning("SCHED: Maximum number of DL allocations reached");
|
||||
return alloc_result::no_grant_space;
|
||||
}
|
||||
if (bwp_pdcch_slot.dl_prbs.collides(dl_grant)) {
|
||||
return alloc_result::sch_collision;
|
||||
}
|
||||
|
||||
// Find space in PUCCH
|
||||
// TODO
|
||||
|
||||
// Find space and allocate PDCCH
|
||||
const uint32_t aggr_idx = 2, ss_id = 1;
|
||||
uint32_t coreset_id = ue.cfg->phy().pdcch.search_space[ss_id].coreset_id;
|
||||
if (not bwp_pdcch_slot.coresets[coreset_id]->alloc_dci(pdcch_grant_type_t::dl_data, aggr_idx, ss_id, &ue)) {
|
||||
// Could not find space in PDCCH
|
||||
return alloc_result::no_cch_space;
|
||||
}
|
||||
|
||||
// Allocate HARQ
|
||||
if (ue.h_dl->empty()) {
|
||||
int mcs = 20;
|
||||
int tbs = 100;
|
||||
bool ret = ue.h_dl->new_tx(ue.pdsch_tti, ue.uci_tti, dl_grant, mcs, tbs, 4);
|
||||
srsran_assert(ret, "Failed to allocate DL HARQ");
|
||||
} else {
|
||||
bool ret = ue.h_dl->new_retx(ue.pdsch_tti, ue.uci_tti, dl_grant);
|
||||
srsran_assert(ret, "Failed to allocate DL HARQ retx");
|
||||
}
|
||||
|
||||
// Allocation Successful
|
||||
|
||||
// Generate PDCCH
|
||||
pdcch_dl_t& pdcch = bwp_pdcch_slot.dl_pdcchs.back();
|
||||
fill_dl_dci_ue_fields(ue, *bwp_grid.cfg, ss_id, pdcch.dci.ctx.location, pdcch.dci);
|
||||
pdcch.dci.pucch_resource = 0;
|
||||
pdcch.dci.dai = std::count_if(bwp_uci_slot.pending_acks.begin(),
|
||||
bwp_uci_slot.pending_acks.end(),
|
||||
[&ue](const harq_ack_t& p) { return p.res.rnti == ue.rnti; });
|
||||
pdcch.dci.dai %= 4;
|
||||
|
||||
// Generate PUCCH
|
||||
bwp_uci_slot.pending_acks.emplace_back();
|
||||
bwp_uci_slot.pending_acks.back().phy_cfg = &ue.cfg->phy();
|
||||
srsran_assert(ue.cfg->phy().get_pdsch_ack_resource(pdcch.dci, bwp_uci_slot.pending_acks.back().res),
|
||||
"Error getting ack resource");
|
||||
|
||||
// Generate PDSCH
|
||||
bwp_pdsch_slot.dl_prbs |= dl_grant;
|
||||
bwp_pdsch_slot.pdschs.emplace_back();
|
||||
pdsch_t& pdsch = bwp_pdsch_slot.pdschs.back();
|
||||
srsran_slot_cfg_t slot_cfg;
|
||||
slot_cfg.idx = ue.pdsch_tti.sf_idx();
|
||||
bool ret = ue.cfg->phy().get_pdsch_cfg(slot_cfg, pdcch.dci, pdsch.sch);
|
||||
srsran_assert(ret, "Error converting DCI to grant");
|
||||
if (ue.h_dl->nof_retx() == 0) {
|
||||
ue.h_dl->set_tbs(pdsch.sch.grant.tb[0].tbs); // update HARQ with correct TBS
|
||||
} else {
|
||||
srsran_assert(pdsch.sch.grant.tb[0].tbs == (int)ue.h_dl->tbs(), "The TBS did not remain constant in retx");
|
||||
}
|
||||
pdsch.sch.grant.tb[0].softbuffer.tx = ue.h_dl->get_softbuffer().get();
|
||||
|
||||
return alloc_result::success;
|
||||
}
|
||||
|
||||
alloc_result bwp_slot_allocator::alloc_pusch(slot_ue& ue, const rbg_bitmap& ul_mask)
|
||||
{
|
||||
if (ue.h_ul == nullptr) {
|
||||
logger.warning("SCHED: Trying to allocate PUSCH for rnti=0x%x with no available HARQs", ue.rnti);
|
||||
return alloc_result::no_rnti_opportunity;
|
||||
}
|
||||
pusch_list& pusch_grants = bwp_grid[ue.pusch_tti].pusch_grants;
|
||||
if (pusch_grants.full()) {
|
||||
auto& bwp_pdcch_slot = bwp_grid[ue.pdcch_tti];
|
||||
auto& bwp_pusch_slot = bwp_grid[ue.pusch_tti];
|
||||
if (not bwp_pusch_slot.is_ul) {
|
||||
logger.warning("SCHED: Trying to allocate PUSCH in TDD non-UL slot index=%d", bwp_pusch_slot.slot_idx);
|
||||
return alloc_result::no_sch_space;
|
||||
}
|
||||
pdcch_ul_list_t& pdcchs = bwp_pdcch_slot.ul_pdcchs;
|
||||
if (pdcchs.full()) {
|
||||
logger.warning("SCHED: Maximum number of UL allocations reached");
|
||||
return alloc_result::no_grant_space;
|
||||
}
|
||||
rbgmask_t& pusch_mask = bwp_grid[ue.pusch_tti].ul_rbgs;
|
||||
const rbg_bitmap& pusch_mask = bwp_pusch_slot.ul_prbs.rbgs();
|
||||
if ((pusch_mask & ul_mask).any()) {
|
||||
return alloc_result::sch_collision;
|
||||
}
|
||||
const uint32_t aggr_idx = 3, coreset_id = 0;
|
||||
if (not bwp_grid[ue.pdcch_tti].coresets[coreset_id].alloc_dci(
|
||||
pdcch_grant_type_t::ul_data, aggr_idx, coreset_id, &ue)) {
|
||||
const uint32_t aggr_idx = 2, ss_id = 1;
|
||||
uint32_t coreset_id = ue.cfg->phy().pdcch.search_space[ss_id].coreset_id;
|
||||
if (not bwp_pdcch_slot.coresets[coreset_id].value().alloc_dci(pdcch_grant_type_t::ul_data, aggr_idx, ss_id, &ue)) {
|
||||
// Could not find space in PDCCH
|
||||
return alloc_result::no_cch_space;
|
||||
}
|
||||
|
||||
int mcs = -1, tbs = -1;
|
||||
if (ue.h_ul->empty()) {
|
||||
mcs = 20;
|
||||
tbs = 100;
|
||||
bool ret = ue.h_ul->new_tx(ue.pusch_tti, ue.pusch_tti, ul_mask, mcs, tbs, ue.cfg->maxharq_tx);
|
||||
int mcs = 20;
|
||||
int tbs = 100;
|
||||
bool ret = ue.h_ul->new_tx(ue.pusch_tti, ue.pusch_tti, ul_mask, mcs, tbs, ue.cfg->ue_cfg()->maxharq_tx);
|
||||
srsran_assert(ret, "Failed to allocate UL HARQ");
|
||||
} else {
|
||||
srsran_assert(ue.h_ul->new_retx(ue.pusch_tti, ue.pusch_tti, ul_mask, &mcs, &tbs),
|
||||
"Failed to allocate UL HARQ retx");
|
||||
srsran_assert(ue.h_ul->new_retx(ue.pusch_tti, ue.pusch_tti, ul_mask), "Failed to allocate UL HARQ retx");
|
||||
}
|
||||
|
||||
// Allocation Successful
|
||||
pdcch_ul_t& pdcch = bwp_grid[ue.pdcch_tti].pdcch_ul_list.back();
|
||||
fill_dci_ue_cfg(ue, pdcch.dci);
|
||||
pusch_grants.emplace_back();
|
||||
pusch_grant& grant = pusch_grants.back();
|
||||
grant.dci.ctx.rnti = ue.rnti;
|
||||
grant.bitmap = ul_mask;
|
||||
pusch_mask |= ul_mask;
|
||||
// Generate PDCCH
|
||||
pdcch_ul_t& pdcch = pdcchs.back();
|
||||
fill_ul_dci_ue_fields(ue, *bwp_grid.cfg, ss_id, pdcch.dci.ctx.location, pdcch.dci);
|
||||
// Generate PUSCH
|
||||
bwp_pusch_slot.ul_prbs.add(ul_mask);
|
||||
|
||||
return alloc_result::success;
|
||||
}
|
||||
|
|
|
@ -25,57 +25,35 @@
|
|||
namespace srsenb {
|
||||
namespace sched_nr_impl {
|
||||
|
||||
ue_cfg_extended::ue_cfg_extended(uint16_t rnti_, const ue_cfg_t& uecfg) : ue_cfg_t(uecfg), rnti(rnti_)
|
||||
{
|
||||
cc_params.resize(carriers.size());
|
||||
for (uint32_t cc = 0; cc < cc_params.size(); ++cc) {
|
||||
cc_params[cc].bwps.resize(1);
|
||||
auto& bwp = cc_params[cc].bwps[0];
|
||||
for (uint32_t ssid = 0; ssid < SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE; ++ssid) {
|
||||
if (phy_cfg.pdcch.search_space_present[ssid]) {
|
||||
bwp.search_spaces.emplace_back();
|
||||
bwp.search_spaces.back().cfg = &phy_cfg.pdcch.search_space[ssid];
|
||||
}
|
||||
}
|
||||
for (uint32_t csid = 0; csid < SRSRAN_UE_DL_NR_MAX_NOF_CORESET; ++csid) {
|
||||
if (phy_cfg.pdcch.coreset_present[csid]) {
|
||||
bwp.coresets.emplace_back();
|
||||
auto& coreset = bwp.coresets.back();
|
||||
coreset.cfg = &phy_cfg.pdcch.coreset[csid];
|
||||
for (auto& ss : bwp.search_spaces) {
|
||||
if (ss.cfg->coreset_id == csid) {
|
||||
coreset.ss_list.push_back(&ss);
|
||||
get_dci_locs(*coreset.cfg, *coreset.ss_list.back()->cfg, rnti, coreset.cce_positions);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
slot_ue::slot_ue(resource_guard::token ue_token_, uint16_t rnti_, tti_point tti_rx_, uint32_t cc_) :
|
||||
ue_token(std::move(ue_token_)), rnti(rnti_), tti_rx(tti_rx_), cc(cc_)
|
||||
{}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ue_carrier::ue_carrier(uint16_t rnti_, uint32_t cc_, const ue_cfg_t& uecfg_) : rnti(rnti_), cc(cc_), cfg(&uecfg_) {}
|
||||
ue_carrier::ue_carrier(uint16_t rnti_, const ue_cfg_t& uecfg_, const sched_cell_params& cell_params_) :
|
||||
rnti(rnti_),
|
||||
cc(cell_params_.cc),
|
||||
bwp_cfg(rnti_, cell_params_.bwps[0], uecfg_),
|
||||
cell_params(cell_params_),
|
||||
harq_ent(cell_params_.nof_prb())
|
||||
{}
|
||||
|
||||
void ue_carrier::push_feedback(srsran::move_callback<void(ue_carrier&)> callback)
|
||||
{
|
||||
pending_feedback.push_back(std::move(callback));
|
||||
}
|
||||
|
||||
slot_ue ue_carrier::try_reserve(tti_point tti_rx, const ue_cfg_extended& uecfg_)
|
||||
slot_ue ue_carrier::try_reserve(tti_point tti_rx, const ue_cfg_t& uecfg_)
|
||||
{
|
||||
slot_ue sfu(busy, rnti, tti_rx, cc);
|
||||
if (sfu.empty()) {
|
||||
return sfu;
|
||||
}
|
||||
// successfully acquired. Process any CC-specific pending feedback
|
||||
cfg = &uecfg_;
|
||||
if (bwp_cfg.ue_cfg() != &uecfg_) {
|
||||
bwp_cfg = bwp_ue_cfg(rnti, cell_params.bwps[0], uecfg_);
|
||||
}
|
||||
while (not pending_feedback.empty()) {
|
||||
pending_feedback.front()(*this);
|
||||
pending_feedback.pop_front();
|
||||
|
@ -90,23 +68,35 @@ slot_ue ue_carrier::try_reserve(tti_point tti_rx, const ue_cfg_extended& uecfg_)
|
|||
}
|
||||
|
||||
// set UE parameters common to all carriers
|
||||
sfu.cfg = &uecfg_;
|
||||
sfu.cfg = &bwp_cfg;
|
||||
|
||||
// copy cc-specific parameters and find available HARQs
|
||||
sfu.cc_cfg = &uecfg_.carriers[cc];
|
||||
sfu.pdcch_tti = tti_rx + TX_ENB_DELAY;
|
||||
sfu.pdsch_tti = sfu.pdcch_tti + sfu.cc_cfg->pdsch_res_list[0].k0;
|
||||
sfu.pusch_tti = sfu.pdcch_tti + sfu.cc_cfg->pusch_res_list[0].k2;
|
||||
sfu.uci_tti = sfu.pdsch_tti + sfu.cc_cfg->pdsch_res_list[0].k1;
|
||||
sfu.cc_cfg = &uecfg_.carriers[cc];
|
||||
sfu.pdcch_tti = tti_rx + TX_ENB_DELAY;
|
||||
const uint32_t k0 = 0;
|
||||
sfu.pdsch_tti = sfu.pdcch_tti + k0;
|
||||
uint32_t k1 =
|
||||
sfu.cfg->phy().harq_ack.dl_data_to_ul_ack[sfu.pdsch_tti.sf_idx() % sfu.cfg->phy().harq_ack.nof_dl_data_to_ul_ack];
|
||||
sfu.uci_tti = sfu.pdsch_tti + k1;
|
||||
uint32_t k2 = k1;
|
||||
sfu.pusch_tti = sfu.pdcch_tti + k2;
|
||||
sfu.dl_cqi = dl_cqi;
|
||||
sfu.ul_cqi = ul_cqi;
|
||||
sfu.h_dl = harq_ent.find_pending_dl_retx();
|
||||
if (sfu.h_dl == nullptr) {
|
||||
sfu.h_dl = harq_ent.find_empty_dl_harq();
|
||||
|
||||
const srsran_tdd_config_nr_t& tdd_cfg = cell_params.cell_cfg.tdd;
|
||||
if (srsran_tdd_nr_is_dl(&tdd_cfg, 0, sfu.pdsch_tti.sf_idx())) {
|
||||
// If DL enabled
|
||||
sfu.h_dl = harq_ent.find_pending_dl_retx();
|
||||
if (sfu.h_dl == nullptr) {
|
||||
sfu.h_dl = harq_ent.find_empty_dl_harq();
|
||||
}
|
||||
}
|
||||
sfu.h_ul = harq_ent.find_pending_ul_retx();
|
||||
if (sfu.h_ul == nullptr) {
|
||||
sfu.h_ul = harq_ent.find_empty_ul_harq();
|
||||
if (srsran_tdd_nr_is_ul(&tdd_cfg, 0, sfu.pusch_tti.sf_idx())) {
|
||||
// If UL enabled
|
||||
sfu.h_ul = harq_ent.find_pending_ul_retx();
|
||||
if (sfu.h_ul == nullptr) {
|
||||
sfu.h_ul = harq_ent.find_empty_ul_harq();
|
||||
}
|
||||
}
|
||||
|
||||
if (sfu.h_dl == nullptr and sfu.h_ul == nullptr) {
|
||||
|
@ -119,12 +109,12 @@ slot_ue ue_carrier::try_reserve(tti_point tti_rx, const ue_cfg_extended& uecfg_)
|
|||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ue::ue(uint16_t rnti_, const ue_cfg_t& cfg) : rnti(rnti_)
|
||||
ue::ue(uint16_t rnti_, const ue_cfg_t& cfg, const sched_params& sched_cfg_) : rnti(rnti_), sched_cfg(sched_cfg_)
|
||||
{
|
||||
ue_cfgs[0] = ue_cfg_extended(rnti, cfg);
|
||||
ue_cfgs[0] = cfg;
|
||||
for (uint32_t cc = 0; cc < cfg.carriers.size(); ++cc) {
|
||||
if (cfg.carriers[cc].active) {
|
||||
carriers[cc].reset(new ue_carrier(rnti, cc, cfg));
|
||||
carriers[cc].reset(new ue_carrier(rnti, cfg, sched_cfg.cells[cc]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,10 +20,15 @@
|
|||
*/
|
||||
|
||||
#include "srsenb/hdr/stack/mac/nr/sched_nr_worker.h"
|
||||
#include "srsran/common/string_helpers.h"
|
||||
|
||||
namespace srsenb {
|
||||
namespace sched_nr_impl {
|
||||
|
||||
slot_cc_worker::slot_cc_worker(serv_cell_ctxt& cc_sched) :
|
||||
cell(cc_sched), cfg(*cc_sched.cfg), bwp_alloc(cc_sched.bwps[0].grid), logger(srslog::fetch_basic_logger("MAC"))
|
||||
{}
|
||||
|
||||
/// Called at the beginning of TTI in a locked context, to reserve available UE resources
|
||||
void slot_cc_worker::start(tti_point tti_rx_, ue_map_t& ue_db)
|
||||
{
|
||||
|
@ -43,22 +48,23 @@ void slot_cc_worker::start(tti_point tti_rx_, ue_map_t& ue_db)
|
|||
}
|
||||
// UE acquired successfully for scheduling in this {tti, cc}
|
||||
}
|
||||
|
||||
tti_rx = tti_rx_;
|
||||
}
|
||||
|
||||
void slot_cc_worker::run()
|
||||
{
|
||||
srsran_assert(running(), "scheduler worker::run() called for non-active worker");
|
||||
|
||||
// Prioritize PDCCH scheduling for DL and UL data in a RoundRobin fashion
|
||||
if ((tti_rx.to_uint() & 0x1u) == 0) {
|
||||
alloc_dl_ues();
|
||||
alloc_ul_ues();
|
||||
} else {
|
||||
alloc_ul_ues();
|
||||
alloc_dl_ues();
|
||||
}
|
||||
bwp_alloc.new_slot(tti_rx + TX_ENB_DELAY);
|
||||
|
||||
// Allocate pending RARs
|
||||
cell.bwps[0].ra.run_slot(bwp_alloc);
|
||||
|
||||
// TODO: Prioritize PDCCH scheduling for DL and UL data in a Round-Robin fashion
|
||||
alloc_dl_ues();
|
||||
alloc_ul_ues();
|
||||
|
||||
// Log CC scheduler result
|
||||
log_result();
|
||||
}
|
||||
|
||||
void slot_cc_worker::end_tti()
|
||||
|
@ -81,10 +87,11 @@ void slot_cc_worker::alloc_dl_ues()
|
|||
return;
|
||||
}
|
||||
|
||||
rbgmask_t dlmask(cfg.cell_cfg.nof_rbg);
|
||||
rbgmask_t dlmask(cfg.bwps[0].N_rbg);
|
||||
dlmask.fill(0, dlmask.size(), true);
|
||||
res_grid.alloc_pdsch(ue, dlmask);
|
||||
bwp_alloc.alloc_pdsch(ue, dlmask);
|
||||
}
|
||||
|
||||
void slot_cc_worker::alloc_ul_ues()
|
||||
{
|
||||
if (slot_ues.empty()) {
|
||||
|
@ -95,69 +102,99 @@ void slot_cc_worker::alloc_ul_ues()
|
|||
return;
|
||||
}
|
||||
|
||||
rbgmask_t ulmask(cfg.cell_cfg.nof_rbg);
|
||||
rbgmask_t ulmask(cfg.bwps[0].N_rbg);
|
||||
ulmask.fill(0, ulmask.size(), true);
|
||||
res_grid.alloc_pusch(ue, ulmask);
|
||||
bwp_alloc.alloc_pusch(ue, ulmask);
|
||||
}
|
||||
|
||||
void slot_cc_worker::log_result() const
|
||||
{
|
||||
const bwp_slot_grid& bwp_slot = cell.bwps[0].grid[tti_rx + TX_ENB_DELAY];
|
||||
for (const pdcch_dl_t& pdcch : bwp_slot.dl_pdcchs) {
|
||||
fmt::memory_buffer fmtbuf;
|
||||
if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_c) {
|
||||
const slot_ue& ue = slot_ues[pdcch.dci.ctx.rnti];
|
||||
fmt::format_to(fmtbuf,
|
||||
"SCHED: DL {}, cc={}, rnti=0x{:x}, pid={}, nrtx={}, dai={}, tti_pdsch={}, tti_ack={}",
|
||||
ue.h_dl->nof_retx() == 0 ? "tx" : "retx",
|
||||
cell.cfg->cc,
|
||||
ue.rnti,
|
||||
ue.h_dl->pid,
|
||||
ue.h_dl->nof_retx(),
|
||||
pdcch.dci.dai,
|
||||
ue.pdsch_tti,
|
||||
ue.uci_tti);
|
||||
} else if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_ra) {
|
||||
fmt::format_to(fmtbuf, "SCHED: DL RAR, cc={}", cell.cfg->cc);
|
||||
} else {
|
||||
fmt::format_to(fmtbuf, "SCHED: unknown format");
|
||||
}
|
||||
|
||||
logger.info("%s", srsran::to_c_str(fmtbuf));
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
sched_worker_manager::sched_worker_manager(ue_map_t& ue_db_, const sched_params& cfg_) : cfg(cfg_), ue_db(ue_db_)
|
||||
sched_worker_manager::sched_worker_manager(ue_map_t& ue_db_, const sched_params& cfg_) :
|
||||
cfg(cfg_), ue_db(ue_db_), logger(srslog::fetch_basic_logger("MAC"))
|
||||
{
|
||||
for (uint32_t cc = 0; cc < cfg.cells.size(); ++cc) {
|
||||
cell_grid_list.emplace_back(cfg.cells[cc]);
|
||||
}
|
||||
|
||||
// Note: For now, we only allow parallelism at the sector level
|
||||
slot_ctxts.resize(cfg.sched_cfg.nof_concurrent_subframes);
|
||||
slot_worker_ctxts.resize(cfg.sched_cfg.nof_concurrent_subframes);
|
||||
for (size_t i = 0; i < cfg.sched_cfg.nof_concurrent_subframes; ++i) {
|
||||
slot_ctxts[i].reset(new slot_worker_ctxt());
|
||||
sem_init(&slot_ctxts[i]->sf_sem, 0, 1);
|
||||
slot_ctxts[i]->workers.reserve(cfg.cells.size());
|
||||
slot_worker_ctxts[i].reset(new slot_worker_ctxt());
|
||||
slot_worker_ctxts[i]->workers.reserve(cfg.cells.size());
|
||||
for (uint32_t cc = 0; cc < cfg.cells.size(); ++cc) {
|
||||
slot_ctxts[i]->workers.emplace_back(cfg.cells[cc], cell_grid_list[cc]);
|
||||
slot_worker_ctxts[i]->workers.emplace_back(cell_grid_list[cc]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sched_worker_manager::~sched_worker_manager()
|
||||
{
|
||||
// acquire all slot worker contexts
|
||||
for (auto& slot_ctxt : slot_ctxts) {
|
||||
sem_wait(&slot_ctxt->sf_sem);
|
||||
}
|
||||
// destroy all slot worker contexts
|
||||
for (auto& slot_ctxt : slot_ctxts) {
|
||||
sem_destroy(&slot_ctxt->sf_sem);
|
||||
}
|
||||
}
|
||||
sched_worker_manager::~sched_worker_manager() = default;
|
||||
|
||||
sched_worker_manager::slot_worker_ctxt& sched_worker_manager::get_sf(tti_point tti_rx)
|
||||
{
|
||||
return *slot_ctxts[tti_rx.to_uint() % slot_ctxts.size()];
|
||||
return *slot_worker_ctxts[tti_rx.to_uint() % slot_worker_ctxts.size()];
|
||||
}
|
||||
|
||||
void sched_worker_manager::reserve_workers(tti_point tti_rx_)
|
||||
void sched_worker_manager::start_slot(tti_point tti_rx, srsran::move_callback<void()> process_feedback)
|
||||
{
|
||||
// lock if slot worker is already being used
|
||||
auto& sf_worker_ctxt = get_sf(tti_rx_);
|
||||
sem_wait(&sf_worker_ctxt.sf_sem);
|
||||
auto& sf_worker_ctxt = get_sf(tti_rx);
|
||||
|
||||
sf_worker_ctxt.tti_rx = tti_rx_;
|
||||
std::unique_lock<std::mutex> lock(sf_worker_ctxt.slot_mutex);
|
||||
while ((sf_worker_ctxt.tti_rx.is_valid() and sf_worker_ctxt.tti_rx != tti_rx)) {
|
||||
// wait for previous slot to finish
|
||||
sf_worker_ctxt.nof_workers_waiting++;
|
||||
sf_worker_ctxt.cvar.wait(lock);
|
||||
sf_worker_ctxt.nof_workers_waiting--;
|
||||
}
|
||||
if (sf_worker_ctxt.tti_rx == tti_rx) {
|
||||
// another worker with the same slot idx already started
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> db_lock(ue_db_mutex);
|
||||
|
||||
process_feedback();
|
||||
|
||||
for (uint32_t cc = 0; cc < sf_worker_ctxt.workers.size(); ++cc) {
|
||||
sf_worker_ctxt.workers[cc].start(tti_rx, ue_db);
|
||||
}
|
||||
}
|
||||
|
||||
sf_worker_ctxt.tti_rx = tti_rx;
|
||||
sf_worker_ctxt.worker_count.store(static_cast<int>(sf_worker_ctxt.workers.size()), std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void sched_worker_manager::start_tti(tti_point tti_rx_)
|
||||
{
|
||||
auto& sf_worker_ctxt = get_sf(tti_rx_);
|
||||
srsran_assert(sf_worker_ctxt.tti_rx == tti_rx_, "invalid run_tti(tti, cc) arguments");
|
||||
|
||||
for (uint32_t cc = 0; cc < sf_worker_ctxt.workers.size(); ++cc) {
|
||||
sf_worker_ctxt.workers[cc].start(sf_worker_ctxt.tti_rx, ue_db);
|
||||
if (sf_worker_ctxt.nof_workers_waiting > 0) {
|
||||
sf_worker_ctxt.cvar.notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
bool sched_worker_manager::run_tti(tti_point tti_rx_, uint32_t cc, slot_res_t& tti_req)
|
||||
bool sched_worker_manager::run_slot(tti_point tti_rx_, uint32_t cc)
|
||||
{
|
||||
auto& sf_worker_ctxt = get_sf(tti_rx_);
|
||||
srsran_assert(sf_worker_ctxt.tti_rx == tti_rx_, "invalid run_tti(tti, cc) arguments");
|
||||
|
@ -165,15 +202,6 @@ bool sched_worker_manager::run_tti(tti_point tti_rx_, uint32_t cc, slot_res_t& t
|
|||
// Get {tti, cc} scheduling decision
|
||||
sf_worker_ctxt.workers[cc].run();
|
||||
|
||||
// Copy requested TTI DL and UL sched result
|
||||
tti_req.dl_res.pdsch_tti = tti_rx_ + TX_ENB_DELAY;
|
||||
tti_req.dl_res.pdcchs = cell_grid_list[cc].bwps[0][tti_req.dl_res.pdsch_tti].pdcch_dl_list;
|
||||
tti_req.dl_res.pdschs = cell_grid_list[cc].bwps[0][tti_req.dl_res.pdsch_tti].pdsch_grants;
|
||||
cell_grid_list[cc].bwps[0][tti_req.dl_res.pdsch_tti].reset();
|
||||
tti_req.ul_res.pusch_tti = tti_rx_ + TX_ENB_DELAY;
|
||||
tti_req.ul_res.pusch = cell_grid_list[cc].bwps[0][tti_req.ul_res.pusch_tti].pusch_grants;
|
||||
cell_grid_list[cc].bwps[0][tti_req.ul_res.pusch_tti].reset();
|
||||
|
||||
// decrement the number of active workers
|
||||
int rem_workers = sf_worker_ctxt.worker_count.fetch_sub(1, std::memory_order_release) - 1;
|
||||
srsran_assert(rem_workers >= 0, "invalid number of calls to run_tti(tti, cc)");
|
||||
|
@ -181,18 +209,76 @@ bool sched_worker_manager::run_tti(tti_point tti_rx_, uint32_t cc, slot_res_t& t
|
|||
return rem_workers == 0;
|
||||
}
|
||||
|
||||
void sched_worker_manager::end_tti(tti_point tti_rx_)
|
||||
void sched_worker_manager::release_slot(tti_point tti_rx_)
|
||||
{
|
||||
auto& sf_worker_ctxt = get_sf(tti_rx_);
|
||||
srsran_assert(sf_worker_ctxt.tti_rx == tti_rx_, "invalid run_tti(tti, cc) arguments");
|
||||
srsran_assert(sf_worker_ctxt.worker_count == 0, "invalid number of calls to run_tti(tti, cc)");
|
||||
|
||||
// All the workers of the same TTI have finished. Synchronize scheduling decisions with UEs state
|
||||
for (slot_cc_worker& worker : sf_worker_ctxt.workers) {
|
||||
worker.end_tti();
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(ue_db_mutex);
|
||||
|
||||
// All the workers of the same slot have finished. Synchronize scheduling decisions with UEs state
|
||||
for (slot_cc_worker& worker : sf_worker_ctxt.workers) {
|
||||
worker.end_tti();
|
||||
}
|
||||
}
|
||||
|
||||
sem_post(&sf_worker_ctxt.sf_sem);
|
||||
std::unique_lock<std::mutex> lock(sf_worker_ctxt.slot_mutex);
|
||||
sf_worker_ctxt.tti_rx = {};
|
||||
if (sf_worker_ctxt.nof_workers_waiting > 0) {
|
||||
lock.unlock();
|
||||
sf_worker_ctxt.cvar.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
bool sched_worker_manager::save_sched_result(tti_point pdcch_tti, uint32_t cc, dl_sched_t& dl_res, ul_sched_t& ul_res)
|
||||
{
|
||||
auto& bwp_slot = cell_grid_list[cc].bwps[0].grid[pdcch_tti];
|
||||
|
||||
dl_res.pdcch_dl = bwp_slot.dl_pdcchs;
|
||||
dl_res.pdcch_ul = bwp_slot.ul_pdcchs;
|
||||
dl_res.pdsch = bwp_slot.pdschs;
|
||||
ul_res.pusch = bwp_slot.puschs;
|
||||
|
||||
// Group pending HARQ ACKs
|
||||
srsran_pdsch_ack_nr_t ack = {};
|
||||
ack.nof_cc = not bwp_slot.pending_acks.empty();
|
||||
const srsran::phy_cfg_nr_t* phy_cfg = nullptr;
|
||||
for (const harq_ack_t& pending_ack : bwp_slot.pending_acks) {
|
||||
srsran_harq_ack_m_t ack_m = {};
|
||||
ack_m.resource = pending_ack.res;
|
||||
ack_m.present = true;
|
||||
srsran_harq_ack_insert_m(&ack, &ack_m);
|
||||
phy_cfg = pending_ack.phy_cfg;
|
||||
}
|
||||
|
||||
if (phy_cfg != nullptr) {
|
||||
srsran_slot_cfg_t slot_cfg{};
|
||||
slot_cfg.idx = pdcch_tti.sf_idx();
|
||||
srsran_uci_cfg_nr_t uci_cfg = {};
|
||||
srsran_assert(phy_cfg->get_uci_cfg(slot_cfg, ack, uci_cfg), "Error getting UCI CFG");
|
||||
|
||||
if (uci_cfg.ack.count > 0 || uci_cfg.nof_csi > 0 || uci_cfg.o_sr > 0) {
|
||||
if (not ul_res.pusch.empty()) {
|
||||
// Put UCI configuration in PUSCH config
|
||||
srsran_assert(phy_cfg->get_pusch_uci_cfg(slot_cfg, uci_cfg, ul_res.pusch[0].sch),
|
||||
"Error setting UCI configuration in PUSCH");
|
||||
} else {
|
||||
// Put UCI configuration in PUCCH config
|
||||
ul_res.pucch.emplace_back();
|
||||
pucch_t& pucch = ul_res.pucch.back();
|
||||
pucch.uci_cfg = uci_cfg;
|
||||
srsran_assert(phy_cfg->get_pucch_uci_cfg(slot_cfg, pucch.uci_cfg, pucch.pucch_cfg, pucch.resource),
|
||||
"Error getting PUCCH UCI cfg");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// clear up BWP slot
|
||||
bwp_slot.reset();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace sched_nr_impl
|
||||
|
|
|
@ -288,6 +288,7 @@ uint32_t sched_ue_cell::get_aggr_level(uint32_t nof_bits) const
|
|||
} else {
|
||||
dl_cqi = dl_cqi_ctxt.get_avg_cqi();
|
||||
}
|
||||
dl_cqi = std::max(cell_cfg->sched_cfg->pdcch_cqi_offset + (int)dl_cqi, 0);
|
||||
return srsenb::get_aggr_level(nof_bits,
|
||||
dl_cqi,
|
||||
cell_cfg->sched_cfg->min_aggr_level,
|
||||
|
|
|
@ -80,6 +80,7 @@ cc_used_buffers_map::~cc_used_buffers_map()
|
|||
|
||||
srsran::unique_byte_buffer_t cc_used_buffers_map::release_pdu(tti_point tti)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
if (not has_tti(tti)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -94,6 +95,7 @@ srsran::unique_byte_buffer_t cc_used_buffers_map::release_pdu(tti_point tti)
|
|||
|
||||
uint8_t* cc_used_buffers_map::request_pdu(tti_point tti, uint32_t len)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
if (not pdu_map.has_space(tti.to_uint())) {
|
||||
logger->error("UE buffers: could not allocate buffer for tti=%d", tti.to_uint());
|
||||
return nullptr;
|
||||
|
@ -114,6 +116,7 @@ uint8_t* cc_used_buffers_map::request_pdu(tti_point tti, uint32_t len)
|
|||
|
||||
void cc_used_buffers_map::clear_old_pdus(tti_point current_tti)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
static const uint32_t old_tti_threshold = SRSRAN_FDD_NOF_HARQ + 4;
|
||||
|
||||
tti_point max_tti{current_tti - old_tti_threshold};
|
||||
|
@ -262,13 +265,11 @@ srsran_softbuffer_tx_t* ue::get_tx_softbuffer(uint32_t enb_cc_idx, uint32_t harq
|
|||
uint8_t* ue::request_buffer(uint32_t tti, uint32_t enb_cc_idx, uint32_t len)
|
||||
{
|
||||
srsran_assert(len > 0, "UE buffers: Requesting buffer for zero bytes");
|
||||
std::unique_lock<std::mutex> lock(rx_buffers_mutex);
|
||||
return cc_buffers[enb_cc_idx].get_rx_used_buffers().request_pdu(tti_point(tti), len);
|
||||
}
|
||||
|
||||
void ue::clear_old_buffers(uint32_t tti)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(rx_buffers_mutex);
|
||||
// remove old buffers
|
||||
for (auto& cc : cc_buffers) {
|
||||
cc.get_rx_used_buffers().clear_old_pdus(tti_point{tti});
|
||||
|
@ -398,7 +399,6 @@ void ue::process_pdu(srsran::unique_byte_buffer_t pdu, uint32_t ue_cc_idx, uint3
|
|||
|
||||
srsran::unique_byte_buffer_t ue::release_pdu(uint32_t tti, uint32_t enb_cc_idx)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(rx_buffers_mutex);
|
||||
return cc_buffers[enb_cc_idx].get_rx_used_buffers().release_pdu(tti_point(tti));
|
||||
}
|
||||
|
||||
|
|
|
@ -112,6 +112,14 @@ int32_t rrc::init(const rrc_cfg_t& cfg_,
|
|||
|
||||
running = true;
|
||||
|
||||
if (logger.debug.enabled()) {
|
||||
asn1::json_writer js{};
|
||||
cfg.srb1_cfg.rlc_cfg.to_json(js);
|
||||
logger.debug("SRB1 configuration: %s", js.to_string().c_str());
|
||||
js = {};
|
||||
cfg.srb2_cfg.rlc_cfg.to_json(js);
|
||||
logger.debug("SRB2 configuration: %s", js.to_string().c_str());
|
||||
}
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -56,18 +56,18 @@ bool rrc::ue::rrc_endc::fill_conn_recfg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn
|
|||
meas_cfg_s& meas_cfg = conn_recfg->meas_cfg;
|
||||
|
||||
meas_cfg.meas_obj_to_add_mod_list_present = true;
|
||||
meas_cfg.meas_obj_to_add_mod_list.resize(2);
|
||||
|
||||
auto& meas_obj = meas_cfg.meas_obj_to_add_mod_list[0];
|
||||
meas_obj.meas_obj_id = 1;
|
||||
meas_obj_to_add_mod_s meas_obj = {};
|
||||
meas_obj.meas_obj_id = meas_cfg.meas_obj_to_add_mod_list.size() + 1;
|
||||
meas_obj.meas_obj.set_meas_obj_eutra();
|
||||
meas_obj.meas_obj.meas_obj_eutra().carrier_freq = 300;
|
||||
meas_obj.meas_obj.meas_obj_eutra().allowed_meas_bw = allowed_meas_bw_opts::mbw50;
|
||||
meas_obj.meas_obj.meas_obj_eutra().presence_ant_port1 = false;
|
||||
meas_obj.meas_obj.meas_obj_eutra().neigh_cell_cfg.from_number(0b01);
|
||||
meas_cfg.meas_obj_to_add_mod_list.push_back(meas_obj);
|
||||
|
||||
auto& meas_obj2 = meas_cfg.meas_obj_to_add_mod_list[1];
|
||||
meas_obj2.meas_obj_id = 2;
|
||||
meas_obj_to_add_mod_s meas_obj2 = {};
|
||||
meas_obj2.meas_obj_id = meas_cfg.meas_obj_to_add_mod_list.size() + 1;
|
||||
meas_obj2.meas_obj.set_meas_obj_nr_r15();
|
||||
meas_obj2.meas_obj.meas_obj_nr_r15().carrier_freq_r15 = 634176;
|
||||
meas_obj2.meas_obj.meas_obj_nr_r15().rs_cfg_ssb_r15.meas_timing_cfg_r15.periodicity_and_offset_r15.set_sf20_r15();
|
||||
|
@ -78,13 +78,13 @@ bool rrc::ue::rrc_endc::fill_conn_recfg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn
|
|||
meas_obj2.meas_obj.meas_obj_nr_r15().ext = true;
|
||||
meas_obj2.meas_obj.meas_obj_nr_r15().band_nr_r15.set_present(true);
|
||||
meas_obj2.meas_obj.meas_obj_nr_r15().band_nr_r15.get()->set_setup() = 78;
|
||||
meas_cfg.meas_obj_to_add_mod_list.push_back(meas_obj2);
|
||||
|
||||
// report config
|
||||
meas_cfg.report_cfg_to_add_mod_list_present = true;
|
||||
meas_cfg.report_cfg_to_add_mod_list.resize(1);
|
||||
auto& report_cfg = meas_cfg.report_cfg_to_add_mod_list[0];
|
||||
report_cfg_to_add_mod_s report_cfg = {};
|
||||
|
||||
report_cfg.report_cfg_id = 1;
|
||||
report_cfg.report_cfg_id = meas_cfg.report_cfg_to_add_mod_list.size() + 1;
|
||||
report_cfg.report_cfg.set_report_cfg_inter_rat();
|
||||
report_cfg.report_cfg.report_cfg_inter_rat().trigger_type.set_event();
|
||||
report_cfg.report_cfg.report_cfg_inter_rat().trigger_type.event().event_id.set_event_b1_nr_r15();
|
||||
|
@ -109,14 +109,15 @@ bool rrc::ue::rrc_endc::fill_conn_recfg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn
|
|||
report_cfg.report_cfg.report_cfg_inter_rat().report_quant_cell_nr_r15.get()->ss_rsrp = true;
|
||||
report_cfg.report_cfg.report_cfg_inter_rat().report_quant_cell_nr_r15.get()->ss_rsrq = true;
|
||||
report_cfg.report_cfg.report_cfg_inter_rat().report_quant_cell_nr_r15.get()->ss_sinr = true;
|
||||
meas_cfg.report_cfg_to_add_mod_list.push_back(report_cfg);
|
||||
|
||||
// measIdToAddModList
|
||||
meas_cfg.meas_id_to_add_mod_list_present = true;
|
||||
meas_cfg.meas_id_to_add_mod_list.resize(1);
|
||||
auto& meas_id = meas_cfg.meas_id_to_add_mod_list[0];
|
||||
meas_id.meas_id = 1;
|
||||
meas_id.meas_obj_id = 2;
|
||||
meas_id.report_cfg_id = 1;
|
||||
meas_id_to_add_mod_s meas_id = {};
|
||||
meas_id.meas_id = meas_obj.meas_obj_id;
|
||||
meas_id.meas_obj_id = meas_obj2.meas_obj_id;
|
||||
meas_id.report_cfg_id = report_cfg.report_cfg_id;
|
||||
meas_cfg.meas_id_to_add_mod_list.push_back(meas_id);
|
||||
|
||||
// quantityConfig
|
||||
meas_cfg.quant_cfg_present = true;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "srsenb/hdr/stack/rrc/ue_rr_cfg.h"
|
||||
#include "srsran/asn1/rrc_utils.h"
|
||||
#include "srsran/common/enb_events.h"
|
||||
#include "srsran/common/srsran_assert.h"
|
||||
#include "srsran/common/standard_streams.h"
|
||||
#include "srsran/interfaces/enb_pdcp_interfaces.h"
|
||||
#include "srsran/interfaces/enb_rlc_interfaces.h"
|
||||
|
@ -1420,8 +1421,30 @@ void rrc::ue::apply_pdcp_drb_updates(const rr_cfg_ded_s& pending_rr_cfg)
|
|||
void rrc::ue::apply_rlc_rb_updates(const rr_cfg_ded_s& pending_rr_cfg)
|
||||
{
|
||||
for (const srb_to_add_mod_s& srb : pending_rr_cfg.srb_to_add_mod_list) {
|
||||
parent->rlc->add_bearer(rnti, srb.srb_id, srsran::rlc_config_t::srb_config(srb.srb_id));
|
||||
srb_cfg_t* srb_cfg;
|
||||
if (srb.srb_id == 1) {
|
||||
srb_cfg = &parent->cfg.srb1_cfg;
|
||||
} else if (srb.srb_id == 2) {
|
||||
srb_cfg = &parent->cfg.srb2_cfg;
|
||||
} else {
|
||||
srsran_terminate("Invalid LTE SRB id=%d", srb.srb_id);
|
||||
}
|
||||
|
||||
if (srb_cfg->rlc_cfg.type() == srb_to_add_mod_s::rlc_cfg_c_::types_opts::explicit_value) {
|
||||
srsran::rlc_config_t rlc_cfg = srsran::make_rlc_config_t(srb_cfg->rlc_cfg.explicit_value());
|
||||
if (rlc_cfg.rlc_mode == srsran::rlc_mode_t::am and srb_cfg->enb_dl_max_retx_thres > 0) {
|
||||
rlc_cfg.am.max_retx_thresh = srb_cfg->enb_dl_max_retx_thres;
|
||||
}
|
||||
parent->rlc->add_bearer(rnti, srb.srb_id, rlc_cfg);
|
||||
} else {
|
||||
srsran::rlc_config_t rlc_cfg = srsran::rlc_config_t::srb_config(srb.srb_id);
|
||||
if (rlc_cfg.rlc_mode == srsran::rlc_mode_t::am and srb_cfg->enb_dl_max_retx_thres > 0) {
|
||||
rlc_cfg.am.max_retx_thresh = srb_cfg->enb_dl_max_retx_thres;
|
||||
}
|
||||
parent->rlc->add_bearer(rnti, srb.srb_id, rlc_cfg);
|
||||
}
|
||||
}
|
||||
|
||||
if (pending_rr_cfg.drb_to_release_list.size() > 0) {
|
||||
for (uint8_t drb_id : pending_rr_cfg.drb_to_release_list) {
|
||||
parent->rlc->del_bearer(rnti, drb_to_lcid((lte_drb)drb_id));
|
||||
|
@ -1431,7 +1454,13 @@ void rrc::ue::apply_rlc_rb_updates(const rr_cfg_ded_s& pending_rr_cfg)
|
|||
if (not drb.rlc_cfg_present) {
|
||||
parent->logger.warning("Default RLC DRB config not supported");
|
||||
}
|
||||
parent->rlc->add_bearer(rnti, drb.lc_ch_id, srsran::make_rlc_config_t(drb.rlc_cfg));
|
||||
srsran::rlc_config_t rlc_cfg = srsran::make_rlc_config_t(drb.rlc_cfg);
|
||||
const bearer_cfg_handler::erab_t& erab = bearer_list.get_erabs().at(drb.eps_bearer_id);
|
||||
if (rlc_cfg.rlc_mode == srsran::rlc_mode_t::am and
|
||||
parent->cfg.qci_cfg.at(erab.qos_params.qci).enb_dl_max_retx_thres > 0) {
|
||||
rlc_cfg.am.max_retx_thresh = parent->cfg.qci_cfg.at(erab.qos_params.qci).enb_dl_max_retx_thres;
|
||||
}
|
||||
parent->rlc->add_bearer(rnti, drb.lc_ch_id, rlc_cfg);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue