00ab2d647f10192d1192c2811a608688e0de2c8c
[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 <vapi/vapi.hpp>
26 #include <vapi/vpe.api.vapi.hpp>
27
28 #include "vom/connection.hpp"
29 #include "vom/rpc_cmd.hpp"
30
31 namespace VOM {
32 class HW
33 {
34 public:
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
331 private:
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  */
390 template <>
391 std::string HW::item<bool>::to_string() const;
392
393 /**
394  * uint Specialisation for HW::item to_string
395  */
396 template <>
397 std::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