hsa: fix vpp_echo session close
[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   if (!mp->app_mq)
287     {
288       ECHO_FAIL (ECHO_FAIL_VL_API_NULL_APP_MQ, "NULL app_mq");
289       return;
290     }
291   em->app_mq = uword_to_pointer (mp->app_mq, svm_msg_q_t *);
292   em->ctrl_mq = uword_to_pointer (mp->vpp_ctrl_mq, svm_msg_q_t *);
293
294   if (mp->n_fds)
295     {
296       vec_validate (fds, mp->n_fds);
297       if (vl_socket_client_recv_fd_msg (fds, mp->n_fds, 5))
298         {
299           ECHO_FAIL (ECHO_FAIL_VL_API_RECV_FD_MSG,
300                      "vl_socket_client_recv_fd_msg failed");
301           goto failed;
302         }
303
304       if (mp->fd_flags & SESSION_FD_F_VPP_MQ_SEGMENT)
305         if (ssvm_segment_attach (0, SSVM_SEGMENT_MEMFD, fds[n_fds++]))
306           {
307             ECHO_FAIL (ECHO_FAIL_VL_API_SVM_FIFO_SEG_ATTACH,
308                        "svm_fifo_segment_attach failed on SSVM_SEGMENT_MEMFD");
309             goto failed;
310           }
311
312       if (mp->fd_flags & SESSION_FD_F_MEMFD_SEGMENT)
313         if (ssvm_segment_attach ((char *) mp->segment_name,
314                                  SSVM_SEGMENT_MEMFD, fds[n_fds++]))
315           {
316             ECHO_FAIL (ECHO_FAIL_VL_API_SVM_FIFO_SEG_ATTACH,
317                        "svm_fifo_segment_attach ('%s') "
318                        "failed on SSVM_SEGMENT_MEMFD", mp->segment_name);
319             goto failed;
320           }
321       if (mp->fd_flags & SESSION_FD_F_MQ_EVENTFD)
322         svm_msg_q_set_consumer_eventfd (em->app_mq, fds[n_fds++]);
323
324       vec_free (fds);
325     }
326   else
327     {
328       if (ssvm_segment_attach ((char *) mp->segment_name, SSVM_SEGMENT_SHM,
329                                -1))
330         {
331           ECHO_FAIL (ECHO_FAIL_VL_API_SVM_FIFO_SEG_ATTACH,
332                      "svm_fifo_segment_attach ('%s') "
333                      "failed on SSVM_SEGMENT_SHM", mp->segment_name);
334           return;
335         }
336     }
337   echo_segment_handle_add_del (em, segment_handle, 1 /* add */ );
338   ECHO_LOG (1, "Mapped segment 0x%lx", segment_handle);
339
340   em->state = STATE_ATTACHED_NO_CERT;
341   return;
342 failed:
343   for (i = clib_max (n_fds - 1, 0); i < vec_len (fds); i++)
344     close (fds[i]);
345   vec_free (fds);
346 }
347
348 static void
349 vl_api_application_detach_reply_t_handler (vl_api_application_detach_reply_t *
350                                            mp)
351 {
352   if (mp->retval)
353     {
354       ECHO_FAIL (ECHO_FAIL_VL_API_DETACH_REPLY,
355                  "app detach returned with err: %d", mp->retval);
356       return;
357     }
358   echo_main.state = STATE_DETACHED;
359 }
360
361 static void
362 vl_api_unmap_segment_t_handler (vl_api_unmap_segment_t * mp)
363 {
364   echo_main_t *em = &echo_main;
365   u64 segment_handle = clib_net_to_host_u64 (mp->segment_handle);
366   echo_segment_handle_add_del (em, segment_handle, 0 /* add */ );
367   ECHO_LOG (1, "Unmaped segment 0x%lx", segment_handle);
368 }
369
370 static void
371 vl_api_map_another_segment_t_handler (vl_api_map_another_segment_t * mp)
372 {
373   fifo_segment_main_t *sm = &echo_main.segment_main;
374   fifo_segment_create_args_t _a, *a = &_a;
375   echo_main_t *em = &echo_main;
376   int *fds = 0, i;
377   char *seg_name = (char *) mp->segment_name;
378   u64 segment_handle = clib_net_to_host_u64 (mp->segment_handle);
379
380   if (mp->fd_flags & SESSION_FD_F_MEMFD_SEGMENT)
381     {
382       vec_validate (fds, 1);
383       if (vl_socket_client_recv_fd_msg (fds, 1, 5))
384         {
385           ECHO_FAIL (ECHO_FAIL_VL_API_RECV_FD_MSG,
386                      "vl_socket_client_recv_fd_msg failed");
387           goto failed;
388         }
389
390       if (ssvm_segment_attach (seg_name, SSVM_SEGMENT_MEMFD, fds[0]))
391         {
392           ECHO_FAIL (ECHO_FAIL_VL_API_SVM_FIFO_SEG_ATTACH,
393                      "svm_fifo_segment_attach ('%s') "
394                      "failed on SSVM_SEGMENT_MEMFD", seg_name);
395           goto failed;
396         }
397       vec_free (fds);
398     }
399   else
400     {
401       clib_memset (a, 0, sizeof (*a));
402       a->segment_name = seg_name;
403       a->segment_size = mp->segment_size;
404       /* Attach to the segment vpp created */
405       if (fifo_segment_attach (sm, a))
406         {
407           ECHO_FAIL (ECHO_FAIL_VL_API_FIFO_SEG_ATTACH,
408                      "fifo_segment_attach ('%s') failed", seg_name);
409           goto failed;
410         }
411     }
412   echo_segment_handle_add_del (em, segment_handle, 1 /* add */ );
413   ECHO_LOG (1, "Mapped segment 0x%lx", segment_handle);
414   return;
415
416 failed:
417   for (i = 0; i < vec_len (fds); i++)
418     close (fds[i]);
419   vec_free (fds);
420 }
421
422 #define foreach_quic_echo_msg                              \
423 _(APP_ATTACH_REPLY, app_attach_reply)                      \
424 _(APPLICATION_DETACH_REPLY, application_detach_reply)      \
425 _(MAP_ANOTHER_SEGMENT, map_another_segment)                \
426 _(APPLICATION_TLS_CERT_ADD_REPLY, application_tls_cert_add_reply)              \
427 _(APPLICATION_TLS_KEY_ADD_REPLY, application_tls_key_add_reply)              \
428 _(UNMAP_SEGMENT, unmap_segment)
429
430 void
431 echo_api_hookup (echo_main_t * em)
432 {
433 #define _(N,n)                                                  \
434     vl_msg_api_set_handlers(VL_API_##N, #n,                     \
435                            vl_api_##n##_t_handler,              \
436                            vl_noop_handler,                     \
437                            vl_api_##n##_t_endian,               \
438                            vl_api_##n##_t_print,                \
439                            sizeof(vl_api_##n##_t), 1);
440   foreach_quic_echo_msg;
441 #undef _
442 }
443
444 /*
445  * fd.io coding-style-patch-verification: ON
446  *
447  * Local Variables:
448  * eval: (c-set-style "gnu")
449  * End:
450  */