+ if (PREDICT_TRUE (thread_index != sa0->decrypt_thread_index))
+ {
+ next[0] = AH_DECRYPT_NEXT_HANDOFF;
+ goto next;
+ }
+
+ pd->sa_index = current_sa_index;
+
+ ih4 = vlib_buffer_get_current (b[0]);
+ ih6 = vlib_buffer_get_current (b[0]);
+ pd->current_data = b[0]->current_data;
+
+ if (is_ip6)
+ {
+ ip6_ext_header_t *prev = NULL;
+ ah0 =
+ ip6_ext_header_find (vm, b[0], ih6, IP_PROTOCOL_IPSEC_AH, &prev);
+ pd->ip_hdr_size = sizeof (ip6_header_t);
+ ASSERT ((u8 *) ah0 - (u8 *) ih6 == pd->ip_hdr_size);
+ }
+ else
+ {
+ if (ip4_is_fragment (ih4))
+ {
+ b[0]->error = node->errors[AH_DECRYPT_ERROR_DROP_FRAGMENTS];
+ next[0] = AH_DECRYPT_NEXT_DROP;
+ goto next;
+ }
+ pd->ip_hdr_size = ip4_header_bytes (ih4);
+ ah0 = (ah_header_t *) ((u8 *) ih4 + pd->ip_hdr_size);
+ }
+
+ pd->seq = clib_host_to_net_u32 (ah0->seq_no);
+
+ /* anti-replay check */
+ if (ipsec_sa_anti_replay_check (sa0, pd->seq))
+ {
+ b[0]->error = node->errors[AH_DECRYPT_ERROR_REPLAY];
+ next[0] = AH_DECRYPT_NEXT_DROP;
+ goto next;
+ }
+
+ current_sa_bytes += b[0]->current_length;
+ current_sa_pkts += 1;
+
+ pd->icv_size = sa0->integ_icv_size;
+ pd->nexthdr_cached = ah0->nexthdr;
+ if (PREDICT_TRUE (sa0->integ_alg != IPSEC_INTEG_ALG_NONE))
+ {
+ if (PREDICT_FALSE (ipsec_sa_is_set_USE_ESN (sa0) &&
+ pd->current_data + b[0]->current_length
+ + sizeof (u32) > buffer_data_size))
+ {
+ b[0]->error = node->errors[AH_DECRYPT_ERROR_NO_TAIL_SPACE];
+ next[0] = AH_DECRYPT_NEXT_DROP;
+ goto next;
+ }
+
+ vnet_crypto_op_t *op;
+ vec_add2_aligned (ptd->integ_ops, op, 1, CLIB_CACHE_LINE_BYTES);
+ vnet_crypto_op_init (op, sa0->integ_op_id);
+
+ op->src = (u8 *) ih4;
+ op->len = b[0]->current_length;
+ op->digest = (u8 *) ih4 - pd->icv_size;
+ op->flags = VNET_CRYPTO_OP_FLAG_HMAC_CHECK;
+ op->digest_len = pd->icv_size;
+ op->key_index = sa0->integ_key_index;
+ op->user_data = b - bufs;
+ if (ipsec_sa_is_set_USE_ESN (sa0))
+ {
+ u32 seq_hi = clib_host_to_net_u32 (sa0->seq_hi);
+
+ op->len += sizeof (seq_hi);
+ clib_memcpy (op->src + b[0]->current_length, &seq_hi,
+ sizeof (seq_hi));
+ }
+ clib_memcpy (op->digest, ah0->auth_data, pd->icv_size);
+ clib_memset (ah0->auth_data, 0, pd->icv_size);