Line data Source code
1 : /*
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:
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 <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>
24 : #include <vnet/ip/ip_types_api.h>
25 :
26 : #include <vnet/format_fns.h>
27 : #include <vnet/session/session.api_enum.h>
28 : #include <vnet/session/session.api_types.h>
29 :
30 : #define REPLY_MSG_ID_BASE session_main.msg_id_base
31 : #include <vlibapi/api_helper_macros.h>
32 :
33 : static transport_proto_t
34 0 : api_session_transport_proto_decode (const vl_api_transport_proto_t * api_tp)
35 : {
36 0 : switch (*api_tp)
37 : {
38 0 : case TRANSPORT_PROTO_API_TCP:
39 0 : return TRANSPORT_PROTO_TCP;
40 0 : case TRANSPORT_PROTO_API_UDP:
41 0 : return TRANSPORT_PROTO_UDP;
42 0 : case TRANSPORT_PROTO_API_TLS:
43 0 : return TRANSPORT_PROTO_TLS;
44 0 : case TRANSPORT_PROTO_API_QUIC:
45 0 : return TRANSPORT_PROTO_QUIC;
46 0 : default:
47 0 : return TRANSPORT_PROTO_NONE;
48 : }
49 : }
50 :
51 : static vl_api_transport_proto_t
52 0 : api_session_transport_proto_encode (const transport_proto_t tp)
53 : {
54 0 : switch (tp)
55 : {
56 0 : case TRANSPORT_PROTO_TCP:
57 0 : return TRANSPORT_PROTO_API_TCP;
58 0 : case TRANSPORT_PROTO_UDP:
59 0 : return TRANSPORT_PROTO_API_UDP;
60 0 : case TRANSPORT_PROTO_TLS:
61 0 : return TRANSPORT_PROTO_API_TLS;
62 0 : case TRANSPORT_PROTO_QUIC:
63 0 : return TRANSPORT_PROTO_API_QUIC;
64 0 : default:
65 0 : return TRANSPORT_PROTO_API_NONE;
66 : }
67 : }
68 :
69 : static int
70 42 : session_send_fds (vl_api_registration_t * reg, int fds[], int n_fds)
71 : {
72 : clib_error_t *error;
73 42 : if (vl_api_registration_file_index (reg) == VL_API_INVALID_FI)
74 0 : return SESSION_E_BAPI_NO_FD;
75 42 : error = vl_api_send_fd_msg (reg, fds, n_fds);
76 42 : if (error)
77 : {
78 0 : clib_error_report (error);
79 0 : return SESSION_E_BAPI_SEND_FD;
80 : }
81 42 : return 0;
82 : }
83 :
84 : static int
85 47 : mq_send_session_accepted_cb (session_t * s)
86 : {
87 47 : app_worker_t *app_wrk = app_worker_get (s->app_wrk_index);
88 47 : session_accepted_msg_t m = { 0 };
89 : fifo_segment_t *eq_seg;
90 : session_t *listener;
91 : application_t *app;
92 :
93 47 : app = application_get (app_wrk->app_index);
94 :
95 47 : m.context = app->app_index;
96 47 : m.server_rx_fifo = fifo_segment_fifo_offset (s->rx_fifo);
97 47 : m.server_tx_fifo = fifo_segment_fifo_offset (s->tx_fifo);
98 47 : m.segment_handle = session_segment_handle (s);
99 47 : m.flags = s->flags;
100 :
101 47 : eq_seg = application_get_rx_mqs_segment (app);
102 :
103 47 : if (session_has_transport (s))
104 : {
105 35 : listener = listen_session_get_from_handle (s->listener_handle);
106 35 : m.listener_handle = app_listen_session_handle (listener);
107 35 : if (application_is_proxy (app))
108 : {
109 : listener =
110 0 : app_worker_first_listener (app_wrk, session_get_fib_proto (s),
111 0 : session_get_transport_proto (s));
112 0 : if (listener)
113 0 : m.listener_handle = listen_session_get_handle (listener);
114 : }
115 35 : m.vpp_event_queue_address =
116 35 : fifo_segment_msg_q_offset (eq_seg, s->thread_index);
117 35 : m.mq_index = s->thread_index;
118 35 : m.handle = session_handle (s);
119 :
120 35 : session_get_endpoint (s, &m.rmt, 0 /* is_lcl */);
121 35 : session_get_endpoint (s, &m.lcl, 1 /* is_lcl */);
122 : }
123 : else
124 : {
125 : ct_connection_t *ct;
126 :
127 12 : ct = (ct_connection_t *) session_get_transport (s);
128 12 : listener = listen_session_get_from_handle (s->listener_handle);
129 12 : m.listener_handle = app_listen_session_handle (listener);
130 12 : m.rmt.is_ip4 = session_type_is_ip4 (listener->session_type);
131 12 : m.rmt.port = ct->c_rmt_port;
132 12 : m.lcl.port = ct->c_lcl_port;
133 12 : m.handle = session_handle (s);
134 12 : m.vpp_event_queue_address =
135 12 : fifo_segment_msg_q_offset (eq_seg, s->thread_index);
136 12 : m.mq_index = s->thread_index;
137 : }
138 :
139 47 : if (application_original_dst_is_enabled (app))
140 : {
141 0 : session_get_original_dst (&m.lcl, &m.rmt,
142 : session_get_transport_proto (s),
143 : &m.original_dst_ip4, &m.original_dst_port);
144 : }
145 :
146 47 : app_wrk_send_ctrl_evt (app_wrk, SESSION_CTRL_EVT_ACCEPTED, &m, sizeof (m));
147 :
148 47 : return 0;
149 : }
150 :
151 : static inline void
152 40 : mq_send_session_close_evt (app_worker_t * app_wrk, session_handle_t sh,
153 : session_evt_type_t evt_type)
154 : {
155 40 : session_disconnected_msg_t m = { 0 };
156 :
157 40 : m.handle = sh;
158 40 : m.context = app_wrk->api_client_index;
159 :
160 40 : app_wrk_send_ctrl_evt (app_wrk, evt_type, &m, sizeof (m));
161 40 : }
162 :
163 : static inline void
164 0 : mq_notify_close_subscribers (u32 app_index, session_handle_t sh,
165 : svm_fifo_t * f, session_evt_type_t evt_type)
166 : {
167 : app_worker_t *app_wrk;
168 : application_t *app;
169 : int i;
170 :
171 0 : app = application_get (app_index);
172 0 : if (!app)
173 0 : return;
174 :
175 0 : for (i = 0; i < f->shr->n_subscribers; i++)
176 : {
177 0 : if (!(app_wrk = application_get_worker (app, f->shr->subscribers[i])))
178 0 : continue;
179 0 : mq_send_session_close_evt (app_wrk, sh, SESSION_CTRL_EVT_DISCONNECTED);
180 : }
181 : }
182 :
183 : static void
184 34 : mq_send_session_disconnected_cb (session_t * s)
185 : {
186 34 : app_worker_t *app_wrk = app_worker_get (s->app_wrk_index);
187 34 : session_handle_t sh = session_handle (s);
188 :
189 34 : mq_send_session_close_evt (app_wrk, session_handle (s),
190 : SESSION_CTRL_EVT_DISCONNECTED);
191 :
192 34 : if (svm_fifo_n_subscribers (s->rx_fifo))
193 0 : mq_notify_close_subscribers (app_wrk->app_index, sh, s->rx_fifo,
194 : SESSION_CTRL_EVT_DISCONNECTED);
195 34 : }
196 :
197 : static void
198 6 : mq_send_session_reset_cb (session_t * s)
199 : {
200 6 : app_worker_t *app_wrk = app_worker_get (s->app_wrk_index);
201 6 : session_handle_t sh = session_handle (s);
202 :
203 6 : mq_send_session_close_evt (app_wrk, sh, SESSION_CTRL_EVT_RESET);
204 :
205 6 : if (svm_fifo_n_subscribers (s->rx_fifo))
206 0 : mq_notify_close_subscribers (app_wrk->app_index, sh, s->rx_fifo,
207 : SESSION_CTRL_EVT_RESET);
208 6 : }
209 :
210 : int
211 51 : mq_send_session_connected_cb (u32 app_wrk_index, u32 api_context,
212 : session_t * s, session_error_t err)
213 : {
214 51 : session_connected_msg_t m = { 0 };
215 : transport_connection_t *tc;
216 : fifo_segment_t *eq_seg;
217 : app_worker_t *app_wrk;
218 : application_t *app;
219 :
220 51 : app_wrk = app_worker_get (app_wrk_index);
221 :
222 51 : m.context = api_context;
223 51 : m.retval = err;
224 :
225 51 : if (err)
226 0 : goto snd_msg;
227 :
228 51 : app = application_get (app_wrk->app_index);
229 51 : eq_seg = application_get_rx_mqs_segment (app);
230 :
231 51 : if (session_has_transport (s))
232 : {
233 39 : tc = session_get_transport (s);
234 39 : if (!tc)
235 : {
236 0 : clib_warning ("failed to retrieve transport!");
237 0 : m.retval = SESSION_E_REFUSED;
238 0 : goto snd_msg;
239 : }
240 :
241 39 : m.handle = session_handle (s);
242 39 : m.vpp_event_queue_address =
243 39 : fifo_segment_msg_q_offset (eq_seg, s->thread_index);
244 :
245 39 : session_get_endpoint (s, &m.lcl, 1 /* is_lcl */);
246 :
247 39 : m.server_rx_fifo = fifo_segment_fifo_offset (s->rx_fifo);
248 39 : m.server_tx_fifo = fifo_segment_fifo_offset (s->tx_fifo);
249 39 : m.segment_handle = session_segment_handle (s);
250 39 : m.mq_index = s->thread_index;
251 : }
252 : else
253 : {
254 : ct_connection_t *cct;
255 : session_t *ss;
256 :
257 12 : cct = (ct_connection_t *) session_get_transport (s);
258 12 : m.handle = session_handle (s);
259 12 : m.lcl.port = cct->c_lcl_port;
260 12 : m.lcl.is_ip4 = cct->c_is_ip4;
261 12 : m.vpp_event_queue_address =
262 12 : fifo_segment_msg_q_offset (eq_seg, s->thread_index);
263 12 : m.server_rx_fifo = fifo_segment_fifo_offset (s->rx_fifo);
264 12 : m.server_tx_fifo = fifo_segment_fifo_offset (s->tx_fifo);
265 12 : m.segment_handle = session_segment_handle (s);
266 12 : ss = ct_session_get_peer (s);
267 12 : m.ct_rx_fifo = fifo_segment_fifo_offset (ss->tx_fifo);
268 12 : m.ct_tx_fifo = fifo_segment_fifo_offset (ss->rx_fifo);
269 12 : m.ct_segment_handle = session_segment_handle (ss);
270 12 : m.mq_index = s->thread_index;
271 : }
272 :
273 : /* Setup client session index in advance, in case data arrives
274 : * before the app processes message and updates it */
275 51 : s->rx_fifo->shr->client_session_index = api_context;
276 51 : s->tx_fifo->shr->client_session_index = api_context;
277 :
278 51 : snd_msg:
279 :
280 51 : app_wrk_send_ctrl_evt (app_wrk, SESSION_CTRL_EVT_CONNECTED, &m, sizeof (m));
281 :
282 51 : return 0;
283 : }
284 :
285 : int
286 43 : mq_send_session_bound_cb (u32 app_wrk_index, u32 api_context,
287 : session_handle_t handle, int rv)
288 : {
289 43 : session_bound_msg_t m = { 0 };
290 : transport_endpoint_t tep;
291 : fifo_segment_t *eq_seg;
292 : app_worker_t *app_wrk;
293 : application_t *app;
294 : app_listener_t *al;
295 43 : session_t *ls = 0;
296 :
297 43 : app_wrk = app_worker_get (app_wrk_index);
298 :
299 43 : m.context = api_context;
300 43 : m.retval = rv;
301 :
302 43 : if (rv)
303 0 : goto snd_msg;
304 :
305 43 : m.handle = handle;
306 43 : al = app_listener_get_w_handle (handle);
307 43 : if (al->session_index != SESSION_INVALID_INDEX)
308 31 : ls = app_listener_get_session (al);
309 : else
310 12 : ls = app_listener_get_local_session (al);
311 :
312 43 : session_get_endpoint (ls, &tep, 1 /* is_lcl */);
313 43 : m.lcl_port = tep.port;
314 43 : m.lcl_is_ip4 = tep.is_ip4;
315 43 : clib_memcpy_fast (m.lcl_ip, &tep.ip, sizeof (tep.ip));
316 43 : app = application_get (app_wrk->app_index);
317 43 : eq_seg = application_get_rx_mqs_segment (app);
318 43 : m.vpp_evt_q = fifo_segment_msg_q_offset (eq_seg, ls->thread_index);
319 43 : m.mq_index = ls->thread_index;
320 :
321 43 : if (session_transport_service_type (ls) == TRANSPORT_SERVICE_CL &&
322 3 : ls->rx_fifo)
323 : {
324 3 : m.mq_index = transport_cl_thread ();
325 3 : m.vpp_evt_q = fifo_segment_msg_q_offset (eq_seg, m.mq_index);
326 3 : m.rx_fifo = fifo_segment_fifo_offset (ls->rx_fifo);
327 3 : m.tx_fifo = fifo_segment_fifo_offset (ls->tx_fifo);
328 3 : m.segment_handle = session_segment_handle (ls);
329 : }
330 :
331 40 : snd_msg:
332 :
333 43 : app_wrk_send_ctrl_evt (app_wrk, SESSION_CTRL_EVT_BOUND, &m, sizeof (m));
334 :
335 43 : return 0;
336 : }
337 :
338 : void
339 18 : mq_send_unlisten_reply (app_worker_t * app_wrk, session_handle_t sh,
340 : u32 context, int rv)
341 : {
342 18 : session_unlisten_reply_msg_t m = { 0 };
343 :
344 18 : m.context = context;
345 18 : m.handle = sh;
346 18 : m.retval = rv;
347 18 : app_wrk_send_ctrl_evt (app_wrk, SESSION_CTRL_EVT_UNLISTEN_REPLY, &m,
348 : sizeof (m));
349 18 : }
350 :
351 : static void
352 0 : mq_send_session_migrate_cb (session_t * s, session_handle_t new_sh)
353 : {
354 0 : session_migrated_msg_t m = { 0 };
355 : fifo_segment_t *eq_seg;
356 : app_worker_t *app_wrk;
357 : application_t *app;
358 : u32 thread_index;
359 :
360 0 : thread_index = session_thread_from_handle (new_sh);
361 0 : app_wrk = app_worker_get (s->app_wrk_index);
362 0 : app = application_get (app_wrk->app_index);
363 0 : eq_seg = application_get_rx_mqs_segment (app);
364 :
365 0 : m.handle = session_handle (s);
366 0 : m.new_handle = new_sh;
367 0 : m.vpp_thread_index = thread_index;
368 0 : m.vpp_evt_q = fifo_segment_msg_q_offset (eq_seg, thread_index);
369 0 : m.segment_handle = SESSION_INVALID_HANDLE;
370 :
371 0 : app_wrk_send_ctrl_evt (app_wrk, SESSION_CTRL_EVT_MIGRATED, &m, sizeof (m));
372 0 : }
373 :
374 : static int
375 31 : mq_send_add_segment_cb (u32 app_wrk_index, u64 segment_handle)
376 : {
377 31 : session_app_add_segment_msg_t m = { 0 };
378 : vl_api_registration_t *reg;
379 : app_worker_t *app_wrk;
380 : fifo_segment_t *fs;
381 : ssvm_private_t *sp;
382 31 : u8 fd_flags = 0;
383 :
384 31 : app_wrk = app_worker_get (app_wrk_index);
385 :
386 31 : reg = vl_mem_api_client_index_to_registration (app_wrk->api_client_index);
387 31 : if (!reg)
388 : {
389 0 : clib_warning ("no api registration for client: %u",
390 : app_wrk->api_client_index);
391 0 : return -1;
392 : }
393 :
394 31 : fs = segment_manager_get_segment_w_handle (segment_handle);
395 31 : sp = &fs->ssvm;
396 31 : if (ssvm_type (sp) == SSVM_SEGMENT_MEMFD)
397 : {
398 31 : if (vl_api_registration_file_index (reg) == VL_API_INVALID_FI)
399 : {
400 0 : clib_warning ("can't send memfd fd");
401 0 : return -1;
402 : }
403 :
404 31 : fd_flags |= SESSION_FD_F_MEMFD_SEGMENT;
405 : }
406 :
407 31 : m.segment_size = sp->ssvm_size;
408 31 : m.fd_flags = fd_flags;
409 31 : m.segment_handle = segment_handle;
410 31 : strncpy ((char *) m.segment_name, (char *) sp->name,
411 : sizeof (m.segment_name) - 1);
412 :
413 31 : app_wrk_send_ctrl_evt_fd (app_wrk, SESSION_CTRL_EVT_APP_ADD_SEGMENT, &m,
414 : sizeof (m), sp->fd);
415 :
416 31 : return 0;
417 : }
418 :
419 : static int
420 5 : mq_send_del_segment_cb (u32 app_wrk_index, u64 segment_handle)
421 : {
422 5 : session_app_del_segment_msg_t m = { 0 };
423 : vl_api_registration_t *reg;
424 : app_worker_t *app_wrk;
425 :
426 5 : app_wrk = app_worker_get (app_wrk_index);
427 5 : reg = vl_mem_api_client_index_to_registration (app_wrk->api_client_index);
428 5 : if (!reg)
429 : {
430 0 : clib_warning ("no registration: %u", app_wrk->api_client_index);
431 0 : return -1;
432 : }
433 :
434 5 : m.segment_handle = segment_handle;
435 :
436 5 : app_wrk_send_ctrl_evt (app_wrk, SESSION_CTRL_EVT_APP_DEL_SEGMENT, &m,
437 : sizeof (m));
438 :
439 5 : return 0;
440 : }
441 :
442 : static void
443 74 : mq_send_session_cleanup_cb (session_t * s, session_cleanup_ntf_t ntf)
444 : {
445 74 : session_cleanup_msg_t m = { 0 };
446 : app_worker_t *app_wrk;
447 :
448 : /* Propagate transport cleanup notifications only if app didn't close */
449 74 : if (ntf == SESSION_CLEANUP_TRANSPORT
450 37 : && s->session_state != SESSION_STATE_TRANSPORT_DELETED)
451 0 : return;
452 :
453 74 : app_wrk = app_worker_get_if_valid (s->app_wrk_index);
454 74 : if (!app_wrk)
455 0 : return;
456 :
457 74 : m.handle = session_handle (s);
458 74 : m.type = ntf;
459 :
460 74 : app_wrk_send_ctrl_evt (app_wrk, SESSION_CTRL_EVT_CLEANUP, &m, sizeof (m));
461 : }
462 :
463 : static int
464 172531 : mq_send_io_rx_event (session_t *s)
465 : {
466 : session_event_t *mq_evt;
467 : svm_msg_q_msg_t mq_msg;
468 : app_worker_t *app_wrk;
469 : svm_msg_q_t *mq;
470 :
471 172531 : if (svm_fifo_has_event (s->rx_fifo))
472 107342 : return 0;
473 :
474 65189 : app_wrk = app_worker_get (s->app_wrk_index);
475 65189 : mq = app_wrk->event_queue;
476 :
477 65189 : mq_msg = svm_msg_q_alloc_msg_w_ring (mq, SESSION_MQ_IO_EVT_RING);
478 65189 : mq_evt = svm_msg_q_msg_data (mq, &mq_msg);
479 :
480 65189 : mq_evt->event_type = SESSION_IO_EVT_RX;
481 65189 : mq_evt->session_index = s->rx_fifo->shr->client_session_index;
482 :
483 65189 : (void) svm_fifo_set_event (s->rx_fifo);
484 :
485 65189 : svm_msg_q_add_raw (mq, &mq_msg);
486 :
487 65189 : return 0;
488 : }
489 :
490 : static int
491 27296 : mq_send_io_tx_event (session_t *s)
492 : {
493 27296 : app_worker_t *app_wrk = app_worker_get (s->app_wrk_index);
494 27296 : svm_msg_q_t *mq = app_wrk->event_queue;
495 : session_event_t *mq_evt;
496 : svm_msg_q_msg_t mq_msg;
497 :
498 27296 : mq_msg = svm_msg_q_alloc_msg_w_ring (mq, SESSION_MQ_IO_EVT_RING);
499 27296 : mq_evt = svm_msg_q_msg_data (mq, &mq_msg);
500 :
501 27296 : mq_evt->event_type = SESSION_IO_EVT_TX;
502 27296 : mq_evt->session_index = s->tx_fifo->shr->client_session_index;
503 :
504 27296 : svm_msg_q_add_raw (mq, &mq_msg);
505 :
506 27296 : return 0;
507 : }
508 :
509 : static session_cb_vft_t session_mq_cb_vft = {
510 : .session_accept_callback = mq_send_session_accepted_cb,
511 : .session_disconnect_callback = mq_send_session_disconnected_cb,
512 : .session_connected_callback = mq_send_session_connected_cb,
513 : .session_reset_callback = mq_send_session_reset_cb,
514 : .session_migrate_callback = mq_send_session_migrate_cb,
515 : .session_cleanup_callback = mq_send_session_cleanup_cb,
516 : .add_segment_callback = mq_send_add_segment_cb,
517 : .del_segment_callback = mq_send_del_segment_cb,
518 : .builtin_app_rx_callback = mq_send_io_rx_event,
519 : .builtin_app_tx_callback = mq_send_io_tx_event,
520 : };
521 :
522 : static void
523 75 : vl_api_session_enable_disable_t_handler (vl_api_session_enable_disable_t * mp)
524 : {
525 : vl_api_session_enable_disable_reply_t *rmp;
526 75 : vlib_main_t *vm = vlib_get_main ();
527 75 : int rv = 0;
528 :
529 75 : vnet_session_enable_disable (vm, mp->is_enable);
530 75 : REPLY_MACRO (VL_API_SESSION_ENABLE_DISABLE_REPLY);
531 : }
532 :
533 : static void
534 0 : vl_api_session_sapi_enable_disable_t_handler (
535 : vl_api_session_sapi_enable_disable_t *mp)
536 : {
537 : vl_api_session_sapi_enable_disable_reply_t *rmp;
538 0 : int rv = 0;
539 :
540 0 : rv = appns_sapi_enable_disable (mp->is_enable);
541 0 : REPLY_MACRO (VL_API_SESSION_SAPI_ENABLE_DISABLE_REPLY);
542 : }
543 :
544 : static void
545 42 : vl_api_app_attach_t_handler (vl_api_app_attach_t * mp)
546 : {
547 42 : int rv = 0, *fds = 0, n_fds = 0, n_workers, i;
548 42 : fifo_segment_t *segp, *rx_mqs_seg = 0;
549 42 : vnet_app_attach_args_t _a, *a = &_a;
550 : vl_api_app_attach_reply_t *rmp;
551 42 : u8 fd_flags = 0, ctrl_thread;
552 : vl_api_registration_t *reg;
553 : svm_msg_q_t *rx_mq;
554 : application_t *app;
555 :
556 42 : reg = vl_api_client_index_to_registration (mp->client_index);
557 42 : if (!reg)
558 0 : return;
559 :
560 42 : n_workers = vlib_num_workers ();
561 42 : if (!session_main_is_enabled () || appns_sapi_enabled ())
562 : {
563 0 : rv = VNET_API_ERROR_FEATURE_DISABLED;
564 0 : goto done;
565 : }
566 : /* Only support binary api with socket transport */
567 42 : if (vl_api_registration_file_index (reg) == VL_API_INVALID_FI)
568 : {
569 0 : rv = VNET_API_ERROR_APP_UNSUPPORTED_CFG;
570 0 : goto done;
571 : }
572 :
573 : STATIC_ASSERT (sizeof (u64) * APP_OPTIONS_N_OPTIONS <=
574 : sizeof (mp->options),
575 : "Out of options, fix api message definition");
576 :
577 42 : clib_memset (a, 0, sizeof (*a));
578 42 : a->api_client_index = mp->client_index;
579 42 : a->options = mp->options;
580 42 : a->session_cb_vft = &session_mq_cb_vft;
581 42 : a->namespace_id = vl_api_from_api_to_new_vec (mp, &mp->namespace_id);
582 :
583 42 : if ((rv = vnet_application_attach (a)))
584 : {
585 0 : clib_warning ("attach returned: %U", format_session_error, rv);
586 0 : rv = VNET_API_ERROR_UNSPECIFIED;
587 0 : vec_free (a->namespace_id);
588 0 : goto done;
589 : }
590 42 : vec_free (a->namespace_id);
591 :
592 42 : vec_validate (fds, 3 /* segs + tx evtfd */ + n_workers);
593 :
594 : /* Send rx mqs segment */
595 42 : app = application_get (a->app_index);
596 42 : rx_mqs_seg = application_get_rx_mqs_segment (app);
597 :
598 42 : fd_flags |= SESSION_FD_F_VPP_MQ_SEGMENT;
599 42 : fds[n_fds] = rx_mqs_seg->ssvm.fd;
600 42 : n_fds += 1;
601 :
602 : /* Send fifo segment fd if needed */
603 42 : if (ssvm_type (a->segment) == SSVM_SEGMENT_MEMFD)
604 : {
605 42 : fd_flags |= SESSION_FD_F_MEMFD_SEGMENT;
606 42 : fds[n_fds] = a->segment->fd;
607 42 : n_fds += 1;
608 : }
609 42 : if (a->options[APP_OPTIONS_FLAGS] & APP_OPTIONS_FLAGS_EVT_MQ_USE_EVENTFD)
610 : {
611 0 : fd_flags |= SESSION_FD_F_MQ_EVENTFD;
612 0 : fds[n_fds] = svm_msg_q_get_eventfd (a->app_evt_q);
613 0 : n_fds += 1;
614 : }
615 :
616 42 : if (application_use_private_rx_mqs ())
617 : {
618 0 : fd_flags |= SESSION_FD_F_VPP_MQ_EVENTFD;
619 0 : for (i = 0; i < n_workers + 1; i++)
620 : {
621 0 : rx_mq = application_rx_mq_get (app, i);
622 0 : fds[n_fds] = svm_msg_q_get_eventfd (rx_mq);
623 0 : n_fds += 1;
624 : }
625 : }
626 :
627 42 : done:
628 : /* *INDENT-OFF* */
629 42 : REPLY_MACRO3 (
630 : VL_API_APP_ATTACH_REPLY,
631 : ((!rv) ? vec_len (((fifo_segment_t *) a->segment)->ssvm.name) : 0), ({
632 : if (!rv)
633 : {
634 : ctrl_thread = n_workers ? 1 : 0;
635 : segp = (fifo_segment_t *) a->segment;
636 : rmp->app_index = clib_host_to_net_u32 (a->app_index);
637 : rmp->app_mq = fifo_segment_msg_q_offset (segp, 0);
638 : rmp->vpp_ctrl_mq =
639 : fifo_segment_msg_q_offset (rx_mqs_seg, ctrl_thread);
640 : rmp->vpp_ctrl_mq_thread = ctrl_thread;
641 : rmp->n_fds = n_fds;
642 : rmp->fd_flags = fd_flags;
643 : if (vec_len (segp->ssvm.name))
644 : {
645 : vl_api_vec_to_api_string (segp->ssvm.name, &rmp->segment_name);
646 : }
647 : rmp->segment_size = segp->ssvm.ssvm_size;
648 : rmp->segment_handle = clib_host_to_net_u64 (a->segment_handle);
649 : }
650 : }));
651 : /* *INDENT-ON* */
652 :
653 42 : if (n_fds)
654 42 : session_send_fds (reg, fds, n_fds);
655 42 : vec_free (fds);
656 : }
657 :
658 : static void
659 11 : vl_api_app_worker_add_del_t_handler (vl_api_app_worker_add_del_t * mp)
660 : {
661 11 : int rv = 0, fds[SESSION_N_FD_TYPE], n_fds = 0;
662 : vl_api_app_worker_add_del_reply_t *rmp;
663 : vl_api_registration_t *reg;
664 : application_t *app;
665 11 : u8 fd_flags = 0;
666 :
667 11 : if (!session_main_is_enabled () || appns_sapi_enabled ())
668 : {
669 0 : rv = VNET_API_ERROR_FEATURE_DISABLED;
670 0 : goto done;
671 : }
672 :
673 11 : reg = vl_api_client_index_to_registration (mp->client_index);
674 11 : if (!reg)
675 0 : return;
676 :
677 11 : app = application_get_if_valid (clib_net_to_host_u32 (mp->app_index));
678 11 : if (!app)
679 : {
680 0 : rv = VNET_API_ERROR_INVALID_VALUE;
681 0 : goto done;
682 : }
683 :
684 22 : vnet_app_worker_add_del_args_t args = {
685 11 : .app_index = app->app_index,
686 11 : .wrk_map_index = clib_net_to_host_u32 (mp->wrk_index),
687 11 : .api_client_index = mp->client_index,
688 11 : .is_add = mp->is_add
689 : };
690 11 : rv = vnet_app_worker_add_del (&args);
691 11 : if (rv)
692 : {
693 0 : clib_warning ("app worker add/del returned: %U", format_session_error,
694 : rv);
695 0 : rv = VNET_API_ERROR_UNSPECIFIED;
696 0 : goto done;
697 : }
698 :
699 11 : if (!mp->is_add)
700 11 : goto done;
701 :
702 : /* Send fifo segment fd if needed */
703 0 : if (ssvm_type (args.segment) == SSVM_SEGMENT_MEMFD)
704 : {
705 0 : fd_flags |= SESSION_FD_F_MEMFD_SEGMENT;
706 0 : fds[n_fds] = args.segment->fd;
707 0 : n_fds += 1;
708 : }
709 0 : if (application_segment_manager_properties (app)->use_mq_eventfd)
710 : {
711 0 : fd_flags |= SESSION_FD_F_MQ_EVENTFD;
712 0 : fds[n_fds] = svm_msg_q_get_eventfd (args.evt_q);
713 0 : n_fds += 1;
714 : }
715 :
716 : /* *INDENT-OFF* */
717 0 : done:
718 11 : REPLY_MACRO3 (
719 : VL_API_APP_WORKER_ADD_DEL_REPLY,
720 : ((!rv && mp->is_add) ? vec_len (args.segment->name) : 0), ({
721 : rmp->is_add = mp->is_add;
722 : rmp->wrk_index = clib_host_to_net_u32 (args.wrk_map_index);
723 : rmp->segment_handle = clib_host_to_net_u64 (args.segment_handle);
724 : if (!rv && mp->is_add)
725 : {
726 : rmp->app_event_queue_address =
727 : fifo_segment_msg_q_offset ((fifo_segment_t *) args.segment, 0);
728 : rmp->n_fds = n_fds;
729 : rmp->fd_flags = fd_flags;
730 : if (vec_len (args.segment->name))
731 : {
732 : vl_api_vec_to_api_string (args.segment->name,
733 : &rmp->segment_name);
734 : }
735 : }
736 : }));
737 : /* *INDENT-ON* */
738 :
739 11 : if (n_fds)
740 0 : session_send_fds (reg, fds, n_fds);
741 : }
742 :
743 : static void
744 0 : vl_api_application_detach_t_handler (vl_api_application_detach_t * mp)
745 : {
746 : vl_api_application_detach_reply_t *rmp;
747 0 : int rv = VNET_API_ERROR_INVALID_VALUE_2;
748 0 : vnet_app_detach_args_t _a, *a = &_a;
749 : application_t *app;
750 :
751 0 : if (!session_main_is_enabled () || appns_sapi_enabled ())
752 : {
753 0 : rv = VNET_API_ERROR_FEATURE_DISABLED;
754 0 : goto done;
755 : }
756 :
757 0 : app = application_lookup (mp->client_index);
758 0 : if (app)
759 : {
760 0 : a->app_index = app->app_index;
761 0 : a->api_client_index = mp->client_index;
762 0 : rv = vnet_application_detach (a);
763 0 : if (rv)
764 : {
765 0 : clib_warning ("vnet_application_detach: %U", format_session_error,
766 : rv);
767 0 : rv = VNET_API_ERROR_UNSPECIFIED;
768 : }
769 : }
770 :
771 0 : done:
772 0 : REPLY_MACRO (VL_API_APPLICATION_DETACH_REPLY);
773 : }
774 :
775 : static void
776 0 : vl_api_app_namespace_add_del_t_handler (vl_api_app_namespace_add_del_t * mp)
777 : {
778 : vl_api_app_namespace_add_del_reply_t *rmp;
779 0 : u32 appns_index = 0;
780 0 : u8 *ns_id = 0;
781 0 : int rv = 0;
782 0 : if (session_main_is_enabled () == 0)
783 : {
784 0 : rv = VNET_API_ERROR_FEATURE_DISABLED;
785 0 : goto done;
786 : }
787 :
788 0 : ns_id = vl_api_from_api_to_new_vec (mp, &mp->namespace_id);
789 :
790 0 : vnet_app_namespace_add_del_args_t args = {
791 : .ns_id = ns_id,
792 : .sock_name = 0,
793 0 : .secret = clib_net_to_host_u64 (mp->secret),
794 0 : .sw_if_index = clib_net_to_host_u32 (mp->sw_if_index),
795 0 : .ip4_fib_id = clib_net_to_host_u32 (mp->ip4_fib_id),
796 0 : .ip6_fib_id = clib_net_to_host_u32 (mp->ip6_fib_id),
797 : .is_add = 1
798 : };
799 0 : rv = vnet_app_namespace_add_del (&args);
800 0 : if (!rv)
801 : {
802 0 : appns_index = app_namespace_index_from_id (ns_id);
803 0 : if (appns_index == APP_NAMESPACE_INVALID_INDEX)
804 : {
805 0 : clib_warning ("app ns lookup failed");
806 0 : rv = VNET_API_ERROR_UNSPECIFIED;
807 : }
808 : }
809 0 : vec_free (ns_id);
810 :
811 : /* *INDENT-OFF* */
812 0 : done:
813 0 : REPLY_MACRO2 (VL_API_APP_NAMESPACE_ADD_DEL_REPLY, ({
814 : if (!rv)
815 : rmp->appns_index = clib_host_to_net_u32 (appns_index);
816 : }));
817 : /* *INDENT-ON* */
818 : }
819 :
820 : static void
821 0 : vl_api_app_namespace_add_del_v2_t_handler (
822 : vl_api_app_namespace_add_del_v2_t *mp)
823 : {
824 : vl_api_app_namespace_add_del_v2_reply_t *rmp;
825 0 : u8 *ns_id = 0;
826 0 : u32 appns_index = 0;
827 0 : int rv = 0;
828 :
829 0 : if (session_main_is_enabled () == 0)
830 : {
831 0 : rv = VNET_API_ERROR_FEATURE_DISABLED;
832 0 : goto done;
833 : }
834 :
835 0 : mp->namespace_id[sizeof (mp->namespace_id) - 1] = 0;
836 0 : ns_id = format (0, "%s", &mp->namespace_id);
837 :
838 0 : vnet_app_namespace_add_del_args_t args = {
839 : .ns_id = ns_id,
840 : .sock_name = 0,
841 0 : .secret = clib_net_to_host_u64 (mp->secret),
842 0 : .sw_if_index = clib_net_to_host_u32 (mp->sw_if_index),
843 0 : .ip4_fib_id = clib_net_to_host_u32 (mp->ip4_fib_id),
844 0 : .ip6_fib_id = clib_net_to_host_u32 (mp->ip6_fib_id),
845 : .is_add = 1
846 : };
847 0 : rv = vnet_app_namespace_add_del (&args);
848 0 : if (!rv)
849 : {
850 0 : appns_index = app_namespace_index_from_id (ns_id);
851 0 : if (appns_index == APP_NAMESPACE_INVALID_INDEX)
852 : {
853 0 : clib_warning ("app ns lookup failed id:%s", ns_id);
854 0 : rv = VNET_API_ERROR_UNSPECIFIED;
855 : }
856 : }
857 0 : vec_free (ns_id);
858 :
859 0 : done:
860 0 : REPLY_MACRO2 (VL_API_APP_NAMESPACE_ADD_DEL_V2_REPLY, ({
861 : if (!rv)
862 : rmp->appns_index = clib_host_to_net_u32 (appns_index);
863 : }));
864 : }
865 :
866 : static void
867 42 : vl_api_app_namespace_add_del_v4_t_handler (
868 : vl_api_app_namespace_add_del_v4_t *mp)
869 : {
870 : vl_api_app_namespace_add_del_v4_reply_t *rmp;
871 42 : u8 *ns_id = 0, *sock_name = 0;
872 42 : u32 appns_index = 0;
873 42 : int rv = 0;
874 42 : if (session_main_is_enabled () == 0)
875 : {
876 0 : rv = VNET_API_ERROR_FEATURE_DISABLED;
877 0 : goto done;
878 : }
879 42 : mp->namespace_id[sizeof (mp->namespace_id) - 1] = 0;
880 42 : ns_id = format (0, "%s", &mp->namespace_id);
881 42 : sock_name = vl_api_from_api_to_new_vec (mp, &mp->sock_name);
882 210 : vnet_app_namespace_add_del_args_t args = {
883 : .ns_id = ns_id,
884 : .sock_name = sock_name,
885 42 : .secret = clib_net_to_host_u64 (mp->secret),
886 42 : .sw_if_index = clib_net_to_host_u32 (mp->sw_if_index),
887 42 : .ip4_fib_id = clib_net_to_host_u32 (mp->ip4_fib_id),
888 42 : .ip6_fib_id = clib_net_to_host_u32 (mp->ip6_fib_id),
889 42 : .is_add = mp->is_add,
890 : };
891 42 : rv = vnet_app_namespace_add_del (&args);
892 42 : if (!rv && mp->is_add)
893 : {
894 42 : appns_index = app_namespace_index_from_id (ns_id);
895 42 : if (appns_index == APP_NAMESPACE_INVALID_INDEX)
896 : {
897 0 : clib_warning ("app ns lookup failed id:%s", ns_id);
898 0 : rv = VNET_API_ERROR_UNSPECIFIED;
899 : }
900 : }
901 42 : vec_free (ns_id);
902 42 : vec_free (sock_name);
903 42 : done:
904 42 : REPLY_MACRO2 (VL_API_APP_NAMESPACE_ADD_DEL_V4_REPLY, ({
905 : if (!rv)
906 : rmp->appns_index = clib_host_to_net_u32 (appns_index);
907 : }));
908 : }
909 :
910 : static void
911 0 : vl_api_app_namespace_add_del_v3_t_handler (
912 : vl_api_app_namespace_add_del_v3_t *mp)
913 : {
914 : vl_api_app_namespace_add_del_v3_reply_t *rmp;
915 0 : u8 *ns_id = 0, *sock_name = 0, *api_sock_name = 0;
916 0 : u32 appns_index = 0;
917 0 : int rv = 0;
918 0 : if (session_main_is_enabled () == 0)
919 : {
920 0 : rv = VNET_API_ERROR_FEATURE_DISABLED;
921 0 : goto done;
922 : }
923 0 : mp->namespace_id[sizeof (mp->namespace_id) - 1] = 0;
924 0 : ns_id = format (0, "%s", &mp->namespace_id);
925 0 : api_sock_name = vl_api_from_api_to_new_vec (mp, &mp->sock_name);
926 0 : mp->netns[sizeof (mp->netns) - 1] = 0;
927 0 : if (strlen ((char *) mp->netns) != 0)
928 : {
929 0 : sock_name =
930 0 : format (0, "abstract:%v,netns_name=%s", api_sock_name, &mp->netns);
931 : }
932 : else
933 : {
934 0 : sock_name = api_sock_name;
935 0 : api_sock_name = 0; // for vec_free
936 : }
937 :
938 0 : vnet_app_namespace_add_del_args_t args = {
939 : .ns_id = ns_id,
940 : .sock_name = sock_name,
941 0 : .secret = clib_net_to_host_u64 (mp->secret),
942 0 : .sw_if_index = clib_net_to_host_u32 (mp->sw_if_index),
943 0 : .ip4_fib_id = clib_net_to_host_u32 (mp->ip4_fib_id),
944 0 : .ip6_fib_id = clib_net_to_host_u32 (mp->ip6_fib_id),
945 0 : .is_add = mp->is_add,
946 : };
947 0 : rv = vnet_app_namespace_add_del (&args);
948 0 : if (!rv && mp->is_add)
949 : {
950 0 : appns_index = app_namespace_index_from_id (ns_id);
951 0 : if (appns_index == APP_NAMESPACE_INVALID_INDEX)
952 : {
953 0 : clib_warning ("app ns lookup failed id:%s", ns_id);
954 0 : rv = VNET_API_ERROR_UNSPECIFIED;
955 : }
956 : }
957 0 : vec_free (ns_id);
958 0 : vec_free (sock_name);
959 0 : vec_free (api_sock_name);
960 0 : done:
961 0 : REPLY_MACRO2 (VL_API_APP_NAMESPACE_ADD_DEL_V3_REPLY, ({
962 : if (!rv)
963 : rmp->appns_index = clib_host_to_net_u32 (appns_index);
964 : }));
965 : }
966 :
967 : static void
968 0 : vl_api_session_rule_add_del_t_handler (vl_api_session_rule_add_del_t * mp)
969 : {
970 : vl_api_session_rule_add_del_reply_t *rmp;
971 : session_rule_add_del_args_t args;
972 0 : session_rule_table_add_del_args_t *table_args = &args.table_args;
973 0 : int rv = 0;
974 :
975 0 : clib_memset (&args, 0, sizeof (args));
976 :
977 0 : ip_prefix_decode (&mp->lcl, &table_args->lcl);
978 0 : ip_prefix_decode (&mp->rmt, &table_args->rmt);
979 :
980 0 : table_args->lcl_port = mp->lcl_port;
981 0 : table_args->rmt_port = mp->rmt_port;
982 0 : table_args->action_index = clib_net_to_host_u32 (mp->action_index);
983 0 : table_args->is_add = mp->is_add;
984 0 : mp->tag[sizeof (mp->tag) - 1] = 0;
985 0 : table_args->tag = format (0, "%s", mp->tag);
986 0 : args.appns_index = clib_net_to_host_u32 (mp->appns_index);
987 0 : args.scope = mp->scope;
988 0 : args.transport_proto =
989 0 : api_session_transport_proto_decode (&mp->transport_proto) ==
990 0 : TRANSPORT_PROTO_UDP ? 1 : 0;
991 :
992 0 : rv = vnet_session_rule_add_del (&args);
993 0 : if (rv)
994 : {
995 0 : clib_warning ("rule add del returned: %U", format_session_error, rv);
996 0 : rv = VNET_API_ERROR_UNSPECIFIED;
997 : }
998 0 : vec_free (table_args->tag);
999 0 : REPLY_MACRO (VL_API_SESSION_RULE_ADD_DEL_REPLY);
1000 : }
1001 :
1002 : static void
1003 0 : send_session_rule_details4 (mma_rule_16_t * rule, u8 is_local,
1004 : u8 transport_proto, u32 appns_index, u8 * tag,
1005 : vl_api_registration_t * reg, u32 context)
1006 : {
1007 0 : vl_api_session_rules_details_t *rmp = 0;
1008 0 : session_mask_or_match_4_t *match =
1009 : (session_mask_or_match_4_t *) & rule->match;
1010 0 : session_mask_or_match_4_t *mask =
1011 : (session_mask_or_match_4_t *) & rule->mask;
1012 : fib_prefix_t lcl, rmt;
1013 :
1014 0 : rmp = vl_msg_api_alloc (sizeof (*rmp));
1015 0 : clib_memset (rmp, 0, sizeof (*rmp));
1016 0 : rmp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_SESSION_RULES_DETAILS);
1017 0 : rmp->context = context;
1018 :
1019 0 : clib_memset (&lcl, 0, sizeof (lcl));
1020 0 : clib_memset (&rmt, 0, sizeof (rmt));
1021 0 : ip_set (&lcl.fp_addr, &match->lcl_ip, 1);
1022 0 : ip_set (&rmt.fp_addr, &match->rmt_ip, 1);
1023 0 : lcl.fp_len = ip4_mask_to_preflen (&mask->lcl_ip);
1024 0 : rmt.fp_len = ip4_mask_to_preflen (&mask->rmt_ip);
1025 :
1026 0 : ip_prefix_encode (&lcl, &rmp->lcl);
1027 0 : ip_prefix_encode (&rmt, &rmp->rmt);
1028 0 : rmp->lcl_port = match->lcl_port;
1029 0 : rmp->rmt_port = match->rmt_port;
1030 0 : rmp->action_index = clib_host_to_net_u32 (rule->action_index);
1031 0 : rmp->scope =
1032 0 : is_local ? SESSION_RULE_SCOPE_API_LOCAL : SESSION_RULE_SCOPE_API_GLOBAL;
1033 0 : rmp->transport_proto = api_session_transport_proto_encode (transport_proto);
1034 0 : rmp->appns_index = clib_host_to_net_u32 (appns_index);
1035 0 : if (tag)
1036 : {
1037 0 : clib_memcpy_fast (rmp->tag, tag, vec_len (tag));
1038 0 : rmp->tag[vec_len (tag)] = 0;
1039 : }
1040 :
1041 0 : vl_api_send_msg (reg, (u8 *) rmp);
1042 0 : }
1043 :
1044 : static void
1045 0 : send_session_rule_details6 (mma_rule_40_t * rule, u8 is_local,
1046 : u8 transport_proto, u32 appns_index, u8 * tag,
1047 : vl_api_registration_t * reg, u32 context)
1048 : {
1049 0 : vl_api_session_rules_details_t *rmp = 0;
1050 0 : session_mask_or_match_6_t *match =
1051 : (session_mask_or_match_6_t *) & rule->match;
1052 0 : session_mask_or_match_6_t *mask =
1053 : (session_mask_or_match_6_t *) & rule->mask;
1054 : fib_prefix_t lcl, rmt;
1055 :
1056 0 : rmp = vl_msg_api_alloc (sizeof (*rmp));
1057 0 : clib_memset (rmp, 0, sizeof (*rmp));
1058 0 : rmp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_SESSION_RULES_DETAILS);
1059 0 : rmp->context = context;
1060 :
1061 0 : clib_memset (&lcl, 0, sizeof (lcl));
1062 0 : clib_memset (&rmt, 0, sizeof (rmt));
1063 0 : ip_set (&lcl.fp_addr, &match->lcl_ip, 0);
1064 0 : ip_set (&rmt.fp_addr, &match->rmt_ip, 0);
1065 0 : lcl.fp_len = ip6_mask_to_preflen (&mask->lcl_ip);
1066 0 : rmt.fp_len = ip6_mask_to_preflen (&mask->rmt_ip);
1067 :
1068 0 : ip_prefix_encode (&lcl, &rmp->lcl);
1069 0 : ip_prefix_encode (&rmt, &rmp->rmt);
1070 0 : rmp->lcl_port = match->lcl_port;
1071 0 : rmp->rmt_port = match->rmt_port;
1072 0 : rmp->action_index = clib_host_to_net_u32 (rule->action_index);
1073 0 : rmp->scope =
1074 0 : is_local ? SESSION_RULE_SCOPE_API_LOCAL : SESSION_RULE_SCOPE_API_GLOBAL;
1075 0 : rmp->transport_proto = api_session_transport_proto_encode (transport_proto);
1076 0 : rmp->appns_index = clib_host_to_net_u32 (appns_index);
1077 0 : if (tag)
1078 : {
1079 0 : clib_memcpy_fast (rmp->tag, tag, vec_len (tag));
1080 0 : rmp->tag[vec_len (tag)] = 0;
1081 : }
1082 :
1083 0 : vl_api_send_msg (reg, (u8 *) rmp);
1084 0 : }
1085 :
1086 : static void
1087 0 : send_session_rules_table_details (session_rules_table_t * srt, u8 fib_proto,
1088 : u8 tp, u8 is_local, u32 appns_index,
1089 : vl_api_registration_t * reg, u32 context)
1090 : {
1091 : mma_rule_16_t *rule16;
1092 : mma_rule_40_t *rule40;
1093 : mma_rules_table_16_t *srt16;
1094 : mma_rules_table_40_t *srt40;
1095 : u32 ri;
1096 :
1097 0 : if (is_local || fib_proto == FIB_PROTOCOL_IP4)
1098 : {
1099 0 : u8 *tag = 0;
1100 : /* *INDENT-OFF* */
1101 0 : srt16 = &srt->session_rules_tables_16;
1102 0 : pool_foreach (rule16, srt16->rules) {
1103 0 : ri = mma_rules_table_rule_index_16 (srt16, rule16);
1104 0 : tag = session_rules_table_rule_tag (srt, ri, 1);
1105 0 : send_session_rule_details4 (rule16, is_local, tp, appns_index, tag,
1106 : reg, context);
1107 : }
1108 : /* *INDENT-ON* */
1109 : }
1110 0 : if (is_local || fib_proto == FIB_PROTOCOL_IP6)
1111 : {
1112 0 : u8 *tag = 0;
1113 : /* *INDENT-OFF* */
1114 0 : srt40 = &srt->session_rules_tables_40;
1115 0 : pool_foreach (rule40, srt40->rules) {
1116 0 : ri = mma_rules_table_rule_index_40 (srt40, rule40);
1117 0 : tag = session_rules_table_rule_tag (srt, ri, 1);
1118 0 : send_session_rule_details6 (rule40, is_local, tp, appns_index, tag,
1119 : reg, context);
1120 : }
1121 : /* *INDENT-ON* */
1122 : }
1123 0 : }
1124 :
1125 : static void
1126 0 : vl_api_session_rules_dump_t_handler (vl_api_session_rules_dump_t * mp)
1127 : {
1128 : vl_api_registration_t *reg;
1129 : session_table_t *st;
1130 : u8 tp;
1131 :
1132 0 : reg = vl_api_client_index_to_registration (mp->client_index);
1133 0 : if (!reg)
1134 0 : return;
1135 :
1136 : /* *INDENT-OFF* */
1137 0 : session_table_foreach (st, ({
1138 : for (tp = 0; tp < TRANSPORT_N_PROTOS; tp++)
1139 : {
1140 : send_session_rules_table_details (&st->session_rules[tp],
1141 : st->active_fib_proto, tp,
1142 : st->is_local, st->appns_index, reg,
1143 : mp->context);
1144 : }
1145 : }));
1146 : /* *INDENT-ON* */
1147 : }
1148 :
1149 : static void
1150 2 : vl_api_app_add_cert_key_pair_t_handler (vl_api_app_add_cert_key_pair_t * mp)
1151 : {
1152 : vl_api_app_add_cert_key_pair_reply_t *rmp;
1153 2 : vnet_app_add_cert_key_pair_args_t _a, *a = &_a;
1154 : u32 certkey_len, key_len, cert_len;
1155 2 : int rv = 0;
1156 2 : if (session_main_is_enabled () == 0)
1157 : {
1158 0 : rv = VNET_API_ERROR_FEATURE_DISABLED;
1159 0 : goto done;
1160 : }
1161 :
1162 2 : cert_len = clib_net_to_host_u16 (mp->cert_len);
1163 2 : if (cert_len > 10000)
1164 : {
1165 0 : rv = VNET_API_ERROR_INVALID_VALUE;
1166 0 : goto done;
1167 : }
1168 :
1169 2 : certkey_len = clib_net_to_host_u16 (mp->certkey_len);
1170 2 : if (certkey_len < cert_len)
1171 : {
1172 0 : rv = VNET_API_ERROR_INVALID_VALUE;
1173 0 : goto done;
1174 : }
1175 :
1176 2 : key_len = certkey_len - cert_len;
1177 2 : if (key_len > 10000)
1178 : {
1179 0 : rv = VNET_API_ERROR_INVALID_VALUE;
1180 0 : goto done;
1181 : }
1182 :
1183 2 : clib_memset (a, 0, sizeof (*a));
1184 2 : a->cert = mp->certkey;
1185 2 : a->key = mp->certkey + cert_len;
1186 2 : a->cert_len = cert_len;
1187 2 : a->key_len = key_len;
1188 2 : rv = vnet_app_add_cert_key_pair (a);
1189 :
1190 2 : done:
1191 : /* *INDENT-OFF* */
1192 2 : REPLY_MACRO2 (VL_API_APP_ADD_CERT_KEY_PAIR_REPLY, ({
1193 : if (!rv)
1194 : rmp->index = clib_host_to_net_u32 (a->index);
1195 : }));
1196 : /* *INDENT-ON* */
1197 : }
1198 :
1199 : static void
1200 0 : vl_api_app_del_cert_key_pair_t_handler (vl_api_app_del_cert_key_pair_t * mp)
1201 : {
1202 : vl_api_app_del_cert_key_pair_reply_t *rmp;
1203 : u32 ckpair_index;
1204 0 : int rv = 0;
1205 0 : if (session_main_is_enabled () == 0)
1206 : {
1207 0 : rv = VNET_API_ERROR_FEATURE_DISABLED;
1208 0 : goto done;
1209 : }
1210 0 : ckpair_index = clib_net_to_host_u32 (mp->index);
1211 0 : rv = vnet_app_del_cert_key_pair (ckpair_index);
1212 0 : if (rv)
1213 : {
1214 0 : clib_warning ("vnet_app_del_cert_key_pair: %U", format_session_error,
1215 : rv);
1216 0 : rv = VNET_API_ERROR_UNSPECIFIED;
1217 : }
1218 :
1219 0 : done:
1220 0 : REPLY_MACRO (VL_API_APP_DEL_CERT_KEY_PAIR_REPLY);
1221 : }
1222 :
1223 : static clib_error_t *
1224 1241 : application_reaper_cb (u32 client_index)
1225 : {
1226 1241 : application_t *app = application_lookup (client_index);
1227 1241 : vnet_app_detach_args_t _a, *a = &_a;
1228 1241 : if (app)
1229 : {
1230 0 : a->app_index = app->app_index;
1231 0 : a->api_client_index = client_index;
1232 0 : vnet_application_detach (a);
1233 : }
1234 1241 : return 0;
1235 : }
1236 :
1237 575 : VL_MSG_API_REAPER_FUNCTION (application_reaper_cb);
1238 :
1239 : /*
1240 : * Socket api functions
1241 : */
1242 :
1243 : static int
1244 9 : mq_send_add_segment_sapi_cb (u32 app_wrk_index, u64 segment_handle)
1245 : {
1246 9 : session_app_add_segment_msg_t m = { 0 };
1247 : app_worker_t *app_wrk;
1248 : fifo_segment_t *fs;
1249 : ssvm_private_t *sp;
1250 9 : u8 fd_flags = 0;
1251 :
1252 9 : app_wrk = app_worker_get (app_wrk_index);
1253 :
1254 9 : fs = segment_manager_get_segment_w_handle (segment_handle);
1255 9 : sp = &fs->ssvm;
1256 9 : ASSERT (ssvm_type (sp) == SSVM_SEGMENT_MEMFD);
1257 :
1258 9 : fd_flags |= SESSION_FD_F_MEMFD_SEGMENT;
1259 :
1260 9 : m.segment_size = sp->ssvm_size;
1261 9 : m.fd_flags = fd_flags;
1262 9 : m.segment_handle = segment_handle;
1263 9 : strncpy ((char *) m.segment_name, (char *) sp->name,
1264 : sizeof (m.segment_name) - 1);
1265 :
1266 9 : app_wrk_send_ctrl_evt_fd (app_wrk, SESSION_CTRL_EVT_APP_ADD_SEGMENT, &m,
1267 : sizeof (m), sp->fd);
1268 :
1269 9 : return 0;
1270 : }
1271 :
1272 : static int
1273 1 : mq_send_del_segment_sapi_cb (u32 app_wrk_index, u64 segment_handle)
1274 : {
1275 1 : session_app_del_segment_msg_t m = { 0 };
1276 : app_worker_t *app_wrk;
1277 :
1278 1 : app_wrk = app_worker_get (app_wrk_index);
1279 :
1280 1 : m.segment_handle = segment_handle;
1281 :
1282 1 : app_wrk_send_ctrl_evt (app_wrk, SESSION_CTRL_EVT_APP_DEL_SEGMENT, &m,
1283 : sizeof (m));
1284 :
1285 1 : return 0;
1286 : }
1287 :
1288 : static session_cb_vft_t session_mq_sapi_cb_vft = {
1289 : .session_accept_callback = mq_send_session_accepted_cb,
1290 : .session_disconnect_callback = mq_send_session_disconnected_cb,
1291 : .session_connected_callback = mq_send_session_connected_cb,
1292 : .session_reset_callback = mq_send_session_reset_cb,
1293 : .session_migrate_callback = mq_send_session_migrate_cb,
1294 : .session_cleanup_callback = mq_send_session_cleanup_cb,
1295 : .add_segment_callback = mq_send_add_segment_sapi_cb,
1296 : .del_segment_callback = mq_send_del_segment_sapi_cb,
1297 : .builtin_app_rx_callback = mq_send_io_rx_event,
1298 : .builtin_app_tx_callback = mq_send_io_tx_event,
1299 : };
1300 :
1301 : static void
1302 14 : session_api_attach_handler (app_namespace_t * app_ns, clib_socket_t * cs,
1303 : app_sapi_attach_msg_t * mp)
1304 : {
1305 14 : int rv = 0, *fds = 0, n_fds = 0, i, n_workers;
1306 14 : vnet_app_attach_args_t _a, *a = &_a;
1307 : app_sapi_attach_reply_msg_t *rmp;
1308 14 : u8 fd_flags = 0, ctrl_thread;
1309 : app_ns_api_handle_t *handle;
1310 : fifo_segment_t *rx_mqs_seg;
1311 14 : app_sapi_msg_t msg = { 0 };
1312 : app_worker_t *app_wrk;
1313 : application_t *app;
1314 : svm_msg_q_t *rx_mq;
1315 :
1316 : /* Make sure name is null terminated */
1317 14 : mp->name[63] = 0;
1318 :
1319 14 : clib_memset (a, 0, sizeof (*a));
1320 14 : a->api_client_index = appns_sapi_socket_handle (app_ns, cs);
1321 14 : a->name = format (0, "%s", (char *) mp->name);
1322 14 : a->options = mp->options;
1323 14 : a->session_cb_vft = &session_mq_sapi_cb_vft;
1324 14 : a->use_sock_api = 1;
1325 14 : a->options[APP_OPTIONS_NAMESPACE] = app_namespace_index (app_ns);
1326 :
1327 14 : if ((rv = vnet_application_attach (a)))
1328 : {
1329 0 : clib_warning ("attach returned: %d", rv);
1330 0 : goto done;
1331 : }
1332 :
1333 14 : n_workers = vlib_num_workers ();
1334 14 : vec_validate (fds, 3 /* segs + tx evtfd */ + n_workers);
1335 :
1336 : /* Send event queues segment */
1337 14 : app = application_get (a->app_index);
1338 14 : rx_mqs_seg = application_get_rx_mqs_segment (app);
1339 :
1340 14 : fd_flags |= SESSION_FD_F_VPP_MQ_SEGMENT;
1341 14 : fds[n_fds] = rx_mqs_seg->ssvm.fd;
1342 14 : n_fds += 1;
1343 :
1344 : /* Send fifo segment fd if needed */
1345 14 : if (ssvm_type (a->segment) == SSVM_SEGMENT_MEMFD)
1346 : {
1347 14 : fd_flags |= SESSION_FD_F_MEMFD_SEGMENT;
1348 14 : fds[n_fds] = a->segment->fd;
1349 14 : n_fds += 1;
1350 : }
1351 14 : if (a->options[APP_OPTIONS_FLAGS] & APP_OPTIONS_FLAGS_EVT_MQ_USE_EVENTFD)
1352 : {
1353 0 : fd_flags |= SESSION_FD_F_MQ_EVENTFD;
1354 0 : fds[n_fds] = svm_msg_q_get_eventfd (a->app_evt_q);
1355 0 : n_fds += 1;
1356 : }
1357 :
1358 14 : if (application_use_private_rx_mqs ())
1359 : {
1360 4 : fd_flags |= SESSION_FD_F_VPP_MQ_EVENTFD;
1361 8 : for (i = 0; i < n_workers + 1; i++)
1362 : {
1363 4 : rx_mq = application_rx_mq_get (app, i);
1364 4 : fds[n_fds] = svm_msg_q_get_eventfd (rx_mq);
1365 4 : n_fds += 1;
1366 : }
1367 : }
1368 :
1369 14 : done:
1370 :
1371 14 : msg.type = APP_SAPI_MSG_TYPE_ATTACH_REPLY;
1372 14 : rmp = &msg.attach_reply;
1373 14 : rmp->retval = rv;
1374 14 : if (!rv)
1375 : {
1376 14 : ctrl_thread = n_workers ? 1 : 0;
1377 14 : rmp->app_index = a->app_index;
1378 14 : rmp->app_mq =
1379 14 : fifo_segment_msg_q_offset ((fifo_segment_t *) a->segment, 0);
1380 14 : rmp->vpp_ctrl_mq = fifo_segment_msg_q_offset (rx_mqs_seg, ctrl_thread);
1381 14 : rmp->vpp_ctrl_mq_thread = ctrl_thread;
1382 14 : rmp->n_fds = n_fds;
1383 14 : rmp->fd_flags = fd_flags;
1384 : /* No segment name and size since we only support memfds
1385 : * in this configuration */
1386 14 : rmp->segment_handle = a->segment_handle;
1387 14 : rmp->api_client_handle = a->api_client_index;
1388 :
1389 : /* Update app index for socket */
1390 14 : handle = (app_ns_api_handle_t *) & cs->private_data;
1391 14 : app_wrk = application_get_worker (app, 0);
1392 14 : handle->aah_app_wrk_index = app_wrk->wrk_index;
1393 : }
1394 :
1395 14 : clib_socket_sendmsg (cs, &msg, sizeof (msg), fds, n_fds);
1396 14 : vec_free (a->name);
1397 14 : vec_free (fds);
1398 14 : }
1399 :
1400 : void
1401 14 : sapi_socket_close_w_handle (u32 api_handle)
1402 : {
1403 14 : app_namespace_t *app_ns = app_namespace_get (api_handle >> 16);
1404 14 : u16 sock_index = api_handle & 0xffff;
1405 : app_ns_api_handle_t *handle;
1406 : clib_socket_t *cs;
1407 : clib_file_t *cf;
1408 :
1409 14 : cs = appns_sapi_get_socket (app_ns, sock_index);
1410 14 : if (!cs)
1411 0 : return;
1412 :
1413 14 : handle = (app_ns_api_handle_t *) & cs->private_data;
1414 14 : cf = clib_file_get (&file_main, handle->aah_file_index);
1415 14 : clib_file_del (&file_main, cf);
1416 :
1417 14 : clib_socket_close (cs);
1418 14 : appns_sapi_free_socket (app_ns, cs);
1419 : }
1420 :
1421 : static void
1422 2 : sapi_add_del_worker_handler (app_namespace_t * app_ns,
1423 : clib_socket_t * cs,
1424 : app_sapi_worker_add_del_msg_t * mp)
1425 : {
1426 2 : int rv = 0, fds[SESSION_N_FD_TYPE], n_fds = 0;
1427 : app_sapi_worker_add_del_reply_msg_t *rmp;
1428 : app_ns_api_handle_t *handle;
1429 2 : app_sapi_msg_t msg = { 0 };
1430 : app_worker_t *app_wrk;
1431 2 : u32 sapi_handle = -1;
1432 : application_t *app;
1433 2 : u8 fd_flags = 0;
1434 :
1435 2 : app = application_get_if_valid (mp->app_index);
1436 2 : if (!app)
1437 : {
1438 0 : rv = SESSION_E_INVALID;
1439 0 : goto done;
1440 : }
1441 :
1442 2 : sapi_handle = appns_sapi_socket_handle (app_ns, cs);
1443 :
1444 2 : vnet_app_worker_add_del_args_t args = {
1445 2 : .app_index = app->app_index,
1446 2 : .wrk_map_index = mp->wrk_index,
1447 : .api_client_index = sapi_handle,
1448 2 : .is_add = mp->is_add
1449 : };
1450 2 : rv = vnet_app_worker_add_del (&args);
1451 2 : if (rv)
1452 : {
1453 0 : clib_warning ("app worker add/del returned: %U", format_session_error,
1454 : rv);
1455 0 : goto done;
1456 : }
1457 :
1458 2 : if (!mp->is_add)
1459 2 : goto done;
1460 :
1461 : /* Send fifo segment fd if needed */
1462 0 : if (ssvm_type (args.segment) == SSVM_SEGMENT_MEMFD)
1463 : {
1464 0 : fd_flags |= SESSION_FD_F_MEMFD_SEGMENT;
1465 0 : fds[n_fds] = args.segment->fd;
1466 0 : n_fds += 1;
1467 : }
1468 0 : if (application_segment_manager_properties (app)->use_mq_eventfd)
1469 : {
1470 0 : fd_flags |= SESSION_FD_F_MQ_EVENTFD;
1471 0 : fds[n_fds] = svm_msg_q_get_eventfd (args.evt_q);
1472 0 : n_fds += 1;
1473 : }
1474 :
1475 0 : done:
1476 :
1477 2 : msg.type = APP_SAPI_MSG_TYPE_ADD_DEL_WORKER_REPLY;
1478 2 : rmp = &msg.worker_add_del_reply;
1479 2 : rmp->retval = rv;
1480 2 : rmp->is_add = mp->is_add;
1481 2 : rmp->api_client_handle = sapi_handle;
1482 2 : rmp->wrk_index = args.wrk_map_index;
1483 2 : rmp->segment_handle = args.segment_handle;
1484 2 : if (!rv && mp->is_add)
1485 : {
1486 : /* No segment name and size. This supports only memfds */
1487 0 : rmp->app_event_queue_address =
1488 0 : fifo_segment_msg_q_offset ((fifo_segment_t *) args.segment, 0);
1489 0 : rmp->n_fds = n_fds;
1490 0 : rmp->fd_flags = fd_flags;
1491 :
1492 : /* Update app index for socket */
1493 0 : handle = (app_ns_api_handle_t *) & cs->private_data;
1494 0 : app_wrk = application_get_worker (app, args.wrk_map_index);
1495 0 : handle->aah_app_wrk_index = app_wrk->wrk_index;
1496 : }
1497 :
1498 2 : clib_socket_sendmsg (cs, &msg, sizeof (msg), fds, n_fds);
1499 2 : }
1500 :
1501 : /* This is a workaround for the case when session layer starts reading
1502 : * the socket before the client actualy sends the data
1503 : */
1504 : static clib_error_t *
1505 8 : sapi_socket_receive_wait (clib_socket_t *cs, u8 *msg, u32 msg_len)
1506 : {
1507 : clib_error_t *err;
1508 8 : int n_tries = 5;
1509 :
1510 : while (1)
1511 : {
1512 8 : err = clib_socket_recvmsg (cs, msg, msg_len, 0, 0);
1513 8 : if (!err)
1514 8 : break;
1515 :
1516 0 : if (!n_tries)
1517 0 : return err;
1518 :
1519 0 : n_tries--;
1520 0 : usleep (1);
1521 : }
1522 :
1523 8 : return err;
1524 : }
1525 :
1526 : static void
1527 12 : sapi_add_del_cert_key_handler (app_namespace_t *app_ns, clib_socket_t *cs,
1528 : app_sapi_cert_key_add_del_msg_t *mp)
1529 : {
1530 12 : vnet_app_add_cert_key_pair_args_t _a, *a = &_a;
1531 : app_sapi_cert_key_add_del_reply_msg_t *rmp;
1532 12 : app_sapi_msg_t msg = { 0 };
1533 12 : int rv = 0;
1534 :
1535 12 : if (mp->is_add)
1536 : {
1537 8 : const u32 max_certkey_len = 2e4, max_cert_len = 1e4, max_key_len = 1e4;
1538 : clib_error_t *err;
1539 8 : u8 *certkey = 0;
1540 : u32 key_len;
1541 :
1542 8 : if (mp->certkey_len > max_certkey_len)
1543 : {
1544 0 : rv = SESSION_E_INVALID;
1545 0 : goto send_reply;
1546 : }
1547 :
1548 8 : vec_validate (certkey, mp->certkey_len - 1);
1549 :
1550 8 : err = sapi_socket_receive_wait (cs, certkey, mp->certkey_len);
1551 8 : if (err)
1552 : {
1553 0 : clib_error_report (err);
1554 0 : rv = SESSION_E_INVALID;
1555 0 : goto send_reply;
1556 : }
1557 :
1558 8 : if (mp->cert_len > max_cert_len)
1559 : {
1560 0 : rv = SESSION_E_INVALID;
1561 0 : goto send_reply;
1562 : }
1563 :
1564 8 : if (mp->certkey_len < mp->cert_len)
1565 : {
1566 0 : rv = SESSION_E_INVALID;
1567 0 : goto send_reply;
1568 : }
1569 :
1570 8 : key_len = mp->certkey_len - mp->cert_len;
1571 8 : if (key_len > max_key_len)
1572 : {
1573 0 : rv = SESSION_E_INVALID;
1574 0 : goto send_reply;
1575 : }
1576 :
1577 8 : clib_memset (a, 0, sizeof (*a));
1578 8 : a->cert = certkey;
1579 8 : a->key = certkey + mp->cert_len;
1580 8 : a->cert_len = mp->cert_len;
1581 8 : a->key_len = key_len;
1582 8 : rv = vnet_app_add_cert_key_pair (a);
1583 :
1584 8 : vec_free (certkey);
1585 : }
1586 : else
1587 : {
1588 4 : rv = vnet_app_del_cert_key_pair (mp->index);
1589 : }
1590 :
1591 12 : send_reply:
1592 :
1593 12 : msg.type = APP_SAPI_MSG_TYPE_ADD_DEL_CERT_KEY_REPLY;
1594 12 : rmp = &msg.cert_key_add_del_reply;
1595 12 : rmp->retval = rv;
1596 12 : rmp->context = mp->context;
1597 12 : if (!rv && mp->is_add)
1598 8 : rmp->index = a->index;
1599 :
1600 12 : clib_socket_sendmsg (cs, &msg, sizeof (msg), 0, 0);
1601 12 : }
1602 :
1603 : static void
1604 8 : sapi_socket_detach (app_namespace_t * app_ns, clib_socket_t * cs)
1605 : {
1606 : app_ns_api_handle_t *handle;
1607 : app_worker_t *app_wrk;
1608 : u32 api_client_handle;
1609 :
1610 8 : api_client_handle = appns_sapi_socket_handle (app_ns, cs);
1611 :
1612 : /* Cleanup everything because app worker closed socket or crashed */
1613 8 : handle = (app_ns_api_handle_t *) & cs->private_data;
1614 8 : app_wrk = app_worker_get_if_valid (handle->aah_app_wrk_index);
1615 8 : if (!app_wrk)
1616 0 : return;
1617 :
1618 8 : vnet_app_worker_add_del_args_t args = {
1619 8 : .app_index = app_wrk->app_index,
1620 8 : .wrk_map_index = app_wrk->wrk_map_index,
1621 : .api_client_index = api_client_handle,
1622 : .is_add = 0
1623 : };
1624 : /* Send rpc to main thread for worker barrier */
1625 8 : vlib_rpc_call_main_thread (vnet_app_worker_add_del, (u8 *) & args,
1626 : sizeof (args));
1627 : }
1628 :
1629 : static clib_error_t *
1630 36 : sapi_sock_read_ready (clib_file_t * cf)
1631 : {
1632 36 : app_ns_api_handle_t *handle = (app_ns_api_handle_t *) & cf->private_data;
1633 36 : vlib_main_t *vm = vlib_get_main ();
1634 36 : app_sapi_msg_t msg = { 0 };
1635 : app_namespace_t *app_ns;
1636 36 : clib_error_t *err = 0;
1637 : clib_socket_t *cs;
1638 :
1639 36 : app_ns = app_namespace_get (handle->aah_app_ns_index);
1640 36 : cs = appns_sapi_get_socket (app_ns, handle->aah_sock_index);
1641 36 : if (!cs)
1642 0 : goto error;
1643 :
1644 36 : err = clib_socket_recvmsg (cs, &msg, sizeof (msg), 0, 0);
1645 36 : if (err)
1646 : {
1647 8 : clib_error_free (err);
1648 8 : sapi_socket_detach (app_ns, cs);
1649 8 : goto error;
1650 : }
1651 :
1652 28 : handle = (app_ns_api_handle_t *) & cs->private_data;
1653 :
1654 28 : vlib_worker_thread_barrier_sync (vm);
1655 :
1656 28 : switch (msg.type)
1657 : {
1658 14 : case APP_SAPI_MSG_TYPE_ATTACH:
1659 14 : session_api_attach_handler (app_ns, cs, &msg.attach);
1660 14 : break;
1661 2 : case APP_SAPI_MSG_TYPE_ADD_DEL_WORKER:
1662 2 : sapi_add_del_worker_handler (app_ns, cs, &msg.worker_add_del);
1663 2 : break;
1664 12 : case APP_SAPI_MSG_TYPE_ADD_DEL_CERT_KEY:
1665 12 : sapi_add_del_cert_key_handler (app_ns, cs, &msg.cert_key_add_del);
1666 12 : break;
1667 0 : default:
1668 0 : clib_warning ("app wrk %u unknown message type: %u",
1669 : handle->aah_app_wrk_index, msg.type);
1670 0 : break;
1671 : }
1672 :
1673 28 : vlib_worker_thread_barrier_release (vm);
1674 :
1675 36 : error:
1676 36 : return 0;
1677 : }
1678 :
1679 : static clib_error_t *
1680 0 : sapi_sock_write_ready (clib_file_t * cf)
1681 : {
1682 0 : app_ns_api_handle_t *handle = (app_ns_api_handle_t *) & cf->private_data;
1683 0 : clib_warning ("called for app ns %u", handle->aah_app_ns_index);
1684 0 : return 0;
1685 : }
1686 :
1687 : static clib_error_t *
1688 0 : sapi_sock_error (clib_file_t * cf)
1689 : {
1690 0 : app_ns_api_handle_t *handle = (app_ns_api_handle_t *) & cf->private_data;
1691 : app_namespace_t *app_ns;
1692 : clib_socket_t *cs;
1693 :
1694 0 : app_ns = app_namespace_get (handle->aah_app_ns_index);
1695 0 : cs = appns_sapi_get_socket (app_ns, handle->aah_sock_index);
1696 0 : if (!cs)
1697 0 : return 0;
1698 :
1699 0 : sapi_socket_detach (app_ns, cs);
1700 0 : return 0;
1701 : }
1702 :
1703 : static clib_error_t *
1704 14 : sapi_sock_accept_ready (clib_file_t * scf)
1705 : {
1706 14 : app_ns_api_handle_t handle = *(app_ns_api_handle_t *) & scf->private_data;
1707 : app_namespace_t *app_ns;
1708 14 : clib_file_t cf = { 0 };
1709 14 : clib_error_t *err = 0;
1710 : clib_socket_t *ccs, *scs;
1711 :
1712 : /* Listener files point to namespace */
1713 14 : app_ns = app_namespace_get (handle.aah_app_ns_index);
1714 :
1715 : /*
1716 : * Initialize client socket
1717 : */
1718 14 : ccs = appns_sapi_alloc_socket (app_ns);
1719 :
1720 : /* Grab server socket after client is initialized */
1721 14 : scs = appns_sapi_get_socket (app_ns, handle.aah_sock_index);
1722 14 : if (!scs)
1723 0 : goto error;
1724 :
1725 14 : err = clib_socket_accept (scs, ccs);
1726 14 : if (err)
1727 : {
1728 0 : clib_error_report (err);
1729 0 : goto error;
1730 : }
1731 :
1732 14 : cf.read_function = sapi_sock_read_ready;
1733 14 : cf.write_function = sapi_sock_write_ready;
1734 14 : cf.error_function = sapi_sock_error;
1735 14 : cf.file_descriptor = ccs->fd;
1736 : /* File points to app namespace and socket */
1737 14 : handle.aah_sock_index = appns_sapi_socket_index (app_ns, ccs);
1738 14 : cf.private_data = handle.as_u64;
1739 14 : cf.description = format (0, "app sock conn fd: %d", ccs->fd);
1740 :
1741 : /* Poll until we get an attach message. Socket points to file and
1742 : * application that owns the socket */
1743 14 : handle.aah_app_wrk_index = APP_INVALID_INDEX;
1744 14 : handle.aah_file_index = clib_file_add (&file_main, &cf);
1745 14 : ccs->private_data = handle.as_u64;
1746 :
1747 14 : return err;
1748 :
1749 0 : error:
1750 0 : appns_sapi_free_socket (app_ns, ccs);
1751 0 : return err;
1752 : }
1753 :
1754 : void
1755 0 : appns_sapi_del_ns_socket (app_namespace_t *app_ns)
1756 : {
1757 : app_ns_api_handle_t *handle;
1758 : clib_socket_t *cs;
1759 :
1760 0 : pool_foreach (cs, app_ns->app_sockets)
1761 : {
1762 0 : handle = (app_ns_api_handle_t *) &cs->private_data;
1763 0 : clib_file_del_by_index (&file_main, handle->aah_file_index);
1764 :
1765 0 : clib_socket_close (cs);
1766 0 : clib_socket_free (cs);
1767 : }
1768 0 : pool_free (app_ns->app_sockets);
1769 0 : }
1770 :
1771 : int
1772 35 : appns_sapi_add_ns_socket (app_namespace_t * app_ns)
1773 : {
1774 35 : char *subdir = "/app_ns_sockets/";
1775 : app_ns_api_handle_t *handle;
1776 35 : clib_file_t cf = { 0 };
1777 : struct stat file_stat;
1778 : clib_error_t *err;
1779 : clib_socket_t *cs;
1780 : char dir[4096];
1781 :
1782 35 : snprintf (dir, sizeof (dir), "%s%s", vlib_unix_get_runtime_dir (), subdir);
1783 :
1784 35 : if (!app_ns->sock_name)
1785 35 : app_ns->sock_name = format (0, "%s%v%c", dir, app_ns->ns_id, 0);
1786 :
1787 : /*
1788 : * Create and initialize socket to listen on
1789 : */
1790 35 : cs = appns_sapi_alloc_socket (app_ns);
1791 35 : cs->config = (char *) vec_dup (app_ns->sock_name);
1792 35 : cs->flags = CLIB_SOCKET_F_IS_SERVER |
1793 35 : CLIB_SOCKET_F_ALLOW_GROUP_WRITE |
1794 35 : CLIB_SOCKET_F_SEQPACKET | CLIB_SOCKET_F_PASSCRED;
1795 :
1796 35 : if (clib_socket_prefix_get_type (cs->config) == CLIB_SOCKET_TYPE_UNIX)
1797 : {
1798 35 : err = vlib_unix_recursive_mkdir ((char *) dir);
1799 35 : if (err)
1800 : {
1801 0 : clib_error_report (err);
1802 0 : return SESSION_E_SYSCALL;
1803 : }
1804 : }
1805 :
1806 35 : if ((err = clib_socket_init (cs)))
1807 : {
1808 0 : clib_error_report (err);
1809 0 : return -1;
1810 : }
1811 :
1812 70 : if (clib_socket_prefix_get_type (cs->config) == CLIB_SOCKET_TYPE_UNIX &&
1813 35 : stat ((char *) app_ns->sock_name, &file_stat) == -1)
1814 0 : return -1;
1815 :
1816 : /*
1817 : * Start polling it
1818 : */
1819 35 : cf.read_function = sapi_sock_accept_ready;
1820 35 : cf.file_descriptor = cs->fd;
1821 : /* File points to namespace */
1822 35 : handle = (app_ns_api_handle_t *) & cf.private_data;
1823 35 : handle->aah_app_ns_index = app_namespace_index (app_ns);
1824 35 : handle->aah_sock_index = appns_sapi_socket_index (app_ns, cs);
1825 35 : cf.description = format (0, "app sock listener: %s", app_ns->sock_name);
1826 :
1827 : /* Socket points to clib file index */
1828 35 : handle = (app_ns_api_handle_t *) & cs->private_data;
1829 35 : handle->aah_file_index = clib_file_add (&file_main, &cf);
1830 35 : handle->aah_app_wrk_index = APP_INVALID_INDEX;
1831 :
1832 35 : return 0;
1833 : }
1834 :
1835 : #include <vnet/session/session.api.c>
1836 : static clib_error_t *
1837 575 : session_api_hookup (vlib_main_t *vm)
1838 : {
1839 : /*
1840 : * Set up the (msg_name, crc, message-id) table
1841 : */
1842 575 : REPLY_MSG_ID_BASE = setup_message_id_table ();
1843 :
1844 575 : return 0;
1845 : }
1846 :
1847 17279 : VLIB_API_INIT_FUNCTION (session_api_hookup);
1848 :
1849 : /*
1850 : * fd.io coding-style-patch-verification: ON
1851 : *
1852 : * Local Variables:
1853 : * eval: (c-set-style "gnu")
1854 : * End:
1855 : */
|