diff --git a/lib/include/srsran/interfaces/gnb_ngap_interfaces.h b/lib/include/srsran/interfaces/gnb_ngap_interfaces.h index b8a5d649d..859884c3a 100644 --- a/lib/include/srsran/interfaces/gnb_ngap_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_ngap_interfaces.h @@ -26,17 +26,25 @@ namespace srsenb { +const static int SRSRAN_NUM_SLICE = 3; +struct nssai_t { + bool active = false; + uint64_t sst; + uint64_t sd; +}; + struct ngap_args_t { - uint32_t gnb_id = 0; // 20-bit id (lsb bits) - uint8_t cell_id = 0; // 8-bit cell id - uint16_t tac = 0; // 16-bit tac - uint16_t mcc = 0; // BCD-coded with 0xF filler - uint16_t mnc = 0; // BCD-coded with 0xF filler - std::string amf_addr = ""; - std::string gtp_bind_addr = ""; - std::string gtp_advertise_addr = ""; - std::string ngc_bind_addr = ""; - std::string gnb_name = ""; + uint32_t gnb_id = 0; // 20-bit id (lsb bits) + uint8_t cell_id = 0; // 8-bit cell id + uint16_t tac = 0; // 16-bit tac + uint16_t mcc = 0; // BCD-coded with 0xF filler + uint16_t mnc = 0; // BCD-coded with 0xF filler + std::array nssai = {{{true, 1, 0}, {false, 2, 0}, {false, 3, 0}}}; + std::string amf_addr = ""; + std::string gtp_bind_addr = ""; + std::string gtp_advertise_addr = ""; + std::string ngc_bind_addr = ""; + std::string gnb_name = ""; }; // NGAP interface for RRC diff --git a/srsenb/enb.conf.example b/srsenb/enb.conf.example index 5e8eb88a2..ba5abc8fa 100644 --- a/srsenb/enb.conf.example +++ b/srsenb/enb.conf.example @@ -217,9 +217,26 @@ enable = false #init_dl_cqi=5 #max_sib_coderate=0.3 #pdcch_cqi_offset=0 -nr_pdsch_mcs=28 +#nr_pdsch_mcs=28 #nr_pusch_mcs=28 +##################################################################### +# Slicing configuration +# enable_eMBB Enables enhanced mobile broadband (eMBB) slice in the gNodeB +# enable_URLLC Enables Ultra Reliable Low Latency Communications (URLLC) slice in the gNodeB +# enable_MIoT Enables Massive Internet of Things (MIoT) slice in the gNodeB +# eMBB_sd eMBB slice differentiator +# URLLC_sd URLLC slice differentiator +# MIoT_sd MIoT slice differentiator +##################################################################### +[slicing] +#enable_eMBB = false +#enable_URLLC = false +#enable_MIoT = false +#eMBB_sd = 1 +#URLLC_sd = 1 +#MIoT_sd = 1 + ##################################################################### # eMBMS configuration options # diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index 336ee2b65..ed7ac215c 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -181,7 +181,13 @@ void parse_args(all_args_t* args, int argc, char* argv[]) ("scheduler.max_sib_coderate", bpo::value(&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(&args->stack.mac.sched.pdcch_cqi_offset)->default_value(0), "CQI offset in derivation of PDCCH aggregation level") - + /*Slicing conifguration*/ + ("slicing.enable_eMBB", bpo::value(&args->nr_stack.ngap.nssai[0].active)->default_value(true), "Enables enhanced mobile broadband (eMBB) slice in the gNodeB") + ("slicing.enable_URLLC", bpo::value(&args->nr_stack.ngap.nssai[1].active)->default_value(false), "Enables Ultra Reliable Low Latency Communications (URLLC) slice in the gNodeB") + ("slicing.enable_MIoT", bpo::value(&args->nr_stack.ngap.nssai[2].active)->default_value(false), "Enables Massive Internet of Things (MIoT) slice in the gNodeB") + ("slicing.eMBB_sd", bpo::value(&args->nr_stack.ngap.nssai[0].sd)->default_value(0), " eMBB slice differentiator") + ("slicing.URLLC_sd", bpo::value(&args->nr_stack.ngap.nssai[1].sd)->default_value(0), " URLLC slice differentiator") + ("slicing.MIoT_sd", bpo::value(&args->nr_stack.ngap.nssai[2].sd)->default_value(0), " slice differentiator") /* Downlink Channel emulator section */ ("channel.dl.enable", bpo::value(&args->phy.dl_channel_args.enable)->default_value(false), "Enable/Disable internal Downlink channel emulator") diff --git a/srsgnb/hdr/stack/ngap/ngap.h b/srsgnb/hdr/stack/ngap/ngap.h index 8f74c51bb..f293e63a7 100644 --- a/srsgnb/hdr/stack/ngap/ngap.h +++ b/srsgnb/hdr/stack/ngap/ngap.h @@ -118,6 +118,7 @@ private: uint32_t next_gnb_ue_ngap_id = 1; // Next GNB-side UE identifier uint16_t next_ue_stream_id = 1; // Next UE SCTP stream identifier srsran::unique_timer amf_connect_timer, ngsetup_timeout; + std::vector nssai_allowed_list; // Protocol IEs sent with every UL NGAP message asn1::ngap::tai_s tai; diff --git a/srsgnb/src/stack/ngap/ngap.cc b/srsgnb/src/stack/ngap/ngap.cc index 881e8ada2..3d5000eed 100644 --- a/srsgnb/src/stack/ngap/ngap.cc +++ b/srsgnb/src/stack/ngap/ngap.cc @@ -480,6 +480,21 @@ bool ngap::handle_ng_setup_response(const asn1::ngap::ng_setup_resp_s& msg) amf_connected = true; ng_setup_proc_t::ngsetupresult res; res.success = true; + for (size_t i = 0; i < ngsetupresponse->plmn_support_list->size(); i++) { + plmn_support_item_s& plmn_support_item = ngsetupresponse->plmn_support_list.value[i]; + for (size_t j = 0; j < plmn_support_item.slice_support_list.size(); j++) { + slice_support_item_s slice_item = plmn_support_item.slice_support_list[j]; + for (int k = 0; k < SRSRAN_NUM_SLICE; k++) { + if (args.nssai[k].active) { + if (args.nssai[k].sst == slice_item.s_nssai.sst.to_number()) { + if (args.nssai[k].sd == slice_item.s_nssai.sd.to_number()) { + nssai_allowed_list.push_back(args.nssai[k]); + } + } + } + } + } + } logger.info("AMF name: %s", ngsetupresponse->amf_name.value.to_string()); ngsetup_proc.trigger(res); @@ -718,9 +733,17 @@ bool ngap::setup_ng() container->supported_ta_list.value[0].tac = tai.tac; container->supported_ta_list.value[0].broadcast_plmn_list.resize(1); container->supported_ta_list.value[0].broadcast_plmn_list[0].plmn_id = tai.plmn_id; - container->supported_ta_list.value[0].broadcast_plmn_list[0].tai_slice_support_list.resize(1); - container->supported_ta_list.value[0].broadcast_plmn_list[0].tai_slice_support_list[0].s_nssai.sst.from_number(1); - + for (const auto& slice : args.nssai) { + if (slice.active) { + slice_support_item_s slice_item; + slice_item.s_nssai.sst.from_number(slice.sst); + if (slice.sd != 0) { + slice_item.s_nssai.sd_present = true; + slice_item.s_nssai.sd.from_number(slice.sd); + } + container->supported_ta_list.value[0].broadcast_plmn_list[0].tai_slice_support_list.push_back(slice_item); + } + } container->default_paging_drx.value.value = asn1::ngap::paging_drx_opts::v256; // Todo: add to args, config file return sctp_send_ngap_pdu(pdu, 0, "ngSetupRequest"); diff --git a/srsue/hdr/stack/upper/nas_5g.h b/srsue/hdr/stack/upper/nas_5g.h index 122ab15e2..efdd935cd 100644 --- a/srsue/hdr/stack/upper/nas_5g.h +++ b/srsue/hdr/stack/upper/nas_5g.h @@ -159,6 +159,7 @@ private: void fill_security_caps(srsran::nas_5g::ue_security_capability_t& sec_caps); int apply_security_config(srsran::unique_byte_buffer_t& pdu, uint8_t sec_hdr_type); bool check_replayed_ue_security_capabilities(srsran::nas_5g::ue_security_capability_t& caps); + void set_nssai(srsran::nas_5g::s_nssai_t& s_nssai); // message handler int handle_registration_accept(srsran::nas_5g::registration_accept_t& registration_accept); diff --git a/srsue/hdr/stack/upper/nas_config.h b/srsue/hdr/stack/upper/nas_config.h index 0d7184e2f..3fa80dae8 100644 --- a/srsue/hdr/stack/upper/nas_config.h +++ b/srsue/hdr/stack/upper/nas_config.h @@ -67,6 +67,10 @@ public: std::string ia5g; std::string ea5g; std::vector pdu_session_cfgs; + // slicing configuration + bool enable_slicing; + int nssai_sst; + int nssai_sd; }; } // namespace srsue diff --git a/srsue/src/main.cc b/srsue/src/main.cc index ac51d2d98..286dada33 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -161,6 +161,10 @@ static int parse_args(all_args_t* args, int argc, char* argv[]) ("nas.eia", bpo::value(&args->stack.nas.eia)->default_value("1,2,3"), "List of integrity algorithms included in UE capabilities") ("nas.eea", bpo::value(&args->stack.nas.eea)->default_value("0,1,2,3"), "List of ciphering algorithms included in UE capabilities") + ("slicing.enable", bpo::value(&args->stack.nas_5g.enable_slicing)->default_value(false), "enable slicing in the UE") + ("slicing.nssai-sst", bpo::value(&args->stack.nas_5g.nssai_sst)->default_value(1), "sst of requested slice") + ("slicing.nssai-sd", bpo::value(&args->stack.nas_5g.nssai_sd)->default_value(1), "sd of requested slice") + ("pcap.enable", bpo::value(&args->stack.pkt_trace.enable)->default_value("none"), "Enable (MAC, MAC_NR, NAS) packet captures for wireshark") ("pcap.mac_filename", bpo::value(&args->stack.pkt_trace.mac_pcap.filename)->default_value("/tmp/ue_mac.pcap"), "MAC layer capture filename") ("pcap.mac_nr_filename", bpo::value(&args->stack.pkt_trace.mac_nr_pcap.filename)->default_value("/tmp/ue_mac_nr.pcap"), "MAC_NR layer capture filename") diff --git a/srsue/src/stack/upper/nas_5g.cc b/srsue/src/stack/upper/nas_5g.cc index 1f8ac1ec1..2a72b17ed 100644 --- a/srsue/src/stack/upper/nas_5g.cc +++ b/srsue/src/stack/upper/nas_5g.cc @@ -278,6 +278,12 @@ int nas_5g::send_registration_request() reg_req.ue_security_capability_present = true; fill_security_caps(reg_req.ue_security_capability); + if (cfg.enable_slicing) { + reg_req.requested_nssai_present = true; + s_nssai_t nssai; + set_nssai(nssai); + reg_req.requested_nssai.s_nssai_list.push_back(nssai); + } if (initial_registration_request_stored.pack(pdu) != SRSASN_SUCCESS) { logger.error("Failed to pack registration request"); return SRSRAN_ERROR; @@ -426,14 +432,14 @@ int nas_5g::send_security_mode_complete(const srsran::nas_5g::security_mode_comm // TODO: Save TMSI registration_request_t& modified_registration_request = initial_registration_request_stored.registration_request(); modified_registration_request.capability_5gmm_present = true; - modified_registration_request.requested_nssai_present = true; modified_registration_request.update_type_5gs_present = true; - s_nssai_t s_nssai{}; - s_nssai.type = s_nssai_t::SST_type_::options::sst; - s_nssai.sst = 1; - modified_registration_request.requested_nssai.s_nssai_list = {s_nssai}; - + if (cfg.enable_slicing) { + s_nssai_t s_nssai{}; + modified_registration_request.requested_nssai_present = true; + set_nssai(s_nssai); + modified_registration_request.requested_nssai.s_nssai_list = {s_nssai}; + } modified_registration_request.capability_5gmm.lpp = 0; modified_registration_request.capability_5gmm.ho_attach = 0; modified_registration_request.capability_5gmm.s1_mode = 0; @@ -529,6 +535,17 @@ void nas_5g::release_proc_trans_id(uint32_t proc_id) return; } +void nas_5g::set_nssai(srsran::nas_5g::s_nssai_t& s_nssai) +{ + if (cfg.nssai_sd == 0) { + s_nssai.type = s_nssai_t::SST_type_::options::sst; + } else { + s_nssai.type = s_nssai_t::SST_type_::options::sst_and_sd; + } + s_nssai.sst = cfg.nssai_sst; + s_nssai.sd = cfg.nssai_sd; +} + int nas_5g::send_pdu_session_establishment_request(uint32_t transaction_identity, uint16_t pdu_session_id, const pdu_session_cfg_t& pdu_session_cfg) @@ -584,10 +601,10 @@ int nas_5g::send_pdu_session_establishment_request(uint32_t tran ul_nas_msg.request_type_present = true; ul_nas_msg.request_type.request_type_value = request_type_t::Request_type_value_type_::options::initial_request; - ul_nas_msg.s_nssai_present = true; - ul_nas_msg.s_nssai.type = s_nssai_t::SST_type_::options::sst; - ul_nas_msg.s_nssai.sst = 1; - + if (cfg.enable_slicing) { + ul_nas_msg.s_nssai_present = true; + set_nssai(ul_nas_msg.s_nssai); + } ul_nas_msg.dnn_present = true; ul_nas_msg.dnn.dnn_value.resize(pdu_session_cfg.apn_name.size() + 1); ul_nas_msg.dnn.dnn_value.data()[0] = static_cast(pdu_session_cfg.apn_name.size()); diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index 5bae8ce76..bdd115efb 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -188,6 +188,18 @@ imei = 353490069873319 #eia = 1,2,3 #eea = 0,1,2,3 +##################################################################### +# Slice configuration +# +# enable: Enable a specific slice +# nssai-sst: Specfic Slice Type +# nssai-sd: Slice diffentiator +##################################################################### +[slicing] +#enable = false +#nssai-sst = 1 +#nssai-sd = 1 + ##################################################################### # GW configuration #