+static inline void
+ip4_local_check_src_x2 (vlib_buffer_t ** b, ip4_header_t ** ip,
+ ip4_local_last_check_t * last_check, u8 * error)
+{
+ ip4_fib_mtrie_leaf_t leaf[2];
+ ip4_fib_mtrie_t *mtrie[2];
+ const dpo_id_t *dpo[2];
+ load_balance_t *lb[2];
+ u32 not_last_hit;
+ u32 lbi[2];
+
+ not_last_hit = last_check->first;
+ not_last_hit |= ip[0]->src_address.as_u32 ^ last_check->src.as_u32;
+ not_last_hit |= ip[1]->src_address.as_u32 ^ last_check->src.as_u32;
+
+ vnet_buffer (b[0])->ip.fib_index =
+ vnet_buffer (b[0])->sw_if_index[VLIB_TX] != ~0 ?
+ vnet_buffer (b[0])->sw_if_index[VLIB_TX] :
+ vnet_buffer (b[0])->ip.fib_index;
+
+ vnet_buffer (b[1])->ip.fib_index =
+ vnet_buffer (b[1])->sw_if_index[VLIB_TX] != ~0 ?
+ vnet_buffer (b[1])->sw_if_index[VLIB_TX] :
+ vnet_buffer (b[1])->ip.fib_index;
+
+ if (PREDICT_FALSE (not_last_hit))
+ {
+ mtrie[0] = &ip4_fib_get (vnet_buffer (b[0])->ip.fib_index)->mtrie;
+ mtrie[1] = &ip4_fib_get (vnet_buffer (b[1])->ip.fib_index)->mtrie;
+
+ leaf[0] = ip4_fib_mtrie_lookup_step_one (mtrie[0], &ip[0]->src_address);
+ leaf[1] = ip4_fib_mtrie_lookup_step_one (mtrie[1], &ip[1]->src_address);
+
+ leaf[0] = ip4_fib_mtrie_lookup_step (mtrie[0], leaf[0],
+ &ip[0]->src_address, 2);
+ leaf[1] = ip4_fib_mtrie_lookup_step (mtrie[1], leaf[1],
+ &ip[1]->src_address, 2);
+
+ leaf[0] = ip4_fib_mtrie_lookup_step (mtrie[0], leaf[0],
+ &ip[0]->src_address, 3);
+ leaf[1] = ip4_fib_mtrie_lookup_step (mtrie[1], leaf[1],
+ &ip[1]->src_address, 3);
+
+ lbi[0] = ip4_fib_mtrie_leaf_get_adj_index (leaf[0]);
+ lbi[1] = ip4_fib_mtrie_leaf_get_adj_index (leaf[1]);
+
+ vnet_buffer (b[0])->ip.adj_index[VLIB_TX] = lbi[0];
+ vnet_buffer (b[0])->ip.adj_index[VLIB_RX] = lbi[0];
+
+ vnet_buffer (b[1])->ip.adj_index[VLIB_TX] = lbi[1];
+ vnet_buffer (b[1])->ip.adj_index[VLIB_RX] = lbi[1];
+
+ lb[0] = load_balance_get (lbi[0]);
+ lb[1] = load_balance_get (lbi[1]);
+
+ dpo[0] = load_balance_get_bucket_i (lb[0], 0);
+ dpo[1] = load_balance_get_bucket_i (lb[1], 0);
+
+ error[0] = ((error[0] == IP4_ERROR_UNKNOWN_PROTOCOL &&
+ dpo[0]->dpoi_type == DPO_RECEIVE) ?
+ IP4_ERROR_SPOOFED_LOCAL_PACKETS : error[0]);
+ error[0] = ((error[0] == IP4_ERROR_UNKNOWN_PROTOCOL &&
+ !fib_urpf_check_size (lb[0]->lb_urpf) &&
+ ip[0]->dst_address.as_u32 != 0xFFFFFFFF)
+ ? IP4_ERROR_SRC_LOOKUP_MISS : error[0]);
+
+ error[1] = ((error[1] == IP4_ERROR_UNKNOWN_PROTOCOL &&
+ dpo[1]->dpoi_type == DPO_RECEIVE) ?
+ IP4_ERROR_SPOOFED_LOCAL_PACKETS : error[1]);
+ error[1] = ((error[1] == IP4_ERROR_UNKNOWN_PROTOCOL &&
+ !fib_urpf_check_size (lb[1]->lb_urpf) &&
+ ip[1]->dst_address.as_u32 != 0xFFFFFFFF)
+ ? IP4_ERROR_SRC_LOOKUP_MISS : error[1]);
+
+ last_check->src.as_u32 = ip[1]->src_address.as_u32;
+ last_check->lbi = lbi[1];
+ last_check->error = error[1];
+ }
+ else
+ {
+ vnet_buffer (b[0])->ip.adj_index[VLIB_TX] = last_check->lbi;
+ vnet_buffer (b[0])->ip.adj_index[VLIB_RX] = last_check->lbi;