FD.io VPP  v21.10.1-2-g0a485f517
Vector Packet Processing
application_local.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
17 #include <vnet/session/session.h>
18 
19 typedef enum ct_segment_flags_
20 {
24 
25 typedef struct ct_segment_
26 {
33 } ct_segment_t;
34 
35 typedef struct ct_segments_
36 {
43 
44 typedef struct ct_main_
45 {
46  ct_connection_t **connections; /**< Per-worker connection pools */
47  u32 n_workers; /**< Number of vpp workers */
48  u32 n_sessions; /**< Cumulative sessions counter */
49  u32 *ho_reusable; /**< Vector of reusable ho indices */
50  clib_spinlock_t ho_reuseable_lock; /**< Lock for reusable ho indices */
51  clib_rwlock_t app_segs_lock; /**< RW lock for seg contexts */
52  uword *app_segs_ctxs_table; /**< App handle to segment pool map */
53  ct_segments_ctx_t *app_seg_ctxs; /**< Pool of ct segment contexts */
54 } ct_main_t;
55 
57 
58 static ct_connection_t *
60 {
61  ct_connection_t *ct;
62 
64  ct->c_c_index = ct - ct_main.connections[thread_index];
65  ct->c_thread_index = thread_index;
66  ct->client_wrk = ~0;
67  ct->server_wrk = ~0;
68  ct->seg_ctx_index = ~0;
69  ct->ct_seg_index = ~0;
70  return ct;
71 }
72 
73 static ct_connection_t *
75 {
77  return 0;
79 }
80 
81 static void
83 {
84  if (CLIB_DEBUG)
85  {
86  u32 thread_index = ct->c_thread_index;
87  memset (ct, 0xfc, sizeof (*ct));
89  return;
90  }
91  pool_put (ct_main.connections[ct->c_thread_index], ct);
92 }
93 
94 static ct_connection_t *
96 {
97  ct_main_t *cm = &ct_main;
98  u32 *hip;
99 
100  clib_spinlock_lock (&cm->ho_reuseable_lock);
101  vec_foreach (hip, cm->ho_reusable)
102  pool_put_index (cm->connections[0], *hip);
103  vec_reset_length (cm->ho_reusable);
104  clib_spinlock_unlock (&cm->ho_reuseable_lock);
105 
106  return ct_connection_alloc (0);
107 }
108 
109 void
111 {
112  ct_main_t *cm = &ct_main;
113 
114  clib_spinlock_lock (&cm->ho_reuseable_lock);
115  vec_add1 (cm->ho_reusable, ho_index);
116  clib_spinlock_unlock (&cm->ho_reuseable_lock);
117 }
118 
119 session_t *
121 {
122  ct_connection_t *ct, *peer_ct;
124  peer_ct = ct_connection_get (ct->peer_index, s->thread_index);
125  return session_get (peer_ct->c_s_index, s->thread_index);
126 }
127 
128 void
130 {
131  ct_connection_t *ct;
133  sep->transport_proto = ct->actual_tp;
134  sep->port = ct->c_lcl_port;
135  sep->is_ip4 = ct->c_is_ip4;
136  ip_copy (&sep->ip, &ct->c_lcl_ip, ct->c_is_ip4);
137 }
138 
139 static void
141  svm_fifo_t *tx_fifo)
142 {
143  ct_segments_ctx_t *seg_ctx;
144  ct_main_t *cm = &ct_main;
145  segment_manager_t *sm;
146  app_worker_t *app_wrk;
147  ct_segment_t *ct_seg;
148  fifo_segment_t *fs;
149  u8 del_segment = 0;
150  u32 seg_index;
151  int cnt;
152 
153  /*
154  * Cleanup fifos
155  */
156 
157  sm = segment_manager_get (rx_fifo->segment_manager);
158  seg_index = rx_fifo->segment_index;
159 
160  fs = segment_manager_get_segment_w_lock (sm, seg_index);
161  fifo_segment_free_fifo (fs, rx_fifo);
162  fifo_segment_free_fifo (fs, tx_fifo);
164 
165  /*
166  * Atomically update segment context with readers lock
167  */
168 
169  clib_rwlock_reader_lock (&cm->app_segs_lock);
170 
171  seg_ctx = pool_elt_at_index (cm->app_seg_ctxs, ct->seg_ctx_index);
172  ct_seg = pool_elt_at_index (seg_ctx->segments, ct->ct_seg_index);
173 
174  if (ct->flags & CT_CONN_F_CLIENT)
175  {
176  cnt =
177  __atomic_sub_fetch (&ct_seg->client_n_sessions, 1, __ATOMIC_RELAXED);
178  }
179  else
180  {
181  cnt =
182  __atomic_sub_fetch (&ct_seg->server_n_sessions, 1, __ATOMIC_RELAXED);
183  }
184 
185  clib_rwlock_reader_unlock (&cm->app_segs_lock);
186 
187  /*
188  * No need to do any app updates, return
189  */
190  ASSERT (cnt >= 0);
191  if (cnt)
192  return;
193 
194  /*
195  * Grab exclusive lock and update flags unless some other thread
196  * added more sessions
197  */
198  clib_rwlock_writer_lock (&cm->app_segs_lock);
199 
200  seg_ctx = pool_elt_at_index (cm->app_seg_ctxs, ct->seg_ctx_index);
201  ct_seg = pool_elt_at_index (seg_ctx->segments, ct->ct_seg_index);
202  if (ct->flags & CT_CONN_F_CLIENT)
203  {
204  cnt = ct_seg->client_n_sessions;
205  if (!cnt)
207  }
208  else
209  {
210  cnt = ct_seg->server_n_sessions;
211  if (!cnt)
213  }
214 
215  /*
216  * Remove segment context because both client and server detached
217  */
218 
219  if (!cnt && (ct_seg->flags & CT_SEGMENT_F_CLIENT_DETACHED) &&
221  {
222  pool_put_index (seg_ctx->segments, ct->ct_seg_index);
223 
224  /*
225  * No more segment indices left, remove the segments context
226  */
227  if (!pool_elts (seg_ctx->segments))
228  {
229  u64 table_handle = seg_ctx->client_wrk << 16 | seg_ctx->server_wrk;
230  table_handle = (u64) seg_ctx->sm_index << 32 | table_handle;
231  hash_unset (cm->app_segs_ctxs_table, table_handle);
232  pool_free (seg_ctx->segments);
233  pool_put_index (cm->app_seg_ctxs, ct->seg_ctx_index);
234  }
235  del_segment = 1;
236  }
237 
238  clib_rwlock_writer_unlock (&cm->app_segs_lock);
239 
240  /*
241  * Session counter went to zero, notify the app that detached
242  */
243  if (cnt)
244  return;
245 
246  if (ct->flags & CT_CONN_F_CLIENT)
247  {
248  app_wrk = app_worker_get_if_valid (ct->client_wrk);
249  /* Determine if client app still needs notification, i.e., if it is
250  * still attached. If client detached and this is the last ct session
251  * on this segment, then its connects segment manager should also be
252  * detached, so do not send notification */
253  if (app_wrk)
254  {
255  segment_manager_t *csm;
257  if (!segment_manager_app_detached (csm))
259  }
260  }
261  else if (!segment_manager_app_detached (sm))
262  {
263  app_wrk = app_worker_get (ct->server_wrk);
265  }
266 
267  if (!del_segment)
268  return;
269 
270  segment_manager_lock_and_del_segment (sm, seg_index);
271 
272  /* Cleanup segment manager if needed. If server detaches there's a chance
273  * the client's sessions will hold up segment removal */
276 }
277 
278 int
280 {
281  u32 ss_index, opaque, thread_index;
282  ct_connection_t *sct, *cct;
283  app_worker_t *client_wrk;
284  session_t *cs;
285 
286  ss_index = ss->session_index;
288  sct = (ct_connection_t *) session_get_transport (ss);
289  client_wrk = app_worker_get (sct->client_wrk);
290  opaque = sct->client_opaque;
291 
293 
294  /* Client closed while waiting for reply from server */
295  if (PREDICT_FALSE (!cct))
296  {
299  ct_connection_free (sct);
300  return 0;
301  }
302 
304  cct->flags &= ~CT_CONN_F_HALF_OPEN;
305 
306  if (PREDICT_FALSE (err))
307  goto connect_error;
308 
309  /*
310  * Alloc client session
311  */
312 
314  ss = session_get (ss_index, thread_index);
315  cs->session_type = ss->session_type;
317  cs->session_state = SESSION_STATE_CONNECTING;
318  cs->app_wrk_index = client_wrk->wrk_index;
319  cs->connection_index = cct->c_c_index;
320  cct->c_s_index = cs->session_index;
321 
322  /* This will allocate fifos for the session. They won't be used for
323  * exchanging data but they will be used to close the connection if
324  * the segment manager/worker is freed */
325  if ((err = app_worker_init_connected (client_wrk, cs)))
326  {
327  session_free (cs);
328  session_close (ss);
329  err = SESSION_E_ALLOC;
330  goto connect_error;
331  }
332 
333  cs->session_state = SESSION_STATE_CONNECTING;
334 
335  if (app_worker_connect_notify (client_wrk, cs, 0, opaque))
336  {
338  session_free (cs);
339  session_close (ss);
340  goto cleanup_client;
341  }
342 
343  cs = session_get (cct->c_s_index, cct->c_thread_index);
344  cs->session_state = SESSION_STATE_READY;
345 
346  return 0;
347 
348 connect_error:
349 
350  app_worker_connect_notify (client_wrk, 0, err, cct->client_opaque);
351 
352 cleanup_client:
353 
354  if (cct->client_rx_fifo)
356  ct_connection_free (cct);
357  return -1;
358 }
359 
360 static inline ct_segment_t *
362  u32 seg_ctx_index)
363 {
364  uword free_bytes, max_free_bytes;
365  ct_segment_t *ct_seg, *res = 0;
366  ct_segments_ctx_t *seg_ctx;
367  fifo_segment_t *fs;
368  u32 max_fifos;
369 
370  seg_ctx = pool_elt_at_index (cm->app_seg_ctxs, seg_ctx_index);
371  max_free_bytes = seg_ctx->fifo_pair_bytes;
372 
373  pool_foreach (ct_seg, seg_ctx->segments)
374  {
375  /* Client or server has detached so segment cannot be used */
376  if ((ct_seg->flags & CT_SEGMENT_F_SERVER_DETACHED) ||
378  continue;
379  fs = segment_manager_get_segment (sm, ct_seg->segment_index);
380  free_bytes = fifo_segment_available_bytes (fs);
381  max_fifos = fifo_segment_size (fs) / seg_ctx->fifo_pair_bytes;
382  if (free_bytes > max_free_bytes &&
383  fifo_segment_num_fifos (fs) / 2 < max_fifos)
384  {
385  max_free_bytes = free_bytes;
386  res = ct_seg;
387  }
388  }
389 
390  return res;
391 }
392 
393 static ct_segment_t *
394 ct_alloc_segment (ct_main_t *cm, app_worker_t *server_wrk, u64 table_handle,
395  segment_manager_t *sm, u32 client_wrk_index)
396 {
397  u32 seg_ctx_index = ~0, sm_index, pair_bytes;
399  const u32 margin = 16 << 10;
400  ct_segments_ctx_t *seg_ctx;
401  app_worker_t *client_wrk;
402  u64 seg_size, seg_handle;
403  application_t *server;
404  ct_segment_t *ct_seg;
405  uword *spp;
406  int fs_index;
407 
408  server = application_get (server_wrk->app_index);
410  sm_index = segment_manager_index (sm);
411  pair_bytes = props->rx_fifo_size + props->tx_fifo_size + margin;
412 
413  /*
414  * Make sure another thread did not alloc a segment while acquiring the lock
415  */
416 
417  spp = hash_get (cm->app_segs_ctxs_table, table_handle);
418  if (spp)
419  {
420  seg_ctx_index = *spp;
421  ct_seg = ct_lookup_free_segment (cm, sm, seg_ctx_index);
422  if (ct_seg)
423  return ct_seg;
424  }
425 
426  /*
427  * No segment, try to alloc one and notify the server and the client.
428  * Make sure the segment is not used for other fifos
429  */
430  seg_size = clib_max (props->segment_size, 128 << 20);
431  fs_index =
433  if (fs_index < 0)
434  return 0;
435 
436  if (seg_ctx_index == ~0)
437  {
438  pool_get_zero (cm->app_seg_ctxs, seg_ctx);
439  seg_ctx_index = seg_ctx - cm->app_seg_ctxs;
440  hash_set (cm->app_segs_ctxs_table, table_handle, seg_ctx_index);
441  seg_ctx->server_wrk = server_wrk->wrk_index;
442  seg_ctx->client_wrk = client_wrk_index;
443  seg_ctx->sm_index = sm_index;
444  seg_ctx->fifo_pair_bytes = pair_bytes;
445  }
446  else
447  {
448  seg_ctx = pool_elt_at_index (cm->app_seg_ctxs, seg_ctx_index);
449  }
450 
451  pool_get_zero (seg_ctx->segments, ct_seg);
452  ct_seg->segment_index = fs_index;
453  ct_seg->server_n_sessions = 0;
454  ct_seg->client_n_sessions = 0;
455  ct_seg->ct_seg_index = ct_seg - seg_ctx->segments;
456  ct_seg->seg_ctx_index = seg_ctx_index;
457 
458  /* New segment, notify the server and client */
459  seg_handle = segment_manager_make_segment_handle (sm_index, fs_index);
460  if (app_worker_add_segment_notify (server_wrk, seg_handle))
461  goto error;
462 
463  client_wrk = app_worker_get (client_wrk_index);
464  if (app_worker_add_segment_notify (client_wrk, seg_handle))
465  {
466  app_worker_del_segment_notify (server_wrk, seg_handle);
467  goto error;
468  }
469 
470  return ct_seg;
471 
472 error:
473 
475  pool_put_index (seg_ctx->segments, ct_seg->seg_ctx_index);
476  return 0;
477 }
478 
479 static int
481  session_t *ls, session_t *ll)
482 {
484  u64 seg_handle, table_handle;
485  u32 sm_index, fs_index = ~0;
486  ct_segments_ctx_t *seg_ctx;
487  ct_main_t *cm = &ct_main;
488  application_t *server;
489  segment_manager_t *sm;
490  ct_segment_t *ct_seg;
491  fifo_segment_t *fs;
492  uword *spp;
493  int rv;
494 
495  sm = app_worker_get_listen_segment_manager (server_wrk, ll);
496  sm_index = segment_manager_index (sm);
497  server = application_get (server_wrk->app_index);
499 
500  table_handle = ct->client_wrk << 16 | server_wrk->wrk_index;
501  table_handle = (u64) sm_index << 32 | table_handle;
502 
503  /*
504  * Check if we already have a segment that can hold the fifos
505  */
506 
507  clib_rwlock_reader_lock (&cm->app_segs_lock);
508 
509  spp = hash_get (cm->app_segs_ctxs_table, table_handle);
510  if (spp)
511  {
512  ct_seg = ct_lookup_free_segment (cm, sm, *spp);
513  if (ct_seg)
514  {
515  ct->seg_ctx_index = ct_seg->seg_ctx_index;
516  ct->ct_seg_index = ct_seg->ct_seg_index;
517  fs_index = ct_seg->segment_index;
518  __atomic_add_fetch (&ct_seg->server_n_sessions, 1, __ATOMIC_RELAXED);
519  __atomic_add_fetch (&ct_seg->client_n_sessions, 1, __ATOMIC_RELAXED);
520  }
521  }
522 
523  clib_rwlock_reader_unlock (&cm->app_segs_lock);
524 
525  /*
526  * If not, grab exclusive lock and allocate segment
527  */
528  if (fs_index == ~0)
529  {
530  clib_rwlock_writer_lock (&cm->app_segs_lock);
531 
532  ct_seg =
533  ct_alloc_segment (cm, server_wrk, table_handle, sm, ct->client_wrk);
534  if (!ct_seg)
535  {
536  clib_rwlock_writer_unlock (&cm->app_segs_lock);
537  return -1;
538  }
539 
540  ct->seg_ctx_index = ct_seg->seg_ctx_index;
541  ct->ct_seg_index = ct_seg->ct_seg_index;
542  ct_seg->server_n_sessions += 1;
543  ct_seg->client_n_sessions += 1;
544  fs_index = ct_seg->segment_index;
545 
546  clib_rwlock_writer_unlock (&cm->app_segs_lock);
547  }
548 
549  /*
550  * Allocate and initialize the fifos
551  */
552  fs = segment_manager_get_segment_w_lock (sm, fs_index);
554  fs, ls->thread_index, props->rx_fifo_size, props->tx_fifo_size,
555  &ls->rx_fifo, &ls->tx_fifo);
556  if (rv)
557  {
559 
560  clib_rwlock_reader_lock (&cm->app_segs_lock);
561 
562  seg_ctx = pool_elt_at_index (cm->app_seg_ctxs, ct->seg_ctx_index);
563  ct_seg = pool_elt_at_index (seg_ctx->segments, ct->ct_seg_index);
564  __atomic_sub_fetch (&ct_seg->server_n_sessions, 1, __ATOMIC_RELAXED);
565  __atomic_sub_fetch (&ct_seg->client_n_sessions, 1, __ATOMIC_RELAXED);
566 
567  clib_rwlock_reader_unlock (&cm->app_segs_lock);
568 
569  return rv;
570  }
571 
572  ls->rx_fifo->shr->master_session_index = ls->session_index;
573  ls->tx_fifo->shr->master_session_index = ls->session_index;
574  ls->rx_fifo->master_thread_index = ls->thread_index;
575  ls->tx_fifo->master_thread_index = ls->thread_index;
576  ls->rx_fifo->segment_manager = sm_index;
577  ls->tx_fifo->segment_manager = sm_index;
578  ls->rx_fifo->segment_index = fs_index;
579  ls->tx_fifo->segment_index = fs_index;
580 
581  seg_handle = segment_manager_segment_handle (sm, fs);
583 
584  ct->segment_handle = seg_handle;
585 
586  return 0;
587 }
588 
589 static void
590 ct_accept_rpc_wrk_handler (void *accept_args)
591 {
592  u32 cct_index, ho_index, thread_index, ll_index;
593  ct_connection_t *sct, *cct, *ho;
594  transport_connection_t *ll_ct;
595  app_worker_t *server_wrk;
596  session_t *ss, *ll;
597 
598  /*
599  * Alloc client ct and initialize from ho
600  */
603  cct_index = cct->c_c_index;
604 
605  ho_index = pointer_to_uword (accept_args);
606  ho = ct_connection_get (ho_index, 0);
607 
608  /* Unlikely but half-open session and transport could have been freed */
609  if (PREDICT_FALSE (!ho))
610  {
611  ct_connection_free (cct);
612  return;
613  }
614 
615  clib_memcpy (cct, ho, sizeof (*ho));
616  cct->c_c_index = cct_index;
617  cct->c_thread_index = thread_index;
618  cct->flags |= CT_CONN_F_HALF_OPEN;
619 
620  /* Notify session layer that half-open is on a different thread
621  * and mark ho connection index reusable. Avoids another rpc
622  */
625  ct_half_open_add_reusable (ho_index);
626 
627  /*
628  * Alloc and init server transport
629  */
630 
631  ll_index = cct->peer_index;
632  ll = listen_session_get (ll_index);
634  /* Transport not necessarily ct but it might, so grab after sct alloc */
635  ll_ct = listen_session_get_transport (ll);
636 
637  /* Make sure cct is valid after sct alloc */
638  cct = ct_connection_get (cct_index, thread_index);
639 
640  sct->c_rmt_port = 0;
641  sct->c_lcl_port = ll_ct->lcl_port;
642  sct->c_is_ip4 = cct->c_is_ip4;
643  clib_memcpy (&sct->c_lcl_ip, &ll_ct->lcl_ip, sizeof (ll_ct->lcl_ip));
644  sct->client_wrk = cct->client_wrk;
645  sct->c_proto = TRANSPORT_PROTO_NONE;
646  sct->client_opaque = cct->client_opaque;
647  sct->actual_tp = cct->actual_tp;
648 
649  sct->peer_index = cct->c_c_index;
650  cct->peer_index = sct->c_c_index;
651 
652  /*
653  * Accept server session. Client session is created only after
654  * server confirms accept.
655  */
657  ll = listen_session_get (ll_index);
658  ss->session_type = session_type_from_proto_and_ip (TRANSPORT_PROTO_NONE,
659  sct->c_is_ip4);
660  ss->connection_index = sct->c_c_index;
662  ss->session_state = SESSION_STATE_CREATED;
663 
664  server_wrk = application_listener_select_worker (ll);
665  ss->app_wrk_index = server_wrk->wrk_index;
666 
667  sct->c_s_index = ss->session_index;
668  sct->server_wrk = ss->app_wrk_index;
669 
670  if (ct_init_accepted_session (server_wrk, sct, ss, ll))
671  {
672  ct_session_connect_notify (ss, SESSION_E_ALLOC);
673  ct_connection_free (sct);
674  session_free (ss);
675  return;
676  }
677 
678  cct->seg_ctx_index = sct->seg_ctx_index;
679  cct->ct_seg_index = sct->ct_seg_index;
680  cct->client_rx_fifo = ss->tx_fifo;
681  cct->client_tx_fifo = ss->rx_fifo;
682  cct->client_rx_fifo->refcnt++;
683  cct->client_tx_fifo->refcnt++;
684  cct->segment_handle = sct->segment_handle;
685 
686  ss->session_state = SESSION_STATE_ACCEPTING;
687  if (app_worker_accept_notify (server_wrk, ss))
688  {
689  ct_session_connect_notify (ss, SESSION_E_REFUSED);
690  ct_session_dealloc_fifos (sct, ss->rx_fifo, ss->tx_fifo);
691  ct_connection_free (sct);
692  session_free (ss);
693  }
694 }
695 
696 static int
697 ct_connect (app_worker_t * client_wrk, session_t * ll,
699 {
700  u32 thread_index, ho_index;
701  ct_main_t *cm = &ct_main;
702  ct_connection_t *ho;
703 
704  /* Simple round-robin policy for spreading sessions over workers. We skip
705  * thread index 0, i.e., offset the index by 1, when we have workers as it
706  * is the one dedicated to main thread. Note that n_workers does not include
707  * main thread */
708  cm->n_sessions += 1;
709  thread_index = cm->n_workers ? (cm->n_sessions % cm->n_workers) + 1 : 0;
710 
711  /*
712  * Alloc and init client half-open transport
713  */
714 
715  ho = ct_half_open_alloc ();
716  ho_index = ho->c_c_index;
717  ho->c_rmt_port = sep->port;
718  ho->c_lcl_port = 0;
719  ho->c_is_ip4 = sep->is_ip4;
720  ho->client_opaque = sep->opaque;
721  ho->client_wrk = client_wrk->wrk_index;
722  ho->peer_index = ll->session_index;
723  ho->c_proto = TRANSPORT_PROTO_NONE;
724  ho->c_flags |= TRANSPORT_CONNECTION_F_NO_LOOKUP;
725  clib_memcpy (&ho->c_rmt_ip, &sep->ip, sizeof (sep->ip));
726  ho->flags |= CT_CONN_F_CLIENT;
727  ho->c_s_index = ~0;
728  ho->actual_tp = sep->transport_proto;
729 
730  /*
731  * Accept connection on thread selected above. Connected reply comes
732  * after server accepts the connection.
733  */
734 
737  uword_to_pointer (ho_index, void *));
738 
739  return ho_index;
740 }
741 
742 static u32
743 ct_start_listen (u32 app_listener_index, transport_endpoint_t * tep)
744 {
746  ct_connection_t *ct;
747 
748  sep = (session_endpoint_cfg_t *) tep;
749  ct = ct_connection_alloc (0);
750  ct->server_wrk = sep->app_wrk_index;
751  ct->c_is_ip4 = sep->is_ip4;
752  clib_memcpy (&ct->c_lcl_ip, &sep->ip, sizeof (sep->ip));
753  ct->c_lcl_port = sep->port;
754  ct->c_s_index = app_listener_index;
755  ct->actual_tp = sep->transport_proto;
756  return ct->c_c_index;
757 }
758 
759 static u32
760 ct_stop_listen (u32 ct_index)
761 {
762  ct_connection_t *ct;
763  ct = ct_connection_get (ct_index, 0);
764  ct_connection_free (ct);
765  return 0;
766 }
767 
768 static transport_connection_t *
770 {
771  return (transport_connection_t *) ct_connection_get (ct_index, 0);
772 }
773 
774 static transport_connection_t *
776 {
777  return (transport_connection_t *) ct_connection_get (ct_index, 0);
778 }
779 
780 static void
782 {
783  ct_connection_t *ct, *peer_ct;
784 
785  ct = ct_connection_get (conn_index, thread_index);
786  if (!ct)
787  return;
788 
789  peer_ct = ct_connection_get (ct->peer_index, thread_index);
790  if (peer_ct)
791  peer_ct->peer_index = ~0;
792 
793  ct_connection_free (ct);
794 }
795 
796 static void
797 ct_cleanup_ho (u32 ho_index)
798 {
799  ct_connection_free (ct_connection_get (ho_index, 0));
800 }
801 
802 static int
804 {
805  session_endpoint_cfg_t *sep_ext;
806  session_endpoint_t _sep, *sep = &_sep;
807  app_worker_t *app_wrk;
808  session_handle_t lh;
809  application_t *app;
810  app_listener_t *al;
811  u32 table_index;
812  session_t *ll;
813  u8 fib_proto;
814 
815  sep_ext = (session_endpoint_cfg_t *) tep;
816  _sep = *(session_endpoint_t *) tep;
817  app_wrk = app_worker_get (sep_ext->app_wrk_index);
818  app = application_get (app_wrk->app_index);
819 
820  sep->transport_proto = sep_ext->original_tp;
821  table_index = application_local_session_table (app);
822  lh = session_lookup_local_endpoint (table_index, sep);
823  if (lh == SESSION_DROP_HANDLE)
824  return SESSION_E_FILTERED;
825 
826  if (lh == SESSION_INVALID_HANDLE)
827  goto global_scope;
828 
830  al = app_listener_get_w_session (ll);
831 
832  /*
833  * Break loop if rule in local table points to connecting app. This
834  * can happen if client is a generic proxy. Route connect through
835  * global table instead.
836  */
837  if (al->app_index == app->app_index)
838  goto global_scope;
839 
840  return ct_connect (app_wrk, ll, sep_ext);
841 
842  /*
843  * If nothing found, check the global scope for locally attached
844  * destinations. Make sure first that we're allowed to.
845  */
846 
847 global_scope:
848  if (session_endpoint_is_local (sep))
849  return SESSION_E_NOROUTE;
850 
851  if (!application_has_global_scope (app))
852  return SESSION_E_SCOPE;
853 
854  fib_proto = session_endpoint_fib_proto (sep);
855  table_index = session_lookup_get_index_for_fib (fib_proto, sep->fib_index);
856  ll = session_lookup_listener_wildcard (table_index, sep);
857 
858  /* Avoid connecting app to own listener */
859  if (ll && ll->app_index != app->app_index)
860  return ct_connect (app_wrk, ll, sep_ext);
861 
862  /* Failed to connect but no error */
863  return SESSION_E_LOCAL_CONNECT;
864 }
865 
866 static void
868 {
869  ct_connection_t *ct, *peer_ct;
870  app_worker_t *app_wrk;
871  session_t *s;
872 
873  ct = ct_connection_get (ct_index, thread_index);
874  s = session_get (ct->c_s_index, ct->c_thread_index);
875  peer_ct = ct_connection_get (ct->peer_index, thread_index);
876  if (peer_ct)
877  {
878  peer_ct->peer_index = ~0;
879  /* Make sure session was allocated */
880  if (peer_ct->flags & CT_CONN_F_HALF_OPEN)
881  {
882  ct_session_connect_notify (s, SESSION_E_REFUSED);
883  }
884  else if (peer_ct->c_s_index != ~0)
886  else
887  ct_connection_free (peer_ct);
888  }
889 
890  if (ct->flags & CT_CONN_F_CLIENT)
891  {
892  /* Normal free for client session as the fifos are allocated through
893  * the connects segment manager in a segment that's not shared with
894  * the server */
897  }
898  else
899  {
900  /* Manual session and fifo segment cleanup to avoid implicit
901  * segment manager cleanups and notifications */
902  app_wrk = app_worker_get_if_valid (s->app_wrk_index);
903  if (app_wrk)
905 
907  session_free (s);
908  }
909 
910  ct_connection_free (ct);
911 }
912 
913 static transport_connection_t *
915 {
916  return (transport_connection_t *) ct_connection_get (ct_index,
917  thread_index);
918 }
919 
920 static u8 *
921 format_ct_connection_id (u8 * s, va_list * args)
922 {
923  ct_connection_t *ct = va_arg (*args, ct_connection_t *);
924  if (!ct)
925  return s;
926  if (ct->c_is_ip4)
927  {
928  s = format (s, "[%d:%d][CT:%U] %U:%d->%U:%d", ct->c_thread_index,
929  ct->c_s_index, format_transport_proto_short, ct->actual_tp,
930  format_ip4_address, &ct->c_lcl_ip4,
931  clib_net_to_host_u16 (ct->c_lcl_port), format_ip4_address,
932  &ct->c_rmt_ip4, clib_net_to_host_u16 (ct->c_rmt_port));
933  }
934  else
935  {
936  s = format (s, "[%d:%d][CT:%U] %U:%d->%U:%d", ct->c_thread_index,
937  ct->c_s_index, format_transport_proto_short, ct->actual_tp,
938  format_ip6_address, &ct->c_lcl_ip6,
939  clib_net_to_host_u16 (ct->c_lcl_port), format_ip6_address,
940  &ct->c_rmt_ip6, clib_net_to_host_u16 (ct->c_rmt_port));
941  }
942 
943  return s;
944 }
945 
946 static int
948 {
949  session_t *s = (session_t *) session;
950  if (session_has_transport (s))
951  return 0;
952  /* If event enqueued towards peer, remove from scheduler and remove
953  * session tx flag, i.e., accept new tx events. Unset fifo flag now to
954  * avoid missing events if peer did not clear fifo flag yet, which is
955  * interpreted as successful notification and session is descheduled. */
957  if (!ct_session_tx (s))
959 
960  /* The scheduler uses packet count as a means of upper bounding the amount
961  * of work done per dispatch. So make it look like we have sent something */
962  return 1;
963 }
964 
965 static int
967 {
968  ct_connection_t *ct = (ct_connection_t *) tc, *peer_ct;
969  session_t *ps;
970 
971  peer_ct = ct_connection_get (ct->peer_index, tc->thread_index);
972  if (!peer_ct)
973  return -1;
974  ps = session_get (peer_ct->c_s_index, peer_ct->c_thread_index);
975  return session_dequeue_notify (ps);
976 }
977 
978 static u8 *
979 format_ct_listener (u8 * s, va_list * args)
980 {
981  u32 tc_index = va_arg (*args, u32);
982  u32 __clib_unused thread_index = va_arg (*args, u32);
983  u32 __clib_unused verbose = va_arg (*args, u32);
984  ct_connection_t *ct = ct_connection_get (tc_index, 0);
985  s = format (s, "%-" SESSION_CLI_ID_LEN "U", format_ct_connection_id, ct);
986  if (verbose)
987  s = format (s, "%-" SESSION_CLI_STATE_LEN "s", "LISTEN");
988  return s;
989 }
990 
991 static u8 *
992 format_ct_half_open (u8 *s, va_list *args)
993 {
994  u32 ho_index = va_arg (*args, u32);
995  u32 verbose = va_arg (*args, u32);
996  ct_connection_t *ct = ct_connection_get (ho_index, 0);
997  s = format (s, "%-" SESSION_CLI_ID_LEN "U", format_ct_connection_id, ct);
998  if (verbose)
999  s = format (s, "%-" SESSION_CLI_STATE_LEN "s", "HALF-OPEN");
1000  return s;
1001 }
1002 
1003 static u8 *
1004 format_ct_connection (u8 * s, va_list * args)
1005 {
1006  ct_connection_t *ct = va_arg (*args, ct_connection_t *);
1007  u32 verbose = va_arg (*args, u32);
1008 
1009  if (!ct)
1010  return s;
1011  s = format (s, "%-" SESSION_CLI_ID_LEN "U", format_ct_connection_id, ct);
1012  if (verbose)
1013  {
1014  s = format (s, "%-" SESSION_CLI_STATE_LEN "s", "ESTABLISHED");
1015  if (verbose > 1)
1016  {
1017  s = format (s, "\n");
1018  }
1019  }
1020  return s;
1021 }
1022 
1023 static u8 *
1024 format_ct_session (u8 * s, va_list * args)
1025 {
1026  u32 ct_index = va_arg (*args, u32);
1027  u32 thread_index = va_arg (*args, u32);
1028  u32 verbose = va_arg (*args, u32);
1029  ct_connection_t *ct;
1030 
1031  ct = ct_connection_get (ct_index, thread_index);
1032  if (!ct)
1033  {
1034  s = format (s, "empty\n");
1035  return s;
1036  }
1037 
1038  s = format (s, "%U", format_ct_connection, ct, verbose);
1039  return s;
1040 }
1041 
1042 clib_error_t *
1044 {
1045  ct_main_t *cm = &ct_main;
1046 
1047  cm->n_workers = vlib_num_workers ();
1048  vec_validate (cm->connections, cm->n_workers);
1049  clib_spinlock_init (&cm->ho_reuseable_lock);
1050  clib_rwlock_init (&cm->app_segs_lock);
1051  return 0;
1052 }
1053 
1054 /* *INDENT-OFF* */
1056  .enable = ct_enable_disable,
1057  .start_listen = ct_start_listen,
1058  .stop_listen = ct_stop_listen,
1059  .get_connection = ct_session_get,
1060  .get_listener = ct_listener_get,
1061  .get_half_open = ct_half_open_get,
1062  .cleanup = ct_session_cleanup,
1063  .cleanup_ho = ct_cleanup_ho,
1064  .connect = ct_session_connect,
1065  .close = ct_session_close,
1066  .custom_tx = ct_custom_tx,
1067  .app_rx_evt = ct_app_rx_evt,
1068  .format_listener = format_ct_listener,
1069  .format_half_open = format_ct_half_open,
1070  .format_connection = format_ct_session,
1071  .transport_options = {
1072  .name = "ct",
1073  .short_name = "C",
1074  .tx_type = TRANSPORT_TX_INTERNAL,
1075  .service_type = TRANSPORT_SERVICE_VC,
1076  },
1077 };
1078 /* *INDENT-ON* */
1079 
1080 int
1082 {
1083  ct_connection_t *ct, *peer_ct;
1084  session_t *peer_s;
1085 
1087  peer_ct = ct_connection_get (ct->peer_index, ct->c_thread_index);
1088  if (!peer_ct)
1089  return 0;
1090  peer_s = session_get (peer_ct->c_s_index, peer_ct->c_thread_index);
1091  if (peer_s->session_state >= SESSION_STATE_TRANSPORT_CLOSING)
1092  return 0;
1093  return session_enqueue_notify (peer_s);
1094 }
1095 
1096 static clib_error_t *
1098 {
1099  transport_register_protocol (TRANSPORT_PROTO_NONE, &cut_thru_proto,
1100  FIB_PROTOCOL_IP4, ~0);
1101  transport_register_protocol (TRANSPORT_PROTO_NONE, &cut_thru_proto,
1102  FIB_PROTOCOL_IP6, ~0);
1103  return 0;
1104 }
1105 
1107 
1108 /*
1109  * fd.io coding-style-patch-verification: ON
1110  *
1111  * Local Variables:
1112  * eval: (c-set-style "gnu")
1113  * End:
1114  */
vec_reset_length
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
Definition: vec_bootstrap.h:194
segment_manager_get_segment_w_lock
fifo_segment_t * segment_manager_get_segment_w_lock(segment_manager_t *sm, u32 segment_index)
Reads a segment from the segment manager's pool and acquires reader lock.
Definition: segment_manager.c:311
ct_connection_
Definition: application_local.h:41
clib_spinlock_init
static void clib_spinlock_init(clib_spinlock_t *p)
Definition: lock.h:65
SESSION_CLI_STATE_LEN
#define SESSION_CLI_STATE_LEN
Definition: session_types.h:508
ct_segments_ctx_t
struct ct_segments_ ct_segments_ctx_t
format_ct_listener
static u8 * format_ct_listener(u8 *s, va_list *args)
Definition: application_local.c:979
vlib_num_workers
static u32 vlib_num_workers()
Definition: threads.h:333
app_worker_::wrk_index
u32 wrk_index
Worker index in global worker pool.
Definition: application.h:37
ct_half_open_alloc
static ct_connection_t * ct_half_open_alloc(void)
Definition: application_local.c:95
session_error_t
enum session_error_ session_error_t
hash_set
#define hash_set(h, key, value)
Definition: hash.h:255
session_enqueue_notify
int session_enqueue_notify(session_t *s)
Definition: session.c:778
thread_index
u32 thread_index
Definition: nat44_ei_hairpinning.c:495
CT_SEGMENT_F_SERVER_DETACHED
@ CT_SEGMENT_F_SERVER_DETACHED
Definition: application_local.c:22
segment_manager_get
segment_manager_t * segment_manager_get(u32 index)
Definition: segment_manager.c:547
session_dequeue_notify
int session_dequeue_notify(session_t *s)
Definition: session.c:816
ct_main_::app_seg_ctxs
ct_segments_ctx_t * app_seg_ctxs
Pool of ct segment contexts.
Definition: application_local.c:53
session_::session_index
u32 session_index
Index in thread pool where session was allocated.
Definition: session_types.h:188
svm_fifo_unset_event
static void svm_fifo_unset_event(svm_fifo_t *f)
Unset fifo event flag.
Definition: svm_fifo.h:746
format_ip4_address
format_function_t format_ip4_address
Definition: format.h:73
clib_memcpy
#define clib_memcpy(d, s, n)
Definition: string.h:197
SESSION_CLI_ID_LEN
#define SESSION_CLI_ID_LEN
Definition: session_types.h:507
session_close
void session_close(session_t *s)
Initialize session closing procedure.
Definition: session.c:1494
ct_start_listen
static u32 ct_start_listen(u32 app_listener_index, transport_endpoint_t *tep)
Definition: application_local.c:743
clib_max
#define clib_max(x, y)
Definition: clib.h:335
session_transport_closing_notify
void session_transport_closing_notify(transport_connection_t *tc)
Notification from transport that connection is being closed.
Definition: session.c:1062
ct_connection_alloc
static ct_connection_t * ct_connection_alloc(u32 thread_index)
Definition: application_local.c:59
pointer_to_uword
static uword pointer_to_uword(const void *p)
Definition: types.h:131
session_half_open_delete_notify
void session_half_open_delete_notify(transport_connection_t *tc)
Definition: session.c:347
pool_elt_at_index
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:549
ct_custom_tx
static int ct_custom_tx(void *session, transport_send_params_t *sp)
Definition: application_local.c:947
listen_session_get_handle
static u64 listen_session_get_handle(session_t *s)
Definition: session.h:623
ct_session_get_peer
session_t * ct_session_get_peer(session_t *s)
Definition: application_local.c:120
ct_connection_::ct_seg_index
u32 ct_seg_index
Definition: application_local.h:50
session_::tx_fifo
svm_fifo_t * tx_fifo
Definition: session_types.h:179
ct_session_dealloc_fifos
static void ct_session_dealloc_fifos(ct_connection_t *ct, svm_fifo_t *rx_fifo, svm_fifo_t *tx_fifo)
Definition: application_local.c:140
ct_half_open_add_reusable
void ct_half_open_add_reusable(u32 ho_index)
Definition: application_local.c:110
fifo_segment_t
Definition: fifo_segment.h:68
app_worker_get_listen_segment_manager
segment_manager_t * app_worker_get_listen_segment_manager(app_worker_t *, session_t *)
Definition: application_worker.c:531
session_
Definition: session_types.h:175
segment_manager_t
struct _segment_manager segment_manager_t
session_endpoint_cfg_t
struct _session_endpoint_cfg session_endpoint_cfg_t
application_segment_manager_properties
segment_manager_props_t * application_segment_manager_properties(application_t *app)
Definition: application.c:1656
session_handle_t
u64 session_handle_t
Definition: session_types.h:111
ct_segment_::flags
ct_segment_flags_t flags
Definition: application_local.c:32
transport_proto_vft_t
struct _transport_proto_vft transport_proto_vft_t
ct_session_connect_notify
int ct_session_connect_notify(session_t *ss, session_error_t err)
Definition: application_local.c:279
listen_session_get
static session_t * listen_session_get(u32 ls_index)
Definition: session.h:654
application_::app_index
u32 app_index
App index in app pool.
Definition: application.h:111
session_half_open_migrated_notify
int session_half_open_migrated_notify(transport_connection_t *tc)
Definition: session.c:373
ct_connection_::server_wrk
u32 server_wrk
Definition: application_local.h:45
session_::thread_index
u8 thread_index
Index of the thread that allocated the session.
Definition: session_types.h:194
pool_put
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:305
session_::session_type
session_type_t session_type
Type built from transport and network protocol types.
Definition: session_types.h:182
vm
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
Definition: nat44_ei.c:3047
ct_main_::ho_reusable
u32 * ho_reusable
Vector of reusable ho indices.
Definition: application_local.c:49
session_endpoint_is_local
static u8 session_endpoint_is_local(session_endpoint_t *sep)
Definition: session_types.h:98
ct_connection_::flags
ct_connection_flags_t flags
Definition: application_local.h:54
application_
Definition: application.h:108
ct_segments_::server_wrk
u32 server_wrk
Definition: application_local.c:38
transport_connection_t
struct _transport_connection transport_connection_t
app_worker_del_segment_notify
int app_worker_del_segment_notify(app_worker_t *app_wrk, u64 segment_handle)
Definition: application_worker.c:600
clib_rwlock_reader_lock
static void clib_rwlock_reader_lock(clib_rwlock_t *p)
Definition: lock.h:169
transport_endpoint_pair_
Definition: transport_types.h:216
clib_rwlock_reader_unlock
static void clib_rwlock_reader_unlock(clib_rwlock_t *p)
Definition: lock.h:184
session_free
void session_free(session_t *s)
Definition: session.c:227
pool_put_index
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:337
clib_rwlock_writer_unlock
static void clib_rwlock_writer_unlock(clib_rwlock_t *p)
Definition: lock.h:206
error
Definition: cJSON.c:88
hash_unset
#define hash_unset(h, key)
Definition: hash.h:261
ct_segments_::sm_index
u32 sm_index
Definition: application_local.c:37
application_local.h
segment_manager_app_detached
u8 segment_manager_app_detached(segment_manager_t *sm)
Definition: segment_manager.c:67
svm_fifo_t
struct _svm_fifo svm_fifo_t
pool_is_free_index
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:302
app_worker_cleanup_notify
int app_worker_cleanup_notify(app_worker_t *app_wrk, session_t *s, session_cleanup_ntf_t ntf)
Definition: application_worker.c:432
application_get
application_t * application_get(u32 app_index)
Definition: application.c:710
session_::app_wrk_index
u32 app_wrk_index
Index of the app worker that owns the session.
Definition: session_types.h:191
application_has_global_scope
u8 application_has_global_scope(application_t *app)
Definition: application.c:1518
pool_foreach
#define pool_foreach(VAR, POOL)
Iterate through pool.
Definition: pool.h:534
app_worker_init_connected
int app_worker_init_connected(app_worker_t *app_wrk, session_t *s)
Definition: application_worker.c:358
TRANSPORT_SND_F_DESCHED
@ TRANSPORT_SND_F_DESCHED
Definition: transport.h:40
ct_lookup_free_segment
static ct_segment_t * ct_lookup_free_segment(ct_main_t *cm, segment_manager_t *sm, u32 seg_ctx_index)
Definition: application_local.c:361
session_::rx_fifo
svm_fifo_t * rx_fifo
Pointers to rx/tx buffers.
Definition: session_types.h:178
ct_session_close
static void ct_session_close(u32 ct_index, u32 thread_index)
Definition: application_local.c:867
app_listener_::app_index
u32 app_index
owning app index
Definition: application.h:84
ct_segments_::client_wrk
u32 client_wrk
Definition: application_local.c:39
session_::app_index
u32 app_index
Index of application that owns the listener.
Definition: session_types.h:203
vec_add1
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:606
segment_manager_dealloc_fifos
void segment_manager_dealloc_fifos(svm_fifo_t *rx_fifo, svm_fifo_t *tx_fifo)
Definition: segment_manager.c:825
session_get_transport
transport_connection_t * session_get_transport(session_t *s)
Definition: session.c:1743
ct_listener_get
static transport_connection_t * ct_listener_get(u32 ct_index)
Definition: application_local.c:769
session_lookup_listener_wildcard
session_t * session_lookup_listener_wildcard(u32 table_index, session_endpoint_t *sep)
Lookup listener wildcard match.
Definition: session_lookup.c:769
segment_manager_props_t
struct _segment_manager_props segment_manager_props_t
ct_connection_::segment_handle
u64 segment_handle
Definition: application_local.h:48
PREDICT_FALSE
#define PREDICT_FALSE(x)
Definition: clib.h:124
vlib_get_thread_index
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:187
app_worker_get_if_valid
app_worker_t * app_worker_get_if_valid(u32 wrk_index)
Definition: application_worker.c:47
application_listener_select_worker
app_worker_t * application_listener_select_worker(session_t *ls)
Definition: application.c:998
hash_get
#define hash_get(h, key)
Definition: hash.h:249
clib_spinlock_lock
static_always_inline void clib_spinlock_lock(clib_spinlock_t *p)
Definition: lock.h:82
clib_spinlock_s
Definition: lock.h:51
clib_rw_lock_
Definition: lock.h:139
session_endpoint_fib_proto
static u8 session_endpoint_fib_proto(session_endpoint_t *sep)
Definition: session_types.h:92
clib_rwlock_writer_lock
static void clib_rwlock_writer_lock(clib_rwlock_t *p)
Definition: lock.h:192
uword
u64 uword
Definition: types.h:112
ct_connection_::client_rx_fifo
svm_fifo_t * client_rx_fifo
Definition: application_local.h:51
segment_manager_segment_reader_unlock
void segment_manager_segment_reader_unlock(segment_manager_t *sm)
Definition: segment_manager.c:324
segment_manager_get_segment
fifo_segment_t * segment_manager_get_segment(segment_manager_t *sm, u32 segment_index)
Reads a segment from the segment manager's pool without lock.
Definition: segment_manager.c:269
ct_segment_flags_
ct_segment_flags_
Definition: application_local.c:19
ct_connection_::peer_index
u32 peer_index
Definition: application_local.h:47
session_half_open_migrate_notify
void session_half_open_migrate_notify(transport_connection_t *tc)
Definition: session.c:363
transport_register_protocol
void transport_register_protocol(transport_proto_t transport_proto, const transport_proto_vft_t *vft, fib_protocol_t fib_proto, u32 output_node)
Register transport virtual function table.
Definition: transport.c:246
ct_segments_::segments
ct_segment_t * segments
Definition: application_local.c:41
segment_manager_segment_handle
u64 segment_manager_segment_handle(segment_manager_t *sm, fifo_segment_t *segment)
Definition: segment_manager.c:275
cm
vnet_feature_config_main_t * cm
Definition: nat44_ei_hairpinning.c:594
ct_segment_::seg_ctx_index
u32 seg_ctx_index
Definition: application_local.c:29
segment_manager_lock_and_del_segment
void segment_manager_lock_and_del_segment(segment_manager_t *sm, u32 fs_index)
Definition: segment_manager.c:260
session_lookup_local_endpoint
u64 session_lookup_local_endpoint(u32 table_index, session_endpoint_t *sep)
Look up endpoint in local session table.
Definition: session_lookup.c:546
ct_segment_::ct_seg_index
u32 ct_seg_index
Definition: application_local.c:30
vec_validate
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment)
Definition: vec.h:523
ct_connection_get
static ct_connection_t * ct_connection_get(u32 ct_index, u32 thread_index)
Definition: application_local.c:74
format_ct_session
static u8 * format_ct_session(u8 *s, va_list *args)
Definition: application_local.c:1024
SESSION_DROP_HANDLE
#define SESSION_DROP_HANDLE
Definition: session_table.h:58
FIB_PROTOCOL_IP4
@ FIB_PROTOCOL_IP4
Definition: fib_types.h:36
format_ct_connection_id
static u8 * format_ct_connection_id(u8 *s, va_list *args)
Definition: application_local.c:921
segment_manager_index
u32 segment_manager_index(segment_manager_t *sm)
Definition: segment_manager.c:561
session_get
static session_t * session_get(u32 si, u32 thread_index)
Definition: session.h:337
session_transport_delete_notify
void session_transport_delete_notify(transport_connection_t *tc)
Notification from transport that connection is being deleted.
Definition: session.c:1084
app_worker_connect_notify
int app_worker_connect_notify(app_worker_t *app_wrk, session_t *s, session_error_t err, u32 opaque)
Definition: application_worker.c:375
clib_rwlock_init
static void clib_rwlock_init(clib_rwlock_t *p)
Definition: lock.h:152
ct_main_::n_workers
u32 n_workers
Number of vpp workers.
Definition: application_local.c:47
ct_segments_
Definition: application_local.c:35
ct_connection_::actual_tp
transport_proto_t actual_tp
Definition: application_local.h:53
TRANSPORT_TX_INTERNAL
@ TRANSPORT_TX_INTERNAL
apps acting as transports
Definition: transport_types.h:32
session_::listener_handle
session_handle_t listener_handle
Parent listener session index if the result of an accept.
Definition: session_types.h:208
session_type_from_proto_and_ip
static session_type_t session_type_from_proto_and_ip(transport_proto_t proto, u8 is_ip4)
Definition: session_types.h:224
transport_send_params_
Definition: transport.h:45
TRANSPORT_SERVICE_VC
@ TRANSPORT_SERVICE_VC
virtual circuit service
Definition: transport_types.h:39
application_local_session_table
u32 application_local_session_table(application_t *app)
Definition: application.c:373
ct_connection_::connection
transport_connection_t connection
Definition: application_local.h:43
fifo_segment_num_fifos
u32 fifo_segment_num_fifos(fifo_segment_t *fs)
Get number of active fifos.
Definition: fifo_segment.c:1275
ct_stop_listen
static u32 ct_stop_listen(u32 ct_index)
Definition: application_local.c:760
fifo_segment_free_fifo
void fifo_segment_free_fifo(fifo_segment_t *fs, svm_fifo_t *f)
Free fifo allocated in fifo segment.
Definition: fifo_segment.c:919
ct_init_accepted_session
static int ct_init_accepted_session(app_worker_t *server_wrk, ct_connection_t *ct, session_t *ls, session_t *ll)
Definition: application_local.c:480
TRANSPORT_CONNECTION_F_NO_LOOKUP
@ TRANSPORT_CONNECTION_F_NO_LOOKUP
Don't register connection in lookup.
Definition: transport_types.h:52
u64
unsigned long u64
Definition: types.h:89
format
description fragment has unexpected format
Definition: map.api:433
ASSERT
#define ASSERT(truth)
Definition: error_bootstrap.h:69
ct_half_open_get
static transport_connection_t * ct_half_open_get(u32 ct_index)
Definition: application_local.c:775
ct_main_::app_segs_lock
clib_rwlock_t app_segs_lock
RW lock for seg contexts.
Definition: application_local.c:51
ct_main_t
struct ct_main_ ct_main_t
app_worker_add_segment_notify
int app_worker_add_segment_notify(app_worker_t *app_wrk, u64 segment_handle)
Send an API message to the external app, to map new segment.
Definition: application_worker.c:591
u32
unsigned int u32
Definition: types.h:88
SESSION_CLEANUP_SESSION
@ SESSION_CLEANUP_SESSION
Definition: session_types.h:116
VLIB_INIT_FUNCTION
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:172
listen_session_get_transport
transport_connection_t * listen_session_get_transport(session_t *s)
Definition: session.c:1778
ip_copy
void ip_copy(ip46_address_t *dst, ip46_address_t *src, u8 is_ip4)
Definition: ip.c:83
transport_endpoint_
Definition: transport_types.h:193
ct_main_::n_sessions
u32 n_sessions
Cumulative sessions counter.
Definition: application_local.c:48
FIB_PROTOCOL_IP6
@ FIB_PROTOCOL_IP6
Definition: fib_types.h:37
ct_connection_::seg_ctx_index
u32 seg_ctx_index
Definition: application_local.h:49
app_worker_get
app_worker_t * app_worker_get(u32 wrk_index)
Definition: application_worker.c:41
app_worker_
Definition: application.h:32
ct_segment_flags_t
enum ct_segment_flags_ ct_segment_flags_t
ct_main_::connections
ct_connection_t ** connections
Per-worker connection pools.
Definition: application_local.c:46
vec_foreach
#define vec_foreach(var, vec)
Vector iterator.
Definition: vec_bootstrap.h:213
ct_main_::app_segs_ctxs_table
uword * app_segs_ctxs_table
App handle to segment pool map.
Definition: application_local.c:52
ct_connection_::client_opaque
u32 client_opaque
Definition: application_local.h:46
ct_cleanup_ho
static void ct_cleanup_ho(u32 ho_index)
Definition: application_local.c:797
session_endpoint_t
struct _session_endpoint session_endpoint_t
pool_elts
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:127
ct_connection_free
static void ct_connection_free(ct_connection_t *ct)
Definition: application_local.c:82
ct_connection_::client_tx_fifo
svm_fifo_t * client_tx_fifo
Definition: application_local.h:52
clib_spinlock_unlock
static_always_inline void clib_spinlock_unlock(clib_spinlock_t *p)
Definition: lock.h:121
ct_segments_::fifo_pair_bytes
u32 fifo_pair_bytes
Definition: application_local.c:40
SESSION_INVALID_HANDLE
#define SESSION_INVALID_HANDLE
Definition: session_types.h:23
ct_transport_init
static clib_error_t * ct_transport_init(vlib_main_t *vm)
Definition: application_local.c:1097
fifo_segment_available_bytes
uword fifo_segment_available_bytes(fifo_segment_t *fs)
Definition: fifo_segment.c:1415
segment_manager_has_fifos
u8 segment_manager_has_fifos(segment_manager_t *sm)
Definition: segment_manager.c:567
app_worker_get_connect_segment_manager
segment_manager_t * app_worker_get_connect_segment_manager(app_worker_t *)
Definition: application_worker.c:524
ct_session_tx
int ct_session_tx(session_t *s)
Definition: application_local.c:1081
vlib_main_t
Definition: main.h:102
FIFO_SEGMENT_F_CUSTOM_USE
@ FIFO_SEGMENT_F_CUSTOM_USE
Definition: fifo_segment.h:41
CT_SEGMENT_F_CLIENT_DETACHED
@ CT_SEGMENT_F_CLIENT_DETACHED
Definition: application_local.c:21
fifo_segment_size
uword fifo_segment_size(fifo_segment_t *fs)
Fifo segment allocated size.
Definition: fifo_segment.c:1375
pool_get_zero
#define pool_get_zero(P, E)
Allocate an object E from a pool P and zero it.
Definition: pool.h:258
u8
unsigned char u8
Definition: types.h:56
clib_error_t
Definition: clib_error.h:21
ct_segment_::client_n_sessions
u32 client_n_sessions
Definition: application_local.c:27
vlib_init_function_t
clib_error_t *() vlib_init_function_t(struct vlib_main_t *vm)
Definition: init.h:51
format_ip6_address
format_function_t format_ip6_address
Definition: format.h:91
ct_session_endpoint
void ct_session_endpoint(session_t *ll, session_endpoint_t *sep)
Definition: application_local.c:129
uword_to_pointer
#define uword_to_pointer(u, type)
Definition: types.h:136
ct_segment_
Definition: application_local.c:25
session.h
pool_free
#define pool_free(p)
Free a pool.
Definition: pool.h:447
cut_thru_proto
static const transport_proto_vft_t cut_thru_proto
Definition: application_local.c:1055
transport_send_params_::flags
transport_snd_flags_t flags
Definition: transport.h:62
ct_segment_t
struct ct_segment_ ct_segment_t
ct_app_rx_evt
static int ct_app_rx_evt(transport_connection_t *tc)
Definition: application_local.c:966
ct_main
static ct_main_t ct_main
Definition: application_local.c:56
format_ct_connection
static u8 * format_ct_connection(u8 *s, va_list *args)
Definition: application_local.c:1004
segment_manager_free_safe
void segment_manager_free_safe(segment_manager_t *sm)
Definition: segment_manager.c:517
ct_alloc_segment
static ct_segment_t * ct_alloc_segment(ct_main_t *cm, app_worker_t *server_wrk, u64 table_handle, segment_manager_t *sm, u32 client_wrk_index)
Definition: application_local.c:394
rv
int __clib_unused rv
Definition: application.c:491
session_free_w_fifos
void session_free_w_fifos(session_t *s)
Definition: session.c:279
segment_manager_add_segment2
int segment_manager_add_segment2(segment_manager_t *sm, uword segment_size, u8 flags)
Definition: segment_manager.c:193
app_listener_get_w_session
app_listener_t * app_listener_get_w_session(session_t *ls)
Definition: application.c:67
ct_session_get
static transport_connection_t * ct_session_get(u32 ct_index, u32 thread_index)
Definition: application_local.c:914
ct_segment_::server_n_sessions
u32 server_n_sessions
Definition: application_local.c:28
ct_segment_::segment_index
u32 segment_index
Definition: application_local.c:31
format_ct_half_open
static u8 * format_ct_half_open(u8 *s, va_list *args)
Definition: application_local.c:992
ct_main_::ho_reuseable_lock
clib_spinlock_t ho_reuseable_lock
Lock for reusable ho indices.
Definition: application_local.c:50
ct_connection_::client_wrk
u32 client_wrk
Definition: application_local.h:44
app_worker_::app_index
u32 app_index
Index of owning app.
Definition: application.h:43
session_has_transport
static u8 session_has_transport(session_t *s)
Definition: session_types.h:255
ct_main_
Definition: application_local.c:44
ct_session_cleanup
static void ct_session_cleanup(u32 conn_index, u32 thread_index)
Definition: application_local.c:781
ct_connect
static int ct_connect(app_worker_t *client_wrk, session_t *ll, session_endpoint_cfg_t *sep)
Definition: application_local.c:697
format_transport_proto_short
u8 * format_transport_proto_short(u8 *s, va_list *args)
Definition: transport.c:65
session_lookup_get_index_for_fib
u32 session_lookup_get_index_for_fib(u32 fib_proto, u32 fib_index)
Definition: session_lookup.c:210
ct_enable_disable
clib_error_t * ct_enable_disable(vlib_main_t *vm, u8 is_en)
Definition: application_local.c:1043
app_worker_accept_notify
int app_worker_accept_notify(app_worker_t *app_wrk, session_t *s)
Definition: application_worker.c:351
session_alloc
session_t * session_alloc(u32 thread_index)
Definition: session.c:201
ct_session_connect
static int ct_session_connect(transport_endpoint_cfg_t *tep)
Definition: application_local.c:803
session_::session_state
volatile u8 session_state
State in session layer state machine.
Definition: session_types.h:185
session_::connection_index
u32 connection_index
Index of the transport connection associated to the session.
Definition: session_types.h:200
ct_accept_rpc_wrk_handler
static void ct_accept_rpc_wrk_handler(void *accept_args)
Definition: application_local.c:590
segment_manager_try_alloc_fifos
int segment_manager_try_alloc_fifos(fifo_segment_t *fifo_segment, u32 thread_index, u32 rx_fifo_size, u32 tx_fifo_size, svm_fifo_t **rx_fifo, svm_fifo_t **tx_fifo)
Definition: segment_manager.c:698
listen_session_get_from_handle
static session_t * listen_session_get_from_handle(session_handle_t handle)
Definition: session.h:631
session_send_rpc_evt_to_thread_force
void session_send_rpc_evt_to_thread_force(u32 thread_index, void *fp, void *rpc_args)
Definition: session.c:108
segment_manager_make_segment_handle
u64 segment_manager_make_segment_handle(u32 segment_manager_index, u32 segment_index)
Definition: segment_manager.c:283
app_listener_
Definition: application.h:79