2 * Copyright (c) 2015-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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 #include <vnet/vnet.h>
17 #include <vlibmemory/api.h>
18 #include <vnet/session/application.h>
19 #include <vnet/session/application_interface.h>
20 #include <vnet/session/application_local.h>
21 #include <vnet/session/session_rules_table.h>
22 #include <vnet/session/session_table.h>
23 #include <vnet/session/session.h>
25 #include <vnet/ip/ip_types_api.h>
27 #include <vnet/vnet_msg_enum.h>
29 #define vl_typedefs /* define message structures */
30 #include <vnet/vnet_all_api_h.h>
33 #define vl_endianfun /* define message structures */
34 #include <vnet/vnet_all_api_h.h>
37 /* instantiate all the print functions we know about */
38 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
40 #include <vnet/vnet_all_api_h.h>
43 #include <vlibapi/api_helper_macros.h>
45 #define foreach_session_api_msg \
46 _(APP_ATTACH, app_attach) \
47 _(APPLICATION_DETACH, application_detach) \
48 _(SESSION_ENABLE_DISABLE, session_enable_disable) \
49 _(APP_NAMESPACE_ADD_DEL, app_namespace_add_del) \
50 _(SESSION_RULE_ADD_DEL, session_rule_add_del) \
51 _(SESSION_RULES_DUMP, session_rules_dump) \
52 _(APP_ADD_CERT_KEY_PAIR, app_add_cert_key_pair) \
53 _(APP_DEL_CERT_KEY_PAIR, app_del_cert_key_pair) \
54 _(APP_WORKER_ADD_DEL, app_worker_add_del) \
56 static transport_proto_t
57 api_session_transport_proto_decode (const vl_api_transport_proto_t * api_tp)
61 case TRANSPORT_PROTO_API_TCP:
62 return TRANSPORT_PROTO_TCP;
63 case TRANSPORT_PROTO_API_UDP:
64 return TRANSPORT_PROTO_UDP;
65 case TRANSPORT_PROTO_API_TLS:
66 return TRANSPORT_PROTO_TLS;
67 case TRANSPORT_PROTO_API_QUIC:
68 return TRANSPORT_PROTO_QUIC;
70 return TRANSPORT_PROTO_NONE;
74 static vl_api_transport_proto_t
75 api_session_transport_proto_encode (const transport_proto_t tp)
79 case TRANSPORT_PROTO_TCP:
80 return TRANSPORT_PROTO_API_TCP;
81 case TRANSPORT_PROTO_UDP:
82 return TRANSPORT_PROTO_API_UDP;
83 case TRANSPORT_PROTO_TLS:
84 return TRANSPORT_PROTO_API_TLS;
85 case TRANSPORT_PROTO_QUIC:
86 return TRANSPORT_PROTO_API_QUIC;
88 return TRANSPORT_PROTO_API_NONE;
93 session_send_fds (vl_api_registration_t * reg, int fds[], int n_fds)
96 if (vl_api_registration_file_index (reg) == VL_API_INVALID_FI)
97 return SESSION_E_BAPI_NO_FD;
98 error = vl_api_send_fd_msg (reg, fds, n_fds);
101 clib_error_report (error);
102 return SESSION_E_BAPI_SEND_FD;
108 mq_try_lock_and_alloc_msg (svm_msg_q_t * app_mq, svm_msg_q_msg_t * msg)
114 rv = svm_msg_q_lock_and_alloc_msg_w_ring (app_mq,
115 SESSION_MQ_CTRL_EVT_RING,
122 clib_warning ("failed to alloc msg");
127 mq_send_session_accepted_cb (session_t * s)
129 app_worker_t *app_wrk = app_worker_get (s->app_wrk_index);
130 svm_msg_q_msg_t _msg, *msg = &_msg;
131 session_accepted_msg_t m = { 0 };
133 fifo_segment_t *eq_seg;
135 session_event_t *evt;
138 app = application_get (app_wrk->app_index);
140 m.context = app->app_index;
141 m.server_rx_fifo = fifo_segment_fifo_offset (s->rx_fifo);
142 m.server_tx_fifo = fifo_segment_fifo_offset (s->tx_fifo);
143 m.segment_handle = session_segment_handle (s);
146 eq_seg = application_get_rx_mqs_segment (app);
148 if (session_has_transport (s))
150 listener = listen_session_get_from_handle (s->listener_handle);
151 m.listener_handle = app_listen_session_handle (listener);
152 if (application_is_proxy (app))
155 app_worker_first_listener (app_wrk, session_get_fib_proto (s),
156 session_get_transport_proto (s));
158 m.listener_handle = listen_session_get_handle (listener);
160 m.vpp_event_queue_address =
161 fifo_segment_msg_q_offset (eq_seg, s->thread_index);
162 m.mq_index = s->thread_index;
163 m.handle = session_handle (s);
165 session_get_endpoint (s, &m.rmt, 0 /* is_lcl */);
166 session_get_endpoint (s, &m.lcl, 1 /* is_lcl */);
172 ct = (ct_connection_t *) session_get_transport (s);
173 listener = listen_session_get_from_handle (s->listener_handle);
174 m.listener_handle = app_listen_session_handle (listener);
175 m.rmt.is_ip4 = session_type_is_ip4 (listener->session_type);
176 m.rmt.port = ct->c_rmt_port;
177 m.lcl.port = ct->c_lcl_port;
178 m.handle = session_handle (s);
179 m.vpp_event_queue_address =
180 fifo_segment_msg_q_offset (eq_seg, s->thread_index);
181 m.mq_index = s->thread_index;
184 app_mq = app_wrk->event_queue;
185 if (mq_try_lock_and_alloc_msg (app_mq, msg))
186 return SESSION_E_MQ_MSG_ALLOC;
188 evt = svm_msg_q_msg_data (app_mq, msg);
189 clib_memset (evt, 0, sizeof (*evt));
190 evt->event_type = SESSION_CTRL_EVT_ACCEPTED;
191 clib_memcpy_fast (evt->data, &m, sizeof (m));
192 svm_msg_q_add_and_unlock (app_mq, msg);
198 mq_send_session_close_evt (app_worker_t * app_wrk, session_handle_t sh,
199 session_evt_type_t evt_type)
201 svm_msg_q_msg_t _msg, *msg = &_msg;
202 session_disconnected_msg_t *mp;
204 session_event_t *evt;
206 app_mq = app_wrk->event_queue;
207 if (mq_try_lock_and_alloc_msg (app_mq, msg))
209 evt = svm_msg_q_msg_data (app_mq, msg);
210 clib_memset (evt, 0, sizeof (*evt));
211 evt->event_type = evt_type;
212 mp = (session_disconnected_msg_t *) evt->data;
214 mp->context = app_wrk->api_client_index;
215 svm_msg_q_add_and_unlock (app_mq, msg);
219 mq_notify_close_subscribers (u32 app_index, session_handle_t sh,
220 svm_fifo_t * f, session_evt_type_t evt_type)
222 app_worker_t *app_wrk;
226 app = application_get (app_index);
230 for (i = 0; i < f->shr->n_subscribers; i++)
232 if (!(app_wrk = application_get_worker (app, f->shr->subscribers[i])))
234 mq_send_session_close_evt (app_wrk, sh, SESSION_CTRL_EVT_DISCONNECTED);
239 mq_send_session_disconnected_cb (session_t * s)
241 app_worker_t *app_wrk = app_worker_get (s->app_wrk_index);
242 session_handle_t sh = session_handle (s);
244 mq_send_session_close_evt (app_wrk, session_handle (s),
245 SESSION_CTRL_EVT_DISCONNECTED);
247 if (svm_fifo_n_subscribers (s->rx_fifo))
248 mq_notify_close_subscribers (app_wrk->app_index, sh, s->rx_fifo,
249 SESSION_CTRL_EVT_DISCONNECTED);
253 mq_send_session_reset_cb (session_t * s)
255 app_worker_t *app_wrk = app_worker_get (s->app_wrk_index);
256 session_handle_t sh = session_handle (s);
258 mq_send_session_close_evt (app_wrk, sh, SESSION_CTRL_EVT_RESET);
260 if (svm_fifo_n_subscribers (s->rx_fifo))
261 mq_notify_close_subscribers (app_wrk->app_index, sh, s->rx_fifo,
262 SESSION_CTRL_EVT_RESET);
266 mq_send_session_connected_cb (u32 app_wrk_index, u32 api_context,
267 session_t * s, session_error_t err)
269 svm_msg_q_msg_t _msg, *msg = &_msg;
270 session_connected_msg_t m = { 0 };
272 transport_connection_t *tc;
273 fifo_segment_t *eq_seg;
274 app_worker_t *app_wrk;
275 session_event_t *evt;
278 app_wrk = app_worker_get (app_wrk_index);
280 m.context = api_context;
286 app = application_get (app_wrk->app_index);
287 eq_seg = application_get_rx_mqs_segment (app);
289 if (session_has_transport (s))
291 tc = session_get_transport (s);
294 clib_warning ("failed to retrieve transport!");
295 m.retval = SESSION_E_REFUSED;
299 m.handle = session_handle (s);
300 m.vpp_event_queue_address =
301 fifo_segment_msg_q_offset (eq_seg, s->thread_index);
303 session_get_endpoint (s, &m.lcl, 1 /* is_lcl */);
305 m.server_rx_fifo = fifo_segment_fifo_offset (s->rx_fifo);
306 m.server_tx_fifo = fifo_segment_fifo_offset (s->tx_fifo);
307 m.segment_handle = session_segment_handle (s);
311 ct_connection_t *cct;
314 cct = (ct_connection_t *) session_get_transport (s);
315 m.handle = session_handle (s);
316 m.lcl.port = cct->c_lcl_port;
317 m.lcl.is_ip4 = cct->c_is_ip4;
318 m.vpp_event_queue_address =
319 fifo_segment_msg_q_offset (eq_seg, s->thread_index);
320 m.server_rx_fifo = fifo_segment_fifo_offset (s->rx_fifo);
321 m.server_tx_fifo = fifo_segment_fifo_offset (s->tx_fifo);
322 m.segment_handle = session_segment_handle (s);
323 ss = ct_session_get_peer (s);
324 m.ct_rx_fifo = fifo_segment_fifo_offset (ss->tx_fifo);
325 m.ct_tx_fifo = fifo_segment_fifo_offset (ss->rx_fifo);
326 m.ct_segment_handle = session_segment_handle (ss);
329 /* Setup client session index in advance, in case data arrives
330 * before the app processes message and updates it */
331 s->rx_fifo->shr->client_session_index = api_context;
332 s->tx_fifo->shr->client_session_index = api_context;
336 app_mq = app_wrk->event_queue;
338 if (mq_try_lock_and_alloc_msg (app_mq, msg))
339 return SESSION_E_MQ_MSG_ALLOC;
341 evt = svm_msg_q_msg_data (app_mq, msg);
342 clib_memset (evt, 0, sizeof (*evt));
343 evt->event_type = SESSION_CTRL_EVT_CONNECTED;
344 clib_memcpy_fast (evt->data, &m, sizeof (m));
346 svm_msg_q_add_and_unlock (app_mq, msg);
351 mq_send_session_bound_cb (u32 app_wrk_index, u32 api_context,
352 session_handle_t handle, int rv)
354 svm_msg_q_msg_t _msg, *msg = &_msg;
355 session_bound_msg_t m = { 0 };
357 transport_endpoint_t tep;
358 fifo_segment_t *eq_seg;
359 app_worker_t *app_wrk;
360 session_event_t *evt;
365 app_wrk = app_worker_get (app_wrk_index);
367 m.context = api_context;
374 al = app_listener_get_w_handle (handle);
375 if (al->session_index != SESSION_INVALID_INDEX)
376 ls = app_listener_get_session (al);
378 ls = app_listener_get_local_session (al);
380 session_get_endpoint (ls, &tep, 1 /* is_lcl */);
381 m.lcl_port = tep.port;
382 m.lcl_is_ip4 = tep.is_ip4;
383 clib_memcpy_fast (m.lcl_ip, &tep.ip, sizeof (tep.ip));
384 app = application_get (app_wrk->app_index);
385 eq_seg = application_get_rx_mqs_segment (app);
386 m.vpp_evt_q = fifo_segment_msg_q_offset (eq_seg, ls->thread_index);
388 if (session_transport_service_type (ls) == TRANSPORT_SERVICE_CL &&
391 m.rx_fifo = fifo_segment_fifo_offset (ls->rx_fifo);
392 m.tx_fifo = fifo_segment_fifo_offset (ls->tx_fifo);
393 m.segment_handle = session_segment_handle (ls);
398 app_mq = app_wrk->event_queue;
400 if (mq_try_lock_and_alloc_msg (app_mq, msg))
401 return SESSION_E_MQ_MSG_ALLOC;
403 evt = svm_msg_q_msg_data (app_mq, msg);
404 clib_memset (evt, 0, sizeof (*evt));
405 evt->event_type = SESSION_CTRL_EVT_BOUND;
406 clib_memcpy_fast (evt->data, &m, sizeof (m));
408 svm_msg_q_add_and_unlock (app_mq, msg);
413 mq_send_unlisten_reply (app_worker_t * app_wrk, session_handle_t sh,
416 svm_msg_q_msg_t _msg, *msg = &_msg;
417 session_unlisten_reply_msg_t *ump;
419 session_event_t *evt;
421 app_mq = app_wrk->event_queue;
422 if (mq_try_lock_and_alloc_msg (app_mq, msg))
425 evt = svm_msg_q_msg_data (app_mq, msg);
426 clib_memset (evt, 0, sizeof (*evt));
427 evt->event_type = SESSION_CTRL_EVT_UNLISTEN_REPLY;
428 ump = (session_unlisten_reply_msg_t *) evt->data;
429 ump->context = context;
432 svm_msg_q_add_and_unlock (app_mq, msg);
436 mq_send_session_migrate_cb (session_t * s, session_handle_t new_sh)
438 svm_msg_q_msg_t _msg, *msg = &_msg;
439 session_migrated_msg_t m = { 0 };
440 fifo_segment_t *eq_seg;
441 app_worker_t *app_wrk;
442 session_event_t *evt;
447 thread_index = session_thread_from_handle (new_sh);
448 app_wrk = app_worker_get (s->app_wrk_index);
449 app_mq = app_wrk->event_queue;
450 app = application_get (app_wrk->app_index);
451 eq_seg = application_get_rx_mqs_segment (app);
453 m.handle = session_handle (s);
454 m.new_handle = new_sh;
455 m.vpp_thread_index = thread_index;
456 m.vpp_evt_q = fifo_segment_msg_q_offset (eq_seg, thread_index);
457 m.segment_handle = SESSION_INVALID_HANDLE;
459 if (mq_try_lock_and_alloc_msg (app_mq, msg))
462 evt = svm_msg_q_msg_data (app_mq, msg);
463 clib_memset (evt, 0, sizeof (*evt));
464 evt->event_type = SESSION_CTRL_EVT_MIGRATED;
465 clib_memcpy_fast (evt->data, &m, sizeof (m));
467 svm_msg_q_add_and_unlock (app_mq, msg);
471 mq_send_add_segment_cb (u32 app_wrk_index, u64 segment_handle)
473 int fds[SESSION_N_FD_TYPE], n_fds = 0;
474 svm_msg_q_msg_t _msg, *msg = &_msg;
475 session_app_add_segment_msg_t *mp;
476 vl_api_registration_t *reg;
477 app_worker_t *app_wrk;
478 session_event_t *evt;
484 app_wrk = app_worker_get (app_wrk_index);
486 reg = vl_mem_api_client_index_to_registration (app_wrk->api_client_index);
489 clib_warning ("no api registration for client: %u",
490 app_wrk->api_client_index);
494 fs = segment_manager_get_segment_w_handle (segment_handle);
496 if (ssvm_type (sp) == SSVM_SEGMENT_MEMFD)
498 if (vl_api_registration_file_index (reg) == VL_API_INVALID_FI)
500 clib_warning ("can't send memfd fd");
504 fd_flags |= SESSION_FD_F_MEMFD_SEGMENT;
509 app_mq = app_wrk->event_queue;
510 if (mq_try_lock_and_alloc_msg (app_mq, msg))
514 session_send_fds (reg, fds, n_fds);
516 evt = svm_msg_q_msg_data (app_mq, msg);
517 clib_memset (evt, 0, sizeof (*evt));
518 evt->event_type = SESSION_CTRL_EVT_APP_ADD_SEGMENT;
519 mp = (session_app_add_segment_msg_t *) evt->data;
520 clib_memset (mp, 0, sizeof (*mp));
521 mp->segment_size = sp->ssvm_size;
522 mp->fd_flags = fd_flags;
523 mp->segment_handle = segment_handle;
524 strncpy ((char *) mp->segment_name, (char *) sp->name,
525 sizeof (mp->segment_name) - 1);
527 svm_msg_q_add_and_unlock (app_mq, msg);
533 mq_send_del_segment_cb (u32 app_wrk_index, u64 segment_handle)
535 svm_msg_q_msg_t _msg, *msg = &_msg;
536 session_app_del_segment_msg_t *mp;
537 vl_api_registration_t *reg;
538 app_worker_t *app_wrk;
539 session_event_t *evt;
542 app_wrk = app_worker_get (app_wrk_index);
543 reg = vl_mem_api_client_index_to_registration (app_wrk->api_client_index);
546 clib_warning ("no registration: %u", app_wrk->api_client_index);
550 app_mq = app_wrk->event_queue;
551 if (mq_try_lock_and_alloc_msg (app_mq, msg))
554 evt = svm_msg_q_msg_data (app_mq, msg);
555 clib_memset (evt, 0, sizeof (*evt));
556 evt->event_type = SESSION_CTRL_EVT_APP_DEL_SEGMENT;
557 mp = (session_app_del_segment_msg_t *) evt->data;
558 clib_memset (mp, 0, sizeof (*mp));
559 mp->segment_handle = segment_handle;
560 svm_msg_q_add_and_unlock (app_mq, msg);
566 mq_send_session_cleanup_cb (session_t * s, session_cleanup_ntf_t ntf)
568 svm_msg_q_msg_t _msg, *msg = &_msg;
569 session_cleanup_msg_t *mp;
571 session_event_t *evt;
572 app_worker_t *app_wrk;
574 /* Propagate transport cleanup notifications only if app didn't close */
575 if (ntf == SESSION_CLEANUP_TRANSPORT
576 && s->session_state != SESSION_STATE_TRANSPORT_DELETED)
579 app_wrk = app_worker_get_if_valid (s->app_wrk_index);
583 app_mq = app_wrk->event_queue;
584 if (mq_try_lock_and_alloc_msg (app_mq, msg))
587 evt = svm_msg_q_msg_data (app_mq, msg);
588 clib_memset (evt, 0, sizeof (*evt));
589 evt->event_type = SESSION_CTRL_EVT_CLEANUP;
590 mp = (session_cleanup_msg_t *) evt->data;
591 mp->handle = session_handle (s);
593 svm_msg_q_add_and_unlock (app_mq, msg);
596 static session_cb_vft_t session_mq_cb_vft = {
597 .session_accept_callback = mq_send_session_accepted_cb,
598 .session_disconnect_callback = mq_send_session_disconnected_cb,
599 .session_connected_callback = mq_send_session_connected_cb,
600 .session_reset_callback = mq_send_session_reset_cb,
601 .session_migrate_callback = mq_send_session_migrate_cb,
602 .session_cleanup_callback = mq_send_session_cleanup_cb,
603 .add_segment_callback = mq_send_add_segment_cb,
604 .del_segment_callback = mq_send_del_segment_cb,
608 vl_api_session_enable_disable_t_handler (vl_api_session_enable_disable_t * mp)
610 vl_api_session_enable_disable_reply_t *rmp;
611 vlib_main_t *vm = vlib_get_main ();
614 vnet_session_enable_disable (vm, mp->is_enable);
615 REPLY_MACRO (VL_API_SESSION_ENABLE_DISABLE_REPLY);
619 vl_api_app_attach_t_handler (vl_api_app_attach_t * mp)
621 int rv = 0, *fds = 0, n_fds = 0, n_workers, i;
622 fifo_segment_t *segp, *rx_mqs_seg = 0;
623 vnet_app_attach_args_t _a, *a = &_a;
624 vl_api_app_attach_reply_t *rmp;
625 u8 fd_flags = 0, ctrl_thread;
626 vl_api_registration_t *reg;
630 reg = vl_api_client_index_to_registration (mp->client_index);
634 n_workers = vlib_num_workers ();
635 if (!session_main_is_enabled () || appns_sapi_enabled ())
637 rv = VNET_API_ERROR_FEATURE_DISABLED;
640 /* Only support binary api with socket transport */
641 if (vl_api_registration_file_index (reg) == VL_API_INVALID_FI)
643 rv = VNET_API_ERROR_APP_UNSUPPORTED_CFG;
647 STATIC_ASSERT (sizeof (u64) * APP_OPTIONS_N_OPTIONS <=
648 sizeof (mp->options),
649 "Out of options, fix api message definition");
651 clib_memset (a, 0, sizeof (*a));
652 a->api_client_index = mp->client_index;
653 a->options = mp->options;
654 a->session_cb_vft = &session_mq_cb_vft;
655 a->namespace_id = vl_api_from_api_to_new_vec (mp, &mp->namespace_id);
657 if ((rv = vnet_application_attach (a)))
659 clib_warning ("attach returned: %d", rv);
660 vec_free (a->namespace_id);
663 vec_free (a->namespace_id);
665 vec_validate (fds, 3 /* segs + tx evtfd */ + n_workers);
667 /* Send rx mqs segment */
668 app = application_get (a->app_index);
669 rx_mqs_seg = application_get_rx_mqs_segment (app);
671 fd_flags |= SESSION_FD_F_VPP_MQ_SEGMENT;
672 fds[n_fds] = rx_mqs_seg->ssvm.fd;
675 /* Send fifo segment fd if needed */
676 if (ssvm_type (a->segment) == SSVM_SEGMENT_MEMFD)
678 fd_flags |= SESSION_FD_F_MEMFD_SEGMENT;
679 fds[n_fds] = a->segment->fd;
682 if (a->options[APP_OPTIONS_FLAGS] & APP_OPTIONS_FLAGS_EVT_MQ_USE_EVENTFD)
684 fd_flags |= SESSION_FD_F_MQ_EVENTFD;
685 fds[n_fds] = svm_msg_q_get_eventfd (a->app_evt_q);
689 if (application_use_private_rx_mqs ())
691 fd_flags |= SESSION_FD_F_VPP_MQ_EVENTFD;
692 for (i = 0; i < n_workers + 1; i++)
694 rx_mq = application_rx_mq_get (app, i);
695 fds[n_fds] = svm_msg_q_get_eventfd (rx_mq);
702 REPLY_MACRO2 (VL_API_APP_ATTACH_REPLY, ({
705 ctrl_thread = n_workers ? 1 : 0;
706 segp = (fifo_segment_t *) a->segment;
707 rmp->app_index = clib_host_to_net_u32 (a->app_index);
708 rmp->app_mq = fifo_segment_msg_q_offset (segp, 0);
709 rmp->vpp_ctrl_mq = fifo_segment_msg_q_offset (rx_mqs_seg, ctrl_thread);
710 rmp->vpp_ctrl_mq_thread = ctrl_thread;
712 rmp->fd_flags = fd_flags;
713 if (vec_len (segp->ssvm.name))
715 vl_api_vec_to_api_string (segp->ssvm.name, &rmp->segment_name);
717 rmp->segment_size = segp->ssvm.ssvm_size;
718 rmp->segment_handle = clib_host_to_net_u64 (a->segment_handle);
724 session_send_fds (reg, fds, n_fds);
729 vl_api_app_worker_add_del_t_handler (vl_api_app_worker_add_del_t * mp)
731 int rv = 0, fds[SESSION_N_FD_TYPE], n_fds = 0;
732 vl_api_app_worker_add_del_reply_t *rmp;
733 vl_api_registration_t *reg;
737 if (!session_main_is_enabled () || appns_sapi_enabled ())
739 rv = VNET_API_ERROR_FEATURE_DISABLED;
743 reg = vl_api_client_index_to_registration (mp->client_index);
747 app = application_get_if_valid (clib_net_to_host_u32 (mp->app_index));
750 rv = VNET_API_ERROR_INVALID_VALUE;
754 vnet_app_worker_add_del_args_t args = {
755 .app_index = app->app_index,
756 .wrk_map_index = clib_net_to_host_u32 (mp->wrk_index),
757 .api_client_index = mp->client_index,
760 rv = vnet_app_worker_add_del (&args);
763 clib_warning ("app worker add/del returned: %d", rv);
770 /* Send fifo segment fd if needed */
771 if (ssvm_type (args.segment) == SSVM_SEGMENT_MEMFD)
773 fd_flags |= SESSION_FD_F_MEMFD_SEGMENT;
774 fds[n_fds] = args.segment->fd;
777 if (application_segment_manager_properties (app)->use_mq_eventfd)
779 fd_flags |= SESSION_FD_F_MQ_EVENTFD;
780 fds[n_fds] = svm_msg_q_get_eventfd (args.evt_q);
786 REPLY_MACRO2 (VL_API_APP_WORKER_ADD_DEL_REPLY, ({
787 rmp->is_add = mp->is_add;
788 rmp->wrk_index = clib_host_to_net_u32 (args.wrk_map_index);
789 rmp->segment_handle = clib_host_to_net_u64 (args.segment_handle);
790 if (!rv && mp->is_add)
792 rmp->app_event_queue_address =
793 fifo_segment_msg_q_offset ((fifo_segment_t *) args.segment, 0);
795 rmp->fd_flags = fd_flags;
796 if (vec_len (args.segment->name))
798 vl_api_vec_to_api_string (args.segment->name, &rmp->segment_name);
805 session_send_fds (reg, fds, n_fds);
809 vl_api_application_detach_t_handler (vl_api_application_detach_t * mp)
811 vl_api_application_detach_reply_t *rmp;
812 int rv = VNET_API_ERROR_INVALID_VALUE_2;
813 vnet_app_detach_args_t _a, *a = &_a;
816 if (!session_main_is_enabled () || appns_sapi_enabled ())
818 rv = VNET_API_ERROR_FEATURE_DISABLED;
822 app = application_lookup (mp->client_index);
825 a->app_index = app->app_index;
826 a->api_client_index = mp->client_index;
827 rv = vnet_application_detach (a);
831 REPLY_MACRO (VL_API_APPLICATION_DETACH_REPLY);
835 vl_api_app_namespace_add_del_t_handler (vl_api_app_namespace_add_del_t * mp)
837 vl_api_app_namespace_add_del_reply_t *rmp;
841 if (session_main_is_enabled () == 0)
843 rv = VNET_API_ERROR_FEATURE_DISABLED;
847 ns_id = vl_api_from_api_to_new_vec (mp, &mp->namespace_id);
849 vnet_app_namespace_add_del_args_t args = {
851 .secret = clib_net_to_host_u64 (mp->secret),
852 .sw_if_index = clib_net_to_host_u32 (mp->sw_if_index),
853 .ip4_fib_id = clib_net_to_host_u32 (mp->ip4_fib_id),
854 .ip6_fib_id = clib_net_to_host_u32 (mp->ip6_fib_id),
857 rv = vnet_app_namespace_add_del (&args);
860 appns_index = app_namespace_index_from_id (ns_id);
861 if (appns_index == APP_NAMESPACE_INVALID_INDEX)
863 clib_warning ("app ns lookup failed");
864 rv = VNET_API_ERROR_UNSPECIFIED;
871 REPLY_MACRO2 (VL_API_APP_NAMESPACE_ADD_DEL_REPLY, ({
873 rmp->appns_index = clib_host_to_net_u32 (appns_index);
879 vl_api_session_rule_add_del_t_handler (vl_api_session_rule_add_del_t * mp)
881 vl_api_session_rule_add_del_reply_t *rmp;
882 session_rule_add_del_args_t args;
883 session_rule_table_add_del_args_t *table_args = &args.table_args;
886 clib_memset (&args, 0, sizeof (args));
888 ip_prefix_decode (&mp->lcl, &table_args->lcl);
889 ip_prefix_decode (&mp->rmt, &table_args->rmt);
891 table_args->lcl_port = mp->lcl_port;
892 table_args->rmt_port = mp->rmt_port;
893 table_args->action_index = clib_net_to_host_u32 (mp->action_index);
894 table_args->is_add = mp->is_add;
895 mp->tag[sizeof (mp->tag) - 1] = 0;
896 table_args->tag = format (0, "%s", mp->tag);
897 args.appns_index = clib_net_to_host_u32 (mp->appns_index);
898 args.scope = mp->scope;
899 args.transport_proto =
900 api_session_transport_proto_decode (&mp->transport_proto) ==
901 TRANSPORT_PROTO_UDP ? 1 : 0;
903 rv = vnet_session_rule_add_del (&args);
905 clib_warning ("rule add del returned: %d", rv);
906 vec_free (table_args->tag);
907 REPLY_MACRO (VL_API_SESSION_RULE_ADD_DEL_REPLY);
911 send_session_rule_details4 (mma_rule_16_t * rule, u8 is_local,
912 u8 transport_proto, u32 appns_index, u8 * tag,
913 vl_api_registration_t * reg, u32 context)
915 vl_api_session_rules_details_t *rmp = 0;
916 session_mask_or_match_4_t *match =
917 (session_mask_or_match_4_t *) & rule->match;
918 session_mask_or_match_4_t *mask =
919 (session_mask_or_match_4_t *) & rule->mask;
920 fib_prefix_t lcl, rmt;
922 rmp = vl_msg_api_alloc (sizeof (*rmp));
923 clib_memset (rmp, 0, sizeof (*rmp));
924 rmp->_vl_msg_id = ntohs (VL_API_SESSION_RULES_DETAILS);
925 rmp->context = context;
927 clib_memset (&lcl, 0, sizeof (lcl));
928 clib_memset (&rmt, 0, sizeof (rmt));
929 ip_set (&lcl.fp_addr, &match->lcl_ip, 1);
930 ip_set (&rmt.fp_addr, &match->rmt_ip, 1);
931 lcl.fp_len = ip4_mask_to_preflen (&mask->lcl_ip);
932 rmt.fp_len = ip4_mask_to_preflen (&mask->rmt_ip);
934 ip_prefix_encode (&lcl, &rmp->lcl);
935 ip_prefix_encode (&rmt, &rmp->rmt);
936 rmp->lcl_port = match->lcl_port;
937 rmp->rmt_port = match->rmt_port;
938 rmp->action_index = clib_host_to_net_u32 (rule->action_index);
940 is_local ? SESSION_RULE_SCOPE_API_LOCAL : SESSION_RULE_SCOPE_API_GLOBAL;
941 rmp->transport_proto = api_session_transport_proto_encode (transport_proto);
942 rmp->appns_index = clib_host_to_net_u32 (appns_index);
945 clib_memcpy_fast (rmp->tag, tag, vec_len (tag));
946 rmp->tag[vec_len (tag)] = 0;
949 vl_api_send_msg (reg, (u8 *) rmp);
953 send_session_rule_details6 (mma_rule_40_t * rule, u8 is_local,
954 u8 transport_proto, u32 appns_index, u8 * tag,
955 vl_api_registration_t * reg, u32 context)
957 vl_api_session_rules_details_t *rmp = 0;
958 session_mask_or_match_6_t *match =
959 (session_mask_or_match_6_t *) & rule->match;
960 session_mask_or_match_6_t *mask =
961 (session_mask_or_match_6_t *) & rule->mask;
962 fib_prefix_t lcl, rmt;
964 rmp = vl_msg_api_alloc (sizeof (*rmp));
965 clib_memset (rmp, 0, sizeof (*rmp));
966 rmp->_vl_msg_id = ntohs (VL_API_SESSION_RULES_DETAILS);
967 rmp->context = context;
969 clib_memset (&lcl, 0, sizeof (lcl));
970 clib_memset (&rmt, 0, sizeof (rmt));
971 ip_set (&lcl.fp_addr, &match->lcl_ip, 0);
972 ip_set (&rmt.fp_addr, &match->rmt_ip, 0);
973 lcl.fp_len = ip6_mask_to_preflen (&mask->lcl_ip);
974 rmt.fp_len = ip6_mask_to_preflen (&mask->rmt_ip);
976 ip_prefix_encode (&lcl, &rmp->lcl);
977 ip_prefix_encode (&rmt, &rmp->rmt);
978 rmp->lcl_port = match->lcl_port;
979 rmp->rmt_port = match->rmt_port;
980 rmp->action_index = clib_host_to_net_u32 (rule->action_index);
982 is_local ? SESSION_RULE_SCOPE_API_LOCAL : SESSION_RULE_SCOPE_API_GLOBAL;
983 rmp->transport_proto = api_session_transport_proto_encode (transport_proto);
984 rmp->appns_index = clib_host_to_net_u32 (appns_index);
987 clib_memcpy_fast (rmp->tag, tag, vec_len (tag));
988 rmp->tag[vec_len (tag)] = 0;
991 vl_api_send_msg (reg, (u8 *) rmp);
995 send_session_rules_table_details (session_rules_table_t * srt, u8 fib_proto,
996 u8 tp, u8 is_local, u32 appns_index,
997 vl_api_registration_t * reg, u32 context)
999 mma_rule_16_t *rule16;
1000 mma_rule_40_t *rule40;
1001 mma_rules_table_16_t *srt16;
1002 mma_rules_table_40_t *srt40;
1005 if (is_local || fib_proto == FIB_PROTOCOL_IP4)
1009 srt16 = &srt->session_rules_tables_16;
1010 pool_foreach (rule16, srt16->rules) {
1011 ri = mma_rules_table_rule_index_16 (srt16, rule16);
1012 tag = session_rules_table_rule_tag (srt, ri, 1);
1013 send_session_rule_details4 (rule16, is_local, tp, appns_index, tag,
1018 if (is_local || fib_proto == FIB_PROTOCOL_IP6)
1022 srt40 = &srt->session_rules_tables_40;
1023 pool_foreach (rule40, srt40->rules) {
1024 ri = mma_rules_table_rule_index_40 (srt40, rule40);
1025 tag = session_rules_table_rule_tag (srt, ri, 1);
1026 send_session_rule_details6 (rule40, is_local, tp, appns_index, tag,
1034 vl_api_session_rules_dump_t_handler (vl_api_session_rules_dump_t * mp)
1036 vl_api_registration_t *reg;
1037 session_table_t *st;
1040 reg = vl_api_client_index_to_registration (mp->client_index);
1045 session_table_foreach (st, ({
1046 for (tp = 0; tp < TRANSPORT_N_PROTOS; tp++)
1048 send_session_rules_table_details (&st->session_rules[tp],
1049 st->active_fib_proto, tp,
1050 st->is_local, st->appns_index, reg,
1058 vl_api_app_add_cert_key_pair_t_handler (vl_api_app_add_cert_key_pair_t * mp)
1060 vl_api_app_add_cert_key_pair_reply_t *rmp;
1061 vnet_app_add_cert_key_pair_args_t _a, *a = &_a;
1062 u32 certkey_len, key_len, cert_len;
1064 if (session_main_is_enabled () == 0)
1066 rv = VNET_API_ERROR_FEATURE_DISABLED;
1070 cert_len = clib_net_to_host_u16 (mp->cert_len);
1071 if (cert_len > 10000)
1073 rv = VNET_API_ERROR_INVALID_VALUE;
1077 certkey_len = clib_net_to_host_u16 (mp->certkey_len);
1078 if (certkey_len < cert_len)
1080 rv = VNET_API_ERROR_INVALID_VALUE;
1084 key_len = certkey_len - cert_len;
1085 if (key_len > 10000)
1087 rv = VNET_API_ERROR_INVALID_VALUE;
1091 clib_memset (a, 0, sizeof (*a));
1092 a->cert = mp->certkey;
1093 a->key = mp->certkey + cert_len;
1094 a->cert_len = cert_len;
1095 a->key_len = key_len;
1096 rv = vnet_app_add_cert_key_pair (a);
1100 REPLY_MACRO2 (VL_API_APP_ADD_CERT_KEY_PAIR_REPLY, ({
1102 rmp->index = clib_host_to_net_u32 (a->index);
1108 vl_api_app_del_cert_key_pair_t_handler (vl_api_app_del_cert_key_pair_t * mp)
1110 vl_api_app_del_cert_key_pair_reply_t *rmp;
1113 if (session_main_is_enabled () == 0)
1115 rv = VNET_API_ERROR_FEATURE_DISABLED;
1118 ckpair_index = clib_net_to_host_u32 (mp->index);
1119 rv = vnet_app_del_cert_key_pair (ckpair_index);
1122 REPLY_MACRO (VL_API_APP_DEL_CERT_KEY_PAIR_REPLY);
1125 static clib_error_t *
1126 application_reaper_cb (u32 client_index)
1128 application_t *app = application_lookup (client_index);
1129 vnet_app_detach_args_t _a, *a = &_a;
1132 a->app_index = app->app_index;
1133 a->api_client_index = client_index;
1134 vnet_application_detach (a);
1139 VL_MSG_API_REAPER_FUNCTION (application_reaper_cb);
1141 #define vl_msg_name_crc_list
1142 #include <vnet/vnet_all_api_h.h>
1143 #undef vl_msg_name_crc_list
1146 setup_message_id_table (api_main_t * am)
1148 #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
1149 foreach_vl_msg_name_crc_session;
1154 * session_api_hookup
1155 * Add uri's API message handlers to the table.
1156 * vlib has already mapped shared memory and
1157 * added the client registration handlers.
1158 * See .../open-repo/vlib/memclnt_vlib.c:memclnt_process()
1160 static clib_error_t *
1161 session_api_hookup (vlib_main_t * vm)
1163 api_main_t *am = vlibapi_get_main ();
1166 vl_msg_api_set_handlers(VL_API_##N, #n, \
1167 vl_api_##n##_t_handler, \
1169 vl_api_##n##_t_endian, \
1170 vl_api_##n##_t_print, \
1171 sizeof(vl_api_##n##_t), 1);
1172 foreach_session_api_msg;
1176 * Set up the (msg_name, crc, message-id) table
1178 setup_message_id_table (am);
1183 VLIB_API_INIT_FUNCTION (session_api_hookup);
1186 * Socket api functions
1190 sapi_send_fds (app_worker_t * app_wrk, int *fds, int n_fds)
1192 app_sapi_msg_t smsg = { 0 };
1193 app_namespace_t *app_ns;
1198 app = application_get (app_wrk->app_index);
1199 app_ns = app_namespace_get (app->ns_index);
1200 cs_index = appns_sapi_handle_sock_index (app_wrk->api_client_index);
1201 cs = appns_sapi_get_socket (app_ns, cs_index);
1202 if (PREDICT_FALSE (!cs))
1205 /* There's no payload for the message only the type */
1206 smsg.type = APP_SAPI_MSG_TYPE_SEND_FDS;
1207 clib_socket_sendmsg (cs, &smsg, sizeof (smsg), fds, n_fds);
1211 mq_send_add_segment_sapi_cb (u32 app_wrk_index, u64 segment_handle)
1213 int fds[SESSION_N_FD_TYPE], n_fds = 0;
1214 svm_msg_q_msg_t _msg, *msg = &_msg;
1215 session_app_add_segment_msg_t *mp;
1216 app_worker_t *app_wrk;
1217 session_event_t *evt;
1218 svm_msg_q_t *app_mq;
1223 app_wrk = app_worker_get (app_wrk_index);
1225 fs = segment_manager_get_segment_w_handle (segment_handle);
1227 ASSERT (ssvm_type (sp) == SSVM_SEGMENT_MEMFD);
1229 fd_flags |= SESSION_FD_F_MEMFD_SEGMENT;
1230 fds[n_fds] = sp->fd;
1233 app_mq = app_wrk->event_queue;
1234 if (mq_try_lock_and_alloc_msg (app_mq, msg))
1238 * Send the fd over api socket
1240 sapi_send_fds (app_wrk, fds, n_fds);
1243 * Send the actual message over mq
1245 evt = svm_msg_q_msg_data (app_mq, msg);
1246 clib_memset (evt, 0, sizeof (*evt));
1247 evt->event_type = SESSION_CTRL_EVT_APP_ADD_SEGMENT;
1248 mp = (session_app_add_segment_msg_t *) evt->data;
1249 clib_memset (mp, 0, sizeof (*mp));
1250 mp->segment_size = sp->ssvm_size;
1251 mp->fd_flags = fd_flags;
1252 mp->segment_handle = segment_handle;
1253 strncpy ((char *) mp->segment_name, (char *) sp->name,
1254 sizeof (mp->segment_name) - 1);
1256 svm_msg_q_add_and_unlock (app_mq, msg);
1262 mq_send_del_segment_sapi_cb (u32 app_wrk_index, u64 segment_handle)
1264 svm_msg_q_msg_t _msg, *msg = &_msg;
1265 session_app_del_segment_msg_t *mp;
1266 app_worker_t *app_wrk;
1267 session_event_t *evt;
1268 svm_msg_q_t *app_mq;
1270 app_wrk = app_worker_get (app_wrk_index);
1272 app_mq = app_wrk->event_queue;
1273 if (mq_try_lock_and_alloc_msg (app_mq, msg))
1276 evt = svm_msg_q_msg_data (app_mq, msg);
1277 clib_memset (evt, 0, sizeof (*evt));
1278 evt->event_type = SESSION_CTRL_EVT_APP_DEL_SEGMENT;
1279 mp = (session_app_del_segment_msg_t *) evt->data;
1280 clib_memset (mp, 0, sizeof (*mp));
1281 mp->segment_handle = segment_handle;
1282 svm_msg_q_add_and_unlock (app_mq, msg);
1287 static session_cb_vft_t session_mq_sapi_cb_vft = {
1288 .session_accept_callback = mq_send_session_accepted_cb,
1289 .session_disconnect_callback = mq_send_session_disconnected_cb,
1290 .session_connected_callback = mq_send_session_connected_cb,
1291 .session_reset_callback = mq_send_session_reset_cb,
1292 .session_migrate_callback = mq_send_session_migrate_cb,
1293 .session_cleanup_callback = mq_send_session_cleanup_cb,
1294 .add_segment_callback = mq_send_add_segment_sapi_cb,
1295 .del_segment_callback = mq_send_del_segment_sapi_cb,
1299 session_api_attach_handler (app_namespace_t * app_ns, clib_socket_t * cs,
1300 app_sapi_attach_msg_t * mp)
1302 int rv = 0, *fds = 0, n_fds = 0, i, n_workers;
1303 vnet_app_attach_args_t _a, *a = &_a;
1304 app_sapi_attach_reply_msg_t *rmp;
1305 u8 fd_flags = 0, ctrl_thread;
1306 app_ns_api_handle_t *handle;
1307 fifo_segment_t *rx_mqs_seg;
1308 app_sapi_msg_t msg = { 0 };
1309 app_worker_t *app_wrk;
1313 /* Make sure name is null terminated */
1316 clib_memset (a, 0, sizeof (*a));
1317 a->api_client_index = appns_sapi_socket_handle (app_ns, cs);
1318 a->name = format (0, "%s", (char *) mp->name);
1319 a->options = mp->options;
1320 a->session_cb_vft = &session_mq_sapi_cb_vft;
1321 a->use_sock_api = 1;
1322 a->options[APP_OPTIONS_NAMESPACE] = app_namespace_index (app_ns);
1324 if ((rv = vnet_application_attach (a)))
1326 clib_warning ("attach returned: %d", rv);
1330 n_workers = vlib_num_workers ();
1331 vec_validate (fds, 3 /* segs + tx evtfd */ + n_workers);
1333 /* Send event queues segment */
1334 app = application_get (a->app_index);
1335 rx_mqs_seg = application_get_rx_mqs_segment (app);
1337 fd_flags |= SESSION_FD_F_VPP_MQ_SEGMENT;
1338 fds[n_fds] = rx_mqs_seg->ssvm.fd;
1341 /* Send fifo segment fd if needed */
1342 if (ssvm_type (a->segment) == SSVM_SEGMENT_MEMFD)
1344 fd_flags |= SESSION_FD_F_MEMFD_SEGMENT;
1345 fds[n_fds] = a->segment->fd;
1348 if (a->options[APP_OPTIONS_FLAGS] & APP_OPTIONS_FLAGS_EVT_MQ_USE_EVENTFD)
1350 fd_flags |= SESSION_FD_F_MQ_EVENTFD;
1351 fds[n_fds] = svm_msg_q_get_eventfd (a->app_evt_q);
1355 if (application_use_private_rx_mqs ())
1357 fd_flags |= SESSION_FD_F_VPP_MQ_EVENTFD;
1358 for (i = 0; i < n_workers + 1; i++)
1360 rx_mq = application_rx_mq_get (app, i);
1361 fds[n_fds] = svm_msg_q_get_eventfd (rx_mq);
1368 msg.type = APP_SAPI_MSG_TYPE_ATTACH_REPLY;
1369 rmp = &msg.attach_reply;
1373 ctrl_thread = n_workers ? 1 : 0;
1374 rmp->app_index = a->app_index;
1376 fifo_segment_msg_q_offset ((fifo_segment_t *) a->segment, 0);
1377 rmp->vpp_ctrl_mq = fifo_segment_msg_q_offset (rx_mqs_seg, ctrl_thread);
1378 rmp->vpp_ctrl_mq_thread = ctrl_thread;
1380 rmp->fd_flags = fd_flags;
1381 /* No segment name and size since we only support memfds
1382 * in this configuration */
1383 rmp->segment_handle = a->segment_handle;
1384 rmp->api_client_handle = a->api_client_index;
1386 /* Update app index for socket */
1387 handle = (app_ns_api_handle_t *) & cs->private_data;
1388 app_wrk = application_get_worker (app, 0);
1389 handle->aah_app_wrk_index = app_wrk->wrk_index;
1392 clib_socket_sendmsg (cs, &msg, sizeof (msg), fds, n_fds);
1398 sapi_socket_close_w_handle (u32 api_handle)
1400 app_namespace_t *app_ns = app_namespace_get (api_handle >> 16);
1401 u16 sock_index = api_handle & 0xffff;
1402 app_ns_api_handle_t *handle;
1406 cs = appns_sapi_get_socket (app_ns, sock_index);
1410 handle = (app_ns_api_handle_t *) & cs->private_data;
1411 cf = clib_file_get (&file_main, handle->aah_file_index);
1412 clib_file_del (&file_main, cf);
1414 clib_socket_close (cs);
1415 appns_sapi_free_socket (app_ns, cs);
1419 sapi_add_del_worker_handler (app_namespace_t * app_ns,
1421 app_sapi_worker_add_del_msg_t * mp)
1423 int rv = 0, fds[SESSION_N_FD_TYPE], n_fds = 0;
1424 app_sapi_worker_add_del_reply_msg_t *rmp;
1425 app_ns_api_handle_t *handle;
1426 app_sapi_msg_t msg = { 0 };
1427 app_worker_t *app_wrk;
1428 u32 sapi_handle = -1;
1432 app = application_get_if_valid (mp->app_index);
1435 rv = VNET_API_ERROR_INVALID_VALUE;
1439 sapi_handle = appns_sapi_socket_handle (app_ns, cs);
1441 vnet_app_worker_add_del_args_t args = {
1442 .app_index = app->app_index,
1443 .wrk_map_index = mp->wrk_index,
1444 .api_client_index = sapi_handle,
1445 .is_add = mp->is_add
1447 rv = vnet_app_worker_add_del (&args);
1450 clib_warning ("app worker add/del returned: %d", rv);
1456 sapi_socket_close_w_handle (sapi_handle);
1460 /* Send fifo segment fd if needed */
1461 if (ssvm_type (args.segment) == SSVM_SEGMENT_MEMFD)
1463 fd_flags |= SESSION_FD_F_MEMFD_SEGMENT;
1464 fds[n_fds] = args.segment->fd;
1467 if (application_segment_manager_properties (app)->use_mq_eventfd)
1469 fd_flags |= SESSION_FD_F_MQ_EVENTFD;
1470 fds[n_fds] = svm_msg_q_get_eventfd (args.evt_q);
1476 msg.type = APP_SAPI_MSG_TYPE_ADD_DEL_WORKER_REPLY;
1477 rmp = &msg.worker_add_del_reply;
1479 rmp->is_add = mp->is_add;
1480 rmp->api_client_handle = sapi_handle;
1481 rmp->wrk_index = args.wrk_map_index;
1482 rmp->segment_handle = args.segment_handle;
1483 if (!rv && mp->is_add)
1485 /* No segment name and size. This supports only memfds */
1486 rmp->app_event_queue_address =
1487 fifo_segment_msg_q_offset ((fifo_segment_t *) args.segment, 0);
1489 rmp->fd_flags = fd_flags;
1491 /* Update app index for socket */
1492 handle = (app_ns_api_handle_t *) & cs->private_data;
1493 app_wrk = application_get_worker (app, args.wrk_map_index);
1494 handle->aah_app_wrk_index = app_wrk->wrk_index;
1497 clib_socket_sendmsg (cs, &msg, sizeof (msg), fds, n_fds);
1501 sapi_socket_detach (app_namespace_t * app_ns, clib_socket_t * cs)
1503 app_ns_api_handle_t *handle;
1504 app_worker_t *app_wrk;
1505 u32 api_client_handle;
1507 api_client_handle = appns_sapi_socket_handle (app_ns, cs);
1508 sapi_socket_close_w_handle (api_client_handle);
1510 /* Cleanup everything because app worker closed socket or crashed */
1511 handle = (app_ns_api_handle_t *) & cs->private_data;
1512 app_wrk = app_worker_get (handle->aah_app_wrk_index);
1514 vnet_app_worker_add_del_args_t args = {
1515 .app_index = app_wrk->app_index,
1516 .wrk_map_index = app_wrk->wrk_map_index,
1517 .api_client_index = api_client_handle,
1520 /* Send rpc to main thread for worker barrier */
1521 vlib_rpc_call_main_thread (vnet_app_worker_add_del, (u8 *) & args,
1525 static clib_error_t *
1526 sapi_sock_read_ready (clib_file_t * cf)
1528 app_ns_api_handle_t *handle = (app_ns_api_handle_t *) & cf->private_data;
1529 vlib_main_t *vm = vlib_get_main ();
1530 app_sapi_msg_t msg = { 0 };
1531 app_namespace_t *app_ns;
1532 clib_error_t *err = 0;
1535 app_ns = app_namespace_get (handle->aah_app_ns_index);
1536 cs = appns_sapi_get_socket (app_ns, handle->aah_sock_index);
1540 err = clib_socket_recvmsg (cs, &msg, sizeof (msg), 0, 0);
1543 clib_error_free (err);
1544 sapi_socket_detach (app_ns, cs);
1548 handle = (app_ns_api_handle_t *) & cs->private_data;
1550 vlib_worker_thread_barrier_sync (vm);
1554 case APP_SAPI_MSG_TYPE_ATTACH:
1555 session_api_attach_handler (app_ns, cs, &msg.attach);
1557 case APP_SAPI_MSG_TYPE_ADD_DEL_WORKER:
1558 sapi_add_del_worker_handler (app_ns, cs, &msg.worker_add_del);
1561 clib_warning ("app wrk %u unknown message type: %u",
1562 handle->aah_app_wrk_index, msg.type);
1566 vlib_worker_thread_barrier_release (vm);
1572 static clib_error_t *
1573 sapi_sock_write_ready (clib_file_t * cf)
1575 app_ns_api_handle_t *handle = (app_ns_api_handle_t *) & cf->private_data;
1576 clib_warning ("called for app ns %u", handle->aah_app_ns_index);
1580 static clib_error_t *
1581 sapi_sock_error (clib_file_t * cf)
1583 app_ns_api_handle_t *handle = (app_ns_api_handle_t *) & cf->private_data;
1584 app_namespace_t *app_ns;
1587 app_ns = app_namespace_get (handle->aah_app_ns_index);
1588 cs = appns_sapi_get_socket (app_ns, handle->aah_sock_index);
1592 sapi_socket_detach (app_ns, cs);
1596 static clib_error_t *
1597 sapi_sock_accept_ready (clib_file_t * scf)
1599 app_ns_api_handle_t handle = *(app_ns_api_handle_t *) & scf->private_data;
1600 app_namespace_t *app_ns;
1601 clib_file_t cf = { 0 };
1602 clib_error_t *err = 0;
1603 clib_socket_t *ccs, *scs;
1605 /* Listener files point to namespace */
1606 app_ns = app_namespace_get (handle.aah_app_ns_index);
1609 * Initialize client socket
1611 ccs = appns_sapi_alloc_socket (app_ns);
1613 /* Grab server socket after client is initialized */
1614 scs = appns_sapi_get_socket (app_ns, handle.aah_sock_index);
1618 err = clib_socket_accept (scs, ccs);
1621 clib_error_report (err);
1625 cf.read_function = sapi_sock_read_ready;
1626 cf.write_function = sapi_sock_write_ready;
1627 cf.error_function = sapi_sock_error;
1628 cf.file_descriptor = ccs->fd;
1629 /* File points to app namespace and socket */
1630 handle.aah_sock_index = appns_sapi_socket_index (app_ns, ccs);
1631 cf.private_data = handle.as_u64;
1632 cf.description = format (0, "app sock conn fd: %d", ccs->fd);
1634 /* Poll until we get an attach message. Socket points to file and
1635 * application that owns the socket */
1636 handle.aah_app_wrk_index = APP_INVALID_INDEX;
1637 handle.aah_file_index = clib_file_add (&file_main, &cf);
1638 ccs->private_data = handle.as_u64;
1643 appns_sapi_free_socket (app_ns, ccs);
1648 appns_sapi_add_ns_socket (app_namespace_t * app_ns)
1650 char *subdir = "/app_ns_sockets/";
1651 app_ns_api_handle_t *handle;
1652 clib_file_t cf = { 0 };
1653 struct stat file_stat;
1659 vec_add (dir, vlib_unix_get_runtime_dir (),
1660 strlen (vlib_unix_get_runtime_dir ()));
1661 vec_add (dir, (u8 *) subdir, strlen (subdir));
1663 err = vlib_unix_recursive_mkdir ((char *) dir);
1666 clib_error_report (err);
1671 app_ns->sock_name = format (0, "%v%v%c", dir, app_ns->ns_id, 0);
1674 * Create and initialize socket to listen on
1676 cs = appns_sapi_alloc_socket (app_ns);
1677 cs->config = (char *) app_ns->sock_name;
1678 cs->flags = CLIB_SOCKET_F_IS_SERVER |
1679 CLIB_SOCKET_F_ALLOW_GROUP_WRITE |
1680 CLIB_SOCKET_F_SEQPACKET | CLIB_SOCKET_F_PASSCRED;
1682 if ((err = clib_socket_init (cs)))
1684 clib_error_report (err);
1689 if (stat ((char *) app_ns->sock_name, &file_stat) == -1)
1698 cf.read_function = sapi_sock_accept_ready;
1699 cf.file_descriptor = cs->fd;
1700 /* File points to namespace */
1701 handle = (app_ns_api_handle_t *) & cf.private_data;
1702 handle->aah_app_ns_index = app_namespace_index (app_ns);
1703 handle->aah_sock_index = appns_sapi_socket_index (app_ns, cs);
1704 cf.description = format (0, "app sock listener: %s", app_ns->sock_name);
1706 /* Socket points to clib file index */
1707 handle = (app_ns_api_handle_t *) & cs->private_data;
1708 handle->aah_file_index = clib_file_add (&file_main, &cf);
1709 handle->aah_app_wrk_index = APP_INVALID_INDEX;
1717 * fd.io coding-style-patch-verification: ON
1720 * eval: (c-set-style "gnu")