vcl: remove support for shm api connections
[vpp.git] / src / vcl / vcl_bapi.c
1 /*
2  * Copyright (c) 2018-2019 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this
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 #include <vcl/vcl_private.h>
17 #include <vlibmemory/api.h>
18 #include <vpp/api/vpe_msg_enum.h>
19
20 #define vl_typedefs             /* define message structures */
21 #include <vpp/api/vpe_all_api_h.h>
22 #undef vl_typedefs
23
24 /* declare message handlers for each api */
25
26 #define vl_endianfun            /* define message structures */
27 #include <vpp/api/vpe_all_api_h.h>
28 #undef vl_endianfun
29
30 /* instantiate all the print functions we know about */
31 #define vl_print(handle, ...)
32 #define vl_printfun
33 #include <vpp/api/vpe_all_api_h.h>
34 #undef vl_printfun
35
36 static u8 *
37 format_api_error (u8 * s, va_list * args)
38 {
39   i32 error = va_arg (*args, u32);
40   uword *p;
41
42   p = hash_get (vcm->error_string_by_error_number, -error);
43
44   if (p)
45     s = format (s, "%s (%d)", p[0], error);
46   else
47     s = format (s, "%d", error);
48   return s;
49 }
50
51 static void
52   vl_api_session_enable_disable_reply_t_handler
53   (vl_api_session_enable_disable_reply_t * mp)
54 {
55   if (mp->retval)
56     {
57       clib_warning ("VCL<%d>: session_enable_disable failed: %U", getpid (),
58                     format_api_error, ntohl (mp->retval));
59     }
60   else
61     vcm->bapi_app_state = STATE_APP_ENABLED;
62 }
63
64 static void
65 vl_api_app_attach_reply_t_handler (vl_api_app_attach_reply_t * mp)
66 {
67   vcl_worker_t *wrk = vcl_worker_get (0);
68   svm_msg_q_t *ctrl_mq;
69   u64 segment_handle;
70   int *fds = 0, i, rv;
71   u32 n_fds = 0;
72   char *segment_name = 0;
73
74   if (mp->retval)
75     {
76       VERR ("attach failed: %U", format_api_error, ntohl (mp->retval));
77       goto failed;
78     }
79
80   wrk->app_event_queue = uword_to_pointer (mp->app_mq, svm_msg_q_t *);
81   ctrl_mq = uword_to_pointer (mp->vpp_ctrl_mq, svm_msg_q_t *);
82   vec_validate (wrk->vpp_event_queues, mp->vpp_ctrl_mq_thread);
83   wrk->vpp_event_queues[mp->vpp_ctrl_mq_thread] = ctrl_mq;
84   vcm->ctrl_mq = wrk->ctrl_mq = ctrl_mq;
85   segment_handle = clib_net_to_host_u64 (mp->segment_handle);
86   if (segment_handle == VCL_INVALID_SEGMENT_HANDLE)
87     {
88       VERR ("invalid segment handle");
89       goto failed;
90     }
91
92   if (mp->n_fds)
93     {
94       vec_validate (fds, mp->n_fds);
95       if (vl_socket_client_recv_fd_msg2 (&wrk->bapi_sock_ctx, fds, mp->n_fds,
96                                          5))
97         goto failed;
98
99       if (mp->fd_flags & SESSION_FD_F_VPP_MQ_SEGMENT)
100         if (vcl_segment_attach (vcl_vpp_worker_segment_handle (0),
101                                 "vpp-mq-seg", SSVM_SEGMENT_MEMFD,
102                                 fds[n_fds++]))
103           goto failed;
104
105       if (mp->fd_flags & SESSION_FD_F_MEMFD_SEGMENT)
106         {
107           segment_name = vl_api_from_api_to_new_c_string (&mp->segment_name);
108           rv =
109             vcl_segment_attach (segment_handle, segment_name,
110                                 SSVM_SEGMENT_MEMFD, fds[n_fds++]);
111           vec_free (segment_name);
112           if (rv != 0)
113             goto failed;
114         }
115
116
117       if (mp->fd_flags & SESSION_FD_F_MQ_EVENTFD)
118         {
119           svm_msg_q_set_consumer_eventfd (wrk->app_event_queue, fds[n_fds]);
120           vcl_mq_epoll_add_evfd (wrk, wrk->app_event_queue);
121           n_fds++;
122         }
123
124       vec_free (fds);
125     }
126   else
127     {
128       segment_name = vl_api_from_api_to_new_c_string (&mp->segment_name);
129       rv =
130         vcl_segment_attach (segment_handle, segment_name, SSVM_SEGMENT_SHM,
131                             -1);
132       vec_free (segment_name);
133       if (rv != 0)
134         goto failed;
135     }
136
137   vcm->app_index = clib_net_to_host_u32 (mp->app_index);
138   vcm->bapi_app_state = STATE_APP_ATTACHED;
139   return;
140
141 failed:
142   vcm->bapi_app_state = STATE_APP_FAILED;
143   for (i = clib_max (n_fds - 1, 0); i < vec_len (fds); i++)
144     close (fds[i]);
145   vec_free (fds);
146 }
147
148 static void
149 vl_api_app_worker_add_del_reply_t_handler (vl_api_app_worker_add_del_reply_t *
150                                            mp)
151 {
152   int n_fds = 0, *fds = 0, i, rv;
153   u64 segment_handle;
154   vcl_worker_t *wrk;
155   u32 wrk_index;
156   char *segment_name = 0;
157
158   if (mp->retval)
159     {
160       clib_warning ("VCL<%d>: add/del worker failed: %U", getpid (),
161                     format_api_error, ntohl (mp->retval));
162       goto failed;
163     }
164
165   if (!mp->is_add)
166     return;
167
168   wrk_index = mp->context;
169   wrk = vcl_worker_get_if_valid (wrk_index);
170   if (!wrk)
171     return;
172
173   wrk->vpp_wrk_index = clib_net_to_host_u32 (mp->wrk_index);
174   wrk->app_event_queue = uword_to_pointer (mp->app_event_queue_address,
175                                            svm_msg_q_t *);
176   wrk->ctrl_mq = vcm->ctrl_mq;
177
178   segment_handle = clib_net_to_host_u64 (mp->segment_handle);
179   if (segment_handle == VCL_INVALID_SEGMENT_HANDLE)
180     {
181       clib_warning ("invalid segment handle");
182       goto failed;
183     }
184
185   if (mp->n_fds)
186     {
187       vec_validate (fds, mp->n_fds);
188       if (vl_socket_client_recv_fd_msg2 (&wrk->bapi_sock_ctx, fds, mp->n_fds,
189                                          5))
190         goto failed;
191
192       if (mp->fd_flags & SESSION_FD_F_VPP_MQ_SEGMENT)
193         if (vcl_segment_attach (vcl_vpp_worker_segment_handle (wrk_index),
194                                 "vpp-worker-seg", SSVM_SEGMENT_MEMFD,
195                                 fds[n_fds++]))
196           goto failed;
197
198       if (mp->fd_flags & SESSION_FD_F_MEMFD_SEGMENT)
199         {
200           segment_name = vl_api_from_api_to_new_c_string (&mp->segment_name);
201           rv =
202             vcl_segment_attach (segment_handle, segment_name,
203                                 SSVM_SEGMENT_MEMFD, fds[n_fds++]);
204           vec_free (segment_name);
205           if (rv != 0)
206             goto failed;
207         }
208
209       if (mp->fd_flags & SESSION_FD_F_MQ_EVENTFD)
210         {
211           svm_msg_q_set_consumer_eventfd (wrk->app_event_queue, fds[n_fds]);
212           vcl_mq_epoll_add_evfd (wrk, wrk->app_event_queue);
213           n_fds++;
214         }
215
216       vec_free (fds);
217     }
218   else
219     {
220       segment_name = vl_api_from_api_to_new_c_string (&mp->segment_name);
221       rv =
222         vcl_segment_attach (segment_handle, segment_name, SSVM_SEGMENT_SHM,
223                             -1);
224       vec_free (segment_name);
225       if (rv != 0)
226         goto failed;
227     }
228   vcm->bapi_app_state = STATE_APP_READY;
229   VDBG (0, "worker %u vpp-worker %u added", wrk_index, wrk->vpp_wrk_index);
230   return;
231
232 failed:
233   vcm->bapi_app_state = STATE_APP_FAILED;
234   for (i = clib_max (n_fds - 1, 0); i < vec_len (fds); i++)
235     close (fds[i]);
236   vec_free (fds);
237 }
238
239 static void
240   vl_api_application_tls_cert_add_reply_t_handler
241   (vl_api_application_tls_cert_add_reply_t * mp)
242 {
243   if (mp->retval)
244     VDBG (0, "add cert failed: %U", format_api_error, ntohl (mp->retval));
245   vcm->bapi_app_state = STATE_APP_READY;
246 }
247
248 static void
249   vl_api_application_tls_key_add_reply_t_handler
250   (vl_api_application_tls_key_add_reply_t * mp)
251 {
252   if (mp->retval)
253     VDBG (0, "add key failed: %U", format_api_error, ntohl (mp->retval));
254   vcm->bapi_app_state = STATE_APP_READY;
255 }
256
257 #define foreach_sock_msg                                                \
258 _(SESSION_ENABLE_DISABLE_REPLY, session_enable_disable_reply)           \
259 _(APP_ATTACH_REPLY, app_attach_reply)                                   \
260 _(APPLICATION_TLS_CERT_ADD_REPLY, application_tls_cert_add_reply)       \
261 _(APPLICATION_TLS_KEY_ADD_REPLY, application_tls_key_add_reply)         \
262 _(APP_WORKER_ADD_DEL_REPLY, app_worker_add_del_reply)                   \
263
264 static void
265 vcl_bapi_hookup (void)
266 {
267 #define _(N, n)                                                 \
268     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
269                            vl_api_##n##_t_handler,              \
270                            vl_noop_handler,                     \
271                            vl_api_##n##_t_endian,               \
272                            vl_api_##n##_t_print,                \
273                            sizeof(vl_api_##n##_t), 1);
274   foreach_sock_msg;
275 #undef _
276 }
277
278 /*
279  * VPP-API message functions
280  */
281 static void
282 vcl_bapi_send_session_enable_disable (u8 is_enable)
283 {
284   vcl_worker_t *wrk = vcl_worker_get_current ();
285   vl_api_session_enable_disable_t *bmp;
286   bmp = vl_msg_api_alloc (sizeof (*bmp));
287   memset (bmp, 0, sizeof (*bmp));
288
289   bmp->_vl_msg_id = ntohs (VL_API_SESSION_ENABLE_DISABLE);
290   bmp->client_index = wrk->api_client_handle;
291   bmp->context = htonl (0xfeedface);
292   bmp->is_enable = is_enable;
293   vl_msg_api_send_shmem (wrk->vl_input_queue, (u8 *) & bmp);
294 }
295
296 void
297 vcl_bapi_send_attach (void)
298 {
299   vcl_worker_t *wrk = vcl_worker_get_current ();
300   u8 tls_engine = CRYPTO_ENGINE_OPENSSL;
301   vl_api_app_attach_t *bmp;
302   u8 nsid_len = vec_len (vcm->cfg.namespace_id);
303   u8 app_is_proxy = (vcm->cfg.app_proxy_transport_tcp ||
304                      vcm->cfg.app_proxy_transport_udp);
305
306   tls_engine = vcm->cfg.tls_engine ? vcm->cfg.tls_engine : tls_engine;
307
308   bmp = vl_msg_api_alloc (sizeof (*bmp));
309   memset (bmp, 0, sizeof (*bmp));
310
311   bmp->_vl_msg_id = ntohs (VL_API_APP_ATTACH);
312   bmp->client_index = wrk->api_client_handle;
313   bmp->context = htonl (0xfeedface);
314   bmp->options[APP_OPTIONS_FLAGS] =
315     APP_OPTIONS_FLAGS_ACCEPT_REDIRECT | APP_OPTIONS_FLAGS_ADD_SEGMENT |
316     (vcm->cfg.app_scope_local ? APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE : 0) |
317     (vcm->cfg.app_scope_global ? APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE : 0) |
318     (app_is_proxy ? APP_OPTIONS_FLAGS_IS_PROXY : 0) |
319     (vcm->cfg.use_mq_eventfd ? APP_OPTIONS_FLAGS_EVT_MQ_USE_EVENTFD : 0);
320   bmp->options[APP_OPTIONS_PROXY_TRANSPORT] =
321     (u64) ((vcm->cfg.app_proxy_transport_tcp ? 1 << TRANSPORT_PROTO_TCP : 0) |
322            (vcm->cfg.app_proxy_transport_udp ? 1 << TRANSPORT_PROTO_UDP : 0));
323   bmp->options[APP_OPTIONS_SEGMENT_SIZE] = vcm->cfg.segment_size;
324   bmp->options[APP_OPTIONS_ADD_SEGMENT_SIZE] = vcm->cfg.add_segment_size;
325   bmp->options[APP_OPTIONS_RX_FIFO_SIZE] = vcm->cfg.rx_fifo_size;
326   bmp->options[APP_OPTIONS_TX_FIFO_SIZE] = vcm->cfg.tx_fifo_size;
327   bmp->options[APP_OPTIONS_PREALLOC_FIFO_PAIRS] =
328     vcm->cfg.preallocated_fifo_pairs;
329   bmp->options[APP_OPTIONS_EVT_QUEUE_SIZE] = vcm->cfg.event_queue_size;
330   bmp->options[APP_OPTIONS_TLS_ENGINE] = tls_engine;
331   if (nsid_len)
332     {
333       vl_api_vec_to_api_string (vcm->cfg.namespace_id, &bmp->namespace_id);
334       bmp->options[APP_OPTIONS_NAMESPACE_SECRET] = vcm->cfg.namespace_secret;
335     }
336   vl_msg_api_send_shmem (wrk->vl_input_queue, (u8 *) & bmp);
337 }
338
339 void
340 vcl_bapi_send_detach (void)
341 {
342   vcl_worker_t *wrk = vcl_worker_get_current ();
343   vl_api_application_detach_t *bmp;
344   bmp = vl_msg_api_alloc (sizeof (*bmp));
345   memset (bmp, 0, sizeof (*bmp));
346
347   bmp->_vl_msg_id = ntohs (VL_API_APPLICATION_DETACH);
348   bmp->client_index = wrk->api_client_handle;
349   bmp->context = htonl (0xfeedface);
350   vl_msg_api_send_shmem (wrk->vl_input_queue, (u8 *) & bmp);
351 }
352
353 static void
354 vcl_bapi_send_app_worker_add_del (u8 is_add)
355 {
356   vcl_worker_t *wrk = vcl_worker_get_current ();
357   vl_api_app_worker_add_del_t *mp;
358
359   mp = vl_msg_api_alloc (sizeof (*mp));
360   memset (mp, 0, sizeof (*mp));
361
362   mp->_vl_msg_id = ntohs (VL_API_APP_WORKER_ADD_DEL);
363   mp->client_index = wrk->api_client_handle;
364   mp->app_index = clib_host_to_net_u32 (vcm->app_index);
365   mp->context = wrk->wrk_index;
366   mp->is_add = is_add;
367   if (!is_add)
368     mp->wrk_index = clib_host_to_net_u32 (wrk->vpp_wrk_index);
369
370   vl_msg_api_send_shmem (wrk->vl_input_queue, (u8 *) & mp);
371 }
372
373 static void
374 vcl_bapi_send_child_worker_del (vcl_worker_t * child_wrk)
375 {
376   vcl_worker_t *wrk = vcl_worker_get_current ();
377   vl_api_app_worker_add_del_t *mp;
378
379   mp = vl_msg_api_alloc (sizeof (*mp));
380   memset (mp, 0, sizeof (*mp));
381
382   mp->_vl_msg_id = ntohs (VL_API_APP_WORKER_ADD_DEL);
383   mp->client_index = wrk->api_client_handle;
384   mp->app_index = clib_host_to_net_u32 (vcm->app_index);
385   mp->context = wrk->wrk_index;
386   mp->is_add = 0;
387   mp->wrk_index = clib_host_to_net_u32 (child_wrk->vpp_wrk_index);
388
389   vl_msg_api_send_shmem (wrk->vl_input_queue, (u8 *) & mp);
390 }
391
392 void
393 vcl_bapi_send_application_tls_cert_add (vcl_session_t * session, char *cert,
394                                         u32 cert_len)
395 {
396   vcl_worker_t *wrk = vcl_worker_get_current ();
397   vl_api_application_tls_cert_add_t *cert_mp;
398
399   cert_mp = vl_msg_api_alloc (sizeof (*cert_mp) + cert_len);
400   clib_memset (cert_mp, 0, sizeof (*cert_mp));
401   cert_mp->_vl_msg_id = ntohs (VL_API_APPLICATION_TLS_CERT_ADD);
402   cert_mp->client_index = wrk->api_client_handle;
403   cert_mp->context = session->session_index;
404   cert_mp->cert_len = clib_host_to_net_u16 (cert_len);
405   clib_memcpy_fast (cert_mp->cert, cert, cert_len);
406   vl_msg_api_send_shmem (wrk->vl_input_queue, (u8 *) & cert_mp);
407 }
408
409 void
410 vcl_bapi_send_application_tls_key_add (vcl_session_t * session, char *key,
411                                        u32 key_len)
412 {
413   vcl_worker_t *wrk = vcl_worker_get_current ();
414   vl_api_application_tls_key_add_t *key_mp;
415
416   key_mp = vl_msg_api_alloc (sizeof (*key_mp) + key_len);
417   clib_memset (key_mp, 0, sizeof (*key_mp));
418   key_mp->_vl_msg_id = ntohs (VL_API_APPLICATION_TLS_KEY_ADD);
419   key_mp->client_index = wrk->api_client_handle;
420   key_mp->context = session->session_index;
421   key_mp->key_len = clib_host_to_net_u16 (key_len);
422   clib_memcpy_fast (key_mp->key, key, key_len);
423   vl_msg_api_send_shmem (wrk->vl_input_queue, (u8 *) & key_mp);
424 }
425
426 u32
427 vcl_bapi_max_nsid_len (void)
428 {
429   vl_api_app_attach_t *mp;
430   return (sizeof (mp->namespace_id) - 1);
431 }
432
433 static void
434 vcl_bapi_init_error_string_table (void)
435 {
436   vcm->error_string_by_error_number = hash_create (0, sizeof (uword));
437
438 #define _(n, v, s) hash_set (vcm->error_string_by_error_number, -v, s);
439   foreach_vnet_api_error;
440 #undef _
441
442   hash_set (vcm->error_string_by_error_number, 99, "Misc");
443 }
444
445 static void
446 vcl_bapi_cleanup (void)
447 {
448   socket_client_main_t *scm = &socket_client_main;
449   api_main_t *am = vlibapi_get_main ();
450
451   am->my_client_index = ~0;
452   am->my_registration = 0;
453   am->vl_input_queue = 0;
454   am->msg_index_by_name_and_crc = 0;
455   scm->socket_fd = 0;
456
457   vl_client_api_unmap ();
458 }
459
460 static int
461 vcl_bapi_connect_to_vpp (void)
462 {
463   vcl_worker_t *wrk = vcl_worker_get_current ();
464   vppcom_cfg_t *vcl_cfg = &vcm->cfg;
465   int rv = VPPCOM_OK;
466   api_main_t *am;
467   u8 *wrk_name;
468
469   wrk_name = format (0, "%v-wrk-%u%c", vcm->app_name, wrk->wrk_index, 0);
470
471   /* Make sure api is cleaned up in case this is a connect from a
472    * forked worker */
473   vcl_bapi_cleanup ();
474
475   vlibapi_set_main (&wrk->bapi_api_ctx);
476   vcl_bapi_hookup ();
477
478   if (!vcl_cfg->vpp_bapi_socket_name)
479     {
480       rv = VPPCOM_EINVAL;
481       goto error;
482     }
483
484   if (vl_socket_client_connect2 (&wrk->bapi_sock_ctx,
485                                  (char *) vcl_cfg->vpp_bapi_socket_name,
486                                  (char *) wrk_name,
487                                  0 /* default rx/tx buffer */ ))
488     {
489       VERR ("app (%s) socket connect failed!", wrk_name);
490       rv = VPPCOM_ECONNREFUSED;
491       goto error;
492     }
493
494   if (vl_socket_client_init_shm2 (&wrk->bapi_sock_ctx, 0,
495                                   1 /* want_pthread */ ))
496     {
497       VERR ("app (%s) init shm failed!", wrk_name);
498       rv = VPPCOM_ECONNREFUSED;
499       goto error;
500     }
501
502   am = vlibapi_get_main ();
503   wrk->vl_input_queue = am->shmem_hdr->vl_input_queue;
504   wrk->api_client_handle = (u32) am->my_client_index;
505
506   VDBG (0, "app (%s) is connected to VPP!", wrk_name);
507   vcl_evt (VCL_EVT_INIT, vcm);
508
509 error:
510   vec_free (wrk_name);
511   return rv;
512 }
513
514 void
515 vcl_bapi_disconnect_from_vpp (void)
516 {
517   vcl_worker_t *wrk = vcl_worker_get_current ();
518   vppcom_cfg_t *vcl_cfg = &vcm->cfg;
519
520   if (vcl_cfg->vpp_bapi_socket_name)
521     vl_socket_client_disconnect2 (&wrk->bapi_sock_ctx);
522   else
523     vl_client_disconnect_from_vlib ();
524 }
525
526 static const char *
527 vcl_bapi_app_state_str (vcl_bapi_app_state_t state)
528 {
529   char *st;
530
531   switch (state)
532     {
533     case STATE_APP_START:
534       st = "STATE_APP_START";
535       break;
536
537     case STATE_APP_CONN_VPP:
538       st = "STATE_APP_CONN_VPP";
539       break;
540
541     case STATE_APP_ENABLED:
542       st = "STATE_APP_ENABLED";
543       break;
544
545     case STATE_APP_ATTACHED:
546       st = "STATE_APP_ATTACHED";
547       break;
548
549     default:
550       st = "UNKNOWN_APP_STATE";
551       break;
552     }
553
554   return st;
555 }
556
557 static int
558 vcl_bapi_wait_for_app_state_change (vcl_bapi_app_state_t app_state)
559 {
560   vcl_worker_t *wrk = vcl_worker_get_current ();
561   f64 timeout = clib_time_now (&wrk->clib_time) + vcm->cfg.app_timeout;
562
563   while (clib_time_now (&wrk->clib_time) < timeout)
564     {
565       if (vcm->bapi_app_state == app_state)
566         return VPPCOM_OK;
567       if (vcm->bapi_app_state == STATE_APP_FAILED)
568         return VPPCOM_ECONNABORTED;
569     }
570   VDBG (0, "timeout waiting for state %s (%d)",
571         vcl_bapi_app_state_str (app_state), app_state);
572   vcl_evt (VCL_EVT_SESSION_TIMEOUT, vcm, bapi_app_state);
573
574   return VPPCOM_ETIMEDOUT;
575 }
576
577 static int
578 vcl_bapi_session_enable (void)
579 {
580   int rv;
581
582   if (vcm->bapi_app_state != STATE_APP_ENABLED)
583     {
584       vcl_bapi_send_session_enable_disable (1 /* is_enabled == TRUE */ );
585       rv = vcl_bapi_wait_for_app_state_change (STATE_APP_ENABLED);
586       if (PREDICT_FALSE (rv))
587         {
588           VDBG (0, "application session enable timed out! returning %d (%s)",
589                 rv, vppcom_retval_str (rv));
590           return rv;
591         }
592     }
593   return VPPCOM_OK;
594 }
595
596 static int
597 vcl_bapi_init (void)
598 {
599   int rv;
600
601   vcm->bapi_app_state = STATE_APP_START;
602   vcl_bapi_init_error_string_table ();
603   rv = vcl_bapi_connect_to_vpp ();
604   if (rv)
605     {
606       VERR ("couldn't connect to VPP!");
607       return rv;
608     }
609   VDBG (0, "sending session enable");
610   rv = vcl_bapi_session_enable ();
611   if (rv)
612     {
613       VERR ("vppcom_app_session_enable() failed!");
614       return rv;
615     }
616
617   return 0;
618 }
619
620 int
621 vcl_bapi_attach (void)
622 {
623   int rv;
624
625   /* API hookup and connect to VPP */
626   if ((rv = vcl_bapi_init ()))
627     return rv;
628
629   vcl_bapi_send_attach ();
630   rv = vcl_bapi_wait_for_app_state_change (STATE_APP_ATTACHED);
631   if (PREDICT_FALSE (rv))
632     {
633       VDBG (0, "application attach timed out! returning %d (%s)", rv,
634             vppcom_retval_str (rv));
635       return rv;
636     }
637
638   return 0;
639 }
640
641 int
642 vcl_bapi_app_worker_add (void)
643 {
644   if (vcl_bapi_connect_to_vpp ())
645     return -1;
646
647   vcm->bapi_app_state = STATE_APP_ADDING_WORKER;
648   vcl_bapi_send_app_worker_add_del (1 /* is_add */ );
649   if (vcl_bapi_wait_for_app_state_change (STATE_APP_READY))
650     return -1;
651   return 0;
652 }
653
654 void
655 vcl_bapi_app_worker_del (vcl_worker_t * wrk)
656 {
657   /* Notify vpp that the worker is going away */
658   if (wrk->wrk_index == vcl_get_worker_index ())
659     vcl_bapi_send_app_worker_add_del (0 /* is_add */ );
660   else
661     vcl_bapi_send_child_worker_del (wrk);
662
663   /* Disconnect the binary api */
664   if (vec_len (vcm->workers) == 1)
665     vcl_bapi_disconnect_from_vpp ();
666   else
667     vl_client_send_disconnect (1 /* vpp should cleanup */ );
668 }
669
670 int
671 vcl_bapi_recv_fds (vcl_worker_t * wrk, int *fds, int n_fds)
672 {
673   clib_error_t *err;
674
675   if ((err = vl_socket_client_recv_fd_msg2 (&wrk->bapi_sock_ctx, fds, n_fds,
676                                             5)))
677     {
678       clib_error_report (err);
679       return -1;
680     }
681
682   return 0;
683 }
684
685 int
686 vppcom_session_tls_add_cert (uint32_t session_handle, char *cert,
687                              uint32_t cert_len)
688 {
689
690   vcl_worker_t *wrk = vcl_worker_get_current ();
691   vcl_session_t *session = 0;
692
693   session = vcl_session_get_w_handle (wrk, session_handle);
694   if (!session)
695     return VPPCOM_EBADFD;
696
697   if (cert_len == 0 || cert_len == ~0)
698     return VPPCOM_EBADFD;
699
700   /*
701    * Send listen request to vpp and wait for reply
702    */
703   vcl_bapi_send_application_tls_cert_add (session, cert, cert_len);
704   vcm->bapi_app_state = STATE_APP_ADDING_TLS_DATA;
705   vcl_bapi_wait_for_app_state_change (STATE_APP_READY);
706   return VPPCOM_OK;
707 }
708
709 int
710 vppcom_session_tls_add_key (uint32_t session_handle, char *key,
711                             uint32_t key_len)
712 {
713
714   vcl_worker_t *wrk = vcl_worker_get_current ();
715   vcl_session_t *session = 0;
716
717   session = vcl_session_get_w_handle (wrk, session_handle);
718   if (!session)
719     return VPPCOM_EBADFD;
720
721   if (key_len == 0 || key_len == ~0)
722     return VPPCOM_EBADFD;
723
724   vcl_bapi_send_application_tls_key_add (session, key, key_len);
725   vcm->bapi_app_state = STATE_APP_ADDING_TLS_DATA;
726   vcl_bapi_wait_for_app_state_change (STATE_APP_READY);
727   return VPPCOM_OK;
728 }
729
730 int
731 vcl_bapi_worker_set (void)
732 {
733   vcl_worker_t *wrk = vcl_worker_get_current ();
734   int i;
735
736   /* Find the first worker with the same pid */
737   for (i = 0; i < vec_len (vcm->workers); i++)
738     {
739       if (i == wrk->wrk_index)
740         continue;
741       if (vcm->workers[i].current_pid == wrk->current_pid)
742         {
743           wrk->vl_input_queue = vcm->workers[i].vl_input_queue;
744           wrk->api_client_handle = vcm->workers[i].api_client_handle;
745           return 0;
746         }
747     }
748   return -1;
749 }
750
751 /*
752  * fd.io coding-style-patch-verification: ON
753  *
754  * Local Variables:
755  * eval: (c-set-style "gnu")
756  * End:
757  */