aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/rfnoc
diff options
context:
space:
mode:
authorAlex Williams <alex.williams@ni.com>2019-08-09 08:18:05 -0700
committerMartin Braun <martin.braun@ettus.com>2019-11-26 11:49:37 -0800
commite6da166a179ceda0c74c4acb7eb75ea7dc4201c6 (patch)
tree2344064fed0889d6764fd0c295b19893bcbee474 /host/lib/rfnoc
parent117af6f0b0d50e6ba81bbd8f970d8963f615548a (diff)
downloaduhd-e6da166a179ceda0c74c4acb7eb75ea7dc4201c6.tar.gz
uhd-e6da166a179ceda0c74c4acb7eb75ea7dc4201c6.tar.bz2
uhd-e6da166a179ceda0c74c4acb7eb75ea7dc4201c6.zip
rfnoc: Add basic round-robin allocation for links
When multiple links are present, the graph_stream_manager will now alternate using them for different streams. It does not consider the required bandwidth of the stream, the channel capacity of the local and remote transport adapters, nor the total reserved capacity of the NIC.
Diffstat (limited to 'host/lib/rfnoc')
-rw-r--r--host/lib/rfnoc/graph_stream_manager.cpp77
1 files changed, 65 insertions, 12 deletions
diff --git a/host/lib/rfnoc/graph_stream_manager.cpp b/host/lib/rfnoc/graph_stream_manager.cpp
index fe28eab54..f3c42c87f 100644
--- a/host/lib/rfnoc/graph_stream_manager.cpp
+++ b/host/lib/rfnoc/graph_stream_manager.cpp
@@ -8,7 +8,7 @@
#include <uhd/utils/log.hpp>
#include <uhdlib/rfnoc/graph_stream_manager.hpp>
#include <uhdlib/rfnoc/link_stream_manager.hpp>
-#include <uhdlib/rfnoc/chdr_rx_data_xport.hpp>
+#include <uhdlib/transport/links.hpp>
#include <boost/format.hpp>
#include <boost/make_shared.hpp>
#include <map>
@@ -18,6 +18,9 @@ using namespace uhd;
using namespace uhd::rfnoc;
using namespace uhd::rfnoc::chdr;
+namespace uhd { namespace rfnoc { namespace detail {
+}}} // uhd::rfnoc::detail
+
graph_stream_manager::~graph_stream_manager() = default;
class graph_stream_manager_impl : public graph_stream_manager
@@ -33,6 +36,9 @@ public:
_link_mgrs.emplace(lnk.first,
std::move(link_stream_manager::make(
pkt_factory, *lnk.second, epid_alloc, lnk.first)));
+ if (_alloc_map.count(lnk.first) == 0) {
+ _alloc_map[lnk.first] = allocation_info{0, 0};
+ }
}
for (const auto& mgr_pair : _link_mgrs) {
for (const auto& ep : mgr_pair.second->get_reachable_endpoints()) {
@@ -73,7 +79,8 @@ public:
// When we connect, we setup a route and fire up a control stream between
// the endpoints
- device_id_t gateway = _check_dst_and_find_src(dst_addr, host_device);
+ device_id_t gateway = _check_dst_and_find_src(dst_addr, host_device,
+ uhd::transport::link_type_t::CTRL);
sep_id_pair_t epid_pair =
_link_mgrs.at(gateway)->connect_host_to_device(dst_addr);
UHD_LOGGER_DEBUG("RFNOC::GRAPH")
@@ -122,8 +129,10 @@ public:
{
// We must be connected to dst_addr before getting a register iface
sep_id_t dst_epid = _epid_alloc->get_epid(dst_addr);
- return _link_mgrs.at(_check_dst_and_find_src(dst_addr, via_device))
- ->get_block_register_iface(dst_epid, block_index, client_clk, timebase_clk);
+ auto dev = _check_dst_and_find_src(dst_addr, via_device,
+ uhd::transport::link_type_t::CTRL);
+ return _link_mgrs.at(dev)->get_block_register_iface(dst_epid, block_index,
+ client_clk, timebase_clk);
}
virtual detail::client_zero::sptr get_client_zero(
@@ -131,8 +140,9 @@ public:
{
// We must be connected to dst_addr before getting a client zero
sep_id_t dst_epid = _epid_alloc->get_epid(dst_addr);
- return _link_mgrs.at(_check_dst_and_find_src(dst_addr, via_device))
- ->get_client_zero(dst_epid);
+ auto dev = _check_dst_and_find_src(dst_addr, via_device,
+ uhd::transport::link_type_t::CTRL);
+ return _link_mgrs.at(dev)->get_client_zero(dst_epid);
}
virtual std::tuple<sep_id_pair_t, stream_buff_params_t>
@@ -184,8 +194,12 @@ public:
const device_id_t via_device,
const device_addr_t& xport_args)
{
- return _link_mgrs.at(_check_dst_and_find_src(src_addr, via_device))
- ->create_device_to_host_data_stream(src_addr,
+ auto dev = _check_dst_and_find_src(src_addr, via_device,
+ uhd::transport::link_type_t::RX_DATA);
+ auto allocs = _alloc_map.at(dev);
+ allocs.rx++;
+ _alloc_map[dev] = allocs;
+ return _link_mgrs.at(dev)->create_device_to_host_data_stream(src_addr,
pyld_buff_fmt,
mdata_buff_fmt,
xport_args);
@@ -198,8 +212,12 @@ public:
const device_id_t via_device,
const device_addr_t& xport_args)
{
- return _link_mgrs.at(_check_dst_and_find_src(dst_addr, via_device))
- ->create_host_to_device_data_stream(dst_addr,
+ auto dev = _check_dst_and_find_src(dst_addr, via_device,
+ uhd::transport::link_type_t::TX_DATA);
+ auto allocs = _alloc_map.at(dev);
+ allocs.tx++;
+ _alloc_map[dev] = allocs;
+ return _link_mgrs.at(dev)->create_host_to_device_data_stream(dst_addr,
pyld_buff_fmt,
mdata_buff_fmt,
xport_args);
@@ -214,14 +232,37 @@ public:
}
}
private:
- device_id_t _check_dst_and_find_src(sep_addr_t dst_addr, device_id_t via_device) const
+ device_id_t _check_dst_and_find_src(sep_addr_t dst_addr, device_id_t via_device,
+ uhd::transport::link_type_t link_type) const
{
if (_src_map.count(dst_addr) > 0) {
const auto& src_devs = _src_map.at(dst_addr);
if (via_device == NULL_DEVICE_ID) {
// TODO: Maybe we can come up with a better heuristic for when the user
// gives no preference
- return src_devs[0];
+ auto dev = src_devs[0];
+ auto dev_alloc = _alloc_map.at(dev);
+ for (auto candidate : src_devs) {
+ auto candidate_alloc = _alloc_map.at(candidate);
+ switch (link_type) {
+ case uhd::transport::link_type_t::TX_DATA:
+ if (candidate_alloc.tx < dev_alloc.tx) {
+ dev = candidate;
+ dev_alloc = candidate_alloc;
+ }
+ break;
+ case uhd::transport::link_type_t::RX_DATA:
+ if (candidate_alloc.rx < dev_alloc.rx) {
+ dev = candidate;
+ dev_alloc = candidate_alloc;
+ }
+ break;
+ default:
+ // Just accept first device for CTRL and ASYNC_MSG
+ break;
+ }
+ }
+ return dev;
} else {
for (const auto& src : src_devs) {
if (src == via_device) {
@@ -244,6 +285,18 @@ private:
std::set<sep_addr_t> _reachable_endpoints;
// A map of addresses that can be taken to reach a particular destination
std::map<sep_addr_t, std::vector<device_id_t>> _src_map;
+
+ // Data used for heuristic to determine which link to use
+ struct allocation_info {
+ size_t rx;
+ size_t tx;
+ };
+
+ // A map of allocations for each local_device
+ // NOTE: Multiple local device IDs can refer to the same local xport adapter.
+ // The scheme does not account for a NIC that is used to connect to multiple
+ // remote devices, for example.
+ std::map<device_id_t, allocation_info> _alloc_map;
};
graph_stream_manager::uptr graph_stream_manager::make(