diff options
author | Michael West <michael.west@ettus.com> | 2019-06-19 13:25:32 -0700 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2019-07-18 08:46:16 -0700 |
commit | 028a052dec8733f552fbfe0792126f5e9f8ca526 (patch) | |
tree | 67d42f21e4a2d20eadad036b655c2a0a40f71605 /host | |
parent | ab6893ab32f001d9aab1606bad34fafc4ab76933 (diff) | |
download | uhd-028a052dec8733f552fbfe0792126f5e9f8ca526.tar.gz uhd-028a052dec8733f552fbfe0792126f5e9f8ca526.tar.bz2 uhd-028a052dec8733f552fbfe0792126f5e9f8ca526.zip |
Device3: Fix MTU and default frame sizes
The latest changes to the get_*x_stream() functions to calculate the MTU for
the channel caused default frame size values to be ignored. This change fixes
that by changing the key from "send/recv_frame_size" to "mtu" and then changing
the implementations of make_transport() constrain the frame size values based
on the "mtu" value as well as any device and/or transport-specific limits.
Signed-off-by: Michael West <michael.west@ettus.com>
Diffstat (limited to 'host')
-rw-r--r-- | host/lib/transport/udp_zero_copy.cpp | 5 | ||||
-rw-r--r-- | host/lib/usrp/device3/device3_io_impl.cpp | 86 | ||||
-rw-r--r-- | host/lib/usrp/mpmd/mpmd_xport_ctrl_dpdk_udp.cpp | 41 | ||||
-rw-r--r-- | host/lib/usrp/mpmd/mpmd_xport_ctrl_liberio.cpp | 48 | ||||
-rw-r--r-- | host/lib/usrp/mpmd/mpmd_xport_ctrl_udp.cpp | 86 | ||||
-rw-r--r-- | host/lib/usrp/x300/x300_impl.cpp | 169 |
6 files changed, 277 insertions, 158 deletions
diff --git a/host/lib/transport/udp_zero_copy.cpp b/host/lib/transport/udp_zero_copy.cpp index 6d615570f..e3df80da6 100644 --- a/host/lib/transport/udp_zero_copy.cpp +++ b/host/lib/transport/udp_zero_copy.cpp @@ -384,6 +384,11 @@ udp_zero_copy::sptr udp_zero_copy::make(const std::string& addr, xport_params.send_frame_size = UDP_ZERO_COPY_DEFAULT_FRAME_SIZE; } + UHD_LOG_TRACE("UDP", + "send_frame_size: " << xport_params.send_frame_size); + UHD_LOG_TRACE("UDP", + "recv_frame_size: " << xport_params.recv_frame_size); + if (xport_params.recv_buff_size == 0) { UHD_LOG_TRACE("UDP", "Using default value for recv_buff_size"); xport_params.recv_buff_size = std::max(UDP_ZERO_COPY_DEFAULT_BUFF_SIZE, diff --git a/host/lib/usrp/device3/device3_io_impl.cpp b/host/lib/usrp/device3/device3_io_impl.cpp index 06415dd91..800d2f5a8 100644 --- a/host/lib/usrp/device3/device3_io_impl.cpp +++ b/host/lib/usrp/device3/device3_io_impl.cpp @@ -168,7 +168,9 @@ static size_t get_rx_flow_control_window( size_t window_in_bytes = (static_cast<size_t>(fullness_factor * sw_buff_size)); if (rx_args.has_key("max_recv_window")) { window_in_bytes = std::min( - window_in_bytes, pkt_size * rx_args.cast<size_t>("max_recv_window", 1)); + window_in_bytes, + pkt_size * rx_args.cast<size_t>("max_recv_window", 1) + ); } if (window_in_bytes < pkt_size) { throw uhd::value_error("recv_buff_size must be larger than the recv_frame_size."); @@ -336,10 +338,13 @@ 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; + // Search the device and all nodes for lowest MTU + size_t mtu = std::min( + get_mtu(mb_index, uhd::direction_t::RX_DIRECTION), + blk_ctrl->get_mtu(block_port)); + UHD_RX_STREAMER_LOG() << "Maximum MTU supported by " + << blk_ctrl->unique_id() + << ": " << blk_ctrl->get_mtu(block_port); std::vector<boost::shared_ptr<uhd::rfnoc::source_block_ctrl_base>> upstream_source_nodes = blk_ctrl->find_upstream_node<uhd::rfnoc::source_block_ctrl_base>(); @@ -349,20 +354,19 @@ rx_streamer::sptr device3_impl::get_rx_stream(const stream_args_t& args_) // 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)); + mtu = std::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<size_t>("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<size_t>("recv_frame_size", min_mtu)); + rx_hints["mtu"] = std::to_string(mtu); + + // Make sure user supplied recv_frame_size is less than the MTU + if (rx_hints.cast<size_t>("recv_frame_size", mtu) > mtu) { + UHD_LOGGER_WARNING("STREAMER") + << "Requested recv_frame_size of " + << rx_hints["recv_frame_size"] + << " exceeds the maximum possible on this stream. Using " + << mtu; + rx_hints["recv_frame_size"] = std::to_string(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); @@ -448,8 +452,7 @@ rx_streamer::sptr device3_impl::get_rx_stream(const stream_args_t& args_) convert::get_bytes_per_item(args.otw_format); // bytes per item const size_t spp = std::min(args.args.cast<size_t>("spp", bpp / bpi), bpp / bpi); // samples per packet - UHD_RX_STREAMER_LOG() - << "bpp == " << bpp << ", bpi == " << bpi << ", spp == " << spp; + UHD_RX_STREAMER_LOG() << "bpp == " << bpp << ", bpi == " << bpi << ", spp == " << spp; my_streamer = boost::make_shared<device3_recv_packet_streamer>( spp, recv_terminator, xport); @@ -605,10 +608,13 @@ 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; + // Search the device and all nodes for lowest MTU + size_t mtu = std::min( + get_mtu(mb_index, uhd::direction_t::TX_DIRECTION), + blk_ctrl->get_mtu(block_port)); + UHD_TX_STREAMER_LOG() << "Maximum MTU supported by " + << blk_ctrl->unique_id() << ": " + << blk_ctrl->get_mtu(block_port); std::vector<boost::shared_ptr<uhd::rfnoc::sink_block_ctrl_base>> downstream_sink_nodes = blk_ctrl->find_downstream_node<uhd::rfnoc::sink_block_ctrl_base>(); @@ -616,21 +622,22 @@ tx_streamer::sptr device3_impl::get_tx_stream(const uhd::stream_args_t& args_) 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)); + UHD_TX_STREAMER_LOG() << "Maximum MTU supported by " + << node->unique_id() << ": " + << node->get_mtu(0); + mtu = std::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<size_t>("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<size_t>("send_frame_size", min_mtu)); + tx_hints["mtu"] = std::to_string(mtu); + + // Make sure user supplied send_frame_size is less than the MTU + if (tx_hints.cast<size_t>("send_frame_size", mtu) > mtu) { + UHD_LOGGER_WARNING("STREAMER") + << "Requested send_frame_size of " + << tx_hints["send_frame_size"] + << " exceeds the maximum possible on this stream. Using " + << mtu; + tx_hints["send_frame_size"] = std::to_string(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 @@ -729,13 +736,16 @@ tx_streamer::sptr device3_impl::get_tx_stream(const uhd::stream_args_t& args_) // To calculate the max number of samples per packet, we assume the maximum // header length to avoid fragmentation should the entire header be used. const size_t bpp = - tx_hints.cast<size_t>("bpp", pkt_size) - stream_options.tx_max_len_hdr; + tx_hints.cast<size_t>("bpp", pkt_size) - + stream_options.tx_max_len_hdr; const size_t bpi = convert::get_bytes_per_item(args.otw_format); // bytes per item const size_t spp = std::min(args.args.cast<size_t>("spp", bpp / bpi), bpp / bpi); // samples per packet UHD_TX_STREAMER_LOG() - << "bpp == " << bpp << ", bpi == " << bpi << ", spp == " << spp; + << "bpp == " << bpp + << ", bpi == " << bpi + << ", spp == " << spp; my_streamer = boost::make_shared<device3_send_packet_streamer>( spp, send_terminator, xport, async_xport); diff --git a/host/lib/usrp/mpmd/mpmd_xport_ctrl_dpdk_udp.cpp b/host/lib/usrp/mpmd/mpmd_xport_ctrl_dpdk_udp.cpp index a496e8e69..38d295728 100644 --- a/host/lib/usrp/mpmd/mpmd_xport_ctrl_dpdk_udp.cpp +++ b/host/lib/usrp/mpmd/mpmd_xport_ctrl_dpdk_udp.cpp @@ -21,6 +21,8 @@ constexpr unsigned int MPMD_UDP_RESERVED_FRAME_SIZE = 64; //! Maximum CHDR packet size in bytes const size_t MPMD_10GE_DATA_FRAME_MAX_SIZE = 4000; +const size_t MPMD_10GE_DATA_FRAME_DEFAULT_SIZE = 4000; +const size_t MPMD_10GE_MSG_FRAME_DEFAULT_SIZE = 256; //! Number of send/recv frames const size_t MPMD_ETH_NUM_SEND_FRAMES = 32; @@ -194,27 +196,36 @@ uhd::both_xports_t mpmd_xport_ctrl_dpdk_udp::make_transport( mpmd_xport_mgr::xport_info_t &xport_info, const usrp::device3_impl::xport_type_t xport_type, - const uhd::device_addr_t& xport_args_ + const uhd::device_addr_t& xport_args ) { - auto xport_args = xport_args_; - transport::zero_copy_xport_params default_buff_args; + // Constrain by this transport's MTU and the MTU in the xport_args + const size_t send_mtu = std::min(get_mtu(uhd::TX_DIRECTION), + xport_args.cast<size_t>("mtu", get_mtu(uhd::TX_DIRECTION))); + const size_t recv_mtu = std::min(get_mtu(uhd::RX_DIRECTION), + xport_args.cast<size_t>("mtu", get_mtu(uhd::RX_DIRECTION))); + // Create actual UHD-DPDK UDP transport - default_buff_args.recv_frame_size = - xport_args.cast<size_t>("recv_frame_size", get_mtu(uhd::RX_DIRECTION)); - default_buff_args.send_frame_size = - xport_args.cast<size_t>("send_frame_size", get_mtu(uhd::TX_DIRECTION)); - if (xport_type == usrp::device3_impl::ASYNC_MSG or - xport_type == usrp::device3_impl::CTRL) { - default_buff_args.num_recv_frames = - xport_args.cast<size_t>("num_recv_frames", MPMD_ETH_NUM_CTRL_FRAMES); - default_buff_args.num_send_frames = - xport_args.cast<size_t>("num_send_frames", MPMD_ETH_NUM_CTRL_FRAMES); - } else { + transport::zero_copy_xport_params default_buff_args; + default_buff_args.num_recv_frames = MPMD_ETH_NUM_CTRL_FRAMES; + default_buff_args.num_send_frames = MPMD_ETH_NUM_CTRL_FRAMES; + default_buff_args.recv_frame_size = MPMD_10GE_MSG_FRAME_DEFAULT_SIZE; + default_buff_args.send_frame_size = MPMD_10GE_MSG_FRAME_DEFAULT_SIZE; + + if (xport_type == usrp::device3_impl::RX_DATA) { default_buff_args.num_recv_frames = xport_args.cast<size_t>("num_recv_frames", MPMD_ETH_NUM_RECV_FRAMES); + default_buff_args.recv_frame_size = std::min( + xport_args.cast<size_t>("recv_frame_size", + MPMD_10GE_DATA_FRAME_DEFAULT_SIZE), + recv_mtu); + } else if (xport_type == usrp::device3_impl::TX_DATA) { default_buff_args.num_send_frames = xport_args.cast<size_t>("num_send_frames", MPMD_ETH_NUM_SEND_FRAMES); + default_buff_args.send_frame_size = std::min( + xport_args.cast<size_t>("send_frame_size", + MPMD_10GE_DATA_FRAME_DEFAULT_SIZE), + send_mtu); } UHD_LOG_TRACE("BUFF", "num_recv_frames=" << default_buff_args.num_recv_frames @@ -234,7 +245,7 @@ mpmd_xport_ctrl_dpdk_udp::make_transport( xport_info["port"], "0", default_buff_args, - xport_args + uhd::device_addr_t() ); const uint16_t port = recv->get_local_port(); const std::string src_ip_addr = recv->get_local_addr(); diff --git a/host/lib/usrp/mpmd/mpmd_xport_ctrl_liberio.cpp b/host/lib/usrp/mpmd/mpmd_xport_ctrl_liberio.cpp index 78751c94f..c53eb97a1 100644 --- a/host/lib/usrp/mpmd/mpmd_xport_ctrl_liberio.cpp +++ b/host/lib/usrp/mpmd/mpmd_xport_ctrl_liberio.cpp @@ -47,15 +47,49 @@ mpmd_xport_ctrl_liberio::mpmd_xport_ctrl_liberio(const uhd::device_addr_t& mb_ar uhd::both_xports_t mpmd_xport_ctrl_liberio::make_transport( mpmd_xport_mgr::xport_info_t& xport_info, const usrp::device3_impl::xport_type_t xport_type, - const uhd::device_addr_t& xport_args) + const uhd::device_addr_t& xport_args_) { + auto xport_args = (xport_type == usrp::device3_impl::CTRL) ? + uhd::device_addr_t() : xport_args_; + + // Constrain by this transport's MTU and the MTU passed in + const size_t send_mtu = std::min(get_mtu(uhd::TX_DIRECTION), + xport_args.cast<size_t>("mtu", get_mtu(uhd::TX_DIRECTION))); + const size_t recv_mtu = std::min(get_mtu(uhd::RX_DIRECTION), + xport_args.cast<size_t>("mtu", get_mtu(uhd::RX_DIRECTION))); + size_t send_frame_size = xport_args.cast<size_t>("send_frame_size", send_mtu); + size_t recv_frame_size = xport_args.cast<size_t>("recv_frame_size", recv_mtu); + + // Check any user supplied frame sizes and constrain to MTU + if (xport_args.has_key("send_frame_size") and + xport_type == usrp::device3_impl::TX_DATA) + { + if (send_frame_size > send_mtu) { + UHD_LOGGER_WARNING("MPMD") + << boost::format("Requested send_frame_size of %d exceeds the " + "maximum supported by the hardware. Using %d.") + % send_frame_size % send_mtu; + send_frame_size = send_mtu; + } + } + if (xport_args.has_key("recv_frame_size") and + xport_type == usrp::device3_impl::RX_DATA) + { + size_t recv_frame_size = xport_args.cast<size_t>("recv_frame_size", recv_mtu); + if (recv_frame_size > recv_mtu) { + UHD_LOGGER_WARNING("MPMD") + << boost::format("Requested recv_frame_size of %d exceeds the " + "maximum supported by the hardware. Using %d.") + % recv_frame_size % recv_mtu; + recv_frame_size = recv_mtu; + } + } + transport::zero_copy_xport_params default_buff_args; /* default ones for RX / TX, override below */ - default_buff_args.send_frame_size = - xport_args.cast<size_t>("send_frame_size", get_mtu(uhd::TX_DIRECTION)); - default_buff_args.recv_frame_size = - xport_args.cast<size_t>("recv_frame_size", get_mtu(uhd::RX_DIRECTION)); + default_buff_args.send_frame_size = send_mtu; + default_buff_args.recv_frame_size = recv_mtu; default_buff_args.num_recv_frames = LIBERIO_NUM_RECV_FRAMES; default_buff_args.num_send_frames = LIBERIO_NUM_SEND_FRAMES; @@ -70,9 +104,11 @@ uhd::both_xports_t mpmd_xport_ctrl_liberio::make_transport( default_buff_args.send_frame_size = LIBERIO_ASYNC_FRAME_MAX_SIZE; default_buff_args.recv_frame_size = LIBERIO_ASYNC_FRAME_MAX_SIZE; } else if (xport_type == usrp::device3_impl::RX_DATA) { + default_buff_args.recv_frame_size = recv_frame_size; default_buff_args.send_frame_size = LIBERIO_FC_FRAME_MAX_SIZE; } else { default_buff_args.recv_frame_size = LIBERIO_FC_FRAME_MAX_SIZE; + default_buff_args.send_frame_size = send_frame_size; } const std::string tx_dev = xport_info["tx_dev"]; @@ -140,7 +176,7 @@ bool mpmd_xport_ctrl_liberio::is_valid( return xport_info.at("type") == "liberio"; } -size_t mpmd_xport_ctrl_liberio::get_mtu(const uhd::direction_t dir) const +size_t mpmd_xport_ctrl_liberio::get_mtu(const uhd::direction_t /*dir*/) const { return LIBERIO_PAGES_PER_BUF * getpagesize(); } diff --git a/host/lib/usrp/mpmd/mpmd_xport_ctrl_udp.cpp b/host/lib/usrp/mpmd/mpmd_xport_ctrl_udp.cpp index bdb32b8f6..ba827fcf4 100644 --- a/host/lib/usrp/mpmd/mpmd_xport_ctrl_udp.cpp +++ b/host/lib/usrp/mpmd/mpmd_xport_ctrl_udp.cpp @@ -1,5 +1,6 @@ // // Copyright 2017 Ettus Research, National Instruments Company +// Copyright 2019 Ettus Research, National Instruments Brand // // SPDX-License-Identifier: GPL-3.0-or-later // @@ -20,11 +21,20 @@ namespace { //! Maximum CHDR packet size in bytes const size_t MPMD_10GE_DATA_FRAME_MAX_SIZE = 4000; -//! Maximum CHDR packet size in bytes -const size_t MPMD_10GE_ASYNCMSG_FRAME_MAX_SIZE = 1472; - -//! Number of send/recv frames -const size_t MPMD_ETH_NUM_FRAMES = 32; +//! Default number of send frames +const size_t MPMD_UDP_DEFAULT_NUM_SEND_FRAMES = 1; +//! Default number of recv frames +const size_t MPMD_UDP_DEFAULT_NUM_RECV_FRAMES = 1; +//! Default message frame size +const size_t MPMD_UDP_MSG_FRAME_SIZE = 256; +//! Default 1GbE send frame size +const size_t MPMD_UDP_1GE_DEFAULT_SEND_FRAME_SIZE = 1472; +//! Default 1GbE receive frame size +const size_t MPMD_UDP_1GE_DEFAULT_RECV_FRAME_SIZE = 1472; +//! Default 10GbE send frame size +const size_t MPMD_UDP_10GE_DEFAULT_SEND_FRAME_SIZE = 4000; +//! Default 10GbE receive frame size +const size_t MPMD_UDP_10GE_DEFAULT_RECV_FRAME_SIZE = 4000; //! const double MPMD_BUFFER_DEPTH = 50.0e-3; // s @@ -33,8 +43,8 @@ const double MPMD_BUFFER_DEPTH = 50.0e-3; // s const double MPMD_MTU_DISCOVERY_TIMEOUT = 0.02; // TODO: move these to appropriate header file for all other devices -const size_t MAX_RATE_1GIGE = 1e9 / 8; // byte/s -const size_t MAX_RATE_10GIGE = 10e9 / 8; // byte/s +const double MAX_RATE_1GIGE = 1e9 / 8; // byte/s +const double MAX_RATE_10GIGE = 10e9 / 8; // byte/s std::vector<std::string> get_addrs_from_mb_args(const uhd::device_addr_t& mb_args) { @@ -163,11 +173,10 @@ mpmd_xport_ctrl_udp::mpmd_xport_ctrl_udp(const uhd::device_addr_t& mb_args) uhd::both_xports_t mpmd_xport_ctrl_udp::make_transport( mpmd_xport_mgr::xport_info_t& xport_info, const usrp::device3_impl::xport_type_t xport_type, - const uhd::device_addr_t& xport_args_) + const uhd::device_addr_t& xport_args) { - auto xport_args = xport_args_; - size_t link_speed = MAX_RATE_1GIGE; + double link_speed = MAX_RATE_1GIGE; if (xport_info.count("link_speed") == 0) { UHD_LOG_WARNING("MPMD", "Could not determine link speed; using 1GibE max speed of " @@ -176,29 +185,54 @@ uhd::both_xports_t mpmd_xport_ctrl_udp::make_transport( link_speed = xport_info.at("link_speed") == "10000" ? MAX_RATE_10GIGE : MAX_RATE_1GIGE; } - transport::zero_copy_xport_params default_buff_args; + + // Constrain by this transport's MTU and the MTU in the xport_args + const size_t send_mtu = std::min(get_mtu(uhd::TX_DIRECTION), + xport_args.cast<size_t>("mtu", get_mtu(uhd::TX_DIRECTION))); + const size_t recv_mtu = std::min(get_mtu(uhd::RX_DIRECTION), + xport_args.cast<size_t>("mtu", get_mtu(uhd::RX_DIRECTION))); + // Create actual UDP transport - default_buff_args.num_send_frames = 1; - default_buff_args.num_recv_frames = - xport_type == usrp::device3_impl::CTRL ? - (uhd::rfnoc::CMD_FIFO_SIZE / uhd::rfnoc::MAX_CMD_PKT_SIZE) : - 1; - default_buff_args.recv_frame_size = - xport_args.cast<size_t>("recv_frame_size", get_mtu(uhd::RX_DIRECTION)); - default_buff_args.recv_buff_size = link_speed * MPMD_BUFFER_DEPTH; - default_buff_args.send_buff_size = link_speed * MPMD_BUFFER_DEPTH; - if (xport_type == usrp::device3_impl::ASYNC_MSG) { - default_buff_args.send_frame_size = MPMD_10GE_ASYNCMSG_FRAME_MAX_SIZE; - } else { + transport::zero_copy_xport_params default_buff_args; + default_buff_args.num_send_frames = MPMD_UDP_DEFAULT_NUM_SEND_FRAMES; + default_buff_args.num_recv_frames = MPMD_UDP_DEFAULT_NUM_RECV_FRAMES; + default_buff_args.recv_frame_size = MPMD_UDP_MSG_FRAME_SIZE; + default_buff_args.send_frame_size = MPMD_UDP_MSG_FRAME_SIZE; + if (xport_type == usrp::device3_impl::CTRL) { + default_buff_args.num_recv_frames = + uhd::rfnoc::CMD_FIFO_SIZE / uhd::rfnoc::MAX_CMD_PKT_SIZE; + } else if (xport_type == usrp::device3_impl::TX_DATA) { + const size_t default_frame_size = (link_speed == MAX_RATE_10GIGE ? + MPMD_UDP_10GE_DEFAULT_SEND_FRAME_SIZE : + MPMD_UDP_1GE_DEFAULT_SEND_FRAME_SIZE); default_buff_args.send_frame_size = - xport_args.cast<size_t>("send_frame_size", get_mtu(uhd::TX_DIRECTION)); + xport_args.cast<size_t>("send_frame_size", + std::min(default_frame_size, send_mtu)); + default_buff_args.num_send_frames = + xport_args.cast<size_t>("num_send_frames", + default_buff_args.num_send_frames); + default_buff_args.send_buff_size = + xport_args.cast<size_t>("send_buff_size", + default_buff_args.send_buff_size); + } else if (xport_type == usrp::device3_impl::RX_DATA) { + const size_t default_frame_size = (link_speed == MAX_RATE_10GIGE ? + MPMD_UDP_10GE_DEFAULT_RECV_FRAME_SIZE : + MPMD_UDP_1GE_DEFAULT_RECV_FRAME_SIZE); + default_buff_args.recv_frame_size = + xport_args.cast<size_t>("recv_frame_size", + std::min(default_frame_size, recv_mtu)); + default_buff_args.num_recv_frames = + xport_args.cast<size_t>("num_recv_frames", + default_buff_args.num_recv_frames); + default_buff_args.recv_buff_size = + xport_args.cast<size_t>("recv_buff_size", + default_buff_args.recv_buff_size); } transport::udp_zero_copy::buff_params buff_params; auto recv = transport::udp_zero_copy::make(xport_info["ipv4"], xport_info["port"], default_buff_args, - buff_params, - xport_args); + buff_params); const uint16_t port = recv->get_local_port(); const std::string src_ip_addr = recv->get_local_addr(); xport_info["src_port"] = std::to_string(port); diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index 76759acb3..1113374f5 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -869,9 +869,12 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t& dev_addr) _tree->create<std::string>(mb_path / "codename").set("Yetti"); //////////////////////////////////////////////////////////////////// - // discover ethernet interfaces, frame sizes, and link rates + // discover interfaces, frame sizes, and link rates //////////////////////////////////////////////////////////////////// - if (mb.xport_path == "eth") { + if (mb.xport_path == "nirio") { + _max_frame_sizes.recv_frame_size = PCIE_RX_DATA_FRAME_SIZE; + _max_frame_sizes.send_frame_size = PCIE_TX_DATA_FRAME_SIZE; + } else if (mb.xport_path == "eth") { double link_max_rate = 0.0; // Discover ethernet interfaces @@ -1315,12 +1318,17 @@ uhd::both_xports_t x300_impl::make_transport(const uhd::sid_t& address, { const size_t mb_index = address.get_dst_addr() - x300::DST_ADDR; mboard_members_t& mb = _mb[mb_index]; - const uhd::device_addr_t& xport_args = (xport_type == CTRL) ? uhd::device_addr_t() - : args; zero_copy_xport_params default_buff_args; both_xports_t xports; xports.endianness = mb.if_pkt_is_big_endian ? ENDIANNESS_BIG : ENDIANNESS_LITTLE; + + // Calculate MTU based on MTU in args and device limitations + const size_t send_mtu = args.cast<size_t>("mtu", + get_mtu(mb_index, uhd::TX_DIRECTION)); + const size_t recv_mtu = args.cast<size_t>("mtu", + get_mtu(mb_index, uhd::RX_DIRECTION)); + if (mb.xport_path == "nirio") { xports.lossless = true; xports.send_sid = @@ -1350,26 +1358,30 @@ uhd::both_xports_t x300_impl::make_transport(const uhd::sid_t& address, } // Create a virtual async message transport xports.recv = mb.async_msg_dma_xport->make_stream(xports.recv_sid.get_dst()); - } else { - // Transport for data stream - default_buff_args.send_frame_size = (xport_type == TX_DATA) - ? x300::PCIE_TX_DATA_FRAME_SIZE - : x300::PCIE_MSG_FRAME_SIZE; - - default_buff_args.recv_frame_size = (xport_type == RX_DATA) - ? x300::PCIE_RX_DATA_FRAME_SIZE - : x300::PCIE_MSG_FRAME_SIZE; - - default_buff_args.num_send_frames = (xport_type == TX_DATA) - ? x300::PCIE_TX_DATA_NUM_FRAMES - : x300::PCIE_MSG_NUM_FRAMES; - - default_buff_args.num_recv_frames = (xport_type == RX_DATA) - ? x300::PCIE_RX_DATA_NUM_FRAMES - : x300::PCIE_MSG_NUM_FRAMES; - + } else if (xport_type == TX_DATA) { + default_buff_args.send_frame_size = args.cast<size_t>( + "send_frame_size", std::min(send_mtu, + x300::PCIE_TX_DATA_FRAME_SIZE)); + default_buff_args.num_send_frames = args.cast<size_t>( + "num_send_frames", x300::PCIE_TX_DATA_NUM_FRAMES); + default_buff_args.send_buff_size = args.cast<size_t>( + "send_buff_size", 0); + default_buff_args.recv_frame_size = x300::PCIE_MSG_FRAME_SIZE; + default_buff_args.num_recv_frames = x300::PCIE_MSG_NUM_FRAMES; xports.recv = nirio_zero_copy::make( - mb.rio_fpga_interface, dma_channel_num, default_buff_args, xport_args); + mb.rio_fpga_interface, dma_channel_num, default_buff_args); + } else if (xport_type == RX_DATA) { + default_buff_args.send_frame_size = x300::PCIE_MSG_FRAME_SIZE; + default_buff_args.num_send_frames = x300::PCIE_MSG_NUM_FRAMES; + default_buff_args.recv_frame_size = args.cast<size_t>( + "recv_frame_size", std::min(recv_mtu, + x300::PCIE_RX_DATA_FRAME_SIZE)); + default_buff_args.num_recv_frames = args.cast<size_t>( + "num_recv_frames", x300::PCIE_RX_DATA_NUM_FRAMES); + default_buff_args.recv_buff_size = args.cast<size_t>( + "recv_buff_size", 0); + xports.recv = nirio_zero_copy::make( + mb.rio_fpga_interface, dma_channel_num, default_buff_args); } xports.send = xports.recv; @@ -1413,22 +1425,42 @@ uhd::both_xports_t x300_impl::make_transport(const uhd::sid_t& address, xports.recv_sid = xports.send_sid.reversed(); // Set size and number of frames - size_t system_max_send_frame_size = (size_t)_max_frame_sizes.send_frame_size; - size_t system_max_recv_frame_size = (size_t)_max_frame_sizes.recv_frame_size; - default_buff_args.send_frame_size = xport_args.cast<size_t>("send_frame_size", - std::min(system_max_send_frame_size, x300::ETH_MSG_FRAME_SIZE)); - default_buff_args.recv_frame_size = xport_args.cast<size_t>("recv_frame_size", - std::min(system_max_recv_frame_size, x300::ETH_MSG_FRAME_SIZE)); - default_buff_args.num_recv_frames = - xport_args.cast<size_t>("num_recv_frames", x300::ETH_MSG_NUM_FRAMES); - default_buff_args.num_send_frames = - xport_args.cast<size_t>("num_send_frames", x300::ETH_MSG_NUM_FRAMES); + default_buff_args.send_frame_size = std::min(send_mtu, + x300::ETH_MSG_FRAME_SIZE); + default_buff_args.recv_frame_size = std::min(recv_mtu, + x300::ETH_MSG_FRAME_SIZE); + default_buff_args.num_recv_frames = x300::ETH_MSG_NUM_FRAMES; + default_buff_args.num_send_frames = x300::ETH_MSG_NUM_FRAMES; if (xport_type == CTRL) { // 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 = 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 + ? x300::GE_DATA_FRAME_SEND_SIZE + : x300::XGE_DATA_FRAME_SEND_SIZE; + default_buff_args.send_frame_size = + args.cast<size_t>("send_frame_size", + std::min(default_frame_size, send_mtu)); + default_buff_args.num_send_frames = + args.cast<size_t>("num_send_frames", + default_buff_args.num_send_frames); + default_buff_args.send_buff_size = + args.cast<size_t>("send_buff_size", 0); + } else if (xport_type == RX_DATA) { + size_t default_frame_size = conn.link_rate == x300::MAX_RATE_1GIGE + ? x300::GE_DATA_FRAME_RECV_SIZE + : x300::XGE_DATA_FRAME_RECV_SIZE; + default_buff_args.recv_frame_size = + args.cast<size_t>("recv_frame_size", + std::min(default_frame_size, recv_mtu)); + default_buff_args.num_recv_frames = + args.cast<size_t>("num_recv_frames", + default_buff_args.num_recv_frames); + default_buff_args.recv_buff_size = + args.cast<size_t>("recv_buff_size", 0); } int dpdk_port_id = dpdk_ctx.get_route(conn.addr); @@ -1436,13 +1468,15 @@ uhd::both_xports_t x300_impl::make_transport(const uhd::sid_t& address, throw uhd::runtime_error( "Could not find a DPDK port with route to " + conn.addr); } - auto recv = transport::dpdk_zero_copy::make(dpdk_ctx, - (const unsigned int)dpdk_port_id, + auto recv = transport::dpdk_zero_copy::make( + dpdk_ctx, + (const unsigned int) dpdk_port_id, conn.addr, BOOST_STRINGIZE(X300_VITA_UDP_PORT), "0", default_buff_args, - xport_args); + uhd::device_addr_t() + ); xports.recv = recv; // Note: This is a type cast! xports.send = xports.recv; @@ -1504,12 +1538,10 @@ uhd::both_xports_t x300_impl::make_transport(const uhd::sid_t& address, xports.recv_sid = xports.send_sid.reversed(); // Set size and number of frames - size_t system_max_send_frame_size = (size_t)_max_frame_sizes.send_frame_size; - size_t system_max_recv_frame_size = (size_t)_max_frame_sizes.recv_frame_size; - default_buff_args.send_frame_size = - std::min(system_max_send_frame_size, x300::ETH_MSG_FRAME_SIZE); - default_buff_args.recv_frame_size = - std::min(system_max_recv_frame_size, x300::ETH_MSG_FRAME_SIZE); + default_buff_args.send_frame_size = std::min(send_mtu, + x300::ETH_MSG_FRAME_SIZE); + default_buff_args.recv_frame_size = std::min(recv_mtu, + x300::ETH_MSG_FRAME_SIZE); // Buffering is done in the socket buffers, so size them relative to // the link rate default_buff_args.send_buff_size = conn.link_rate / 50; // 20ms @@ -1531,33 +1563,29 @@ uhd::both_xports_t x300_impl::make_transport(const uhd::sid_t& address, size_t default_frame_size = conn.link_rate == x300::MAX_RATE_1GIGE ? x300::GE_DATA_FRAME_SEND_SIZE : x300::XGE_DATA_FRAME_SEND_SIZE; - default_buff_args.send_frame_size = args.cast<size_t>("send_frame_size", - std::min(default_frame_size, system_max_send_frame_size)); - if (default_buff_args.send_frame_size > system_max_send_frame_size) { - UHD_LOGGER_WARNING("X300") - << boost::format("Requested send_frame_size of %d exceeds the " - "maximum allowed on the %s connection. Using %d.") - % default_buff_args.send_frame_size % conn.addr - % system_max_send_frame_size; - default_buff_args.send_frame_size = system_max_send_frame_size; - } + default_buff_args.send_frame_size = + args.cast<size_t>("send_frame_size", + std::min(default_frame_size, send_mtu)); + default_buff_args.num_send_frames = + args.cast<size_t>("num_send_frames", + default_buff_args.num_send_frames); + default_buff_args.send_buff_size = + args.cast<size_t>("send_buff_size", + default_buff_args.send_buff_size); } else if (xport_type == RX_DATA) { size_t default_frame_size = conn.link_rate == x300::MAX_RATE_1GIGE ? x300::GE_DATA_FRAME_RECV_SIZE : x300::XGE_DATA_FRAME_RECV_SIZE; - default_buff_args.recv_frame_size = args.cast<size_t>("recv_frame_size", - std::min(default_frame_size, system_max_recv_frame_size)); - if (default_buff_args.recv_frame_size > system_max_recv_frame_size) { - UHD_LOGGER_WARNING("X300") - << boost::format("Requested recv_frame_size of %d exceeds the " - "maximum allowed on the %s connection. Using %d.") - % default_buff_args.recv_frame_size % conn.addr - % system_max_recv_frame_size; - default_buff_args.recv_frame_size = system_max_recv_frame_size; - } + default_buff_args.recv_frame_size = + args.cast<size_t>("recv_frame_size", + std::min(default_frame_size, recv_mtu)); + // set some buffers so the offload thread actually offloads the + // socket I/O default_buff_args.num_recv_frames = - 2; // set some buffers so the offload thread actually offloads the socket - // I/O + args.cast<size_t>("num_recv_frames", 2); + default_buff_args.recv_buff_size = + args.cast<size_t>("recv_buff_size", + default_buff_args.recv_buff_size); } // make a new transport - fpga has no idea how to talk to us on this yet @@ -1565,8 +1593,7 @@ uhd::both_xports_t x300_impl::make_transport(const uhd::sid_t& address, xports.recv = udp_zero_copy::make(conn.addr, BOOST_STRINGIZE(X300_VITA_UDP_PORT), default_buff_args, - buff_params, - xport_args); + buff_params); // Create a threaded transport for the receive chain only // Note that this shouldn't affect PCIe @@ -1992,14 +2019,10 @@ 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) +size_t x300_impl::get_mtu(const size_t /*mb_index*/, const uhd::direction_t dir) { - if (_mb[mb_index].xport_path == "nirio") { - return (dir == RX_DIRECTION ? x300::PCIE_RX_DATA_FRAME_SIZE - : x300::PCIE_TX_DATA_FRAME_SIZE); - } - return (dir == RX_DIRECTION) ? _max_frame_sizes.recv_frame_size - : _max_frame_sizes.send_frame_size; + return (dir == RX_DIRECTION) ? _max_frame_sizes.recv_frame_size : + _max_frame_sizes.send_frame_size; } /*********************************************************************** |