FD.io VPP  v18.04-17-g3a0d853
Vector Packet Processing
vapi.hpp
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2017 Cisco and/or its affiliates.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *------------------------------------------------------------------
16  */
17 
18 #ifndef vapi_hpp_included
19 #define vapi_hpp_included
20 
21 #include <cstddef>
22 #include <vector>
23 #include <mutex>
24 #include <queue>
25 #include <cassert>
26 #include <functional>
27 #include <algorithm>
28 #include <atomic>
29 #include <vppinfra/types.h>
30 #include <vapi/vapi.h>
31 #include <vapi/vapi_internal.h>
32 #include <vapi/vapi_dbg.h>
33 #include <vapi/vpe.api.vapi.h>
34 
35 #if VAPI_CPP_DEBUG_LEAKS
36 #include <unordered_set>
37 #endif
38 
39 /**
40  * @file
41  * @brief C++ VPP API
42  */
43 
44 namespace vapi
45 {
46 
47 class Connection;
48 
49 template <typename Req, typename Resp, typename... Args> class Request;
50 template <typename M> class Msg;
51 template <typename M> void vapi_swap_to_be (M *msg);
52 template <typename M> void vapi_swap_to_host (M *msg);
53 template <typename M, typename... Args>
54 M *vapi_alloc (Connection &con, Args...);
55 template <typename M> vapi_msg_id_t vapi_get_msg_id_t ();
56 template <typename M> class Event_registration;
57 
58 class Unexpected_msg_id_exception : public std::exception
59 {
60 public:
61  virtual const char *what () const throw ()
62  {
63  return "unexpected message id";
64  }
65 };
66 
67 class Msg_not_available_exception : public std::exception
68 {
69 public:
70  virtual const char *what () const throw ()
71  {
72  return "message unavailable";
73  }
74 };
75 
76 typedef enum {
77  /** response not ready yet */
79 
80  /** response to request is ready */
82 
83  /** no response to request (will never come) */
86 
87 /**
88  * Class representing common functionality of a request - response state
89  * and context
90  */
92 {
93 public:
94  virtual ~Common_req (){};
95 
97  {
98  return con;
99  };
100 
101  vapi_response_state_e get_response_state (void) const
102  {
103  return response_state;
104  }
105 
106 private:
107  Connection &con;
108  Common_req (Connection &con)
109  : con (con), context{0}, response_state{RESPONSE_NOT_READY}
110  {
111  }
112 
113  void set_response_state (vapi_response_state_e state)
114  {
115  response_state = state;
116  }
117 
118  virtual std::tuple<vapi_error_e, bool> assign_response (vapi_msg_id_t id,
119  void *shm_data) = 0;
120 
121  void set_context (u32 context)
122  {
123  this->context = context;
124  }
125 
126  u32 get_context ()
127  {
128  return context;
129  }
130 
131  u32 context;
132  vapi_response_state_e response_state;
133 
134  friend class Connection;
135 
136  template <typename M> friend class Msg;
137 
138  template <typename Req, typename Resp, typename... Args>
139  friend class Request;
140 
141  template <typename Req, typename Resp, typename... Args> friend class Dump;
142 
143  template <typename M> friend class Event_registration;
144 };
145 
146 /**
147  * Class representing a connection to VPP
148  *
149  * After creating a Connection object, call connect() to actually connect
150  * to VPP. Use is_msg_available to discover whether a specific message is known
151  * and supported by the VPP connected to.
152  */
154 {
155 public:
156  Connection (void) : vapi_ctx{0}, event_count{0}
157  {
158 
159  vapi_error_e rv = VAPI_OK;
160  if (!vapi_ctx)
161  {
162  if (VAPI_OK != (rv = vapi_ctx_alloc (&vapi_ctx)))
163  {
164  throw std::bad_alloc ();
165  }
166  }
167  events.reserve (vapi_get_message_count () + 1);
168  }
169 
170  Connection (const Connection &) = delete;
171 
172  ~Connection (void)
173  {
174  vapi_ctx_free (vapi_ctx);
175 #if VAPI_CPP_DEBUG_LEAKS
176  for (auto x : shm_data_set)
177  {
178  printf ("Leaked shm_data@%p!\n", x);
179  }
180 #endif
181  }
182 
183  /**
184  * @brief check if message identified by it's message id is known by the
185  * vpp to which the connection is open
186  */
188  {
189  return vapi_is_msg_available (vapi_ctx, type);
190  }
191 
192  /**
193  * @brief connect to vpp
194  *
195  * @param name application name
196  * @param chroot_prefix shared memory prefix
197  * @param max_queued_request max number of outstanding requests queued
198  *
199  * @return VAPI_OK on success, other error code on error
200  */
201  vapi_error_e connect (const char *name, const char *chroot_prefix,
202  int max_outstanding_requests, int response_queue_size)
203  {
204  return vapi_connect (vapi_ctx, name, chroot_prefix,
205  max_outstanding_requests, response_queue_size,
207  }
208 
209  /**
210  * @brief disconnect from vpp
211  *
212  * @return VAPI_OK on success, other error code on error
213  */
215  {
216  auto x = requests.size ();
217  while (x > 0)
218  {
219  VAPI_DBG ("popping request @%p", requests.front ());
220  requests.pop_front ();
221  --x;
222  }
223  return vapi_disconnect (vapi_ctx);
224  };
225 
226  /**
227  * @brief get event file descriptor
228  *
229  * @note this file descriptor becomes readable when messages (from vpp)
230  * are waiting in queue
231  *
232  * @param[out] fd pointer to result variable
233  *
234  * @return VAPI_OK on success, other error code on error
235  */
237  {
238  return vapi_get_fd (vapi_ctx, fd);
239  }
240 
241  /**
242  * @brief wait for responses from vpp and assign them to appropriate objects
243  *
244  * @param limit stop dispatch after the limit object received it's response
245  *
246  * @return VAPI_OK on success, other error code on error
247  */
248  vapi_error_e dispatch (const Common_req *limit = nullptr, u32 time = 5)
249  {
250  std::lock_guard<std::mutex> lock (dispatch_mutex);
251  vapi_error_e rv = VAPI_OK;
252  bool loop_again = true;
253  while (loop_again)
254  {
255  void *shm_data;
256  size_t shm_data_size;
257  rv = vapi_recv (vapi_ctx, &shm_data, &shm_data_size, SVM_Q_TIMEDWAIT,
258  time);
259  if (VAPI_OK != rv)
260  {
261  return rv;
262  }
263 #if VAPI_CPP_DEBUG_LEAKS
264  on_shm_data_alloc (shm_data);
265 #endif
266  std::lock_guard<std::recursive_mutex> requests_lock (requests_mutex);
267  std::lock_guard<std::recursive_mutex> events_lock (events_mutex);
269  vapi_ctx, be16toh (*static_cast<u16 *> (shm_data)));
270  bool has_context = vapi_msg_is_with_context (id);
271  bool break_dispatch = false;
272  Common_req *matching_req = nullptr;
273  if (has_context)
274  {
275  u32 context = *reinterpret_cast<u32 *> (
276  (static_cast<u8 *> (shm_data) + vapi_get_context_offset (id)));
277  const auto x = requests.front ();
278  matching_req = x;
279  if (context == x->context)
280  {
281  std::tie (rv, break_dispatch) =
282  x->assign_response (id, shm_data);
283  }
284  else
285  {
286  std::tie (rv, break_dispatch) =
287  x->assign_response (id, nullptr);
288  }
289  if (break_dispatch)
290  {
291  requests.pop_front ();
292  }
293  }
294  else
295  {
296  if (events[id])
297  {
298  std::tie (rv, break_dispatch) =
299  events[id]->assign_response (id, shm_data);
300  matching_req = events[id];
301  }
302  else
303  {
304  msg_free (shm_data);
305  }
306  }
307  if ((matching_req && matching_req == limit && break_dispatch) ||
308  VAPI_OK != rv)
309  {
310  return rv;
311  }
312  loop_again = !requests.empty () || (event_count > 0);
313  }
314  return rv;
315  }
316 
317  /**
318  * @brief convenience wrapper function
319  */
321  {
322  return dispatch (&limit);
323  }
324 
325  /**
326  * @brief wait for response to a specific request
327  *
328  * @param req request to wait for response for
329  *
330  * @return VAPI_OK on success, other error code on error
331  */
333  {
334  if (RESPONSE_READY == req.get_response_state ())
335  {
336  return VAPI_OK;
337  }
338  return dispatch (req);
339  }
340 
341 private:
342  void msg_free (void *shm_data)
343  {
344 #if VAPI_CPP_DEBUG_LEAKS
345  on_shm_data_free (shm_data);
346 #endif
347  vapi_msg_free (vapi_ctx, shm_data);
348  }
349 
350  template <template <typename XReq, typename XResp, typename... XArgs>
351  class X,
352  typename Req, typename Resp, typename... Args>
353  vapi_error_e send (X<Req, Resp, Args...> *req)
354  {
355  if (!req)
356  {
357  return VAPI_EINVAL;
358  }
359  u32 req_context =
360  req_context_counter.fetch_add (1, std::memory_order_relaxed);
361  req->request.shm_data->header.context = req_context;
362  vapi_swap_to_be<Req> (req->request.shm_data);
363  std::lock_guard<std::recursive_mutex> lock (requests_mutex);
364  vapi_error_e rv = vapi_send (vapi_ctx, req->request.shm_data);
365  if (VAPI_OK == rv)
366  {
367  VAPI_DBG ("Push %p", req);
368  requests.emplace_back (req);
369  req->set_context (req_context);
370 #if VAPI_CPP_DEBUG_LEAKS
371  on_shm_data_free (req->request.shm_data);
372 #endif
373  req->request.shm_data = nullptr; /* consumed by vapi_send */
374  }
375  else
376  {
377  vapi_swap_to_host<Req> (req->request.shm_data);
378  }
379  return rv;
380  }
381 
382  template <template <typename XReq, typename XResp, typename... XArgs>
383  class X,
384  typename Req, typename Resp, typename... Args>
385  vapi_error_e send_with_control_ping (X<Req, Resp, Args...> *req)
386  {
387  if (!req)
388  {
389  return VAPI_EINVAL;
390  }
391  u32 req_context =
392  req_context_counter.fetch_add (1, std::memory_order_relaxed);
393  req->request.shm_data->header.context = req_context;
394  vapi_swap_to_be<Req> (req->request.shm_data);
395  std::lock_guard<std::recursive_mutex> lock (requests_mutex);
396  vapi_error_e rv = vapi_send_with_control_ping (
397  vapi_ctx, req->request.shm_data, req_context);
398  if (VAPI_OK == rv)
399  {
400  VAPI_DBG ("Push %p", req);
401  requests.emplace_back (req);
402  req->set_context (req_context);
403 #if VAPI_CPP_DEBUG_LEAKS
404  on_shm_data_free (req->request.shm_data);
405 #endif
406  req->request.shm_data = nullptr; /* consumed by vapi_send */
407  }
408  else
409  {
410  vapi_swap_to_host<Req> (req->request.shm_data);
411  }
412  return rv;
413  }
414 
415  void unregister_request (Common_req *request)
416  {
417  std::lock_guard<std::recursive_mutex> lock (requests_mutex);
418  std::remove (requests.begin (), requests.end (), request);
419  }
420 
421  template <typename M> void register_event (Event_registration<M> *event)
422  {
423  const vapi_msg_id_t id = M::get_msg_id ();
424  std::lock_guard<std::recursive_mutex> lock (events_mutex);
425  events[id] = event;
426  ++event_count;
427  }
428 
429  template <typename M> void unregister_event (Event_registration<M> *event)
430  {
431  const vapi_msg_id_t id = M::get_msg_id ();
432  std::lock_guard<std::recursive_mutex> lock (events_mutex);
433  events[id] = nullptr;
434  --event_count;
435  }
436 
437  vapi_ctx_t vapi_ctx;
438  std::atomic_ulong req_context_counter;
439  std::mutex dispatch_mutex;
440 
441  std::recursive_mutex requests_mutex;
442  std::recursive_mutex events_mutex;
443  std::deque<Common_req *> requests;
444  std::vector<Common_req *> events;
445  int event_count;
446 
447  template <typename Req, typename Resp, typename... Args>
448  friend class Request;
449 
450  template <typename Req, typename Resp, typename... Args> friend class Dump;
451 
452  template <typename M> friend class Result_set;
453 
454  template <typename M> friend class Event_registration;
455 
456  template <typename M, typename... Args>
457  friend M *vapi_alloc (Connection &con, Args...);
458 
459  template <typename M> friend class Msg;
460 
461 #if VAPI_CPP_DEBUG_LEAKS
462  void on_shm_data_alloc (void *shm_data)
463  {
464  if (shm_data)
465  {
466  auto pos = shm_data_set.find (shm_data);
467  if (pos == shm_data_set.end ())
468  {
469  shm_data_set.insert (shm_data);
470  }
471  else
472  {
473  printf ("Double-add shm_data @%p!\n", shm_data);
474  }
475  }
476  }
477 
478  void on_shm_data_free (void *shm_data)
479  {
480  auto pos = shm_data_set.find (shm_data);
481  if (pos == shm_data_set.end ())
482  {
483  printf ("Freeing untracked shm_data @%p!\n", shm_data);
484  }
485  else
486  {
487  shm_data_set.erase (pos);
488  }
489  }
490  std::unordered_set<void *> shm_data_set;
491 #endif
492 };
493 
494 template <typename Req, typename Resp, typename... Args> class Request;
495 
496 template <typename Req, typename Resp, typename... Args> class Dump;
497 
498 template <class, class = void> struct vapi_has_payload_trait : std::false_type
499 {
500 };
501 
502 template <class... T> using vapi_void_t = void;
503 
504 template <class T>
505 struct vapi_has_payload_trait<T, vapi_void_t<decltype (&T::payload)>>
506  : std::true_type
507 {
508 };
509 
510 template <typename M> void vapi_msg_set_msg_id (vapi_msg_id_t id)
511 {
512  Msg<M>::set_msg_id (id);
513 }
514 
515 /**
516  * Class representing a message stored in shared memory
517  */
518 template <typename M> class Msg
519 {
520 public:
521  Msg (const Msg &) = delete;
522 
523  ~Msg ()
524  {
525  VAPI_DBG ("Destroy Msg<%s>@%p, shm_data@%p",
526  vapi_get_msg_name (get_msg_id ()), this, shm_data);
527  if (shm_data)
528  {
529  con.get ().msg_free (shm_data);
530  shm_data = nullptr;
531  }
532  }
533 
535  {
536  return *msg_id_holder ();
537  }
538 
539  template <typename X = M>
540  typename std::enable_if<vapi_has_payload_trait<X>::value,
541  decltype (X::payload) &>::type
542  get_payload () const
543  {
544  return shm_data->payload;
545  }
546 
547 private:
548  Msg (Msg<M> &&msg) : con{msg.con}
549  {
550  VAPI_DBG ("Move construct Msg<%s> from msg@%p to msg@%p, shm_data@%p",
551  vapi_get_msg_name (get_msg_id ()), &msg, this, msg.shm_data);
552  shm_data = msg.shm_data;
553  msg.shm_data = nullptr;
554  }
555 
556  Msg<M> &operator= (Msg<M> &&msg)
557  {
558  VAPI_DBG ("Move assign Msg<%s> from msg@%p to msg@%p, shm_data@%p",
559  vapi_get_msg_name (get_msg_id ()), &msg, this, msg.shm_data);
560  con.get ().msg_free (shm_data);
561  con = msg.con;
562  shm_data = msg.shm_data;
563  msg.shm_data = nullptr;
564  return *this;
565  }
566 
567  struct Msg_allocator : std::allocator<Msg<M>>
568  {
569  template <class U, class... Args> void construct (U *p, Args &&... args)
570  {
571  ::new ((void *)p) U (std::forward<Args> (args)...);
572  }
573 
574  template <class U> struct rebind
575  {
576  typedef Msg_allocator other;
577  };
578  };
579 
580  static void set_msg_id (vapi_msg_id_t id)
581  {
582  assert ((INVALID_MSG_ID == *msg_id_holder ()) ||
583  (id == *msg_id_holder ()));
584  *msg_id_holder () = id;
585  }
586 
587  static vapi_msg_id_t *msg_id_holder ()
588  {
589  static vapi_msg_id_t my_id{INVALID_MSG_ID};
590  return &my_id;
591  }
592 
593  Msg (Connection &con, void *shm_data) : con{con}
594  {
595  if (!con.is_msg_available (get_msg_id ()))
596  {
598  }
599  this->shm_data = static_cast<shm_data_type *> (shm_data);
600  VAPI_DBG ("New Msg<%s>@%p shm_data@%p", vapi_get_msg_name (get_msg_id ()),
601  this, shm_data);
602  }
603 
604  void assign_response (vapi_msg_id_t resp_id, void *shm_data)
605  {
606  assert (nullptr == this->shm_data);
607  if (resp_id != get_msg_id ())
608  {
610  }
611  this->shm_data = static_cast<M *> (shm_data);
612  vapi_swap_to_host<M> (this->shm_data);
613  VAPI_DBG ("Assign response to Msg<%s>@%p shm_data@%p",
614  vapi_get_msg_name (get_msg_id ()), this, shm_data);
615  }
616 
617  std::reference_wrapper<Connection> con;
618  using shm_data_type = M;
619  shm_data_type *shm_data;
620 
621  friend class Connection;
622 
623  template <typename Req, typename Resp, typename... Args>
624  friend class Request;
625 
626  template <typename Req, typename Resp, typename... Args> friend class Dump;
627 
628  template <typename X> friend class Event_registration;
629 
630  template <typename X> friend class Result_set;
631 
632  friend struct Msg_allocator;
633 
634  template <typename X> friend void vapi_msg_set_msg_id (vapi_msg_id_t id);
635 };
636 
637 /**
638  * Class representing a simple request - with a single response message
639  */
640 template <typename Req, typename Resp, typename... Args>
641 class Request : public Common_req
642 {
643 public:
644  Request (Connection &con, Args... args,
645  std::function<vapi_error_e (Request<Req, Resp, Args...> &)>
646  callback = nullptr)
647  : Common_req{con}, callback{callback},
648  request{con, vapi_alloc<Req> (con, args...)}, response{con, nullptr}
649  {
650  }
651 
652  Request (const Request &) = delete;
653 
654  virtual ~Request ()
655  {
656  if (RESPONSE_NOT_READY == get_response_state ())
657  {
658  con.unregister_request (this);
659  }
660  }
661 
662  vapi_error_e execute ()
663  {
664  return con.send (this);
665  }
666 
667  const Msg<Req> &get_request (void) const
668  {
669  return request;
670  }
671 
672  const Msg<Resp> &get_response (void)
673  {
674  return response;
675  }
676 
677 private:
678  virtual std::tuple<vapi_error_e, bool> assign_response (vapi_msg_id_t id,
679  void *shm_data)
680  {
681  assert (RESPONSE_NOT_READY == get_response_state ());
682  response.assign_response (id, shm_data);
683  set_response_state (RESPONSE_READY);
684  if (nullptr != callback)
685  {
686  return std::make_pair (callback (*this), true);
687  }
688  return std::make_pair (VAPI_OK, true);
689  }
690  std::function<vapi_error_e (Request<Req, Resp, Args...> &)> callback;
692  Msg<Resp> response;
693 
694  friend class Connection;
695 };
696 
697 /**
698  * Class representing iterable set of responses of the same type
699  */
700 template <typename M> class Result_set
701 {
702 public:
704  {
705  }
706 
707  Result_set (const Result_set &) = delete;
708 
709  bool is_complete () const
710  {
711  return complete;
712  }
713 
714  size_t size () const
715  {
716  return set.size ();
717  }
718 
719  using const_iterator =
720  typename std::vector<Msg<M>,
722 
724  {
725  return set.begin ();
726  }
727 
729  {
730  return set.end ();
731  }
732 
734  {
735  set.erase (pos);
736  }
737 
739  {
740  set.clear ();
741  }
742 
743 private:
744  void mark_complete ()
745  {
746  complete = true;
747  }
748 
749  void assign_response (vapi_msg_id_t resp_id, void *shm_data)
750  {
751  if (resp_id != Msg<M>::get_msg_id ())
752  {
753  {
755  }
756  }
757  else if (shm_data)
758  {
759  vapi_swap_to_host<M> (static_cast<M *> (shm_data));
760  set.emplace_back (con, shm_data);
761  VAPI_DBG ("Result_set@%p emplace_back shm_data@%p", this, shm_data);
762  }
763  }
764 
765  Result_set (Connection &con) : con (con), complete{false}
766  {
767  }
768 
769  Connection &con;
770  bool complete;
771  std::vector<Msg<M>, typename Msg<M>::Msg_allocator> set;
772 
773  template <typename Req, typename Resp, typename... Args> friend class Dump;
774 
775  template <typename X> friend class Event_registration;
776 };
777 
778 /**
779  * Class representing a dump request - zero or more identical responses to a
780  * single request message
781  */
782 template <typename Req, typename Resp, typename... Args>
783 class Dump : public Common_req
784 {
785 public:
786  Dump (Connection &con, Args... args,
787  std::function<vapi_error_e (Dump<Req, Resp, Args...> &)> callback =
788  nullptr)
789  : Common_req{con}, request{con, vapi_alloc<Req> (con, args...)},
790  result_set{con}, callback{callback}
791  {
792  }
793 
794  Dump (const Dump &) = delete;
795 
796  virtual ~Dump ()
797  {
798  }
799 
800  virtual std::tuple<vapi_error_e, bool> assign_response (vapi_msg_id_t id,
801  void *shm_data)
802  {
804  {
805  con.msg_free (shm_data);
806  result_set.mark_complete ();
807  set_response_state (RESPONSE_READY);
808  if (nullptr != callback)
809  {
810  return std::make_pair (callback (*this), true);
811  }
812  return std::make_pair (VAPI_OK, true);
813  }
814  else
815  {
816  result_set.assign_response (id, shm_data);
817  }
818  return std::make_pair (VAPI_OK, false);
819  }
820 
821  vapi_error_e execute ()
822  {
823  return con.send_with_control_ping (this);
824  }
825 
827  {
828  return request;
829  }
830 
832 
833  const Result_set<Resp> &get_result_set (void) const
834  {
835  return result_set;
836  }
837 
838 private:
840  Result_set<resp_type> result_set;
841  std::function<vapi_error_e (Dump<Req, Resp, Args...> &)> callback;
842 
843  friend class Connection;
844 };
845 
846 /**
847  * Class representing event registration - incoming events (messages) from
848  * vpp as a result of a subscription (typically a want_* simple request)
849  */
850 template <typename M> class Event_registration : public Common_req
851 {
852 public:
854  Connection &con,
855  std::function<vapi_error_e (Event_registration<M> &)> callback = nullptr)
856  : Common_req{con}, result_set{con}, callback{callback}
857  {
858  if (!con.is_msg_available (M::get_msg_id ()))
859  {
861  }
862  con.register_event (this);
863  }
864 
865  Event_registration (const Event_registration &) = delete;
866 
868  {
869  con.unregister_event (this);
870  }
871 
872  virtual std::tuple<vapi_error_e, bool> assign_response (vapi_msg_id_t id,
873  void *shm_data)
874  {
875  result_set.assign_response (id, shm_data);
876  if (nullptr != callback)
877  {
878  return std::make_pair (callback (*this), true);
879  }
880  return std::make_pair (VAPI_OK, true);
881  }
882 
883  using resp_type = typename M::shm_data_type;
884 
886  {
887  return result_set;
888  }
889 
890 private:
891  Result_set<resp_type> result_set;
892  std::function<vapi_error_e (Event_registration<M> &)> callback;
893 };
894 };
895 
896 #endif
897 
898 /*
899  * fd.io coding-style-patch-verification: ON
900  *
901  * Local Variables:
902  * eval: (c-set-style "gnu")
903  * End:
904  */
~Msg()
Definition: vapi.hpp:523
no response to request (will never come)
Definition: vapi.hpp:84
void vapi_msg_set_msg_id(vapi_msg_id_t id)
Definition: vapi.hpp:510
vapi_error_e dispatch(const Common_req &limit)
convenience wrapper function
Definition: vapi.hpp:320
operations block until response received
Definition: vapi_common.h:44
static vapi_msg_id_t get_msg_id()
Definition: vapi.hpp:534
vapi_error_e connect(const char *name, const char *chroot_prefix, int max_outstanding_requests, int response_queue_size)
connect to vpp
Definition: vapi.hpp:201
virtual ~Request()
Definition: vapi.hpp:654
size_t vapi_get_message_count()
Definition: vapi.c:919
vapi_msg_id_t vapi_get_msg_id_t()
Connection & get_connection()
Definition: vapi.hpp:96
virtual ~Common_req()
Definition: vapi.hpp:94
vapi_error_e execute()
Definition: vapi.hpp:821
vapi_error_e vapi_recv(vapi_ctx_t ctx, void **msg, size_t *msg_size, svm_q_conditional_wait_t cond, u32 time)
low-level api for reading messages from vpp
Definition: vapi.c:505
vapi_error_e vapi_send(vapi_ctx_t ctx, void *msg)
low-level api for sending messages to vpp
Definition: vapi.c:419
virtual const char * what() const
Definition: vapi.hpp:61
typename Msg< Resp >::shm_data_type resp_type
Definition: vapi.hpp:831
~Connection(void)
Definition: vapi.hpp:172
blocking call, return on signal or time-out
Definition: queue.h:54
void vapi_swap_to_be(M *msg)
Class representing event registration - incoming events (messages) from vpp as a result of a subscrip...
Definition: vapi.hpp:56
Forward declarations.
Definition: vapi.hpp:44
vapi_response_state_e get_response_state(void) const
Definition: vapi.hpp:101
vapi_error_e vapi_disconnect(vapi_ctx_t ctx)
disconnect from vpp
Definition: vapi.c:397
const Result_set< Resp > & get_result_set(void) const
Definition: vapi.hpp:833
Class representing iterable set of responses of the same type.
Definition: vapi.hpp:700
const Msg< Resp > & get_response(void)
Definition: vapi.hpp:672
size_t vapi_get_context_offset(vapi_msg_id_t id)
Definition: vapi.c:854
response to request is ready
Definition: vapi.hpp:81
vapi_msg_id_t vapi_msg_id_control_ping_reply
Definition: vapi.c:38
const Msg< Req > & get_request(void) const
Definition: vapi.hpp:667
const char * vapi_get_msg_name(vapi_msg_id_t id)
Definition: vapi.c:925
vapi_error_e disconnect()
disconnect from vpp
Definition: vapi.hpp:214
virtual ~Dump()
Definition: vapi.hpp:796
void free_all_responses()
Definition: vapi.hpp:738
vapi_error_e get_fd(int *fd)
get event file descriptor
Definition: vapi.hpp:236
invalid value encountered
Definition: vapi_common.h:28
common vpp api C declarations
virtual std::tuple< vapi_error_e, bool > assign_response(vapi_msg_id_t id, void *shm_data)
Definition: vapi.hpp:800
#define INVALID_MSG_ID
Definition: vapi_common.h:57
#define VAPI_DBG(...)
Definition: vapi_dbg.h:65
bool vapi_msg_is_with_context(vapi_msg_id_t id)
Definition: vapi.c:694
Connection(void)
Definition: vapi.hpp:156
Result_set< resp_type > & get_result_set(void)
Definition: vapi.hpp:885
M * vapi_alloc(Connection &con, Args...)
vapi_msg_id_t vapi_lookup_vapi_msg_id_t(vapi_ctx_t ctx, u16 vl_msg_id)
Definition: vapi.c:235
virtual ~Event_registration()
Definition: vapi.hpp:867
Class representing a message stored in shared memory.
Definition: vapi.hpp:50
Dump(Connection &con, Args...args, std::function< vapi_error_e(Dump< Req, Resp, Args... > &)> callback=nullptr)
Definition: vapi.hpp:786
Msg< Req > & get_request(void)
Definition: vapi.hpp:826
typename std::vector< Msg< resp_type >, typename Msg< resp_type >::Msg_allocator >::const_iterator const_iterator
Definition: vapi.hpp:721
vapi_error_e dispatch(const Common_req *limit=nullptr, u32 time=5)
wait for responses from vpp and assign them to appropriate objects
Definition: vapi.hpp:248
void vapi_swap_to_host(M *msg)
Class representing a connection to VPP.
Definition: vapi.hpp:153
internal vpp api C declarations
void free_response(const_iterator pos)
Definition: vapi.hpp:733
bool vapi_is_msg_available(vapi_ctx_t ctx, vapi_msg_id_t id)
check if message identified by it&#39;s message id is known by the vpp to which the connection is open ...
Definition: vapi.c:286
virtual std::tuple< vapi_error_e, bool > assign_response(vapi_msg_id_t id, void *shm_data)
Definition: vapi.hpp:872
success
Definition: vapi_common.h:27
unsigned int u32
Definition: types.h:88
const_iterator end() const
Definition: vapi.hpp:728
vhost_vring_state_t state
Definition: vhost-user.h:82
vapi_response_state_e
Definition: vapi.hpp:76
size_t size() const
Definition: vapi.hpp:714
response not ready yet
Definition: vapi.hpp:78
virtual const char * what() const
Definition: vapi.hpp:70
Request(Connection &con, Args...args, std::function< vapi_error_e(Request< Req, Resp, Args... > &)> callback=nullptr)
Definition: vapi.hpp:644
Event_registration(Connection &con, std::function< vapi_error_e(Event_registration< M > &)> callback=nullptr)
Definition: vapi.hpp:853
vapi_error_e wait_for_response(const Common_req &req)
wait for response to a specific request
Definition: vapi.hpp:332
void vapi_ctx_free(vapi_ctx_t ctx)
free vapi context
Definition: vapi.c:274
std::enable_if< vapi_has_payload_trait< X >::value, decltype(X::payload)& >::type get_payload() const
Definition: vapi.hpp:542
Class representing a simple request - with a single response message.
Definition: vapi.hpp:49
unsigned char u8
Definition: types.h:56
void vapi_void_t
Definition: vapi.hpp:502
Class representing a dump request - zero or more identical responses to a single request message...
Definition: vapi.hpp:496
bool is_msg_available(vapi_msg_id_t type)
check if message identified by it&#39;s message id is known by the vpp to which the connection is open ...
Definition: vapi.hpp:187
typename M::shm_data_type resp_type
Definition: vapi.hpp:883
vapi_error_e vapi_get_fd(vapi_ctx_t ctx, int *fd)
get event file descriptor
Definition: vapi.c:413
vhost_user_req_t request
Definition: vhost-user.h:76
vapi_error_e execute()
Definition: vapi.hpp:662
void vapi_msg_free(vapi_ctx_t ctx, void *msg)
free a vapi message
Definition: vapi.c:222
Class representing common functionality of a request - response state and context.
Definition: vapi.hpp:91
const_iterator begin() const
Definition: vapi.hpp:723
vapi_error_e vapi_connect(vapi_ctx_t ctx, const char *name, const char *chroot_prefix, int max_outstanding_requests, int response_queue_size, vapi_mode_e mode)
connect to vpp
Definition: vapi.c:292
vapi_error_e vapi_ctx_alloc(vapi_ctx_t *result)
allocate vapi context
Definition: vapi.c:245
unsigned int vapi_msg_id_t
Definition: vapi_common.h:55
bool is_complete() const
Definition: vapi.hpp:709
vapi_error_e
Definition: vapi_common.h:25
#define M(T, mp)