+u32
+vnet_crypto_register_post_node (vlib_main_t * vm, char *post_node_name)
+{
+ vnet_crypto_main_t *cm = &crypto_main;
+ vnet_crypto_async_next_node_t *nn = 0;
+ vlib_node_t *cc, *pn;
+ uword index = vec_len (cm->next_nodes);
+
+ pn = vlib_get_node_by_name (vm, (u8 *) post_node_name);
+ if (!pn)
+ return ~0;
+
+ /* *INDENT-OFF* */
+ vec_foreach (cm->next_nodes, nn)
+ {
+ if (nn->node_idx == pn->index)
+ return nn->next_idx;
+ }
+ /* *INDENT-ON* */
+
+ vec_validate (cm->next_nodes, index);
+ nn = vec_elt_at_index (cm->next_nodes, index);
+
+ cc = vlib_get_node_by_name (vm, (u8 *) "crypto-dispatch");
+ nn->next_idx = vlib_node_add_named_next (vm, cc->index, post_node_name);
+ nn->node_idx = pn->index;
+
+ return nn->next_idx;
+}
+
+void
+vnet_crypto_request_async_mode (int is_enable)
+{
+ vnet_crypto_main_t *cm = &crypto_main;
+ vlib_thread_main_t *tm = vlib_get_thread_main ();
+ u32 skip_master = vlib_num_workers () > 0, i;
+ vlib_node_state_t state = VLIB_NODE_STATE_DISABLED;
+ u8 state_change = 0;
+
+ CLIB_MEMORY_STORE_BARRIER ();
+ if (is_enable && cm->async_refcnt == 0)
+ {
+ state_change = 1;
+ state =
+ cm->dispatch_mode == VNET_CRYPTO_ASYNC_DISPATCH_POLLING ?
+ VLIB_NODE_STATE_POLLING : VLIB_NODE_STATE_INTERRUPT;
+ }
+ if (!is_enable && cm->async_refcnt == 1)
+ {
+ state_change = 1;
+ state = VLIB_NODE_STATE_DISABLED;
+ }
+
+ if (state_change)
+ for (i = skip_master; i < tm->n_vlib_mains; i++)
+ {
+ vlib_main_t *ovm = vlib_get_main_by_index (i);
+ if (state != vlib_node_get_state (ovm, cm->crypto_node_index))
+ vlib_node_set_state (ovm, cm->crypto_node_index, state);
+ }
+
+ if (is_enable)
+ cm->async_refcnt += 1;
+ else if (cm->async_refcnt > 0)
+ cm->async_refcnt -= 1;
+}
+
+void
+vnet_crypto_set_async_dispatch_mode (u8 mode)
+{
+ vnet_crypto_main_t *cm = &crypto_main;
+ u32 skip_master = vlib_num_workers () > 0, i;
+ vlib_thread_main_t *tm = vlib_get_thread_main ();
+ vlib_node_state_t state = VLIB_NODE_STATE_DISABLED;
+
+ CLIB_MEMORY_STORE_BARRIER ();
+ cm->dispatch_mode = mode;
+ if (mode == VNET_CRYPTO_ASYNC_DISPATCH_INTERRUPT)
+ {
+ state =
+ cm->async_refcnt == 0 ?
+ VLIB_NODE_STATE_DISABLED : VLIB_NODE_STATE_INTERRUPT;
+ }
+ else if (mode == VNET_CRYPTO_ASYNC_DISPATCH_POLLING)
+ {
+ state =
+ cm->async_refcnt == 0 ?
+ VLIB_NODE_STATE_DISABLED : VLIB_NODE_STATE_POLLING;
+ }
+
+ for (i = skip_master; i < tm->n_vlib_mains; i++)
+ {
+ vlib_main_t *ovm = vlib_get_main_by_index (i);
+ if (state != vlib_node_get_state (ovm, cm->crypto_node_index))
+ vlib_node_set_state (ovm, cm->crypto_node_index, state);
+ }
+}
+
+int
+vnet_crypto_is_set_async_handler (vnet_crypto_async_op_id_t op)
+{
+ vnet_crypto_main_t *cm = &crypto_main;
+
+ return (op < vec_len (cm->enqueue_handlers) &&
+ NULL != cm->enqueue_handlers[op]);
+}
+
+static void
+vnet_crypto_init_cipher_data (vnet_crypto_alg_t alg, vnet_crypto_op_id_t eid,
+ vnet_crypto_op_id_t did, char *name, u8 is_aead)
+{
+ vnet_crypto_op_type_t eopt, dopt;
+ vnet_crypto_main_t *cm = &crypto_main;
+
+ cm->algs[alg].name = name;
+ cm->opt_data[eid].alg = cm->opt_data[did].alg = alg;
+ cm->opt_data[eid].active_engine_index_simple = ~0;
+ cm->opt_data[did].active_engine_index_simple = ~0;
+ cm->opt_data[eid].active_engine_index_chained = ~0;
+ cm->opt_data[did].active_engine_index_chained = ~0;
+ if (is_aead)
+ {
+ eopt = VNET_CRYPTO_OP_TYPE_AEAD_ENCRYPT;
+ dopt = VNET_CRYPTO_OP_TYPE_AEAD_DECRYPT;
+ }
+ else
+ {
+ eopt = VNET_CRYPTO_OP_TYPE_ENCRYPT;
+ dopt = VNET_CRYPTO_OP_TYPE_DECRYPT;
+ }
+ cm->opt_data[eid].type = eopt;
+ cm->opt_data[did].type = dopt;
+ cm->algs[alg].op_by_type[eopt] = eid;
+ cm->algs[alg].op_by_type[dopt] = did;
+ hash_set_mem (cm->alg_index_by_name, name, alg);
+}
+
+static void
+vnet_crypto_init_hash_data (vnet_crypto_alg_t alg, vnet_crypto_op_id_t id,
+ char *name)
+{
+ vnet_crypto_main_t *cm = &crypto_main;
+ cm->algs[alg].name = name;
+ cm->algs[alg].op_by_type[VNET_CRYPTO_OP_TYPE_HASH] = id;
+ cm->opt_data[id].alg = alg;
+ cm->opt_data[id].active_engine_index_simple = ~0;
+ cm->opt_data[id].active_engine_index_chained = ~0;
+ cm->opt_data[id].type = VNET_CRYPTO_OP_TYPE_HASH;
+ hash_set_mem (cm->alg_index_by_name, name, alg);
+}
+
+static void
+vnet_crypto_init_hmac_data (vnet_crypto_alg_t alg,
+ vnet_crypto_op_id_t id, char *name)
+{
+ vnet_crypto_main_t *cm = &crypto_main;
+ cm->algs[alg].name = name;
+ cm->algs[alg].op_by_type[VNET_CRYPTO_OP_TYPE_HMAC] = id;
+ cm->opt_data[id].alg = alg;
+ cm->opt_data[id].active_engine_index_simple = ~0;
+ cm->opt_data[id].active_engine_index_chained = ~0;
+ cm->opt_data[id].type = VNET_CRYPTO_OP_TYPE_HMAC;
+ hash_set_mem (cm->alg_index_by_name, name, alg);
+}
+
+static void
+vnet_crypto_init_async_data (vnet_crypto_async_alg_t alg,
+ vnet_crypto_async_op_id_t eid,
+ vnet_crypto_async_op_id_t did, char *name)
+{
+ vnet_crypto_main_t *cm = &crypto_main;
+
+ cm->async_algs[alg].name = name;
+ cm->async_algs[alg].op_by_type[VNET_CRYPTO_ASYNC_OP_TYPE_ENCRYPT] = eid;
+ cm->async_algs[alg].op_by_type[VNET_CRYPTO_ASYNC_OP_TYPE_DECRYPT] = did;
+ cm->async_opt_data[eid].type = VNET_CRYPTO_ASYNC_OP_TYPE_ENCRYPT;
+ cm->async_opt_data[eid].alg = alg;
+ cm->async_opt_data[eid].active_engine_index_async = ~0;
+ cm->async_opt_data[eid].active_engine_index_async = ~0;
+ cm->async_opt_data[did].type = VNET_CRYPTO_ASYNC_OP_TYPE_DECRYPT;
+ cm->async_opt_data[did].alg = alg;
+ cm->async_opt_data[did].active_engine_index_async = ~0;
+ cm->async_opt_data[did].active_engine_index_async = ~0;
+ hash_set_mem (cm->async_alg_index_by_name, name, alg);
+}
+