LCOV - code coverage report
Current view: top level - plugins/hs_apps - proxy.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 7 449 1.6 %
Date: 2023-07-05 22:20:52 Functions: 5 39 12.8 %

          Line data    Source code
       1             : /*
       2             : * Copyright (c) 2017-2019 Cisco and/or its affiliates.
       3             : * Licensed under the Apache License, Version 2.0 (the "License");
       4             : * you may not use this file except in compliance with the License.
       5             : * You may obtain a copy of the License at:
       6             : *
       7             : *     http://www.apache.org/licenses/LICENSE-2.0
       8             : *
       9             : * Unless required by applicable law or agreed to in writing, software
      10             : * distributed under the License is distributed on an "AS IS" BASIS,
      11             : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             : * See the License for the specific language governing permissions and
      13             : * limitations under the License.
      14             : */
      15             : 
      16             : #include <vnet/vnet.h>
      17             : #include <vlibmemory/api.h>
      18             : #include <vnet/session/application.h>
      19             : #include <vnet/session/application_interface.h>
      20             : #include <hs_apps/proxy.h>
      21             : #include <vnet/tcp/tcp.h>
      22             : 
      23             : proxy_main_t proxy_main;
      24             : 
      25             : #define TCP_MSS 1460
      26             : 
      27             : typedef struct
      28             : {
      29             :   session_endpoint_cfg_t sep;
      30             :   u32 app_index;
      31             :   u32 api_context;
      32             : } proxy_connect_args_t;
      33             : 
      34             : static void
      35           0 : proxy_cb_fn (void *data, u32 data_len)
      36             : {
      37           0 :   proxy_connect_args_t *pa = (proxy_connect_args_t *) data;
      38             :   vnet_connect_args_t a;
      39             : 
      40           0 :   clib_memset (&a, 0, sizeof (a));
      41           0 :   a.api_context = pa->api_context;
      42           0 :   a.app_index = pa->app_index;
      43           0 :   clib_memcpy (&a.sep_ext, &pa->sep, sizeof (pa->sep));
      44           0 :   vnet_connect (&a);
      45           0 :   if (a.sep_ext.ext_cfg)
      46           0 :     clib_mem_free (a.sep_ext.ext_cfg);
      47           0 : }
      48             : 
      49             : static void
      50           0 : proxy_call_main_thread (vnet_connect_args_t * a)
      51             : {
      52           0 :   if (vlib_get_thread_index () == 0)
      53             :     {
      54           0 :       vnet_connect (a);
      55           0 :       if (a->sep_ext.ext_cfg)
      56           0 :         clib_mem_free (a->sep_ext.ext_cfg);
      57             :     }
      58             :   else
      59             :     {
      60             :       proxy_connect_args_t args;
      61           0 :       args.api_context = a->api_context;
      62           0 :       args.app_index = a->app_index;
      63           0 :       clib_memcpy (&args.sep, &a->sep_ext, sizeof (a->sep_ext));
      64           0 :       vl_api_rpc_call_main_thread (proxy_cb_fn, (u8 *) & args, sizeof (args));
      65             :     }
      66           0 : }
      67             : 
      68             : static proxy_session_t *
      69           0 : proxy_session_alloc (void)
      70             : {
      71           0 :   proxy_main_t *pm = &proxy_main;
      72             :   proxy_session_t *ps;
      73             : 
      74           0 :   pool_get_zero (pm->sessions, ps);
      75           0 :   ps->ps_index = ps - pm->sessions;
      76             : 
      77           0 :   return ps;
      78             : }
      79             : 
      80             : static inline proxy_session_t *
      81           0 : proxy_session_get (u32 ps_index)
      82             : {
      83           0 :   proxy_main_t *pm = &proxy_main;
      84             : 
      85           0 :   return pool_elt_at_index (pm->sessions, ps_index);
      86             : }
      87             : 
      88             : static inline proxy_session_t *
      89           0 : proxy_session_get_if_valid (u32 ps_index)
      90             : {
      91           0 :   proxy_main_t *pm = &proxy_main;
      92             : 
      93           0 :   if (pool_is_free_index (pm->sessions, ps_index))
      94           0 :     return 0;
      95           0 :   return pool_elt_at_index (pm->sessions, ps_index);
      96             : }
      97             : 
      98             : static void
      99           0 : proxy_session_free (proxy_session_t *ps)
     100             : {
     101           0 :   proxy_main_t *pm = &proxy_main;
     102             : 
     103             :   if (CLIB_DEBUG > 0)
     104           0 :     clib_memset (ps, 0xFE, sizeof (*ps));
     105           0 :   pool_put (pm->sessions, ps);
     106           0 : }
     107             : 
     108             : static int
     109           0 : proxy_session_postponed_free_rpc (void *arg)
     110             : {
     111           0 :   uword ps_index = pointer_to_uword (arg);
     112           0 :   proxy_main_t *pm = &proxy_main;
     113           0 :   proxy_session_t *ps = 0;
     114             : 
     115           0 :   clib_spinlock_lock_if_init (&pm->sessions_lock);
     116             : 
     117           0 :   ps = proxy_session_get (ps_index);
     118           0 :   segment_manager_dealloc_fifos (ps->server_rx_fifo, ps->server_tx_fifo);
     119           0 :   proxy_session_free (ps);
     120             : 
     121           0 :   clib_spinlock_unlock_if_init (&pm->sessions_lock);
     122             : 
     123           0 :   return 0;
     124             : }
     125             : 
     126             : static void
     127           0 : proxy_session_postponed_free (proxy_session_t *ps)
     128             : {
     129           0 :   session_send_rpc_evt_to_thread (ps->po_thread_index,
     130             :                                   proxy_session_postponed_free_rpc,
     131           0 :                                   uword_to_pointer (ps->ps_index, void *));
     132           0 : }
     133             : 
     134             : static void
     135           0 : proxy_try_close_session (session_t * s, int is_active_open)
     136             : {
     137           0 :   proxy_main_t *pm = &proxy_main;
     138           0 :   proxy_session_t *ps = 0;
     139           0 :   vnet_disconnect_args_t _a, *a = &_a;
     140             : 
     141           0 :   clib_spinlock_lock_if_init (&pm->sessions_lock);
     142             : 
     143           0 :   ps = proxy_session_get (s->opaque);
     144             : 
     145           0 :   if (is_active_open)
     146             :     {
     147           0 :       a->handle = ps->vpp_active_open_handle;
     148           0 :       a->app_index = pm->active_open_app_index;
     149           0 :       vnet_disconnect_session (a);
     150           0 :       ps->ao_disconnected = 1;
     151             : 
     152           0 :       if (!ps->po_disconnected)
     153             :         {
     154           0 :           ASSERT (ps->vpp_server_handle != SESSION_INVALID_HANDLE);
     155           0 :           a->handle = ps->vpp_server_handle;
     156           0 :           a->app_index = pm->server_app_index;
     157           0 :           vnet_disconnect_session (a);
     158           0 :           ps->po_disconnected = 1;
     159             :         }
     160             :     }
     161             :   else
     162             :     {
     163           0 :       a->handle = ps->vpp_server_handle;
     164           0 :       a->app_index = pm->server_app_index;
     165           0 :       vnet_disconnect_session (a);
     166           0 :       ps->po_disconnected = 1;
     167             : 
     168           0 :       if (!ps->ao_disconnected && !ps->active_open_establishing)
     169             :         {
     170             :           /* Proxy session closed before active open */
     171           0 :           if (ps->vpp_active_open_handle != SESSION_INVALID_HANDLE)
     172             :             {
     173           0 :               a->handle = ps->vpp_active_open_handle;
     174           0 :               a->app_index = pm->active_open_app_index;
     175           0 :               vnet_disconnect_session (a);
     176             :             }
     177           0 :           ps->ao_disconnected = 1;
     178             :         }
     179             :     }
     180           0 :   clib_spinlock_unlock_if_init (&pm->sessions_lock);
     181           0 : }
     182             : 
     183             : static void
     184           0 : proxy_try_delete_session (session_t * s, u8 is_active_open)
     185             : {
     186           0 :   proxy_main_t *pm = &proxy_main;
     187           0 :   proxy_session_t *ps = 0;
     188             : 
     189           0 :   clib_spinlock_lock_if_init (&pm->sessions_lock);
     190             : 
     191           0 :   ps = proxy_session_get (s->opaque);
     192             : 
     193           0 :   if (is_active_open)
     194             :     {
     195           0 :       ps->vpp_active_open_handle = SESSION_INVALID_HANDLE;
     196             : 
     197             :       /* Revert master thread index change on connect notification */
     198           0 :       ps->server_rx_fifo->master_thread_index = ps->po_thread_index;
     199             : 
     200             :       /* Passive open already cleaned up */
     201           0 :       if (ps->vpp_server_handle == SESSION_INVALID_HANDLE)
     202             :         {
     203           0 :           ASSERT (s->rx_fifo->refcnt == 1);
     204             : 
     205             :           /* The two sides of the proxy on different threads */
     206           0 :           if (ps->po_thread_index != s->thread_index)
     207             :             {
     208             :               /* This is not the right thread to delete the fifos */
     209           0 :               s->rx_fifo = 0;
     210           0 :               s->tx_fifo = 0;
     211           0 :               proxy_session_postponed_free (ps);
     212             :             }
     213             :           else
     214           0 :             proxy_session_free (ps);
     215             :         }
     216             :     }
     217             :   else
     218             :     {
     219           0 :       ps->vpp_server_handle = SESSION_INVALID_HANDLE;
     220             : 
     221           0 :       if (ps->vpp_active_open_handle == SESSION_INVALID_HANDLE)
     222             :         {
     223           0 :           if (!ps->active_open_establishing)
     224           0 :             proxy_session_free (ps);
     225             :         }
     226             :     }
     227           0 :   clib_spinlock_unlock_if_init (&pm->sessions_lock);
     228           0 : }
     229             : 
     230             : static int
     231           0 : common_fifo_tuning_callback (session_t * s, svm_fifo_t * f,
     232             :                              session_ft_action_t act, u32 bytes)
     233             : {
     234           0 :   proxy_main_t *pm = &proxy_main;
     235             : 
     236           0 :   segment_manager_t *sm = segment_manager_get (f->segment_manager);
     237           0 :   fifo_segment_t *fs = segment_manager_get_segment (sm, f->segment_index);
     238             : 
     239           0 :   u8 seg_usage = fifo_segment_get_mem_usage (fs);
     240           0 :   u32 fifo_in_use = svm_fifo_max_dequeue_prod (f);
     241           0 :   u32 fifo_size = svm_fifo_size (f);
     242           0 :   u8 fifo_usage = fifo_in_use * 100 / fifo_size;
     243           0 :   u8 update_size = 0;
     244             : 
     245           0 :   ASSERT (act < SESSION_FT_ACTION_N_ACTIONS);
     246             : 
     247           0 :   if (act == SESSION_FT_ACTION_ENQUEUED)
     248             :     {
     249           0 :       if (seg_usage < pm->low_watermark && fifo_usage > 50)
     250           0 :         update_size = fifo_in_use;
     251           0 :       else if (seg_usage < pm->high_watermark && fifo_usage > 80)
     252           0 :         update_size = fifo_in_use;
     253             : 
     254           0 :       update_size = clib_min (update_size, sm->max_fifo_size - fifo_size);
     255           0 :       if (update_size)
     256           0 :         svm_fifo_set_size (f, fifo_size + update_size);
     257             :     }
     258             :   else                          /* dequeued */
     259             :     {
     260           0 :       if (seg_usage > pm->high_watermark || fifo_usage < 20)
     261           0 :         update_size = bytes;
     262           0 :       else if (seg_usage > pm->low_watermark && fifo_usage < 50)
     263           0 :         update_size = (bytes / 2);
     264             : 
     265           0 :       ASSERT (fifo_size >= 4096);
     266           0 :       update_size = clib_min (update_size, fifo_size - 4096);
     267           0 :       if (update_size)
     268           0 :         svm_fifo_set_size (f, fifo_size - update_size);
     269             :     }
     270             : 
     271           0 :   return 0;
     272             : }
     273             : 
     274             : static int
     275           0 : proxy_accept_callback (session_t * s)
     276             : {
     277           0 :   proxy_main_t *pm = &proxy_main;
     278             :   proxy_session_t *ps;
     279             : 
     280           0 :   clib_spinlock_lock_if_init (&pm->sessions_lock);
     281             : 
     282           0 :   ps = proxy_session_alloc ();
     283           0 :   ps->vpp_server_handle = session_handle (s);
     284           0 :   ps->vpp_active_open_handle = SESSION_INVALID_HANDLE;
     285           0 :   ps->po_thread_index = s->thread_index;
     286             : 
     287           0 :   s->opaque = ps->ps_index;
     288             : 
     289           0 :   clib_spinlock_unlock_if_init (&pm->sessions_lock);
     290             : 
     291           0 :   s->session_state = SESSION_STATE_READY;
     292             : 
     293           0 :   return 0;
     294             : }
     295             : 
     296             : static void
     297           0 : proxy_disconnect_callback (session_t * s)
     298             : {
     299           0 :   proxy_try_close_session (s, 0 /* is_active_open */ );
     300           0 : }
     301             : 
     302             : static void
     303           0 : proxy_reset_callback (session_t * s)
     304             : {
     305           0 :   proxy_try_close_session (s, 0 /* is_active_open */ );
     306           0 : }
     307             : 
     308             : static int
     309           0 : proxy_connected_callback (u32 app_index, u32 api_context,
     310             :                           session_t * s, session_error_t err)
     311             : {
     312           0 :   clib_warning ("called...");
     313           0 :   return -1;
     314             : }
     315             : 
     316             : static int
     317           0 : proxy_add_segment_callback (u32 client_index, u64 segment_handle)
     318             : {
     319           0 :   return 0;
     320             : }
     321             : 
     322             : static int
     323           0 : proxy_transport_needs_crypto (transport_proto_t proto)
     324             : {
     325           0 :   return proto == TRANSPORT_PROTO_TLS;
     326             : }
     327             : 
     328             : static int
     329           0 : proxy_rx_callback (session_t * s)
     330             : {
     331           0 :   proxy_main_t *pm = &proxy_main;
     332           0 :   u32 thread_index = vlib_get_thread_index ();
     333             :   svm_fifo_t *ao_tx_fifo;
     334             :   proxy_session_t *ps;
     335             : 
     336           0 :   ASSERT (s->thread_index == thread_index);
     337             : 
     338           0 :   clib_spinlock_lock_if_init (&pm->sessions_lock);
     339             : 
     340           0 :   ps = proxy_session_get (s->opaque);
     341             : 
     342           0 :   if (PREDICT_TRUE (ps->vpp_active_open_handle != SESSION_INVALID_HANDLE))
     343             :     {
     344           0 :       clib_spinlock_unlock_if_init (&pm->sessions_lock);
     345             : 
     346           0 :       ao_tx_fifo = s->rx_fifo;
     347             : 
     348             :       /*
     349             :        * Send event for active open tx fifo
     350             :        */
     351           0 :       if (svm_fifo_set_event (ao_tx_fifo))
     352             :         {
     353           0 :           u32 ao_thread_index = ao_tx_fifo->master_thread_index;
     354           0 :           u32 ao_session_index = ao_tx_fifo->shr->master_session_index;
     355           0 :           if (session_send_io_evt_to_thread_custom (&ao_session_index,
     356             :                                                     ao_thread_index,
     357             :                                                     SESSION_IO_EVT_TX))
     358           0 :             clib_warning ("failed to enqueue tx evt");
     359             :         }
     360             : 
     361           0 :       if (svm_fifo_max_enqueue (ao_tx_fifo) <= TCP_MSS)
     362           0 :         svm_fifo_add_want_deq_ntf (ao_tx_fifo, SVM_FIFO_WANT_DEQ_NOTIF);
     363             :     }
     364             :   else
     365             :     {
     366           0 :       vnet_connect_args_t _a, *a = &_a;
     367             :       svm_fifo_t *tx_fifo, *rx_fifo;
     368             :       u32 max_dequeue, ps_index;
     369             :       int actual_transfer __attribute__ ((unused));
     370             : 
     371           0 :       rx_fifo = s->rx_fifo;
     372           0 :       tx_fifo = s->tx_fifo;
     373             : 
     374           0 :       ASSERT (rx_fifo->master_thread_index == thread_index);
     375           0 :       ASSERT (tx_fifo->master_thread_index == thread_index);
     376             : 
     377           0 :       max_dequeue = svm_fifo_max_dequeue_cons (s->rx_fifo);
     378             : 
     379           0 :       if (PREDICT_FALSE (max_dequeue == 0))
     380             :         {
     381           0 :           clib_spinlock_unlock_if_init (&pm->sessions_lock);
     382           0 :           return 0;
     383             :         }
     384             : 
     385           0 :       max_dequeue = clib_min (pm->rcv_buffer_size, max_dequeue);
     386           0 :       actual_transfer = svm_fifo_peek (rx_fifo, 0 /* relative_offset */ ,
     387           0 :                                        max_dequeue, pm->rx_buf[thread_index]);
     388             : 
     389             :       /* $$$ your message in this space: parse url, etc. */
     390             : 
     391           0 :       clib_memset (a, 0, sizeof (*a));
     392             : 
     393           0 :       ps->server_rx_fifo = rx_fifo;
     394           0 :       ps->server_tx_fifo = tx_fifo;
     395           0 :       ps->active_open_establishing = 1;
     396           0 :       ps_index = ps->ps_index;
     397             : 
     398           0 :       clib_spinlock_unlock_if_init (&pm->sessions_lock);
     399             : 
     400           0 :       clib_memcpy (&a->sep_ext, &pm->client_sep, sizeof (pm->client_sep));
     401           0 :       a->api_context = ps_index;
     402           0 :       a->app_index = pm->active_open_app_index;
     403             : 
     404           0 :       if (proxy_transport_needs_crypto (a->sep.transport_proto))
     405             :         {
     406           0 :           session_endpoint_alloc_ext_cfg (&a->sep_ext,
     407             :                                           TRANSPORT_ENDPT_EXT_CFG_CRYPTO);
     408           0 :           a->sep_ext.ext_cfg->crypto.ckpair_index = pm->ckpair_index;
     409             :         }
     410             : 
     411           0 :       proxy_call_main_thread (a);
     412             :     }
     413             : 
     414           0 :   return 0;
     415             : }
     416             : 
     417             : static void
     418           0 : proxy_force_ack (void *handlep)
     419             : {
     420             :   transport_connection_t *tc;
     421             :   session_t *ao_s;
     422             : 
     423           0 :   ao_s = session_get_from_handle (pointer_to_uword (handlep));
     424           0 :   if (session_get_transport_proto (ao_s) != TRANSPORT_PROTO_TCP)
     425           0 :     return;
     426           0 :   tc = session_get_transport (ao_s);
     427           0 :   tcp_send_ack ((tcp_connection_t *) tc);
     428             : }
     429             : 
     430             : static int
     431           0 : proxy_tx_callback (session_t * proxy_s)
     432             : {
     433           0 :   proxy_main_t *pm = &proxy_main;
     434             :   proxy_session_t *ps;
     435             :   u32 min_free;
     436             : 
     437           0 :   min_free = clib_min (svm_fifo_size (proxy_s->tx_fifo) >> 3, 128 << 10);
     438           0 :   if (svm_fifo_max_enqueue (proxy_s->tx_fifo) < min_free)
     439             :     {
     440           0 :       svm_fifo_add_want_deq_ntf (proxy_s->tx_fifo, SVM_FIFO_WANT_DEQ_NOTIF);
     441           0 :       return 0;
     442             :     }
     443             : 
     444           0 :   clib_spinlock_lock_if_init (&pm->sessions_lock);
     445             : 
     446           0 :   ps = proxy_session_get (proxy_s->opaque);
     447             : 
     448           0 :   if (ps->vpp_active_open_handle == SESSION_INVALID_HANDLE)
     449           0 :     goto unlock;
     450             : 
     451             :   /* Force ack on active open side to update rcv wnd. Make sure it's done on
     452             :    * the right thread */
     453           0 :   void *arg = uword_to_pointer (ps->vpp_active_open_handle, void *);
     454           0 :   session_send_rpc_evt_to_thread (ps->server_rx_fifo->master_thread_index,
     455             :                                   proxy_force_ack, arg);
     456             : 
     457           0 : unlock:
     458           0 :   clib_spinlock_unlock_if_init (&pm->sessions_lock);
     459             : 
     460           0 :   return 0;
     461             : }
     462             : 
     463             : static void
     464           0 : proxy_cleanup_callback (session_t * s, session_cleanup_ntf_t ntf)
     465             : {
     466           0 :   if (ntf == SESSION_CLEANUP_TRANSPORT)
     467           0 :     return;
     468             : 
     469           0 :   proxy_try_delete_session (s, 0 /* is_active_open */ );
     470             : }
     471             : 
     472             : static session_cb_vft_t proxy_session_cb_vft = {
     473             :   .session_accept_callback = proxy_accept_callback,
     474             :   .session_disconnect_callback = proxy_disconnect_callback,
     475             :   .session_connected_callback = proxy_connected_callback,
     476             :   .add_segment_callback = proxy_add_segment_callback,
     477             :   .builtin_app_rx_callback = proxy_rx_callback,
     478             :   .builtin_app_tx_callback = proxy_tx_callback,
     479             :   .session_reset_callback = proxy_reset_callback,
     480             :   .session_cleanup_callback = proxy_cleanup_callback,
     481             :   .fifo_tuning_callback = common_fifo_tuning_callback
     482             : };
     483             : 
     484             : static int
     485           0 : active_open_connected_callback (u32 app_index, u32 opaque,
     486             :                                 session_t * s, session_error_t err)
     487             : {
     488           0 :   proxy_main_t *pm = &proxy_main;
     489             :   proxy_session_t *ps;
     490           0 :   u8 thread_index = vlib_get_thread_index ();
     491             : 
     492             :   /*
     493             :    * Setup proxy session handle.
     494             :    */
     495           0 :   clib_spinlock_lock_if_init (&pm->sessions_lock);
     496             : 
     497           0 :   ps = proxy_session_get (opaque);
     498             : 
     499             :   /* Connection failed */
     500           0 :   if (err)
     501             :     {
     502           0 :       vnet_disconnect_args_t _a, *a = &_a;
     503             : 
     504           0 :       a->handle = ps->vpp_server_handle;
     505           0 :       a->app_index = pm->server_app_index;
     506           0 :       vnet_disconnect_session (a);
     507           0 :       ps->po_disconnected = 1;
     508             :     }
     509             :   else
     510             :     {
     511           0 :       ps->vpp_active_open_handle = session_handle (s);
     512           0 :       ps->active_open_establishing = 0;
     513             :     }
     514             : 
     515             :   /* Passive open session was already closed! */
     516           0 :   if (ps->po_disconnected)
     517             :     {
     518             :       /* Setup everything for the cleanup notification */
     519           0 :       ps->ao_disconnected = 1;
     520           0 :       clib_spinlock_unlock_if_init (&pm->sessions_lock);
     521           0 :       return -1;
     522             :     }
     523             : 
     524           0 :   s->tx_fifo = ps->server_rx_fifo;
     525           0 :   s->rx_fifo = ps->server_tx_fifo;
     526             : 
     527             :   /*
     528             :    * Reset the active-open tx-fifo master indices so the active-open session
     529             :    * will receive data, etc.
     530             :    */
     531           0 :   s->tx_fifo->shr->master_session_index = s->session_index;
     532           0 :   s->tx_fifo->master_thread_index = s->thread_index;
     533             : 
     534             :   /*
     535             :    * Account for the active-open session's use of the fifos
     536             :    * so they won't disappear until the last session which uses
     537             :    * them disappears
     538             :    */
     539           0 :   s->tx_fifo->refcnt++;
     540           0 :   s->rx_fifo->refcnt++;
     541             : 
     542           0 :   s->opaque = opaque;
     543             : 
     544           0 :   clib_spinlock_unlock_if_init (&pm->sessions_lock);
     545             : 
     546             :   /*
     547             :    * Send event for active open tx fifo
     548             :    */
     549           0 :   ASSERT (s->thread_index == thread_index);
     550           0 :   if (svm_fifo_set_event (s->tx_fifo))
     551           0 :     session_send_io_evt_to_thread (s->tx_fifo, SESSION_IO_EVT_TX);
     552             : 
     553           0 :   return 0;
     554             : }
     555             : 
     556             : static void
     557           0 : active_open_reset_callback (session_t * s)
     558             : {
     559           0 :   proxy_try_close_session (s, 1 /* is_active_open */ );
     560           0 : }
     561             : 
     562             : static int
     563           0 : active_open_create_callback (session_t * s)
     564             : {
     565           0 :   return 0;
     566             : }
     567             : 
     568             : static void
     569           0 : active_open_disconnect_callback (session_t * s)
     570             : {
     571           0 :   proxy_try_close_session (s, 1 /* is_active_open */ );
     572           0 : }
     573             : 
     574             : static int
     575           0 : active_open_rx_callback (session_t * s)
     576             : {
     577             :   svm_fifo_t *proxy_tx_fifo;
     578             : 
     579           0 :   proxy_tx_fifo = s->rx_fifo;
     580             : 
     581             :   /*
     582             :    * Send event for server tx fifo
     583             :    */
     584           0 :   if (svm_fifo_set_event (proxy_tx_fifo))
     585             :     {
     586           0 :       u8 thread_index = proxy_tx_fifo->master_thread_index;
     587           0 :       u32 session_index = proxy_tx_fifo->shr->master_session_index;
     588           0 :       return session_send_io_evt_to_thread_custom (&session_index,
     589             :                                                    thread_index,
     590             :                                                    SESSION_IO_EVT_TX);
     591             :     }
     592             : 
     593           0 :   if (svm_fifo_max_enqueue (proxy_tx_fifo) <= TCP_MSS)
     594           0 :     svm_fifo_add_want_deq_ntf (proxy_tx_fifo, SVM_FIFO_WANT_DEQ_NOTIF);
     595             : 
     596           0 :   return 0;
     597             : }
     598             : 
     599             : static int
     600           0 : active_open_tx_callback (session_t * ao_s)
     601             : {
     602           0 :   proxy_main_t *pm = &proxy_main;
     603             :   transport_connection_t *tc;
     604             :   proxy_session_t *ps;
     605             :   session_t *proxy_s;
     606             :   u32 min_free;
     607             : 
     608           0 :   min_free = clib_min (svm_fifo_size (ao_s->tx_fifo) >> 3, 128 << 10);
     609           0 :   if (svm_fifo_max_enqueue (ao_s->tx_fifo) < min_free)
     610             :     {
     611           0 :       svm_fifo_add_want_deq_ntf (ao_s->tx_fifo, SVM_FIFO_WANT_DEQ_NOTIF);
     612           0 :       return 0;
     613             :     }
     614             : 
     615           0 :   clib_spinlock_lock_if_init (&pm->sessions_lock);
     616             : 
     617           0 :   ps = proxy_session_get_if_valid (ao_s->opaque);
     618           0 :   if (!ps)
     619           0 :     goto unlock;
     620             : 
     621           0 :   if (ps->vpp_server_handle == ~0)
     622           0 :     goto unlock;
     623             : 
     624           0 :   proxy_s = session_get_from_handle (ps->vpp_server_handle);
     625             : 
     626             :   /* Force ack on proxy side to update rcv wnd */
     627           0 :   tc = session_get_transport (proxy_s);
     628           0 :   tcp_send_ack ((tcp_connection_t *) tc);
     629             : 
     630           0 : unlock:
     631           0 :   clib_spinlock_unlock_if_init (&pm->sessions_lock);
     632             : 
     633           0 :   return 0;
     634             : }
     635             : 
     636             : static void
     637           0 : active_open_cleanup_callback (session_t * s, session_cleanup_ntf_t ntf)
     638             : {
     639           0 :   if (ntf == SESSION_CLEANUP_TRANSPORT)
     640           0 :     return;
     641             : 
     642           0 :   proxy_try_delete_session (s, 1 /* is_active_open */ );
     643             : }
     644             : 
     645             : /* *INDENT-OFF* */
     646             : static session_cb_vft_t active_open_clients = {
     647             :   .session_reset_callback = active_open_reset_callback,
     648             :   .session_connected_callback = active_open_connected_callback,
     649             :   .session_accept_callback = active_open_create_callback,
     650             :   .session_disconnect_callback = active_open_disconnect_callback,
     651             :   .session_cleanup_callback = active_open_cleanup_callback,
     652             :   .builtin_app_rx_callback = active_open_rx_callback,
     653             :   .builtin_app_tx_callback = active_open_tx_callback,
     654             :   .fifo_tuning_callback = common_fifo_tuning_callback
     655             : };
     656             : /* *INDENT-ON* */
     657             : 
     658             : static int
     659           0 : proxy_server_attach ()
     660             : {
     661           0 :   proxy_main_t *pm = &proxy_main;
     662             :   u64 options[APP_OPTIONS_N_OPTIONS];
     663           0 :   vnet_app_attach_args_t _a, *a = &_a;
     664             : 
     665           0 :   clib_memset (a, 0, sizeof (*a));
     666           0 :   clib_memset (options, 0, sizeof (options));
     667             : 
     668           0 :   a->name = format (0, "proxy-server");
     669           0 :   a->api_client_index = pm->server_client_index;
     670           0 :   a->session_cb_vft = &proxy_session_cb_vft;
     671           0 :   a->options = options;
     672           0 :   a->options[APP_OPTIONS_SEGMENT_SIZE] = pm->segment_size;
     673           0 :   a->options[APP_OPTIONS_ADD_SEGMENT_SIZE] = pm->segment_size;
     674           0 :   a->options[APP_OPTIONS_RX_FIFO_SIZE] = pm->fifo_size;
     675           0 :   a->options[APP_OPTIONS_TX_FIFO_SIZE] = pm->fifo_size;
     676           0 :   a->options[APP_OPTIONS_MAX_FIFO_SIZE] = pm->max_fifo_size;
     677           0 :   a->options[APP_OPTIONS_HIGH_WATERMARK] = (u64) pm->high_watermark;
     678           0 :   a->options[APP_OPTIONS_LOW_WATERMARK] = (u64) pm->low_watermark;
     679           0 :   a->options[APP_OPTIONS_PRIVATE_SEGMENT_COUNT] = pm->private_segment_count;
     680           0 :   a->options[APP_OPTIONS_PREALLOC_FIFO_PAIRS] =
     681           0 :     pm->prealloc_fifos ? pm->prealloc_fifos : 0;
     682             : 
     683           0 :   a->options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
     684             : 
     685           0 :   if (vnet_application_attach (a))
     686             :     {
     687           0 :       clib_warning ("failed to attach server");
     688           0 :       return -1;
     689             :     }
     690           0 :   pm->server_app_index = a->app_index;
     691             : 
     692           0 :   vec_free (a->name);
     693           0 :   return 0;
     694             : }
     695             : 
     696             : static int
     697           0 : active_open_attach (void)
     698             : {
     699           0 :   proxy_main_t *pm = &proxy_main;
     700           0 :   vnet_app_attach_args_t _a, *a = &_a;
     701             :   u64 options[APP_OPTIONS_N_OPTIONS];
     702             : 
     703           0 :   clib_memset (a, 0, sizeof (*a));
     704           0 :   clib_memset (options, 0, sizeof (options));
     705             : 
     706           0 :   a->api_client_index = pm->active_open_client_index;
     707           0 :   a->session_cb_vft = &active_open_clients;
     708           0 :   a->name = format (0, "proxy-active-open");
     709             : 
     710           0 :   options[APP_OPTIONS_ACCEPT_COOKIE] = 0x12345678;
     711           0 :   options[APP_OPTIONS_SEGMENT_SIZE] = 512 << 20;
     712           0 :   options[APP_OPTIONS_RX_FIFO_SIZE] = pm->fifo_size;
     713           0 :   options[APP_OPTIONS_TX_FIFO_SIZE] = pm->fifo_size;
     714           0 :   options[APP_OPTIONS_MAX_FIFO_SIZE] = pm->max_fifo_size;
     715           0 :   options[APP_OPTIONS_HIGH_WATERMARK] = (u64) pm->high_watermark;
     716           0 :   options[APP_OPTIONS_LOW_WATERMARK] = (u64) pm->low_watermark;
     717           0 :   options[APP_OPTIONS_PRIVATE_SEGMENT_COUNT] = pm->private_segment_count;
     718           0 :   options[APP_OPTIONS_PREALLOC_FIFO_PAIRS] =
     719           0 :     pm->prealloc_fifos ? pm->prealloc_fifos : 0;
     720             : 
     721           0 :   options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN
     722             :     | APP_OPTIONS_FLAGS_IS_PROXY;
     723             : 
     724           0 :   a->options = options;
     725             : 
     726           0 :   if (vnet_application_attach (a))
     727           0 :     return -1;
     728             : 
     729           0 :   pm->active_open_app_index = a->app_index;
     730             : 
     731           0 :   vec_free (a->name);
     732             : 
     733           0 :   return 0;
     734             : }
     735             : 
     736             : static int
     737           0 : proxy_server_listen ()
     738             : {
     739           0 :   proxy_main_t *pm = &proxy_main;
     740           0 :   vnet_listen_args_t _a, *a = &_a;
     741             :   int rv;
     742             : 
     743           0 :   clib_memset (a, 0, sizeof (*a));
     744             : 
     745           0 :   a->app_index = pm->server_app_index;
     746           0 :   clib_memcpy (&a->sep_ext, &pm->server_sep, sizeof (pm->server_sep));
     747           0 :   if (proxy_transport_needs_crypto (a->sep.transport_proto))
     748             :     {
     749           0 :       session_endpoint_alloc_ext_cfg (&a->sep_ext,
     750             :                                       TRANSPORT_ENDPT_EXT_CFG_CRYPTO);
     751           0 :       a->sep_ext.ext_cfg->crypto.ckpair_index = pm->ckpair_index;
     752             :     }
     753             : 
     754           0 :   rv = vnet_listen (a);
     755           0 :   if (a->sep_ext.ext_cfg)
     756           0 :     clib_mem_free (a->sep_ext.ext_cfg);
     757             : 
     758           0 :   return rv;
     759             : }
     760             : 
     761             : static void
     762           0 : proxy_server_add_ckpair (void)
     763             : {
     764           0 :   vnet_app_add_cert_key_pair_args_t _ck_pair, *ck_pair = &_ck_pair;
     765           0 :   proxy_main_t *pm = &proxy_main;
     766             : 
     767           0 :   clib_memset (ck_pair, 0, sizeof (*ck_pair));
     768           0 :   ck_pair->cert = (u8 *) test_srv_crt_rsa;
     769           0 :   ck_pair->key = (u8 *) test_srv_key_rsa;
     770           0 :   ck_pair->cert_len = test_srv_crt_rsa_len;
     771           0 :   ck_pair->key_len = test_srv_key_rsa_len;
     772           0 :   vnet_app_add_cert_key_pair (ck_pair);
     773             : 
     774           0 :   pm->ckpair_index = ck_pair->index;
     775           0 : }
     776             : 
     777             : static int
     778           0 : proxy_server_create (vlib_main_t * vm)
     779             : {
     780           0 :   vlib_thread_main_t *vtm = vlib_get_thread_main ();
     781           0 :   proxy_main_t *pm = &proxy_main;
     782             :   u32 num_threads;
     783             :   int i;
     784             : 
     785           0 :   num_threads = 1 /* main thread */  + vtm->n_threads;
     786           0 :   vec_validate (pm->rx_buf, num_threads - 1);
     787             : 
     788           0 :   for (i = 0; i < num_threads; i++)
     789           0 :     vec_validate (pm->rx_buf[i], pm->rcv_buffer_size);
     790             : 
     791           0 :   proxy_server_add_ckpair ();
     792             : 
     793           0 :   if (proxy_server_attach ())
     794             :     {
     795           0 :       clib_warning ("failed to attach server app");
     796           0 :       return -1;
     797             :     }
     798           0 :   if (proxy_server_listen ())
     799             :     {
     800           0 :       clib_warning ("failed to start listening");
     801           0 :       return -1;
     802             :     }
     803           0 :   if (active_open_attach ())
     804             :     {
     805           0 :       clib_warning ("failed to attach active open app");
     806           0 :       return -1;
     807             :     }
     808             : 
     809           0 :   return 0;
     810             : }
     811             : 
     812             : static clib_error_t *
     813           0 : proxy_server_create_command_fn (vlib_main_t * vm, unformat_input_t * input,
     814             :                                 vlib_cli_command_t * cmd)
     815             : {
     816           0 :   unformat_input_t _line_input, *line_input = &_line_input;
     817           0 :   char *default_server_uri = "tcp://0.0.0.0/23";
     818           0 :   char *default_client_uri = "tcp://6.0.2.2/23";
     819           0 :   u8 *server_uri = 0, *client_uri = 0;
     820           0 :   proxy_main_t *pm = &proxy_main;
     821           0 :   clib_error_t *error = 0;
     822             :   int rv, tmp32;
     823             :   u64 tmp64;
     824             : 
     825           0 :   pm->fifo_size = 64 << 10;
     826           0 :   pm->max_fifo_size = 128 << 20;
     827           0 :   pm->high_watermark = 80;
     828           0 :   pm->low_watermark = 50;
     829           0 :   pm->rcv_buffer_size = 1024;
     830           0 :   pm->prealloc_fifos = 0;
     831           0 :   pm->private_segment_count = 0;
     832           0 :   pm->segment_size = 512 << 20;
     833             : 
     834           0 :   if (vlib_num_workers ())
     835           0 :     clib_spinlock_init (&pm->sessions_lock);
     836             : 
     837           0 :   if (!unformat_user (input, unformat_line_input, line_input))
     838           0 :     return 0;
     839             : 
     840           0 :   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
     841             :     {
     842           0 :       if (unformat (line_input, "fifo-size %U", unformat_memory_size,
     843             :                     &pm->fifo_size))
     844             :         ;
     845           0 :       else if (unformat (line_input, "max-fifo-size %U", unformat_memory_size,
     846             :                          &pm->max_fifo_size))
     847             :         ;
     848           0 :       else if (unformat (line_input, "high-watermark %d", &tmp32))
     849           0 :         pm->high_watermark = (u8) tmp32;
     850           0 :       else if (unformat (line_input, "low-watermark %d", &tmp32))
     851           0 :         pm->low_watermark = (u8) tmp32;
     852           0 :       else if (unformat (line_input, "rcv-buf-size %d", &pm->rcv_buffer_size))
     853             :         ;
     854           0 :       else if (unformat (line_input, "prealloc-fifos %d", &pm->prealloc_fifos))
     855             :         ;
     856           0 :       else if (unformat (line_input, "private-segment-count %d",
     857             :                          &pm->private_segment_count))
     858             :         ;
     859           0 :       else if (unformat (line_input, "private-segment-size %U",
     860             :                          unformat_memory_size, &tmp64))
     861             :         {
     862           0 :           pm->segment_size = tmp64;
     863             :         }
     864           0 :       else if (unformat (line_input, "server-uri %s", &server_uri))
     865           0 :         vec_add1 (server_uri, 0);
     866           0 :       else if (unformat (line_input, "client-uri %s", &client_uri))
     867           0 :         vec_add1 (client_uri, 0);
     868             :       else
     869             :         {
     870           0 :           error = clib_error_return (0, "unknown input `%U'",
     871             :                                      format_unformat_error, line_input);
     872           0 :           goto done;
     873             :         }
     874             :     }
     875             : 
     876           0 :   if (!server_uri)
     877             :     {
     878           0 :       clib_warning ("No server-uri provided, Using default: %s",
     879             :                     default_server_uri);
     880           0 :       server_uri = format (0, "%s%c", default_server_uri, 0);
     881             :     }
     882           0 :   if (!client_uri)
     883             :     {
     884           0 :       clib_warning ("No client-uri provided, Using default: %s",
     885             :                     default_client_uri);
     886           0 :       client_uri = format (0, "%s%c", default_client_uri, 0);
     887             :     }
     888             : 
     889           0 :   if (parse_uri ((char *) server_uri, &pm->server_sep))
     890             :     {
     891           0 :       error = clib_error_return (0, "Invalid server uri %v", server_uri);
     892           0 :       goto done;
     893             :     }
     894           0 :   if (parse_uri ((char *) client_uri, &pm->client_sep))
     895             :     {
     896           0 :       error = clib_error_return (0, "Invalid client uri %v", client_uri);
     897           0 :       goto done;
     898             :     }
     899             : 
     900           0 :   vnet_session_enable_disable (vm, 1 /* turn on session and transport */ );
     901             : 
     902           0 :   rv = proxy_server_create (vm);
     903           0 :   switch (rv)
     904             :     {
     905           0 :     case 0:
     906           0 :       break;
     907           0 :     default:
     908           0 :       error = clib_error_return (0, "server_create returned %d", rv);
     909             :     }
     910             : 
     911           0 : done:
     912           0 :   unformat_free (line_input);
     913           0 :   vec_free (client_uri);
     914           0 :   vec_free (server_uri);
     915           0 :   return error;
     916             : }
     917             : 
     918      203447 : VLIB_CLI_COMMAND (proxy_create_command, static) =
     919             : {
     920             :   .path = "test proxy server",
     921             :   .short_help = "test proxy server [server-uri <tcp://ip/port>]"
     922             :       "[client-uri <tcp://ip/port>][fifo-size <nn>[k|m]]"
     923             :       "[max-fifo-size <nn>[k|m]][high-watermark <nn>]"
     924             :       "[low-watermark <nn>][rcv-buf-size <nn>][prealloc-fifos <nn>]"
     925             :       "[private-segment-size <mem>][private-segment-count <nn>]",
     926             :   .function = proxy_server_create_command_fn,
     927             : };
     928             : 
     929             : clib_error_t *
     930         559 : proxy_main_init (vlib_main_t * vm)
     931             : {
     932         559 :   proxy_main_t *pm = &proxy_main;
     933         559 :   pm->server_client_index = ~0;
     934         559 :   pm->active_open_client_index = ~0;
     935             : 
     936         559 :   return 0;
     937             : }
     938             : 
     939        3359 : VLIB_INIT_FUNCTION (proxy_main_init);
     940             : 
     941             : /*
     942             : * fd.io coding-style-patch-verification: ON
     943             : *
     944             : * Local Variables:
     945             : * eval: (c-set-style "gnu")
     946             : * End:
     947             : */

Generated by: LCOV version 1.14