aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2017-12-01 16:14:11 -0800
committerMartin Braun <martin.braun@ettus.com>2017-12-22 15:05:58 -0800
commit87dbcd9f1a5b2b464c27af56c3a91ab00f66c441 (patch)
tree62ccd5be210d94862071aecda5ec3e667b036148
parenta927a364c5b07387be3a849b74546b98ba84db84 (diff)
downloaduhd-87dbcd9f1a5b2b464c27af56c3a91ab00f66c441.tar.gz
uhd-87dbcd9f1a5b2b464c27af56c3a91ab00f66c441.tar.bz2
uhd-87dbcd9f1a5b2b464c27af56c3a91ab00f66c441.zip
mpmd: Refactor MPM transport architecture, use managers
This splits up the transport code in mpmd_impl across multiple classes to properly leverage the request_xport/commit_xport API in MPM. Different types of transport (UDP, liberio) use their own distinct classes, which are generated dynamically on request. This is a true refactoring despite the large amount of changes; there are no functional differences. Reviewed-By: Brent Stapleton <brent.stapleton@ettus.com> Reviewed-By: Trung Tran <trung.tran@ettus.com> Reviewed-By: Ashish Chaudhari <ashish.chaudhari@ettus.com>
-rw-r--r--host/lib/usrp/mpmd/CMakeLists.txt15
-rw-r--r--host/lib/usrp/mpmd/mpmd_impl.cpp48
-rw-r--r--host/lib/usrp/mpmd/mpmd_impl.hpp130
-rw-r--r--host/lib/usrp/mpmd/mpmd_mboard_impl.cpp130
-rw-r--r--host/lib/usrp/mpmd/mpmd_xport.cpp283
-rw-r--r--host/lib/usrp/mpmd/mpmd_xport_ctrl_base.hpp45
-rw-r--r--host/lib/usrp/mpmd/mpmd_xport_ctrl_liberio.cpp145
-rw-r--r--host/lib/usrp/mpmd/mpmd_xport_ctrl_liberio.hpp59
-rw-r--r--host/lib/usrp/mpmd/mpmd_xport_ctrl_udp.cpp103
-rw-r--r--host/lib/usrp/mpmd/mpmd_xport_ctrl_udp.hpp46
-rw-r--r--host/lib/usrp/mpmd/mpmd_xport_mgr.cpp148
-rw-r--r--host/lib/usrp/mpmd/mpmd_xport_mgr.hpp95
-rw-r--r--mpm/python/usrp_mpm/xports/xportmgr_udp.py11
13 files changed, 852 insertions, 406 deletions
diff --git a/host/lib/usrp/mpmd/CMakeLists.txt b/host/lib/usrp/mpmd/CMakeLists.txt
index 5bc8e2d08..e4ce0e316 100644
--- a/host/lib/usrp/mpmd/CMakeLists.txt
+++ b/host/lib/usrp/mpmd/CMakeLists.txt
@@ -17,14 +17,23 @@
IF(ENABLE_MPMD)
IF(ENABLE_LIBERIO)
- MESSAGE(STATUS "Compiling MPM with liberio support...")
- ADD_DEFINITIONS(-DHAVE_LIBERIO)
+ MESSAGE(STATUS "Compiling MPMD with liberio support...")
+ ADD_DEFINITIONS(-DHAVE_LIBERIO)
ENDIF(ENABLE_LIBERIO)
LIBUHD_APPEND_SOURCES(
+ ${CMAKE_CURRENT_SOURCE_DIR}/mpmd_image_loader.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mpmd_impl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mpmd_mboard_impl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mpmd_xport.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/mpmd_image_loader.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/mpmd_xport_mgr.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/mpmd_xport_ctrl_udp.cpp
)
+
+ IF(ENABLE_LIBERIO)
+ LIBUHD_APPEND_SOURCES(
+ ${CMAKE_CURRENT_SOURCE_DIR}/mpmd_xport_ctrl_liberio.cpp
+ )
+ ENDIF(ENABLE_LIBERIO)
+
ENDIF(ENABLE_MPMD)
diff --git a/host/lib/usrp/mpmd/mpmd_impl.cpp b/host/lib/usrp/mpmd/mpmd_impl.cpp
index d020e3546..92f8039a4 100644
--- a/host/lib/usrp/mpmd/mpmd_impl.cpp
+++ b/host/lib/usrp/mpmd/mpmd_impl.cpp
@@ -1,18 +1,7 @@
//
-// Copyright 2017 Ettus Research (National Instruments)
+// Copyright 2017 Ettus Research, a National Instruments Company
//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
+// SPDX-License-Identifier: GPL-3.0
//
#include "mpmd_impl.hpp"
@@ -39,6 +28,7 @@
#include <vector>
using namespace uhd;
+using namespace uhd::mpmd;
namespace {
/*************************************************************************
@@ -274,6 +264,14 @@ namespace {
}
}
+
+/*****************************************************************************
+ * Static class attributes
+ ****************************************************************************/
+const std::string mpmd_impl::MPM_RPC_GET_LAST_ERROR_CMD = "get_last_error";
+const std::string mpmd_impl::MPM_DISCOVERY_CMD = "MPM-DISC";
+const std::string mpmd_impl::MPM_ECHO_CMD = "MPM-ECHO";
+
/*****************************************************************************
* Structors
****************************************************************************/
@@ -285,15 +283,6 @@ mpmd_impl::mpmd_impl(const device_addr_t& device_args)
UHD_LOGGER_INFO("MPMD")
<< "Initializing device with args: " << device_args.to_string();
- for (const std::string& key : device_args.keys()) {
- if (key.find("recv") != std::string::npos) {
- recv_args[key] = device_args[key];
- }
- if (key.find("send") != std::string::npos) {
- send_args[key] = device_args[key];
- }
- }
-
const device_addrs_t mb_args = separate_device_addr(device_args);
_mb.reserve(mb_args.size());
@@ -506,13 +495,18 @@ device_addrs_t mpmd_find_with_addr(const device_addr_t& hint_)
}
transport::udp_simple::sptr comm = transport::udp_simple::make_broadcast(
- query_addr, std::to_string(MPM_DISCOVERY_PORT));
+ query_addr, std::to_string(mpmd_impl::MPM_DISCOVERY_PORT));
comm->send(
- boost::asio::buffer(&MPM_DISCOVERY_CMD, sizeof(MPM_DISCOVERY_CMD)));
+ boost::asio::buffer(
+ mpmd_impl::MPM_DISCOVERY_CMD.c_str(),
+ mpmd_impl::MPM_DISCOVERY_CMD.size()
+ )
+ );
while (true) {
- char buff[4096] = {};
- const size_t nbytes = comm->recv( // TODO make sure we don't buf overflow
- boost::asio::buffer(buff),
+ const size_t MAX_MTU = 8000;
+ char buff[MAX_MTU] = {};
+ const size_t nbytes = comm->recv(
+ boost::asio::buffer(buff, MAX_MTU),
MPMD_FIND_TIMEOUT
);
if (nbytes == 0) {
diff --git a/host/lib/usrp/mpmd/mpmd_impl.hpp b/host/lib/usrp/mpmd/mpmd_impl.hpp
index 3143378dd..7b81be0f6 100644
--- a/host/lib/usrp/mpmd/mpmd_impl.hpp
+++ b/host/lib/usrp/mpmd/mpmd_impl.hpp
@@ -1,22 +1,13 @@
//
-// Copyright 2017 Ettus Research (National Instruments)
+// Copyright 2017 Ettus Research, a National Instruments Company
//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
+// SPDX-License-Identifier: GPL-3.0
//
#ifndef INCLUDED_MPMD_IMPL_HPP
#define INCLUDED_MPMD_IMPL_HPP
+
+#include "mpmd_xport_mgr.hpp"
#include "../../utils/rpc.hpp"
#include "../device3/device3_impl.hpp"
#include <uhd/stream.hpp>
@@ -25,17 +16,9 @@
#include <uhd/utils/tasks.hpp>
#include <uhd/transport/muxed_zero_copy_if.hpp>
#include <map>
+#include <memory>
-static const size_t MPMD_RX_SW_BUFF_SIZE_ETH = 0x2000000;//32MiB For an ~8k frame size any size >32MiB is just wasted buffer space
-static const size_t MPMD_RX_SW_BUFF_SIZE_ETH_MACOS = 0x100000; //1Mib
-
-static const size_t MPM_DISCOVERY_PORT = 49600;
-static const size_t MPM_RPC_PORT = 49601;
-static const char MPM_RPC_GET_LAST_ERROR_CMD[] = "get_last_error";
-static const char MPM_DISCOVERY_CMD[] = "MPM-DISC";
-static const char MPM_ECHO_CMD[] = "MPM-ECHO";
-static const size_t MPMD_10GE_DATA_FRAME_MAX_SIZE = 8000; // CHDR packet size in bytes
-
+namespace uhd { namespace mpmd {
/*! Stores all attributes specific to a single MPM device
*/
@@ -93,28 +76,42 @@ class mpmd_mboard_impl
/*************************************************************************
* API
************************************************************************/
- uhd::sid_t allocate_sid(const uint16_t port,
- const uhd::sid_t address,
- const uint32_t xbar_src_addr,
- const uint32_t xbar_src_dst,
- const uint32_t dst_addr
- );
-
//! Configure a crossbar to have a certain local address
void set_xbar_local_addr(const size_t xbar_index, const size_t local_addr);
//! Return the local address of a given crossbar
- size_t get_xbar_local_addr(const size_t xbar_index) {
+ size_t get_xbar_local_addr(const size_t xbar_index) const {
return xbar_local_addrs.at(xbar_index);
}
+ //! Device-specific make_transport implementation
+ //
+ // A major difference to the mpmd_impl::make_transport() is the meaning of
+ // the first argument (\p sid). mpmd_impl::make_transport() will add a
+ // source part to the SID which needs to be taken into account in this
+ // function.
+ //
+ // \param sid The full SID of this transport (UHD to device)
+ // \param xport_type Transport type (CTRL, RX_DATA, ...)
+ // \param args Any kind of args passed in via get_?x_stream()
+ uhd::both_xports_t make_transport(
+ const sid_t& sid,
+ usrp::device3_impl::xport_type_t xport_type,
+ const uhd::device_addr_t& args
+ );
+
+
+ uhd::device_addr_t get_rx_hints() const;
+ uhd::device_addr_t get_tx_hints() const;
+
private:
/*************************************************************************
* Private methods
************************************************************************/
/*! Renew the claim onto the device.
*
- * This is meant to be called repeatedly, e.g., using a UHD task.
+ * This is meant to be called repeatedly, e.g., using a UHD task. See also
+ * _claimer_task.
*/
bool claim();
@@ -130,10 +127,11 @@ class mpmd_mboard_impl
// what we use when addressing a crossbar in a CHDR header.
std::vector<size_t> xbar_local_addrs;
-
/*! Continuously reclaims the device.
*/
uhd::task::sptr _claimer_task;
+
+ uhd::mpmd::xport::mpmd_xport_mgr::uptr _xport_mgr;
};
@@ -145,16 +143,36 @@ class mpmd_mboard_impl
*/
class mpmd_impl : public uhd::usrp::device3_impl
{
- public:
+public:
+ //! Port on which the discovery process is listening
+ static const size_t MPM_DISCOVERY_PORT = 49600;
+ //! Port on which the RPC process is listening
+ static const size_t MPM_RPC_PORT = 49601;
+ //! This is the command that needs to be sent to the discovery port to
+ // trigger a response.
+ static const std::string MPM_DISCOVERY_CMD;
+ //! This is the command that will let you measure ping responses from the
+ // device via the discovery process. Useful for MTU discovery.
+ static const std::string MPM_ECHO_CMD;
+ //! This is the RPC command that will return the last known error from MPM.
+ static const std::string MPM_RPC_GET_LAST_ERROR_CMD;
+
+ /**************************************************************************
+ * Structors
+ ************************************************************************/
mpmd_impl(const uhd::device_addr_t& device_addr);
~mpmd_impl();
+ /**************************************************************************
+ * API
+ ************************************************************************/
uhd::both_xports_t make_transport(const uhd::sid_t&,
uhd::usrp::device3_impl::xport_type_t,
const uhd::device_addr_t&);
private:
uhd::device_addr_t get_rx_hints(size_t mb_index);
+ uhd::device_addr_t get_tx_hints(size_t mb_index);
/*************************************************************************
* Private methods/helpers
@@ -185,49 +203,14 @@ class mpmd_impl : public uhd::usrp::device3_impl
*/
size_t allocate_xbar_local_addr();
- /*! Return the index of the motherboard carrying the crossbar at \p remote_addr
+ /*! Return the index of the motherboard given the local address of a
+ * crossbar
*/
- size_t identify_mboard_by_sid(const size_t remote_addr);
-
- using xport_info_t = std::map<std::string, std::string>;
- using xport_info_list_t = std::vector<std::map<std::string, std::string>>;
-
- uhd::both_xports_t make_transport_udp(
- const size_t mb_index,
- xport_info_t &xport_info,
- const xport_type_t xport_type,
- const uhd::device_addr_t& xport_args
- );
-
-#ifdef HAVE_LIBERIO
- /*! Create a muxed liberio transport for control packets */
- uhd::transport::muxed_zero_copy_if::sptr make_muxed_liberio_xport(
- const std::string &tx_dev,
- const std::string &rx_dev,
- const uhd::transport::zero_copy_xport_params &buff_args,
- const size_t max_muxed_ports
- );
-
- uhd::both_xports_t make_transport_liberio(
- const size_t mb_index,
- xport_info_t &xport_info,
- const xport_type_t xport_type,
- const uhd::device_addr_t& xport_args
- );
-#endif
+ size_t identify_mboard_by_xbar_addr(const size_t xbar_addr) const;
/*************************************************************************
* Private attributes
************************************************************************/
- // FIXME move the next two into their own transport manager class
- //! Control transport for one liberio connection
- uhd::transport::muxed_zero_copy_if::sptr _ctrl_dma_xport;
- //! Control transport for one liberio connection
- uhd::transport::muxed_zero_copy_if::sptr _async_msg_dma_xport;
-
- uhd::dict<std::string, std::string> recv_args;
- uhd::dict<std::string, std::string> send_args;
-
//! Stores the args with which the device was originally initialized
uhd::device_addr_t _device_args;
//! Stores a list of mboard references
@@ -237,9 +220,12 @@ class mpmd_impl : public uhd::usrp::device3_impl
// No-one touches this except allocate_xbar_local_addr(), gotcha?
size_t _xbar_local_addr_ctr = 2;
+ // TODO make sure this can't wrap
size_t _sid_framer;
};
+}} /* namespace uhd::mpmd */
+
uhd::device_addrs_t mpmd_find(const uhd::device_addr_t& hint_);
#endif /* INCLUDED_MPMD_IMPL_HPP */
diff --git a/host/lib/usrp/mpmd/mpmd_mboard_impl.cpp b/host/lib/usrp/mpmd/mpmd_mboard_impl.cpp
index 337504927..1038be26d 100644
--- a/host/lib/usrp/mpmd/mpmd_mboard_impl.cpp
+++ b/host/lib/usrp/mpmd/mpmd_mboard_impl.cpp
@@ -1,18 +1,7 @@
//
-// Copyright 2017 Ettus Research (National Instruments)
+// Copyright 2017 Ettus Research, a National Instruments Company
//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
+// SPDX-License-Identifier: GPL-3.0
//
#include "mpmd_impl.hpp"
@@ -67,6 +56,7 @@ namespace {
}
using namespace uhd;
+using namespace uhd::mpmd;
/*****************************************************************************
* Structors
@@ -77,8 +67,9 @@ mpmd_mboard_impl::mpmd_mboard_impl(
) : mb_args(mb_args_)
, rpc(uhd::rpc_client::make(
rpc_server_addr,
- MPM_RPC_PORT,
- MPM_RPC_GET_LAST_ERROR_CMD))
+ mpmd_impl::MPM_RPC_PORT,
+ mpmd_impl::MPM_RPC_GET_LAST_ERROR_CMD))
+ , _xport_mgr(xport::mpmd_xport_mgr::make(mb_args))
{
UHD_LOGGER_TRACE("MPMD")
<< "Initializing mboard, connecting to RPC server address: "
@@ -96,7 +87,6 @@ mpmd_mboard_impl::mpmd_mboard_impl(
init_device(rpc, mb_args);
// RFNoC block clocks are now on. Noc-IDs can be read back.
-
auto device_info_dict = rpc->request<dev_info>("get_device_info");
for (const auto &info_pair : device_info_dict) {
device_info[info_pair.first] = info_pair.second;
@@ -120,24 +110,6 @@ mpmd_mboard_impl::mpmd_mboard_impl(
this->num_xbars = rpc->request<size_t>("get_num_xbars");
// xbar_local_addrs is not yet valid after this!
this->xbar_local_addrs.resize(this->num_xbars, 0xFF);
-
- // std::vector<std::string> data_ifaces =
- // rpc.call<std::vector<std::string>>("get_interfaces", rpc_token);
-
- // discover path to device and tell MPM our MAC address seen at the data
- // interfaces
- // move this into make_transport
- //for (const auto& iface : data_ifaces) {
- //std::vector<std::string> addrs = rpc.call<std::vector<std::string>>(
- //"get_interface_addrs", _rpc_token, iface);
- //for (const auto& iface_addr : addrs) {
- //if (rpc_client(iface_addr, MPM_RPC_PORT)
- //.call<bool>("probe_interface", _rpc_token)) {
- //data_interfaces.emplace(iface, iface_addr);
- //break;
- //}
- //}
- //}
}
mpmd_mboard_impl::~mpmd_mboard_impl()
@@ -152,20 +124,6 @@ mpmd_mboard_impl::~mpmd_mboard_impl()
/*****************************************************************************
* API
****************************************************************************/
-uhd::sid_t mpmd_mboard_impl::allocate_sid(
- const uint16_t port,
- const uhd::sid_t address,
- const uint32_t xbar_src_addr,
- const uint32_t xbar_src_port,
- const uint32_t dst_addr
-) {
- const auto sid = rpc->request_with_token<uint32_t>(
- "allocate_sid",
- port, address.get(), xbar_src_addr, xbar_src_port, dst_addr
- );
- return uhd::sid_t(sid);
-}
-
void mpmd_mboard_impl::set_xbar_local_addr(
const size_t xbar_index,
const size_t local_addr
@@ -175,6 +133,82 @@ void mpmd_mboard_impl::set_xbar_local_addr(
xbar_local_addrs.at(xbar_index) = local_addr;
}
+uhd::both_xports_t mpmd_mboard_impl::make_transport(
+ const sid_t& sid,
+ usrp::device3_impl::xport_type_t xport_type,
+ const uhd::device_addr_t& xport_args
+) {
+ const std::string xport_type_str = [xport_type](){
+ switch (xport_type) {
+ case mpmd_impl::CTRL:
+ return "CTRL";
+ case mpmd_impl::ASYNC_MSG:
+ return "ASYNC_MSG";
+ case mpmd_impl::RX_DATA:
+ return "RX_DATA";
+ case mpmd_impl::TX_DATA:
+ return "TX_DATA";
+ default:
+ UHD_THROW_INVALID_CODE_PATH();
+ };
+ }();
+
+ UHD_LOGGER_TRACE("MPMD")
+ << __func__ << "(): Creating new transport of type: "
+ << xport_type_str
+ ;
+
+ using namespace uhd::mpmd::xport;
+ const auto xport_info_list =
+ rpc->request_with_token<mpmd_xport_mgr::xport_info_list_t>(
+ "request_xport",
+ sid.get_dst(),
+ sid.get_src(),
+ xport_type_str
+ );
+ UHD_LOGGER_TRACE("MPMD")
+ << __func__
+ << "(): request_xport() gave us " << xport_info_list.size()
+ << " option(s)."
+ ;
+ if (xport_info_list.empty()) {
+ UHD_LOG_ERROR("MPMD", "No viable transport path found!");
+ throw uhd::runtime_error("No viable transport path found!");
+ }
+
+ xport::mpmd_xport_mgr::xport_info_t xport_info_out;
+ auto xports = _xport_mgr->make_transport(
+ xport_info_list,
+ xport_type,
+ xport_args,
+ xport_info_out
+ );
+
+ if (not rpc->request_with_token<bool>(
+ "commit_xport",
+ xport_info_out)) {
+ UHD_LOG_ERROR("MPMD", "Failed to create UDP transport!");
+ throw uhd::runtime_error("commit_xport() failed!");
+ }
+
+ return xports;
+}
+
+uhd::device_addr_t mpmd_mboard_impl::get_rx_hints() const
+{
+ // TODO: See if we need to do anything here. get_rx_stream() might care.
+ device_addr_t rx_hints;
+ return rx_hints;
+}
+
+uhd::device_addr_t mpmd_mboard_impl::get_tx_hints() const
+{
+ // TODO: See if we need to do anything here. get_tx_stream() might care.
+ device_addr_t tx_hints;
+ return tx_hints;
+}
+
+
/*****************************************************************************
* Private methods
****************************************************************************/
diff --git a/host/lib/usrp/mpmd/mpmd_xport.cpp b/host/lib/usrp/mpmd/mpmd_xport.cpp
index 5dd29a6f7..c21da3839 100644
--- a/host/lib/usrp/mpmd/mpmd_xport.cpp
+++ b/host/lib/usrp/mpmd/mpmd_xport.cpp
@@ -4,57 +4,39 @@
// SPDX-License-Identifier: GPL-3.0
//
-// make_transport logic for mpmd_impl.
-
+// make_transport logic for mpmd_impl. Note that mpmd_xport_mgr.* has most of
+// the actual transport logic, this for transport-related APIs.
#include "mpmd_impl.hpp"
-#include "../transport/liberio_zero_copy.hpp"
-#include <uhd/transport/udp_zero_copy.hpp>
-#include <uhd/utils/byteswap.hpp>
+#include "mpmd_xport_mgr.hpp"
using namespace uhd;
+using namespace uhd::mpmd;
-
-// TODO this does not consider the liberio use case!
-uhd::device_addr_t mpmd_impl::get_rx_hints(size_t /* mb_index */)
+uhd::device_addr_t mpmd_impl::get_rx_hints(size_t mb_index)
{
- //device_addr_t rx_hints = _mb[mb_index].recv_args;
- device_addr_t rx_hints; // TODO don't ignore what the user tells us
- // (default to a large recv buff)
- if (not rx_hints.has_key("recv_buff_size"))
- {
- //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"] = boost::lexical_cast<std::string>(MPMD_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"] = boost::lexical_cast<std::string>(MPMD_RX_SW_BUFF_SIZE_ETH);
- #endif
- }
- return rx_hints;
+ return _mb.at(mb_index)->get_rx_hints();
}
+uhd::device_addr_t mpmd_impl::get_tx_hints(size_t mb_index)
+{
+ return _mb.at(mb_index)->get_tx_hints();
+}
-/******************************************************************************
- * General make_transport() + helpers
- *****************************************************************************/
-size_t mpmd_impl::identify_mboard_by_sid(const size_t remote_addr)
+size_t mpmd_impl::identify_mboard_by_xbar_addr(const size_t xbar_addr) const
{
for (size_t mb_index = 0; mb_index < _mb.size(); mb_index++) {
for (size_t xbar_index = 0;
xbar_index < _mb[mb_index]->num_xbars;
xbar_index++) {
- if (_mb[mb_index]->get_xbar_local_addr(xbar_index) == remote_addr) {
+ if (_mb.at(mb_index)->get_xbar_local_addr(xbar_index) == xbar_addr) {
return mb_index;
}
}
}
throw uhd::lookup_error(str(
- boost::format("Cannot identify mboard for remote address %d")
- % remote_addr
+ boost::format("Cannot identify mboard for crossbar address %d")
+ % xbar_addr
));
}
@@ -63,59 +45,27 @@ both_xports_t mpmd_impl::make_transport(
usrp::device3_impl::xport_type_t xport_type,
const uhd::device_addr_t& args
) {
- const size_t mb_index = identify_mboard_by_sid(dst_address.get_dst_addr());
- // Could also be a map...
- const std::string xport_type_str = [xport_type](){
- switch (xport_type) {
- case CTRL:
- return "CTRL";
- case ASYNC_MSG:
- return "ASYNC_MSG";
- case RX_DATA:
- return "RX_DATA";
- case TX_DATA:
- return "TX_DATA";
- default:
- UHD_THROW_INVALID_CODE_PATH();
- };
- }();
-
+ const size_t mb_index =
+ identify_mboard_by_xbar_addr(dst_address.get_dst_addr());
+
+ const sid_t sid(
+ 0,
+ _sid_framer++, // FIXME make sure we only increment if actually valid
+ dst_address.get_dst_addr(),
+ dst_address.get_dst_endpoint()
+ );
UHD_LOGGER_TRACE("MPMD")
- << "Creating new transport of type: " << xport_type_str
- << " To mboard: " << mb_index
- << " Destination address: " << dst_address.to_pp_string_hex().substr(6)
+ << "Creating new transport to mboard: " << mb_index
+ << " SID: " << sid.to_pp_string_hex()
<< " User-defined xport args: " << args.to_string()
;
- const auto xport_info_list =
- _mb[mb_index]->rpc->request_with_token<xport_info_list_t>(
- "request_xport",
- dst_address.get_dst(),
- _sid_framer++, // FIXME make sure we only increment if actually valid
- xport_type_str
+ both_xports_t xports = _mb[mb_index]->make_transport(
+ sid,
+ xport_type,
+ args
);
UHD_LOGGER_TRACE("MPMD")
- << "request_xport() gave us " << xport_info_list.size()
- << " option(s)."
- ;
-
- // This is not very elegant, and needs some kind of factory model or
- // whatnot.
- auto xport_info = xport_info_list.at(0); // In the future, actually pick one
- // sensibly. This is what would
- // enable dual Eth support. FIXME
- both_xports_t xports;
- if (xport_info["type"] == "UDP") {
- xports = make_transport_udp(mb_index, xport_info, xport_type, args);
-#ifdef HAVE_LIBERIO
- } else if (xport_info["type"] == "liberio") {
- xports = make_transport_liberio(mb_index, xport_info, xport_type, args);
-#endif
- } else {
- UHD_THROW_INVALID_CODE_PATH();
- }
-
- UHD_LOGGER_TRACE("MPMD")
<< "xport info: send_sid==" << xports.send_sid.to_pp_string_hex()
<< " recv_sid==" << xports.recv_sid.to_pp_string_hex()
<< " endianness=="
@@ -123,181 +73,6 @@ both_xports_t mpmd_impl::make_transport(
<< " recv_buff_size==" << xports.recv_buff_size
<< " send_buff_size==" << xports.send_buff_size
;
-
- return xports;
-}
-
-
-/******************************************************************************
- * UDP Transport
- *****************************************************************************/
-both_xports_t mpmd_impl::make_transport_udp(
- const size_t mb_index,
- xport_info_t &xport_info,
- const xport_type_t /*xport_type*/,
- const uhd::device_addr_t& xport_args
-) {
- auto &rpc = _mb[mb_index]->rpc;
-
- transport::zero_copy_xport_params default_buff_args;
- // Create actual UDP transport
- // TODO don't hardcode these
- default_buff_args.send_frame_size = 8000;
- default_buff_args.recv_frame_size = 8000;
- default_buff_args.num_recv_frames = 32;
- default_buff_args.num_send_frames = 32;
-
- transport::udp_zero_copy::buff_params buff_params;
- auto recv = transport::udp_zero_copy::make(
- xport_info["ipv4"],
- xport_info["port"],
- default_buff_args,
- buff_params,
- xport_args
- );
- const uint16_t port = recv->get_local_port();
- const std::string src_ip_addr = recv->get_local_addr();
- xport_info["src_port"] = std::to_string(port);
- xport_info["src_ipv4"] = src_ip_addr;
-
- // Communicate it all back to MPM
- if (not rpc->request_with_token<bool>("commit_xport", xport_info)) {
- UHD_LOG_ERROR("MPMD", "Failed to create UDP transport!");
- throw uhd::runtime_error("commit_xport() failed!");
- }
-
- // Create both_xports_t object and finish:
- both_xports_t xports;
- xports.endianness = uhd::ENDIANNESS_BIG;
- xports.send_sid = sid_t(xport_info["send_sid"]);
- xports.recv_sid = xports.send_sid.reversed();
- xports.recv_buff_size = buff_params.recv_buff_size;
- xports.send_buff_size = buff_params.send_buff_size;
- xports.recv = recv; // Note: This is a type cast!
- xports.send = recv; // This too
- return xports;
-}
-
-/******************************************************************************
- * Liberio Transport
- *****************************************************************************/
-#ifdef HAVE_LIBERIO
-static uint32_t extract_sid_from_pkt(void* pkt, size_t) {
- return uhd::sid_t(uhd::wtohx(static_cast<const uint32_t*>(pkt)[1]))
- .get_dst();
-}
-
-uhd::transport::muxed_zero_copy_if::sptr mpmd_impl::make_muxed_liberio_xport(
- const std::string &tx_dev,
- const std::string &rx_dev,
- const uhd::transport::zero_copy_xport_params &buff_args,
- const size_t max_muxed_ports
-) {
- auto base_xport = transport::liberio_zero_copy::make(
- tx_dev, rx_dev, buff_args);
-
- return uhd::transport::muxed_zero_copy_if::make(
- base_xport, extract_sid_from_pkt, max_muxed_ports);
-}
-
-both_xports_t mpmd_impl::make_transport_liberio(
- const size_t mb_index,
- xport_info_t &xport_info,
- const xport_type_t xport_type,
- const uhd::device_addr_t& xport_args
-) {
- auto &rpc = _mb[mb_index]->rpc;
-
- transport::zero_copy_xport_params default_buff_args;
- /* default ones for RX / TX, override below */
- default_buff_args.send_frame_size = 4 * getpagesize();
- default_buff_args.recv_frame_size = 4 * getpagesize();
- default_buff_args.num_recv_frames = 128;
- default_buff_args.num_send_frames = 128;
-
- if (xport_type == CTRL) {
- default_buff_args.send_frame_size = 128;
- default_buff_args.recv_frame_size = 128;
- } else if (xport_type == ASYNC_MSG) {
- default_buff_args.send_frame_size = 256;
- default_buff_args.recv_frame_size = 256;
- } else if (xport_type == RX_DATA) {
- default_buff_args.send_frame_size = 64;
- } else {
- default_buff_args.recv_frame_size = 64;
- }
-
- const std::string tx_dev = xport_info["tx_dev"];
- const std::string rx_dev = xport_info["rx_dev"];
-
- both_xports_t xports;
- xports.endianness = uhd::ENDIANNESS_LITTLE;
- xports.send_sid = sid_t(xport_info["send_sid"]);
- xports.recv_sid = xports.send_sid.reversed();
-
- // this is kinda ghetto: scale buffer for muxed xports since we share the
- // buffer...
- float divisor = 1;
- if (xport_type == CTRL)
- divisor = 16;
- else if (xport_type == ASYNC_MSG)
- divisor = 4;
-
-
- //if (xport_info["muxed"] == "True") {
- //// FIXME tbw
- //}
- if (xport_type == CTRL) {
- UHD_ASSERT_THROW(xport_info["muxed"] == "True");
- if (not _ctrl_dma_xport) {
- default_buff_args.send_frame_size = 128;
- default_buff_args.recv_frame_size = 128;
- _ctrl_dma_xport = make_muxed_liberio_xport(tx_dev, rx_dev,
- default_buff_args, int(divisor));
- }
-
- UHD_LOGGER_TRACE("MPMD")
- << "Making (muxed) stream with num " << xports.recv_sid.get_dst();
- xports.recv = _ctrl_dma_xport->make_stream(xports.recv_sid.get_dst());
- } else if (xport_type == ASYNC_MSG) {
- UHD_ASSERT_THROW(xport_info["muxed"] == "True");
- if (not _async_msg_dma_xport) {
- default_buff_args.send_frame_size = 256;
- default_buff_args.recv_frame_size = 256;
- _async_msg_dma_xport = make_muxed_liberio_xport(
- tx_dev, rx_dev, default_buff_args, int(divisor));
- }
-
- UHD_LOGGER_TRACE("MPMD")
- << "making (muxed) stream with num " << xports.recv_sid.get_dst();
- xports.recv =
- _async_msg_dma_xport->make_stream(xports.recv_sid.get_dst());
- } else {
- xports.recv =
- transport::liberio_zero_copy::make(
- tx_dev, rx_dev, default_buff_args);
- }
-
- transport::udp_zero_copy::buff_params buff_params;
- buff_params.recv_buff_size =
- float(default_buff_args.recv_frame_size) *
- float(default_buff_args.num_recv_frames) / divisor;
- buff_params.send_buff_size =
- float(default_buff_args.send_frame_size) *
- float(default_buff_args.num_send_frames) / divisor;
-
-
- // Communicate it all back to MPM
- if (not rpc->request_with_token<bool>("commit_xport", xport_info)) {
- UHD_LOG_ERROR("MPMD", "Failed to create UDP transport!");
- throw uhd::runtime_error("commit_xport() failed!");
- }
-
- // Finish both_xports_t object and return:
- xports.recv_buff_size = buff_params.recv_buff_size;
- xports.send_buff_size = buff_params.send_buff_size;
- xports.send = xports.recv;
return xports;
}
-#endif /* HAVE_LIBERIO */
diff --git a/host/lib/usrp/mpmd/mpmd_xport_ctrl_base.hpp b/host/lib/usrp/mpmd/mpmd_xport_ctrl_base.hpp
new file mode 100644
index 000000000..e5a3b7e31
--- /dev/null
+++ b/host/lib/usrp/mpmd/mpmd_xport_ctrl_base.hpp
@@ -0,0 +1,45 @@
+//
+// Copyright 2017 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: GPL-3.0
+//
+
+#ifndef INCLUDED_MPMD_XPORT_CTRL_BASE_HPP
+#define INCLUDED_MPMD_XPORT_CTRL_BASE_HPP
+
+#include "mpmd_xport_mgr.hpp"
+#include "../device3/device3_impl.hpp"
+#include <uhd/types/device_addr.hpp>
+#include <memory>
+
+namespace uhd { namespace mpmd { namespace xport {
+
+/*! Transport manager implementation base
+ */
+class mpmd_xport_ctrl_base
+{
+public:
+ using uptr = std::unique_ptr<mpmd_xport_ctrl_base>;
+
+ /*! This is the final step of a make_transport() sequence
+ *
+ * \param xport_info Contains all necessary transport info. The
+ * implementation may update this!
+ * \param xport_type CTRL, ASYNC_MSG, ... (see xport_type_t)
+ * \param xport_args Additional arguments. These can come from the user.
+ */
+ virtual both_xports_t make_transport(
+ mpmd_xport_mgr::xport_info_t& xport_info,
+ const usrp::device3_impl::xport_type_t xport_type,
+ const uhd::device_addr_t& xport_args
+ ) = 0;
+
+ //! Assert if an xport_info is even valid/feasible/available
+ virtual bool is_valid(
+ const mpmd_xport_mgr::xport_info_t& xport_info
+ ) const = 0;
+};
+
+}}} /* namespace uhd::mpmd::xport */
+
+#endif /* INCLUDED_MPMD_XPORT_CTRL_BASE_HPP */
diff --git a/host/lib/usrp/mpmd/mpmd_xport_ctrl_liberio.cpp b/host/lib/usrp/mpmd/mpmd_xport_ctrl_liberio.cpp
new file mode 100644
index 000000000..2e4f024b4
--- /dev/null
+++ b/host/lib/usrp/mpmd/mpmd_xport_ctrl_liberio.cpp
@@ -0,0 +1,145 @@
+//
+// Copyright 2017 Ettus Research, National Instruments Company
+//
+// SPDX-License-Identifier: GPL-3.0
+//
+
+#include "mpmd_xport_ctrl_liberio.hpp"
+#include "../transport/liberio_zero_copy.hpp"
+#include <uhd/transport/udp_zero_copy.hpp>
+#include <uhd/utils/byteswap.hpp>
+
+using namespace uhd;
+using namespace uhd::mpmd::xport;
+
+namespace {
+
+ uint32_t extract_sid_from_pkt(void* pkt, size_t) {
+ return uhd::sid_t(uhd::wtohx(static_cast<const uint32_t*>(pkt)[1]))
+ .get_dst();
+ }
+
+}
+
+mpmd_xport_ctrl_liberio::mpmd_xport_ctrl_liberio(
+ const uhd::device_addr_t& mb_args
+) : _mb_args(mb_args)
+ , _recv_args(filter_args(mb_args, "recv"))
+ , _send_args(filter_args(mb_args, "send"))
+{
+ // nop
+}
+
+
+uhd::both_xports_t
+mpmd_xport_ctrl_liberio::make_transport(
+ mpmd_xport_mgr::xport_info_t &xport_info,
+ const usrp::device3_impl::xport_type_t xport_type,
+ const uhd::device_addr_t& /*xport_args_*/
+) {
+ transport::zero_copy_xport_params default_buff_args;
+ /* default ones for RX / TX, override below */
+ default_buff_args.send_frame_size = 4 * getpagesize();
+ default_buff_args.recv_frame_size = 4 * getpagesize();
+ default_buff_args.num_recv_frames = 128;
+ default_buff_args.num_send_frames = 128;
+
+ if (xport_type == usrp::device3_impl::CTRL) {
+ default_buff_args.send_frame_size = 128;
+ default_buff_args.recv_frame_size = 128;
+ } else if (xport_type == usrp::device3_impl::ASYNC_MSG) {
+ default_buff_args.send_frame_size = 256;
+ default_buff_args.recv_frame_size = 256;
+ } else if (xport_type == usrp::device3_impl::RX_DATA) {
+ default_buff_args.send_frame_size = 64;
+ } else {
+ default_buff_args.recv_frame_size = 64;
+ }
+
+ const std::string tx_dev = xport_info["tx_dev"];
+ const std::string rx_dev = xport_info["rx_dev"];
+
+ both_xports_t xports;
+ xports.endianness = uhd::ENDIANNESS_LITTLE;
+ xports.send_sid = sid_t(xport_info["send_sid"]);
+ xports.recv_sid = xports.send_sid.reversed();
+
+ // this is kinda ghetto: scale buffer for muxed xports since we share the
+ // buffer...
+ float divisor = 1;
+ if (xport_type == usrp::device3_impl::CTRL)
+ divisor = 16;
+ else if (xport_type == usrp::device3_impl::ASYNC_MSG)
+ divisor = 4;
+
+
+ //if (xport_info["muxed"] == "True") {
+ //// FIXME tbw
+ //}
+ if (xport_type == usrp::device3_impl::CTRL) {
+ UHD_ASSERT_THROW(xport_info["muxed"] == "True");
+ if (not _ctrl_dma_xport) {
+ default_buff_args.send_frame_size = 128;
+ default_buff_args.recv_frame_size = 128;
+ _ctrl_dma_xport = make_muxed_liberio_xport(tx_dev, rx_dev,
+ default_buff_args, int(divisor));
+ }
+
+ UHD_LOGGER_TRACE("MPMD")
+ << "Making (muxed) stream with num " << xports.recv_sid.get_dst();
+ xports.recv = _ctrl_dma_xport->make_stream(xports.recv_sid.get_dst());
+ } else if (xport_type == usrp::device3_impl::ASYNC_MSG) {
+ UHD_ASSERT_THROW(xport_info["muxed"] == "True");
+ if (not _async_msg_dma_xport) {
+ default_buff_args.send_frame_size = 256;
+ default_buff_args.recv_frame_size = 256;
+ _async_msg_dma_xport = make_muxed_liberio_xport(
+ tx_dev, rx_dev, default_buff_args, int(divisor));
+ }
+
+ UHD_LOGGER_TRACE("MPMD")
+ << "making (muxed) stream with num " << xports.recv_sid.get_dst();
+ xports.recv =
+ _async_msg_dma_xport->make_stream(xports.recv_sid.get_dst());
+ } else {
+ xports.recv =
+ transport::liberio_zero_copy::make(
+ tx_dev, rx_dev, default_buff_args);
+ }
+
+ transport::udp_zero_copy::buff_params buff_params;
+ buff_params.recv_buff_size =
+ float(default_buff_args.recv_frame_size) *
+ float(default_buff_args.num_recv_frames) / divisor;
+ buff_params.send_buff_size =
+ float(default_buff_args.send_frame_size) *
+ float(default_buff_args.num_send_frames) / divisor;
+
+
+ // Finish both_xports_t object and return:
+ xports.recv_buff_size = buff_params.recv_buff_size;
+ xports.send_buff_size = buff_params.send_buff_size;
+ xports.send = xports.recv;
+ return xports;
+}
+
+bool mpmd_xport_ctrl_liberio::is_valid(
+ const mpmd_xport_mgr::xport_info_t& xport_info
+) const {
+ return xport_info.at("type") == "liberio";
+}
+
+uhd::transport::muxed_zero_copy_if::sptr
+mpmd_xport_ctrl_liberio::make_muxed_liberio_xport(
+ const std::string &tx_dev,
+ const std::string &rx_dev,
+ const uhd::transport::zero_copy_xport_params &buff_args,
+ const size_t max_muxed_ports
+) {
+ auto base_xport = transport::liberio_zero_copy::make(
+ tx_dev, rx_dev, buff_args);
+
+ return uhd::transport::muxed_zero_copy_if::make(
+ base_xport, extract_sid_from_pkt, max_muxed_ports);
+}
+
diff --git a/host/lib/usrp/mpmd/mpmd_xport_ctrl_liberio.hpp b/host/lib/usrp/mpmd/mpmd_xport_ctrl_liberio.hpp
new file mode 100644
index 000000000..76bb88f03
--- /dev/null
+++ b/host/lib/usrp/mpmd/mpmd_xport_ctrl_liberio.hpp
@@ -0,0 +1,59 @@
+//
+// Copyright 2017 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: GPL-3.0
+//
+
+#ifndef INCLUDED_MPMD_XPORT_ctrl_liberio_HPP
+#define INCLUDED_MPMD_XPORT_ctrl_liberio_HPP
+
+#include "mpmd_xport_ctrl_base.hpp"
+#include <uhd/types/device_addr.hpp>
+#include "../device3/device3_impl.hpp"
+#include <uhd/transport/muxed_zero_copy_if.hpp>
+
+namespace uhd { namespace mpmd { namespace xport {
+
+/*! Liberio transport manager
+ */
+class mpmd_xport_ctrl_liberio : public mpmd_xport_ctrl_base
+{
+public:
+ mpmd_xport_ctrl_liberio(
+ const uhd::device_addr_t& mb_args
+ );
+
+ /*! Open DMA interface to kernel (and thus to FPGA DMA engine)
+ */
+ both_xports_t make_transport(
+ mpmd_xport_mgr::xport_info_t& xport_info,
+ const usrp::device3_impl::xport_type_t xport_type,
+ const uhd::device_addr_t& xport_args
+ );
+
+ bool is_valid(
+ const mpmd_xport_mgr::xport_info_t& xport_info
+ ) const;
+
+private:
+ /*! Create a muxed liberio transport for control packets */
+ uhd::transport::muxed_zero_copy_if::sptr make_muxed_liberio_xport(
+ const std::string &tx_dev,
+ const std::string &rx_dev,
+ const uhd::transport::zero_copy_xport_params &buff_args,
+ const size_t max_muxed_ports
+ );
+
+ const uhd::device_addr_t _mb_args;
+ const uhd::dict<std::string, std::string> _recv_args;
+ const uhd::dict<std::string, std::string> _send_args;
+
+ //! Control transport for one liberio connection
+ uhd::transport::muxed_zero_copy_if::sptr _ctrl_dma_xport;
+ //! Control transport for one liberio connection
+ uhd::transport::muxed_zero_copy_if::sptr _async_msg_dma_xport;
+};
+
+}}} /* namespace uhd::mpmd::xport */
+
+#endif /* INCLUDED_MPMD_XPORT_ctrl_liberio_HPP */
diff --git a/host/lib/usrp/mpmd/mpmd_xport_ctrl_udp.cpp b/host/lib/usrp/mpmd/mpmd_xport_ctrl_udp.cpp
new file mode 100644
index 000000000..de4b3bbba
--- /dev/null
+++ b/host/lib/usrp/mpmd/mpmd_xport_ctrl_udp.cpp
@@ -0,0 +1,103 @@
+//
+// Copyright 2017 Ettus Research, National Instruments Company
+//
+// SPDX-License-Identifier: GPL-3.0
+//
+
+#include "mpmd_xport_mgr.hpp"
+#include "mpmd_xport_ctrl_udp.hpp"
+#include <uhd/transport/udp_zero_copy.hpp>
+
+using namespace uhd;
+using namespace uhd::mpmd::xport;
+
+namespace {
+
+ #if defined(UHD_PLATFORM_MACOS) || defined(UHD_PLATFORM_BSD)
+ const size_t MPMD_RX_SW_BUFF_SIZE_ETH = 0x100000; // 1Mib
+ #elif defined(UHD_PLATFORM_LINUX) || defined(UHD_PLATFORM_WIN32)
+ //For an ~8k frame size any size >32MiB is just wasted buffer space:
+ const size_t MPMD_RX_SW_BUFF_SIZE_ETH = 0x2000000; // 32 MiB
+ #endif
+
+ const size_t MPMD_10GE_DATA_FRAME_MAX_SIZE = 8000; // CHDR packet size in bytes
+
+ std::vector<std::string> get_addrs_from_mb_args(
+ const uhd::device_addr_t& mb_args
+ ) {
+ // mb_args must always include addr
+ std::vector<std::string> addrs{mb_args["addr"]};
+ if (mb_args.has_key("second_addr")){
+ addrs.push_back(mb_args["second_addr"]);
+ }
+ return addrs;
+ }
+}
+
+
+mpmd_xport_ctrl_udp::mpmd_xport_ctrl_udp(
+ const uhd::device_addr_t& mb_args
+) : _mb_args(mb_args)
+ , _recv_args(filter_args(mb_args, "recv"))
+ , _send_args(filter_args(mb_args, "send"))
+ , _available_addrs(get_addrs_from_mb_args(mb_args))
+{
+}
+
+uhd::both_xports_t
+mpmd_xport_ctrl_udp::make_transport(
+ mpmd_xport_mgr::xport_info_t &xport_info,
+ const usrp::device3_impl::xport_type_t xport_type,
+ const uhd::device_addr_t& xport_args_
+) {
+ auto xport_args = xport_args_;
+
+ if (xport_type == usrp::device3_impl::RX_DATA
+ and not xport_args.has_key("recv_buff_size")) {
+ xport_args["recv_buff_size"] =
+ std::to_string(MPMD_RX_SW_BUFF_SIZE_ETH);
+ }
+
+ transport::zero_copy_xport_params default_buff_args;
+ // Create actual UDP transport
+ // TODO don't hardcode these
+ default_buff_args.send_frame_size = 8000;
+ default_buff_args.recv_frame_size = 8000;
+ default_buff_args.num_recv_frames = 32;
+ default_buff_args.num_send_frames = 32;
+
+ transport::udp_zero_copy::buff_params buff_params;
+ auto recv = transport::udp_zero_copy::make(
+ xport_info["ipv4"],
+ xport_info["port"],
+ default_buff_args,
+ buff_params,
+ xport_args
+ );
+ const uint16_t port = recv->get_local_port();
+ const std::string src_ip_addr = recv->get_local_addr();
+ xport_info["src_port"] = std::to_string(port);
+ xport_info["src_ipv4"] = src_ip_addr;
+
+ // Create both_xports_t object and finish:
+ both_xports_t xports;
+ xports.endianness = uhd::ENDIANNESS_BIG;
+ xports.send_sid = sid_t(xport_info["send_sid"]);
+ xports.recv_sid = xports.send_sid.reversed();
+ xports.recv_buff_size = buff_params.recv_buff_size;
+ xports.send_buff_size = buff_params.send_buff_size;
+ xports.recv = recv; // Note: This is a type cast!
+ xports.send = recv; // This too
+ return xports;
+}
+
+bool mpmd_xport_ctrl_udp::is_valid(
+ const mpmd_xport_mgr::xport_info_t& xport_info
+) const {
+ return std::find(
+ _available_addrs.cbegin(),
+ _available_addrs.cend(),
+ xport_info.at("ipv4")
+ ) != _available_addrs.cend();
+}
+
diff --git a/host/lib/usrp/mpmd/mpmd_xport_ctrl_udp.hpp b/host/lib/usrp/mpmd/mpmd_xport_ctrl_udp.hpp
new file mode 100644
index 000000000..0c8c19479
--- /dev/null
+++ b/host/lib/usrp/mpmd/mpmd_xport_ctrl_udp.hpp
@@ -0,0 +1,46 @@
+//
+// Copyright 2017 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: GPL-3.0
+//
+
+#ifndef INCLUDED_MPMD_XPORT_ctrl_udp_HPP
+#define INCLUDED_MPMD_XPORT_ctrl_udp_HPP
+
+#include "mpmd_xport_ctrl_base.hpp"
+#include <uhd/types/device_addr.hpp>
+#include "../device3/device3_impl.hpp"
+
+namespace uhd { namespace mpmd { namespace xport {
+
+/*! UDP transport manager
+ *
+ * Opens UDP sockets
+ */
+class mpmd_xport_ctrl_udp : public mpmd_xport_ctrl_base
+{
+public:
+ mpmd_xport_ctrl_udp(
+ const uhd::device_addr_t& mb_args
+ );
+
+ both_xports_t make_transport(
+ mpmd_xport_mgr::xport_info_t& xport_info,
+ const usrp::device3_impl::xport_type_t xport_type,
+ const uhd::device_addr_t& xport_args
+ );
+
+ bool is_valid(
+ const mpmd_xport_mgr::xport_info_t& xport_info
+ ) const;
+
+private:
+ const uhd::device_addr_t _mb_args;
+ const uhd::dict<std::string, std::string> _recv_args;
+ const uhd::dict<std::string, std::string> _send_args;
+ const std::vector<std::string> _available_addrs;
+};
+
+}}} /* namespace uhd::mpmd::xport */
+
+#endif /* INCLUDED_MPMD_XPORT_ctrl_udp_HPP */
diff --git a/host/lib/usrp/mpmd/mpmd_xport_mgr.cpp b/host/lib/usrp/mpmd/mpmd_xport_mgr.cpp
new file mode 100644
index 000000000..242a46527
--- /dev/null
+++ b/host/lib/usrp/mpmd/mpmd_xport_mgr.cpp
@@ -0,0 +1,148 @@
+//
+// Copyright 2017 Ettus Research, National Instruments Company
+//
+// SPDX-License-Identifier: GPL-3.0
+//
+
+#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<std::string, std::string> uhd::mpmd::xport::filter_args(
+ const uhd::device_addr_t& args,
+ const std::string& prefix
+) {
+ uhd::dict<std::string, std::string> 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);
+
+ // When we've picked our preferred option, pass it to the transport
+ // implementation for execution:
+ return _xport_ctrls[xport_medium]->make_transport(
+ xport_info_out,
+ xport_type,
+ xport_args
+ );
+ }
+
+
+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 {
+ // Naive xport picking method, this needs fixing (FIXME).
+ // Have algorithm run on baseline score, allocation, and random soup
+ return xport_info_list.at(0);
+ }
+
+ //! 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 {
+ throw uhd::key_error("Unknown transport medium!");
+ }
+ }
+
+ //! This will make sure that _xport_ctrls contains 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 << "'");
+ _xport_ctrls[xport_medium] = make_mgr_impl(xport_medium, _mb_args);
+ }
+ }
+
+ /**************************************************************************
+ * Private attributes
+ *************************************************************************/
+ //! Cache available xport manager implementations
+ //
+ // Should only every be populated by require_xport_mgr()
+ std::map<std::string, mpmd_xport_ctrl_base::uptr> _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));
+}
+
diff --git a/host/lib/usrp/mpmd/mpmd_xport_mgr.hpp b/host/lib/usrp/mpmd/mpmd_xport_mgr.hpp
new file mode 100644
index 000000000..2da4af323
--- /dev/null
+++ b/host/lib/usrp/mpmd/mpmd_xport_mgr.hpp
@@ -0,0 +1,95 @@
+//
+// Copyright 2017 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: GPL-3.0
+//
+
+#ifndef INCLUDED_MPMD_XPORT_MGR_HPP
+#define INCLUDED_MPMD_XPORT_MGR_HPP
+
+#include "../device3/device3_impl.hpp"
+#include <uhd/types/dict.hpp>
+#include <memory>
+#include <map>
+#include <vector>
+#include <string>
+
+namespace uhd { namespace mpmd { namespace xport {
+
+/*! Return filtered subset from a device_addr_t
+ *
+ * The return dictionary will contain all key/value pairs from \p args
+ * where the key begins with \p prefix.
+ *
+ * \param args Bucket of key/value pairs
+ * \param prefix Key prefix to match against
+ */
+uhd::dict<std::string, std::string> filter_args(
+ const uhd::device_addr_t& args,
+ const std::string& prefix
+);
+
+/*! MPMD Transport Manager
+ *
+ * A transport manager is an object which sets up a physical connection to a
+ * CHDR device. Its implementation is specific to the underlying transport
+ * medium. For example, if the medium is Ethernet/UDP, this class will create
+ * sockets.
+ */
+class mpmd_xport_mgr
+{
+public:
+ using uptr = std::unique_ptr<mpmd_xport_mgr>;
+ using xport_info_t = std::map<std::string, std::string>;
+ using xport_info_list_t = std::vector<std::map<std::string, std::string>>;
+
+ /*! Return a reference to a transport manager
+ *
+ * \param mb_args Additional args from the motherboard. These may contain
+ * transport-related args (e.g., "recv_buff_size") which
+ * can be relevant to the underlying implementation.
+ *
+ * \returns Reference to manager object
+ * \throws uhd::key_error if \p xport_medium is not supported. The ctor of
+ * the underlying class that is requested can also throw.
+ */
+ static uptr make(
+ const uhd::device_addr_t& mb_args
+ );
+
+ /*! Create a transports object
+ *
+ * Implementation details depend on the underlying implementation.
+ * In general, the implementations will follow the following recipe:
+ * 1. Pick a suitable element from \p xport_info_list
+ * 2. Do whatever system calls are necessary to create the physical
+ * transport; to do so, call the underlying implementation (UDP or
+ * whatever)
+ * 3. Update the selected element from xport_info_list
+ * 5. Return results
+ *
+ * \param xport_info_list List of possible options to choose from. Every
+ * element of this argument needs to have the same
+ * "type" key (e.g., they all need to be "UDP").
+ * \param xport_type Transport type (CTRL, RX_DATA, ...)
+ * \param xport_args Arbitrary additional transport args. These could come
+ * from the user, or other places.
+ * \param xport_info_out The updated dictionary from xport_info_list that
+ * was eventually chosen
+ *
+ * \returns The both_xports_t object containing the actual transport info,
+ * and xport_info_out contains the updated transport option info.
+ * The latter needs to get sent back to MPM to complete the
+ * transport handshake.
+ */
+ virtual both_xports_t make_transport(
+ const xport_info_list_t &xport_info_list,
+ const usrp::device3_impl::xport_type_t xport_type,
+ const uhd::device_addr_t& xport_args,
+ xport_info_t& xport_info_out
+ ) = 0;
+};
+
+}}} /* namespace uhd::mpmd::xport */
+
+#endif /* INCLUDED_MPMD_XPORT_MGR_HPP */
diff --git a/mpm/python/usrp_mpm/xports/xportmgr_udp.py b/mpm/python/usrp_mpm/xports/xportmgr_udp.py
index 0a7f19ffc..edd20a629 100644
--- a/mpm/python/usrp_mpm/xports/xportmgr_udp.py
+++ b/mpm/python/usrp_mpm/xports/xportmgr_udp.py
@@ -70,12 +70,19 @@ class XportMgrUDP(object):
After calling this, _chdr_ifaces and _eth_dispatchers are in sync.
"""
+ ifaces_to_remove = [
+ x for x in self._eth_dispatchers.keys()
+ if x not in self._chdr_ifaces
+ ]
+ for iface in ifaces_to_remove:
+ self._eth_dispatchers.pop(iface)
for iface in self._chdr_ifaces:
if iface not in self._eth_dispatchers:
self._eth_dispatchers[iface] = \
EthDispatcherTable(self.iface_config[iface]['label'])
- for ifname, table in iteritems(self._eth_dispatchers):
- table.set_ipv4_addr(self._chdr_ifaces[ifname]['ip_addr'])
+ self._eth_dispatchers[iface].set_ipv4_addr(
+ self._chdr_ifaces[iface]['ip_addr']
+ )
def init(self, args):
"""