LCOV - code coverage report
Current view: top level - vcl - vcl_private.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 234 421 55.6 %
Date: 2023-07-05 22:20:52 Functions: 20 33 60.6 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2018-2019 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this
       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 <vcl/vcl_private.h>
      17             : 
      18             : static pthread_key_t vcl_worker_stop_key;
      19             : 
      20             : vcl_mq_evt_conn_t *
      21           0 : vcl_mq_evt_conn_alloc (vcl_worker_t * wrk)
      22             : {
      23             :   vcl_mq_evt_conn_t *mqc;
      24           0 :   pool_get (wrk->mq_evt_conns, mqc);
      25           0 :   memset (mqc, 0, sizeof (*mqc));
      26           0 :   return mqc;
      27             : }
      28             : 
      29             : u32
      30           0 : vcl_mq_evt_conn_index (vcl_worker_t * wrk, vcl_mq_evt_conn_t * mqc)
      31             : {
      32           0 :   return (mqc - wrk->mq_evt_conns);
      33             : }
      34             : 
      35             : vcl_mq_evt_conn_t *
      36           0 : vcl_mq_evt_conn_get (vcl_worker_t * wrk, u32 mq_conn_idx)
      37             : {
      38           0 :   return pool_elt_at_index (wrk->mq_evt_conns, mq_conn_idx);
      39             : }
      40             : 
      41             : /* Add unix socket to epoll.
      42             :  * Used only to get a notification on socket close
      43             :  * We can't use eventfd because we don't get notifications on that fds
      44             :  */
      45             : static int
      46           0 : vcl_mq_epoll_add_api_sock (vcl_worker_t *wrk)
      47             : {
      48           0 :   clib_socket_t *cs = &wrk->app_api_sock;
      49           0 :   struct epoll_event e = { 0 };
      50             :   int rv;
      51             : 
      52           0 :   e.data.u32 = ~0;
      53           0 :   rv = epoll_ctl (wrk->mqs_epfd, EPOLL_CTL_ADD, cs->fd, &e);
      54           0 :   if (rv != EEXIST && rv < 0)
      55           0 :     return -1;
      56             : 
      57           0 :   return 0;
      58             : }
      59             : 
      60             : int
      61           0 : vcl_mq_epoll_add_evfd (vcl_worker_t * wrk, svm_msg_q_t * mq)
      62             : {
      63           0 :   struct epoll_event e = { 0 };
      64             :   vcl_mq_evt_conn_t *mqc;
      65             :   u32 mqc_index;
      66             :   int mq_fd;
      67             : 
      68           0 :   mq_fd = svm_msg_q_get_eventfd (mq);
      69             : 
      70           0 :   if (wrk->mqs_epfd < 0 || mq_fd == -1)
      71           0 :     return -1;
      72             : 
      73           0 :   mqc = vcl_mq_evt_conn_alloc (wrk);
      74           0 :   mqc_index = vcl_mq_evt_conn_index (wrk, mqc);
      75           0 :   mqc->mq_fd = mq_fd;
      76           0 :   mqc->mq = mq;
      77             : 
      78           0 :   e.events = EPOLLIN;
      79           0 :   e.data.u32 = mqc_index;
      80           0 :   if (epoll_ctl (wrk->mqs_epfd, EPOLL_CTL_ADD, mq_fd, &e) < 0)
      81             :     {
      82           0 :       VDBG (0, "failed to add mq eventfd to mq epoll fd");
      83           0 :       return -1;
      84             :     }
      85             : 
      86           0 :   if (vcl_mq_epoll_add_api_sock (wrk))
      87             :     {
      88           0 :       VDBG (0, "failed to add mq socket to mq epoll fd");
      89           0 :       return -1;
      90             :     }
      91             : 
      92           0 :   return mqc_index;
      93             : }
      94             : 
      95             : int
      96           0 : vcl_mq_epoll_del_evfd (vcl_worker_t * wrk, u32 mqc_index)
      97             : {
      98             :   vcl_mq_evt_conn_t *mqc;
      99             : 
     100           0 :   if (wrk->mqs_epfd || mqc_index == ~0)
     101           0 :     return -1;
     102             : 
     103           0 :   mqc = vcl_mq_evt_conn_get (wrk, mqc_index);
     104           0 :   if (epoll_ctl (wrk->mqs_epfd, EPOLL_CTL_DEL, mqc->mq_fd, 0) < 0)
     105             :     {
     106           0 :       VDBG (0, "failed to del mq eventfd to mq epoll fd");
     107           0 :       return -1;
     108             :     }
     109           0 :   return 0;
     110             : }
     111             : 
     112             : static vcl_worker_t *
     113          37 : vcl_worker_alloc (void)
     114             : {
     115             :   vcl_worker_t *wrk;
     116          37 :   pool_get (vcm->workers, wrk);
     117          37 :   memset (wrk, 0, sizeof (*wrk));
     118          37 :   wrk->wrk_index = wrk - vcm->workers;
     119          37 :   wrk->forked_child = ~0;
     120          37 :   return wrk;
     121             : }
     122             : 
     123             : static void
     124          37 : vcl_worker_free (vcl_worker_t * wrk)
     125             : {
     126          37 :   pool_put (vcm->workers, wrk);
     127          37 : }
     128             : 
     129             : int
     130           0 : vcl_api_app_worker_add (void)
     131             : {
     132           0 :   if (vcm->cfg.vpp_app_socket_api)
     133           0 :     return vcl_sapi_app_worker_add ();
     134             : 
     135           0 :   return vcl_bapi_app_worker_add ();
     136             : }
     137             : 
     138             : void
     139          13 : vcl_api_app_worker_del (vcl_worker_t * wrk)
     140             : {
     141          13 :   if (wrk->api_client_handle == ~0)
     142           0 :     return;
     143             : 
     144          13 :   if (vcm->cfg.vpp_app_socket_api)
     145           2 :     return vcl_sapi_app_worker_del (wrk);
     146             : 
     147          11 :   vcl_bapi_app_worker_del (wrk);
     148             : }
     149             : 
     150             : void
     151          37 : vcl_worker_cleanup (vcl_worker_t * wrk, u8 notify_vpp)
     152             : {
     153          37 :   clib_spinlock_lock (&vcm->workers_lock);
     154          37 :   if (notify_vpp)
     155          13 :     vcl_api_app_worker_del (wrk);
     156             : 
     157          37 :   if (wrk->mqs_epfd > 0)
     158           0 :     close (wrk->mqs_epfd);
     159          37 :   pool_free (wrk->sessions);
     160          37 :   pool_free (wrk->mq_evt_conns);
     161          37 :   hash_free (wrk->session_index_by_vpp_handles);
     162          37 :   vec_free (wrk->mq_events);
     163          37 :   vec_free (wrk->mq_msg_vector);
     164          37 :   vec_free (wrk->unhandled_evts_vector);
     165          37 :   vec_free (wrk->pending_session_wrk_updates);
     166          37 :   clib_bitmap_free (wrk->rd_bitmap);
     167          37 :   clib_bitmap_free (wrk->wr_bitmap);
     168          37 :   clib_bitmap_free (wrk->ex_bitmap);
     169          37 :   vcl_worker_free (wrk);
     170          37 :   clib_spinlock_unlock (&vcm->workers_lock);
     171          37 : }
     172             : 
     173             : static void
     174           0 : vcl_worker_cleanup_cb (void *arg)
     175             : {
     176             :   vcl_worker_t *wrk;
     177             :   u32 wrk_index;
     178             : 
     179           0 :   wrk_index = vcl_get_worker_index ();
     180           0 :   wrk = vcl_worker_get_if_valid (wrk_index);
     181           0 :   if (!wrk)
     182           0 :     return;
     183             : 
     184           0 :   vcl_worker_cleanup (wrk, 1 /* notify vpp */ );
     185           0 :   vcl_set_worker_index (~0);
     186           0 :   VDBG (0, "cleaned up worker %u", wrk_index);
     187             : }
     188             : 
     189             : void
     190           0 : vcl_worker_detach_sessions (vcl_worker_t *wrk)
     191             : {
     192             :   session_event_t *e;
     193             :   vcl_session_t *s;
     194           0 :   uword *seg_indices_map = 0;
     195           0 :   u32 seg_index, val, *seg_indices = 0;
     196             : 
     197           0 :   close (wrk->app_api_sock.fd);
     198           0 :   pool_foreach (s, wrk->sessions)
     199             :     {
     200           0 :       if (s->session_state == VCL_STATE_LISTEN)
     201             :         {
     202           0 :           s->session_state = VCL_STATE_LISTEN_NO_MQ;
     203           0 :           continue;
     204             :         }
     205           0 :       if ((s->flags & VCL_SESSION_F_IS_VEP) ||
     206           0 :           s->session_state == VCL_STATE_LISTEN_NO_MQ ||
     207           0 :           s->session_state == VCL_STATE_CLOSED)
     208           0 :         continue;
     209             : 
     210           0 :       hash_set (seg_indices_map, s->tx_fifo->segment_index, 1);
     211             : 
     212           0 :       s->session_state = VCL_STATE_DETACHED;
     213           0 :       vec_add2 (wrk->unhandled_evts_vector, e, 1);
     214           0 :       e->event_type = SESSION_CTRL_EVT_DISCONNECTED;
     215           0 :       e->session_index = s->session_index;
     216           0 :       e->postponed = 1;
     217             :     }
     218             : 
     219           0 :   hash_foreach (seg_index, val, seg_indices_map,
     220             :                 ({ vec_add1 (seg_indices, seg_index); }));
     221             : 
     222           0 :   vcl_segment_detach_segments (seg_indices);
     223             : 
     224             :   /* Detach worker's mqs segment */
     225           0 :   vcl_segment_detach (vcl_vpp_worker_segment_handle (wrk->wrk_index));
     226             : 
     227           0 :   vec_free (seg_indices);
     228           0 :   hash_free (seg_indices_map);
     229           0 : }
     230             : 
     231             : vcl_worker_t *
     232          37 : vcl_worker_alloc_and_init ()
     233             : {
     234             :   vcl_worker_t *wrk;
     235             : 
     236             :   /* This was initialized already */
     237          37 :   if (vcl_get_worker_index () != ~0)
     238           0 :     return 0;
     239             : 
     240             :   /* Grab lock before selecting mem thread index */
     241          37 :   clib_spinlock_lock (&vcm->workers_lock);
     242             : 
     243             :   /* Use separate heap map entry for worker */
     244          37 :   clib_mem_set_thread_index ();
     245             : 
     246          37 :   if (pool_elts (vcm->workers) == vcm->cfg.max_workers)
     247             :     {
     248           0 :       VDBG (0, "max-workers %u limit reached", vcm->cfg.max_workers);
     249           0 :       wrk = 0;
     250           0 :       goto done;
     251             :     }
     252             : 
     253          37 :   wrk = vcl_worker_alloc ();
     254          37 :   vcl_set_worker_index (wrk->wrk_index);
     255          37 :   wrk->api_client_handle = ~0;
     256          37 :   wrk->thread_id = pthread_self ();
     257          37 :   wrk->current_pid = getpid ();
     258             : 
     259          37 :   wrk->mqs_epfd = -1;
     260          37 :   if (vcm->cfg.use_mq_eventfd)
     261             :     {
     262           0 :       wrk->vcl_needs_real_epoll = 1;
     263           0 :       wrk->mqs_epfd = epoll_create (1);
     264           0 :       wrk->vcl_needs_real_epoll = 0;
     265           0 :       if (wrk->mqs_epfd < 0)
     266             :         {
     267           0 :           clib_unix_warning ("epoll_create() returned");
     268           0 :           goto done;
     269             :         }
     270             :     }
     271             : 
     272          37 :   wrk->ep_lt_current = VCL_INVALID_SESSION_INDEX;
     273          37 :   wrk->session_index_by_vpp_handles = hash_create (0, sizeof (uword));
     274          37 :   clib_time_init (&wrk->clib_time);
     275          37 :   vec_validate (wrk->mq_events, 64);
     276          37 :   vec_validate (wrk->mq_msg_vector, 128);
     277          37 :   vec_reset_length (wrk->mq_msg_vector);
     278          37 :   vec_validate (wrk->unhandled_evts_vector, 128);
     279          37 :   vec_reset_length (wrk->unhandled_evts_vector);
     280             : 
     281           0 : done:
     282          37 :   clib_spinlock_unlock (&vcm->workers_lock);
     283          37 :   return wrk;
     284             : }
     285             : 
     286             : int
     287           0 : vcl_worker_register_with_vpp (void)
     288             : {
     289           0 :   vcl_worker_t *wrk = vcl_worker_get_current ();
     290             : 
     291           0 :   clib_spinlock_lock (&vcm->workers_lock);
     292             : 
     293           0 :   if (vcl_api_app_worker_add ())
     294             :     {
     295           0 :       VDBG (0, "failed to add worker to vpp");
     296           0 :       clib_spinlock_unlock (&vcm->workers_lock);
     297           0 :       return -1;
     298             :     }
     299           0 :   if (pthread_key_create (&vcl_worker_stop_key, vcl_worker_cleanup_cb))
     300           0 :     VDBG (0, "failed to add pthread cleanup function");
     301           0 :   if (pthread_setspecific (vcl_worker_stop_key, &wrk->thread_id))
     302           0 :     VDBG (0, "failed to setup key value");
     303             : 
     304           0 :   clib_spinlock_unlock (&vcm->workers_lock);
     305             : 
     306           0 :   VDBG (0, "added worker %u", wrk->wrk_index);
     307           0 :   return 0;
     308             : }
     309             : 
     310             : svm_msg_q_t *
     311         134 : vcl_worker_ctrl_mq (vcl_worker_t * wrk)
     312             : {
     313         134 :   return wrk->ctrl_mq;
     314             : }
     315             : 
     316             : int
     317    50345200 : vcl_session_read_ready (vcl_session_t * s)
     318             : {
     319    50345200 :   if (PREDICT_FALSE (s->flags & VCL_SESSION_F_IS_VEP))
     320             :     {
     321           0 :       VDBG (0, "ERROR: session %u: cannot read from an epoll session!",
     322             :             s->session_index);
     323           0 :       return VPPCOM_EBADFD;
     324             :     }
     325             : 
     326    50345200 :   if (vcl_session_is_open (s))
     327             :     {
     328    36132900 :       if (vcl_session_is_ct (s))
     329       17694 :         return svm_fifo_max_dequeue_cons (s->ct_rx_fifo);
     330             : 
     331    36115200 :       if (s->is_dgram)
     332             :         {
     333             :           session_dgram_pre_hdr_t ph;
     334             :           u32 max_deq;
     335             : 
     336     6974220 :           max_deq = svm_fifo_max_dequeue_cons (s->rx_fifo);
     337     6974220 :           if (max_deq <= SESSION_CONN_HDR_LEN)
     338     6972930 :             return 0;
     339        1292 :           if (svm_fifo_peek (s->rx_fifo, 0, sizeof (ph), (u8 *) & ph) < 0)
     340           0 :             return 0;
     341        1292 :           if (ph.data_length + SESSION_CONN_HDR_LEN > max_deq)
     342           0 :             return 0;
     343             : 
     344        1292 :           return ph.data_length;
     345             :         }
     346             : 
     347    29140900 :       return svm_fifo_max_dequeue_cons (s->rx_fifo);
     348             :     }
     349    14212400 :   else if (s->session_state == VCL_STATE_LISTEN)
     350             :     {
     351    14212400 :       return clib_fifo_elts (s->accept_evts_fifo);
     352             :     }
     353             :   else
     354             :     {
     355           0 :       return (s->session_state == VCL_STATE_DISCONNECT) ?
     356           0 :         VPPCOM_ECONNRESET : VPPCOM_ENOTCONN;
     357             :     }
     358             : }
     359             : 
     360             : int
     361     7627220 : vcl_session_write_ready (vcl_session_t * s)
     362             : {
     363     7627220 :   if (PREDICT_FALSE (s->flags & VCL_SESSION_F_IS_VEP))
     364             :     {
     365           0 :       VDBG (0, "session %u [0x%llx]: cannot write to an epoll session!",
     366             :             s->session_index, s->vpp_handle);
     367           0 :       return VPPCOM_EBADFD;
     368             :     }
     369             : 
     370     7627220 :   if (vcl_session_is_open (s))
     371             :     {
     372     7627210 :       if (vcl_session_is_ct (s))
     373       17689 :         return svm_fifo_max_enqueue_prod (s->ct_tx_fifo);
     374             : 
     375     7609520 :       if (s->is_dgram)
     376             :         {
     377        1416 :           u32 max_enq = svm_fifo_max_enqueue_prod (s->tx_fifo);
     378             : 
     379        1416 :           if (max_enq <= sizeof (session_dgram_hdr_t))
     380           0 :             return 0;
     381        1416 :           return max_enq - sizeof (session_dgram_hdr_t);
     382             :         }
     383             : 
     384     7608110 :       return svm_fifo_max_enqueue_prod (s->tx_fifo);
     385             :     }
     386           3 :   else if (s->session_state == VCL_STATE_LISTEN)
     387             :     {
     388           0 :       if (s->tx_fifo)
     389           0 :         return svm_fifo_max_enqueue_prod (s->tx_fifo);
     390             :       else
     391           0 :         return VPPCOM_EBADFD;
     392             :     }
     393           3 :   else if (s->session_state == VCL_STATE_UPDATED)
     394             :     {
     395           0 :       return 0;
     396             :     }
     397             :   else
     398             :     {
     399           3 :       return (s->session_state == VCL_STATE_DISCONNECT) ?
     400           3 :         VPPCOM_ECONNRESET : VPPCOM_ENOTCONN;
     401             :     }
     402             : }
     403             : 
     404             : int
     405           6 : vcl_session_alloc_ext_cfg (vcl_session_t *s,
     406             :                            transport_endpt_ext_cfg_type_t type, u32 len)
     407             : {
     408           6 :   if (s->ext_config)
     409           0 :     return -1;
     410             : 
     411           6 :   s->ext_config = clib_mem_alloc (len);
     412           6 :   clib_memset (s->ext_config, 0, len);
     413           6 :   s->ext_config->len = len;
     414           6 :   s->ext_config->type = type;
     415             : 
     416           6 :   return 0;
     417             : }
     418             : 
     419             : int
     420         111 : vcl_segment_attach (u64 segment_handle, char *name, ssvm_segment_type_t type,
     421             :                     int fd)
     422             : {
     423         111 :   fifo_segment_create_args_t _a, *a = &_a;
     424             :   int rv;
     425             : 
     426         111 :   memset (a, 0, sizeof (*a));
     427         111 :   a->segment_name = name;
     428         111 :   a->segment_type = type;
     429             : 
     430         111 :   if (type == SSVM_SEGMENT_MEMFD)
     431         111 :     a->memfd_fd = fd;
     432             : 
     433         111 :   clib_rwlock_writer_lock (&vcm->segment_table_lock);
     434             : 
     435         111 :   if ((rv = fifo_segment_attach (&vcm->segment_main, a)))
     436             :     {
     437           0 :       clib_warning ("svm_fifo_segment_attach ('%s') failed", name);
     438           0 :       clib_rwlock_writer_unlock (&vcm->segment_table_lock);
     439           0 :       return rv;
     440             :     }
     441         111 :   hash_set (vcm->segment_table, segment_handle, a->new_segment_indices[0]);
     442             : 
     443         111 :   clib_rwlock_writer_unlock (&vcm->segment_table_lock);
     444             : 
     445         111 :   vec_free (a->new_segment_indices);
     446         111 :   return 0;
     447             : }
     448             : 
     449             : u32
     450         307 : vcl_segment_table_lookup (u64 segment_handle)
     451             : {
     452             :   uword *seg_indexp;
     453             : 
     454         307 :   clib_rwlock_reader_lock (&vcm->segment_table_lock);
     455         307 :   seg_indexp = hash_get (vcm->segment_table, segment_handle);
     456         307 :   clib_rwlock_reader_unlock (&vcm->segment_table_lock);
     457             : 
     458         307 :   if (!seg_indexp)
     459           0 :     return VCL_INVALID_SEGMENT_INDEX;
     460         307 :   return ((u32) * seg_indexp);
     461             : }
     462             : 
     463             : void
     464           4 : vcl_segment_detach (u64 segment_handle)
     465             : {
     466           4 :   fifo_segment_main_t *sm = &vcm->segment_main;
     467             :   fifo_segment_t *segment;
     468             :   u32 segment_index;
     469             : 
     470           4 :   segment_index = vcl_segment_table_lookup (segment_handle);
     471           4 :   if (segment_index == (u32) ~ 0)
     472           0 :     return;
     473             : 
     474           4 :   clib_rwlock_writer_lock (&vcm->segment_table_lock);
     475             : 
     476           4 :   segment = fifo_segment_get_segment (sm, segment_index);
     477           4 :   fifo_segment_delete (sm, segment);
     478           4 :   hash_unset (vcm->segment_table, segment_handle);
     479             : 
     480           4 :   clib_rwlock_writer_unlock (&vcm->segment_table_lock);
     481             : 
     482           4 :   VDBG (0, "detached segment %u handle %lx", segment_index, segment_handle);
     483             : }
     484             : 
     485             : void
     486           0 : vcl_segment_detach_segments (u32 *seg_indices)
     487             : {
     488           0 :   u64 *seg_handles = 0, *seg_handle, key;
     489             :   u32 *seg_index;
     490             :   u32 val;
     491             : 
     492           0 :   clib_rwlock_reader_lock (&vcm->segment_table_lock);
     493             : 
     494           0 :   vec_foreach (seg_index, seg_indices)
     495             :     {
     496             :       /* clang-format off */
     497           0 :       hash_foreach (key, val, vcm->segment_table, ({
     498             :         if (val == *seg_index)
     499             :           {
     500             :             vec_add1 (seg_handles, key);
     501             :             break;
     502             :           }
     503             :       }));
     504             :       /* clang-format on */
     505             :     }
     506             : 
     507           0 :   clib_rwlock_reader_unlock (&vcm->segment_table_lock);
     508             : 
     509           0 :   vec_foreach (seg_handle, seg_handles)
     510           0 :     vcl_segment_detach (seg_handle[0]);
     511             : 
     512           0 :   vec_free (seg_handles);
     513           0 : }
     514             : 
     515             : int
     516          99 : vcl_segment_attach_session (uword segment_handle, uword rxf_offset,
     517             :                             uword txf_offset, uword mq_offset, u32 mq_index,
     518             :                             u8 is_ct, vcl_session_t *s)
     519             : {
     520             :   u32 fs_index, eqs_index;
     521             :   svm_fifo_t *rxf, *txf;
     522             :   fifo_segment_t *fs;
     523             :   u64 eqs_handle;
     524             : 
     525          99 :   fs_index = vcl_segment_table_lookup (segment_handle);
     526          99 :   if (fs_index == VCL_INVALID_SEGMENT_INDEX)
     527             :     {
     528           0 :       VDBG (0, "ERROR: segment for session %u is not mounted!",
     529             :             s->session_index);
     530           0 :       return -1;
     531             :     }
     532             : 
     533          99 :   if (!is_ct && mq_offset != (uword) ~0)
     534             :     {
     535          87 :       eqs_handle = vcl_vpp_worker_segment_handle (0);
     536          87 :       eqs_index = vcl_segment_table_lookup (eqs_handle);
     537          87 :       ASSERT (eqs_index != VCL_INVALID_SEGMENT_INDEX);
     538             :     }
     539             : 
     540          99 :   clib_rwlock_reader_lock (&vcm->segment_table_lock);
     541             : 
     542          99 :   fs = fifo_segment_get_segment (&vcm->segment_main, fs_index);
     543          99 :   rxf = fifo_segment_alloc_fifo_w_offset (fs, rxf_offset);
     544          99 :   txf = fifo_segment_alloc_fifo_w_offset (fs, txf_offset);
     545          99 :   rxf->segment_index = fs_index;
     546          99 :   txf->segment_index = fs_index;
     547             : 
     548          99 :   if (!is_ct && mq_offset != (uword) ~0)
     549             :     {
     550          87 :       fs = fifo_segment_get_segment (&vcm->segment_main, eqs_index);
     551          87 :       s->vpp_evt_q = fifo_segment_msg_q_attach (fs, mq_offset, mq_index);
     552             :     }
     553             : 
     554          99 :   clib_rwlock_reader_unlock (&vcm->segment_table_lock);
     555             : 
     556          99 :   if (!is_ct)
     557             :     {
     558          87 :       rxf->shr->client_session_index = s->session_index;
     559          87 :       txf->shr->client_session_index = s->session_index;
     560          87 :       rxf->client_thread_index = vcl_get_worker_index ();
     561          87 :       txf->client_thread_index = vcl_get_worker_index ();
     562          87 :       s->rx_fifo = rxf;
     563          87 :       s->tx_fifo = txf;
     564             :     }
     565             :   else
     566             :     {
     567          12 :       s->ct_rx_fifo = rxf;
     568          12 :       s->ct_tx_fifo = txf;
     569             :     }
     570             : 
     571          99 :   return 0;
     572             : }
     573             : 
     574             : void
     575          24 : vcl_session_detach_fifos (vcl_session_t *s)
     576             : {
     577             :   fifo_segment_t *fs;
     578             : 
     579          24 :   if (!s->rx_fifo)
     580           7 :     return;
     581             : 
     582          17 :   clib_rwlock_reader_lock (&vcm->segment_table_lock);
     583             : 
     584          17 :   fs = fifo_segment_get_segment_if_valid (&vcm->segment_main,
     585          17 :                                           s->rx_fifo->segment_index);
     586          17 :   if (!fs)
     587           0 :     goto done;
     588             : 
     589          17 :   fifo_segment_free_client_fifo (fs, s->rx_fifo);
     590          17 :   fifo_segment_free_client_fifo (fs, s->tx_fifo);
     591          17 :   if (s->ct_rx_fifo)
     592             :     {
     593           4 :       fs = fifo_segment_get_segment_if_valid (&vcm->segment_main,
     594           4 :                                               s->ct_rx_fifo->segment_index);
     595           4 :       if (!fs)
     596           0 :         goto done;
     597             : 
     598           4 :       fifo_segment_free_client_fifo (fs, s->ct_rx_fifo);
     599           4 :       fifo_segment_free_client_fifo (fs, s->ct_tx_fifo);
     600             :     }
     601             : 
     602          13 : done:
     603          17 :   clib_rwlock_reader_unlock (&vcm->segment_table_lock);
     604             : }
     605             : 
     606             : int
     607          74 : vcl_segment_attach_mq (uword segment_handle, uword mq_offset, u32 mq_index,
     608             :                        svm_msg_q_t **mq)
     609             : {
     610             :   fifo_segment_t *fs;
     611             :   u32 fs_index;
     612             : 
     613          74 :   fs_index = vcl_segment_table_lookup (segment_handle);
     614          74 :   if (fs_index == VCL_INVALID_SEGMENT_INDEX)
     615             :     {
     616           0 :       VDBG (0, "ERROR: mq segment %lx for is not attached!", segment_handle);
     617           0 :       return -1;
     618             :     }
     619             : 
     620          74 :   clib_rwlock_reader_lock (&vcm->segment_table_lock);
     621             : 
     622          74 :   fs = fifo_segment_get_segment (&vcm->segment_main, fs_index);
     623          74 :   *mq = fifo_segment_msg_q_attach (fs, mq_offset, mq_index);
     624             : 
     625          74 :   clib_rwlock_reader_unlock (&vcm->segment_table_lock);
     626             : 
     627          74 :   return 0;
     628             : }
     629             : 
     630             : int
     631          37 : vcl_segment_discover_mqs (uword segment_handle, int *fds, u32 n_fds)
     632             : {
     633             :   fifo_segment_t *fs;
     634             :   u32 fs_index;
     635             : 
     636          37 :   fs_index = vcl_segment_table_lookup (segment_handle);
     637          37 :   if (fs_index == VCL_INVALID_SEGMENT_INDEX)
     638             :     {
     639           0 :       VDBG (0, "ERROR: mq segment %lx for is not attached!", segment_handle);
     640           0 :       return -1;
     641             :     }
     642             : 
     643          37 :   clib_rwlock_reader_lock (&vcm->segment_table_lock);
     644             : 
     645          37 :   fs = fifo_segment_get_segment (&vcm->segment_main, fs_index);
     646          37 :   fifo_segment_msg_qs_discover (fs, fds, n_fds);
     647             : 
     648          37 :   clib_rwlock_reader_unlock (&vcm->segment_table_lock);
     649             : 
     650          37 :   return 0;
     651             : }
     652             : 
     653             : svm_fifo_chunk_t *
     654           6 : vcl_segment_alloc_chunk (uword segment_handle, u32 slice_index, u32 size,
     655             :                          uword *offset)
     656             : {
     657             :   svm_fifo_chunk_t *c;
     658             :   fifo_segment_t *fs;
     659             :   u32 fs_index;
     660             : 
     661           6 :   fs_index = vcl_segment_table_lookup (segment_handle);
     662           6 :   if (fs_index == VCL_INVALID_SEGMENT_INDEX)
     663             :     {
     664           0 :       VDBG (0, "ERROR: mq segment %lx for is not attached!", segment_handle);
     665           0 :       return 0;
     666             :     }
     667             : 
     668           6 :   clib_rwlock_reader_lock (&vcm->segment_table_lock);
     669             : 
     670           6 :   fs = fifo_segment_get_segment (&vcm->segment_main, fs_index);
     671           6 :   c = fifo_segment_alloc_chunk_w_slice (fs, slice_index, size);
     672           6 :   *offset = fifo_segment_chunk_offset (fs, c);
     673             : 
     674           6 :   clib_rwlock_reader_unlock (&vcm->segment_table_lock);
     675             : 
     676           6 :   return c;
     677             : }
     678             : 
     679             : int
     680           0 : vcl_session_share_fifos (vcl_session_t *s, svm_fifo_t *rxf, svm_fifo_t *txf)
     681             : {
     682           0 :   vcl_worker_t *wrk = vcl_worker_get_current ();
     683             :   fifo_segment_t *fs;
     684             : 
     685           0 :   clib_rwlock_reader_lock (&vcm->segment_table_lock);
     686             : 
     687           0 :   fs = fifo_segment_get_segment (&vcm->segment_main, rxf->segment_index);
     688           0 :   s->rx_fifo = fifo_segment_duplicate_fifo (fs, rxf);
     689           0 :   s->tx_fifo = fifo_segment_duplicate_fifo (fs, txf);
     690             : 
     691           0 :   clib_rwlock_reader_unlock (&vcm->segment_table_lock);
     692             : 
     693           0 :   svm_fifo_add_subscriber (s->rx_fifo, wrk->vpp_wrk_index);
     694           0 :   svm_fifo_add_subscriber (s->tx_fifo, wrk->vpp_wrk_index);
     695             : 
     696           0 :   return 0;
     697             : }
     698             : 
     699             : const char *
     700           0 : vcl_session_state_str (vcl_session_state_t state)
     701             : {
     702             :   char *st;
     703             : 
     704           0 :   switch (state)
     705             :     {
     706           0 :     case VCL_STATE_CLOSED:
     707           0 :       st = "STATE_CLOSED";
     708           0 :       break;
     709           0 :     case VCL_STATE_LISTEN:
     710           0 :       st = "STATE_LISTEN";
     711           0 :       break;
     712           0 :     case VCL_STATE_READY:
     713           0 :       st = "STATE_READY";
     714           0 :       break;
     715           0 :     case VCL_STATE_VPP_CLOSING:
     716           0 :       st = "STATE_VPP_CLOSING";
     717           0 :       break;
     718           0 :     case VCL_STATE_DISCONNECT:
     719           0 :       st = "STATE_DISCONNECT";
     720           0 :       break;
     721           0 :     case VCL_STATE_DETACHED:
     722           0 :       st = "STATE_DETACHED";
     723           0 :       break;
     724           0 :     case VCL_STATE_UPDATED:
     725           0 :       st = "STATE_UPDATED";
     726           0 :       break;
     727           0 :     case VCL_STATE_LISTEN_NO_MQ:
     728           0 :       st = "STATE_LISTEN_NO_MQ";
     729           0 :       break;
     730           0 :     default:
     731           0 :       st = "UNKNOWN_STATE";
     732           0 :       break;
     733             :     }
     734             : 
     735           0 :   return st;
     736             : }
     737             : 
     738             : u8 *
     739         229 : vcl_format_ip4_address (u8 *s, va_list *args)
     740             : {
     741         229 :   u8 *a = va_arg (*args, u8 *);
     742         229 :   return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
     743             : }
     744             : 
     745             : u8 *
     746          26 : vcl_format_ip6_address (u8 *s, va_list *args)
     747             : {
     748          26 :   ip6_address_t *a = va_arg (*args, ip6_address_t *);
     749             :   u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
     750             : 
     751          26 :   i_max_n_zero = ARRAY_LEN (a->as_u16);
     752          26 :   max_n_zeros = 0;
     753          26 :   i_first_zero = i_max_n_zero;
     754          26 :   n_zeros = 0;
     755         234 :   for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
     756             :     {
     757         208 :       u32 is_zero = a->as_u16[i] == 0;
     758         208 :       if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
     759             :         {
     760          26 :           i_first_zero = i;
     761          26 :           n_zeros = 0;
     762             :         }
     763         208 :       n_zeros += is_zero;
     764         208 :       if ((!is_zero && n_zeros > max_n_zeros) ||
     765         197 :           (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
     766             :         {
     767          26 :           i_max_n_zero = i_first_zero;
     768          26 :           max_n_zeros = n_zeros;
     769          26 :           i_first_zero = ARRAY_LEN (a->as_u16);
     770          26 :           n_zeros = 0;
     771             :         }
     772             :     }
     773             : 
     774          26 :   last_double_colon = 0;
     775          73 :   for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
     776             :     {
     777          47 :       if (i == i_max_n_zero && max_n_zeros > 1)
     778             :         {
     779          26 :           s = format (s, "::");
     780          26 :           i += max_n_zeros - 1;
     781          26 :           last_double_colon = 1;
     782             :         }
     783             :       else
     784             :         {
     785          21 :           s = format (s, "%s%x", (last_double_colon || i == 0) ? "" : ":",
     786          21 :                       clib_net_to_host_u16 (a->as_u16[i]));
     787          21 :           last_double_colon = 0;
     788             :         }
     789             :     }
     790             : 
     791          26 :   return s;
     792             : }
     793             : 
     794             : /* Format an IP46 address. */
     795             : u8 *
     796         255 : vcl_format_ip46_address (u8 *s, va_list *args)
     797             : {
     798         255 :   ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
     799         255 :   ip46_type_t type = va_arg (*args, ip46_type_t);
     800         255 :   int is_ip4 = 1;
     801             : 
     802         255 :   switch (type)
     803             :     {
     804           0 :     case IP46_TYPE_ANY:
     805           0 :       is_ip4 = ip46_address_is_ip4 (ip46);
     806           0 :       break;
     807         229 :     case IP46_TYPE_IP4:
     808         229 :       is_ip4 = 1;
     809         229 :       break;
     810          26 :     case IP46_TYPE_IP6:
     811          26 :       is_ip4 = 0;
     812          26 :       break;
     813             :     }
     814             : 
     815         281 :   return is_ip4 ? format (s, "%U", vcl_format_ip4_address, &ip46->ip4) :
     816          26 :                   format (s, "%U", vcl_format_ip6_address, &ip46->ip6);
     817             : }
     818             : 
     819             : /*
     820             :  * fd.io coding-style-patch-verification: ON
     821             :  *
     822             :  * Local Variables:
     823             :  * eval: (c-set-style "gnu")
     824             :  * End:
     825             :  */

Generated by: LCOV version 1.14