1 //
2 // Copyright 2017 Ettus Research, National Instruments Company
3 // Copyright 2019 Ettus Research, National Instruments Brand
4 //
5 // SPDX-License-Identifier: GPL-3.0-or-later
6 //
7 
8 #include "mpmd_link_if_mgr.hpp"
9 #include "mpmd_impl.hpp"
10 #include "mpmd_link_if_ctrl_base.hpp"
11 #include "mpmd_link_if_ctrl_udp.hpp"
12 
filter_args(const uhd::device_addr_t & args,const std::string & prefix)13 uhd::dict<std::string, std::string> uhd::mpmd::xport::filter_args(
14     const uhd::device_addr_t& args, const std::string& prefix)
15 {
16     uhd::dict<std::string, std::string> filtered_args;
17     for (const std::string& key : args.keys()) {
18         if (key.find(prefix) != std::string::npos) {
19             filtered_args[key] = args[key];
20         }
21     }
22 
23     return filtered_args;
24 }
25 
26 using namespace uhd::mpmd::xport;
27 
28 class mpmd_link_if_mgr_impl : public mpmd_link_if_mgr
29 {
30 public:
mpmd_link_if_mgr_impl(const uhd::device_addr_t & mb_args)31     mpmd_link_if_mgr_impl(const uhd::device_addr_t& mb_args) : _mb_args(mb_args) {}
32 
33     /**************************************************************************
34      * API (see mpmd_link_if_mgr.hpp)
35      *************************************************************************/
connect(const std::string & link_type,const xport_info_list_t & xport_info,const uhd::rfnoc::chdr_w_t chdr_w)36     bool connect(const std::string& link_type,
37         const xport_info_list_t& xport_info,
38         const uhd::rfnoc::chdr_w_t chdr_w)
39     {
40         auto link_if_ctrl = make_link_if_ctrl(link_type, xport_info, chdr_w);
41         if (!link_if_ctrl) {
42             UHD_LOG_WARNING(
43                 "MPMD::XPORT", "Unable to create xport ctrl for link type " << link_type);
44             return false;
45         }
46         if (link_if_ctrl->get_num_links() == 0) {
47             UHD_LOG_TRACE("MPMD::XPORT",
48                 "Link type " << link_type
49                              << " has no valid links in this configuration.");
50             return false;
51         }
52         const size_t xport_idx = _link_if_ctrls.size();
53         for (size_t link_idx = 0; link_idx < link_if_ctrl->get_num_links(); link_idx++) {
54             _link_link_if_ctrl_map.push_back(std::make_pair(xport_idx, link_idx));
55         }
56         _link_if_ctrls.push_back(std::move(link_if_ctrl));
57         return true;
58     }
59 
get_num_links()60     size_t get_num_links()
61     {
62         return _link_link_if_ctrl_map.size();
63     }
64 
get_link(const size_t link_idx,const uhd::transport::link_type_t link_type,const uhd::device_addr_t & link_args)65     uhd::transport::both_links_t get_link(const size_t link_idx,
66         const uhd::transport::link_type_t link_type,
67         const uhd::device_addr_t& link_args)
68     {
69         const size_t link_if_ctrl_idx = _link_link_if_ctrl_map.at(link_idx).first;
70         const size_t xport_link_idx   = _link_link_if_ctrl_map.at(link_idx).second;
71         return _link_if_ctrls.at(link_if_ctrl_idx)
72             ->get_link(xport_link_idx, link_type, link_args);
73     }
74 
get_mtu(const size_t link_idx,const uhd::direction_t dir) const75     size_t get_mtu(const size_t link_idx, const uhd::direction_t dir) const
76     {
77         return _link_if_ctrls.at(_link_link_if_ctrl_map.at(link_idx).first)->get_mtu(dir);
78     }
79 
get_packet_factory(const size_t link_idx) const80     const uhd::rfnoc::chdr::chdr_packet_factory& get_packet_factory(
81         const size_t link_idx) const
82     {
83         const size_t link_if_ctrl_idx = _link_link_if_ctrl_map.at(link_idx).first;
84         return _link_if_ctrls.at(link_if_ctrl_idx)->get_packet_factory();
85     }
86 
87 private:
88     /**************************************************************************
89      * Private methods / helpers
90      *************************************************************************/
make_link_if_ctrl(const std::string & link_type,const xport_info_list_t & xport_info,const uhd::rfnoc::chdr_w_t chdr_w)91     mpmd_link_if_ctrl_base::uptr make_link_if_ctrl(const std::string& link_type,
92         const xport_info_list_t& xport_info,
93         const uhd::rfnoc::chdr_w_t chdr_w)
94     {
95         // Here, we hard-code the list of available transport types
96         if (link_type == "udp") {
97             return std::make_unique<mpmd_link_if_ctrl_udp>(_mb_args, xport_info, chdr_w);
98         }
99         UHD_LOG_WARNING("MPMD", "Cannot instantiate transport medium " << link_type);
100         return nullptr;
101     }
102 
103     /**************************************************************************
104      * Private attributes
105      *************************************************************************/
106     //! Cache available xport manager implementations
107     //
108     // Should only every be populated by connect()
109     std::vector<mpmd_link_if_ctrl_base::uptr> _link_if_ctrls;
110     // Maps link index to link_if_ctrl index. To look up the xport ctrl for link
111     // number L, do something like this:
112     // auto& link_if_ctrl = _link_if_ctrls.at(_link_link_if_ctrl_map.at(L).first);
113     std::vector<std::pair<size_t, size_t>> _link_link_if_ctrl_map;
114 
115     //! Motherboard args, can contain things like 'recv_buff_size'
116     const uhd::device_addr_t _mb_args;
117 };
118 
make(const uhd::device_addr_t & mb_args)119 mpmd_link_if_mgr::uptr mpmd_link_if_mgr::make(const uhd::device_addr_t& mb_args)
120 {
121     return std::make_unique<mpmd_link_if_mgr_impl>(mb_args);
122 }
123