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