+ if (b[1]->flags & VLIB_BUFFER_IS_TRACED)
+ {
+ ipsec_if_input_trace_t *tr =
+ vlib_add_trace (vm, node, b[1], sizeof (*tr));
+ tr->spi = clib_host_to_net_u32 (esp1->spi);
+ tr->seq = clib_host_to_net_u32 (esp1->seq);
+ }
+ }
+
+ /* next */
+ b += 2;
+ next += 2;
+ n_left_from -= 2;
+ }
+ while (n_left_from > 0)
+ {
+ u32 sw_if_index0;
+ ip4_header_t *ip40;
+ ip6_header_t *ip60;
+ esp_header_t *esp0;
+ u32 len0;
+ u16 buf_adv0;
+ u32 tid0;
+ ipsec_tunnel_if_t *t0;
+ ipsec4_tunnel_key_t key40;
+ ipsec6_tunnel_key_t key60;
+
+ ip40 =
+ (ip4_header_t *) (b[0]->data + vnet_buffer (b[0])->l3_hdr_offset);
+
+ if (is_ip6)
+ {
+ ip60 = (ip6_header_t *) ip40;
+ esp0 = (esp_header_t *) ((u8 *) ip60 + sizeof (ip6_header_t));
+ buf_adv0 = sizeof (ip6_header_t);
+ }
+ else
+ {
+ /* NAT UDP port 4500 case, don't advance any more */
+ if (ip40->protocol == IP_PROTOCOL_UDP)
+ {
+ esp0 =
+ (esp_header_t *) ((u8 *) ip40 + ip4_header_bytes (ip40) +
+ sizeof (udp_header_t));
+ buf_adv0 = 0;
+ }
+ else
+ {
+ esp0 = (esp_header_t *) ((u8 *) ip40 + ip4_header_bytes (ip40));
+ buf_adv0 = ip4_header_bytes (ip40);
+ }
+ }
+
+ /* stats for the tunnel include all the data after the IP header
+ just like a norml IP-IP tunnel */
+ vlib_buffer_advance (b[0], buf_adv0);
+ len0 = vlib_buffer_length_in_chain (vm, b[0]);
+
+ if (is_ip6)
+ {
+ key60.remote_ip = ip60->src_address;
+ key60.spi = esp0->spi;
+
+ if (memcmp (&key60, &last_key6, sizeof (last_key6)) == 0)
+ {
+ tid0 = last_tunnel_id;
+ }
+ else
+ {
+ uword *p =
+ hash_get_mem (im->ipsec6_if_pool_index_by_key, &key60);
+ if (p)
+ {
+ tid0 = p[0];
+ last_tunnel_id = tid0;
+ clib_memcpy_fast (&last_key6, &key60, sizeof (key60));
+ }
+ else
+ {
+ n_no_tunnel++;
+ next[0] = IPSEC_INPUT_NEXT_DROP;
+ goto trace00;
+ }
+ }
+ }
+ else /* !is_ip6 */
+ {
+ key40.remote_ip = ip40->src_address.as_u32;
+ key40.spi = esp0->spi;
+
+ if (key40.as_u64 == last_key4.as_u64)
+ {
+ tid0 = last_tunnel_id;
+ }
+ else
+ {
+ uword *p =
+ hash_get (im->ipsec4_if_pool_index_by_key, key40.as_u64);
+ if (p)
+ {
+ tid0 = p[0];
+ last_tunnel_id = tid0;
+ last_key4.as_u64 = key40.as_u64;
+ }
+ else
+ {
+ n_no_tunnel++;
+ next[0] = IPSEC_INPUT_NEXT_DROP;
+ goto trace00;
+ }
+ }
+ }
+
+ t0 = pool_elt_at_index (im->tunnel_interfaces, tid0);
+ vnet_buffer (b[0])->ipsec.sad_index = t0->input_sa_index;