blob: 4150d5f481fc3c09ea12f9cf5002699caea817e2 [file] [log] [blame]
Neale Ranns812ed392017-10-16 04:20:13 -07001/*
2 * Copyright (c) 2017 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "vom/hw.hpp"
Neale Ranns9ef1c0a2017-11-03 04:39:05 -070017#include "vom/hw_cmds.hpp"
Neale Ranns812ed392017-10-16 04:20:13 -070018#include "vom/logger.hpp"
19
Neale Ranns812ed392017-10-16 04:20:13 -070020namespace VOM {
21HW::cmd_q::cmd_q()
22 : m_enabled(true)
23 , m_connected(false)
24 , m_conn()
25{
26}
27
28HW::cmd_q::~cmd_q()
29{
30 m_connected = false;
31
32 if (m_rx_thread && m_rx_thread->joinable()) {
33 m_rx_thread->join();
34 }
35}
36
37HW::cmd_q&
38HW::cmd_q::operator=(const HW::cmd_q& f)
39{
40 return (*this);
41}
42
43/**
44 * Run the connect/dispatch thread.
45 */
46void
47HW::cmd_q::rx_run()
48{
49 while (m_connected) {
50 m_conn.ctx().dispatch();
51 }
52}
53
54void
55HW::cmd_q::enqueue(cmd* c)
56{
57 std::shared_ptr<cmd> sp(c);
58
59 m_queue.push_back(sp);
60}
61
62void
63HW::cmd_q::enqueue(std::shared_ptr<cmd> c)
64{
65 m_queue.push_back(c);
66}
67
68void
69HW::cmd_q::enqueue(std::queue<cmd*>& cmds)
70{
71 while (cmds.size()) {
72 std::shared_ptr<cmd> sp(cmds.front());
73
74 m_queue.push_back(sp);
75 cmds.pop();
76 }
77}
78
79void
80HW::cmd_q::dequeue(cmd* c)
81{
82 c->retire(m_conn);
83 m_pending.erase(c);
84}
85
86void
87HW::cmd_q::dequeue(std::shared_ptr<cmd> c)
88{
89 c->retire(m_conn);
90 m_pending.erase(c.get());
91}
92
93void
94HW::cmd_q::connect()
95{
96 if (m_connected) {
97 m_conn.disconnect();
98 }
99
100 m_connected = false;
101
102 if (m_rx_thread && m_rx_thread->joinable()) {
103 m_rx_thread->join();
104 }
105
106 m_conn.connect();
107
108 m_connected = true;
109 m_rx_thread.reset(new std::thread(&HW::cmd_q::rx_run, this));
110}
111
112void
113HW::cmd_q::enable()
114{
115 m_enabled = true;
116}
117
118void
119HW::cmd_q::disable()
120{
121 m_enabled = false;
122}
123
124rc_t
125HW::cmd_q::write()
126{
127 rc_t rc = rc_t::OK;
128
129 /*
Neale Ranns8ac4ce82017-11-17 05:08:55 -0800130 * The queue is enabled, Execute each command in the queue.
131 * If one execution fails, abort the rest
132 */
Neale Ranns812ed392017-10-16 04:20:13 -0700133 auto it = m_queue.begin();
134
135 while (it != m_queue.end()) {
136 std::shared_ptr<cmd> c = *it;
137
138 VOM_LOG(log_level_t::DEBUG) << *c;
139
140 if (m_enabled) {
141 /*
Neale Ranns8ac4ce82017-11-17 05:08:55 -0800142 * before we issue the command we must move it to the pending
143 * store
144 * ince a async event can be recieved before the command
145 * completes
146 */
Neale Ranns812ed392017-10-16 04:20:13 -0700147 m_pending[c.get()] = c;
148
149 rc = c->issue(m_conn);
150
151 if (rc_t::INPROGRESS == rc) {
152 /*
Neale Ranns8ac4ce82017-11-17 05:08:55 -0800153 * this command completes asynchronously
154 * leave the command in the pending store
155 */
Neale Ranns812ed392017-10-16 04:20:13 -0700156 } else {
157 /*
Neale Ranns8ac4ce82017-11-17 05:08:55 -0800158 * the command completed, remove from the pending store
159 */
Neale Ranns812ed392017-10-16 04:20:13 -0700160 m_pending.erase(c.get());
161
162 if (rc_t::OK == rc) {
163 /*
Neale Ranns8ac4ce82017-11-17 05:08:55 -0800164 * move to the next
165 */
Neale Ranns812ed392017-10-16 04:20:13 -0700166 } else {
167 /*
Neale Ranns8ac4ce82017-11-17 05:08:55 -0800168 * barf out without issuing the rest
169 */
170 VOM_LOG(log_level_t::ERROR) << "Failed to execute: "
171 << c->to_string();
Neale Ranns812ed392017-10-16 04:20:13 -0700172 break;
173 }
174 }
175 } else {
176 /*
Neale Ranns8ac4ce82017-11-17 05:08:55 -0800177 * The HW is disabled, so set each command as succeeded
178 */
Neale Ranns812ed392017-10-16 04:20:13 -0700179 c->succeeded();
180 }
181
182 ++it;
183 }
184
185 /*
Neale Ranns8ac4ce82017-11-17 05:08:55 -0800186 * erase all objects in the queue
187 */
Neale Ranns812ed392017-10-16 04:20:13 -0700188 m_queue.erase(m_queue.begin(), m_queue.end());
189
190 return (rc);
191}
192
193/*
194 * The single Command Queue
195 */
196HW::cmd_q* HW::m_cmdQ;
197HW::item<bool> HW::m_poll_state;
198
199/**
200 * Initialse the connection to VPP
201 */
202void
203HW::init(HW::cmd_q* f)
204{
205 m_cmdQ = f;
206}
207
208/**
209 * Initialse the connection to VPP
210 */
211void
212HW::init()
213{
214 m_cmdQ = new cmd_q();
215}
216
217void
218HW::enqueue(cmd* cmd)
219{
220 m_cmdQ->enqueue(cmd);
221}
222
223void
224HW::enqueue(std::shared_ptr<cmd> cmd)
225{
226 m_cmdQ->enqueue(cmd);
227}
228
229void
230HW::enqueue(std::queue<cmd*>& cmds)
231{
232 m_cmdQ->enqueue(cmds);
233}
234
235void
236HW::dequeue(cmd* cmd)
237{
238 m_cmdQ->dequeue(cmd);
239}
240
241void
242HW::dequeue(std::shared_ptr<cmd> cmd)
243{
244 m_cmdQ->dequeue(cmd);
245}
246
247void
248HW::connect()
249{
250 m_cmdQ->connect();
251}
252
253void
254HW::enable()
255{
256 m_cmdQ->enable();
257}
258
259void
260HW::disable()
261{
262 m_cmdQ->disable();
263}
264
265rc_t
266HW::write()
267{
268 return (m_cmdQ->write());
269}
270
271bool
272HW::poll()
273{
Neale Ranns9ef1c0a2017-11-03 04:39:05 -0700274 std::shared_ptr<cmd> poll(new hw_cmds::poll(m_poll_state));
Neale Ranns812ed392017-10-16 04:20:13 -0700275
276 HW::enqueue(poll);
277 HW::write();
278
279 return (m_poll_state);
Neale Ranns9ef1c0a2017-11-03 04:39:05 -0700280 return (true);
Neale Ranns812ed392017-10-16 04:20:13 -0700281}
282
283template <>
284std::string
285HW::item<bool>::to_string() const
286{
287 std::ostringstream os;
288
289 os << "hw-item:["
290 << "rc:" << item_rc.to_string() << " data:" << item_data << "]";
291 return (os.str());
292}
293
294template <>
295std::string
296HW::item<unsigned int>::to_string() const
297{
298 std::ostringstream os;
299
300 os << "hw-item:["
301 << "rc:" << item_rc.to_string() << " data:" << item_data << "]";
302 return (os.str());
303}
Neale Ranns812ed392017-10-16 04:20:13 -0700304}
305
306/*
307 * fd.io coding-style-patch-verification: ON
308 *
309 * Local Variables:
310 * eval: (c-set-style "mozilla")
311 * End:
312 */