From 2960e559515348dce83bfdbdd6ef39e551235045 Mon Sep 17 00:00:00 2001 From: Sugandha Gupta Date: Fri, 25 Jan 2019 17:36:26 -0800 Subject: device3: Constraint send/recv_frame_size based on down/upstream MTU We need to properly contraint the send/recv_frame_size based on the minimum MTU of all the down/upstream blocks. This fixes the issue with E310 tx/rx streaming as it has smaller MTU sizes than the other usrps. --- host/include/uhd/rfnoc/sink_block_ctrl_base.hpp | 12 +++++ host/include/uhd/rfnoc/source_block_ctrl_base.hpp | 12 +++++ host/lib/rfnoc/block_ctrl_base.cpp | 8 +++- host/lib/rfnoc/sink_block_ctrl_base.cpp | 14 ++++-- host/lib/rfnoc/source_block_ctrl_base.cpp | 10 +++++ host/lib/usrp/device3/device3_impl.hpp | 3 ++ host/lib/usrp/device3/device3_io_impl.cpp | 54 +++++++++++++++++++++++ host/lib/usrp/e300/e300_impl.cpp | 5 +++ host/lib/usrp/e300/e300_impl.hpp | 3 ++ host/lib/usrp/mpmd/mpmd_impl.cpp | 4 ++ host/lib/usrp/mpmd/mpmd_impl.hpp | 3 ++ host/lib/usrp/x300/x300_impl.cpp | 7 ++- host/lib/usrp/x300/x300_impl.hpp | 3 ++ 13 files changed, 132 insertions(+), 6 deletions(-) diff --git a/host/include/uhd/rfnoc/sink_block_ctrl_base.hpp b/host/include/uhd/rfnoc/sink_block_ctrl_base.hpp index a2d4685be..5267612e6 100644 --- a/host/include/uhd/rfnoc/sink_block_ctrl_base.hpp +++ b/host/include/uhd/rfnoc/sink_block_ctrl_base.hpp @@ -63,6 +63,18 @@ public: */ size_t get_fifo_size(size_t block_port = 0) const; + /*! Return the MTU size on a given block port. + * + * This is necessary for setting up transports, among other things. + * + * If the block port is not defined, it will return 0, and not throw. + * + * \param block_port The block port (0 through 15). + * + * Returns the MTU in bytes. + */ + size_t get_mtu(size_t block_port = 0) const; + /*! Configure flow control for incoming streams. * * If flow control is enabled for incoming streams, this block will periodically diff --git a/host/include/uhd/rfnoc/source_block_ctrl_base.hpp b/host/include/uhd/rfnoc/source_block_ctrl_base.hpp index a22a19da9..e79b7ef69 100644 --- a/host/include/uhd/rfnoc/source_block_ctrl_base.hpp +++ b/host/include/uhd/rfnoc/source_block_ctrl_base.hpp @@ -118,6 +118,18 @@ public: const size_t block_port = 0, const uhd::sid_t& sid = uhd::sid_t()); + /*! Return the MTU size on a given block port. + * + * This is necessary for setting up transports, among other things. + * + * If the block port is not defined, it will return 0, and not throw. + * + * \param block_port The block port (0 through 15). + * + * Returns the MTU in bytes. + */ + size_t get_mtu(size_t block_port = 0) const; + protected: /*********************************************************************** diff --git a/host/lib/rfnoc/block_ctrl_base.cpp b/host/lib/rfnoc/block_ctrl_base.cpp index ed8068b5b..e70267b96 100644 --- a/host/lib/rfnoc/block_ctrl_base.cpp +++ b/host/lib/rfnoc/block_ctrl_base.cpp @@ -94,12 +94,16 @@ block_ctrl_base::block_ctrl_base(const make_args_t& make_args) // Set source addresses: sr_write(SR_BLOCK_SID, get_address(ctrl_port), ctrl_port); // Set sink buffer sizes: - settingsbus_reg_t reg = SR_READBACK_REG_FIFOSIZE; - size_t buf_size_bytes = size_t(sr_read64(reg, ctrl_port)); + settingsbus_reg_t reg_fifo = SR_READBACK_REG_FIFOSIZE; + size_t buf_size_bytes = size_t(sr_read64(reg_fifo, ctrl_port)); if (buf_size_bytes > 0) n_valid_input_buffers++; _tree->create(_root_path / "input_buffer_size" / ctrl_port) .set(buf_size_bytes); + // Set MTU size and convert to bytes: + settingsbus_reg_t reg_mtu = SR_READBACK_REG_MTU; + size_t mtu = 8 * (1 << size_t(sr_read64(reg_mtu, ctrl_port))); + _tree->create(_root_path / "mtu" / ctrl_port).set(mtu); // Set default destination SIDs // Otherwise, the default is someone else's SID, which we don't want sr_write(SR_RESP_IN_DST_SID, 0xFFFF, ctrl_port); diff --git a/host/lib/rfnoc/sink_block_ctrl_base.cpp b/host/lib/rfnoc/sink_block_ctrl_base.cpp index bb81706f9..f1d65350a 100644 --- a/host/lib/rfnoc/sink_block_ctrl_base.cpp +++ b/host/lib/rfnoc/sink_block_ctrl_base.cpp @@ -43,11 +43,19 @@ std::vector sink_block_ctrl_base::get_input_ports() const **********************************************************************/ size_t sink_block_ctrl_base::get_fifo_size(size_t block_port) const { - if (_tree->exists( - _root_path / "input_buffer_size" / str(boost::format("%d") % block_port))) { + if (_tree->exists(_root_path / "input_buffer_size" / std::to_string(block_port))) { return _tree ->access( - _root_path / "input_buffer_size" / str(boost::format("%d") % block_port)) + _root_path / "input_buffer_size" / std::to_string(block_port)) + .get(); + } + return 0; +} + +size_t sink_block_ctrl_base::get_mtu(size_t block_port) const +{ + if (_tree->exists(_root_path / "mtu" / std::to_string(block_port))) { + return _tree->access(_root_path / "mtu" / std::to_string(block_port)) .get(); } return 0; diff --git a/host/lib/rfnoc/source_block_ctrl_base.cpp b/host/lib/rfnoc/source_block_ctrl_base.cpp index 656ab26af..d06b6632d 100644 --- a/host/lib/rfnoc/source_block_ctrl_base.cpp +++ b/host/lib/rfnoc/source_block_ctrl_base.cpp @@ -143,6 +143,16 @@ void source_block_ctrl_base::configure_flow_control_out(const bool enable_fc_out sr_write(SR_FLOW_CTRL_EN, config, block_port); } +size_t source_block_ctrl_base::get_mtu(size_t block_port) const +{ + if (_tree->exists(_root_path / "mtu" / std::to_string(block_port))) { + return _tree->access(_root_path / "mtu" / std::to_string(block_port)) + .get(); + } + return 0; +} + + /*********************************************************************** * Hooks **********************************************************************/ diff --git a/host/lib/usrp/device3/device3_impl.hpp b/host/lib/usrp/device3/device3_impl.hpp index 3bf6f6111..62fd399ac 100644 --- a/host/lib/usrp/device3/device3_impl.hpp +++ b/host/lib/usrp/device3/device3_impl.hpp @@ -206,6 +206,9 @@ protected: //! Is called after a streamer is generated virtual void post_streamer_hooks(uhd::direction_t) {} + //! get mtu + virtual size_t get_mtu(const size_t, const uhd::direction_t) = 0; + /*********************************************************************** * Channel-related **********************************************************************/ diff --git a/host/lib/usrp/device3/device3_io_impl.cpp b/host/lib/usrp/device3/device3_io_impl.cpp index ce8ff2cbf..081f881d5 100644 --- a/host/lib/usrp/device3/device3_io_impl.cpp +++ b/host/lib/usrp/device3/device3_io_impl.cpp @@ -338,6 +338,33 @@ rx_streamer::sptr device3_impl::get_rx_stream(const stream_args_t& args_) // Setup the DSP transport hints device_addr_t rx_hints = get_rx_hints(mb_index); + // Traverse the upstream nodes for minimum mtu + size_t min_mtu = blk_ctrl->get_mtu(block_port); + UHD_RX_STREAMER_LOG() << "Maximum MTU supported by " << blk_ctrl->unique_id() + << ": " << min_mtu; + std::vector> + upstream_source_nodes = + blk_ctrl->find_upstream_node(); + for (const boost::shared_ptr& node : + upstream_source_nodes) { + // Get MTU from Port 0 of the upstream nodes. This is okay for now as + // currently we use port 0 of a block in case of channel 1. + UHD_RX_STREAMER_LOG() << "Maximum MTU supported by " << node->unique_id() + << ": " << node->get_mtu(0); + min_mtu = std::min(min_mtu, node->get_mtu(0)); + } + // Contraint min_mtu by device mtu + min_mtu = std::min(min_mtu, get_mtu(mb_index, uhd::direction_t::RX_DIRECTION)); + if (rx_hints.has_key("recv_frame_size")) { + if (rx_hints.cast("recv_frame_size", min_mtu) > min_mtu) { + UHD_RX_STREAMER_LOG() << "Requested recv_frame_size of " << rx_hints["recv_frame_size"] + << " exceeds the maximum possible on this stream. Using " << min_mtu; + } + min_mtu = + std::min(min_mtu, rx_hints.cast("recv_frame_size", min_mtu)); + } + rx_hints["recv_frame_size"] = std::to_string(min_mtu); + // allocate sid and create transport uhd::sid_t stream_address = blk_ctrl->get_address(block_port); UHD_RX_STREAMER_LOG() << "creating rx stream " << rx_hints.to_string(); @@ -577,6 +604,33 @@ tx_streamer::sptr device3_impl::get_tx_stream(const uhd::stream_args_t& args_) // Setup the dsp transport hints device_addr_t tx_hints = get_tx_hints(mb_index); + + // Traverse the downstream nodes for minimum mtu + size_t min_mtu = blk_ctrl->get_mtu(block_port); + UHD_TX_STREAMER_LOG() << "Maximum MTU supported by " << blk_ctrl->unique_id() + << ": " << min_mtu; + std::vector> + downstream_sink_nodes = + blk_ctrl->find_downstream_node(); + for (const boost::shared_ptr& node : + downstream_sink_nodes) { + // Get MTU from Port 0 of the downstream nodes. This is okay for now as + // currently we use port 0 of a block in case of channel 1. + UHD_TX_STREAMER_LOG() << "Maximum MTU supported by " << node->unique_id() + << ": " << node->get_mtu(0); + min_mtu = std::min(min_mtu, node->get_mtu(0)); + } + min_mtu = std::min(min_mtu, get_mtu(mb_index, uhd::direction_t::TX_DIRECTION)); + if (tx_hints.has_key("send_frame_size")) { + if (tx_hints.cast("send_frame_size", min_mtu) > min_mtu) { + UHD_TX_STREAMER_LOG() << "Requested send_frame_size of " << tx_hints["send_frame_size"] + << " exceeds the maximum possible on this stream. Using " << min_mtu; + } + min_mtu = + std::min(min_mtu, tx_hints.cast("send_frame_size", min_mtu)); + } + tx_hints["send_frame_size"] = std::to_string(min_mtu); + const size_t fifo_size = blk_ctrl->get_fifo_size(block_port); // Allocate sid and create transport uhd::sid_t stream_address = blk_ctrl->get_address(block_port); diff --git a/host/lib/usrp/e300/e300_impl.cpp b/host/lib/usrp/e300/e300_impl.cpp index 59a8cec88..5a6376039 100644 --- a/host/lib/usrp/e300/e300_impl.cpp +++ b/host/lib/usrp/e300/e300_impl.cpp @@ -731,6 +731,11 @@ uhd::both_xports_t e300_impl::make_transport( return xports; } +size_t e300_impl::get_mtu(const size_t /*mb_index*/, const uhd::direction_t dir) { + return (dir == RX_DIRECTION) ? _data_xport_params.recv_frame_size : + _data_xport_params.send_frame_size; +} + void e300_impl::_update_clock_source(const std::string &source) { if (source != "internal") { diff --git a/host/lib/usrp/e300/e300_impl.hpp b/host/lib/usrp/e300/e300_impl.hpp index 2e919cf9b..0a6f153eb 100644 --- a/host/lib/usrp/e300/e300_impl.hpp +++ b/host/lib/usrp/e300/e300_impl.hpp @@ -166,6 +166,9 @@ private: // methods return uhd::ENDIANNESS_LITTLE; }; + //! get mtu + size_t get_mtu(const size_t, const uhd::direction_t); + /************************************************************************ * Helpers ***********************************************************************/ diff --git a/host/lib/usrp/mpmd/mpmd_impl.cpp b/host/lib/usrp/mpmd/mpmd_impl.cpp index b8ce6cabd..2f3584498 100644 --- a/host/lib/usrp/mpmd/mpmd_impl.cpp +++ b/host/lib/usrp/mpmd/mpmd_impl.cpp @@ -348,6 +348,10 @@ void mpmd_impl::setup_rpc_blocks( } } +size_t mpmd_impl::get_mtu(const size_t mb_index, const uhd::direction_t dir) { + return _mb[mb_index]->get_mtu(dir); +} + /***************************************************************************** * Factory & Registry ****************************************************************************/ diff --git a/host/lib/usrp/mpmd/mpmd_impl.hpp b/host/lib/usrp/mpmd/mpmd_impl.hpp index f74627afa..bdb6bd691 100644 --- a/host/lib/usrp/mpmd/mpmd_impl.hpp +++ b/host/lib/usrp/mpmd/mpmd_impl.hpp @@ -246,6 +246,9 @@ public: uhd::usrp::device3_impl::xport_type_t, const uhd::device_addr_t&); + //! get mtu + size_t get_mtu(const size_t, const uhd::direction_t); + private: uhd::device_addr_t get_rx_hints(size_t mb_index); uhd::device_addr_t get_tx_hints(size_t mb_index); diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index 796d422ad..b9b4a06f9 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -1526,7 +1526,7 @@ uhd::both_xports_t x300_impl::make_transport(const uhd::sid_t& address, // Increasing number of recv frames here because ctrl_iface uses it // to determine how many control packets can be in flight before it // must wait for an ACK - default_buff_args.num_recv_frames = + default_buff_args.num_recv_frames = uhd::rfnoc::CMD_FIFO_SIZE / uhd::rfnoc::MAX_CMD_PKT_SIZE; } else if (xport_type == TX_DATA) { size_t default_frame_size = conn.link_rate == x300::MAX_RATE_1GIGE @@ -1993,6 +1993,11 @@ x300_impl::frame_size_t x300_impl::determine_max_frame_size( return frame_size; } +size_t x300_impl::get_mtu(const size_t /*mb_index*/, const uhd::direction_t dir) { + return (dir == RX_DIRECTION) ? _max_frame_sizes.recv_frame_size : + _max_frame_sizes.send_frame_size; +} + /*********************************************************************** * compat checks **********************************************************************/ diff --git a/host/lib/usrp/x300/x300_impl.hpp b/host/lib/usrp/x300/x300_impl.hpp index c101b3032..8d50f9914 100644 --- a/host/lib/usrp/x300/x300_impl.hpp +++ b/host/lib/usrp/x300/x300_impl.hpp @@ -173,6 +173,9 @@ private: const xport_type_t xport_type, const uhd::device_addr_t& args); + //! get mtu + size_t get_mtu(const size_t, const uhd::direction_t); + struct frame_size_t { size_t recv_frame_size; -- cgit v1.2.3