aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/mpmd/mpmd_xport_ctrl_liberio.cpp
blob: 7efe2bb9a8109454428d46e82154d81fa3268a78 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//
// Copyright 2017 Ettus Research, National Instruments Company
//
// SPDX-License-Identifier: GPL-3.0-or-later
//

#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 {

//! Max frame size of a control packet in bytes
const size_t LIBERIO_CTRL_FRAME_MAX_SIZE = 128;
//! Max frame size of an async message packet in bytes
const size_t LIBERIO_ASYNC_FRAME_MAX_SIZE = 256;
//! Max frame size of a flow control packet in bytes
const size_t LIBERIO_FC_FRAME_MAX_SIZE = 64;
//! The max MTU will be this number times the page size
const size_t LIBERIO_PAGES_PER_BUF = 2;
//! Number of descriptors that liberio allocates (receive)
const size_t LIBERIO_NUM_RECV_FRAMES = 128;
//! Number of descriptors that liberio allocates (send)
const size_t LIBERIO_NUM_SEND_FRAMES = 128;

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();
}

} // namespace

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 = get_mtu(uhd::TX_DIRECTION);
    default_buff_args.recv_frame_size = get_mtu(uhd::RX_DIRECTION);
    default_buff_args.num_recv_frames = LIBERIO_NUM_RECV_FRAMES;
    default_buff_args.num_send_frames = LIBERIO_NUM_SEND_FRAMES;

    if (xport_type == usrp::device3_impl::CTRL) {
        default_buff_args.send_frame_size = LIBERIO_CTRL_FRAME_MAX_SIZE;
        default_buff_args.recv_frame_size = LIBERIO_CTRL_FRAME_MAX_SIZE;
    } else if (xport_type == usrp::device3_impl::ASYNC_MSG) {
        default_buff_args.send_frame_size = LIBERIO_ASYNC_FRAME_MAX_SIZE;
        default_buff_args.recv_frame_size = LIBERIO_ASYNC_FRAME_MAX_SIZE;
    } else if (xport_type == usrp::device3_impl::RX_DATA) {
        default_buff_args.send_frame_size = LIBERIO_FC_FRAME_MAX_SIZE;
    } else {
        default_buff_args.recv_frame_size = LIBERIO_FC_FRAME_MAX_SIZE;
    }

    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 = LIBERIO_CTRL_FRAME_MAX_SIZE;
            default_buff_args.recv_frame_size = LIBERIO_CTRL_FRAME_MAX_SIZE;
            _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 = LIBERIO_ASYNC_FRAME_MAX_SIZE;
            default_buff_args.recv_frame_size = LIBERIO_ASYNC_FRAME_MAX_SIZE;
            _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";
}

size_t mpmd_xport_ctrl_liberio::get_mtu(const uhd::direction_t /* dir */
    ) const
{
    return LIBERIO_PAGES_PER_BUF * getpagesize();
}

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);
}