From 65713fa6f5dd534da1dcc34a7fb4baeeccc5d4c8 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Sat, 20 May 2017 17:44:01 -0700 Subject: Rename netd to mpmd --- host/lib/CMakeLists.txt | 4 +- host/lib/deps/CMakeLists.txt | 2 +- host/lib/usrp/CMakeLists.txt | 2 +- host/lib/usrp/dboard/eiscat/CMakeLists.txt | 4 +- host/lib/usrp/dboard/magnesium/CMakeLists.txt | 4 +- host/lib/usrp/mpmd/CMakeLists.txt | 26 ++ host/lib/usrp/mpmd/mpmd_impl.cpp | 378 ++++++++++++++++++++++++++ host/lib/usrp/mpmd/mpmd_impl.hpp | 93 +++++++ host/lib/usrp/netd/CMakeLists.txt | 29 -- host/lib/usrp/netd/netd_impl.cpp | 378 -------------------------- host/lib/usrp/netd/netd_impl.hpp | 93 ------- 11 files changed, 505 insertions(+), 508 deletions(-) create mode 100644 host/lib/usrp/mpmd/CMakeLists.txt create mode 100644 host/lib/usrp/mpmd/mpmd_impl.cpp create mode 100644 host/lib/usrp/mpmd/mpmd_impl.hpp delete mode 100644 host/lib/usrp/netd/CMakeLists.txt delete mode 100644 host/lib/usrp/netd/netd_impl.cpp delete mode 100644 host/lib/usrp/netd/netd_impl.hpp (limited to 'host') diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index a1c5648ad..bfc8ddc11 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -72,7 +72,7 @@ LIBUHD_REGISTER_COMPONENT("USRP1" ENABLE_USRP1 ON "ENABLE_LIBUHD;ENABLE_USB" OFF LIBUHD_REGISTER_COMPONENT("USRP2" ENABLE_USRP2 ON "ENABLE_LIBUHD" OFF OFF) LIBUHD_REGISTER_COMPONENT("X300" ENABLE_X300 ON "ENABLE_LIBUHD" OFF OFF) LIBUHD_REGISTER_COMPONENT("N230" ENABLE_N230 ON "ENABLE_LIBUHD" OFF OFF) -LIBUHD_REGISTER_COMPONENT("NETD" ENABLE_NETD ON "ENABLE_LIBUHD" OFF OFF) +LIBUHD_REGISTER_COMPONENT("MPMD" ENABLE_MPMD ON "ENABLE_LIBUHD" OFF OFF) LIBUHD_REGISTER_COMPONENT("OctoClock" ENABLE_OCTOCLOCK ON "ENABLE_LIBUHD" OFF OFF) ######################################################################## @@ -165,7 +165,7 @@ ENDIF(MSVC) ######################################################################## # Setup libuhd library ######################################################################## -IF(ENABLE_NETD) +IF(ENABLE_MPMD) INCLUDE_DIRECTORIES(deps/rpclib/include) ADD_SUBDIRECTORY(deps) LIST(APPEND libuhd_sources $) diff --git a/host/lib/deps/CMakeLists.txt b/host/lib/deps/CMakeLists.txt index bcb89d29a..8f292d4f2 100644 --- a/host/lib/deps/CMakeLists.txt +++ b/host/lib/deps/CMakeLists.txt @@ -14,6 +14,6 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . # -IF(ENABLE_NETD) +IF(ENABLE_MPMD) ADD_SUBDIRECTORY(rpclib) ENDIF() diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt index 0f8172d41..7515a9bb0 100644 --- a/host/lib/usrp/CMakeLists.txt +++ b/host/lib/usrp/CMakeLists.txt @@ -41,7 +41,7 @@ INCLUDE_SUBDIRECTORY(cores) INCLUDE_SUBDIRECTORY(dboard) INCLUDE_SUBDIRECTORY(common) INCLUDE_SUBDIRECTORY(device3) -INCLUDE_SUBDIRECTORY(netd) +INCLUDE_SUBDIRECTORY(mpmd) INCLUDE_SUBDIRECTORY(usrp1) INCLUDE_SUBDIRECTORY(usrp2) INCLUDE_SUBDIRECTORY(b100) diff --git a/host/lib/usrp/dboard/eiscat/CMakeLists.txt b/host/lib/usrp/dboard/eiscat/CMakeLists.txt index bd55dcc14..c1ff10b3d 100644 --- a/host/lib/usrp/dboard/eiscat/CMakeLists.txt +++ b/host/lib/usrp/dboard/eiscat/CMakeLists.txt @@ -15,10 +15,10 @@ # along with this program. If not, see . # -IF(ENABLE_NETD AND ENABLE_EISCAT) +IF(ENABLE_MPMD AND ENABLE_EISCAT) LIST(APPEND EISCAT_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/eiscat_radio_ctrl_impl.cpp ) LIBUHD_APPEND_SOURCES(${EISCAT_SOURCES}) -ENDIF(ENABLE_NETD AND ENABLE_EISCAT) +ENDIF(ENABLE_MPMD AND ENABLE_EISCAT) diff --git a/host/lib/usrp/dboard/magnesium/CMakeLists.txt b/host/lib/usrp/dboard/magnesium/CMakeLists.txt index 6d3f53fba..07677b8c9 100644 --- a/host/lib/usrp/dboard/magnesium/CMakeLists.txt +++ b/host/lib/usrp/dboard/magnesium/CMakeLists.txt @@ -15,10 +15,10 @@ # along with this program. If not, see . # -IF(ENABLE_NETD) +IF(ENABLE_MPMD) LIST(APPEND MAGNESIUM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/magnesium_radio_ctrl_impl.cpp ) LIBUHD_APPEND_SOURCES(${MAGNESIUM_SOURCES}) -ENDIF(ENABLE_NETD) +ENDIF(ENABLE_MPMD) diff --git a/host/lib/usrp/mpmd/CMakeLists.txt b/host/lib/usrp/mpmd/CMakeLists.txt new file mode 100644 index 000000000..5ff1f36eb --- /dev/null +++ b/host/lib/usrp/mpmd/CMakeLists.txt @@ -0,0 +1,26 @@ +# +# Copyright 2017 Ettus Research (National Instruments) +# +# 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 . +# + +######################################################################## +# This file included, use CMake directory variables +######################################################################## + +IF(ENABLE_MPMD) + LIBUHD_APPEND_SOURCES( + ${CMAKE_CURRENT_SOURCE_DIR}/mpmd_impl.cpp + ) +ENDIF(ENABLE_MPMD) diff --git a/host/lib/usrp/mpmd/mpmd_impl.cpp b/host/lib/usrp/mpmd/mpmd_impl.cpp new file mode 100644 index 000000000..1caec550e --- /dev/null +++ b/host/lib/usrp/mpmd/mpmd_impl.cpp @@ -0,0 +1,378 @@ +// +// Copyright 2017 Ettus Research (National Instruments) +// +// 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 . +// + +#include "mpmd_impl.hpp" +#include <../device3/device3_impl.hpp> +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace uhd; + +mpmd_mboard_impl::mpmd_mboard_impl(const std::string& addr) + : rpc(addr, MPM_RPC_PORT) +{ + UHD_LOG_TRACE("MPMD", "Initializing mboard, IP address: " << addr); + std::map _dev_info = + rpc.call("get_device_info"); + device_info = + dict(_dev_info.begin(), _dev_info.end()); + // Get initial claim on mboard + _rpc_token = rpc.call("claim", "UHD - Session 01"); // make this configurable with device_addr? + if (_rpc_token.empty()){ + throw uhd::value_error("mpmd device claiming failed!"); + } + _claimer_task = task::make([this] { + if (not this->claim()) { + throw uhd::value_error("mpmd device reclaiming loop failed!"); + }; + boost::this_thread::sleep_for(boost::chrono::milliseconds(1000)); + }); + // std::vector data_ifaces = + // rpc.call>("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 addrs = rpc.call>( + //"get_interface_addrs", _rpc_token, iface); + //for (const auto& iface_addr : addrs) { + //if (rpc_client(iface_addr, MPM_RPC_PORT) + //.call("probe_interface", _rpc_token)) { + //data_interfaces.emplace(iface, iface_addr); + //break; + //} + //} + //} +} + +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 sid = rpc.call("allocate_sid", _rpc_token, port, + address.get(), xbar_src_addr, xbar_src_port); + return sid; +} +mpmd_mboard_impl::~mpmd_mboard_impl() {} + +mpmd_mboard_impl::uptr mpmd_mboard_impl::make(const std::string& addr) +{ + mpmd_mboard_impl::uptr mb = + mpmd_mboard_impl::uptr(new mpmd_mboard_impl(addr)); + // implicit move + return mb; +} + +bool mpmd_mboard_impl::claim() { return rpc.call("reclaim", _rpc_token); } + +mpmd_impl::mpmd_impl(const device_addr_t& device_addr) + : usrp::device3_impl() + , _device_addr(device_addr) + , _sid_framer(0) +{ + UHD_LOGGER_INFO("MPMD") << "MPMD initialization sequence. Device args: " << device_addr.to_string(); + _tree->create("/name").set("MPMD - Series device"); + const device_addrs_t device_args = separate_device_addr(device_addr); + _mb.reserve(device_args.size()); + for (size_t mb_i = 0; mb_i < device_args.size(); ++mb_i) { + _mb.push_back(setup_mb(mb_i, device_args[mb_i])); + } + + try { + enumerate_rfnoc_blocks( + 0, + 3, /* num blocks */ + 3, /* base port */ + uhd::sid_t(0x0200), + device_addr + ); + } catch (const std::exception &ex) { + UHD_HERE(); + std::cout << ex.what() << std::endl; + } +} + +mpmd_impl::~mpmd_impl() {} + +mpmd_mboard_impl::uptr mpmd_impl::setup_mb(const size_t mb_i, + const uhd::device_addr_t& dev_addr) +{ + const fs_path mb_path = "/mboards/" + std::to_string(mb_i); + mpmd_mboard_impl::uptr mb = mpmd_mboard_impl::make(dev_addr["addr"]); + mb->initialization_done = false; + std::vector addrs; + const std::string eth0_addr = dev_addr["addr"]; + _tree->create(mb_path / "name") + .set(mb->device_info.get("type", "")); + _tree->create(mb_path / "serial") + .set(mb->device_info.get("serial", "")); + _tree->create(mb_path / "connection") + .set(mb->device_info.get("connection", "remote")); + + for (const std::string& key : dev_addr.keys()) { + if (key.find("recv") != std::string::npos) + mb->recv_args[key] = dev_addr[key]; + if (key.find("send") != std::string::npos) + mb->send_args[key] = dev_addr[key]; + } + + // Do real MTU discovery (something similar like X300 but with MPM) + + _tree->create(mb_path / "mtu/recv").set(1500); + _tree->create(mb_path / "mtu/send").set(1500); + _tree->create(mb_path / "link_max_rate").set(1e9 / 8); + + // query more information about FPGA/MPM + + // Call init on periph_manager, this will init the dboards/mboard, maybe + // even selfcal and everything + + // Query time/clock sources on mboards/dboards + // Throw rpc calls with boost bind into the property tree? + + // Query rfnoc blocks on the device (MPM may know about them?) + + // call enumerate rfnoc_blocks on the device + + // configure radio? + + // implicit move + return mb; +} + + +// TODO this does not consider the liberio use case! +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(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(MPMD_RX_SW_BUFF_SIZE_ETH); + #endif + } + return rx_hints; +} + + +// frame_size_t determine_max_frame_size(const std::string &addr, +// const frame_size_t &user_frame_size){ +// transport::udp_simple::sptr udp = +// transport::udp_simple::make_connected(addr, +// std::to_string(MPM_DISCOVERY_PORT)); +// std::vector buffer(std::max(user_frame_size.rec)) +// } +// Everything fake below here + +both_xports_t mpmd_impl::make_transport(const sid_t& address, + usrp::device3_impl::xport_type_t xport_type, + const uhd::device_addr_t& args) +{ + //const size_t mb_index = address.get_dst_addr(); + size_t mb_index = 0; + + both_xports_t xports; + xports.endianness = uhd::ENDIANNESS_BIG; + const uhd::device_addr_t& xport_args = (xport_type == CTRL) ? uhd::device_addr_t() : args; + transport::zero_copy_xport_params default_buff_args; + + /* + std::cout << address << std::endl; + std::cout << address.get_src_addr() << std::endl; + std::cout << address.get_dst_addr() << std::endl; + */ + + std::string interface_addr = _device_addr["addr"]; + const uint32_t xbar_src_addr = address.get_src_addr(); + const uint32_t xbar_src_dst = 0; + + 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; + // hardcode frame size for now + + transport::udp_zero_copy::buff_params buff_params; + auto recv = transport::udp_zero_copy::make( + interface_addr, + BOOST_STRINGIZE(49153), + default_buff_args, + buff_params, + xport_args); + uint16_t port = recv->get_local_port(); + + xports.send_sid = _mb[mb_index]->allocate_sid(port, address, xbar_src_addr, xbar_src_dst); + 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; + xports.send = xports.recv; + + return xports; +} + +device_addrs_t mpmd_find_with_addr(const device_addr_t& hint_) +{ + transport::udp_simple::sptr comm = transport::udp_simple::make_broadcast( + hint_["addr"], std::to_string(MPM_DISCOVERY_PORT)); + comm->send( + boost::asio::buffer(&MPM_DISCOVERY_CMD, sizeof(MPM_DISCOVERY_CMD))); + device_addrs_t addrs; + while (true) { + char buff[4096] = {}; + const size_t nbytes = comm->recv(boost::asio::buffer(buff), 0.050); + if (nbytes == 0) { + break; + } + const char* reply = (const char*)buff; + std::string reply_string = std::string(reply); + std::vector result; + boost::algorithm::split(result, reply_string, + [](const char& in) { return in == ';'; }, + boost::token_compress_on); + if (result.empty()) { + continue; + } + // who else is reposending to our request !? + if (result[0] != "USRP-MPM") { + continue; + } + const std::string recv_addr = comm->get_recv_addr(); + + // remove external iface addrs if executed directly on device + bool external_iface = false; + for (const auto& addr : transport::get_if_addrs()) { + if ((addr.inet == comm->get_recv_addr()) && + recv_addr != + boost::asio::ip::address_v4::loopback().to_string()) { + external_iface = true; + } + } + if (external_iface) { + continue; + } + device_addr_t new_addr; + new_addr["addr"] = recv_addr; + new_addr["type"] = "mpmd"; // hwd will overwrite this + // remove ident string and put other informations into device_addr dict + result.erase(result.begin()); + // parse key-value pairs in the discovery string and add them to the + // device_addr + for (const auto& el : result) { + std::vector value; + boost::algorithm::split(value, el, + [](const char& in) { return in == '='; }, + boost::token_compress_on); + new_addr[value[0]] = value[1]; + } + addrs.push_back(new_addr); + } + return addrs; +}; + +device_addrs_t mpmd_find(const device_addr_t& hint_) +{ + // handle cases: + // + // - empty hint + // - multiple addrs + // - single addr + + device_addrs_t hints = separate_device_addr(hint_); + // either hints has: + // multiple entries + // -> search for multiple devices and join them back into one + // device_addr_t + // one entry with addr: + // -> search for one device with this addr + // one + // multiple addrs + if (hints.size() > 1) { + device_addrs_t found_devices; + found_devices.reserve(hints.size()); + for (const auto& hint : hints) { + if (not hint.has_key("addr")) { // maybe allow other attributes as well + return device_addrs_t(); + } + device_addrs_t reply_addrs = mpmd_find_with_addr(hint); + if (reply_addrs.size() > 1) { + throw uhd::value_error( + str(boost::format("Could not resolve device hint \"%s\" to " + "a single device.") % + hint.to_string())); + } else if (reply_addrs.empty()) { + return device_addrs_t(); + } + found_devices.push_back(reply_addrs[0]); + } + return device_addrs_t(1, combine_device_addrs(found_devices)); + } + hints.resize(1); + device_addr_t hint = hints[0]; + device_addrs_t addrs; + + if (hint.has_key("addr")) { + // is this safe? + return mpmd_find_with_addr(hint); + } + + for (const transport::if_addrs_t& if_addr : transport::get_if_addrs()) { + device_addr_t new_hint = hint; + new_hint["addr"] = if_addr.bcast; + + device_addrs_t reply_addrs = mpmd_find_with_addr(new_hint); + addrs.insert(addrs.begin(), reply_addrs.begin(), reply_addrs.end()); + } + return addrs; +} + +static device::sptr mpmd_make(const device_addr_t& device_addr) +{ + return device::sptr(boost::make_shared(device_addr)); +} + +UHD_STATIC_BLOCK(register_mpmd_device) +{ + device::register_device(&mpmd_find, &mpmd_make, device::USRP); +} +// vim: sw=4 expandtab: diff --git a/host/lib/usrp/mpmd/mpmd_impl.hpp b/host/lib/usrp/mpmd/mpmd_impl.hpp new file mode 100644 index 000000000..3b6a4b213 --- /dev/null +++ b/host/lib/usrp/mpmd/mpmd_impl.hpp @@ -0,0 +1,93 @@ +// +// Copyright 2017 Ettus Research (National Instruments) +// +// 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 . +// + +#ifndef INCLUDED_MPMD_IMPL_HPP +#define INCLUDED_MPMD_IMPL_HPP +#include "../../utils/rpc.hpp" +#include "../device3/device3_impl.hpp" +#include +#include +#include +#include +#include + +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_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 + +struct frame_size_t +{ + size_t recv_frame_size; + size_t send_frame_size; +}; + +class mpmd_mboard_impl +{ + public: + using uptr = std::unique_ptr; + using dev_info = std::map; + mpmd_mboard_impl(const std::string& addr); + ~mpmd_mboard_impl(); + static uptr make(const std::string& addr); + + bool initialization_done = false; + uhd::dict device_info; + uhd::dict recv_args; + uhd::dict send_args; + std::map data_interfaces; + std::string loaded_fpga_image; + std::string xport_path; + uhd::rpc_client rpc; + 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); + + private: + bool claim(); + std::string generate_token() const; + std::string _rpc_token; + uhd::task::sptr _claimer_task; +}; + +class mpmd_impl : public uhd::usrp::device3_impl +{ + public: + mpmd_impl(const uhd::device_addr_t& device_addr); + ~mpmd_impl(); + + mpmd_mboard_impl::uptr setup_mb(const size_t mb_i, + const uhd::device_addr_t& dev_addr); + 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 _device_addr; + std::vector _mb; + size_t _sid_framer; +}; +uhd::device_addrs_t mpmd_find(const uhd::device_addr_t& hint_); +#endif /* INCLUDED_MPMD_IMPL_HPP */ +// vim: sw=4 expandtab: diff --git a/host/lib/usrp/netd/CMakeLists.txt b/host/lib/usrp/netd/CMakeLists.txt deleted file mode 100644 index a33c978c8..000000000 --- a/host/lib/usrp/netd/CMakeLists.txt +++ /dev/null @@ -1,29 +0,0 @@ -# -# Copyright 2017 Ettus Research (National Instruments) -# -# 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 . -# - -######################################################################## -# This file included, use CMake directory variables -######################################################################## - -######################################################################## -# Conditionally configure the X300 support -######################################################################## -IF(ENABLE_NETD) - LIBUHD_APPEND_SOURCES( - ${CMAKE_CURRENT_SOURCE_DIR}/netd_impl.cpp - ) -ENDIF(ENABLE_NETD) diff --git a/host/lib/usrp/netd/netd_impl.cpp b/host/lib/usrp/netd/netd_impl.cpp deleted file mode 100644 index d57fbd901..000000000 --- a/host/lib/usrp/netd/netd_impl.cpp +++ /dev/null @@ -1,378 +0,0 @@ -// -// Copyright 2017 Ettus Research (National Instruments) -// -// 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 . -// - -#include "netd_impl.hpp" -#include <../device3/device3_impl.hpp> -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace uhd; - -netd_mboard_impl::netd_mboard_impl(const std::string& addr) - : rpc(addr, MPM_RPC_PORT) -{ - UHD_LOG_TRACE("MPMD", "Initializing mboard, IP address: " << addr); - std::map _dev_info = - rpc.call("get_device_info"); - device_info = - dict(_dev_info.begin(), _dev_info.end()); - // Get initial claim on mboard - _rpc_token = rpc.call("claim", "UHD - Session 01"); // make this configurable with device_addr? - if (_rpc_token.empty()){ - throw uhd::value_error("netd device claiming failed!"); - } - _claimer_task = task::make([this] { - if (not this->claim()) { - throw uhd::value_error("netd device reclaiming loop failed!"); - }; - boost::this_thread::sleep_for(boost::chrono::milliseconds(1000)); - }); - // std::vector data_ifaces = - // rpc.call>("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 addrs = rpc.call>( - //"get_interface_addrs", _rpc_token, iface); - //for (const auto& iface_addr : addrs) { - //if (rpc_client(iface_addr, MPM_RPC_PORT) - //.call("probe_interface", _rpc_token)) { - //data_interfaces.emplace(iface, iface_addr); - //break; - //} - //} - //} -} - -uhd::sid_t netd_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 sid = rpc.call("allocate_sid", _rpc_token, port, - address.get(), xbar_src_addr, xbar_src_port); - return sid; -} -netd_mboard_impl::~netd_mboard_impl() {} - -netd_mboard_impl::uptr netd_mboard_impl::make(const std::string& addr) -{ - netd_mboard_impl::uptr mb = - netd_mboard_impl::uptr(new netd_mboard_impl(addr)); - // implicit move - return mb; -} - -bool netd_mboard_impl::claim() { return rpc.call("reclaim", _rpc_token); } - -netd_impl::netd_impl(const device_addr_t& device_addr) - : usrp::device3_impl() - , _device_addr(device_addr) - , _sid_framer(0) -{ - UHD_LOGGER_INFO("NETD") << "NETD initialization sequence. Device args: " << device_addr.to_string(); - _tree->create("/name").set("NETD - Series device"); - const device_addrs_t device_args = separate_device_addr(device_addr); - _mb.reserve(device_args.size()); - for (size_t mb_i = 0; mb_i < device_args.size(); ++mb_i) { - _mb.push_back(setup_mb(mb_i, device_args[mb_i])); - } - - try { - enumerate_rfnoc_blocks( - 0, - 3, /* num blocks */ - 3, /* base port */ - uhd::sid_t(0x0200), - device_addr - ); - } catch (const std::exception &ex) { - UHD_HERE(); - std::cout << ex.what() << std::endl; - } -} - -netd_impl::~netd_impl() {} - -netd_mboard_impl::uptr netd_impl::setup_mb(const size_t mb_i, - const uhd::device_addr_t& dev_addr) -{ - const fs_path mb_path = "/mboards/" + std::to_string(mb_i); - netd_mboard_impl::uptr mb = netd_mboard_impl::make(dev_addr["addr"]); - mb->initialization_done = false; - std::vector addrs; - const std::string eth0_addr = dev_addr["addr"]; - _tree->create(mb_path / "name") - .set(mb->device_info.get("type", "")); - _tree->create(mb_path / "serial") - .set(mb->device_info.get("serial", "")); - _tree->create(mb_path / "connection") - .set(mb->device_info.get("connection", "remote")); - - for (const std::string& key : dev_addr.keys()) { - if (key.find("recv") != std::string::npos) - mb->recv_args[key] = dev_addr[key]; - if (key.find("send") != std::string::npos) - mb->send_args[key] = dev_addr[key]; - } - - // Do real MTU discovery (something similar like X300 but with MPM) - - _tree->create(mb_path / "mtu/recv").set(1500); - _tree->create(mb_path / "mtu/send").set(1500); - _tree->create(mb_path / "link_max_rate").set(1e9 / 8); - - // query more information about FPGA/MPM - - // Call init on periph_manager, this will init the dboards/mboard, maybe - // even selfcal and everything - - // Query time/clock sources on mboards/dboards - // Throw rpc calls with boost bind into the property tree? - - // Query rfnoc blocks on the device (MPM may know about them?) - - // call enumerate rfnoc_blocks on the device - - // configure radio? - - // implicit move - return mb; -} - - -// TODO this does not consider the liberio use case! -uhd::device_addr_t netd_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(NETD_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(NETD_RX_SW_BUFF_SIZE_ETH); - #endif - } - return rx_hints; -} - - -// frame_size_t determine_max_frame_size(const std::string &addr, -// const frame_size_t &user_frame_size){ -// transport::udp_simple::sptr udp = -// transport::udp_simple::make_connected(addr, -// std::to_string(MPM_DISCOVERY_PORT)); -// std::vector buffer(std::max(user_frame_size.rec)) -// } -// Everything fake below here - -both_xports_t netd_impl::make_transport(const sid_t& address, - usrp::device3_impl::xport_type_t xport_type, - const uhd::device_addr_t& args) -{ - //const size_t mb_index = address.get_dst_addr(); - size_t mb_index = 0; - - both_xports_t xports; - xports.endianness = uhd::ENDIANNESS_BIG; - const uhd::device_addr_t& xport_args = (xport_type == CTRL) ? uhd::device_addr_t() : args; - transport::zero_copy_xport_params default_buff_args; - - /* - std::cout << address << std::endl; - std::cout << address.get_src_addr() << std::endl; - std::cout << address.get_dst_addr() << std::endl; - */ - - std::string interface_addr = _device_addr["addr"]; - const uint32_t xbar_src_addr = address.get_src_addr(); - const uint32_t xbar_src_dst = 0; - - 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; - // hardcode frame size for now - - transport::udp_zero_copy::buff_params buff_params; - auto recv = transport::udp_zero_copy::make( - interface_addr, - BOOST_STRINGIZE(49153), - default_buff_args, - buff_params, - xport_args); - uint16_t port = recv->get_local_port(); - - xports.send_sid = _mb[mb_index]->allocate_sid(port, address, xbar_src_addr, xbar_src_dst); - 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; - xports.send = xports.recv; - - return xports; -} - -device_addrs_t netd_find_with_addr(const device_addr_t& hint_) -{ - transport::udp_simple::sptr comm = transport::udp_simple::make_broadcast( - hint_["addr"], std::to_string(MPM_DISCOVERY_PORT)); - comm->send( - boost::asio::buffer(&MPM_DISCOVERY_CMD, sizeof(MPM_DISCOVERY_CMD))); - device_addrs_t addrs; - while (true) { - char buff[4096] = {}; - const size_t nbytes = comm->recv(boost::asio::buffer(buff), 0.050); - if (nbytes == 0) { - break; - } - const char* reply = (const char*)buff; - std::string reply_string = std::string(reply); - std::vector result; - boost::algorithm::split(result, reply_string, - [](const char& in) { return in == ';'; }, - boost::token_compress_on); - if (result.empty()) { - continue; - } - // who else is reposending to our request !? - if (result[0] != "USRP-MPM") { - continue; - } - const std::string recv_addr = comm->get_recv_addr(); - - // remove external iface addrs if executed directly on device - bool external_iface = false; - for (const auto& addr : transport::get_if_addrs()) { - if ((addr.inet == comm->get_recv_addr()) && - recv_addr != - boost::asio::ip::address_v4::loopback().to_string()) { - external_iface = true; - } - } - if (external_iface) { - continue; - } - device_addr_t new_addr; - new_addr["addr"] = recv_addr; - new_addr["type"] = "netd"; // hwd will overwrite this - // remove ident string and put other informations into device_addr dict - result.erase(result.begin()); - // parse key-value pairs in the discovery string and add them to the - // device_addr - for (const auto& el : result) { - std::vector value; - boost::algorithm::split(value, el, - [](const char& in) { return in == '='; }, - boost::token_compress_on); - new_addr[value[0]] = value[1]; - } - addrs.push_back(new_addr); - } - return addrs; -}; - -device_addrs_t netd_find(const device_addr_t& hint_) -{ - // handle cases: - // - // - empty hint - // - multiple addrs - // - single addr - - device_addrs_t hints = separate_device_addr(hint_); - // either hints has: - // multiple entries - // -> search for multiple devices and join them back into one - // device_addr_t - // one entry with addr: - // -> search for one device with this addr - // one - // multiple addrs - if (hints.size() > 1) { - device_addrs_t found_devices; - found_devices.reserve(hints.size()); - for (const auto& hint : hints) { - if (not hint.has_key("addr")) { // maybe allow other attributes as well - return device_addrs_t(); - } - device_addrs_t reply_addrs = netd_find_with_addr(hint); - if (reply_addrs.size() > 1) { - throw uhd::value_error( - str(boost::format("Could not resolve device hint \"%s\" to " - "a single device.") % - hint.to_string())); - } else if (reply_addrs.empty()) { - return device_addrs_t(); - } - found_devices.push_back(reply_addrs[0]); - } - return device_addrs_t(1, combine_device_addrs(found_devices)); - } - hints.resize(1); - device_addr_t hint = hints[0]; - device_addrs_t addrs; - - if (hint.has_key("addr")) { - // is this safe? - return netd_find_with_addr(hint); - } - - for (const transport::if_addrs_t& if_addr : transport::get_if_addrs()) { - device_addr_t new_hint = hint; - new_hint["addr"] = if_addr.bcast; - - device_addrs_t reply_addrs = netd_find_with_addr(new_hint); - addrs.insert(addrs.begin(), reply_addrs.begin(), reply_addrs.end()); - } - return addrs; -} - -static device::sptr netd_make(const device_addr_t& device_addr) -{ - return device::sptr(boost::make_shared(device_addr)); -} - -UHD_STATIC_BLOCK(register_netd_device) -{ - device::register_device(&netd_find, &netd_make, device::USRP); -} -// vim: sw=4 expandtab: diff --git a/host/lib/usrp/netd/netd_impl.hpp b/host/lib/usrp/netd/netd_impl.hpp deleted file mode 100644 index b8a3988f2..000000000 --- a/host/lib/usrp/netd/netd_impl.hpp +++ /dev/null @@ -1,93 +0,0 @@ -// -// Copyright 2017 Ettus Research (National Instruments) -// -// 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 . -// - -#ifndef INCLUDED_NETD_IMPL_HPP -#define INCLUDED_NETD_IMPL_HPP -#include "../../utils/rpc.hpp" -#include "../device3/device3_impl.hpp" -#include -#include -#include -#include -#include - -static const size_t NETD_RX_SW_BUFF_SIZE_ETH = 0x2000000;//32MiB For an ~8k frame size any size >32MiB is just wasted buffer space -static const size_t NETD_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_DISCOVERY_CMD[] = "MPM-DISC"; -static const char MPM_ECHO_CMD[] = "MPM-ECHO"; -static const size_t NETD_10GE_DATA_FRAME_MAX_SIZE = 8000; // CHDR packet size in bytes - -struct frame_size_t -{ - size_t recv_frame_size; - size_t send_frame_size; -}; - -class netd_mboard_impl -{ - public: - using uptr = std::unique_ptr; - using dev_info = std::map; - netd_mboard_impl(const std::string& addr); - ~netd_mboard_impl(); - static uptr make(const std::string& addr); - - bool initialization_done = false; - uhd::dict device_info; - uhd::dict recv_args; - uhd::dict send_args; - std::map data_interfaces; - std::string loaded_fpga_image; - std::string xport_path; - uhd::rpc_client rpc; - 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); - - private: - bool claim(); - std::string generate_token() const; - std::string _rpc_token; - uhd::task::sptr _claimer_task; -}; - -class netd_impl : public uhd::usrp::device3_impl -{ - public: - netd_impl(const uhd::device_addr_t& device_addr); - ~netd_impl(); - - netd_mboard_impl::uptr setup_mb(const size_t mb_i, - const uhd::device_addr_t& dev_addr); - 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 _device_addr; - std::vector _mb; - size_t _sid_framer; -}; -uhd::device_addrs_t netd_find(const uhd::device_addr_t& hint_); -#endif /* INCLUDED_NETD_IMPL_HPP */ -// vim: sw=4 expandtab: -- cgit v1.2.3