aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/include/uhd/rfnoc/sink_block_ctrl_base.hpp4
-rw-r--r--host/include/uhd/rfnoc/source_block_ctrl_base.hpp8
-rw-r--r--host/include/uhd/transport/zero_copy.hpp10
-rw-r--r--host/lib/rfnoc/graph_impl.cpp5
-rw-r--r--host/lib/rfnoc/sink_block_ctrl_base.cpp4
-rw-r--r--host/lib/rfnoc/source_block_ctrl_base.cpp10
-rw-r--r--host/lib/transport/super_recv_packet_handler.hpp2
-rw-r--r--host/lib/transport/super_send_packet_handler.hpp8
-rw-r--r--host/lib/transport/udp_common.hpp9
-rw-r--r--host/lib/transport/udp_zero_copy.cpp54
-rw-r--r--host/lib/usrp/device3/device3_impl.hpp18
-rw-r--r--host/lib/usrp/device3/device3_io_impl.cpp163
-rw-r--r--host/lib/usrp/x300/x300_impl.cpp347
-rw-r--r--host/lib/usrp/x300/x300_impl.hpp31
-rw-r--r--host/lib/usrp/x300/x300_io_impl.cpp16
15 files changed, 355 insertions, 334 deletions
diff --git a/host/include/uhd/rfnoc/sink_block_ctrl_base.hpp b/host/include/uhd/rfnoc/sink_block_ctrl_base.hpp
index f90361cf1..57c398ce3 100644
--- a/host/include/uhd/rfnoc/sink_block_ctrl_base.hpp
+++ b/host/include/uhd/rfnoc/sink_block_ctrl_base.hpp
@@ -80,8 +80,8 @@ public:
* \param block_port Set up flow control for a stream coming in on this particular block port.
*/
virtual void configure_flow_control_in(
- size_t bytes,
- size_t block_port=0
+ const size_t bytes,
+ const size_t block_port=0
);
/*! Configure the behaviour for errors on incoming packets
diff --git a/host/include/uhd/rfnoc/source_block_ctrl_base.hpp b/host/include/uhd/rfnoc/source_block_ctrl_base.hpp
index 39e7411f3..c9976b774 100644
--- a/host/include/uhd/rfnoc/source_block_ctrl_base.hpp
+++ b/host/include/uhd/rfnoc/source_block_ctrl_base.hpp
@@ -111,10 +111,10 @@ public:
* not sufficient to set the flow control, and as such is rarely used.
*/
virtual void configure_flow_control_out(
- bool enable_output,
- size_t buf_size_bytes,
- size_t pkt_limit=0,
- size_t block_port=0,
+ const bool enable_output,
+ const size_t buf_size_bytes,
+ const size_t pkt_limit=0,
+ const size_t block_port=0,
const uhd::sid_t &sid=uhd::sid_t()
);
diff --git a/host/include/uhd/transport/zero_copy.hpp b/host/include/uhd/transport/zero_copy.hpp
index 73d1686b8..4218ab2f9 100644
--- a/host/include/uhd/transport/zero_copy.hpp
+++ b/host/include/uhd/transport/zero_copy.hpp
@@ -128,10 +128,20 @@ namespace uhd{ namespace transport{
* Transport parameters
*/
struct zero_copy_xport_params {
+ zero_copy_xport_params() :
+ recv_frame_size(0),
+ send_frame_size(0),
+ num_recv_frames(0),
+ num_send_frames(0),
+ recv_buff_size(0),
+ send_buff_size(0)
+ { /* NOP */ }
size_t recv_frame_size;
size_t send_frame_size;
size_t num_recv_frames;
size_t num_send_frames;
+ size_t recv_buff_size;
+ size_t send_buff_size;
};
/*!
diff --git a/host/lib/rfnoc/graph_impl.cpp b/host/lib/rfnoc/graph_impl.cpp
index a2e0e64f4..d9e069993 100644
--- a/host/lib/rfnoc/graph_impl.cpp
+++ b/host/lib/rfnoc/graph_impl.cpp
@@ -139,11 +139,12 @@ void graph_impl::connect(
src_block_port
);
// On the same crossbar, use lots of FC packets
- size_t bytes_per_response = std::ceil<size_t>(buf_size_bytes / uhd::rfnoc::DEFAULT_FC_XBAR_RESPONSE_FREQ);
+ size_t bytes_per_response = buf_size_bytes / uhd::rfnoc::DEFAULT_FC_XBAR_RESPONSE_FREQ;
// Over the network, use less or we'd flood the transport
if (sid.get_src_addr() != sid.get_dst_addr()) {
- bytes_per_response = std::ceil<size_t>(buf_size_bytes / uhd::rfnoc::DEFAULT_FC_TX_RESPONSE_FREQ);
+ bytes_per_response = buf_size_bytes / uhd::rfnoc::DEFAULT_FC_TX_RESPONSE_FREQ;
}
+ UHD_ASSERT_THROW(bytes_per_response != 0);
dst->configure_flow_control_in(
bytes_per_response,
dst_block_port
diff --git a/host/lib/rfnoc/sink_block_ctrl_base.cpp b/host/lib/rfnoc/sink_block_ctrl_base.cpp
index 1562e134b..d14fe2f38 100644
--- a/host/lib/rfnoc/sink_block_ctrl_base.cpp
+++ b/host/lib/rfnoc/sink_block_ctrl_base.cpp
@@ -52,8 +52,8 @@ size_t sink_block_ctrl_base::get_fifo_size(size_t block_port) const {
}
void sink_block_ctrl_base::configure_flow_control_in(
- size_t bytes,
- size_t block_port
+ const size_t bytes,
+ const size_t block_port
) {
UHD_RFNOC_BLOCK_TRACE() << boost::format("sink_block_ctrl_base::configure_flow_control_in(bytes=%d)") % bytes;
diff --git a/host/lib/rfnoc/source_block_ctrl_base.cpp b/host/lib/rfnoc/source_block_ctrl_base.cpp
index afec6ba1b..0f1c31e4f 100644
--- a/host/lib/rfnoc/source_block_ctrl_base.cpp
+++ b/host/lib/rfnoc/source_block_ctrl_base.cpp
@@ -77,10 +77,10 @@ void source_block_ctrl_base::set_destination(
}
void source_block_ctrl_base::configure_flow_control_out(
- bool enable_fc_output,
- size_t buf_size_bytes,
- size_t pkt_limit,
- size_t block_port,
+ const bool enable_fc_output,
+ const size_t buf_size_bytes,
+ const size_t pkt_limit,
+ const size_t block_port,
UHD_UNUSED(const uhd::sid_t &sid)
) {
UHD_RFNOC_BLOCK_TRACE() << "source_block_ctrl_base::configure_flow_control_out() buf_size_bytes==" << buf_size_bytes;
@@ -113,7 +113,7 @@ void source_block_ctrl_base::configure_flow_control_out(
//based flow control
const bool enable_byte_fc = (buf_size_bytes != 0);
const bool enable_pkt_cnt_fc = (pkt_limit != 0);
- const size_t config = enable_fc_output + (enable_byte_fc << 1) + (enable_pkt_cnt_fc << 2);
+ const uint32_t config = (enable_fc_output ? 1 : 0) | (enable_byte_fc << 1) | (enable_pkt_cnt_fc << 2);
//Resize the FC window.
//Precondition: No data can be buffered upstream.
diff --git a/host/lib/transport/super_recv_packet_handler.hpp b/host/lib/transport/super_recv_packet_handler.hpp
index fcb333a04..ea02f367d 100644
--- a/host/lib/transport/super_recv_packet_handler.hpp
+++ b/host/lib/transport/super_recv_packet_handler.hpp
@@ -392,7 +392,7 @@ private:
#endif
//bounds check before extract
- size_t num_packet_words32 = buff->size()/sizeof(uint32_t);
+ const size_t num_packet_words32 = buff->size()/sizeof(uint32_t);
if (num_packet_words32 <= _header_offset_words32){
throw std::runtime_error("recv buffer smaller than vrt packet offset");
}
diff --git a/host/lib/transport/super_send_packet_handler.hpp b/host/lib/transport/super_send_packet_handler.hpp
index 5cba570a7..b90ea8afd 100644
--- a/host/lib/transport/super_send_packet_handler.hpp
+++ b/host/lib/transport/super_send_packet_handler.hpp
@@ -47,11 +47,11 @@ namespace sph {
**********************************************************************/
class send_packet_handler{
public:
- typedef boost::function<managed_send_buffer::sptr(double)> get_buff_type;
- typedef boost::function<void(void)> post_send_cb_type;
- typedef boost::function<bool(uhd::async_metadata_t &, const double)> async_receiver_type;
+ typedef std::function<managed_send_buffer::sptr(double)> get_buff_type;
+ typedef std::function<void(void)> post_send_cb_type;
+ typedef std::function<bool(uhd::async_metadata_t &, const double)> async_receiver_type;
typedef void(*vrt_packer_type)(uint32_t *, vrt::if_packet_info_t &);
- //typedef boost::function<void(uint32_t *, vrt::if_packet_info_t &)> vrt_packer_type;
+ //typedef std::function<void(uint32_t *, vrt::if_packet_info_t &)> vrt_packer_type;
/*!
* Make a new packet handler for send
diff --git a/host/lib/transport/udp_common.hpp b/host/lib/transport/udp_common.hpp
index e21d1fcc8..19457903b 100644
--- a/host/lib/transport/udp_common.hpp
+++ b/host/lib/transport/udp_common.hpp
@@ -13,8 +13,13 @@
namespace uhd{ namespace transport{
- // Jumbo frames are limited to 9000;
- static const size_t MAX_ETHERNET_MTU = 9000;
+ // Jumbo frames can be up to 9600 bytes;
+ static const size_t MAX_ETHERNET_MTU = 9600;
+
+#if defined(UHD_PLATFORM_MACOS) || defined(UHD_PLATFORM_BSD)
+ // MacOS limits socket buffer size to 1 Mib
+ static const size_t MAX_BUFF_SIZE_ETH_MACOS = 0x100000; //1Mib
+#endif
typedef boost::shared_ptr<boost::asio::ip::udp::socket> socket_sptr;
diff --git a/host/lib/transport/udp_zero_copy.cpp b/host/lib/transport/udp_zero_copy.cpp
index 29dbd6c1e..3b3760334 100644
--- a/host/lib/transport/udp_zero_copy.cpp
+++ b/host/lib/transport/udp_zero_copy.cpp
@@ -22,9 +22,6 @@ using namespace uhd;
using namespace uhd::transport;
namespace asio = boost::asio;
-//A reasonable number of frames for send/recv and async/sync
-//static const size_t DEFAULT_NUM_FRAMES = 32;
-
/***********************************************************************
* Check registry for correct fast-path setting (windows only)
**********************************************************************/
@@ -211,7 +208,12 @@ public:
}
//set size for internal socket buffer
- template <typename Opt> size_t resize_buff(size_t num_bytes){
+ template <typename Opt> size_t resize_buff(size_t num_bytes)
+ {
+ #if defined(UHD_PLATFORM_MACOS) || defined(UHD_PLATFORM_BSD)
+ //limit buffer resize on macos or it will error
+ num_bytes = std::min(num_bytes, MAX_BUFF_SIZE_ETH_MACOS);
+ #endif
Opt option(num_bytes);
_socket->set_option(option);
return get_buff_size<Opt>();
@@ -316,26 +318,31 @@ udp_zero_copy::sptr udp_zero_copy::make(
xport_params.num_recv_frames = size_t(hints.cast<double>("num_recv_frames", default_buff_args.num_recv_frames));
xport_params.send_frame_size = size_t(hints.cast<double>("send_frame_size", default_buff_args.send_frame_size));
xport_params.num_send_frames = size_t(hints.cast<double>("num_send_frames", default_buff_args.num_send_frames));
+ xport_params.recv_buff_size = size_t(hints.cast<double>("recv_buff_size", default_buff_args.recv_buff_size));
+ xport_params.send_buff_size = size_t(hints.cast<double>("send_buff_size", default_buff_args.send_buff_size));
- //extract buffer size hints from the device addr
- size_t usr_recv_buff_size = size_t(hints.cast<double>("recv_buff_size", xport_params.num_recv_frames * MAX_ETHERNET_MTU));
- size_t usr_send_buff_size = size_t(hints.cast<double>("send_buff_size", xport_params.num_send_frames * MAX_ETHERNET_MTU));
-
- if (hints.has_key("recv_buff_size")) {
- if (usr_recv_buff_size < xport_params.num_recv_frames * MAX_ETHERNET_MTU) {
- throw uhd::value_error((boost::format(
- "recv_buff_size must be equal to or greater than %d")
- % (xport_params.num_recv_frames * MAX_ETHERNET_MTU)).str());
- }
+ // Preserve legacy defaults
+ if (xport_params.recv_buff_size == 0) {
+ xport_params.recv_buff_size = xport_params.num_recv_frames * xport_params.recv_frame_size;
+ }
+ if (xport_params.send_buff_size == 0) {
+ xport_params.send_buff_size = xport_params.num_recv_frames * xport_params.send_frame_size;
}
+
+ // Resize receive buffer due to known issue where Intel X710 uses full MTU for every packet regardless of actual size
+ xport_params.recv_buff_size = xport_params.recv_buff_size * MAX_ETHERNET_MTU / xport_params.recv_frame_size;
- if (hints.has_key("send_buff_size")) {
- if (usr_send_buff_size < xport_params.num_send_frames * MAX_ETHERNET_MTU) {
- throw uhd::value_error((boost::format(
- "send_buff_size must be equal to or greater than %d")
- % (xport_params.num_send_frames * MAX_ETHERNET_MTU)).str());
+ #if defined(UHD_PLATFORM_MACOS) || defined(UHD_PLATFORM_BSD)
+ //limit default buffer size on macos to avoid the warning issued by resize_buff_helper
+ if (not hints.has_key("recv_buff_size") and xport_params.recv_buff_size > MAX_BUFF_SIZE_ETH_MACOS)
+ {
+ xport_params.recv_buff_size = MAX_BUFF_SIZE_ETH_MACOS;
}
- }
+ if (not hints.has_key("send_buff_size") and xport_params.send_buff_size > MAX_BUFF_SIZE_ETH_MACOS)
+ {
+ xport_params.send_buff_size = MAX_BUFF_SIZE_ETH_MACOS;
+ }
+ #endif
udp_zero_copy_asio_impl::sptr udp_trans(
new udp_zero_copy_asio_impl(addr, port, xport_params)
@@ -343,9 +350,12 @@ udp_zero_copy::sptr udp_zero_copy::make(
//call the helper to resize send and recv buffers
buff_params_out.recv_buff_size =
- resize_buff_helper<asio::socket_base::receive_buffer_size>(udp_trans, usr_recv_buff_size, "recv");
+ resize_buff_helper<asio::socket_base::receive_buffer_size>(udp_trans, xport_params.recv_buff_size, "recv");
buff_params_out.send_buff_size =
- resize_buff_helper<asio::socket_base::send_buffer_size> (udp_trans, usr_send_buff_size, "send");
+ resize_buff_helper<asio::socket_base::send_buffer_size> (udp_trans, xport_params.send_buff_size, "send");
+
+ // Resize usable amount of receive buffer due to known issue where Intel X710 uses full MTU for every packet regardless of actual size
+ buff_params_out.recv_buff_size = buff_params_out.recv_buff_size * xport_params.recv_frame_size / MAX_ETHERNET_MTU;
return udp_trans;
}
diff --git a/host/lib/usrp/device3/device3_impl.hpp b/host/lib/usrp/device3/device3_impl.hpp
index 580268e4a..11487b54c 100644
--- a/host/lib/usrp/device3/device3_impl.hpp
+++ b/host/lib/usrp/device3/device3_impl.hpp
@@ -56,13 +56,13 @@ public:
_terminator(terminator),
_data_xport(data_xport),
_async_msg_xport(async_msg_xport)
- {};
+ {}
~device3_send_packet_streamer()
{
// Make sure the async task is destroyed before the transports
_tx_async_msg_tasks.clear();
- };
+ }
uhd::rfnoc::tx_stream_terminator::sptr get_terminator()
{
@@ -92,9 +92,9 @@ public:
) :
uhd::transport::sph::recv_packet_streamer(max_num_samps),
_terminator(terminator),
- _xport(xport) {};
+ _xport(xport) {}
- ~device3_recv_packet_streamer() {};
+ ~device3_recv_packet_streamer() {}
both_xports_t get_xport()
{
@@ -145,7 +145,7 @@ public:
, rx_max_len_hdr(DEVICE3_RX_MAX_HDR_LEN)
, rx_fc_request_freq(DEVICE3_RX_FC_REQUEST_FREQ)
, tx_fc_response_freq(DEVICE3_TX_FC_RESPONSE_FREQ)
- {};
+ {}
};
/***********************************************************************
@@ -165,7 +165,7 @@ protected:
* Structors
**********************************************************************/
device3_impl();
- virtual ~device3_impl() {};
+ virtual ~device3_impl() {}
/***********************************************************************
* Streaming-related
@@ -196,11 +196,11 @@ protected:
const uhd::device_addr_t& args
) = 0;
- virtual uhd::device_addr_t get_tx_hints(size_t) { return uhd::device_addr_t(); };
- virtual uhd::device_addr_t get_rx_hints(size_t) { return uhd::device_addr_t(); };
+ virtual uhd::device_addr_t get_tx_hints(size_t) { return uhd::device_addr_t(); }
+ virtual uhd::device_addr_t get_rx_hints(size_t) { return uhd::device_addr_t(); }
//! Is called after a streamer is generated
- virtual void post_streamer_hooks(uhd::direction_t) {};
+ virtual void post_streamer_hooks(uhd::direction_t) {}
/***********************************************************************
* Channel-related
diff --git a/host/lib/usrp/device3/device3_io_impl.cpp b/host/lib/usrp/device3/device3_io_impl.cpp
index e4c38aca6..490f10c3c 100644
--- a/host/lib/usrp/device3/device3_io_impl.cpp
+++ b/host/lib/usrp/device3/device3_io_impl.cpp
@@ -158,7 +158,10 @@ struct rx_fc_cache_t
uint64_t seq_num;
sid_t sid;
zero_copy_if::sptr xport;
- endianness_t endianness;
+ std::function<uint32_t(uint32_t)> to_host;
+ std::function<uint32_t(uint32_t)> from_host;
+ std::function<void(const uint32_t *packet_buff, vrt::if_packet_info_t &)> unpack;
+ std::function<void(uint32_t *packet_buff, vrt::if_packet_info_t &)> pack;
};
/*! Determine the size of the flow control window in number of packets.
@@ -218,8 +221,8 @@ static size_t get_rx_flow_control_window(
* skip the counter update.
*/
static bool rx_flow_ctrl(
- boost::shared_ptr<rx_fc_cache_t> fc_cache,
- managed_buffer::sptr buff
+ boost::shared_ptr<rx_fc_cache_t> fc_cache,
+ managed_buffer::sptr buff
) {
// If the caller supplied a buffer
if (buff)
@@ -229,17 +232,12 @@ static bool rx_flow_ctrl(
packet_info.num_packet_words32 = buff->size()/sizeof(uint32_t);
const uint32_t *pkt = buff->cast<const uint32_t *>();
try {
- if (fc_cache->endianness == ENDIANNESS_BIG)
- {
- vrt::chdr::if_hdr_unpack_be(pkt, packet_info);
- } else {
- vrt::chdr::if_hdr_unpack_le(pkt, packet_info);
- }
+ fc_cache->unpack(pkt, packet_info);
}
catch(const std::exception &ex)
{
// Log and ignore
- UHD_LOGGER_ERROR("RX FLOW CTRL") << "Error unpacking flow control packet: " << ex.what() << std::endl;
+ UHD_LOGGER_ERROR("RX FLOW CTRL") << "Error unpacking packet: " << ex.what() << std::endl;
return true;
}
@@ -282,23 +280,13 @@ static bool rx_flow_ctrl(
packet_info.has_tsf = false;
packet_info.has_tlr = false;
- if (fc_cache->endianness == ENDIANNESS_BIG) {
- // Load Header:
- vrt::chdr::if_hdr_pack_be(pkt, packet_info);
- // Load Payload: Packet count, and byte count
- pkt[packet_info.num_header_words32+DEVICE3_FC_PACKET_COUNT_OFFSET] =
- uhd::htonx<uint32_t>(fc_cache->total_packets_consumed);
- pkt[packet_info.num_header_words32+DEVICE3_FC_BYTE_COUNT_OFFSET] =
- uhd::htonx<uint32_t>(fc_cache->total_bytes_consumed);
- } else {
- // Load Header:
- vrt::chdr::if_hdr_pack_le(pkt, packet_info);
- // Load Payload: Packet count, and byte count
- pkt[packet_info.num_header_words32+DEVICE3_FC_PACKET_COUNT_OFFSET] =
- uhd::htowx<uint32_t>(fc_cache->total_packets_consumed);
- pkt[packet_info.num_header_words32+DEVICE3_FC_BYTE_COUNT_OFFSET] =
- uhd::htowx<uint32_t>(fc_cache->total_bytes_consumed);
- }
+ // Load Header:
+ fc_cache->pack(pkt, packet_info);
+ // Load Payload: Packet count, and byte count
+ pkt[packet_info.num_header_words32+DEVICE3_FC_PACKET_COUNT_OFFSET] =
+ fc_cache->from_host(fc_cache->total_packets_consumed);
+ pkt[packet_info.num_header_words32+DEVICE3_FC_BYTE_COUNT_OFFSET] =
+ fc_cache->from_host(fc_cache->total_bytes_consumed);
//send the buffer over the interface
fc_buff->commit(sizeof(uint32_t)*(packet_info.num_packet_words32));
@@ -313,15 +301,11 @@ static bool rx_flow_ctrl(
*
*/
static void handle_rx_flowctrl_ack(
- boost::shared_ptr<rx_fc_cache_t> fc_cache,
- const uint32_t *payload
+ boost::shared_ptr<rx_fc_cache_t> fc_cache,
+ const uint32_t *payload
) {
- const uint32_t pkt_count = (fc_cache->endianness == ENDIANNESS_BIG) ?
- uhd::ntohx<uint32_t>(payload[0]) :
- uhd::wtohx<uint32_t>(payload[0]);
- const uint32_t byte_count = (fc_cache->endianness == ENDIANNESS_BIG) ?
- uhd::ntohx<uint32_t>(payload[1]) :
- uhd::wtohx<uint32_t>(payload[1]);
+ const uint32_t pkt_count = fc_cache->to_host(payload[0]);
+ const uint32_t byte_count = fc_cache->to_host(payload[1]);
if (fc_cache->total_bytes_consumed != byte_count)
{
UHD_LOGGER_DEBUG("device3")
@@ -362,13 +346,15 @@ struct tx_fc_cache_t
uint32_t window_size;
uint32_t fc_ack_seqnum;
bool fc_received;
+ std::function<uint32_t(uint32_t)> to_host;
+ std::function<uint32_t(uint32_t)> from_host;
+ std::function<void(const uint32_t *packet_buff, vrt::if_packet_info_t &)> unpack;
+ std::function<void(uint32_t *packet_buff, vrt::if_packet_info_t &)> pack;
};
static bool tx_flow_ctrl(
boost::shared_ptr<tx_fc_cache_t> fc_cache,
- zero_copy_if::sptr xport,
- uint32_t (*to_host)(uint32_t),
- void (*unpack)(const uint32_t *packet_buff, vrt::if_packet_info_t &),
+ zero_copy_if::sptr xport,
managed_buffer::sptr buff
) {
while (true)
@@ -395,7 +381,7 @@ static bool tx_flow_ctrl(
if_packet_info.num_packet_words32 = buff->size()/sizeof(uint32_t);
const uint32_t *packet_buff = buff->cast<const uint32_t *>();
try {
- unpack(packet_buff, if_packet_info);
+ fc_cache->unpack(packet_buff, if_packet_info);
}
catch(const std::exception &ex)
{
@@ -410,8 +396,8 @@ static bool tx_flow_ctrl(
}
const uint32_t *payload = &packet_buff[if_packet_info.num_header_words32];
- const uint32_t pkt_count = to_host(payload[0]);
- const uint32_t byte_count = to_host(payload[1]);
+ const uint32_t pkt_count = fc_cache->to_host(payload[0]);
+ const uint32_t byte_count = fc_cache->to_host(payload[1]);
// update the amount of space
fc_cache->last_byte_ack = byte_count;
@@ -426,9 +412,7 @@ static bool tx_flow_ctrl(
static void tx_flow_ctrl_ack(
boost::shared_ptr<tx_fc_cache_t> fc_cache,
zero_copy_if::sptr send_xport,
- sid_t send_sid,
- uint32_t (*from_host)(uint32_t),
- void (*pack)(uint32_t *packet_buff, vrt::if_packet_info_t &)
+ sid_t send_sid
) {
if (not fc_cache->fc_received)
{
@@ -462,7 +446,7 @@ static void tx_flow_ctrl_ack(
packet_info.has_tlr = false;
// Load Header:
- pack(pkt, packet_info);
+ fc_cache->pack(pkt, packet_info);
// Update counters to include this packet
size_t fc_ack_pkt_size = sizeof(uint32_t)*(packet_info.num_packet_words32);
@@ -476,9 +460,9 @@ static void tx_flow_ctrl_ack(
// Load Payload: Packet count, and byte count
pkt[packet_info.num_header_words32+DEVICE3_FC_PACKET_COUNT_OFFSET] =
- from_host(fc_cache->pkt_count);
+ fc_cache->from_host(fc_cache->pkt_count);
pkt[packet_info.num_header_words32+DEVICE3_FC_BYTE_COUNT_OFFSET] =
- from_host(fc_cache->byte_count);
+ fc_cache->from_host(fc_cache->byte_count);
// Send the buffer over the interface
fc_buff->commit(fc_ack_pkt_size);
@@ -506,7 +490,8 @@ struct async_tx_info_t
static void handle_tx_async_msgs(
boost::shared_ptr<async_tx_info_t> async_info,
zero_copy_if::sptr xport,
- endianness_t endianness,
+ uint32_t (*to_host)(uint32_t),
+ void (*unpack)(const uint32_t *packet_buff, vrt::if_packet_info_t &),
boost::function<double(void)> get_tick_rate
) {
managed_recv_buffer::sptr buff = xport->get_recv_buff();
@@ -521,19 +506,9 @@ static void handle_tx_async_msgs(
const uint32_t *packet_buff = buff->cast<const uint32_t *>();
//unpacking can fail
- uint32_t (*endian_conv)(uint32_t) = uhd::ntohx;
try
{
- if (endianness == ENDIANNESS_BIG)
- {
- vrt::chdr::if_hdr_unpack_be(packet_buff, if_packet_info);
- endian_conv = uhd::ntohx;
- }
- else
- {
- vrt::chdr::if_hdr_unpack_le(packet_buff, if_packet_info);
- endian_conv = uhd::wtohx;
- }
+ unpack(packet_buff, if_packet_info);
}
catch(const std::exception &ex)
{
@@ -549,7 +524,7 @@ static void handle_tx_async_msgs(
//fill in the async metadata
async_metadata_t metadata;
load_metadata_from_buff(
- endian_conv,
+ to_host,
metadata,
if_packet_info,
packet_buff,
@@ -681,14 +656,29 @@ rx_streamer::sptr device3_impl::get_rx_stream(const stream_args_t &args_)
boost::shared_ptr<rx_fc_cache_t> fc_cache(new rx_fc_cache_t());
fc_cache->sid = xport.send_sid;
fc_cache->xport = xport.send;
- fc_cache->endianness = xport.endianness;
fc_cache->interval = fc_handle_window;
+ if (xport.endianness == ENDIANNESS_BIG)
+ {
+ fc_cache->to_host = uhd::ntohx<uint32_t>;
+ fc_cache->from_host = uhd::htonx<uint32_t>;
+ fc_cache->pack = vrt::chdr::if_hdr_pack_be;
+ fc_cache->unpack = vrt::chdr::if_hdr_unpack_be;
+ }
+ else
+ {
+ fc_cache->to_host = uhd::wtohx<uint32_t>;
+ fc_cache->from_host = uhd::htowx<uint32_t>;
+ fc_cache->pack = vrt::chdr::if_hdr_pack_le;
+ fc_cache->unpack = vrt::chdr::if_hdr_unpack_le;
+ }
xport.recv = zero_copy_flow_ctrl::make
(
xport.recv,
NULL,
- [=](managed_buffer::sptr buff) {
- return rx_flow_ctrl(fc_cache, buff);
+ [fc_cache](managed_buffer::sptr buff) {
+ return rx_flow_ctrl(
+ fc_cache,
+ buff);
}
);
@@ -753,7 +743,7 @@ rx_streamer::sptr device3_impl::get_rx_stream(const stream_args_t &args_)
// Give the streamer a functor to handle flow control ACK messages
my_streamer->set_xport_handle_flowctrl_ack(
stream_i,
- [=](const uint32_t *payload) {
+ [fc_cache](const uint32_t *payload) {
handle_rx_flowctrl_ack(
fc_cache,
payload
@@ -764,7 +754,9 @@ rx_streamer::sptr device3_impl::get_rx_stream(const stream_args_t &args_)
//Give the streamer a functor to get the recv_buffer
my_streamer->set_xport_chan_get_buff(
stream_i,
- [=](double timeout) {return xport.recv->get_recv_buff(timeout);},
+ [xport](double timeout) {
+ return xport.recv->get_recv_buff(timeout);
+ },
true /*flush*/
);
@@ -774,7 +766,7 @@ rx_streamer::sptr device3_impl::get_rx_stream(const stream_args_t &args_)
boost::weak_ptr<uhd::rx_streamer> weak_ptr(my_streamer);
my_streamer->set_overflow_handler(
stream_i,
- [=]() {
+ [recv_terminator, weak_ptr, stream_i]() {
recv_terminator->handle_overrun(
weak_ptr,
stream_i);
@@ -784,7 +776,9 @@ rx_streamer::sptr device3_impl::get_rx_stream(const stream_args_t &args_)
//Give the streamer a functor issue stream cmd
my_streamer->set_issue_stream_cmd(
stream_i,
- [=](const stream_cmd_t& stream_cmd) {blk_ctrl->issue_stream_cmd(stream_cmd, block_port);}
+ [blk_ctrl, block_port](const stream_cmd_t& stream_cmd) {
+ blk_ctrl->issue_stream_cmd(stream_cmd, block_port);
+ }
);
}
@@ -913,14 +907,24 @@ tx_streamer::sptr device3_impl::get_tx_stream(const uhd::stream_args_t &args_)
);
// Add flow control transport
boost::shared_ptr<tx_fc_cache_t> fc_cache(new tx_fc_cache_t(fc_window));
+ if (xport.endianness == ENDIANNESS_BIG)
+ {
+ fc_cache->to_host = uhd::ntohx<uint32_t>;
+ fc_cache->from_host = uhd::htonx<uint32_t>;
+ fc_cache->pack = vrt::chdr::if_hdr_pack_be;
+ fc_cache->unpack = vrt::chdr::if_hdr_unpack_be;
+ } else {
+ fc_cache->to_host = uhd::wtohx<uint32_t>;
+ fc_cache->from_host = uhd::htowx<uint32_t>;
+ fc_cache->pack = vrt::chdr::if_hdr_pack_le;
+ fc_cache->unpack = vrt::chdr::if_hdr_unpack_le;
+ }
xport.send = zero_copy_flow_ctrl::make(
xport.send,
- [=](managed_buffer::sptr buff) {
+ [fc_cache, xport](managed_buffer::sptr buff) {
return tx_flow_ctrl(
fc_cache,
xport.recv,
- (xport.endianness == ENDIANNESS_BIG ? uhd::ntohx<uint32_t> : uhd::wtohx<uint32_t>),
- (xport.endianness == ENDIANNESS_BIG ? vrt::chdr::if_hdr_unpack_be : vrt::chdr::if_hdr_unpack_le),
buff);
},
NULL
@@ -1004,12 +1008,13 @@ tx_streamer::sptr device3_impl::get_tx_stream(const uhd::stream_args_t &args_)
async_tx_info->old_async_queue = _async_md;
task::sptr async_task = task::make(
- [=]() {
+ [async_tx_info, async_xport, xport, send_terminator]() {
handle_tx_async_msgs(
async_tx_info,
async_xport.recv,
- xport.endianness,
- [=]() {return send_terminator->get_tick_rate();}
+ xport.endianness == ENDIANNESS_BIG ? uhd::ntohx<uint32_t> : uhd::wtohx<uint32_t>,
+ xport.endianness == ENDIANNESS_BIG ? vrt::chdr::if_hdr_unpack_be : vrt::chdr::if_hdr_unpack_le,
+ [send_terminator]() {return send_terminator->get_tick_rate();}
);
}
);
@@ -1018,13 +1023,13 @@ tx_streamer::sptr device3_impl::get_tx_stream(const uhd::stream_args_t &args_)
//Give the streamer a functor to get the send buffer
my_streamer->set_xport_chan_get_buff(
stream_i,
- [=](const double timeout) {
+ [xport](const double timeout) {
return xport.send->get_send_buff(timeout);
}
);
//Give the streamer a functor handled received async messages
my_streamer->set_async_receiver(
- [=](uhd::async_metadata_t& md, const double timeout) {
+ [async_md](uhd::async_metadata_t& md, const double timeout) {
return async_md->pop_with_timed_wait(md, timeout);
}
);
@@ -1034,15 +1039,13 @@ tx_streamer::sptr device3_impl::get_tx_stream(const uhd::stream_args_t &args_)
my_streamer->set_xport_chan_post_send_cb(
stream_i,
- [=]() {
+ [fc_cache, xport]() {
tx_flow_ctrl_ack(
fc_cache,
xport.send,
- xport.send_sid,
- (xport.endianness == ENDIANNESS_BIG ? uhd::htonx<uint32_t> : uhd::htowx<uint32_t>),
- (xport.endianness == ENDIANNESS_BIG ? vrt::chdr::if_hdr_pack_be : vrt::chdr::if_hdr_pack_le)
+ xport.send_sid
);
- }
+ }
);
}
diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp
index 60be75f2b..d0915d592 100644
--- a/host/lib/usrp/x300/x300_impl.cpp
+++ b/host/lib/usrp/x300/x300_impl.cpp
@@ -473,8 +473,10 @@ void x300_impl::mboard_members_t::discover_eth(
// Choose the interface based on the index parity
if (i % 2 == 0) {
conn_iface.type = X300_IFACE_ETH0;
+ conn_iface.link_rate = loaded_fpga_image == "HG" ? X300_MAX_RATE_1GIGE : X300_MAX_RATE_10GIGE;
} else {
conn_iface.type = X300_IFACE_ETH1;
+ conn_iface.link_rate = X300_MAX_RATE_10GIGE;
}
break;
}
@@ -492,15 +494,19 @@ void x300_impl::mboard_members_t::discover_eth(
if (addr == boost::asio::ip::address_v4(
uint32_t(X300_DEFAULT_IP_ETH0_1G)).to_string()) {
conn_iface.type = X300_IFACE_ETH0;
+ conn_iface.link_rate = X300_MAX_RATE_1GIGE;
} else if (addr == boost::asio::ip::address_v4(
uint32_t(X300_DEFAULT_IP_ETH1_1G)).to_string()) {
conn_iface.type = X300_IFACE_ETH1;
+ conn_iface.link_rate = X300_MAX_RATE_1GIGE;
} else if (addr == boost::asio::ip::address_v4(
uint32_t(X300_DEFAULT_IP_ETH0_10G)).to_string()) {
conn_iface.type = X300_IFACE_ETH0;
+ conn_iface.link_rate = X300_MAX_RATE_10GIGE;
} else if (addr == boost::asio::ip::address_v4(
uint32_t(X300_DEFAULT_IP_ETH1_10G)).to_string()) {
conn_iface.type = X300_IFACE_ETH1;
+ conn_iface.link_rate = X300_MAX_RATE_10GIGE;
} else {
throw uhd::assertion_error(str(boost::format(
"X300 Initialization Error: Failed to match address %s with "
@@ -624,91 +630,6 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr)
if (key.find("send") != std::string::npos) mb.send_args[key] = dev_addr[key];
}
- if (mb.xport_path == "eth" ) {
- /* This is an ETH connection. Figure out what the maximum supported frame
- * size is for the transport in the up and down directions. The frame size
- * depends on the host PIC's NIC's MTU settings. To determine the frame size,
- * we test for support up to an expected "ceiling". If the user
- * specified a frame size, we use that frame size as the ceiling. If no
- * frame size was specified, we use the maximum UHD frame size.
- *
- * To optimize performance, the frame size should be greater than or equal
- * to the frame size that UHD uses so that frames don't get split across
- * multiple transmission units - this is why the limits passed into the
- * 'determine_max_frame_size' function are actually frame sizes. */
- frame_size_t req_max_frame_size;
- req_max_frame_size.recv_frame_size = (mb.recv_args.has_key("recv_frame_size")) \
- ? boost::lexical_cast<size_t>(mb.recv_args["recv_frame_size"]) \
- : X300_10GE_DATA_FRAME_MAX_SIZE;
- req_max_frame_size.send_frame_size = (mb.send_args.has_key("send_frame_size")) \
- ? boost::lexical_cast<size_t>(mb.send_args["send_frame_size"]) \
- : X300_10GE_DATA_FRAME_MAX_SIZE;
-
- #if defined UHD_PLATFORM_LINUX
- const std::string mtu_tool("ip link");
- #elif defined UHD_PLATFORM_WIN32
- const std::string mtu_tool("netsh");
- #else
- const std::string mtu_tool("ifconfig");
- #endif
-
- // Detect the frame size on the path to the USRP
- try {
- frame_size_t pri_frame_sizes = determine_max_frame_size(
- eth_addrs.at(0), req_max_frame_size
- );
-
- _max_frame_sizes = pri_frame_sizes;
- if (eth_addrs.size() > 1) {
- frame_size_t sec_frame_sizes = determine_max_frame_size(
- eth_addrs.at(1), req_max_frame_size
- );
-
- // Choose the minimum of the max frame sizes
- // to ensure we don't exceed any one of the links' MTU
- _max_frame_sizes.recv_frame_size = std::min(
- pri_frame_sizes.recv_frame_size,
- sec_frame_sizes.recv_frame_size
- );
-
- _max_frame_sizes.send_frame_size = std::min(
- pri_frame_sizes.send_frame_size,
- sec_frame_sizes.send_frame_size
- );
- }
- } catch(std::exception &e) {
- UHD_LOGGER_ERROR("X300") << e.what() ;
- }
-
- if ((mb.recv_args.has_key("recv_frame_size"))
- && (req_max_frame_size.recv_frame_size > _max_frame_sizes.recv_frame_size)) {
- UHD_LOGGER_WARNING("X300")
- << boost::format("You requested a receive frame size of (%lu) but your NIC's max frame size is (%lu).")
- % req_max_frame_size.recv_frame_size
- % _max_frame_sizes.recv_frame_size
- << boost::format("Please verify your NIC's MTU setting using '%s' or set the recv_frame_size argument appropriately.")
- % mtu_tool
- << "UHD will use the auto-detected max frame size for this connection."
- ;
- }
-
- if ((mb.recv_args.has_key("send_frame_size"))
- && (req_max_frame_size.send_frame_size > _max_frame_sizes.send_frame_size)) {
- UHD_LOGGER_WARNING("X300")
- << boost::format("You requested a send frame size of (%lu) but your NIC's max frame size is (%lu).")
- % req_max_frame_size.send_frame_size
- % _max_frame_sizes.send_frame_size
- << boost::format("Please verify your NIC's MTU setting using '%s' or set the send_frame_size argument appropriately.")
- % mtu_tool
- << "UHD will use the auto-detected max frame size for this connection."
- ;
- }
-
- _tree->create<size_t>(mb_path / "mtu/recv").set(_max_frame_sizes.recv_frame_size);
- _tree->create<size_t>(mb_path / "mtu/send").set(_max_frame_sizes.send_frame_size);
- _tree->create<double>(mb_path / "link_max_rate").set(X300_MAX_RATE_10GIGE);
- }
-
//create basic communication
UHD_LOGGER_DEBUG("X300") << "Setting up basic communication...";
if (mb.xport_path == "nirio") {
@@ -828,11 +749,129 @@ 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");
////////////////////////////////////////////////////////////////////
- // determine routing based on address match
+ // discover ethernet interfaces, frame sizes, and link rates
////////////////////////////////////////////////////////////////////
- if (mb.xport_path != "nirio") {
+ if (mb.xport_path == "eth" ) {
+ double link_max_rate = 0.0;
+
// Discover ethernet interfaces
mb.discover_eth(mb_eeprom, eth_addrs);
+
+ /* This is an ETH connection. Figure out what the maximum supported frame
+ * size is for the transport in the up and down directions. The frame size
+ * depends on the host PC's NIC's MTU settings. To determine the frame size,
+ * we test for support up to an expected "ceiling". If the user
+ * specified a frame size, we use that frame size as the ceiling. If no
+ * frame size was specified, we use the maximum UHD frame size.
+ *
+ * To optimize performance, the frame size should be greater than or equal
+ * to the frame size that UHD uses so that frames don't get split across
+ * multiple transmission units - this is why the limits passed into the
+ * 'determine_max_frame_size' function are actually frame sizes. */
+ frame_size_t req_max_frame_size;
+ req_max_frame_size.recv_frame_size = (mb.recv_args.has_key("recv_frame_size")) \
+ ? boost::lexical_cast<size_t>(mb.recv_args["recv_frame_size"]) \
+ : X300_DATA_FRAME_MAX_SIZE;
+ req_max_frame_size.send_frame_size = (mb.send_args.has_key("send_frame_size")) \
+ ? boost::lexical_cast<size_t>(mb.send_args["send_frame_size"]) \
+ : X300_DATA_FRAME_MAX_SIZE;
+
+ #if defined UHD_PLATFORM_LINUX
+ const std::string mtu_tool("ip link");
+ #elif defined UHD_PLATFORM_WIN32
+ const std::string mtu_tool("netsh");
+ #else
+ const std::string mtu_tool("ifconfig");
+ #endif
+
+ // Detect the frame size on the path to the USRP
+ try {
+ frame_size_t pri_frame_sizes = determine_max_frame_size(
+ eth_addrs.at(0), req_max_frame_size
+ );
+
+ _max_frame_sizes = pri_frame_sizes;
+ if (eth_addrs.size() > 1) {
+ frame_size_t sec_frame_sizes = determine_max_frame_size(
+ eth_addrs.at(1), req_max_frame_size
+ );
+
+ // Choose the minimum of the max frame sizes
+ // to ensure we don't exceed any one of the links' MTU
+ _max_frame_sizes.recv_frame_size = std::min(
+ pri_frame_sizes.recv_frame_size,
+ sec_frame_sizes.recv_frame_size
+ );
+
+ _max_frame_sizes.send_frame_size = std::min(
+ pri_frame_sizes.send_frame_size,
+ sec_frame_sizes.send_frame_size
+ );
+ }
+ } catch(std::exception &e) {
+ UHD_LOGGER_ERROR("X300") << e.what() ;
+ }
+
+ if ((mb.recv_args.has_key("recv_frame_size"))
+ && (req_max_frame_size.recv_frame_size > _max_frame_sizes.recv_frame_size)) {
+ UHD_LOGGER_WARNING("X300")
+ << boost::format("You requested a receive frame size of (%lu) but your NIC's max frame size is (%lu).")
+ % req_max_frame_size.recv_frame_size
+ % _max_frame_sizes.recv_frame_size
+
+ << boost::format("Please verify your NIC's MTU setting using '%s' or set the recv_frame_size argument appropriately.")
+ % mtu_tool
+ << "UHD will use the auto-detected max frame size for this connection."
+ ;
+ }
+
+ if ((mb.send_args.has_key("send_frame_size"))
+ && (req_max_frame_size.send_frame_size > _max_frame_sizes.send_frame_size)) {
+ UHD_LOGGER_WARNING("X300")
+ << boost::format("You requested a send frame size of (%lu) but your NIC's max frame size is (%lu).")
+ % req_max_frame_size.send_frame_size
+ % _max_frame_sizes.send_frame_size
+
+ << boost::format("Please verify your NIC's MTU setting using '%s' or set the send_frame_size argument appropriately.")
+ % mtu_tool
+ << "UHD will use the auto-detected max frame size for this connection."
+ ;
+ }
+
+ // Check frame sizes
+ for (auto conn : mb.eth_conns)
+ {
+ link_max_rate += conn.link_rate;
+
+ size_t rec_send_frame_size = conn.link_rate == X300_MAX_RATE_1GIGE ? X300_1GE_DATA_FRAME_SEND_SIZE : X300_10GE_DATA_FRAME_SEND_SIZE;
+ size_t rec_recv_frame_size = conn.link_rate == X300_MAX_RATE_1GIGE ? X300_1GE_DATA_FRAME_RECV_SIZE : X300_10GE_DATA_FRAME_RECV_SIZE;
+
+ if (_max_frame_sizes.send_frame_size < rec_send_frame_size)
+ {
+ UHD_LOGGER_WARNING("X300")
+ << boost::format("For the %s connection, UHD recommends a send frame size of at least %lu for best\nperformance, but your configuration will only allow %lu.")
+ % conn.addr
+ % rec_send_frame_size
+ % _max_frame_sizes.send_frame_size
+ << "This may negatively impact your maximum achievable sample rate.\nCheck the MTU on the interface and/or the send_frame_size argument."
+ ;
+ }
+
+ if (_max_frame_sizes.recv_frame_size < rec_recv_frame_size)
+ {
+ UHD_LOGGER_WARNING("X300")
+ << boost::format("For the %s connection, UHD recommends a receive frame size of at least %lu for best\nperformance, but your configuration will only allow %lu.")
+ % conn.addr
+ % rec_recv_frame_size
+ % _max_frame_sizes.recv_frame_size
+ << "This may negatively impact your maximum achievable sample rate.\nCheck the MTU on the interface and/or the recv_frame_size argument."
+ ;
+ }
+ }
+
+ _tree->create<size_t>(mb_path / "mtu/recv").set(_max_frame_sizes.recv_frame_size);
+ _tree->create<size_t>(mb_path / "mtu/send").set(_max_frame_sizes.send_frame_size);
+ _tree->create<double>(mb_path / "link_max_rate").set(link_max_rate);
}
////////////////////////////////////////////////////////////////////
@@ -1264,97 +1303,66 @@ uhd::both_xports_t x300_impl::make_transport(
xport_type == TX_DATA ? mb.next_tx_src_addr :
xport_type == RX_DATA ? mb.next_rx_src_addr :
mb.next_src_addr;
- std::string interface_addr = mb.eth_conns[next_src_addr].addr;
+ x300_eth_conn_t conn = mb.eth_conns[next_src_addr];
const uint32_t xbar_src_addr =
next_src_addr==0 ? X300_SRC_ADDR0 : X300_SRC_ADDR1;
const uint32_t xbar_src_dst =
- mb.eth_conns[next_src_addr].type==X300_IFACE_ETH0 ? X300_XB_DST_E0 : X300_XB_DST_E1;
- next_src_addr = (next_src_addr + 1) % mb.eth_conns.size();
+ conn.type==X300_IFACE_ETH0 ? X300_XB_DST_E0 : X300_XB_DST_E1;
+ if (xport_type != TX_DATA) next_src_addr = (next_src_addr + 1) % mb.eth_conns.size();
xports.send_sid = this->allocate_sid(mb, address, xbar_src_addr, xbar_src_dst);
xports.recv_sid = xports.send_sid.reversed();
- /* Determine what the recommended frame size is for this
- * connection type.*/
- size_t eth_data_rec_frame_size = 0;
-
- fs_path mboard_path = fs_path("/mboards") / mb_index / "link_max_rate";
-
- if (mb.loaded_fpga_image == "HG") {
- size_t max_link_rate = 0;
- if (xbar_src_dst == X300_XB_DST_E0) {
- eth_data_rec_frame_size = X300_1GE_DATA_FRAME_MAX_SIZE;
- max_link_rate += X300_MAX_RATE_1GIGE;
- } else if (xbar_src_dst == X300_XB_DST_E1) {
- eth_data_rec_frame_size = X300_10GE_DATA_FRAME_MAX_SIZE;
- max_link_rate += X300_MAX_RATE_10GIGE;
+ // 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.num_send_frames = 1; // never need multiple frames on send
+ default_buff_args.num_recv_frames = 1; // only need multiple frames with offload thread
+ default_buff_args.send_buff_size = conn.link_rate / 50; // 20ms
+ default_buff_args.recv_buff_size = std::max(conn.link_rate / 50, X300_ETH_MSG_NUM_FRAMES * X300_ETH_MSG_FRAME_SIZE); // enough to hold greater of 20ms or number of msg frames
+ if (xport_type == TX_DATA)
+ {
+ size_t default_frame_size = conn.link_rate == X300_MAX_RATE_1GIGE ? X300_1GE_DATA_FRAME_SEND_SIZE : X300_10GE_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;
}
- _tree->access<double>(mboard_path).set(max_link_rate);
- } else if (mb.loaded_fpga_image == "XG" or mb.loaded_fpga_image == "XA") {
- eth_data_rec_frame_size = X300_10GE_DATA_FRAME_MAX_SIZE;
- size_t max_link_rate = X300_MAX_RATE_10GIGE;
- max_link_rate *= mb.eth_conns.size();
- _tree->access<double>(mboard_path).set(max_link_rate);
- } else if (mb.loaded_fpga_image == "HA") {
- eth_data_rec_frame_size = X300_1GE_DATA_FRAME_MAX_SIZE;
- size_t max_link_rate = X300_MAX_RATE_1GIGE;
- max_link_rate *= mb.eth_conns.size();
- _tree->access<double>(mboard_path).set(max_link_rate);
- }
-
- if (eth_data_rec_frame_size == 0) {
- throw uhd::runtime_error("Unable to determine ETH link type.");
}
+ else if (xport_type == RX_DATA)
+ {
+ size_t default_frame_size = conn.link_rate == X300_MAX_RATE_1GIGE ? X300_1GE_DATA_FRAME_RECV_SIZE : X300_10GE_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;
+ }
+ // set default buffering for data
+ default_buff_args.recv_buff_size = conn.link_rate / 10; // 100ms
+ default_buff_args.num_recv_frames = 2; // set some buffers so the offload thread actually offloads the socket I/O
- /* Print a warning if the system's max available frame size is less than the most optimal
- * frame size for this type of connection. */
- if (_max_frame_sizes.send_frame_size < eth_data_rec_frame_size) {
- UHD_LOGGER_WARNING("X300")
- << boost::format("For this connection, UHD recommends a send frame size of at least %lu for best\nperformance, but your system's MTU will only allow %lu.")
- % eth_data_rec_frame_size
- % _max_frame_sizes.send_frame_size
- << "This may negatively impact your maximum achievable sample rate."
- ;
+ // set buffering for flow control messages
+ default_buff_args.num_send_frames = 1;
}
- if (_max_frame_sizes.recv_frame_size < eth_data_rec_frame_size) {
- UHD_LOGGER_WARNING("X300")
- << boost::format("For this connection, UHD recommends a receive frame size of at least %lu for best\nperformance, but your system's MTU will only allow %lu.")
- % eth_data_rec_frame_size
- % _max_frame_sizes.recv_frame_size
- << "This may negatively impact your maximum achievable sample rate."
- ;
- }
-
- 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;
-
- // Make sure frame sizes do not exceed the max available value supported by UHD
- default_buff_args.send_frame_size =
- (xport_type == TX_DATA)
- ? std::min(system_max_send_frame_size, X300_10GE_DATA_FRAME_MAX_SIZE)
- : std::min(system_max_send_frame_size, X300_ETH_MSG_FRAME_SIZE);
-
- default_buff_args.recv_frame_size =
- (xport_type == RX_DATA)
- ? std::min(system_max_recv_frame_size, X300_10GE_DATA_FRAME_MAX_SIZE)
- : std::min(system_max_recv_frame_size, X300_ETH_MSG_FRAME_SIZE);
-
- default_buff_args.num_send_frames =
- (xport_type == TX_DATA)
- ? X300_ETH_DATA_NUM_FRAMES
- : X300_ETH_MSG_NUM_FRAMES;
-
- default_buff_args.num_recv_frames =
- (xport_type == RX_DATA)
- ? X300_ETH_DATA_NUM_FRAMES
- : X300_ETH_MSG_NUM_FRAMES;
-
//make a new transport - fpga has no idea how to talk to us on this yet
udp_zero_copy::buff_params buff_params;
-
xports.recv = udp_zero_copy::make(
- interface_addr,
+ conn.addr,
BOOST_STRINGIZE(X300_VITA_UDP_PORT),
default_buff_args,
buff_params,
@@ -1365,12 +1373,12 @@ uhd::both_xports_t x300_impl::make_transport(
if (xport_type == RX_DATA) {
xports.recv = zero_copy_recv_offload::make(
xports.recv,
- X300_THREAD_BUFFER_TIMEOUT
+ X300_RECV_OFFLOAD_BUFFER_TIMEOUT
);
}
xports.send = xports.recv;
- //For the UDP transport the buffer size if the size of the socket buffer
+ //For the UDP transport the buffer size is the size of the socket buffer
//in the kernel
xports.recv_buff_size = buff_params.recv_buff_size;
xports.send_buff_size = buff_params.send_buff_size;
@@ -1381,9 +1389,8 @@ uhd::both_xports_t x300_impl::make_transport(
//send a mini packet with SID into the ZPU
//ZPU will reprogram the ethernet framer
- UHD_LOGGER_TRACE("X300")
- << "programming packet for new xport on "
- << interface_addr << " sid " << xports.send_sid;
+ UHD_LOGGER_DEBUG("X300") << "programming packet for new xport on "
+ << conn.addr << " sid " << xports.send_sid ;
//YES, get a __send__ buffer from the __recv__ socket
//-- this is the only way to program the framer for recv:
managed_send_buffer::sptr buff = xports.recv->get_send_buff();
@@ -1691,9 +1698,9 @@ x300_impl::frame_size_t x300_impl::determine_max_frame_size(const std::string &a
//Reducing range of (min,max) by setting max value to 10gig max_frame_size as larger sizes are not supported
size_t min_recv_frame_size = sizeof(x300_mtu_t);
- size_t max_recv_frame_size = std::min(user_frame_size.recv_frame_size, X300_10GE_DATA_FRAME_MAX_SIZE) & size_t(~3);
+ size_t max_recv_frame_size = std::min(user_frame_size.recv_frame_size, X300_DATA_FRAME_MAX_SIZE) & size_t(~3);
size_t min_send_frame_size = sizeof(x300_mtu_t);
- size_t max_send_frame_size = std::min(user_frame_size.send_frame_size, X300_10GE_DATA_FRAME_MAX_SIZE) & size_t(~3);
+ size_t max_send_frame_size = std::min(user_frame_size.send_frame_size, X300_DATA_FRAME_MAX_SIZE) & size_t(~3);
UHD_LOGGER_DEBUG("X300") << "Determining maximum frame size... ";
while (min_recv_frame_size < max_recv_frame_size)
diff --git a/host/lib/usrp/x300/x300_impl.hpp b/host/lib/usrp/x300/x300_impl.hpp
index e67242aa3..dfe038107 100644
--- a/host/lib/usrp/x300/x300_impl.hpp
+++ b/host/lib/usrp/x300/x300_impl.hpp
@@ -39,9 +39,6 @@ static const std::string X300_DEFAULT_CLOCK_SOURCE = "internal";
static const double X300_DEFAULT_TICK_RATE = 200e6; //Hz
static const double X300_BUS_CLOCK_RATE = 187.5e6; //Hz
-static const size_t X300_RX_SW_BUFF_SIZE_ETH = 0x2000000;//32MiB For an ~8k frame size any size >32MiB is just wasted buffer space
-static const size_t X300_RX_SW_BUFF_SIZE_ETH_MACOS = 0x100000; //1Mib
-
//The FIFO closest to the DMA controller is 1023 elements deep for RX and 1029 elements deep for TX
//where an element is 8 bytes. The buffers (number of frames * frame size) must be aligned to the
//memory page size. For the control, we are getting lucky because 64 frames * 256 bytes each aligns
@@ -50,22 +47,25 @@ static const size_t X300_RX_SW_BUFF_SIZE_ETH_MACOS = 0x100000; //1Mib
static const size_t X300_PCIE_RX_DATA_FRAME_SIZE = 4096; //bytes
static const size_t X300_PCIE_RX_DATA_NUM_FRAMES = 4096;
static const size_t X300_PCIE_TX_DATA_FRAME_SIZE = 4096; //bytes
-static const size_t X300_PCIE_TX_DATA_NUM_FRAMES = 4096;
+static const size_t X300_PCIE_TX_DATA_NUM_FRAMES = 4096;
static const size_t X300_PCIE_MSG_FRAME_SIZE = 256; //bytes
static const size_t X300_PCIE_MSG_NUM_FRAMES = 64;
static const size_t X300_PCIE_MAX_CHANNELS = 6;
static const size_t X300_PCIE_MAX_MUXED_CTRL_XPORTS = 32;
static const size_t X300_PCIE_MAX_MUXED_ASYNC_XPORTS = 4;
-//Reduced to 4000 to make sure flow control packets are not blocked for too long at high rates
-static const size_t X300_10GE_DATA_FRAME_MAX_SIZE = 4000; // CHDR packet size in bytes
-static const size_t X300_1GE_DATA_FRAME_MAX_SIZE = 1472; // CHDR packet size in bytes
+static const size_t X300_DATA_FRAME_MAX_SIZE = 8000; // CHDR packet size in bytes
+
+// Ethernet frame sizes
+static const size_t X300_10GE_DATA_FRAME_SEND_SIZE = 4000; // Reduced to make sure flow control packets are not blocked for too long at high rates
+static const size_t X300_10GE_DATA_FRAME_RECV_SIZE = 8000;
+static const size_t X300_1GE_DATA_FRAME_SEND_SIZE = 1472;
+static const size_t X300_1GE_DATA_FRAME_RECV_SIZE = 1472;
static const size_t X300_ETH_MSG_FRAME_SIZE = uhd::transport::udp_simple::mtu; //bytes
+static const size_t X300_ETH_MSG_NUM_FRAMES = 64;
-static const double X300_THREAD_BUFFER_TIMEOUT = 0.1; // Time in seconds
+static const double X300_RECV_OFFLOAD_BUFFER_TIMEOUT = 0.1; //seconds
-static const size_t X300_ETH_MSG_NUM_FRAMES = 64;
-static const size_t X300_ETH_DATA_NUM_FRAMES = 32;
static const double X300_DEFAULT_SYSREF_RATE = 10e6;
// Limit the number of initialization threads
@@ -74,12 +74,12 @@ static const size_t X300_MAX_INIT_THREADS = 10;
static const size_t X300_MAX_RATE_PCIE = 800000000; // bytes/s
static const size_t X300_MAX_RATE_10GIGE = (size_t)( // bytes/s
10e9 / 8 * // wire speed multiplied by percentage of packets that is sample data
- ( float(X300_10GE_DATA_FRAME_MAX_SIZE - uhd::usrp::DEVICE3_TX_MAX_HDR_LEN) /
- float(X300_10GE_DATA_FRAME_MAX_SIZE + 8 /* UDP header */ + 20 /* Ethernet header length */ )));
+ ( float(X300_DATA_FRAME_MAX_SIZE - uhd::usrp::DEVICE3_TX_MAX_HDR_LEN) /
+ float(X300_DATA_FRAME_MAX_SIZE + 8 /* UDP header */ + 20 /* Ethernet header length */ )));
static const size_t X300_MAX_RATE_1GIGE = (size_t)( // bytes/s
- 10e9 / 8 * // wire speed multiplied by percentage of packets that is sample data
- ( float(X300_1GE_DATA_FRAME_MAX_SIZE - uhd::usrp::DEVICE3_TX_MAX_HDR_LEN) /
- float(X300_1GE_DATA_FRAME_MAX_SIZE + 8 /* UDP header */ + 20 /* Ethernet header length */ )));
+ 1e9 / 8 * // wire speed multiplied by percentage of packets that is sample data
+ ( float(X300_DATA_FRAME_MAX_SIZE - uhd::usrp::DEVICE3_TX_MAX_HDR_LEN) /
+ float(X300_DATA_FRAME_MAX_SIZE + 8 /* UDP header */ + 20 /* Ethernet header length */ )));
#define X300_RADIO_DEST_PREFIX_TX 0
@@ -106,6 +106,7 @@ struct x300_eth_conn_t
{
std::string addr;
x300_eth_iface_t type;
+ size_t link_rate;
};
diff --git a/host/lib/usrp/x300/x300_io_impl.cpp b/host/lib/usrp/x300/x300_io_impl.cpp
index af5aa7c9e..d833b3715 100644
--- a/host/lib/usrp/x300/x300_io_impl.cpp
+++ b/host/lib/usrp/x300/x300_io_impl.cpp
@@ -17,22 +17,6 @@ using namespace uhd::usrp;
device_addr_t x300_impl::get_rx_hints(size_t mb_index)
{
device_addr_t rx_hints = _mb[mb_index].recv_args;
- // (default to a large recv buff)
- if (not rx_hints.has_key("recv_buff_size"))
- {
- if (_mb[mb_index].xport_path != "nirio") {
- //For the ethernet transport, the buffer has to be set before creating
- //the transport because it is independent of the frame size and # frames
- //For nirio, the buffer size is not configurable by the user
- #if defined(UHD_PLATFORM_MACOS) || defined(UHD_PLATFORM_BSD)
- //limit buffer resize on macos or it will error
- rx_hints["recv_buff_size"] = std::to_string(X300_RX_SW_BUFF_SIZE_ETH_MACOS);
- #elif defined(UHD_PLATFORM_LINUX) || defined(UHD_PLATFORM_WIN32)
- //set to half-a-second of buffering at max rate
- rx_hints["recv_buff_size"] = std::to_string(X300_RX_SW_BUFF_SIZE_ETH);
- #endif
- }
- }
return rx_hints;
}