VOM reshuffle
[vpp.git] / src / vpp-api / vom / hw.cpp
1 /*
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"
17 #include "vom/hw_cmds.hpp"
18 #include "vom/logger.hpp"
19
20 namespace VOM {
21 HW::cmd_q::cmd_q()
22   : m_enabled(true)
23   , m_connected(false)
24   , m_conn()
25 {
26 }
27
28 HW::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
37 HW::cmd_q&
38 HW::cmd_q::operator=(const HW::cmd_q& f)
39 {
40   return (*this);
41 }
42
43 /**
44  * Run the connect/dispatch thread.
45  */
46 void
47 HW::cmd_q::rx_run()
48 {
49   while (m_connected) {
50     m_conn.ctx().dispatch();
51   }
52 }
53
54 void
55 HW::cmd_q::enqueue(cmd* c)
56 {
57   std::shared_ptr<cmd> sp(c);
58
59   m_queue.push_back(sp);
60 }
61
62 void
63 HW::cmd_q::enqueue(std::shared_ptr<cmd> c)
64 {
65   m_queue.push_back(c);
66 }
67
68 void
69 HW::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
79 void
80 HW::cmd_q::dequeue(cmd* c)
81 {
82   c->retire(m_conn);
83   m_pending.erase(c);
84 }
85
86 void
87 HW::cmd_q::dequeue(std::shared_ptr<cmd> c)
88 {
89   c->retire(m_conn);
90   m_pending.erase(c.get());
91 }
92
93 void
94 HW::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
112 void
113 HW::cmd_q::enable()
114 {
115   m_enabled = true;
116 }
117
118 void
119 HW::cmd_q::disable()
120 {
121   m_enabled = false;
122 }
123
124 rc_t
125 HW::cmd_q::write()
126 {
127   rc_t rc = rc_t::OK;
128
129   /*
130  * The queue is enabled, Execute each command in the queue.
131  * If one execution fails, abort the rest
132  */
133   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       /*
142  * 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  */
147       m_pending[c.get()] = c;
148
149       rc = c->issue(m_conn);
150
151       if (rc_t::INPROGRESS == rc) {
152         /*
153  * this command completes asynchronously
154  * leave the command in the pending store
155  */
156       } else {
157         /*
158  * the command completed, remove from the pending store
159  */
160         m_pending.erase(c.get());
161
162         if (rc_t::OK == rc) {
163           /*
164  * move to the next
165  */
166         } else {
167           /*
168  * barf out without issuing the rest
169  */
170           break;
171         }
172       }
173     } else {
174       /*
175  * The HW is disabled, so set each command as succeeded
176  */
177       c->succeeded();
178     }
179
180     ++it;
181   }
182
183   /*
184  * erase all objects in the queue
185  */
186   m_queue.erase(m_queue.begin(), m_queue.end());
187
188   return (rc);
189 }
190
191 /*
192  * The single Command Queue
193  */
194 HW::cmd_q* HW::m_cmdQ;
195 HW::item<bool> HW::m_poll_state;
196
197 /**
198  * Initialse the connection to VPP
199  */
200 void
201 HW::init(HW::cmd_q* f)
202 {
203   m_cmdQ = f;
204 }
205
206 /**
207  * Initialse the connection to VPP
208  */
209 void
210 HW::init()
211 {
212   m_cmdQ = new cmd_q();
213 }
214
215 void
216 HW::enqueue(cmd* cmd)
217 {
218   m_cmdQ->enqueue(cmd);
219 }
220
221 void
222 HW::enqueue(std::shared_ptr<cmd> cmd)
223 {
224   m_cmdQ->enqueue(cmd);
225 }
226
227 void
228 HW::enqueue(std::queue<cmd*>& cmds)
229 {
230   m_cmdQ->enqueue(cmds);
231 }
232
233 void
234 HW::dequeue(cmd* cmd)
235 {
236   m_cmdQ->dequeue(cmd);
237 }
238
239 void
240 HW::dequeue(std::shared_ptr<cmd> cmd)
241 {
242   m_cmdQ->dequeue(cmd);
243 }
244
245 void
246 HW::connect()
247 {
248   m_cmdQ->connect();
249 }
250
251 void
252 HW::enable()
253 {
254   m_cmdQ->enable();
255 }
256
257 void
258 HW::disable()
259 {
260   m_cmdQ->disable();
261 }
262
263 rc_t
264 HW::write()
265 {
266   return (m_cmdQ->write());
267 }
268
269 bool
270 HW::poll()
271 {
272   std::shared_ptr<cmd> poll(new hw_cmds::poll(m_poll_state));
273
274   HW::enqueue(poll);
275   HW::write();
276
277   return (m_poll_state);
278   return (true);
279 }
280
281 template <>
282 std::string
283 HW::item<bool>::to_string() const
284 {
285   std::ostringstream os;
286
287   os << "hw-item:["
288      << "rc:" << item_rc.to_string() << " data:" << item_data << "]";
289   return (os.str());
290 }
291
292 template <>
293 std::string
294 HW::item<unsigned int>::to_string() const
295 {
296   std::ostringstream os;
297
298   os << "hw-item:["
299      << "rc:" << item_rc.to_string() << " data:" << item_data << "]";
300   return (os.str());
301 }
302 }
303
304 /*
305  * fd.io coding-style-patch-verification: ON
306  *
307  * Local Variables:
308  * eval: (c-set-style "mozilla")
309  * End:
310  */