diff options
author | Szymon Sliwa <szs@semihalf.com> | 2018-01-26 12:30:41 +0100 |
---|---|---|
committer | Szymon Sliwa <szs@semihalf.com> | 2018-02-06 14:48:32 +0100 |
commit | afb5b006e4451a9dcb3270d4a5755413e65f5497 (patch) | |
tree | e5a8de9f1c1bda994b9a9248cab18d8506b052c4 /src/plugins/odp/ipsec/crypto_input.c | |
parent | 9775521a9ca1466e9a02fe4d69afafc55dcbc09c (diff) |
plugins: odp: Add support for async crypto mode
By default ipsec picks asynchronuous crypto. After the operation it may
turn out that the operation was performed synchronously anyways, in such
case the packet is send further by the esp_* node because there will be
no notification event sent about the crypto completion.
To use asynchronous mode put async in the odp section
of the startup.conf file,
like this:
odp {
async
}
Falls back to synchronous mode.
Change-Id: I5301df5f1c93a5ccd53a9c0ed2c4cacb9ca5fdd4
Signed-off-by: Szymon Sliwa <szs@semihalf.com>
Diffstat (limited to 'src/plugins/odp/ipsec/crypto_input.c')
-rw-r--r-- | src/plugins/odp/ipsec/crypto_input.c | 155 |
1 files changed, 155 insertions, 0 deletions
diff --git a/src/plugins/odp/ipsec/crypto_input.c b/src/plugins/odp/ipsec/crypto_input.c new file mode 100644 index 00000000..03d2ccd8 --- /dev/null +++ b/src/plugins/odp/ipsec/crypto_input.c @@ -0,0 +1,155 @@ +#include <vlib/vlib.h> +#include <vnet/ip/ip.h> + +#include <odp/ipsec/ipsec.h> +#include <odp/ipsec/esp.h> +#include <odp/odp_packet.h> + +#include <assert.h> + +#define foreach_odp_crypto_input_next \ + _(DROP, "error-drop") \ + _(ENCRYPT_POST, "odp-crypto-esp-encrypt-post") \ + _(DECRYPT_POST, "odp-crypto-esp-decrypt-post") + +typedef enum +{ +#define _(f, s) ODP_CRYPTO_INPUT_NEXT_##f, + foreach_odp_crypto_input_next +#undef _ +ODP_CRYPTO_INPUT_N_NEXT, +} odp_crypto_input_next_t; + +#define foreach_crypto_input_error \ +_(DEQUE_COP, "Dequed crypto operations") + +typedef enum +{ +#define _(sym,str) CRYPTO_INPUT_ERROR_##sym, + foreach_crypto_input_error +#undef _ +} crypto_input_error_t; + +static char *crypto_input_error_strings[] = { +#define _(sym,string) string, + foreach_crypto_input_error +#undef _ +}; + +typedef struct +{ + u32 next_index; + odp_packet_t pkt; +} odp_packet_crypto_trace_t; + +static u8 * +format_odp_crypto_input_trace (u8 * s, va_list * args) +{ + CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); + CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); + + s = format (s, " odp-crypto-input "); + + return s; +} + +static uword +odp_dequeue_cops (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * frame, odp_queue_t queue, u32 next_node_index) +{ + u32 next_index = next_node_index, n_deq, n_cops, *to_next = 0; + const int MAX_EVENTS = (1<<8); + odp_event_t events[MAX_EVENTS]; + + n_deq = odp_queue_deq_multi(queue, events, MAX_EVENTS); + + n_cops = n_deq; + + int index = 0; + while(n_cops > 0) { + u32 n_left_to_next; + + vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); + + while(n_cops > 0 && n_left_to_next > 0) { + odp_event_t event = events[index++]; + + ASSERT(ODP_EVENT_CRYPTO_COMPL == odp_event_type(event)); + + odp_crypto_compl_t compl; + odp_crypto_op_result_t result; + odp_packet_t pkt; + vlib_buffer_t *b0; + u32 bi0; + + compl = odp_crypto_compl_from_event(event); + odp_crypto_compl_result(compl, &result); + pkt = result.pkt; + + b0 = vlib_buffer_from_odp_packet(pkt); + bi0 = vlib_get_buffer_index (vm, b0); + + to_next[0] = bi0; + to_next += 1; + + n_cops -= 1; + n_left_to_next -= 1; + + if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) + { + odp_packet_crypto_trace_t *tr; + tr = vlib_add_trace (vm, node, b0, sizeof (*tR)); + tr->next_index = next_index; + } + + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, + to_next, n_left_to_next, bi0, next_node_index); + } + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + vlib_node_increment_counter (vm, odp_crypto_input_node.index, + CRYPTO_INPUT_ERROR_DEQUE_COP, + n_deq); + + return n_deq; +} + +static uword +odp_crypto_input_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + odp_crypto_main_t *ocm = &odp_crypto_main; + u32 thread_index = vlib_get_thread_index (); + odp_crypto_worker_main_t *cwm = + vec_elt_at_index (ocm->workers, thread_index); + u32 n_cops_dequeued = 0; + n_cops_dequeued += odp_dequeue_cops(vm, node, frame, cwm->post_encrypt, ODP_CRYPTO_INPUT_NEXT_ENCRYPT_POST); + n_cops_dequeued += odp_dequeue_cops(vm, node, frame, cwm->post_decrypt, ODP_CRYPTO_INPUT_NEXT_DECRYPT_POST); + return n_cops_dequeued; +} + + +VLIB_REGISTER_NODE (odp_crypto_input_node) = +{ + .function = odp_crypto_input_node_fn, + .name = "odp-crypto-input", + .format_trace = format_odp_crypto_input_trace, + .type = VLIB_NODE_TYPE_INPUT, + .state = VLIB_NODE_STATE_DISABLED, + + .n_errors = ARRAY_LEN(crypto_input_error_strings), + .error_strings = crypto_input_error_strings, + + .n_next_nodes = ODP_CRYPTO_INPUT_N_NEXT, + .next_nodes = + { +#define _(s, n) [ODP_CRYPTO_INPUT_NEXT_##s] = n, + foreach_odp_crypto_input_next +#undef _ + }, +}; + +VLIB_NODE_FUNCTION_MULTIARCH (odp_crypto_input_node, odp_crypto_input_node_fn); + + + |