vpp_echo_bapi.c revision 08f26641
1/*
2 * Copyright (c) 2019 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <stdio.h>
17#include <signal.h>
18
19#include <hs_apps/sapi/vpp_echo_common.h>
20
21/*
22 *
23 *  Binary API Messages
24 *
25 */
26
27void
28echo_send_attach (echo_main_t * em)
29{
30  vl_api_app_attach_t *bmp;
31  bmp = vl_msg_api_alloc (sizeof (*bmp));
32  clib_memset (bmp, 0, sizeof (*bmp));
33
34  bmp->_vl_msg_id = ntohs (VL_API_APP_ATTACH);
35  bmp->client_index = em->my_client_index;
36  bmp->context = ntohl (0xfeedface);
37  bmp->options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_ACCEPT_REDIRECT;
38  bmp->options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_ADD_SEGMENT;
39  bmp->options[APP_OPTIONS_PREALLOC_FIFO_PAIRS] = em->prealloc_fifo_pairs;
40  bmp->options[APP_OPTIONS_RX_FIFO_SIZE] = em->fifo_size;
41  bmp->options[APP_OPTIONS_TX_FIFO_SIZE] = em->fifo_size;
42  bmp->options[APP_OPTIONS_ADD_SEGMENT_SIZE] = 128 << 20;
43  bmp->options[APP_OPTIONS_SEGMENT_SIZE] = 256 << 20;
44  bmp->options[APP_OPTIONS_EVT_QUEUE_SIZE] = em->evt_q_size;
45  if (em->appns_id)
46    {
47      bmp->namespace_id_len = vec_len (em->appns_id);
48      clib_memcpy_fast (bmp->namespace_id, em->appns_id,
49			bmp->namespace_id_len);
50      bmp->options[APP_OPTIONS_FLAGS] |= em->appns_flags;
51      bmp->options[APP_OPTIONS_NAMESPACE_SECRET] = em->appns_secret;
52    }
53  vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & bmp);
54}
55
56void
57echo_send_detach (echo_main_t * em)
58{
59  vl_api_application_detach_t *bmp;
60  bmp = vl_msg_api_alloc (sizeof (*bmp));
61  clib_memset (bmp, 0, sizeof (*bmp));
62
63  bmp->_vl_msg_id = ntohs (VL_API_APPLICATION_DETACH);
64  bmp->client_index = em->my_client_index;
65  bmp->context = ntohl (0xfeedface);
66
67  vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & bmp);
68}
69
70void
71echo_send_add_cert_key (echo_main_t * em)
72{
73  u32 cert_len = test_srv_crt_rsa_len;
74  u32 key_len = test_srv_key_rsa_len;
75  vl_api_app_add_cert_key_pair_t *bmp;
76
77  bmp = vl_msg_api_alloc (sizeof (*bmp) + cert_len + key_len);
78  clib_memset (bmp, 0, sizeof (*bmp) + cert_len + key_len);
79
80  bmp->_vl_msg_id = ntohs (VL_API_APP_ADD_CERT_KEY_PAIR);
81  bmp->client_index = em->my_client_index;
82  bmp->context = ntohl (0xfeedface);
83  bmp->cert_len = clib_host_to_net_u16 (cert_len);
84  bmp->certkey_len = clib_host_to_net_u16 (key_len + cert_len);
85  clib_memcpy_fast (bmp->certkey, test_srv_crt_rsa, cert_len);
86  clib_memcpy_fast (bmp->certkey + cert_len, test_srv_key_rsa, key_len);
87
88  vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & bmp);
89}
90
91void
92echo_send_del_cert_key (echo_main_t * em)
93{
94  vl_api_app_del_cert_key_pair_t *bmp;
95  bmp = vl_msg_api_alloc (sizeof (*bmp));
96  clib_memset (bmp, 0, sizeof (*bmp));
97
98  bmp->_vl_msg_id = ntohs (VL_API_APP_DEL_CERT_KEY_PAIR);
99  bmp->client_index = em->my_client_index;
100  bmp->context = ntohl (0xfeedface);
101  bmp->index = clib_host_to_net_u32 (em->ckpair_index);
102  vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & bmp);
103}
104
105void
106echo_send_listen (echo_main_t * em)
107{
108  app_session_evt_t _app_evt, *app_evt = &_app_evt;
109  session_listen_msg_t *mp;
110  svm_msg_q_t *mq = em->ctrl_mq;
111
112  app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_LISTEN);
113  mp = (session_listen_msg_t *) app_evt->evt->data;
114  memset (mp, 0, sizeof (*mp));
115  mp->client_index = em->my_client_index;
116  mp->context = ntohl (0xfeedface);
117  mp->wrk_index = 0;
118  mp->is_ip4 = em->uri_elts.is_ip4;
119  clib_memcpy_fast (&mp->ip, &em->uri_elts.ip, sizeof (mp->ip));
120  mp->port = em->uri_elts.port;
121  mp->proto = em->uri_elts.transport_proto;
122  mp->ckpair_index = em->ckpair_index;
123  mp->crypto_engine = em->crypto_engine;
124  app_send_ctrl_evt_to_vpp (mq, app_evt);
125}
126
127void
128echo_send_unbind (echo_main_t * em, echo_session_t * s)
129{
130  app_session_evt_t _app_evt, *app_evt = &_app_evt;
131  session_unlisten_msg_t *mp;
132  svm_msg_q_t *mq = em->ctrl_mq;
133
134  app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_UNLISTEN);
135  mp = (session_unlisten_msg_t *) app_evt->evt->data;
136  memset (mp, 0, sizeof (*mp));
137  mp->client_index = em->my_client_index;
138  mp->wrk_index = 0;
139  mp->handle = s->vpp_session_handle;
140  mp->context = 0;
141  app_send_ctrl_evt_to_vpp (mq, app_evt);
142}
143
144void
145echo_send_connect (u64 parent_session_handle, u32 opaque)
146{
147  echo_main_t *em = &echo_main;
148  app_session_evt_t _app_evt, *app_evt = &_app_evt;
149  session_connect_msg_t *mp;
150  svm_msg_q_t *mq = em->ctrl_mq;
151
152  clib_atomic_sub_fetch (&em->max_sim_connects, 1);
153  while (em->max_sim_connects <= 0)
154    ;
155
156  app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_CONNECT);
157  mp = (session_connect_msg_t *) app_evt->evt->data;
158  memset (mp, 0, sizeof (*mp));
159  mp->client_index = em->my_client_index;
160  mp->context = ntohl (opaque);
161  mp->wrk_index = 0;
162  mp->is_ip4 = em->uri_elts.is_ip4;
163  clib_memcpy_fast (&mp->ip, &em->uri_elts.ip, sizeof (mp->ip));
164  mp->port = em->uri_elts.port;
165  mp->proto = em->uri_elts.transport_proto;
166  mp->parent_handle = parent_session_handle;
167  mp->ckpair_index = em->ckpair_index;
168  mp->crypto_engine = em->crypto_engine;
169  app_send_ctrl_evt_to_vpp (mq, app_evt);
170}
171
172void
173echo_send_disconnect_session (u64 handle, u32 opaque)
174{
175  echo_main_t *em = &echo_main;
176  echo_session_t *s;
177  app_session_evt_t _app_evt, *app_evt = &_app_evt;
178  session_disconnect_msg_t *mp;
179  svm_msg_q_t *mq = em->ctrl_mq;
180
181  app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_DISCONNECT);
182  mp = (session_disconnect_msg_t *) app_evt->evt->data;
183  memset (mp, 0, sizeof (*mp));
184  mp->client_index = em->my_client_index;
185  mp->handle = handle;
186  app_send_ctrl_evt_to_vpp (mq, app_evt);
187
188  if (!(s = echo_get_session_from_handle (em, mp->handle)))
189    return;
190  em->proto_cb_vft->sent_disconnect_cb (s);
191}
192
193/*
194 *
195 *  Helpers
196 *
197 */
198
199static int
200ssvm_segment_attach (char *name, ssvm_segment_type_t type, int fd)
201{
202  fifo_segment_create_args_t _a, *a = &_a;
203  fifo_segment_main_t *sm = &echo_main.segment_main;
204  int rv;
205
206  clib_memset (a, 0, sizeof (*a));
207  a->segment_name = (char *) name;
208  a->segment_type = type;
209
210  if (type == SSVM_SEGMENT_MEMFD)
211    a->memfd_fd = fd;
212
213  if ((rv = fifo_segment_attach (sm, a)))
214    return rv;
215  vec_reset_length (a->new_segment_indices);
216  return 0;
217}
218
219static inline void
220echo_segment_handle_add_del (echo_main_t * em, u64 segment_handle, u8 add)
221{
222  clib_spinlock_lock (&em->segment_handles_lock);
223  if (add)
224    hash_set (em->shared_segment_handles, segment_handle, 1);
225  else
226    hash_unset (em->shared_segment_handles, segment_handle);
227  clib_spinlock_unlock (&em->segment_handles_lock);
228}
229
230/*
231 *
232 *  Binary API callbacks
233 *
234 */
235
236static void
237  vl_api_app_add_cert_key_pair_reply_t_handler
238  (vl_api_app_add_cert_key_pair_reply_t * mp)
239{
240  echo_main_t *em = &echo_main;
241  if (mp->retval)
242    {
243      ECHO_FAIL (ECHO_FAIL_VL_API_CERT_KEY_ADD_REPLY,
244		 "Adding cert and key returned %d",
245		 clib_net_to_host_u32 (mp->retval));
246      return;
247    }
248  /* No concurrency here, only bapi thread writes */
249  if (em->state != STATE_ATTACHED_NO_CERT)
250    {
251      ECHO_FAIL (ECHO_FAIL_VL_API_CERT_KEY_ADD_REPLY, "Wrong state");
252      return;
253    }
254  em->ckpair_index = clib_net_to_host_u32 (mp->index);
255  em->state = STATE_ATTACHED;
256}
257
258static void
259  vl_api_app_del_cert_key_pair_reply_t_handler
260  (vl_api_app_del_cert_key_pair_reply_t * mp)
261{
262  echo_main_t *em = &echo_main;
263  if (mp->retval)
264    {
265      ECHO_FAIL (ECHO_FAIL_VL_API_CERT_KEY_DEL_REPLY,
266		 "Delete cert and key returned %d",
267		 clib_net_to_host_u32 (mp->retval));
268      return;
269    }
270  em->state = STATE_CLEANED_CERT_KEY;
271}
272
273static void
274vl_api_app_attach_reply_t_handler (vl_api_app_attach_reply_t * mp)
275{
276  echo_main_t *em = &echo_main;
277  int *fds = 0, i;
278  u32 n_fds = 0;
279  u64 segment_handle;
280  segment_handle = clib_net_to_host_u64 (mp->segment_handle);
281  ECHO_LOG (2, "Attached returned app %u", htons (mp->app_index));
282
283  if (mp->retval)
284    {
285      ECHO_FAIL (ECHO_FAIL_VL_API_APP_ATTACH, "attach failed: %U",
286		 format_api_error, clib_net_to_host_u32 (mp->retval));
287      return;
288    }
289
290  if (mp->segment_name_length == 0)
291    {
292      ECHO_FAIL (ECHO_FAIL_VL_API_MISSING_SEGMENT_NAME,
293		 "segment_name_length zero");
294      return;
295    }
296
297  if (!mp->app_mq)
298    {
299      ECHO_FAIL (ECHO_FAIL_VL_API_NULL_APP_MQ, "NULL app_mq");
300      return;
301    }
302  em->app_mq = uword_to_pointer (mp->app_mq, svm_msg_q_t *);
303  em->ctrl_mq = uword_to_pointer (mp->vpp_ctrl_mq, svm_msg_q_t *);
304
305  if (mp->n_fds)
306    {
307      vec_validate (fds, mp->n_fds);
308      if (vl_socket_client_recv_fd_msg (fds, mp->n_fds, 5))
309	{
310	  ECHO_FAIL (ECHO_FAIL_VL_API_RECV_FD_MSG,
311		     "vl_socket_client_recv_fd_msg failed");
312	  goto failed;
313	}
314
315      if (mp->fd_flags & SESSION_FD_F_VPP_MQ_SEGMENT)
316	if (ssvm_segment_attach (0, SSVM_SEGMENT_MEMFD, fds[n_fds++]))
317	  {
318	    ECHO_FAIL (ECHO_FAIL_VL_API_SVM_FIFO_SEG_ATTACH,
319		       "svm_fifo_segment_attach failed on SSVM_SEGMENT_MEMFD");
320	    goto failed;
321	  }
322
323      if (mp->fd_flags & SESSION_FD_F_MEMFD_SEGMENT)
324	if (ssvm_segment_attach ((char *) mp->segment_name,
325				 SSVM_SEGMENT_MEMFD, fds[n_fds++]))
326	  {
327	    ECHO_FAIL (ECHO_FAIL_VL_API_SVM_FIFO_SEG_ATTACH,
328		       "svm_fifo_segment_attach ('%s') "
329		       "failed on SSVM_SEGMENT_MEMFD", mp->segment_name);
330	    goto failed;
331	  }
332      if (mp->fd_flags & SESSION_FD_F_MQ_EVENTFD)
333	svm_msg_q_set_consumer_eventfd (em->app_mq, fds[n_fds++]);
334
335      vec_free (fds);
336    }
337  else
338    {
339      if (ssvm_segment_attach ((char *) mp->segment_name, SSVM_SEGMENT_SHM,
340			       -1))
341	{
342	  ECHO_FAIL (ECHO_FAIL_VL_API_SVM_FIFO_SEG_ATTACH,
343		     "svm_fifo_segment_attach ('%s') "
344		     "failed on SSVM_SEGMENT_SHM", mp->segment_name);
345	  return;
346	}
347    }
348  echo_segment_handle_add_del (em, segment_handle, 1 /* add */ );
349  ECHO_LOG (2, "Mapped segment 0x%lx", segment_handle);
350
351  em->state = STATE_ATTACHED_NO_CERT;
352  return;
353failed:
354  for (i = clib_max (n_fds - 1, 0); i < vec_len (fds); i++)
355    close (fds[i]);
356  vec_free (fds);
357}
358
359static void
360vl_api_application_detach_reply_t_handler (vl_api_application_detach_reply_t *
361					   mp)
362{
363  if (mp->retval)
364    {
365      ECHO_FAIL (ECHO_FAIL_VL_API_DETACH_REPLY,
366		 "app detach returned with err: %d", mp->retval);
367      return;
368    }
369  echo_main.state = STATE_DETACHED;
370}
371
372static void
373vl_api_unmap_segment_t_handler (vl_api_unmap_segment_t * mp)
374{
375  echo_main_t *em = &echo_main;
376  u64 segment_handle = clib_net_to_host_u64 (mp->segment_handle);
377  echo_segment_handle_add_del (em, segment_handle, 0 /* add */ );
378  ECHO_LOG (2, "Unmaped segment 0x%lx", segment_handle);
379}
380
381static void
382vl_api_map_another_segment_t_handler (vl_api_map_another_segment_t * mp)
383{
384  fifo_segment_main_t *sm = &echo_main.segment_main;
385  fifo_segment_create_args_t _a, *a = &_a;
386  echo_main_t *em = &echo_main;
387  int *fds = 0, i;
388  char *seg_name = (char *) mp->segment_name;
389  u64 segment_handle = clib_net_to_host_u64 (mp->segment_handle);
390
391  if (mp->fd_flags & SESSION_FD_F_MEMFD_SEGMENT)
392    {
393      vec_validate (fds, 1);
394      if (vl_socket_client_recv_fd_msg (fds, 1, 5))
395	{
396	  ECHO_FAIL (ECHO_FAIL_VL_API_RECV_FD_MSG,
397		     "vl_socket_client_recv_fd_msg failed");
398	  goto failed;
399	}
400
401      if (ssvm_segment_attach (seg_name, SSVM_SEGMENT_MEMFD, fds[0]))
402	{
403	  ECHO_FAIL (ECHO_FAIL_VL_API_SVM_FIFO_SEG_ATTACH,
404		     "svm_fifo_segment_attach ('%s') "
405		     "failed on SSVM_SEGMENT_MEMFD", seg_name);
406	  goto failed;
407	}
408      vec_free (fds);
409    }
410  else
411    {
412      clib_memset (a, 0, sizeof (*a));
413      a->segment_name = seg_name;
414      a->segment_size = mp->segment_size;
415      /* Attach to the segment vpp created */
416      if (fifo_segment_attach (sm, a))
417	{
418	  ECHO_FAIL (ECHO_FAIL_VL_API_FIFO_SEG_ATTACH,
419		     "fifo_segment_attach ('%s') failed", seg_name);
420	  goto failed;
421	}
422    }
423  echo_segment_handle_add_del (em, segment_handle, 1 /* add */ );
424  ECHO_LOG (2, "Mapped segment 0x%lx", segment_handle);
425  return;
426
427failed:
428  for (i = 0; i < vec_len (fds); i++)
429    close (fds[i]);
430  vec_free (fds);
431}
432
433#define foreach_quic_echo_msg                                    \
434_(APP_ATTACH_REPLY, app_attach_reply)                            \
435_(APPLICATION_DETACH_REPLY, application_detach_reply)            \
436_(MAP_ANOTHER_SEGMENT, map_another_segment)                      \
437_(APP_ADD_CERT_KEY_PAIR_REPLY, app_add_cert_key_pair_reply)      \
438_(APP_DEL_CERT_KEY_PAIR_REPLY, app_del_cert_key_pair_reply)      \
439_(UNMAP_SEGMENT, unmap_segment)
440
441void
442echo_api_hookup (echo_main_t * em)
443{
444#define _(N,n)                                                  \
445    vl_msg_api_set_handlers(VL_API_##N, #n,                     \
446                           vl_api_##n##_t_handler,              \
447                           vl_noop_handler,                     \
448                           vl_api_##n##_t_endian,               \
449                           vl_api_##n##_t_print,                \
450                           sizeof(vl_api_##n##_t), 1);
451  foreach_quic_echo_msg;
452#undef _
453}
454
455/*
456 * fd.io coding-style-patch-verification: ON
457 *
458 * Local Variables:
459 * eval: (c-set-style "gnu")
460 * End:
461 */
462