diff options
-rw-r--r-- | host/lib/include/uhdlib/rfnoc/chdr_types.hpp | 33 | ||||
-rw-r--r-- | host/lib/rfnoc/chdr_types.cpp | 47 | ||||
-rw-r--r-- | host/lib/usrp/mpmd/mpmd_link_if_ctrl_udp.cpp | 7 | ||||
-rw-r--r-- | host/lib/usrp/mpmd/mpmd_link_if_ctrl_udp.hpp | 6 | ||||
-rw-r--r-- | host/lib/usrp/mpmd/mpmd_link_if_mgr.cpp | 13 | ||||
-rw-r--r-- | host/lib/usrp/mpmd/mpmd_link_if_mgr.hpp | 6 | ||||
-rw-r--r-- | host/lib/usrp/mpmd/mpmd_mb_iface.cpp | 2 | ||||
-rw-r--r-- | host/tests/rfnoc_chdr_test.cpp | 106 |
8 files changed, 192 insertions, 28 deletions
diff --git a/host/lib/include/uhdlib/rfnoc/chdr_types.hpp b/host/lib/include/uhdlib/rfnoc/chdr_types.hpp index 6e650507f..3eea40850 100644 --- a/host/lib/include/uhdlib/rfnoc/chdr_types.hpp +++ b/host/lib/include/uhdlib/rfnoc/chdr_types.hpp @@ -678,6 +678,12 @@ public: return _op_payload; } + //! Comparison operator (==) + inline bool operator==(const mgmt_op_t& rhs) const + { + return (_op_code == rhs._op_code) && (_op_payload == rhs._op_payload); + } + private: const op_code_t _op_code; const payload_t _op_payload; @@ -712,12 +718,24 @@ public: } //! Serialize the payload to a uint64_t buffer + // The RFNoC Specification section 2.2.6 specifies that for chdr widths + // greater than 64, all MSBs are 0, so we pad out the hop based on the width size_t serialize(std::vector<uint64_t>& target, - const std::function<uint64_t(uint64_t)>& conv_byte_order) const; + const std::function<uint64_t(uint64_t)>& conv_byte_order, + const size_t padding_size) const; //! Deserialize the payload from a uint64_t buffer + // The RFNoC Specification section 2.2.6 specifies that for chdr widths + // greater than 64, all MSBs are 0, so we remove padding based on the width void deserialize(std::list<uint64_t>& src, - const std::function<uint64_t(uint64_t)>& conv_byte_order); + const std::function<uint64_t(uint64_t)>& conv_byte_order, + const size_t padding_size); + + //! Comparison operator (==) + inline bool operator==(const mgmt_hop_t& rhs) const + { + return _ops == rhs._ops; + } private: std::vector<mgmt_op_t> _ops; @@ -737,9 +755,10 @@ public: inline void set_header(sep_id_t src_epid, uint16_t protover, chdr_w_t chdr_w) { - _src_epid = src_epid; - _chdr_w = chdr_w; - _protover = protover; + _src_epid = src_epid; + _chdr_w = chdr_w; + _protover = protover; + _padding_size = (chdr_w_to_bits(_chdr_w) / 64) - 1; } //! Add a management hop to this transaction @@ -814,11 +833,15 @@ public: return _src_epid; } + //! Comparison operator (==) + bool operator==(const mgmt_payload& rhs) const; + private: sep_id_t _src_epid = 0; uint16_t _protover = 0; chdr_w_t _chdr_w = CHDR_W_64; std::vector<mgmt_hop_t> _hops; + size_t _padding_size = 0; }; }}} // namespace uhd::rfnoc::chdr diff --git a/host/lib/rfnoc/chdr_types.cpp b/host/lib/rfnoc/chdr_types.cpp index 0e30dca7e..cb4642f3a 100644 --- a/host/lib/rfnoc/chdr_types.cpp +++ b/host/lib/rfnoc/chdr_types.cpp @@ -330,20 +330,25 @@ const std::string strc_payload::to_string() const //! Serialize this hop into a list of 64-bit words size_t mgmt_hop_t::serialize(std::vector<uint64_t>& target, - const std::function<uint64_t(uint64_t)>& conv_byte_order) const + const std::function<uint64_t(uint64_t)>& conv_byte_order, + const size_t padding_size) const { for (size_t i = 0; i < get_num_ops(); i++) { target.push_back( conv_byte_order((static_cast<uint64_t>(_ops.at(i).get_op_payload()) << 16) | (static_cast<uint64_t>(_ops.at(i).get_op_code()) << 8) | (static_cast<uint64_t>(get_num_ops() - i - 1) << 0))); + for (size_t j = 0; j < padding_size; j++) { + target.push_back(uint64_t(0)); + } } return get_num_ops(); } //! Deserialize this hop into from list of 64-bit words -void mgmt_hop_t::deserialize( - std::list<uint64_t>& src, const std::function<uint64_t(uint64_t)>& conv_byte_order) +void mgmt_hop_t::deserialize(std::list<uint64_t>& src, + const std::function<uint64_t(uint64_t)>& conv_byte_order, + const size_t padding_size) { _ops.clear(); size_t ops_remaining = 0; @@ -357,6 +362,10 @@ void mgmt_hop_t::deserialize( static_cast<uint64_t>((op_word >> 16))); _ops.push_back(op); src.pop_front(); + for (size_t i = 0; i < padding_size; i++) { + src.pop_front(); + } + } while (ops_remaining > 0); } @@ -381,9 +390,15 @@ size_t mgmt_payload::serialize(uint64_t* buff, | (static_cast<uint64_t>(static_cast<uint8_t>(_chdr_w) & 0x7) << 45) | (static_cast<uint64_t>(get_num_hops() & 0x3FF) << 16) | (static_cast<uint64_t>(_src_epid) << 0))); + // According to the RFNoC specification section 2.2.6, the MSBs are 0 for + // all widths greater than 64. This logic adds the padding. + for (size_t i = 0; i < _padding_size; i++) { + target.push_back(uint64_t(0)); + } + // Insert data from each hop for (const auto& hop : _hops) { - hop.serialize(target, conv_byte_order); + hop.serialize(target, conv_byte_order, _padding_size); } UHD_ASSERT_THROW(target.size() <= max_size_bytes); @@ -401,21 +416,27 @@ void mgmt_payload::deserialize(const uint64_t* buff, // We use a list and copy just for ease of implementation // These transactions are not performance critical - std::list<uint64_t> src_list(buff, buff + num_elems); + std::list<uint64_t> src_list(buff, buff + (num_elems * (_padding_size + 1))); _hops.clear(); // Deframe the header uint64_t hdr = conv_byte_order(src_list.front()); _hops.resize(static_cast<size_t>((hdr >> 16) & 0x3FF)); - _src_epid = static_cast<sep_id_t>(hdr & 0xFFFF); - _chdr_w = static_cast<chdr_w_t>((hdr >> 45) & 0x7); - _protover = static_cast<uint16_t>((hdr >> 48) & 0xFFFF); + _src_epid = static_cast<sep_id_t>(hdr & 0xFFFF); + _chdr_w = static_cast<chdr_w_t>((hdr >> 45) & 0x7); + _protover = static_cast<uint16_t>((hdr >> 48) & 0xFFFF); + _padding_size = (chdr_w_to_bits(_chdr_w) / 64) - 1; src_list.pop_front(); + // According to the RFNoC specification section 2.2.6, the MSBs are 0 for + // all widths greater than 64. This logic removes the padding. + for (size_t i = 0; i < _padding_size; i++) { + src_list.pop_front(); + } // Populate all hops for (size_t i = 0; i < get_num_hops(); i++) { - _hops[i].deserialize(src_list, conv_byte_order); + _hops[i].deserialize(src_list, conv_byte_order, _padding_size); } } @@ -425,3 +446,11 @@ const std::string mgmt_payload::to_string() const "mgmt_payload{src_epid:%lu, chdr_w:%d, protover:0x%x, num_hops:%lu}\n") % _src_epid % int(_chdr_w) % _protover % _hops.size()); } + + +bool mgmt_payload::operator==(const mgmt_payload& rhs) const +{ + return (_src_epid == rhs._src_epid) && (_protover == rhs._protover) + && (_chdr_w == rhs._chdr_w) && (_hops == rhs._hops) + && (_padding_size == rhs._padding_size); +} diff --git a/host/lib/usrp/mpmd/mpmd_link_if_ctrl_udp.cpp b/host/lib/usrp/mpmd/mpmd_link_if_ctrl_udp.cpp index b4a0dfd32..bdf088025 100644 --- a/host/lib/usrp/mpmd/mpmd_link_if_ctrl_udp.cpp +++ b/host/lib/usrp/mpmd/mpmd_link_if_ctrl_udp.cpp @@ -26,9 +26,6 @@ using namespace uhd; using namespace uhd::transport; using namespace uhd::mpmd::xport; -const uhd::rfnoc::chdr::chdr_packet_factory mpmd_link_if_ctrl_udp::_pkt_factory( - uhd::rfnoc::CHDR_W_64, ENDIANNESS_LITTLE); - namespace { //! Maximum CHDR packet size in bytes @@ -214,10 +211,12 @@ size_t discover_mtu(const std::string& address, * Structors *****************************************************************************/ mpmd_link_if_ctrl_udp::mpmd_link_if_ctrl_udp(const uhd::device_addr_t& mb_args, - const mpmd_link_if_mgr::xport_info_list_t& xport_info) + const mpmd_link_if_mgr::xport_info_list_t& xport_info, + const uhd::rfnoc::chdr_w_t chdr_w) : _mb_args(mb_args) , _udp_info(get_udp_info_from_xport_info(xport_info)) , _mtu(MPMD_10GE_DATA_FRAME_MAX_SIZE) + , _pkt_factory(chdr_w, ENDIANNESS_LITTLE) { const bool use_dpdk = mb_args.has_key("use_dpdk"); // FIXME use constrained_device_args diff --git a/host/lib/usrp/mpmd/mpmd_link_if_ctrl_udp.hpp b/host/lib/usrp/mpmd/mpmd_link_if_ctrl_udp.hpp index c80f1e613..ebe4f5db2 100644 --- a/host/lib/usrp/mpmd/mpmd_link_if_ctrl_udp.hpp +++ b/host/lib/usrp/mpmd/mpmd_link_if_ctrl_udp.hpp @@ -10,6 +10,7 @@ #include "mpmd_link_if_ctrl_base.hpp" #include "mpmd_link_if_mgr.hpp" #include <uhd/types/device_addr.hpp> +#include <uhdlib/rfnoc/rfnoc_common.hpp> #include <unordered_map> namespace uhd { namespace mpmd { namespace xport { @@ -30,7 +31,8 @@ public: using udp_link_info_map = std::unordered_map<std::string, udp_link_info_t>; mpmd_link_if_ctrl_udp(const uhd::device_addr_t& mb_args, - const mpmd_link_if_mgr::xport_info_list_t& xport_info); + const mpmd_link_if_mgr::xport_info_list_t& xport_info, + const uhd::rfnoc::chdr_w_t chdr_w); size_t get_num_links() const; uhd::transport::both_links_t get_link(const size_t link_idx, @@ -51,7 +53,7 @@ private: std::vector<std::string> _available_addrs; //! MTU size_t _mtu; - static const uhd::rfnoc::chdr::chdr_packet_factory _pkt_factory; + const uhd::rfnoc::chdr::chdr_packet_factory _pkt_factory; }; }}} /* namespace uhd::mpmd::xport */ diff --git a/host/lib/usrp/mpmd/mpmd_link_if_mgr.cpp b/host/lib/usrp/mpmd/mpmd_link_if_mgr.cpp index 4b36e7ba4..930f5e465 100644 --- a/host/lib/usrp/mpmd/mpmd_link_if_mgr.cpp +++ b/host/lib/usrp/mpmd/mpmd_link_if_mgr.cpp @@ -36,9 +36,11 @@ public: /************************************************************************** * API (see mpmd_link_if_mgr.hpp) *************************************************************************/ - bool connect(const std::string& link_type, const xport_info_list_t& xport_info) + bool connect(const std::string& link_type, + const xport_info_list_t& xport_info, + const uhd::rfnoc::chdr_w_t chdr_w) { - auto link_if_ctrl = make_link_if_ctrl(link_type, xport_info); + auto link_if_ctrl = make_link_if_ctrl(link_type, xport_info, chdr_w); if (!link_if_ctrl) { UHD_LOG_WARNING( "MPMD::XPORT", "Unable to create xport ctrl for link type " << link_type); @@ -89,8 +91,9 @@ private: /************************************************************************** * Private methods / helpers *************************************************************************/ - mpmd_link_if_ctrl_base::uptr make_link_if_ctrl( - const std::string& link_type, const xport_info_list_t& xport_info) + mpmd_link_if_ctrl_base::uptr make_link_if_ctrl(const std::string& link_type, + const xport_info_list_t& xport_info, + const uhd::rfnoc::chdr_w_t chdr_w) { // Here, we hard-code the list of available transport types if (link_type == "udp") { @@ -100,7 +103,7 @@ private: // xport_info); //} #endif - return std::make_unique<mpmd_link_if_ctrl_udp>(_mb_args, xport_info); + return std::make_unique<mpmd_link_if_ctrl_udp>(_mb_args, xport_info, chdr_w); #ifdef HAVE_LIBERIO } else if (link_type == "liberio") { return std::make_unique<mpmd_link_if_ctrl_liberio>(_mb_args, xport_info); diff --git a/host/lib/usrp/mpmd/mpmd_link_if_mgr.hpp b/host/lib/usrp/mpmd/mpmd_link_if_mgr.hpp index a1d11bad7..b8e7454cb 100644 --- a/host/lib/usrp/mpmd/mpmd_link_if_mgr.hpp +++ b/host/lib/usrp/mpmd/mpmd_link_if_mgr.hpp @@ -11,6 +11,7 @@ #include <uhd/types/dict.hpp> #include <uhd/types/direction.hpp> #include <uhdlib/rfnoc/chdr_packet.hpp> +#include <uhdlib/rfnoc/rfnoc_common.hpp> #include <uhdlib/transport/links.hpp> #include <map> #include <memory> @@ -80,8 +81,9 @@ public: * contain the available IP addresses. * \returns true on success */ - virtual bool connect( - const std::string& xport_type, const xport_info_list_t& xport_info) = 0; + virtual bool connect(const std::string& xport_type, + const xport_info_list_t& xport_info, + const uhd::rfnoc::chdr_w_t chdr_w) = 0; /*! The number of available links * diff --git a/host/lib/usrp/mpmd/mpmd_mb_iface.cpp b/host/lib/usrp/mpmd/mpmd_mb_iface.cpp index 41b664374..d4f6cc383 100644 --- a/host/lib/usrp/mpmd/mpmd_mb_iface.cpp +++ b/host/lib/usrp/mpmd/mpmd_mb_iface.cpp @@ -62,7 +62,7 @@ void mpmd_mboard_impl::mpmd_mb_iface::init() "get_chdr_link_options", type); // User may have specified: addr=192.168.10.2, second_addr= // MPM may have said: "my addresses are 192.168.10.2 and 192.168.20.2" - if (_link_if_mgr->connect(type, xport_info)) { + if (_link_if_mgr->connect(type, xport_info, get_chdr_w())) { UHD_LOG_TRACE("MPMD::MB_IFACE", "Link type " << type << " successful."); } } diff --git a/host/tests/rfnoc_chdr_test.cpp b/host/tests/rfnoc_chdr_test.cpp index 747b3c6a4..27b883543 100644 --- a/host/tests/rfnoc_chdr_test.cpp +++ b/host/tests/rfnoc_chdr_test.cpp @@ -74,6 +74,17 @@ strc_payload populate_strc_payload() return pyld; } +mgmt_payload populate_mgmt_payload(const chdr_w_t chdr_w) +{ + mgmt_payload pyld; + pyld.set_header(sep_id_t(rand64() & 0xFFFF), uint16_t(rand64() & 0xFFFF), chdr_w); + mgmt_hop_t hop; + // management op payloads are 48 bits + hop.add_op(mgmt_op_t(mgmt_op_t::MGMT_OP_NOP, rand64() & 0xFFFFFFFFFFFF)); + pyld.add_hop(hop); + return pyld; +} + void byte_swap(uint64_t* buff) { for (size_t i = 0; i < MAX_BUF_SIZE_WORDS; i++) { @@ -264,3 +275,98 @@ BOOST_AUTO_TEST_CASE(chdr_generic_packet_calculate_pyld_offset_64) test_pyld_offset(pkt, PKT_TYPE_DATA_WITH_TS, 2); } } + + +BOOST_AUTO_TEST_CASE(chdr_mgmt_packet_no_swap_64) +{ + uint64_t buff[MAX_BUF_SIZE_WORDS]; + + chdr_mgmt_packet::uptr tx_pkt = chdr64_be_factory.make_mgmt(); + chdr_mgmt_packet::cuptr rx_pkt = chdr64_be_factory.make_mgmt(); + + for (size_t i = 0; i < NUM_ITERS; i++) { + chdr_header hdr = chdr_header(rand64()); + mgmt_payload pyld = populate_mgmt_payload(CHDR_W_64); + + memset(buff, 0, MAX_BUF_SIZE_BYTES); + tx_pkt->refresh(buff, hdr, pyld); + BOOST_CHECK(tx_pkt->get_chdr_header() == hdr); + BOOST_CHECK(tx_pkt->get_payload() == pyld); + + rx_pkt->refresh(buff); + BOOST_CHECK(rx_pkt->get_chdr_header() == hdr); + BOOST_CHECK(rx_pkt->get_payload() == pyld); + + std::cout << pyld.to_string(); + } +} + +BOOST_AUTO_TEST_CASE(chdr_mgmt_packet_no_swap_256) +{ + uint64_t buff[MAX_BUF_SIZE_WORDS]; + + chdr_mgmt_packet::uptr tx_pkt = chdr256_be_factory.make_mgmt(); + chdr_mgmt_packet::cuptr rx_pkt = chdr256_be_factory.make_mgmt(); + + for (size_t i = 0; i < NUM_ITERS; i++) { + chdr_header hdr = chdr_header(rand64()); + mgmt_payload pyld = populate_mgmt_payload(CHDR_W_256); + + memset(buff, 0, MAX_BUF_SIZE_BYTES); + tx_pkt->refresh(buff, hdr, pyld); + BOOST_CHECK(tx_pkt->get_chdr_header() == hdr); + BOOST_CHECK(tx_pkt->get_payload() == pyld); + + rx_pkt->refresh(buff); + BOOST_CHECK(rx_pkt->get_chdr_header() == hdr); + BOOST_CHECK(rx_pkt->get_payload() == pyld); + } +} + +BOOST_AUTO_TEST_CASE(chdr_mgmt_packet_swap_64) +{ + uint64_t buff[MAX_BUF_SIZE_WORDS]; + + chdr_mgmt_packet::uptr tx_pkt = chdr64_be_factory.make_mgmt(); + chdr_mgmt_packet::cuptr rx_pkt = chdr64_le_factory.make_mgmt(); + + for (size_t i = 0; i < NUM_ITERS; i++) { + chdr_header hdr = chdr_header(rand64()); + mgmt_payload pyld = populate_mgmt_payload(CHDR_W_64); + + memset(buff, 0, MAX_BUF_SIZE_BYTES); + tx_pkt->refresh(buff, hdr, pyld); + BOOST_CHECK(tx_pkt->get_chdr_header() == hdr); + BOOST_CHECK(tx_pkt->get_payload() == pyld); + + byte_swap(buff); + + rx_pkt->refresh(buff); + BOOST_CHECK(rx_pkt->get_chdr_header() == hdr); + BOOST_CHECK(rx_pkt->get_payload() == pyld); + } +} + +BOOST_AUTO_TEST_CASE(chdr_mgmt_packet_swap_256) +{ + uint64_t buff[MAX_BUF_SIZE_WORDS]; + + chdr_mgmt_packet::uptr tx_pkt = chdr256_be_factory.make_mgmt(); + chdr_mgmt_packet::cuptr rx_pkt = chdr256_le_factory.make_mgmt(); + + for (size_t i = 0; i < NUM_ITERS; i++) { + chdr_header hdr = chdr_header(rand64()); + mgmt_payload pyld = populate_mgmt_payload(CHDR_W_256); + + memset(buff, 0, MAX_BUF_SIZE_BYTES); + tx_pkt->refresh(buff, hdr, pyld); + BOOST_CHECK(tx_pkt->get_chdr_header() == hdr); + BOOST_CHECK(tx_pkt->get_payload() == pyld); + + byte_swap(buff); + + rx_pkt->refresh(buff); + BOOST_CHECK(rx_pkt->get_chdr_header() == hdr); + BOOST_CHECK(rx_pkt->get_payload() == pyld); + } +} |