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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
|
//
// Copyright 2019 Ettus Research, a National Instruments Brand
//
// SPDX-License-Identifier: GPL-3.0-or-later
//
#include <uhd/rfnoc/chdr_types.hpp>
#include <uhd/utils/log.hpp>
#include <uhdlib/rfnoc/chdr_ctrl_xport.hpp>
using namespace uhd;
using namespace uhd::rfnoc;
using namespace uhd::rfnoc::chdr;
using namespace uhd::transport;
chdr_ctrl_xport::chdr_ctrl_xport(io_service::sptr io_srv,
send_link_if::sptr send_link,
recv_link_if::sptr recv_link,
const chdr::chdr_packet_factory& pkt_factory,
sep_id_t my_epid,
size_t num_send_frames,
size_t num_recv_frames)
: _my_epid(my_epid), _recv_packet(pkt_factory.make_generic())
{
/* Make dumb send pipe */
send_io_if::send_callback_t send_cb = [this](
frame_buff::uptr buff, send_link_if* link) {
link->release_send_buff(std::move(buff));
};
_send_if = io_srv->make_send_client(
send_link, num_send_frames, send_cb, recv_link_if::sptr(), 0, nullptr, nullptr);
/* Make dumb recv pipe that matches management and control packets */
uhd::transport::recv_callback_t ctrl_recv_cb =
[this](frame_buff::uptr& buff,
recv_link_if* /*recv_link*/,
send_link_if * /*send_link*/) -> bool { return this->_ctrl_recv_cb(buff); };
recv_io_if::fc_callback_t release_cb =
[this](frame_buff::uptr buff, recv_link_if* link, send_link_if* /*send_link*/) {
this->_release_cb(std::move(buff), link);
};
_ctrl_recv_if = io_srv->make_recv_client(
recv_link, num_recv_frames, ctrl_recv_cb, send_link_if::sptr(), 0, release_cb);
uhd::transport::recv_callback_t mgmt_recv_cb =
[this](frame_buff::uptr& buff,
recv_link_if* /*recv_link*/,
send_link_if * /*send_link*/) -> bool { return this->_mgmt_recv_cb(buff); };
_mgmt_recv_if = io_srv->make_recv_client(
recv_link, 1, mgmt_recv_cb, send_link_if::sptr(), 0, release_cb);
}
bool chdr_ctrl_xport::_ctrl_recv_cb(uhd::transport::frame_buff::uptr& buff)
{
_recv_packet->refresh(buff->data());
auto hdr = _recv_packet->get_chdr_header();
auto pkt_type = hdr.get_pkt_type();
auto dst_epid = hdr.get_dst_epid();
/* Check type and destination EPID */
if ((pkt_type == PKT_TYPE_CTRL) && (dst_epid == _my_epid)) {
return true;
} else {
return false;
}
return false;
}
bool chdr_ctrl_xport::_mgmt_recv_cb(uhd::transport::frame_buff::uptr& buff)
{
_recv_packet->refresh(buff->data());
auto hdr = _recv_packet->get_chdr_header();
auto pkt_type = hdr.get_pkt_type();
auto dst_epid = hdr.get_dst_epid();
/* Check type and destination EPID */
if ((pkt_type == PKT_TYPE_MGMT) && (dst_epid == _my_epid)) {
return true;
} else {
return false;
}
return false;
}
void chdr_ctrl_xport::_release_cb(
uhd::transport::frame_buff::uptr buff, uhd::transport::recv_link_if* recv_link)
{
recv_link->release_recv_buff(std::move(buff));
}
chdr_ctrl_xport::~chdr_ctrl_xport()
{
// Release I/O service clients before allowing members needed by callbacks
// be destroyed
_send_if.reset();
_ctrl_recv_if.reset();
_mgmt_recv_if.reset();
}
/*!
* Get an empty frame buffer in which to write packet contents.
*
* \param timeout_ms a positive timeout value specifies the maximum number
of ms to wait, a negative value specifies to block
until successful, and a value of 0 specifies no wait.
* \return a frame buffer, or null uptr if timeout occurs
*/
frame_buff::uptr chdr_ctrl_xport::get_send_buff(int32_t timeout_ms)
{
// FIXME: Remove mutex when have threaded_io_service
std::lock_guard<std::mutex> lock(_mutex);
frame_buff::uptr buff = _send_if->get_send_buff(timeout_ms);
if (!buff) {
return frame_buff::uptr();
}
return frame_buff::uptr(std::move(buff));
}
/*!
* Release a frame buffer, allowing the driver to reuse it.
*
* \param buffer frame buffer to release for reuse by the link
*/
void chdr_ctrl_xport::release_send_buff(frame_buff::uptr buff)
{
// FIXME: Remove mutex when have threaded_io_service
std::lock_guard<std::mutex> lock(_mutex);
_send_if->release_send_buff(std::move(buff));
}
/*!
* Attempt to get a frame buffer with data from the recv link.
*
* \param timeout_ms a positive timeout value specifies the maximum number
of ms to wait, a negative value specifies to block
until successful, and a value of 0 specifies no wait.
* \return a frame buffer, or null uptr if timeout occurs
*/
frame_buff::uptr chdr_ctrl_xport::get_recv_buff(int32_t timeout_ms)
{
// FIXME: Remove mutex when have threaded_io_service
std::lock_guard<std::mutex> lock(_mutex);
return _ctrl_recv_if->get_recv_buff(timeout_ms);
}
frame_buff::uptr chdr_ctrl_xport::get_mgmt_buff(int32_t timeout_ms)
{
std::lock_guard<std::mutex> lock(_mutex);
return _mgmt_recv_if->get_recv_buff(timeout_ms);
}
/*!
* Release a frame buffer, allowing the recv link driver to reuse it.
*
* \param buffer frame buffer to release for reuse by the link
*/
void chdr_ctrl_xport::release_recv_buff(frame_buff::uptr buff)
{
// FIXME: Remove mutex when have threaded_io_service
std::lock_guard<std::mutex> lock(_mutex);
_ctrl_recv_if->release_recv_buff(std::move(buff));
}
void chdr_ctrl_xport::release_mgmt_buff(frame_buff::uptr buff)
{
// FIXME: Remove mutex when have threaded_io_service
std::lock_guard<std::mutex> lock(_mutex);
_mgmt_recv_if->release_recv_buff(std::move(buff));
}
/*!
* Get this xport's EPID
*/
sep_id_t chdr_ctrl_xport::get_epid() const
{
return _my_epid;
}
|