vcl: add support for app socket api
[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->bapi_client_index;
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->bapi_client_index;
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->bapi_client_index;
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->bapi_client_index;
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->bapi_client_index;
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->bapi_client_index;
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->bapi_client_index;
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, "%s-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   vlibapi_set_memory_client_main (&wrk->bapi_shm_ctx);
477   vcl_bapi_hookup ();
478
479   if (vcl_cfg->vpp_bapi_socket_name)
480     {
481       if (vl_socket_client_connect2 (&wrk->bapi_sock_ctx,
482                                      (char *) vcl_cfg->vpp_bapi_socket_name,
483                                      (char *) wrk_name,
484                                      0 /* default rx/tx buffer */ ))
485         {
486           VERR ("app (%s) socket connect failed!", wrk_name);
487           rv = VPPCOM_ECONNREFUSED;
488           goto error;
489         }
490
491       if (vl_socket_client_init_shm2 (&wrk->bapi_sock_ctx, 0,
492                                       1 /* want_pthread */ ))
493         {
494           VERR ("app (%s) init shm failed!", wrk_name);
495           rv = VPPCOM_ECONNREFUSED;
496           goto error;
497         }
498     }
499   else
500     {
501       if (!vcl_cfg->vpp_bapi_filename)
502         vcl_cfg->vpp_bapi_filename = format (0, "/vpe-api%c", 0);
503
504       vl_set_memory_root_path ((char *) vcl_cfg->vpp_bapi_chroot);
505
506       VDBG (0, "app (%s) connecting to VPP api (%s)...",
507             wrk_name, vcl_cfg->vpp_bapi_filename);
508
509       if (vl_client_connect_to_vlib ((char *) vcl_cfg->vpp_bapi_filename,
510                                      (char *) wrk_name,
511                                      vcm->cfg.vpp_api_q_length) < 0)
512         {
513           VERR ("app (%s) connect failed!", wrk_name);
514           rv = VPPCOM_ECONNREFUSED;
515           goto error;
516         }
517     }
518
519   am = vlibapi_get_main ();
520   wrk->vl_input_queue = am->shmem_hdr->vl_input_queue;
521   wrk->bapi_client_index = (u32) am->my_client_index;
522
523   VDBG (0, "app (%s) is connected to VPP!", wrk_name);
524   vcl_evt (VCL_EVT_INIT, vcm);
525
526 error:
527   vec_free (wrk_name);
528   return rv;
529 }
530
531 void
532 vcl_bapi_disconnect_from_vpp (void)
533 {
534   vcl_worker_t *wrk = vcl_worker_get_current ();
535   vppcom_cfg_t *vcl_cfg = &vcm->cfg;
536
537   if (vcl_cfg->vpp_bapi_socket_name)
538     vl_socket_client_disconnect2 (&wrk->bapi_sock_ctx);
539   else
540     vl_client_disconnect_from_vlib ();
541 }
542
543 static const char *
544 vcl_bapi_app_state_str (vcl_bapi_app_state_t state)
545 {
546   char *st;
547
548   switch (state)
549     {
550     case STATE_APP_START:
551       st = "STATE_APP_START";
552       break;
553
554     case STATE_APP_CONN_VPP:
555       st = "STATE_APP_CONN_VPP";
556       break;
557
558     case STATE_APP_ENABLED:
559       st = "STATE_APP_ENABLED";
560       break;
561
562     case STATE_APP_ATTACHED:
563       st = "STATE_APP_ATTACHED";
564       break;
565
566     default:
567       st = "UNKNOWN_APP_STATE";
568       break;
569     }
570
571   return st;
572 }
573
574 static int
575 vcl_bapi_wait_for_app_state_change (vcl_bapi_app_state_t app_state)
576 {
577   vcl_worker_t *wrk = vcl_worker_get_current ();
578   f64 timeout = clib_time_now (&wrk->clib_time) + vcm->cfg.app_timeout;
579
580   while (clib_time_now (&wrk->clib_time) < timeout)
581     {
582       if (vcm->bapi_app_state == app_state)
583         return VPPCOM_OK;
584       if (vcm->bapi_app_state == STATE_APP_FAILED)
585         return VPPCOM_ECONNABORTED;
586     }
587   VDBG (0, "timeout waiting for state %s (%d)",
588         vcl_bapi_app_state_str (app_state), app_state);
589   vcl_evt (VCL_EVT_SESSION_TIMEOUT, vcm, bapi_app_state);
590
591   return VPPCOM_ETIMEDOUT;
592 }
593
594 static int
595 vcl_bapi_session_enable (void)
596 {
597   int rv;
598
599   if (vcm->bapi_app_state != STATE_APP_ENABLED)
600     {
601       vcl_bapi_send_session_enable_disable (1 /* is_enabled == TRUE */ );
602       rv = vcl_bapi_wait_for_app_state_change (STATE_APP_ENABLED);
603       if (PREDICT_FALSE (rv))
604         {
605           VDBG (0, "application session enable timed out! returning %d (%s)",
606                 rv, vppcom_retval_str (rv));
607           return rv;
608         }
609     }
610   return VPPCOM_OK;
611 }
612
613 static int
614 vcl_bapi_init (void)
615 {
616   int rv;
617
618   vcm->bapi_app_state = STATE_APP_START;
619   vcl_bapi_init_error_string_table ();
620   rv = vcl_bapi_connect_to_vpp ();
621   if (rv)
622     {
623       VERR ("couldn't connect to VPP!");
624       return rv;
625     }
626   VDBG (0, "sending session enable");
627   rv = vcl_bapi_session_enable ();
628   if (rv)
629     {
630       VERR ("vppcom_app_session_enable() failed!");
631       return rv;
632     }
633
634   return 0;
635 }
636
637 int
638 vcl_bapi_attach (void)
639 {
640   int rv;
641
642   /* API hookup and connect to VPP */
643   if ((rv = vcl_bapi_init ()))
644     return rv;
645
646   vcl_bapi_send_attach ();
647   rv = vcl_bapi_wait_for_app_state_change (STATE_APP_ATTACHED);
648   if (PREDICT_FALSE (rv))
649     {
650       VDBG (0, "application attach timed out! returning %d (%s)", rv,
651             vppcom_retval_str (rv));
652       return rv;
653     }
654
655   return 0;
656 }
657
658 int
659 vcl_bapi_app_worker_add (void)
660 {
661   if (vcl_bapi_connect_to_vpp ())
662     return -1;
663
664   vcm->bapi_app_state = STATE_APP_ADDING_WORKER;
665   vcl_bapi_send_app_worker_add_del (1 /* is_add */ );
666   if (vcl_bapi_wait_for_app_state_change (STATE_APP_READY))
667     return -1;
668   return 0;
669 }
670
671 void
672 vcl_bapi_app_worker_del (vcl_worker_t * wrk)
673 {
674   /* Notify vpp that the worker is going away */
675   if (wrk->wrk_index == vcl_get_worker_index ())
676     vcl_bapi_send_app_worker_add_del (0 /* is_add */ );
677   else
678     vcl_bapi_send_child_worker_del (wrk);
679
680   /* Disconnect the binary api */
681   if (vec_len (vcm->workers) == 1)
682     vcl_bapi_disconnect_from_vpp ();
683   else
684     vl_client_send_disconnect (1 /* vpp should cleanup */ );
685 }
686
687 int
688 vcl_bapi_recv_fds (vcl_worker_t * wrk, int *fds, int n_fds)
689 {
690   clib_error_t *err;
691
692   if ((err = vl_socket_client_recv_fd_msg2 (&wrk->bapi_sock_ctx, fds, n_fds,
693                                             5)))
694     {
695       clib_error_report (err);
696       return -1;
697     }
698
699   return 0;
700 }
701
702 int
703 vppcom_session_tls_add_cert (uint32_t session_handle, char *cert,
704                              uint32_t cert_len)
705 {
706
707   vcl_worker_t *wrk = vcl_worker_get_current ();
708   vcl_session_t *session = 0;
709
710   session = vcl_session_get_w_handle (wrk, session_handle);
711   if (!session)
712     return VPPCOM_EBADFD;
713
714   if (cert_len == 0 || cert_len == ~0)
715     return VPPCOM_EBADFD;
716
717   /*
718    * Send listen request to vpp and wait for reply
719    */
720   vcl_bapi_send_application_tls_cert_add (session, cert, cert_len);
721   vcm->bapi_app_state = STATE_APP_ADDING_TLS_DATA;
722   vcl_bapi_wait_for_app_state_change (STATE_APP_READY);
723   return VPPCOM_OK;
724 }
725
726 int
727 vppcom_session_tls_add_key (uint32_t session_handle, char *key,
728                             uint32_t key_len)
729 {
730
731   vcl_worker_t *wrk = vcl_worker_get_current ();
732   vcl_session_t *session = 0;
733
734   session = vcl_session_get_w_handle (wrk, session_handle);
735   if (!session)
736     return VPPCOM_EBADFD;
737
738   if (key_len == 0 || key_len == ~0)
739     return VPPCOM_EBADFD;
740
741   vcl_bapi_send_application_tls_key_add (session, key, key_len);
742   vcm->bapi_app_state = STATE_APP_ADDING_TLS_DATA;
743   vcl_bapi_wait_for_app_state_change (STATE_APP_READY);
744   return VPPCOM_OK;
745 }
746
747 int
748 vcl_bapi_worker_set (void)
749 {
750   vcl_worker_t *wrk = vcl_worker_get_current ();
751   int i;
752
753   /* Find the first worker with the same pid */
754   for (i = 0; i < vec_len (vcm->workers); i++)
755     {
756       if (i == wrk->wrk_index)
757         continue;
758       if (vcm->workers[i].current_pid == wrk->current_pid)
759         {
760           wrk->vl_input_queue = vcm->workers[i].vl_input_queue;
761           wrk->bapi_client_index = vcm->workers[i].bapi_client_index;
762           return 0;
763         }
764     }
765   return -1;
766 }
767
768 /*
769  * fd.io coding-style-patch-verification: ON
770  *
771  * Local Variables:
772  * eval: (c-set-style "gnu")
773  * End:
774  */