VOM: logging, populate and stats fixes
[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::connect()
81 {
82   if (m_connected) {
83     m_conn.disconnect();
84   }
85
86   m_connected = false;
87
88   if (m_rx_thread && m_rx_thread->joinable()) {
89     m_rx_thread->join();
90   }
91
92   m_conn.connect();
93
94   m_connected = true;
95   m_rx_thread.reset(new std::thread(&HW::cmd_q::rx_run, this));
96 }
97
98 void
99 HW::cmd_q::enable()
100 {
101   m_enabled = true;
102 }
103
104 void
105 HW::cmd_q::disable()
106 {
107   m_enabled = false;
108 }
109
110 rc_t
111 HW::cmd_q::write()
112 {
113   rc_t rc = rc_t::OK;
114
115   /*
116    * The queue is enabled, Execute each command in the queue.
117    * If one execution fails, abort the rest
118    */
119   auto it = m_queue.begin();
120
121   while (it != m_queue.end()) {
122     std::shared_ptr<cmd> c = *it;
123
124     VOM_LOG(log_level_t::DEBUG) << *c;
125
126     if (m_enabled) {
127       /*
128        * before we issue the command we must move it to the pending
129        * store
130        * ince a async event can be recieved before the command
131        * completes
132        */
133       rc = c->issue(m_conn);
134
135       if (rc_t::OK == rc) {
136         /*
137          * move to the next
138          */
139       } else {
140         /*
141          * barf out without issuing the rest
142          */
143         VOM_LOG(log_level_t::ERROR) << "Failed to execute: " << c->to_string();
144         break;
145       }
146     } else {
147       /*
148        * The HW is disabled, so set each command as succeeded
149        */
150       c->succeeded();
151     }
152
153     ++it;
154   }
155
156   /*
157    * erase all objects in the queue
158    */
159   m_queue.erase(m_queue.begin(), m_queue.end());
160
161   return (rc);
162 }
163
164 /*
165  * The single Command Queue
166  */
167 HW::cmd_q* HW::m_cmdQ;
168 HW::item<bool> HW::m_poll_state;
169
170 /**
171  * Initialse the connection to VPP
172  */
173 void
174 HW::init(HW::cmd_q* f)
175 {
176   m_cmdQ = f;
177 }
178
179 /**
180  * Initialse the connection to VPP
181  */
182 void
183 HW::init()
184 {
185   m_cmdQ = new cmd_q();
186 }
187
188 void
189 HW::enqueue(cmd* cmd)
190 {
191   m_cmdQ->enqueue(cmd);
192 }
193
194 void
195 HW::enqueue(std::shared_ptr<cmd> cmd)
196 {
197   m_cmdQ->enqueue(cmd);
198 }
199
200 void
201 HW::enqueue(std::queue<cmd*>& cmds)
202 {
203   m_cmdQ->enqueue(cmds);
204 }
205
206 void
207 HW::connect()
208 {
209   m_cmdQ->connect();
210 }
211
212 void
213 HW::enable()
214 {
215   m_cmdQ->enable();
216 }
217
218 void
219 HW::disable()
220 {
221   m_cmdQ->disable();
222 }
223
224 rc_t
225 HW::write()
226 {
227   return (m_cmdQ->write());
228 }
229
230 bool
231 HW::poll()
232 {
233   std::shared_ptr<cmd> poll(new hw_cmds::poll(m_poll_state));
234
235   HW::enqueue(poll);
236   HW::write();
237
238   return (m_poll_state);
239   return (true);
240 }
241
242 template <>
243 std::string
244 HW::item<bool>::to_string() const
245 {
246   std::ostringstream os;
247
248   os << "hw-item:["
249      << "rc:" << item_rc.to_string() << " data:" << item_data << "]";
250   return (os.str());
251 }
252
253 template <>
254 std::string
255 HW::item<unsigned int>::to_string() const
256 {
257   std::ostringstream os;
258
259   os << "hw-item:["
260      << "rc:" << item_rc.to_string() << " data:" << item_data << "]";
261   return (os.str());
262 }
263 }
264
265 /*
266  * fd.io coding-style-patch-verification: ON
267  *
268  * Local Variables:
269  * eval: (c-set-style "mozilla")
270  * End:
271  */