// // Copyright 2017 Ettus Research, National Instruments Company // // SPDX-License-Identifier: GPL-3.0-or-later // #include "mpmd_impl.hpp" #include "mpmd_xport_mgr.hpp" #include "mpmd_xport_ctrl_base.hpp" #include "mpmd_xport_ctrl_udp.hpp" #ifdef HAVE_LIBERIO # include "mpmd_xport_ctrl_liberio.hpp" #endif uhd::dict uhd::mpmd::xport::filter_args( const uhd::device_addr_t& args, const std::string& prefix ) { uhd::dict filtered_args; for (const std::string& key : args.keys()) { if (key.find(prefix) != std::string::npos) { filtered_args[key] = args[key]; } } return filtered_args; } using namespace uhd::mpmd::xport; class mpmd_xport_mgr_impl : public mpmd_xport_mgr { public: mpmd_xport_mgr_impl( const uhd::device_addr_t& mb_args ) : _mb_args(mb_args) { // nop } /************************************************************************** * API (see mpmd_xport_mgr.hpp) *************************************************************************/ uhd::both_xports_t make_transport( const xport_info_list_t &xport_info_list, const uhd::usrp::device3_impl::xport_type_t xport_type, const uhd::device_addr_t& xport_args, xport_info_t& xport_info_out ) { for (const auto &xport_info : xport_info_list) { require_xport_mgr(xport_info.at("type")); } // Run our incredibly smart selection algorithm xport_info_out = select_xport_option(xport_info_list); const std::string xport_medium = xport_info_out.at("type"); UHD_LOG_TRACE("MPMD", __func__ << "(): xport medium is " << xport_medium); UHD_ASSERT_THROW(_xport_ctrls.count(xport_medium) > 0); UHD_ASSERT_THROW(_xport_ctrls.at(xport_medium)); // When we've picked our preferred option, pass it to the transport // implementation for execution: return _xport_ctrls.at(xport_medium)->make_transport( xport_info_out, xport_type, xport_args ); } size_t get_mtu( const uhd::direction_t dir ) const { if (_xport_ctrls.empty()) { UHD_LOG_WARNING("MPMD", "Cannot determine MTU, no transport controls have been " "established!"); return 0; } size_t mtu = ~size_t(0); for (const auto &xport_ctrl_pair : _xport_ctrls) { mtu = std::min(mtu, xport_ctrl_pair.second->get_mtu(dir)); } return mtu; } private: /************************************************************************** * Private methods / helpers *************************************************************************/ /*! Picks a transport option based on available data * * \param xport_info_list List of available options, they all need to be * valid choices. * * \returns One element of \p xport_info_list based on a selection * algorithm. */ xport_info_t select_xport_option( const xport_info_list_t &xport_info_list ) const { for (const auto& xport_info : xport_info_list) { const std::string xport_medium = xport_info.at("type"); if (_xport_ctrls.count(xport_medium) != 0 and _xport_ctrls.at(xport_medium) and _xport_ctrls.at(xport_medium)->is_valid(xport_info)) { return xport_info; } } throw uhd::runtime_error("Could not select a transport option! " "Either a transport hint was not specified or the specified " "hint does not support communication with RFNoC blocks."); } //! Create an instance of an xport manager implementation // // \param xport_medium "UDP" or "liberio" // \param mb_args Device args mpmd_xport_ctrl_base::uptr make_mgr_impl( const std::string &xport_medium, const uhd::device_addr_t& mb_args ) const { if (xport_medium == "UDP") { return mpmd_xport_ctrl_base::uptr( new mpmd_xport_ctrl_udp(mb_args) ); #ifdef HAVE_LIBERIO } else if (xport_medium == "liberio") { return mpmd_xport_ctrl_base::uptr( new mpmd_xport_ctrl_liberio(mb_args) ); #endif } else { UHD_LOG_WARNING("MPMD", "Cannot instantiate transport medium " << xport_medium); return nullptr; } } //! This will try to make _xport_ctrls contain a valid transport manager // for \p xport_medium // // When this function returns, it will be possible to access // this->_xport_ctrls[xport_medium]. // // \param xport_medium Type of transport, e.g. "UDP", "liberio", ... // // \throws uhd::key_error if \p xport_medium is not known or registered void require_xport_mgr(const std::string &xport_medium) { if (_xport_ctrls.count(xport_medium) == 0) { UHD_LOG_TRACE("MPMD", "Instantiating transport manager `" << xport_medium << "'"); auto mgr_impl = make_mgr_impl(xport_medium, _mb_args); if (mgr_impl) { _xport_ctrls[xport_medium] = std::move(mgr_impl); } } } /************************************************************************** * Private attributes *************************************************************************/ //! Cache available xport manager implementations // // Should only every be populated by require_xport_mgr() std::unordered_map _xport_ctrls; //! Motherboard args, can contain things like 'recv_buff_size' const uhd::device_addr_t _mb_args; }; mpmd_xport_mgr::uptr mpmd_xport_mgr::make( const uhd::device_addr_t& mb_args ) { return mpmd_xport_mgr::uptr(new mpmd_xport_mgr_impl(mb_args)); }