diff --git a/lib/include/srslte/common/basic_pnf.h b/lib/include/srslte/common/basic_pnf.h index 1838feb96..cbebebaf3 100644 --- a/lib/include/srslte/common/basic_pnf.h +++ b/lib/include/srslte/common/basic_pnf.h @@ -43,6 +43,8 @@ #define MIN_TB_LEN (100) // MAX_TB_LEN defined in api.h +#define PING_REQUEST_PDU 1 + namespace srslte { struct pnf_metrics_t { @@ -63,6 +65,7 @@ public: 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), @@ -210,6 +213,11 @@ private: // Send request send_sf_ind(tti); + // provide UL data every 2nd TTI + if (tti % 2 == 0) { + send_rx_data_ind(tti); + } + sf_counter++; } @@ -334,8 +342,52 @@ private: return 0; } - void send_dl_ind(uint32_t tti_) + 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) + { +#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, @@ -350,12 +402,13 @@ private: 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.tti = tti; dl_ind.t1 = 0; dl_ind.nof_pdus = 1; diff --git a/lib/include/srslte/common/basic_vnf.h b/lib/include/srslte/common/basic_vnf.h index 3a2f3035b..5c82504f6 100644 --- a/lib/include/srslte/common/basic_vnf.h +++ b/lib/include/srslte/common/basic_vnf.h @@ -61,6 +61,7 @@ private: 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(); @@ -76,9 +77,6 @@ private: std::unique_ptr m_tx_req_msg; - // std::unique_ptr m_dl_grant; ///< Used by UE as temp buffer for - // all DL indications - bool running = false; vnf_args_t m_args = {}; diff --git a/lib/include/srslte/common/basic_vnf_api.h b/lib/include/srslte/common/basic_vnf_api.h index 62bd7e37e..7637575b5 100644 --- a/lib/include/srslte/common/basic_vnf_api.h +++ b/lib/include/srslte/common/basic_vnf_api.h @@ -58,10 +58,19 @@ namespace basic_vnf_api { // | | // Primitive API messages for basic testing basic VNF/PNF interaction -enum msg_type_t { SF_IND, DL_CONFIG, TX_REQUEST, DL_IND, UL_IND, MSG_TYPE_NITEMS }; +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 }; @@ -113,6 +122,22 @@ struct tx_request_msg_t { 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 @@ -144,4 +169,4 @@ struct ul_ind_msg_t { } // namespace basic_vnf_api -#endif // SRSLTE_BASIC_VNF_API_H \ No newline at end of file +#endif // SRSLTE_BASIC_VNF_API_H diff --git a/lib/include/srslte/interfaces/gnb_interfaces.h b/lib/include/srslte/interfaces/gnb_interfaces.h index eabc9a8c4..9468bc47b 100644 --- a/lib/include/srslte/interfaces/gnb_interfaces.h +++ b/lib/include/srslte/interfaces/gnb_interfaces.h @@ -211,10 +211,24 @@ public: virtual int tx_request(const tx_request_t& request) = 0; }; +class stack_interface_mac +{ +public: + ///< MAC calls stack to inform about new PDUs having arrived to be further processes in stack thread + virtual void process_pdus() = 0; +}; + class stack_interface_phy_nr : public srslte::stack_interface_phy_nr { public: - virtual int sf_indication(const uint32_t tti) = 0; + struct rx_data_ind_t { + uint32_t tti; + uint16_t rnti; + srslte::unique_byte_buffer_t tb; + }; + + virtual int sf_indication(const uint32_t tti) = 0; + virtual int rx_data_indication(rx_data_ind_t& grant) = 0; }; class mac_interface_phy_nr diff --git a/lib/src/common/basic_vnf.cc b/lib/src/common/basic_vnf.cc index 555018e3b..c41644e8e 100644 --- a/lib/src/common/basic_vnf.cc +++ b/lib/src/common/basic_vnf.cc @@ -150,6 +150,9 @@ int srslte_basic_vnf::handle_msg(const uint8_t* buffer, const uint32_t len) 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; @@ -233,6 +236,31 @@ int srslte_basic_vnf::handle_ul_ind(basic_vnf_api::ul_ind_msg_t* msg) return SRSLTE_SUCCESS; } +int srslte_basic_vnf::handle_rx_data_ind(basic_vnf_api::rx_data_ind_msg_t* msg) +{ + m_log->info("Received %s for TTI=%d\n", basic_vnf_api::msg_type_text[msg->header.type], msg->sfn); + + if (msg->nof_pdus != 1 || msg->pdus[0].type != basic_vnf_api::PUSCH) { + m_log->error("Received UL indication for wrong PDU type\n"); + return SRSLTE_ERROR; + } + + // fill struct + srsenb::stack_interface_phy_nr::rx_data_ind_t rx_data = {}; + rx_data.tti = msg->sfn; + rx_data.tb = srslte::allocate_unique_buffer(*m_pool); + 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 SRSLTE_SUCCESS; +} + int srslte_basic_vnf::dl_config_request(const srsenb::phy_interface_stack_nr::dl_config_request_t& request) { // Generate DL Config @@ -362,4 +390,4 @@ bool srslte_basic_vnf::stop() return true; } -} // namespace srslte \ No newline at end of file +} // namespace srslte