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