diff options
Diffstat (limited to 'host/lib')
| -rw-r--r-- | host/lib/rfnoc/graph_impl.cpp | 5 | ||||
| -rw-r--r-- | host/lib/rfnoc/sink_block_ctrl_base.cpp | 4 | ||||
| -rw-r--r-- | host/lib/rfnoc/source_block_ctrl_base.cpp | 10 | ||||
| -rw-r--r-- | host/lib/transport/super_recv_packet_handler.hpp | 2 | ||||
| -rw-r--r-- | host/lib/transport/super_send_packet_handler.hpp | 8 | ||||
| -rw-r--r-- | host/lib/transport/udp_common.hpp | 9 | ||||
| -rw-r--r-- | host/lib/transport/udp_zero_copy.cpp | 54 | ||||
| -rw-r--r-- | host/lib/usrp/device3/device3_impl.hpp | 18 | ||||
| -rw-r--r-- | host/lib/usrp/device3/device3_io_impl.cpp | 163 | ||||
| -rw-r--r-- | host/lib/usrp/x300/x300_impl.cpp | 347 | ||||
| -rw-r--r-- | host/lib/usrp/x300/x300_impl.hpp | 31 | ||||
| -rw-r--r-- | host/lib/usrp/x300/x300_io_impl.cpp | 16 | 
12 files changed, 339 insertions, 328 deletions
| 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;  } | 
