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