+ u8 icv_sz;
+ u8 iv_sz;
+ ipsec_sa_flags_t flags;
+ u32 sa_index;
+ };
+ u64 sa_data;
+ };
+
+ u32 seq;
+ i16 current_data;
+ i16 current_length;
+ u16 hdr_sz;
+ u16 is_chain;
+ u32 seq_hi;
+} esp_decrypt_packet_data_t;
+
+STATIC_ASSERT_SIZEOF (esp_decrypt_packet_data_t, 3 * sizeof (u64));
+STATIC_ASSERT_OFFSET_OF (esp_decrypt_packet_data_t, seq, sizeof (u64));
+
+/* we are forced to store the decrypt post data into 2 separate places -
+ vlib_opaque and opaque2. */
+typedef struct
+{
+ vlib_buffer_t *lb;
+ u32 free_buffer_index;
+ u8 icv_removed;
+} esp_decrypt_packet_data2_t;
+
+typedef union
+{
+ u16 next_index;
+ esp_decrypt_packet_data_t decrypt_data;
+} esp_post_data_t;
+
+STATIC_ASSERT (sizeof (esp_post_data_t) <=
+ STRUCT_SIZE_OF (vnet_buffer_opaque_t, unused),
+ "Custom meta-data too large for vnet_buffer_opaque_t");
+
+#define esp_post_data(b) \
+ ((esp_post_data_t *)((u8 *)((b)->opaque) \
+ + STRUCT_OFFSET_OF (vnet_buffer_opaque_t, unused)))
+
+STATIC_ASSERT (sizeof (esp_decrypt_packet_data2_t) <=
+ STRUCT_SIZE_OF (vnet_buffer_opaque2_t, unused),
+ "Custom meta-data too large for vnet_buffer_opaque2_t");
+
+#define esp_post_data2(b) \
+ ((esp_decrypt_packet_data2_t *)((u8 *)((b)->opaque2) \
+ + STRUCT_OFFSET_OF (vnet_buffer_opaque2_t, unused)))
+
+typedef struct
+{
+ /* esp post node index for async crypto */
+ u32 esp4_post_next;
+ u32 esp6_post_next;
+ u32 esp4_tun_post_next;
+ u32 esp6_tun_post_next;
+ u32 esp_mpls_tun_post_next;
+} esp_async_post_next_t;
+
+extern esp_async_post_next_t esp_encrypt_async_next;
+extern esp_async_post_next_t esp_decrypt_async_next;
+
+/* when submitting a frame is failed, drop all buffers in the frame */
+always_inline u32
+esp_async_recycle_failed_submit (vlib_main_t *vm, vnet_crypto_async_frame_t *f,
+ vlib_node_runtime_t *node, u32 err,
+ u32 ipsec_sa_err, u16 index, u32 *from,
+ u16 *nexts, u16 drop_next_index,
+ bool is_encrypt)
+{
+ vlib_buffer_t *b;
+ u32 n_drop = f->n_elts;
+ u32 *bi = f->buffer_indices;
+
+ while (n_drop--)
+ {
+ u32 sa_index;
+
+ from[index] = bi[0];
+ b = vlib_get_buffer (vm, bi[0]);
+
+ if (is_encrypt)
+ {
+ sa_index = vnet_buffer (b)->ipsec.sad_index;
+ }
+ else
+ {
+ sa_index = esp_post_data (b)->decrypt_data.sa_index;
+ }