blob: 00ab2d647f10192d1192c2811a608688e0de2c8c [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#ifndef __VOM_HW_H__
17#define __VOM_HW_H__
18
19#include <deque>
20#include <map>
21#include <sstream>
22#include <string>
23#include <thread>
24
25#include <vapi/vapi.hpp>
26#include <vapi/vpe.api.vapi.hpp>
27
28#include "vom/connection.hpp"
29#include "vom/rpc_cmd.hpp"
30
31namespace VOM {
32class HW
33{
34public:
35 /**
36 * A HW::item is data that is either to be written to or read from
37 * VPP/HW.
38 * The item is a pair of the data written/read and the result of that
39 * operation.
40 */
41 template <typename T>
42 class item
43 {
44 public:
45 /**
46 * Constructor
47 */
48 item(const T& data)
49 : item_data(data)
50 , item_rc(rc_t::NOOP)
51 {
52 }
53 /**
54 * Constructor
55 */
56 item()
57 : item_rc(rc_t::UNSET)
58 {
59 }
60
61 /**
62 * Constructor
63 */
64 item(rc_t rc)
65 : item_rc(rc)
66 {
67 }
68
69 /**
70 * Constructor
71 */
72 item(const T& data, rc_t rc)
73 : item_data(data)
74 , item_rc(rc)
75 {
76 }
77
78 /**
79 * Comparison operator
80 */
81 bool operator==(const item<T>& i) const
82 {
83 return (item_data == i.item_data);
84 }
85
86 /**
87 * Copy assignment
88 */
89 item& operator=(const item& other)
90 {
91 item_data = other.item_data;
92 item_rc = other.item_rc;
93
94 return (*this);
95 }
96
97 /**
98 * Return the data read/written
99 */
100 T& data() { return (item_data); }
101
102 /**
103 * Const reference to the data
104 */
105 const T& data() const { return (item_data); }
106
107 /**
108 * Get the HW return code
109 */
110 rc_t rc() const { return (item_rc); }
111
112 /**
113 * Set the HW return code - should only be called from the
114 * family of Command objects
115 */
116 void set(const rc_t& rc) { item_rc = rc; }
117
118 /**
119 * Return true if the HW item is configred in HW
120 */
121 operator bool() const { return (rc_t::OK == item_rc); }
122
123 /**
124 * update the item to the desired state.
125 * return true if a HW update is required
126 */
127 bool update(const item& desired)
128 {
129 bool need_hw_update = false;
130
131 /*
132 * if the deisred set is unset (i.e. defaulted, we've
133 * no update to make
134 */
135 if (rc_t::UNSET == desired.rc()) {
136 return (false);
137 }
138 /*
139 * A HW update is needed if thestate is different
140 * or the state is not yet in HW
141 */
142 need_hw_update = (item_data != desired.data() || rc_t::OK != rc());
143
144 item_data = desired.data();
145
146 return (need_hw_update);
147 }
148
149 /**
150 * convert to string format for debug purposes
151 */
152 std::string to_string() const
153 {
154 std::ostringstream os;
155
156 os << "hw-item:["
157 << "rc:" << item_rc.to_string() << " data:" << item_data.to_string()
158 << "]";
159
160 return (os.str());
161 }
162
163 private:
164 /**
165 * The data
166 */
167 T item_data;
168
169 /**
170 * The result when the item was written
171 */
172 rc_t item_rc;
173 };
174
175 /**
176 * The pipe to VPP into which we write the commands
177 */
178 class cmd_q
179 {
180 public:
181 /**
182 * Constructor
183 */
184 cmd_q();
185 /**
186 * Destructor
187 */
188 ~cmd_q();
189
190 /**
191 * Copy assignement - only used in UT
192 */
193 cmd_q& operator=(const cmd_q& f);
194
195 /**
196 * Enqueue a command into the Q.
197 */
198 virtual void enqueue(cmd* c);
199 /**
200 * Enqueue a command into the Q.
201 */
202 virtual void enqueue(std::shared_ptr<cmd> c);
203
204 /**
205 * Enqueue a set of commands
206 */
207 virtual void enqueue(std::queue<cmd*>& c);
208
209 /**
210 * dequeue a command from the Q.
211 */
212 virtual void dequeue(cmd* c);
213
214 /**
215 * dequeue a command from the Q.
216 */
217 virtual void dequeue(std::shared_ptr<cmd> c);
218
219 /**
220 * Write all the commands to HW
221 */
222 virtual rc_t write();
223
224 /**
225 * Blocking Connect to VPP - call once at bootup
226 */
227 void connect();
228
229 /**
230 * Disable the passing of commands to VPP. Whilst disabled all
231 * writes will be discarded. Use this during the reset phase.
232 */
233 void disable();
234
235 /**
236 * Enable the passing of commands to VPP - undoes the disable.
237 * The Q is enabled by default.
238 */
239 void enable();
240
241 private:
242 /**
243 * A queue of enqueued commands, ready to be written
244 */
245 std::deque<std::shared_ptr<cmd>> m_queue;
246
247 /**
248 * A map of issued, but uncompleted, commands.
249 * i.e. those that we are waiting, async stylee,
250 * for VPP to complete
251 */
252 std::map<cmd*, std::shared_ptr<cmd>> m_pending;
253
254 /**
255 * VPP Q poll function
256 */
257 void rx_run();
258
259 /**
260 * The thread object running the poll/dispatch/connect thread
261 */
262 std::unique_ptr<std::thread> m_rx_thread;
263
264 /**
265 * A flag indicating the client has disabled the cmd Q.
266 */
267 bool m_enabled;
268
269 /**
270 * A flag for the thread to poll to see if the queue is still alive
271 */
272 bool m_connected;
273
274 /**
275 * The connection to VPP
276 */
277 connection m_conn;
278 };
279
280 /**
281 * Initialise the HW connection to VPP - the UT version passing
282 * a mock Q.
283 */
284 static void init(cmd_q* f);
285
286 /**
287 * Initialise the HW
288 */
289 static void init();
290
291 /**
292 * Enqueue A command for execution
293 */
294 static void enqueue(cmd* f);
295
296 /**
297 * Enqueue A command for execution
298 */
299 static void enqueue(std::shared_ptr<cmd> c);
300
301 /**
302 * Enqueue A set of commands for execution
303 */
304 static void enqueue(std::queue<cmd*>& c);
305
306 /**
307 * dequeue A command for execution
308 */
309 static void dequeue(cmd* f);
310
311 /**
312 * dequeue A command for execution
313 */
314 static void dequeue(std::shared_ptr<cmd> c);
315
316 /**
317 * Write/Execute all commands hitherto enqueued.
318 */
319 static rc_t write();
320
321 /**
322 * Blocking Connect to VPP
323 */
324 static void connect();
325
326 /**
327 * Blocking pool of the HW connection
328 */
329 static bool poll();
330
331private:
332 /**
333 * The command Q toward HW
334 */
335 static cmd_q* m_cmdQ;
336
337 /**
338 * HW::item representing the connection state as determined by polling
339 */
340 static HW::item<bool> m_poll_state;
341
342 /**
343 * Disable the passing of commands to VPP. Whilst disabled all writes
344 * will be discarded. Use this during the reset phase.
345 */
346 static void disable();
347
348 /**
349 * Enable the passing of commands to VPP - undoes the disable.
350 * The Q is enabled by default.
351 */
352 static void enable();
353
354 /**
355 * Only the OM can enable/disable HW
356 */
357 friend class OM;
358
359 /**
360 * A command pool the HW for liveness
361 */
362 class Poll : public rpc_cmd<HW::item<bool>, rc_t, vapi::Control_ping>
363 {
364 public:
365 /**
366 * Constructor taking the HW::item to update
367 */
368 Poll(HW::item<bool>& item);
369
370 /**
371 * Issue the command to VPP/HW
372 */
373 rc_t issue(connection& con);
374
375 /**
376 * convert to string format for debug purposes
377 */
378 std::string to_string() const;
379
380 /**
381 * Comparison operator - only used for UT
382 */
383 bool operator==(const Poll& i) const;
384 };
385};
386
387/**
388 * bool Specialisation for HW::item to_string
389 */
390template <>
391std::string HW::item<bool>::to_string() const;
392
393/**
394 * uint Specialisation for HW::item to_string
395 */
396template <>
397std::string HW::item<unsigned int>::to_string() const;
398};
399
400/*
401 * fd.io coding-style-patch-verification: ON
402 *
403 * Local Variables:
404 * eval: (c-set-style "mozilla")
405 * End:
406 */
407
408#endif