hsa: make vpp_echo use mq instead of bapi
[vpp.git] / src / plugins / hs_apps / sapi / vpp_echo_bapi.c
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
27 void
28 echo_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
56 void
57 echo_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
70 void
71 echo_send_add_crypto_ctx (echo_main_t * em)
72 {
73   vl_api_application_tls_cert_add_t *cert_mp;
74   vl_api_application_tls_key_add_t *key_mp;
75
76   cert_mp = vl_msg_api_alloc (sizeof (*cert_mp) + test_srv_crt_rsa_len);
77   clib_memset (cert_mp, 0, sizeof (*cert_mp));
78   cert_mp->_vl_msg_id = ntohs (VL_API_APPLICATION_TLS_CERT_ADD);
79   cert_mp->client_index = em->my_client_index;
80   cert_mp->context = ntohl (0xfeedface);
81   cert_mp->cert_len = clib_host_to_net_u16 (test_srv_crt_rsa_len);
82   clib_memcpy_fast (cert_mp->cert, test_srv_crt_rsa, test_srv_crt_rsa_len);
83   vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & cert_mp);
84
85   key_mp = vl_msg_api_alloc (sizeof (*key_mp) + test_srv_key_rsa_len);
86   clib_memset (key_mp, 0, sizeof (*key_mp) + test_srv_key_rsa_len);
87   key_mp->_vl_msg_id = ntohs (VL_API_APPLICATION_TLS_KEY_ADD);
88   key_mp->client_index = em->my_client_index;
89   key_mp->context = ntohl (0xfeedface);
90   key_mp->key_len = clib_host_to_net_u16 (test_srv_key_rsa_len);
91   clib_memcpy_fast (key_mp->key, test_srv_key_rsa, test_srv_key_rsa_len);
92   vl_msg_api_send_shmem (em->vl_input_queue, (u8 *) & key_mp);
93 }
94
95 void
96 echo_send_listen (echo_main_t * em)
97 {
98   app_session_evt_t _app_evt, *app_evt = &_app_evt;
99   session_listen_msg_t *mp;
100   svm_msg_q_t *mq = em->ctrl_mq;
101
102   app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_LISTEN);
103   mp = (session_listen_msg_t *) app_evt->evt->data;
104   memset (mp, 0, sizeof (*mp));
105   mp->client_index = em->my_client_index;
106   mp->context = ntohl (0xfeedface);
107   mp->wrk_index = 0;
108   mp->is_ip4 = em->uri_elts.is_ip4;
109   clib_memcpy_fast (&mp->ip, &em->uri_elts.ip, sizeof (mp->ip));
110   mp->port = em->uri_elts.port;
111   mp->proto = em->uri_elts.transport_proto;
112   app_send_ctrl_evt_to_vpp (mq, app_evt);
113 }
114
115 void
116 echo_send_unbind (echo_main_t * em, echo_session_t * s)
117 {
118   app_session_evt_t _app_evt, *app_evt = &_app_evt;
119   session_unlisten_msg_t *mp;
120   svm_msg_q_t *mq = em->ctrl_mq;
121
122   app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_UNLISTEN);
123   mp = (session_unlisten_msg_t *) app_evt->evt->data;
124   memset (mp, 0, sizeof (*mp));
125   mp->client_index = em->my_client_index;
126   mp->wrk_index = 0;
127   mp->handle = s->vpp_session_handle;
128   mp->context = 0;
129   app_send_ctrl_evt_to_vpp (mq, app_evt);
130 }
131
132 void
133 echo_send_connect (u64 parent_session_handle, u32 opaque)
134 {
135   echo_main_t *em = &echo_main;
136   app_session_evt_t _app_evt, *app_evt = &_app_evt;
137   session_connect_msg_t *mp;
138   svm_msg_q_t *mq = em->ctrl_mq;
139
140   app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_CONNECT);
141   mp = (session_connect_msg_t *) app_evt->evt->data;
142   memset (mp, 0, sizeof (*mp));
143   mp->client_index = em->my_client_index;
144   mp->context = ntohl (opaque);
145   mp->wrk_index = 0;
146   mp->is_ip4 = em->uri_elts.is_ip4;
147   clib_memcpy_fast (&mp->ip, &em->uri_elts.ip, sizeof (mp->ip));
148   mp->port = em->uri_elts.port;
149   mp->proto = em->uri_elts.transport_proto;
150   mp->parent_handle = parent_session_handle;
151   app_send_ctrl_evt_to_vpp (mq, app_evt);
152 }
153
154 void
155 echo_send_disconnect_session (u64 handle, u32 opaque)
156 {
157   echo_main_t *em = &echo_main;
158   echo_session_t *s;
159   app_session_evt_t _app_evt, *app_evt = &_app_evt;
160   session_disconnect_msg_t *mp;
161   svm_msg_q_t *mq = em->ctrl_mq;
162
163   app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_DISCONNECT);
164   mp = (session_disconnect_msg_t *) app_evt->evt->data;
165   memset (mp, 0, sizeof (*mp));
166   mp->client_index = em->my_client_index;
167   mp->handle = handle;
168   app_send_ctrl_evt_to_vpp (mq, app_evt);
169
170   if (!(s = echo_get_session_from_handle (em, mp->handle)))
171     return;
172   em->proto_cb_vft->sent_disconnect_cb (s);
173 }
174
175 /*
176  *
177  *  Helpers
178  *
179  */
180
181 static int
182 ssvm_segment_attach (char *name, ssvm_segment_type_t type, int fd)
183 {
184   fifo_segment_create_args_t _a, *a = &_a;
185   fifo_segment_main_t *sm = &echo_main.segment_main;
186   int rv;
187
188   clib_memset (a, 0, sizeof (*a));
189   a->segment_name = (char *) name;
190   a->segment_type = type;
191
192   if (type == SSVM_SEGMENT_MEMFD)
193     a->memfd_fd = fd;
194
195   if ((rv = fifo_segment_attach (sm, a)))
196     return rv;
197   vec_reset_length (a->new_segment_indices);
198   return 0;
199 }
200
201 static inline void
202 echo_segment_handle_add_del (echo_main_t * em, u64 segment_handle, u8 add)
203 {
204   clib_spinlock_lock (&em->segment_handles_lock);
205   if (add)
206     hash_set (em->shared_segment_handles, segment_handle, 1);
207   else
208     hash_unset (em->shared_segment_handles, segment_handle);
209   clib_spinlock_unlock (&em->segment_handles_lock);
210 }
211
212 /*
213  *
214  *  Binary API callbacks
215  *
216  */
217
218 static void
219   vl_api_application_tls_cert_add_reply_t_handler
220   (vl_api_application_tls_cert_add_reply_t * mp)
221 {
222   echo_main_t *em = &echo_main;
223   if (mp->retval)
224     {
225       ECHO_FAIL (ECHO_FAIL_VL_API_TLS_CERT_ADD_REPLY,
226                  "tls cert add returned %d",
227                  clib_net_to_host_u32 (mp->retval));
228       return;
229     }
230   /* No concurrency here, only bapi thread writes */
231   if (em->state != STATE_ATTACHED_NO_CERT
232       && em->state != STATE_ATTACHED_ONE_CERT)
233     {
234       ECHO_FAIL (ECHO_FAIL_VL_API_TLS_CERT_ADD_REPLY, "Wrong state");
235       return;
236     }
237   em->state++;
238 }
239
240 static void
241   vl_api_application_tls_key_add_reply_t_handler
242   (vl_api_application_tls_key_add_reply_t * mp)
243 {
244   echo_main_t *em = &echo_main;
245   if (mp->retval)
246     {
247       ECHO_FAIL (ECHO_FAIL_VL_API_TLS_KEY_ADD_REPLY,
248                  "tls key add returned %d",
249                  clib_net_to_host_u32 (mp->retval));
250       return;
251     }
252   /* No concurrency here, only bapi thread writes */
253   if (em->state != STATE_ATTACHED_NO_CERT
254       && em->state != STATE_ATTACHED_ONE_CERT)
255     {
256       ECHO_FAIL (ECHO_FAIL_VL_API_TLS_CERT_ADD_REPLY, "Wrong state");
257       return;
258     }
259   em->state++;
260 }
261
262 static void
263 vl_api_app_attach_reply_t_handler (vl_api_app_attach_reply_t * mp)
264 {
265   echo_main_t *em = &echo_main;
266   int *fds = 0, i;
267   u32 n_fds = 0;
268   u64 segment_handle;
269   segment_handle = clib_net_to_host_u64 (mp->segment_handle);
270   ECHO_LOG (1, "Attached returned app %u", htons (mp->app_index));
271
272   if (mp->retval)
273     {
274       ECHO_FAIL (ECHO_FAIL_VL_API_APP_ATTACH, "attach failed: %U",
275                  format_api_error, clib_net_to_host_u32 (mp->retval));
276       return;
277     }
278
279   if (mp->segment_name_length == 0)
280     {
281       ECHO_FAIL (ECHO_FAIL_VL_API_MISSING_SEGMENT_NAME,
282                  "segment_name_length zero");
283       return;
284     }
285
286   ASSERT (mp->app_mq);
287   em->app_mq = uword_to_pointer (mp->app_mq, svm_msg_q_t *);
288   em->ctrl_mq = uword_to_pointer (mp->vpp_ctrl_mq, svm_msg_q_t *);
289
290   if (mp->n_fds)
291     {
292       vec_validate (fds, mp->n_fds);
293       if (vl_socket_client_recv_fd_msg (fds, mp->n_fds, 5))
294         {
295           ECHO_FAIL (ECHO_FAIL_VL_API_RECV_FD_MSG,
296                      "vl_socket_client_recv_fd_msg failed");
297           goto failed;
298         }
299
300       if (mp->fd_flags & SESSION_FD_F_VPP_MQ_SEGMENT)
301         if (ssvm_segment_attach (0, SSVM_SEGMENT_MEMFD, fds[n_fds++]))
302           {
303             ECHO_FAIL (ECHO_FAIL_VL_API_SVM_FIFO_SEG_ATTACH,
304                        "svm_fifo_segment_attach failed on SSVM_SEGMENT_MEMFD");
305             goto failed;
306           }
307
308       if (mp->fd_flags & SESSION_FD_F_MEMFD_SEGMENT)
309         if (ssvm_segment_attach ((char *) mp->segment_name,
310                                  SSVM_SEGMENT_MEMFD, fds[n_fds++]))
311           {
312             ECHO_FAIL (ECHO_FAIL_VL_API_SVM_FIFO_SEG_ATTACH,
313                        "svm_fifo_segment_attach ('%s') "
314                        "failed on SSVM_SEGMENT_MEMFD", mp->segment_name);
315             goto failed;
316           }
317       if (mp->fd_flags & SESSION_FD_F_MQ_EVENTFD)
318         svm_msg_q_set_consumer_eventfd (em->app_mq, fds[n_fds++]);
319
320       vec_free (fds);
321     }
322   else
323     {
324       if (ssvm_segment_attach ((char *) mp->segment_name, SSVM_SEGMENT_SHM,
325                                -1))
326         {
327           ECHO_FAIL (ECHO_FAIL_VL_API_SVM_FIFO_SEG_ATTACH,
328                      "svm_fifo_segment_attach ('%s') "
329                      "failed on SSVM_SEGMENT_SHM", mp->segment_name);
330           return;
331         }
332     }
333   echo_segment_handle_add_del (em, segment_handle, 1 /* add */ );
334   ECHO_LOG (1, "Mapped segment 0x%lx", segment_handle);
335
336   em->state = STATE_ATTACHED_NO_CERT;
337   return;
338 failed:
339   for (i = clib_max (n_fds - 1, 0); i < vec_len (fds); i++)
340     close (fds[i]);
341   vec_free (fds);
342 }
343
344 static void
345 vl_api_application_detach_reply_t_handler (vl_api_application_detach_reply_t *
346                                            mp)
347 {
348   if (mp->retval)
349     {
350       ECHO_FAIL (ECHO_FAIL_VL_API_DETACH_REPLY,
351                  "app detach returned with err: %d", mp->retval);
352       return;
353     }
354   echo_main.state = STATE_DETACHED;
355 }
356
357 static void
358 vl_api_unmap_segment_t_handler (vl_api_unmap_segment_t * mp)
359 {
360   echo_main_t *em = &echo_main;
361   u64 segment_handle = clib_net_to_host_u64 (mp->segment_handle);
362   echo_segment_handle_add_del (em, segment_handle, 0 /* add */ );
363   ECHO_LOG (1, "Unmaped segment 0x%lx", segment_handle);
364 }
365
366 static void
367 vl_api_map_another_segment_t_handler (vl_api_map_another_segment_t * mp)
368 {
369   fifo_segment_main_t *sm = &echo_main.segment_main;
370   fifo_segment_create_args_t _a, *a = &_a;
371   echo_main_t *em = &echo_main;
372   int *fds = 0, i;
373   char *seg_name = (char *) mp->segment_name;
374   u64 segment_handle = clib_net_to_host_u64 (mp->segment_handle);
375
376   if (mp->fd_flags & SESSION_FD_F_MEMFD_SEGMENT)
377     {
378       vec_validate (fds, 1);
379       if (vl_socket_client_recv_fd_msg (fds, 1, 5))
380         {
381           ECHO_FAIL (ECHO_FAIL_VL_API_RECV_FD_MSG,
382                      "vl_socket_client_recv_fd_msg failed");
383           goto failed;
384         }
385
386       if (ssvm_segment_attach (seg_name, SSVM_SEGMENT_MEMFD, fds[0]))
387         {
388           ECHO_FAIL (ECHO_FAIL_VL_API_SVM_FIFO_SEG_ATTACH,
389                      "svm_fifo_segment_attach ('%s') "
390                      "failed on SSVM_SEGMENT_MEMFD", seg_name);
391           goto failed;
392         }
393       vec_free (fds);
394     }
395   else
396     {
397       clib_memset (a, 0, sizeof (*a));
398       a->segment_name = seg_name;
399       a->segment_size = mp->segment_size;
400       /* Attach to the segment vpp created */
401       if (fifo_segment_attach (sm, a))
402         {
403           ECHO_FAIL (ECHO_FAIL_VL_API_FIFO_SEG_ATTACH,
404                      "fifo_segment_attach ('%s') failed", seg_name);
405           goto failed;
406         }
407     }
408   echo_segment_handle_add_del (em, segment_handle, 1 /* add */ );
409   ECHO_LOG (1, "Mapped segment 0x%lx", segment_handle);
410   return;
411
412 failed:
413   for (i = 0; i < vec_len (fds); i++)
414     close (fds[i]);
415   vec_free (fds);
416 }
417
418 #define foreach_quic_echo_msg                              \
419 _(APP_ATTACH_REPLY, app_attach_reply)                      \
420 _(APPLICATION_DETACH_REPLY, application_detach_reply)      \
421 _(MAP_ANOTHER_SEGMENT, map_another_segment)                \
422 _(APPLICATION_TLS_CERT_ADD_REPLY, application_tls_cert_add_reply)              \
423 _(APPLICATION_TLS_KEY_ADD_REPLY, application_tls_key_add_reply)              \
424 _(UNMAP_SEGMENT, unmap_segment)
425
426 void
427 echo_api_hookup (echo_main_t * em)
428 {
429 #define _(N,n)                                                  \
430     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
431                            vl_api_##n##_t_handler,              \
432                            vl_noop_handler,                     \
433                            vl_api_##n##_t_endian,               \
434                            vl_api_##n##_t_print,                \
435                            sizeof(vl_api_##n##_t), 1);
436   foreach_quic_echo_msg;
437 #undef _
438 }
439
440 /*
441  * fd.io coding-style-patch-verification: ON
442  *
443  * Local Variables:
444  * eval: (c-set-style "gnu")
445  * End:
446  */