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