FD.io VPP  v18.01-8-g0eacf49
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)
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);
258  if (VAPI_OK != rv)
259  {
260  return rv;
261  }
262 #if VAPI_CPP_DEBUG_LEAKS
263  on_shm_data_alloc (shm_data);
264 #endif
265  std::lock_guard<std::recursive_mutex> requests_lock (requests_mutex);
266  std::lock_guard<std::recursive_mutex> events_lock (events_mutex);
268  vapi_ctx, be16toh (*static_cast<u16 *> (shm_data)));
269  bool has_context = vapi_msg_is_with_context (id);
270  bool break_dispatch = false;
271  Common_req *matching_req = nullptr;
272  if (has_context)
273  {
274  u32 context = *reinterpret_cast<u32 *> (
275  (static_cast<u8 *> (shm_data) + vapi_get_context_offset (id)));
276  const auto x = requests.front ();
277  matching_req = x;
278  if (context == x->context)
279  {
280  std::tie (rv, break_dispatch) =
281  x->assign_response (id, shm_data);
282  }
283  else
284  {
285  std::tie (rv, break_dispatch) =
286  x->assign_response (id, nullptr);
287  }
288  if (break_dispatch)
289  {
290  requests.pop_front ();
291  }
292  }
293  else
294  {
295  if (events[id])
296  {
297  std::tie (rv, break_dispatch) =
298  events[id]->assign_response (id, shm_data);
299  matching_req = events[id];
300  }
301  else
302  {
303  msg_free (shm_data);
304  }
305  }
306  if ((matching_req && matching_req == limit && break_dispatch) ||
307  VAPI_OK != rv)
308  {
309  return rv;
310  }
311  loop_again = !requests.empty () || (event_count > 0);
312  }
313  return rv;
314  }
315 
316  /**
317  * @brief convenience wrapper function
318  */
320  {
321  return dispatch (&limit);
322  }
323 
324  /**
325  * @brief wait for response to a specific request
326  *
327  * @param req request to wait for response for
328  *
329  * @return VAPI_OK on success, other error code on error
330  */
332  {
333  if (RESPONSE_READY == req.get_response_state ())
334  {
335  return VAPI_OK;
336  }
337  return dispatch (req);
338  }
339 
340 private:
341  void msg_free (void *shm_data)
342  {
343 #if VAPI_CPP_DEBUG_LEAKS
344  on_shm_data_free (shm_data);
345 #endif
346  vapi_msg_free (vapi_ctx, shm_data);
347  }
348 
349  template <template <typename XReq, typename XResp, typename... XArgs>
350  class X,
351  typename Req, typename Resp, typename... Args>
352  vapi_error_e send (X<Req, Resp, Args...> *req)
353  {
354  if (!req)
355  {
356  return VAPI_EINVAL;
357  }
358  u32 req_context =
359  req_context_counter.fetch_add (1, std::memory_order_relaxed);
360  req->request.shm_data->header.context = req_context;
361  vapi_swap_to_be<Req> (req->request.shm_data);
362  std::lock_guard<std::recursive_mutex> lock (requests_mutex);
363  vapi_error_e rv = vapi_send (vapi_ctx, req->request.shm_data);
364  if (VAPI_OK == rv)
365  {
366  VAPI_DBG ("Push %p", req);
367  requests.emplace_back (req);
368  req->set_context (req_context);
369 #if VAPI_CPP_DEBUG_LEAKS
370  on_shm_data_free (req->request.shm_data);
371 #endif
372  req->request.shm_data = nullptr; /* consumed by vapi_send */
373  }
374  else
375  {
376  vapi_swap_to_host<Req> (req->request.shm_data);
377  }
378  return rv;
379  }
380 
381  template <template <typename XReq, typename XResp, typename... XArgs>
382  class X,
383  typename Req, typename Resp, typename... Args>
384  vapi_error_e send_with_control_ping (X<Req, Resp, Args...> *req)
385  {
386  if (!req)
387  {
388  return VAPI_EINVAL;
389  }
390  u32 req_context =
391  req_context_counter.fetch_add (1, std::memory_order_relaxed);
392  req->request.shm_data->header.context = req_context;
393  vapi_swap_to_be<Req> (req->request.shm_data);
394  std::lock_guard<std::recursive_mutex> lock (requests_mutex);
395  vapi_error_e rv = vapi_send_with_control_ping (
396  vapi_ctx, req->request.shm_data, req_context);
397  if (VAPI_OK == rv)
398  {
399  VAPI_DBG ("Push %p", req);
400  requests.emplace_back (req);
401  req->set_context (req_context);
402 #if VAPI_CPP_DEBUG_LEAKS
403  on_shm_data_free (req->request.shm_data);
404 #endif
405  req->request.shm_data = nullptr; /* consumed by vapi_send */
406  }
407  else
408  {
409  vapi_swap_to_host<Req> (req->request.shm_data);
410  }
411  return rv;
412  }
413 
414  void unregister_request (Common_req *request)
415  {
416  std::lock_guard<std::recursive_mutex> lock (requests_mutex);
417  std::remove (requests.begin (), requests.end (), request);
418  }
419 
420  template <typename M> void register_event (Event_registration<M> *event)
421  {
422  const vapi_msg_id_t id = M::get_msg_id ();
423  std::lock_guard<std::recursive_mutex> lock (events_mutex);
424  events[id] = event;
425  ++event_count;
426  }
427 
428  template <typename M> void unregister_event (Event_registration<M> *event)
429  {
430  const vapi_msg_id_t id = M::get_msg_id ();
431  std::lock_guard<std::recursive_mutex> lock (events_mutex);
432  events[id] = nullptr;
433  --event_count;
434  }
435 
436  vapi_ctx_t vapi_ctx;
437  std::atomic_ulong req_context_counter;
438  std::mutex dispatch_mutex;
439 
440  std::recursive_mutex requests_mutex;
441  std::recursive_mutex events_mutex;
442  std::deque<Common_req *> requests;
443  std::vector<Common_req *> events;
444  int event_count;
445 
446  template <typename Req, typename Resp, typename... Args>
447  friend class Request;
448 
449  template <typename Req, typename Resp, typename... Args> friend class Dump;
450 
451  template <typename M> friend class Result_set;
452 
453  template <typename M> friend class Event_registration;
454 
455  template <typename M, typename... Args>
456  friend M *vapi_alloc (Connection &con, Args...);
457 
458  template <typename M> friend class Msg;
459 
460 #if VAPI_CPP_DEBUG_LEAKS
461  void on_shm_data_alloc (void *shm_data)
462  {
463  if (shm_data)
464  {
465  auto pos = shm_data_set.find (shm_data);
466  if (pos == shm_data_set.end ())
467  {
468  shm_data_set.insert (shm_data);
469  }
470  else
471  {
472  printf ("Double-add shm_data @%p!\n", shm_data);
473  }
474  }
475  }
476 
477  void on_shm_data_free (void *shm_data)
478  {
479  auto pos = shm_data_set.find (shm_data);
480  if (pos == shm_data_set.end ())
481  {
482  printf ("Freeing untracked shm_data @%p!\n", shm_data);
483  }
484  else
485  {
486  shm_data_set.erase (pos);
487  }
488  }
489  std::unordered_set<void *> shm_data_set;
490 #endif
491 };
492 
493 template <typename Req, typename Resp, typename... Args> class Request;
494 
495 template <typename Req, typename Resp, typename... Args> class Dump;
496 
497 template <class, class = void> struct vapi_has_payload_trait : std::false_type
498 {
499 };
500 
501 template <class... T> using vapi_void_t = void;
502 
503 template <class T>
504 struct vapi_has_payload_trait<T, vapi_void_t<decltype (&T::payload)>>
505  : std::true_type
506 {
507 };
508 
509 template <typename M> void vapi_msg_set_msg_id (vapi_msg_id_t id)
510 {
511  Msg<M>::set_msg_id (id);
512 }
513 
514 /**
515  * Class representing a message stored in shared memory
516  */
517 template <typename M> class Msg
518 {
519 public:
520  Msg (const Msg &) = delete;
521 
522  ~Msg ()
523  {
524  VAPI_DBG ("Destroy Msg<%s>@%p, shm_data@%p",
525  vapi_get_msg_name (get_msg_id ()), this, shm_data);
526  if (shm_data)
527  {
528  con.get ().msg_free (shm_data);
529  shm_data = nullptr;
530  }
531  }
532 
534  {
535  return *msg_id_holder ();
536  }
537 
538  template <typename X = M>
539  typename std::enable_if<vapi_has_payload_trait<X>::value,
540  decltype (X::payload) &>::type
541  get_payload () const
542  {
543  return shm_data->payload;
544  }
545 
546 private:
547  Msg (Msg<M> &&msg) : con{msg.con}
548  {
549  VAPI_DBG ("Move construct Msg<%s> from msg@%p to msg@%p, shm_data@%p",
550  vapi_get_msg_name (get_msg_id ()), &msg, this, msg.shm_data);
551  shm_data = msg.shm_data;
552  msg.shm_data = nullptr;
553  }
554 
555  Msg<M> &operator= (Msg<M> &&msg)
556  {
557  VAPI_DBG ("Move assign Msg<%s> from msg@%p to msg@%p, shm_data@%p",
558  vapi_get_msg_name (get_msg_id ()), &msg, this, msg.shm_data);
559  con.get ().msg_free (shm_data);
560  con = msg.con;
561  shm_data = msg.shm_data;
562  msg.shm_data = nullptr;
563  return *this;
564  }
565 
566  struct Msg_allocator : std::allocator<Msg<M>>
567  {
568  template <class U, class... Args> void construct (U *p, Args &&... args)
569  {
570  ::new ((void *)p) U (std::forward<Args> (args)...);
571  }
572 
573  template <class U> struct rebind
574  {
575  typedef Msg_allocator other;
576  };
577  };
578 
579  static void set_msg_id (vapi_msg_id_t id)
580  {
581  assert ((INVALID_MSG_ID == *msg_id_holder ()) ||
582  (id == *msg_id_holder ()));
583  *msg_id_holder () = id;
584  }
585 
586  static vapi_msg_id_t *msg_id_holder ()
587  {
588  static vapi_msg_id_t my_id{INVALID_MSG_ID};
589  return &my_id;
590  }
591 
592  Msg (Connection &con, void *shm_data) : con{con}
593  {
594  if (!con.is_msg_available (get_msg_id ()))
595  {
597  }
598  this->shm_data = static_cast<shm_data_type *> (shm_data);
599  VAPI_DBG ("New Msg<%s>@%p shm_data@%p", vapi_get_msg_name (get_msg_id ()),
600  this, shm_data);
601  }
602 
603  void assign_response (vapi_msg_id_t resp_id, void *shm_data)
604  {
605  assert (nullptr == this->shm_data);
606  if (resp_id != get_msg_id ())
607  {
609  }
610  this->shm_data = static_cast<M *> (shm_data);
611  vapi_swap_to_host<M> (this->shm_data);
612  VAPI_DBG ("Assign response to Msg<%s>@%p shm_data@%p",
613  vapi_get_msg_name (get_msg_id ()), this, shm_data);
614  }
615 
616  std::reference_wrapper<Connection> con;
617  using shm_data_type = M;
618  shm_data_type *shm_data;
619 
620  friend class Connection;
621 
622  template <typename Req, typename Resp, typename... Args>
623  friend class Request;
624 
625  template <typename Req, typename Resp, typename... Args> friend class Dump;
626 
627  template <typename X> friend class Event_registration;
628 
629  template <typename X> friend class Result_set;
630 
631  friend struct Msg_allocator;
632 
633  template <typename X> friend void vapi_msg_set_msg_id (vapi_msg_id_t id);
634 };
635 
636 /**
637  * Class representing a simple request - with a single response message
638  */
639 template <typename Req, typename Resp, typename... Args>
640 class Request : public Common_req
641 {
642 public:
643  Request (Connection &con, Args... args,
644  std::function<vapi_error_e (Request<Req, Resp, Args...> &)>
645  callback = nullptr)
646  : Common_req{con}, callback{callback},
647  request{con, vapi_alloc<Req> (con, args...)}, response{con, nullptr}
648  {
649  }
650 
651  Request (const Request &) = delete;
652 
653  virtual ~Request ()
654  {
655  if (RESPONSE_NOT_READY == get_response_state ())
656  {
657  con.unregister_request (this);
658  }
659  }
660 
661  vapi_error_e execute ()
662  {
663  return con.send (this);
664  }
665 
666  const Msg<Req> &get_request (void) const
667  {
668  return request;
669  }
670 
671  const Msg<Resp> &get_response (void)
672  {
673  return response;
674  }
675 
676 private:
677  virtual std::tuple<vapi_error_e, bool> assign_response (vapi_msg_id_t id,
678  void *shm_data)
679  {
680  assert (RESPONSE_NOT_READY == get_response_state ());
681  response.assign_response (id, shm_data);
682  set_response_state (RESPONSE_READY);
683  if (nullptr != callback)
684  {
685  return std::make_pair (callback (*this), true);
686  }
687  return std::make_pair (VAPI_OK, true);
688  }
689  std::function<vapi_error_e (Request<Req, Resp, Args...> &)> callback;
691  Msg<Resp> response;
692 
693  friend class Connection;
694 };
695 
696 /**
697  * Class representing iterable set of responses of the same type
698  */
699 template <typename M> class Result_set
700 {
701 public:
703  {
704  }
705 
706  Result_set (const Result_set &) = delete;
707 
708  bool is_complete () const
709  {
710  return complete;
711  }
712 
713  size_t size () const
714  {
715  return set.size ();
716  }
717 
718  using const_iterator =
719  typename std::vector<Msg<M>,
721 
723  {
724  return set.begin ();
725  }
726 
728  {
729  return set.end ();
730  }
731 
733  {
734  set.erase (pos);
735  }
736 
738  {
739  set.clear ();
740  }
741 
742 private:
743  void mark_complete ()
744  {
745  complete = true;
746  }
747 
748  void assign_response (vapi_msg_id_t resp_id, void *shm_data)
749  {
750  if (resp_id != Msg<M>::get_msg_id ())
751  {
752  {
754  }
755  }
756  else if (shm_data)
757  {
758  vapi_swap_to_host<M> (static_cast<M *> (shm_data));
759  set.emplace_back (con, shm_data);
760  VAPI_DBG ("Result_set@%p emplace_back shm_data@%p", this, shm_data);
761  }
762  }
763 
764  Result_set (Connection &con) : con (con), complete{false}
765  {
766  }
767 
768  Connection &con;
769  bool complete;
770  std::vector<Msg<M>, typename Msg<M>::Msg_allocator> set;
771 
772  template <typename Req, typename Resp, typename... Args> friend class Dump;
773 
774  template <typename X> friend class Event_registration;
775 };
776 
777 /**
778  * Class representing a dump request - zero or more identical responses to a
779  * single request message
780  */
781 template <typename Req, typename Resp, typename... Args>
782 class Dump : public Common_req
783 {
784 public:
785  Dump (Connection &con, Args... args,
786  std::function<vapi_error_e (Dump<Req, Resp, Args...> &)> callback =
787  nullptr)
788  : Common_req{con}, request{con, vapi_alloc<Req> (con, args...)},
789  result_set{con}, callback{callback}
790  {
791  }
792 
793  Dump (const Dump &) = delete;
794 
795  virtual ~Dump ()
796  {
797  }
798 
799  virtual std::tuple<vapi_error_e, bool> assign_response (vapi_msg_id_t id,
800  void *shm_data)
801  {
803  {
804  con.msg_free (shm_data);
805  result_set.mark_complete ();
806  set_response_state (RESPONSE_READY);
807  if (nullptr != callback)
808  {
809  return std::make_pair (callback (*this), true);
810  }
811  return std::make_pair (VAPI_OK, true);
812  }
813  else
814  {
815  result_set.assign_response (id, shm_data);
816  }
817  return std::make_pair (VAPI_OK, false);
818  }
819 
820  vapi_error_e execute ()
821  {
822  return con.send_with_control_ping (this);
823  }
824 
826  {
827  return request;
828  }
829 
831 
832  const Result_set<Resp> &get_result_set (void) const
833  {
834  return result_set;
835  }
836 
837 private:
839  Result_set<resp_type> result_set;
840  std::function<vapi_error_e (Dump<Req, Resp, Args...> &)> callback;
841 
842  friend class Connection;
843 };
844 
845 /**
846  * Class representing event registration - incoming events (messages) from
847  * vpp as a result of a subscription (typically a want_* simple request)
848  */
849 template <typename M> class Event_registration : public Common_req
850 {
851 public:
853  Connection &con,
854  std::function<vapi_error_e (Event_registration<M> &)> callback = nullptr)
855  : Common_req{con}, result_set{con}, callback{callback}
856  {
857  if (!con.is_msg_available (M::get_msg_id ()))
858  {
860  }
861  con.register_event (this);
862  }
863 
864  Event_registration (const Event_registration &) = delete;
865 
867  {
868  con.unregister_event (this);
869  }
870 
871  virtual std::tuple<vapi_error_e, bool> assign_response (vapi_msg_id_t id,
872  void *shm_data)
873  {
874  result_set.assign_response (id, shm_data);
875  if (nullptr != callback)
876  {
877  return std::make_pair (callback (*this), true);
878  }
879  return std::make_pair (VAPI_OK, true);
880  }
881 
882  using resp_type = typename M::shm_data_type;
883 
885  {
886  return result_set;
887  }
888 
889 private:
890  Result_set<resp_type> result_set;
891  std::function<vapi_error_e (Event_registration<M> &)> callback;
892 };
893 };
894 
895 #endif
896 
897 /*
898  * fd.io coding-style-patch-verification: ON
899  *
900  * Local Variables:
901  * eval: (c-set-style "gnu")
902  * End:
903  */
~Msg()
Definition: vapi.hpp:522
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:509
vapi_error_e dispatch(const Common_req &limit)
convenience wrapper function
Definition: vapi.hpp:319
operations block until response received
Definition: vapi_common.h:44
static vapi_msg_id_t get_msg_id()
Definition: vapi.hpp:533
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:653
size_t vapi_get_message_count()
Definition: vapi.c:918
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:820
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:830
~Connection(void)
Definition: vapi.hpp:172
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_error_e vapi_recv(vapi_ctx_t ctx, void **msg, size_t *msg_size)
low-level api for reading messages from vpp
Definition: vapi.c:507
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:832
Class representing iterable set of responses of the same type.
Definition: vapi.hpp:699
const Msg< Resp > & get_response(void)
Definition: vapi.hpp:671
size_t vapi_get_context_offset(vapi_msg_id_t id)
Definition: vapi.c:853
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:666
const char * vapi_get_msg_name(vapi_msg_id_t id)
Definition: vapi.c:924
vapi_error_e disconnect()
disconnect from vpp
Definition: vapi.hpp:214
virtual ~Dump()
Definition: vapi.hpp:795
void free_all_responses()
Definition: vapi.hpp:737
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:799
#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:693
Connection(void)
Definition: vapi.hpp:156
Result_set< resp_type > & get_result_set(void)
Definition: vapi.hpp:884
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:866
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:785
Msg< Req > & get_request(void)
Definition: vapi.hpp:825
typename std::vector< Msg< resp_type >, typename Msg< resp_type >::Msg_allocator >::const_iterator const_iterator
Definition: vapi.hpp:720
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:732
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:871
success
Definition: vapi_common.h:27
unsigned int u32
Definition: types.h:88
const_iterator end() const
Definition: vapi.hpp:727
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:713
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:643
Event_registration(Connection &con, std::function< vapi_error_e(Event_registration< M > &)> callback=nullptr)
Definition: vapi.hpp:852
vapi_error_e wait_for_response(const Common_req &req)
wait for response to a specific request
Definition: vapi.hpp:331
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:541
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:501
Class representing a dump request - zero or more identical responses to a single request message...
Definition: vapi.hpp:495
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:882
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:661
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:722
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:708
vapi_error_e
Definition: vapi_common.h:25
vapi_error_e dispatch(const Common_req *limit=nullptr)
wait for responses from vpp and assign them to appropriate objects
Definition: vapi.hpp:248
#define M(T, mp)