FD.io VPP  v18.07.1-19-g511ce25
Vector Packet Processing
tls_async.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 Intel 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 #include <vnet/vnet.h>
16 #include <vnet/ip/ip.h>
17 #include <vnet/api_errno.h>
18 #include <vnet/ipsec/ipsec.h>
19 #include <vlib/node_funcs.h>
20 #include <openssl/engine.h>
21 #include <tlsopenssl/tls_openssl.h>
22 
23 #define MAX_SESSION 4096
24 #define MAX_VECTOR_ASYNC 256
25 
26 #define SSL_ASYNC_INFLIGHT 1
27 #define SSL_ASYNC_PENDING 2
28 #define SSL_ASYNC_READY 3
29 
30 #define EMPTY_STRUCT {0}
31 
33 {
37 
38 typedef struct openssl_event_
39 {
40  int status;
44 
48 
49  int next;
51 
52 typedef struct openssl_async_status_
53 {
59 
60 typedef struct openssl_async_
61 {
64  void (*polling) (void);
66  ENGINE *engine;
67 
69 
70 void qat_polling ();
71 void qat_pre_init ();
72 void dasync_polling ();
73 
75 {
76  char *engine;
77  void (*polling) (void);
78  void (*pre_init) (void);
79 };
80 
81 struct engine_polling engine_list[] = {
82  {"qat", qat_polling, qat_pre_init},
83  {"dasync", dasync_polling, NULL}
84 };
85 
88 
89 /* to avoid build warning */
91  void *rpc_args);
92 
93 void
95 {
98  int i, num_threads;
99 
100  num_threads = 1 /* main thread */ + vtm->n_threads;
101 
102  TLS_DBG ("Totally there is %d thread\n", num_threads);
103 
104  vec_validate (om->evt_pool, num_threads - 1);
105  vec_validate (om->status, num_threads - 1);
106 
107  om->start_polling = 0;
108  om->engine = 0;
109 
110  for (i = 0; i < num_threads; i++)
111  {
112  om->status[i].evt_run_head = -1;
113  om->status[i].evt_run_tail = -1;
114  om->status[i].evt_pending_head = -1;
115  }
116  om->polling = NULL;
117 
118  TLS_DBG ("Node disabled\n");
120 
121  return;
122 }
123 
124 int
125 openssl_engine_register (char *engine_name, char *algorithm)
126 {
127  int i, registered = -1;
129  void (*p) (void);
130  ENGINE *engine;
131 
132  for (i = 0; i < ARRAY_LEN (engine_list); i++)
133  {
134  if (!strcmp (engine_list[i].engine, engine_name))
135  {
136  om->polling = engine_list[i].polling;
137 
138  registered = i;
139  }
140  }
141  if (registered < 0)
142  {
143  return 0;
144  }
145 
146  ENGINE_load_builtin_engines ();
147  ENGINE_load_dynamic ();
148  engine = ENGINE_by_id (engine_name);
149 
150  if (engine == NULL)
151  {
152  return 0;
153  }
154 
155  om->engine = engine;
156  /* call pre-init */
157  p = engine_list[registered].pre_init;
158  if (p)
159  (*p) ();
160 
161  if (algorithm)
162  {
163  if (!ENGINE_set_default_string (engine, algorithm))
164  {
165  clib_warning ("Failed to set engine %s algorithm %s\n",
166  engine_name, algorithm);
167  return 0;
168  }
169  }
170  else
171  {
172  if (!ENGINE_set_default (engine, ENGINE_METHOD_ALL))
173  {
174  clib_warning ("Failed to set engine %s to all algorithm",
175  engine_name);
176  return 0;
177  }
178  }
179 
180  om->start_polling = 1;
181 
182  return 1;
183 
184 }
185 
186 static openssl_evt_t *
187 openssl_evt_get (u32 evt_index)
188 {
189  openssl_evt_t **evt;
190  evt =
191  pool_elt_at_index (openssl_async_main.evt_pool[vlib_get_thread_index ()],
192  evt_index);
193  return *evt;
194 }
195 
196 static openssl_evt_t *
198 {
199  openssl_evt_t **evt;
200 
201  evt =
202  pool_elt_at_index (openssl_async_main.evt_pool[thread_index], evt_index);
203  return *evt;
204 }
205 
206 int
208 {
209  openssl_evt_t *evt;
211  int *evt_run_tail = &om->status[thread_index].evt_run_tail;
212 
213  if (event_idx < 0)
214  return 0;
215 
216  evt = openssl_evt_get_w_thread (event_idx, thread_index);
217 
218  evt->status = 0;
219 
220  /*pool operation */
221  pool_put_index (om->evt_pool[thread_index], event_idx);
222 
223  if (*evt_run_tail == event_idx)
224  *evt_run_tail = -1;
225 
226  return 1;
227 }
228 
229 static u32
231 {
234  openssl_evt_t **evt;
235 
236  pool_get (tm->evt_pool[thread_index], evt);
237  if (!(*evt))
238  *evt = clib_mem_alloc (sizeof (openssl_evt_t));
239 
240  memset (*evt, 0, sizeof (openssl_evt_t));
241  (*evt)->event_index = evt - tm->evt_pool[thread_index];
242  return ((*evt)->event_index);
243 }
244 
245 int
246 openssl_async_run (void *evt)
247 {
248  openssl_evt_t *event, *event_tail;
251  int thread_index = args->thread_index;
252  int event_index = args->event_index;
253  int *evt_run_tail = &om->status[thread_index].evt_run_tail;
254  int *evt_run_head = &om->status[thread_index].evt_run_head;
255 
256  TLS_DBG ("Set event %d to run\n", event_index);
257 
258  event = openssl_evt_get_w_thread (event_index, thread_index);
259 
260  if (event->status == SSL_ASYNC_READY)
261  return 0;
262 
263  event->status = SSL_ASYNC_READY;
264  event->next = -1;
265 
266 
267  if (*evt_run_tail >= 0)
268  {
269  event_tail = openssl_evt_get_w_thread (*evt_run_tail, thread_index);
270  event_tail->next = event_index;
271  }
272  *evt_run_tail = event_index;
273  if (*evt_run_head < 0)
274  *evt_run_head = event_index;
275 
276  return 1;
277 }
278 
281  openssl_resume_handler * handler)
282 {
283  u32 eidx;
284  openssl_evt_t *event;
286  openssl_ctx_t *oc = (openssl_ctx_t *) ctx;
287  int *evt_pending_head;
288  u32 thread_id = ctx->c_thread_index;
289 
290  eidx = openssl_evt_alloc ();
291  event = openssl_evt_get (eidx);
292 
293  event->ctx_index = oc->openssl_ctx_index;
294  event->status = SSL_ASYNC_PENDING;
295  event->handler = handler;
296  event->cb_args.event_index = eidx;
297  event->cb_args.thread_index = thread_id;
298  event->engine_callback.callback = openssl_async_run;
299  event->engine_callback.arg = &event->cb_args;
300 
301  /* add to pending list */
302  evt_pending_head = &om->status[thread_id].evt_pending_head;
303  event->next = *evt_pending_head;
304  *evt_pending_head = eidx;
305 
306 
307  return &event->engine_callback;
308 }
309 
310 void
311 event_handler (void *tls_async)
312 {
313 
314  openssl_resume_handler *handler;
315  openssl_evt_t *callback;
316  stream_session_t *tls_session;
317  int thread_index;
318  tls_ctx_t *ctx;
319 
320  callback = (openssl_evt_t *) tls_async;
321  thread_index = callback->cb_args.thread_index;
322  ctx = openssl_ctx_get_w_thread (callback->ctx_index, thread_index);
323  handler = callback->handler;
324  tls_session = session_get_from_handle (ctx->tls_session_handle);
325 
326  if (handler)
327  {
328  TLS_DBG ("relaunch...\n");
329  (*handler) (ctx, tls_session);
330  }
331 
332  /* Need to free the event */
333  openssl_evt_free (callback->cb_args.event_index, thread_index);
334 
335  return;
336 }
337 
338  /* engine specific code to polling the response ring */
339 void
341 {
343  openssl_evt_t *event;
344  int *evt_pending;
345  openssl_tls_callback_t *engine_cb;
347 
348  /* POC code here to simulate the engine to call callback */
349  evt_pending = &om->status[thread_index].evt_pending_head;
350  while (*evt_pending >= 0)
351  {
352  TLS_DBG ("polling... current head = %d\n", *evt_pending);
353  event = openssl_evt_get_w_thread (*evt_pending, thread_index);
354  *evt_pending = event->next;
355  if (event->status == SSL_ASYNC_PENDING)
356  {
357  engine_cb = &event->engine_callback;
358  (*engine_cb->callback) (engine_cb->arg);
359  }
360  }
361 
362 }
363 
364 void
366 {
368 
369  ENGINE_ctrl_cmd (om->engine, "ENABLE_EXTERNAL_POLLING", 0, NULL, NULL, 0);
370 }
371 
372 /* Below code is spefic to QAT engine, and other vendors can refer to this code to enable a new engine */
373 void
375 {
378  int *config;
379 
380  config = &om->status[thread_index].poll_config;
381  if (*config)
382  return;
383 
384  ENGINE_ctrl_cmd (om->engine, "SET_INSTANCE_FOR_THREAD", thread_index,
385  NULL, NULL, 0);
386  *config = 1;
387 
388  TLS_DBG ("set thread %d and instance %d mapping\n", thread_index,
389  thread_index);
390 
391 }
392 
393 void
395 {
397  int ret;
398 
399  if (om->start_polling)
400  {
402 #define QAT_CMD_POLL (ENGINE_CMD_BASE + 1)
403  ENGINE_ctrl (om->engine, QAT_CMD_POLL, 0, &ret, NULL);
404  ;
405  }
406 }
407 
408 void
410 {
412  if (om->polling)
413  {
414  (*om->polling) ();
415  }
416 }
417 
418 void
420 {
421  u8 state = is_en ? VLIB_NODE_STATE_POLLING : VLIB_NODE_STATE_DISABLED;
422  /* *INDENT-OFF* */
424  vlib_node_set_state (this_vlib_main, tls_async_process_node.index,
425  state);
426  }));
427  /* *INDENT-ON* */
428 }
429 
430 int
432 {
433  tls_ctx_t *ctx;
434  openssl_evt_t *event;
435 
436  /* do the real job */
437  event = openssl_evt_get_w_thread (eidx, thread_index);
438  ctx = openssl_ctx_get_w_thread (event->ctx_index, thread_index);
439 
440  if (ctx)
441  {
442  ctx->resume = 1;
443  session_send_rpc_evt_to_thread (thread_index, event_handler, event);
444  }
445  return 1;
446 }
447 
448 int
450 {
451  int i;
452 
454  openssl_evt_t *event;
455  int *evt_run_head = &om->status[thread_index].evt_run_head;
456 
457  if (*evt_run_head < 0)
458  return 0;
459 
460  for (i = 0; i < MAX_VECTOR_ASYNC; i++)
461  {
462  if (*evt_run_head >= 0)
463  {
464  event = openssl_evt_get_w_thread (*evt_run_head, thread_index);
465  TLS_DBG ("event run = %d\n", *evt_run_head);
466  tls_async_do_job (*evt_run_head, thread_index);
467 
468  *evt_run_head = event->next;
469 
470  }
471  else
472  {
473  break;
474  }
475  }
476 
477  return 0;
478 
479 }
480 
481 static clib_error_t *
483 {
484 
485  TLS_DBG ("Start to call tls_async_init\n");
486  evt_pool_init (vm);
487  return 0;
488 
489 }
490 
491 static uword
493  vlib_frame_t * f)
494 {
496 
497  thread_index = vlib_get_thread_index ();
499 
500  tls_resume_from_crypto (thread_index);
501 
502  return 0;
503 }
504 
506 
507 /* *INDENT-OFF* */
509  .function = tls_async_process,
510  .type = VLIB_NODE_TYPE_INPUT,
511  .name = "tls-async-process",
512 };
513 
514 
515 /* *INDENT-ON* */
516 
517 /*
518  * fd.io coding-style-patch-verification: ON
519  *
520  * Local Variables:
521  * eval: (c-set-style "gnu")
522  * End:
523  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:437
openssl_evt_t *** evt_pool
Definition: tls_async.c:62
void qat_polling()
Definition: tls_async.c:394
#define SSL_ASYNC_READY
Definition: tls_async.c:28
int openssl_evt_free(int event_idx, u8 thread_index)
Definition: tls_async.c:207
int tls_async_do_job(int eidx, u32 thread_index)
Definition: tls_async.c:431
#define NULL
Definition: clib.h:55
void openssl_async_node_enable_disable(u8 is_en)
Definition: tls_async.c:419
static clib_error_t * tls_async_init(vlib_main_t *vm)
Definition: tls_async.c:482
static openssl_evt_t * openssl_evt_get(u32 evt_index)
Definition: tls_async.c:187
int i
#define MAX_VECTOR_ASYNC
Definition: tls_async.c:24
int(* callback)(void *arg)
Definition: tls_openssl.h:47
static stream_session_t * session_get_from_handle(session_handle_t handle)
Definition: session.h:336
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:228
char * engine
Definition: tls_async.c:76
unsigned char u8
Definition: types.h:56
static openssl_evt_t * openssl_evt_get_w_thread(int evt_index, u8 thread_index)
Definition: tls_async.c:197
static u32 openssl_evt_alloc(void)
Definition: tls_async.c:230
void(* polling)(void)
Definition: tls_async.c:77
static vlib_node_registration_t tls_async_process_node
(constructor) VLIB_REGISTER_NODE (tls_async_process_node)
Definition: tls_async.c:87
void qat_pre_init()
Definition: tls_async.c:365
void qat_polling_config()
Definition: tls_async.c:374
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:156
void session_send_rpc_evt_to_thread(u32 thread_index, void *fp, void *rpc_args)
Definition: session.c:68
struct openssl_async_ openssl_async_t
int openssl_engine_register(char *engine_name, char *algorithm)
Definition: tls_async.c:125
vhost_vring_state_t state
Definition: vhost_user.h:115
unsigned int u32
Definition: types.h:88
void openssl_async_polling()
Definition: tls_async.c:409
int openssl_async_run(void *evt)
Definition: tls_async.c:246
struct _stream_session_t stream_session_t
ENGINE * engine
Definition: tls_async.c:66
openssl_async_status_t * status
Definition: tls_async.c:63
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:464
int tls_resume_from_crypto(int thread_index)
Definition: tls_async.c:449
int openssl_resume_handler(tls_ctx_t *ctx, stream_session_t *tls_session)
Definition: tls_openssl.h:51
#define foreach_vlib_main(body)
Definition: threads.h:244
Definition: tls.h:52
void dasync_polling()
Definition: tls_async.c:340
vlib node functions
openssl_resume_handler * handler
Definition: tls_async.c:45
#define VLIB_REGISTER_NODE(x,...)
Definition: node.h:153
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:221
openssl_tls_callback_arg_t cb_args
Definition: tls_async.c:47
vlib_main_t * vm
Definition: buffer.c:294
struct openssl_tls_callback_arg_ openssl_tls_callback_arg_t
#define clib_warning(format, args...)
Definition: error.h:59
#define ARRAY_LEN(x)
Definition: clib.h:59
#define TLS_DBG(_fmt, _args...)
Definition: tls.h:35
void evt_pool_init(vlib_main_t *vm)
Definition: tls_async.c:94
void event_handler(void *tls_async)
Definition: tls_async.c:311
#define pool_put_index(p, i)
Free pool element with given index.
Definition: pool.h:299
long ctx[MAX_CONNS]
Definition: main.c:126
void(* polling)(void)
Definition: tls_async.c:64
#define SSL_ASYNC_PENDING
Definition: tls_async.c:27
static void vlib_node_set_state(vlib_main_t *vm, u32 node_index, vlib_node_state_t new_state)
Set node dispatch state.
Definition: node_funcs.h:147
static void * clib_mem_alloc(uword size)
Definition: mem.h:112
openssl_async_t openssl_async_main
Definition: tls_async.c:86
struct openssl_async_status_ openssl_async_status_t
tls_ctx_t * openssl_ctx_get_w_thread(u32 ctx_index, u8 thread_index)
Definition: tls_openssl.c:80
struct _vlib_node_registration vlib_node_registration_t
openssl_tls_callback_t * vpp_add_async_pending_event(tls_ctx_t *ctx, openssl_resume_handler *handler)
Definition: tls_async.c:280
u64 uword
Definition: types.h:112
u8 resume
Definition: tls.h:71
void(* pre_init)(void)
Definition: tls_async.c:78
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
openssl_tls_callback_t engine_callback
Definition: tls_async.c:46
struct openssl_event_ openssl_evt_t
#define QAT_CMD_POLL
static uword tls_async_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
Definition: tls_async.c:492