+
+ /* 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;
+
+ if (PREDICT_TRUE (t0->hw_if_index != ~0))
+ {
+ vnet_buffer (b[0])->ipsec.flags = 0;
+ sw_if_index0 = t0->sw_if_index;
+ vnet_buffer (b[0])->sw_if_index[VLIB_RX] = sw_if_index0;
+
+ if (PREDICT_FALSE (!(t0->flags & VNET_HW_INTERFACE_FLAG_LINK_UP)))
+ {
+ vlib_increment_combined_counter
+ (drop_counter, thread_index, sw_if_index0, 1, len0);
+ n_disabled++;
+ next[0] = IPSEC_INPUT_NEXT_DROP;
+ goto trace00;
+ }
+
+ if (PREDICT_TRUE (sw_if_index0 == last_sw_if_index))
+ {
+ n_packets++;
+ n_bytes += len0;
+ }
+ else
+ {
+ if (n_packets)
+ {
+ vlib_increment_combined_counter
+ (rx_counter, thread_index, last_sw_if_index,
+ n_packets, n_bytes);
+ }
+
+ last_sw_if_index = sw_if_index0;
+ n_packets = 1;
+ n_bytes = len0;
+ }
+ }
+ else
+ {
+ vnet_buffer (b[0])->ipsec.flags = IPSEC_FLAG_IPSEC_GRE_TUNNEL;
+ }
+
+ trace00:
+ if (PREDICT_FALSE (is_trace))
+ {
+ if (b[0]->flags & VLIB_BUFFER_IS_TRACED)
+ {
+ ipsec_if_input_trace_t *tr =
+ vlib_add_trace (vm, node, b[0], sizeof (*tr));
+ tr->spi = clib_host_to_net_u32 (esp0->spi);
+ tr->seq = clib_host_to_net_u32 (esp0->seq);
+ }
+ }
+
+ /* next */
+ b += 1;
+ next += 1;
+ n_left_from -= 1;