1543852a4SDave Wallace/*
25e06257cSFlorin Coras * Copyright (c) 2017-2019 Cisco and/or its affiliates.
3543852a4SDave Wallace * Licensed under the Apache License, Version 2.0 (the "License");
4543852a4SDave Wallace * you may not use this
5543852a4SDave Wallace * You may obtain a copy of the License at:
6543852a4SDave Wallace *
7543852a4SDave Wallace *     http://www.apache.org/licenses/LICENSE-2.0
8543852a4SDave Wallace *
9543852a4SDave Wallace * Unless required by applicable law or agreed to in writing, software
10543852a4SDave Wallace * distributed under the License is distributed on an "AS IS" BASIS,
11543852a4SDave Wallace * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12543852a4SDave Wallace * See the License for the specific language governing permissions and
13543852a4SDave Wallace * limitations under the License.
14543852a4SDave Wallace */
15543852a4SDave Wallace
16543852a4SDave Wallace#include <stdio.h>
17543852a4SDave Wallace#include <stdlib.h>
185c7cf1ccSDave Wallace#include <vcl/vppcom.h>
190d427d8dSFlorin Coras#include <vcl/vcl_debug.h>
20697faeacSFlorin Coras#include <vcl/vcl_private.h>
2188001c64SFlorin Coras#include <svm/fifo_segment.h>
227e607a73SDave Wallace
23134a996aSFlorin Coras__thread uword __vcl_worker_index = ~0;
24134a996aSFlorin Coras
25d85de68eSFlorin Corasstatic int
26c4c4cf50SFlorin Corasvcl_segment_is_not_mounted (vcl_worker_t * wrk, u64 segment_handle)
2754693d23SFlorin Coras{
28c4c4cf50SFlorin Coras  u32 segment_index;
2954693d23SFlorin Coras
30d85de68eSFlorin Coras  if (segment_handle == VCL_INVALID_SEGMENT_HANDLE)
315f45e01fSFlorin Coras    return 0;
3254693d23SFlorin Coras
33c4c4cf50SFlorin Coras  segment_index = vcl_segment_table_lookup (segment_handle);
34c4c4cf50SFlorin Coras  if (segment_index != VCL_INVALID_SEGMENT_INDEX)
35c4c4cf50SFlorin Coras    return 0;
36c4c4cf50SFlorin Coras
37d85de68eSFlorin Coras  return 1;
3854693d23SFlorin Coras}
3954693d23SFlorin Coras
4030e79c2eSFlorin Corasstatic inline int
41e003a1b9SFlorin Corasvcl_mq_dequeue_batch (vcl_worker_t * wrk, svm_msg_q_t * mq, u32 n_max_msg)
4230e79c2eSFlorin Coras{
4330e79c2eSFlorin Coras  svm_msg_q_msg_t *msg;
4430e79c2eSFlorin Coras  u32 n_msgs;
4530e79c2eSFlorin Coras  int i;
4630e79c2eSFlorin Coras
47e003a1b9SFlorin Coras  n_msgs = clib_min (svm_msg_q_size (mq), n_max_msg);
4830e79c2eSFlorin Coras  for (i = 0; i < n_msgs; i++)
4930e79c2eSFlorin Coras    {
5030e79c2eSFlorin Coras      vec_add2 (wrk->mq_msg_vector, msg, 1);
5130e79c2eSFlorin Coras      svm_msg_q_sub_w_lock (mq, msg);
5230e79c2eSFlorin Coras    }
5330e79c2eSFlorin Coras  return n_msgs;
5430e79c2eSFlorin Coras}
5530e79c2eSFlorin Coras
56697faeacSFlorin Corasconst char *
57288eaab5SFlorin Corasvppcom_session_state_str (vcl_session_state_t state)
58543852a4SDave Wallace{
59543852a4SDave Wallace  char *st;
60543852a4SDave Wallace
61543852a4SDave Wallace  switch (state)
62543852a4SDave Wallace    {
6354140624SFlorin Coras    case STATE_CLOSED:
6454140624SFlorin Coras      st = "STATE_CLOSED";
65543852a4SDave Wallace      break;
66543852a4SDave Wallace
67543852a4SDave Wallace    case STATE_CONNECT:
68543852a4SDave Wallace      st = "STATE_CONNECT";
69543852a4SDave Wallace      break;
70543852a4SDave Wallace
71543852a4SDave Wallace    case STATE_LISTEN:
72543852a4SDave Wallace      st = "STATE_LISTEN";
73543852a4SDave Wallace      break;
74543852a4SDave Wallace
75543852a4SDave Wallace    case STATE_ACCEPT:
76543852a4SDave Wallace      st = "STATE_ACCEPT";
77543852a4SDave Wallace      break;
78543852a4SDave Wallace
793c7d4f9eSFlorin Coras    case STATE_VPP_CLOSING:
803c7d4f9eSFlorin Coras      st = "STATE_VPP_CLOSING";
814878cbe2SDave Wallace      break;
824878cbe2SDave Wallace
83543852a4SDave Wallace    case STATE_DISCONNECT:
84543852a4SDave Wallace      st = "STATE_DISCONNECT";
85543852a4SDave Wallace      break;
86543852a4SDave Wallace
87adcfb15fSFlorin Coras    case STATE_DETACHED:
88adcfb15fSFlorin Coras      st = "STATE_DETACHED";
89543852a4SDave Wallace      break;
90543852a4SDave Wallace
912d675d72SFlorin Coras    case STATE_UPDATED:
922d675d72SFlorin Coras      st = "STATE_UPDATED";
932d675d72SFlorin Coras      break;
942d675d72SFlorin Coras
952d675d72SFlorin Coras    case STATE_LISTEN_NO_MQ:
962d675d72SFlorin Coras      st = "STATE_LISTEN_NO_MQ";
972d675d72SFlorin Coras      break;
982d675d72SFlorin Coras
99543852a4SDave Wallace    default:
100543852a4SDave Wallace      st = "UNKNOWN_STATE";
101543852a4SDave Wallace      break;
102543852a4SDave Wallace    }
103543852a4SDave Wallace
104543852a4SDave Wallace  return st;
105543852a4SDave Wallace}
106543852a4SDave Wallace
107697faeacSFlorin Corasu8 *
108697faeacSFlorin Corasformat_ip4_address (u8 * s, va_list * args)
109dcf55ce2SFlorin Coras{
110697faeacSFlorin Coras  u8 *a = va_arg (*args, u8 *);
111697faeacSFlorin Coras  return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
112dcf55ce2SFlorin Coras}
113dcf55ce2SFlorin Coras
114697faeacSFlorin Corasu8 *
115697faeacSFlorin Corasformat_ip6_address (u8 * s, va_list * args)
116dcf55ce2SFlorin Coras{
117697faeacSFlorin Coras  ip6_address_t *a = va_arg (*args, ip6_address_t *);
118697faeacSFlorin Coras  u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
1194878cbe2SDave Wallace
120697faeacSFlorin Coras  i_max_n_zero = ARRAY_LEN (a->as_u16);
121697faeacSFlorin Coras  max_n_zeros = 0;
122697faeacSFlorin Coras  i_first_zero = i_max_n_zero;
123697faeacSFlorin Coras  n_zeros = 0;
124697faeacSFlorin Coras  for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
125dcf55ce2SFlorin Coras    {
126697faeacSFlorin Coras      u32 is_zero = a->as_u16[i] == 0;
127697faeacSFlorin Coras      if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
128697faeacSFlorin Coras	{
129697faeacSFlorin Coras	  i_first_zero = i;
130697faeacSFlorin Coras	  n_zeros = 0;
131697faeacSFlorin Coras	}
132697faeacSFlorin Coras      n_zeros += is_zero;
133697faeacSFlorin Coras      if ((!is_zero && n_zeros > max_n_zeros)
134697faeacSFlorin Coras	  || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
135697faeacSFlorin Coras	{
136697faeacSFlorin Coras	  i_max_n_zero = i_first_zero;
137697faeacSFlorin Coras	  max_n_zeros = n_zeros;
138697faeacSFlorin Coras	  i_first_zero = ARRAY_LEN (a->as_u16);
139697faeacSFlorin Coras	  n_zeros = 0;
140697faeacSFlorin Coras	}
141dcf55ce2SFlorin Coras    }
142697faeacSFlorin Coras
143697faeacSFlorin Coras  last_double_colon = 0;
144697faeacSFlorin Coras  for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
145dcf55ce2SFlorin Coras    {
146697faeacSFlorin Coras      if (i == i_max_n_zero && max_n_zeros > 1)
147697faeacSFlorin Coras	{
148697faeacSFlorin Coras	  s = format (s, "::");
149697faeacSFlorin Coras	  i += max_n_zeros - 1;
150697faeacSFlorin Coras	  last_double_colon = 1;
151697faeacSFlorin Coras	}
152697faeacSFlorin Coras      else
153697faeacSFlorin Coras	{
154697faeacSFlorin Coras	  s = format (s, "%s%x",
155697faeacSFlorin Coras		      (last_double_colon || i == 0) ? "" : ":",
156697faeacSFlorin Coras		      clib_net_to_host_u16 (a->as_u16[i]));
157697faeacSFlorin Coras	  last_double_colon = 0;
158697faeacSFlorin Coras	}
159dcf55ce2SFlorin Coras    }
160dcf55ce2SFlorin Coras
161697faeacSFlorin Coras  return s;
1620d2b0d54SKeith Burns (alagalah)}
1630d2b0d54SKeith Burns (alagalah)
164697faeacSFlorin Coras/* Format an IP46 address. */
165697faeacSFlorin Corasu8 *
166697faeacSFlorin Corasformat_ip46_address (u8 * s, va_list * args)
167543852a4SDave Wallace{
168697faeacSFlorin Coras  ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
169697faeacSFlorin Coras  ip46_type_t type = va_arg (*args, ip46_type_t);
170697faeacSFlorin Coras  int is_ip4 = 1;
171048b1d6aSDave Wallace
172697faeacSFlorin Coras  switch (type)
1738aa9aaffSKeith Burns (alagalah)    {
174697faeacSFlorin Coras    case IP46_TYPE_ANY:
175697faeacSFlorin Coras      is_ip4 = ip46_address_is_ip4 (ip46);
176697faeacSFlorin Coras      break;
177697faeacSFlorin Coras    case IP46_TYPE_IP4:
178697faeacSFlorin Coras      is_ip4 = 1;
179697faeacSFlorin Coras      break;
180697faeacSFlorin Coras    case IP46_TYPE_IP6:
181697faeacSFlorin Coras      is_ip4 = 0;
182697faeacSFlorin Coras      break;
183543852a4SDave Wallace    }
184543852a4SDave Wallace
185697faeacSFlorin Coras  return is_ip4 ?
186697faeacSFlorin Coras    format (s, "%U", format_ip4_address, &ip46->ip4) :
187697faeacSFlorin Coras    format (s, "%U", format_ip6_address, &ip46->ip6);
188543852a4SDave Wallace}
189543852a4SDave Wallace
190697faeacSFlorin Coras/*
191697faeacSFlorin Coras * VPPCOM Utility Functions
192697faeacSFlorin Coras */
193543852a4SDave Wallace
194458089bbSFlorin Corasstatic void
195458089bbSFlorin Corasvcl_send_session_listen (vcl_worker_t * wrk, vcl_session_t * s)
196458089bbSFlorin Coras{
197458089bbSFlorin Coras  app_session_evt_t _app_evt, *app_evt = &_app_evt;
198458089bbSFlorin Coras  session_listen_msg_t *mp;
199458089bbSFlorin Coras  svm_msg_q_t *mq;
200458089bbSFlorin Coras
201458089bbSFlorin Coras  mq = vcl_worker_ctrl_mq (wrk);
202458089bbSFlorin Coras  app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_LISTEN);
203458089bbSFlorin Coras  mp = (session_listen_msg_t *) app_evt->evt->data;
204458089bbSFlorin Coras  memset (mp, 0, sizeof (*mp));
205458089bbSFlorin Coras  mp->client_index = wrk->my_client_index;
206458089bbSFlorin Coras  mp->context = s->session_index;
207458089bbSFlorin Coras  mp->wrk_index = wrk->vpp_wrk_index;
208458089bbSFlorin Coras  mp->is_ip4 = s->transport.is_ip4;
209458089bbSFlorin Coras  clib_memcpy_fast (&mp->ip, &s->transport.lcl_ip, sizeof (mp->ip));
210458089bbSFlorin Coras  mp->port = s->transport.lcl_port;
211458089bbSFlorin Coras  mp->proto = s->session_type;
2121e96617dSFlorin Coras  if (s->flags & VCL_SESSION_F_CONNECTED)
2131e96617dSFlorin Coras    mp->flags = TRANSPORT_CFG_F_CONNECTED;
214458089bbSFlorin Coras  app_send_ctrl_evt_to_vpp (mq, app_evt);
215458089bbSFlorin Coras}
216458089bbSFlorin Coras
217458089bbSFlorin Corasstatic void
218458089bbSFlorin Corasvcl_send_session_connect (vcl_worker_t * wrk, vcl_session_t * s)
219458089bbSFlorin Coras{
220458089bbSFlorin Coras  app_session_evt_t _app_evt, *app_evt = &_app_evt;
221458089bbSFlorin Coras  session_connect_msg_t *mp;
222458089bbSFlorin Coras  svm_msg_q_t *mq;
223458089bbSFlorin Coras
224458089bbSFlorin Coras  mq = vcl_worker_ctrl_mq (wrk);
225458089bbSFlorin Coras  app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_CONNECT);
226458089bbSFlorin Coras  mp = (session_connect_msg_t *) app_evt->evt->data;
227458089bbSFlorin Coras  memset (mp, 0, sizeof (*mp));
228458089bbSFlorin Coras  mp->client_index = wrk->my_client_index;
229458089bbSFlorin Coras  mp->context = s->session_index;
230458089bbSFlorin Coras  mp->wrk_index = wrk->vpp_wrk_index;
231458089bbSFlorin Coras  mp->is_ip4 = s->transport.is_ip4;
232458089bbSFlorin Coras  mp->parent_handle = s->parent_handle;
233458089bbSFlorin Coras  clib_memcpy_fast (&mp->ip, &s->transport.rmt_ip, sizeof (mp->ip));
234ef7cbf6aSFlorin Coras  clib_memcpy_fast (&mp->lcl_ip, &s->transport.lcl_ip, sizeof (mp->lcl_ip));
235458089bbSFlorin Coras  mp->port = s->transport.rmt_port;
2360a1e183eSFlorin Coras  mp->lcl_port = s->transport.lcl_port;
237458089bbSFlorin Coras  mp->proto = s->session_type;
2380a1e183eSFlorin Coras  if (s->flags & VCL_SESSION_F_CONNECTED)
2390a1e183eSFlorin Coras    mp->flags |= TRANSPORT_CFG_F_CONNECTED;
240458089bbSFlorin Coras  app_send_ctrl_evt_to_vpp (mq, app_evt);
241458089bbSFlorin Coras}
242458089bbSFlorin Coras
243458089bbSFlorin Corasvoid
244458089bbSFlorin Corasvcl_send_session_unlisten (vcl_worker_t * wrk, vcl_session_t * s)
245458089bbSFlorin Coras{
246458089bbSFlorin Coras  app_session_evt_t _app_evt, *app_evt = &_app_evt;
247458089bbSFlorin Coras  session_unlisten_msg_t *mp;
248458089bbSFlorin Coras  svm_msg_q_t *mq;
249458089bbSFlorin Coras
250458089bbSFlorin Coras  mq = vcl_worker_ctrl_mq (wrk);
251458089bbSFlorin Coras  app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_UNLISTEN);
252458089bbSFlorin Coras  mp = (session_unlisten_msg_t *) app_evt->evt->data;
253458089bbSFlorin Coras  memset (mp, 0, sizeof (*mp));
254458089bbSFlorin Coras  mp->client_index = wrk->my_client_index;
255458089bbSFlorin Coras  mp->wrk_index = wrk->vpp_wrk_index;
256458089bbSFlorin Coras  mp->handle = s->vpp_handle;
257458089bbSFlorin Coras  mp->context = wrk->wrk_index;
258458089bbSFlorin Coras  app_send_ctrl_evt_to_vpp (mq, app_evt);
259458089bbSFlorin Coras}
260458089bbSFlorin Coras
261458089bbSFlorin Corasstatic void
262458089bbSFlorin Corasvcl_send_session_disconnect (vcl_worker_t * wrk, vcl_session_t * s)
263458089bbSFlorin Coras{
264458089bbSFlorin Coras  app_session_evt_t _app_evt, *app_evt = &_app_evt;
265458089bbSFlorin Coras  session_disconnect_msg_t *mp;
266458089bbSFlorin Coras  svm_msg_q_t *mq;
267458089bbSFlorin Coras
268458089bbSFlorin Coras  /* Send to thread that owns the session */
269458089bbSFlorin Coras  mq = s->vpp_evt_q;
270458089bbSFlorin Coras  app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_DISCONNECT);
271458089bbSFlorin Coras  mp = (session_disconnect_msg_t *) app_evt->evt->data;
272458089bbSFlorin Coras  memset (mp, 0, sizeof (*mp));
273458089bbSFlorin Coras  mp->client_index = wrk->my_client_index;
274458089bbSFlorin Coras  mp->handle = s->vpp_handle;
275458089bbSFlorin Coras  app_send_ctrl_evt_to_vpp (mq, app_evt);
276458089bbSFlorin Coras}
277458089bbSFlorin Coras
278458089bbSFlorin Corasstatic void
279458089bbSFlorin Corasvcl_send_app_detach (vcl_worker_t * wrk)
280458089bbSFlorin Coras{
281458089bbSFlorin Coras  app_session_evt_t _app_evt, *app_evt = &_app_evt;
282458089bbSFlorin Coras  session_app_detach_msg_t *mp;
283458089bbSFlorin Coras  svm_msg_q_t *mq;
284458089bbSFlorin Coras
285458089bbSFlorin Coras  mq = vcl_worker_ctrl_mq (wrk);
286458089bbSFlorin Coras  app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_APP_DETACH);
287458089bbSFlorin Coras  mp = (session_app_detach_msg_t *) app_evt->evt->data;
288458089bbSFlorin Coras  memset (mp, 0, sizeof (*mp));
289458089bbSFlorin Coras  mp->client_index = wrk->my_client_index;
290458089bbSFlorin Coras  app_send_ctrl_evt_to_vpp (mq, app_evt);
291458089bbSFlorin Coras}
292543852a4SDave Wallace
29354693d23SFlorin Corasstatic void
29454693d23SFlorin Corasvcl_send_session_accepted_reply (svm_msg_q_t * mq, u32 context,
29554693d23SFlorin Coras				 session_handle_t handle, int retval)
29654693d23SFlorin Coras{
29754693d23SFlorin Coras  app_session_evt_t _app_evt, *app_evt = &_app_evt;
29854693d23SFlorin Coras  session_accepted_reply_msg_t *rmp;
29954693d23SFlorin Coras  app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_ACCEPTED_REPLY);
30054693d23SFlorin Coras  rmp = (session_accepted_reply_msg_t *) app_evt->evt->data;
30154693d23SFlorin Coras  rmp->handle = handle;
30254693d23SFlorin Coras  rmp->context = context;
30354693d23SFlorin Coras  rmp->retval = retval;
30454693d23SFlorin Coras  app_send_ctrl_evt_to_vpp (mq, app_evt);
30554693d23SFlorin Coras}
30654693d23SFlorin Coras
30799368315SFlorin Corasstatic void
30899368315SFlorin Corasvcl_send_session_disconnected_reply (svm_msg_q_t * mq, u32 context,
30999368315SFlorin Coras				     session_handle_t handle, int retval)
31099368315SFlorin Coras{
31199368315SFlorin Coras  app_session_evt_t _app_evt, *app_evt = &_app_evt;
31299368315SFlorin Coras  session_disconnected_reply_msg_t *rmp;
31399368315SFlorin Coras  app_alloc_ctrl_evt_to_vpp (mq, app_evt,
31499368315SFlorin Coras			     SESSION_CTRL_EVT_DISCONNECTED_REPLY);
31599368315SFlorin Coras  rmp = (session_disconnected_reply_msg_t *) app_evt->evt->data;
31699368315SFlorin Coras  rmp->handle = handle;
31799368315SFlorin Coras  rmp->context = context;
31899368315SFlorin Coras  rmp->retval = retval;
31999368315SFlorin Coras  app_send_ctrl_evt_to_vpp (mq, app_evt);
32099368315SFlorin Coras}
32199368315SFlorin Coras
322c9fbd66cSFlorin Corasstatic void
323c9fbd66cSFlorin Corasvcl_send_session_reset_reply (svm_msg_q_t * mq, u32 context,
324c9fbd66cSFlorin Coras			      session_handle_t handle, int retval)
325c9fbd66cSFlorin Coras{
326c9fbd66cSFlorin Coras  app_session_evt_t _app_evt, *app_evt = &_app_evt;
327c9fbd66cSFlorin Coras  session_reset_reply_msg_t *rmp;
328c9fbd66cSFlorin Coras  app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_RESET_REPLY);
329c9fbd66cSFlorin Coras  rmp = (session_reset_reply_msg_t *) app_evt->evt->data;
330c9fbd66cSFlorin Coras  rmp->handle = handle;
331c9fbd66cSFlorin Coras  rmp->context = context;
332c9fbd66cSFlorin Coras  rmp->retval = retval;
333c9fbd66cSFlorin Coras  app_send_ctrl_evt_to_vpp (mq, app_evt);
334c9fbd66cSFlorin Coras}
335c9fbd66cSFlorin Coras
33630e79c2eSFlorin Corasvoid
33730e79c2eSFlorin Corasvcl_send_session_worker_update (vcl_worker_t * wrk, vcl_session_t * s,
33830e79c2eSFlorin Coras				u32 wrk_index)
33930e79c2eSFlorin Coras{
34030e79c2eSFlorin Coras  app_session_evt_t _app_evt, *app_evt = &_app_evt;
34130e79c2eSFlorin Coras  session_worker_update_msg_t *mp;
34230e79c2eSFlorin Coras  svm_msg_q_t *mq;
34330e79c2eSFlorin Coras
34430e79c2eSFlorin Coras  mq = vcl_session_vpp_evt_q (wrk, s);
34530e79c2eSFlorin Coras  app_alloc_ctrl_evt_to_vpp (mq, app_evt, SESSION_CTRL_EVT_WORKER_UPDATE);
34630e79c2eSFlorin Coras  mp = (session_worker_update_msg_t *) app_evt->evt->data;
34730e79c2eSFlorin Coras  mp->client_index = wrk->my_client_index;
34830e79c2eSFlorin Coras  mp->handle = s->vpp_handle;
34930e79c2eSFlorin Coras  mp->req_wrk_index = wrk->vpp_wrk_index;
35030e79c2eSFlorin Coras  mp->wrk_index = wrk_index;
35130e79c2eSFlorin Coras  app_send_ctrl_evt_to_vpp (mq, app_evt);
35230e79c2eSFlorin Coras}
35330e79c2eSFlorin Coras
35454693d23SFlorin Corasstatic u32
35500cca801SFlorin Corasvcl_session_accepted_handler (vcl_worker_t * wrk, session_accepted_msg_t * mp,
35600cca801SFlorin Coras			      u32 ls_index)
35754693d23SFlorin Coras{
35854693d23SFlorin Coras  vcl_session_t *session, *listen_session;
35954693d23SFlorin Coras  svm_fifo_t *rx_fifo, *tx_fifo;
360134a996aSFlorin Coras  u32 vpp_wrk_index;
36199368315SFlorin Coras  svm_msg_q_t *evt_q;
36254693d23SFlorin Coras
363134a996aSFlorin Coras  session = vcl_session_alloc (wrk);
36499368315SFlorin Coras
36500cca801SFlorin Coras  listen_session = vcl_session_get (wrk, ls_index);
36600cca801SFlorin Coras  if (listen_session->vpp_handle != mp->listener_handle)
36754693d23SFlorin Coras    {
36800cca801SFlorin Coras      VDBG (0, "ERROR: listener handle %lu does not match session %u",
36900cca801SFlorin Coras	    mp->listener_handle, ls_index);
37000cca801SFlorin Coras      goto error;
37154693d23SFlorin Coras    }
37254693d23SFlorin Coras
373c4c4cf50SFlorin Coras  if (vcl_segment_is_not_mounted (wrk, mp->segment_handle))
37454693d23SFlorin Coras    {
375c4c4cf50SFlorin Coras      VDBG (0, "ERROR: segment for session %u is not mounted!",
3765e06257cSFlorin Coras	    session->session_index);
37700cca801SFlorin Coras      goto error;
37854693d23SFlorin Coras    }
37954693d23SFlorin Coras
38000cca801SFlorin Coras  rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *);
38100cca801SFlorin Coras  tx_fifo = uword_to_pointer (mp->server_tx_fifo, svm_fifo_t *);
382653e43f0SFlorin Coras  session->vpp_evt_q = uword_to_pointer (mp->vpp_event_queue_address,
383653e43f0SFlorin Coras					 svm_msg_q_t *);
384653e43f0SFlorin Coras  rx_fifo->client_session_index = session->session_index;
385653e43f0SFlorin Coras  tx_fifo->client_session_index = session->session_index;
386653e43f0SFlorin Coras  rx_fifo->client_thread_index = vcl_get_worker_index ();
387653e43f0SFlorin Coras  tx_fifo->client_thread_index = vcl_get_worker_index ();
388653e43f0SFlorin Coras  vpp_wrk_index = tx_fifo->master_thread_index;
389653e43f0SFlorin Coras  vec_validate (wrk->vpp_event_queues, vpp_wrk_index);
390653e43f0SFlorin Coras  wrk->vpp_event_queues[vpp_wrk_index] = session->vpp_evt_q;
391653e43f0SFlorin Coras
39254693d23SFlorin Coras  session->vpp_handle = mp->handle;
3933c7d4f9eSFlorin Coras  session->vpp_thread_index = rx_fifo->master_thread_index;
39454693d23SFlorin Coras  session->rx_fifo = rx_fifo;
39554693d23SFlorin Coras  session->tx_fifo = tx_fifo;
39654693d23SFlorin Coras
39754693d23SFlorin Coras  session->session_state = STATE_ACCEPT;
39809d18c2fSFlorin Coras  session->transport.rmt_port = mp->rmt.port;
39909d18c2fSFlorin Coras  session->transport.is_ip4 = mp->rmt.is_ip4;
40009d18c2fSFlorin Coras  clib_memcpy_fast (&session->transport.rmt_ip, &mp->rmt.ip,
401178cf493SDave Barach		    sizeof (ip46_address_t));
40254693d23SFlorin Coras
403134a996aSFlorin Coras  vcl_session_table_add_vpp_handle (wrk, mp->handle, session->session_index);
40454693d23SFlorin Coras  session->transport.lcl_port = listen_session->transport.lcl_port;
40554693d23SFlorin Coras  session->transport.lcl_ip = listen_session->transport.lcl_ip;
406460dce6eSFlorin Coras  session->session_type = listen_session->session_type;
4079fd99627SNathan Skrzypczak  session->is_dgram = vcl_proto_is_dgram (session->session_type);
4089fd99627SNathan Skrzypczak  session->listener_index = listen_session->session_index;
4099fd99627SNathan Skrzypczak  listen_session->n_accepted_sessions++;
41054693d23SFlorin Coras
4115e06257cSFlorin Coras  VDBG (1, "session %u [0x%llx]: client accept request from %s address %U"
4125e06257cSFlorin Coras	" port %d queue %p!", session->session_index, mp->handle,
41309d18c2fSFlorin Coras	mp->rmt.is_ip4 ? "IPv4" : "IPv6", format_ip46_address, &mp->rmt.ip,
41409d18c2fSFlorin Coras	mp->rmt.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
41509d18c2fSFlorin Coras	clib_net_to_host_u16 (mp->rmt.port), session->vpp_evt_q);
41654693d23SFlorin Coras  vcl_evt (VCL_EVT_ACCEPT, session, listen_session, session_index);
41754693d23SFlorin Coras
41800cca801SFlorin Coras  vcl_send_session_accepted_reply (session->vpp_evt_q, mp->context,
41900cca801SFlorin Coras				   session->vpp_handle, 0);
42000cca801SFlorin Coras
421134a996aSFlorin Coras  return session->session_index;
42200cca801SFlorin Coras
42300cca801SFlorin Coraserror:
42400cca801SFlorin Coras  evt_q = uword_to_pointer (mp->vpp_event_queue_address, svm_msg_q_t *);
42500cca801SFlorin Coras  vcl_send_session_accepted_reply (evt_q, mp->context, mp->handle,
42600cca801SFlorin Coras				   VNET_API_ERROR_INVALID_ARGUMENT);
42700cca801SFlorin Coras  vcl_session_free (wrk, session);
42800cca801SFlorin Coras  return VCL_INVALID_SESSION_INDEX;
42954693d23SFlorin Coras}
43054693d23SFlorin Coras
43154693d23SFlorin Corasstatic u32
432134a996aSFlorin Corasvcl_session_connected_handler (vcl_worker_t * wrk,
433134a996aSFlorin Coras			       session_connected_msg_t * mp)
43454693d23SFlorin Coras{
43599368315SFlorin Coras  u32 session_index, vpp_wrk_index;
43654693d23SFlorin Coras  svm_fifo_t *rx_fifo, *tx_fifo;
43799368315SFlorin Coras  vcl_session_t *session = 0;
43854693d23SFlorin Coras
43954693d23SFlorin Coras  session_index = mp->context;
440134a996aSFlorin Coras  session = vcl_session_get (wrk, session_index);
441070453d8SFlorin Coras  if (!session)
442070453d8SFlorin Coras    {
4435e06257cSFlorin Coras      VDBG (0, "ERROR: vpp handle 0x%llx has no session index (%u)!",
4445e06257cSFlorin Coras	    mp->handle, session_index);
445070453d8SFlorin Coras      return VCL_INVALID_SESSION_INDEX;
446070453d8SFlorin Coras    }
44754693d23SFlorin Coras  if (mp->retval)
44854693d23SFlorin Coras    {
4495e06257cSFlorin Coras      VDBG (0, "ERROR: session index %u: connect failed! %U",
45000e01d3eSFlorin Coras	    session_index, format_session_error, mp->retval);
451adcfb15fSFlorin Coras      session->session_state = STATE_DETACHED | STATE_DISCONNECT;
452070453d8SFlorin Coras      session->vpp_handle = mp->handle;
453070453d8SFlorin Coras      return session_index;
45454693d23SFlorin Coras    }
45554693d23SFlorin Coras
456dbc9c599SFlorin Coras  session->vpp_handle = mp->handle;
457dbc9c599SFlorin Coras  session->vpp_evt_q = uword_to_pointer (mp->vpp_event_queue_address,
458dbc9c599SFlorin Coras					 svm_msg_q_t *);
459460dce6eSFlorin Coras  rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *);
460460dce6eSFlorin Coras  tx_fifo = uword_to_pointer (mp->server_tx_fifo, svm_fifo_t *);
461c4c4cf50SFlorin Coras  if (vcl_segment_is_not_mounted (wrk, mp->segment_handle))
462d85de68eSFlorin Coras    {
463c4c4cf50SFlorin Coras      VDBG (0, "segment for session %u is not mounted!",
464653e43f0SFlorin Coras	    session->session_index);
465adcfb15fSFlorin Coras      session->session_state = STATE_DETACHED | STATE_DISCONNECT;
466dbc9c599SFlorin Coras      vcl_send_session_disconnect (wrk, session);
467dbc9c599SFlorin Coras      return session_index;
468d85de68eSFlorin Coras    }
469d85de68eSFlorin Coras
470460dce6eSFlorin Coras  rx_fifo->client_session_index = session_index;
471460dce6eSFlorin Coras  tx_fifo->client_session_index = session_index;
4722179513bSFlorin Coras  rx_fifo->client_thread_index = vcl_get_worker_index ();
4732179513bSFlorin Coras  tx_fifo->client_thread_index = vcl_get_worker_index ();
474460dce6eSFlorin Coras
475653e43f0SFlorin Coras  vpp_wrk_index = tx_fifo->master_thread_index;
476653e43f0SFlorin Coras  vec_validate (wrk->vpp_event_queues, vpp_wrk_index);
477653e43f0SFlorin Coras  wrk->vpp_event_queues[vpp_wrk_index] = session->vpp_evt_q;
47899368315SFlorin Coras
479653e43f0SFlorin Coras  if (mp->ct_rx_fifo)
48099368315SFlorin Coras    {
481653e43f0SFlorin Coras      session->ct_rx_fifo = uword_to_pointer (mp->ct_rx_fifo, svm_fifo_t *);
482653e43f0SFlorin Coras      session->ct_tx_fifo = uword_to_pointer (mp->ct_tx_fifo, svm_fifo_t *);
483c4c4cf50SFlorin Coras      if (vcl_segment_is_not_mounted (wrk, mp->ct_segment_handle))
484653e43f0SFlorin Coras	{
485c4c4cf50SFlorin Coras	  VDBG (0, "ct segment for session %u is not mounted!",
486653e43f0SFlorin Coras		session->session_index);
487adcfb15fSFlorin Coras	  session->session_state = STATE_DETACHED | STATE_DISCONNECT;
488dbc9c599SFlorin Coras	  vcl_send_session_disconnect (wrk, session);
489dbc9c599SFlorin Coras	  return session_index;
490653e43f0SFlorin Coras	}
49199368315SFlorin Coras    }
49254693d23SFlorin Coras
49354693d23SFlorin Coras  session->rx_fifo = rx_fifo;
49454693d23SFlorin Coras  session->tx_fifo = tx_fifo;
4953c7d4f9eSFlorin Coras  session->vpp_thread_index = rx_fifo->master_thread_index;
49609d18c2fSFlorin Coras  session->transport.is_ip4 = mp->lcl.is_ip4;
49709d18c2fSFlorin Coras  clib_memcpy_fast (&session->transport.lcl_ip, &mp->lcl.ip,
498178cf493SDave Barach		    sizeof (session->transport.lcl_ip));
49909d18c2fSFlorin Coras  session->transport.lcl_port = mp->lcl.port;
50054693d23SFlorin Coras  session->session_state = STATE_CONNECT;
50154693d23SFlorin Coras
50254693d23SFlorin Coras  /* Add it to lookup table */
5033c7d4f9eSFlorin Coras  vcl_session_table_add_vpp_handle (wrk, mp->handle, session_index);
50454693d23SFlorin Coras
5055e06257cSFlorin Coras  VDBG (1, "session %u [0x%llx] connected! rx_fifo %p, refcnt %d, tx_fifo %p,"
5065e06257cSFlorin Coras	" refcnt %d", session_index, mp->handle, session->rx_fifo,
50754693d23SFlorin Coras	session->rx_fifo->refcnt, session->tx_fifo, session->tx_fifo->refcnt);
508070453d8SFlorin Coras
50954693d23SFlorin Coras  return session_index;
51054693d23SFlorin Coras}
51154693d23SFlorin Coras
5123c7d4f9eSFlorin Corasstatic int
5133c7d4f9eSFlorin Corasvcl_flag_accepted_session (vcl_session_t * session, u64 handle, u32 flags)
5143c7d4f9eSFlorin Coras{
5153c7d4f9eSFlorin Coras  vcl_session_msg_t *accepted_msg;
5163c7d4f9eSFlorin Coras  int i;
5173c7d4f9eSFlorin Coras
5183c7d4f9eSFlorin Coras  for (i = 0; i < vec_len (session->accept_evts_fifo); i++)
5193c7d4f9eSFlorin Coras    {
5203c7d4f9eSFlorin Coras      accepted_msg = &session->accept_evts_fifo[i];
5213c7d4f9eSFlorin Coras      if (accepted_msg->accepted_msg.handle == handle)
5223c7d4f9eSFlorin Coras	{
523b0f662feSFlorin Coras	  accepted_msg->flags |= flags;
5243c7d4f9eSFlorin Coras	  return 1;
5253c7d4f9eSFlorin Coras	}
5263c7d4f9eSFlorin Coras    }
5273c7d4f9eSFlorin Coras  return 0;
5283c7d4f9eSFlorin Coras}
5293c7d4f9eSFlorin Coras
530c9fbd66cSFlorin Corasstatic u32
531134a996aSFlorin Corasvcl_session_reset_handler (vcl_worker_t * wrk,
532134a996aSFlorin Coras			   session_reset_msg_t * reset_msg)
533c9fbd66cSFlorin Coras{
534c9fbd66cSFlorin Coras  vcl_session_t *session;
535c9fbd66cSFlorin Coras  u32 sid;
536c9fbd66cSFlorin Coras
537134a996aSFlorin Coras  sid = vcl_session_index_from_vpp_handle (wrk, reset_msg->handle);
538134a996aSFlorin Coras  session = vcl_session_get (wrk, sid);
539c9fbd66cSFlorin Coras  if (!session)
540c9fbd66cSFlorin Coras    {
541c9fbd66cSFlorin Coras      VDBG (0, "request to reset unknown handle 0x%llx", reset_msg->handle);
542c9fbd66cSFlorin Coras      return VCL_INVALID_SESSION_INDEX;
543c9fbd66cSFlorin Coras    }
5443c7d4f9eSFlorin Coras
5453c7d4f9eSFlorin Coras  /* Caught a reset before actually accepting the session */
5463c7d4f9eSFlorin Coras  if (session->session_state == STATE_LISTEN)
5473c7d4f9eSFlorin Coras    {
5483c7d4f9eSFlorin Coras
5493c7d4f9eSFlorin Coras      if (!vcl_flag_accepted_session (session, reset_msg->handle,
5503c7d4f9eSFlorin Coras				      VCL_ACCEPTED_F_RESET))
5513c7d4f9eSFlorin Coras	VDBG (0, "session was not accepted!");
5523c7d4f9eSFlorin Coras      return VCL_INVALID_SESSION_INDEX;
5533c7d4f9eSFlorin Coras    }
5543c7d4f9eSFlorin Coras
555080aa503SFlorin Coras  if (session->session_state != STATE_CLOSED)
556080aa503SFlorin Coras    session->session_state = STATE_DISCONNECT;
5573c7d4f9eSFlorin Coras  VDBG (0, "reset session %u [0x%llx]", sid, reset_msg->handle);
558c9fbd66cSFlorin Coras  return sid;
559c9fbd66cSFlorin Coras}
560c9fbd66cSFlorin Coras
56160116995SFlorin Corasstatic u32
562134a996aSFlorin Corasvcl_session_bound_handler (vcl_worker_t * wrk, session_bound_msg_t * mp)
56360116995SFlorin Coras{
56460116995SFlorin Coras  vcl_session_t *session;
56560116995SFlorin Coras  u32 sid = mp->context;
56660116995SFlorin Coras
567134a996aSFlorin Coras  session = vcl_session_get (wrk, sid);
56860116995SFlorin Coras  if (mp->retval)
56960116995SFlorin Coras    {
5705e06257cSFlorin Coras      VERR ("session %u [0x%llx]: bind failed: %U", sid, mp->handle,
57100e01d3eSFlorin Coras	    format_session_error, mp->retval);
57260116995SFlorin Coras      if (session)
57360116995SFlorin Coras	{
574adcfb15fSFlorin Coras	  session->session_state = STATE_DETACHED;
57560116995SFlorin Coras	  session->vpp_handle = mp->handle;
57660116995SFlorin Coras	  return sid;
57760116995SFlorin Coras	}
57860116995SFlorin Coras      else
57960116995SFlorin Coras	{
5805e06257cSFlorin Coras	  VDBG (0, "ERROR: session %u [0x%llx]: Invalid session index!",
5815e06257cSFlorin Coras		sid, mp->handle);
58260116995SFlorin Coras	  return VCL_INVALID_SESSION_INDEX;
58360116995SFlorin Coras	}
58460116995SFlorin Coras    }
58560116995SFlorin Coras
58660116995SFlorin Coras  session->vpp_handle = mp->handle;
58760116995SFlorin Coras  session->transport.is_ip4 = mp->lcl_is_ip4;
588178cf493SDave Barach  clib_memcpy_fast (&session->transport.lcl_ip, mp->lcl_ip,
589178cf493SDave Barach		    sizeof (ip46_address_t));
59060116995SFlorin Coras  session->transport.lcl_port = mp->lcl_port;
591134a996aSFlorin Coras  vcl_session_table_add_listener (wrk, mp->handle, sid);
59260116995SFlorin Coras  session->session_state = STATE_LISTEN;
59360116995SFlorin Coras
5945f45e01fSFlorin Coras  session->vpp_evt_q = uword_to_pointer (mp->vpp_evt_q, svm_msg_q_t *);
5955f45e01fSFlorin Coras  vec_validate (wrk->vpp_event_queues, 0);
5965f45e01fSFlorin Coras  wrk->vpp_event_queues[0] = session->vpp_evt_q;
5975f45e01fSFlorin Coras
5986e3c1f8eSFlorin Coras  if (vcl_session_is_cl (session))
59960116995SFlorin Coras    {
60060116995SFlorin Coras      svm_fifo_t *rx_fifo, *tx_fifo;
60160116995SFlorin Coras      session->vpp_evt_q = uword_to_pointer (mp->vpp_evt_q, svm_msg_q_t *);
60260116995SFlorin Coras      rx_fifo = uword_to_pointer (mp->rx_fifo, svm_fifo_t *);
60360116995SFlorin Coras      rx_fifo->client_session_index = sid;
60460116995SFlorin Coras      tx_fifo = uword_to_pointer (mp->tx_fifo, svm_fifo_t *);
60560116995SFlorin Coras      tx_fifo->client_session_index = sid;
60660116995SFlorin Coras      session->rx_fifo = rx_fifo;
60760116995SFlorin Coras      session->tx_fifo = tx_fifo;
60860116995SFlorin Coras    }
60960116995SFlorin Coras
61005ecfcc0SFlorin Coras  VDBG (0, "session %u [0x%llx]: listen succeeded!", sid, mp->handle);
61160116995SFlorin Coras  return sid;
61260116995SFlorin Coras}
61360116995SFlorin Coras
614dfae9f93SFlorin Corasstatic void
615dfae9f93SFlorin Corasvcl_session_unlisten_reply_handler (vcl_worker_t * wrk, void *data)
616dfae9f93SFlorin Coras{
617dfae9f93SFlorin Coras  session_unlisten_reply_msg_t *mp = (session_unlisten_reply_msg_t *) data;
618dfae9f93SFlorin Coras  vcl_session_t *s;
619dfae9f93SFlorin Coras
620dfae9f93SFlorin Coras  s = vcl_session_get_w_vpp_handle (wrk, mp->handle);
6210a1e183eSFlorin Coras  if (!s)
622dfae9f93SFlorin Coras    {
623dfae9f93SFlorin Coras      VDBG (0, "Unlisten reply with wrong handle %llx", mp->handle);
624dfae9f93SFlorin Coras      return;
625dfae9f93SFlorin Coras    }
6260a1e183eSFlorin Coras  if (s->session_state != STATE_DISCONNECT)
6270a1e183eSFlorin Coras    {
6280a1e183eSFlorin Coras      /* Connected udp listener */
6290a1e183eSFlorin Coras      if (s->session_type == VPPCOM_PROTO_UDP
6300a1e183eSFlorin Coras	  && s->session_state == STATE_CLOSED)
6310a1e183eSFlorin Coras	return;
6320a1e183eSFlorin Coras
6330a1e183eSFlorin Coras      VDBG (0, "Unlisten session in wrong state %llx", mp->handle);
6340a1e183eSFlorin Coras      return;
6350a1e183eSFlorin Coras    }
636dfae9f93SFlorin Coras
637dfae9f93SFlorin Coras  if (mp->retval)
638dfae9f93SFlorin Coras    VDBG (0, "ERROR: session %u [0xllx]: unlisten failed: %U",
63900e01d3eSFlorin Coras	  s->session_index, mp->handle, format_session_error, mp->retval);
640dfae9f93SFlorin Coras
641dfae9f93SFlorin Coras  if (mp->context != wrk->wrk_index)
642dfae9f93SFlorin Coras    VDBG (0, "wrong context");
643dfae9f93SFlorin Coras
644dfae9f93SFlorin Coras  vcl_session_table_del_vpp_handle (wrk, mp->handle);
645dfae9f93SFlorin Coras  vcl_session_free (wrk, s);
646dfae9f93SFlorin Coras}
647dfae9f93SFlorin Coras
64868b7e588SFlorin Corasstatic void
64968b7e588SFlorin Corasvcl_session_migrated_handler (vcl_worker_t * wrk, void *data)
65068b7e588SFlorin Coras{
65168b7e588SFlorin Coras  session_migrated_msg_t *mp = (session_migrated_msg_t *) data;
65268b7e588SFlorin Coras  vcl_session_t *s;
65368b7e588SFlorin Coras
65468b7e588SFlorin Coras  s = vcl_session_get_w_vpp_handle (wrk, mp->handle);
65568b7e588SFlorin Coras  if (!s)
65668b7e588SFlorin Coras    {
65768b7e588SFlorin Coras      VDBG (0, "Migrated notification with wrong handle %llx", mp->handle);
65868b7e588SFlorin Coras      return;
65968b7e588SFlorin Coras    }
66068b7e588SFlorin Coras
66168b7e588SFlorin Coras  s->vpp_thread_index = mp->vpp_thread_index;
66257660d9dSFlorin Coras  s->vpp_handle = mp->new_handle;
66368b7e588SFlorin Coras  s->vpp_evt_q = uword_to_pointer (mp->vpp_evt_q, svm_msg_q_t *);
66468b7e588SFlorin Coras
66568b7e588SFlorin Coras  vec_validate (wrk->vpp_event_queues, s->vpp_thread_index);
66668b7e588SFlorin Coras  wrk->vpp_event_queues[s->vpp_thread_index] = s->vpp_evt_q;
66768b7e588SFlorin Coras
66868b7e588SFlorin Coras  vcl_session_table_del_vpp_handle (wrk, mp->handle);
66968b7e588SFlorin Coras  vcl_session_table_add_vpp_handle (wrk, mp->new_handle, s->session_index);
67068b7e588SFlorin Coras
67168b7e588SFlorin Coras  /* Generate new tx event if we have outstanding data */
67268b7e588SFlorin Coras  if (svm_fifo_has_event (s->tx_fifo))
67368b7e588SFlorin Coras    app_send_io_evt_to_vpp (s->vpp_evt_q, s->tx_fifo->master_session_index,
67468b7e588SFlorin Coras			    SESSION_IO_EVT_TX, SVM_Q_WAIT);
67568b7e588SFlorin Coras
67657660d9dSFlorin Coras  VDBG (0, "Migrated 0x%lx to thread %u 0x%lx", mp->handle,
67757660d9dSFlorin Coras	s->vpp_thread_index, mp->new_handle);
67868b7e588SFlorin Coras}
67968b7e588SFlorin Coras
6803c7d4f9eSFlorin Corasstatic vcl_session_t *
6813c7d4f9eSFlorin Corasvcl_session_accepted (vcl_worker_t * wrk, session_accepted_msg_t * msg)
6823c7d4f9eSFlorin Coras{
6833c7d4f9eSFlorin Coras  vcl_session_msg_t *vcl_msg;
6843c7d4f9eSFlorin Coras  vcl_session_t *session;
6853c7d4f9eSFlorin Coras
6863c7d4f9eSFlorin Coras  session = vcl_session_get_w_vpp_handle (wrk, msg->handle);
6873c7d4f9eSFlorin Coras  if (PREDICT_FALSE (session != 0))
688b0f662feSFlorin Coras    VWRN ("session overlap handle %lu state %u!", msg->handle,
689b0f662feSFlorin Coras	  session->session_state);
6903c7d4f9eSFlorin Coras
6913c7d4f9eSFlorin Coras  session = vcl_session_table_lookup_listener (wrk, msg->listener_handle);
6923c7d4f9eSFlorin Coras  if (!session)
6933c7d4f9eSFlorin Coras    {
6943c7d4f9eSFlorin Coras      VERR ("couldn't find listen session: listener handle %llx",
6953c7d4f9eSFlorin Coras	    msg->listener_handle);
6963c7d4f9eSFlorin Coras      return 0;
6973c7d4f9eSFlorin Coras    }
6983c7d4f9eSFlorin Coras
6993c7d4f9eSFlorin Coras  clib_fifo_add2 (session->accept_evts_fifo, vcl_msg);
700e88845e4SFlorin Coras  vcl_msg->flags = 0;
7013c7d4f9eSFlorin Coras  vcl_msg->accepted_msg = *msg;
7023c7d4f9eSFlorin Coras  /* Session handle points to listener until fully accepted by app */
7033c7d4f9eSFlorin Coras  vcl_session_table_add_vpp_handle (wrk, msg->handle, session->session_index);
7043c7d4f9eSFlorin Coras
7053c7d4f9eSFlorin Coras  return session;
7063c7d4f9eSFlorin Coras}
7073c7d4f9eSFlorin Coras
7083c7d4f9eSFlorin Corasstatic vcl_session_t *
7093c7d4f9eSFlorin Corasvcl_session_disconnected_handler (vcl_worker_t * wrk,
7103c7d4f9eSFlorin Coras				  session_disconnected_msg_t * msg)
7113c7d4f9eSFlorin Coras{
7123c7d4f9eSFlorin Coras  vcl_session_t *session;
7133c7d4f9eSFlorin Coras
7143c7d4f9eSFlorin Coras  session = vcl_session_get_w_vpp_handle (wrk, msg->handle);
7153c7d4f9eSFlorin Coras  if (!session)
7163c7d4f9eSFlorin Coras    {
7173c7d4f9eSFlorin Coras      VDBG (0, "request to disconnect unknown handle 0x%llx", msg->handle);
7183c7d4f9eSFlorin Coras      return 0;
7193c7d4f9eSFlorin Coras    }
7203c7d4f9eSFlorin Coras
721adcfb15fSFlorin Coras  /* Late disconnect notification on a session that has been closed */
722adcfb15fSFlorin Coras  if (session->session_state == STATE_CLOSED)
723adcfb15fSFlorin Coras    return 0;
724adcfb15fSFlorin Coras
7253c7d4f9eSFlorin Coras  /* Caught a disconnect before actually accepting the session */
7263c7d4f9eSFlorin Coras  if (session->session_state == STATE_LISTEN)
7273c7d4f9eSFlorin Coras    {
7283c7d4f9eSFlorin Coras      if (!vcl_flag_accepted_session (session, msg->handle,
7293c7d4f9eSFlorin Coras				      VCL_ACCEPTED_F_CLOSED))
7303c7d4f9eSFlorin Coras	VDBG (0, "session was not accepted!");
7313c7d4f9eSFlorin Coras      return 0;
7323c7d4f9eSFlorin Coras    }
7333c7d4f9eSFlorin Coras
734adcfb15fSFlorin Coras  /* If not already reset change state */
735adcfb15fSFlorin Coras  if (session->session_state != STATE_DISCONNECT)
736adcfb15fSFlorin Coras    session->session_state = STATE_VPP_CLOSING;
737adcfb15fSFlorin Coras
7383c7d4f9eSFlorin Coras  return session;
7393c7d4f9eSFlorin Coras}
7403c7d4f9eSFlorin Coras
7419ace36d0SFlorin Corasstatic void
7429ace36d0SFlorin Corasvcl_session_cleanup_handler (vcl_worker_t * wrk, void *data)
7439ace36d0SFlorin Coras{
7449ace36d0SFlorin Coras  session_cleanup_msg_t *msg;
7459ace36d0SFlorin Coras  vcl_session_t *session;
7469ace36d0SFlorin Coras
7479ace36d0SFlorin Coras  msg = (session_cleanup_msg_t *) data;
7489ace36d0SFlorin Coras  session = vcl_session_get_w_vpp_handle (wrk, msg->handle);
7499ace36d0SFlorin Coras  if (!session)
7509ace36d0SFlorin Coras    {
7519ace36d0SFlorin Coras      VDBG (0, "disconnect confirmed for unknown handle 0x%llx", msg->handle);
7529ace36d0SFlorin Coras      return;
7539ace36d0SFlorin Coras    }
7549ace36d0SFlorin Coras
75536d49391SFlorin Coras  if (msg->type == SESSION_CLEANUP_TRANSPORT)
75636d49391SFlorin Coras    {
75736d49391SFlorin Coras      /* Transport was cleaned up before we confirmed close. Probably the
75836d49391SFlorin Coras       * app is still waiting for some data that cannot be delivered.
75936d49391SFlorin Coras       * Confirm close to make sure everything is cleaned up */
76036d49391SFlorin Coras      if (session->session_state == STATE_VPP_CLOSING)
76136d49391SFlorin Coras	vcl_session_cleanup (wrk, session, vcl_session_handle (session),
76236d49391SFlorin Coras			     1 /* do_disconnect */ );
76336d49391SFlorin Coras      return;
76436d49391SFlorin Coras    }
76536d49391SFlorin Coras
7669ace36d0SFlorin Coras  vcl_session_table_del_vpp_handle (wrk, msg->handle);
767adcfb15fSFlorin Coras  /* Should not happen. App did not close the connection so don't free it. */
768adcfb15fSFlorin Coras  if (session->session_state != STATE_CLOSED)
769adcfb15fSFlorin Coras    {
770adcfb15fSFlorin Coras      VDBG (0, "app did not close session %d", session->session_index);
771adcfb15fSFlorin Coras      session->session_state = STATE_DETACHED;
772adcfb15fSFlorin Coras      session->vpp_handle = VCL_INVALID_SESSION_HANDLE;
773adcfb15fSFlorin Coras      return;
774adcfb15fSFlorin Coras    }
7759ace36d0SFlorin Coras  vcl_session_free (wrk, session);
7769ace36d0SFlorin Coras}
7779ace36d0SFlorin Coras
77830e79c2eSFlorin Corasstatic void
77930e79c2eSFlorin Corasvcl_session_req_worker_update_handler (vcl_worker_t * wrk, void *data)
78030e79c2eSFlorin Coras{
78130e79c2eSFlorin Coras  session_req_worker_update_msg_t *msg;
78230e79c2eSFlorin Coras  vcl_session_t *s;
78330e79c2eSFlorin Coras
78430e79c2eSFlorin Coras  msg = (session_req_worker_update_msg_t *) data;
78530e79c2eSFlorin Coras  s = vcl_session_get_w_vpp_handle (wrk, msg->session_handle);
78630e79c2eSFlorin Coras  if (!s)
78730e79c2eSFlorin Coras    return;
78830e79c2eSFlorin Coras
78930e79c2eSFlorin Coras  vec_add1 (wrk->pending_session_wrk_updates, s->session_index);
79030e79c2eSFlorin Coras}
79130e79c2eSFlorin Coras
79230e79c2eSFlorin Corasstatic void
79330e79c2eSFlorin Corasvcl_session_worker_update_reply_handler (vcl_worker_t * wrk, void *data)
79430e79c2eSFlorin Coras{
79530e79c2eSFlorin Coras  session_worker_update_reply_msg_t *msg;
79630e79c2eSFlorin Coras  vcl_session_t *s;
79730e79c2eSFlorin Coras
79830e79c2eSFlorin Coras  msg = (session_worker_update_reply_msg_t *) data;
79930e79c2eS