- &i0, &i1);
- next0 = vec_elt(gm->next_by_protocol, i0);
- next1 = vec_elt(gm->next_by_protocol, i1);
-
- b0->error = node->errors[i0 == SPARSE_VEC_INVALID_INDEX ? GRE_ERROR_UNKNOWN_PROTOCOL : GRE_ERROR_NONE];
- b1->error = node->errors[i1 == SPARSE_VEC_INVALID_INDEX ? GRE_ERROR_UNKNOWN_PROTOCOL : GRE_ERROR_NONE];
-
- version0 = clib_net_to_host_u16 (h0->flags_and_version);
- verr0 = version0 & GRE_VERSION_MASK;
- version1 = clib_net_to_host_u16 (h1->flags_and_version);
- verr1 = version1 & GRE_VERSION_MASK;
-
- b0->error = verr0 ? node->errors[GRE_ERROR_UNSUPPORTED_VERSION]
- : b0->error;
- next0 = verr0 ? GRE_INPUT_NEXT_DROP : next0;
- b1->error = verr1 ? node->errors[GRE_ERROR_UNSUPPORTED_VERSION]
- : b1->error;
- next1 = verr1 ? GRE_INPUT_NEXT_DROP : next1;
-
-
- /* RPF check for ip4/ip6 input */
- if (PREDICT_TRUE(next0 == GRE_INPUT_NEXT_IP4_INPUT
- || next0 == GRE_INPUT_NEXT_IP6_INPUT
- || next0 == GRE_INPUT_NEXT_ETHERNET_INPUT
- || next0 == GRE_INPUT_NEXT_MPLS_INPUT))
- {
-
- u64 key4, key6[4];
- if (!is_ipv6)
- {
- key4 = ((u64)(ip4_tun_dst0) << 32) | (u64)(ip4_tun_src0);
- }
- else
- {
- key6[0] = ip6_tun_dst0[0];
- key6[1] = ip6_tun_dst0[1];
- key6[2] = ip6_tun_src0[0];
- key6[3] = ip6_tun_src0[1];
- }
-
- if ((!is_ipv6 && cached_tunnel_key4 != key4) ||
- (is_ipv6 && cached_tunnel_key6[0] != key6[0] &&
- cached_tunnel_key6[1] != key6[1] &&
- cached_tunnel_key6[2] != key6[2] &&
- cached_tunnel_key6[3] != key6[3]))
- {
- vnet_hw_interface_t * hi;
- gre_tunnel_t * t;
- uword * p;
-
- if (!is_ipv6)
- p = hash_get (gm->tunnel_by_key4, key4);
- else
- p = hash_get_mem (gm->tunnel_by_key6, key6);
- if (!p)
- {
- next0 = GRE_INPUT_NEXT_DROP;
- b0->error = node->errors[GRE_ERROR_NO_SUCH_TUNNEL];
- goto drop0;
- }
- t = pool_elt_at_index (gm->tunnels, p[0]);
- hi = vnet_get_hw_interface (gm->vnet_main,
- t->hw_if_index);
- tunnel_sw_if_index = hi->sw_if_index;
-
- cached_tunnel_sw_if_index = tunnel_sw_if_index;
- }
- else
- {
- tunnel_sw_if_index = cached_tunnel_sw_if_index;
- }
- }
- else
- {
- next0 = GRE_INPUT_NEXT_DROP;
- goto drop0;
- }
- len = vlib_buffer_length_in_chain (vm, b0);
- vlib_increment_combined_counter (im->combined_sw_if_counters
- + VNET_INTERFACE_COUNTER_RX,
- thread_index,
- tunnel_sw_if_index,
- 1 /* packets */,
- len /* bytes */);
-
- vnet_buffer(b0)->sw_if_index[VLIB_RX] = tunnel_sw_if_index;
-
-drop0:
- if (PREDICT_TRUE(next1 == GRE_INPUT_NEXT_IP4_INPUT
- || next1 == GRE_INPUT_NEXT_IP6_INPUT
- || next1 == GRE_INPUT_NEXT_ETHERNET_INPUT
- || next1 == GRE_INPUT_NEXT_MPLS_INPUT))
- {
- u64 key4, key6[4];
- if (!is_ipv6)
- {
- key4 = ((u64)(ip4_tun_dst1) << 32) | (u64)(ip4_tun_src1);
- }
- else
- {
- key6[0] = ip6_tun_dst1[0];
- key6[1] = ip6_tun_dst1[1];
- key6[2] = ip6_tun_src1[0];
- key6[3] = ip6_tun_src1[1];
- }
-
- if ((!is_ipv6 && cached_tunnel_key4 != key4) ||
- (is_ipv6 && cached_tunnel_key6[0] != key6[0] &&
- cached_tunnel_key6[1] != key6[1] &&
- cached_tunnel_key6[2] != key6[2] &&
- cached_tunnel_key6[3] != key6[3]))
- {
- vnet_hw_interface_t * hi;
- gre_tunnel_t * t;
- uword * p;
-
- if (!is_ipv6)
- p = hash_get (gm->tunnel_by_key4, key4);
- else
- p = hash_get_mem (gm->tunnel_by_key6, key6);
-
- if (!p)
- {
- next1 = GRE_INPUT_NEXT_DROP;
- b1->error = node->errors[GRE_ERROR_NO_SUCH_TUNNEL];
- goto drop1;
- }
- t = pool_elt_at_index (gm->tunnels, p[0]);
- hi = vnet_get_hw_interface (gm->vnet_main,
- t->hw_if_index);
- tunnel_sw_if_index = hi->sw_if_index;
-
- cached_tunnel_sw_if_index = tunnel_sw_if_index;
- }
- else
- {
- tunnel_sw_if_index = cached_tunnel_sw_if_index;
- }
- }
- else
- {
- next1 = GRE_INPUT_NEXT_DROP;
- goto drop1;
- }
- len = vlib_buffer_length_in_chain (vm, b1);
- vlib_increment_combined_counter (im->combined_sw_if_counters
- + VNET_INTERFACE_COUNTER_RX,
- thread_index,
- tunnel_sw_if_index,
- 1 /* packets */,
- len /* bytes */);
-
- vnet_buffer(b1)->sw_if_index[VLIB_RX] = tunnel_sw_if_index;
-
-drop1:
- if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
- {
- gre_rx_trace_t *tr = vlib_add_trace (vm, node,
- b0, sizeof (*tr));
- tr->tunnel_id = tunnel_sw_if_index;
- if (!is_ipv6)
- {
- tr->length = ip4_0->length;
- tr->src.ip4.as_u32 = ip4_0->src_address.as_u32;
- tr->dst.ip4.as_u32 = ip4_0->dst_address.as_u32;
- }
- else
- {
- tr->length = ip6_0->payload_length;
- tr->src.ip6.as_u64[0] = ip6_0->src_address.as_u64[0];
- tr->src.ip6.as_u64[1] = ip6_0->src_address.as_u64[1];
- tr->dst.ip6.as_u64[0] = ip6_0->dst_address.as_u64[0];
- tr->dst.ip6.as_u64[1] = ip6_0->dst_address.as_u64[1];
- }
- }
-
- if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
- {
- gre_rx_trace_t *tr = vlib_add_trace (vm, node,
- b1, sizeof (*tr));
- tr->tunnel_id = tunnel_sw_if_index;
- if (!is_ipv6)
- {
- tr->length = ip4_1->length;
- tr->src.ip4.as_u32 = ip4_1->src_address.as_u32;
- tr->dst.ip4.as_u32 = ip4_1->dst_address.as_u32;
- }
- else
- {
- tr->length = ip6_1->payload_length;
- tr->src.ip6.as_u64[0] = ip6_1->src_address.as_u64[0];
- tr->src.ip6.as_u64[1] = ip6_1->src_address.as_u64[1];
- tr->dst.ip6.as_u64[0] = ip6_1->dst_address.as_u64[0];
- tr->dst.ip6.as_u64[1] = ip6_1->dst_address.as_u64[1];
- }
- }
-
- vlib_buffer_advance (b0, sizeof (*h0));
- vlib_buffer_advance (b1, sizeof (*h1));
+ &i0, &i1);
+ next0 = vec_elt (gm->next_by_protocol, i0).next_index;
+ next1 = vec_elt (gm->next_by_protocol, i1).next_index;
+ u8 ttype0 = vec_elt (gm->next_by_protocol, i0).tunnel_type;
+ u8 ttype1 = vec_elt (gm->next_by_protocol, i1).tunnel_type;
+
+ b0->error =
+ node->errors[i0 ==
+ SPARSE_VEC_INVALID_INDEX ? GRE_ERROR_UNKNOWN_PROTOCOL
+ : GRE_ERROR_NONE];
+ b1->error =
+ node->errors[i1 ==
+ SPARSE_VEC_INVALID_INDEX ? GRE_ERROR_UNKNOWN_PROTOCOL
+ : GRE_ERROR_NONE];
+
+ version0 = clib_net_to_host_u16 (h0->flags_and_version);
+ verr0 = version0 & GRE_VERSION_MASK;
+ version1 = clib_net_to_host_u16 (h1->flags_and_version);
+ verr1 = version1 & GRE_VERSION_MASK;
+
+ b0->error = verr0 ? node->errors[GRE_ERROR_UNSUPPORTED_VERSION]
+ : b0->error;
+ next0 = verr0 ? GRE_INPUT_NEXT_DROP : next0;
+ b1->error = verr1 ? node->errors[GRE_ERROR_UNSUPPORTED_VERSION]
+ : b1->error;
+ next1 = verr1 ? GRE_INPUT_NEXT_DROP : next1;
+
+
+ /* RPF check for ip4/ip6 input */
+ if (PREDICT_TRUE (next0 > GRE_INPUT_NEXT_DROP))
+ {
+ if (is_ipv6)
+ {
+ gre_mk_key6 (&ip6_0->dst_address,
+ &ip6_0->src_address,
+ vnet_buffer (b0)->ip.fib_index,
+ ttype0, 0, &key0.gtk_v6);
+ }
+ else
+ {
+ gre_mk_key4 (ip4_0->dst_address,
+ ip4_0->src_address,
+ vnet_buffer (b0)->ip.fib_index,
+ ttype0, 0, &key0.gtk_v4);
+ }
+
+ if ((!is_ipv6 && !gre_match_key4 (&cached_tunnel_key.gtk_v4,
+ &key0.gtk_v4)) ||
+ (is_ipv6 && !gre_match_key6 (&cached_tunnel_key.gtk_v6,
+ &key0.gtk_v6)))
+ {
+ gre_tunnel_t *t;
+ uword *p;
+
+ if (!is_ipv6)
+ {
+ p = hash_get_mem (gm->tunnel_by_key4, &key0.gtk_v4);
+ }
+ else
+ {
+ p = hash_get_mem (gm->tunnel_by_key6, &key0.gtk_v6);
+ }
+ if (!p)
+ {
+ next0 = GRE_INPUT_NEXT_DROP;
+ b0->error = node->errors[GRE_ERROR_NO_SUCH_TUNNEL];
+ goto drop0;
+ }
+ t = pool_elt_at_index (gm->tunnels, p[0]);
+ tunnel_sw_if_index = t->sw_if_index;
+
+ cached_tunnel_sw_if_index = tunnel_sw_if_index;
+ if (!is_ipv6)
+ {
+ cached_tunnel_key.gtk_v4 = key0.gtk_v4;
+ }
+ else
+ {
+ cached_tunnel_key.gtk_v6 = key0.gtk_v6;
+ }
+ }
+ else
+ {
+ tunnel_sw_if_index = cached_tunnel_sw_if_index;
+ }
+ }
+ else
+ {
+ next0 = GRE_INPUT_NEXT_DROP;
+ goto drop0;
+ }
+ len = vlib_buffer_length_in_chain (vm, b0);
+ vlib_increment_combined_counter (im->combined_sw_if_counters
+ + VNET_INTERFACE_COUNTER_RX,
+ thread_index,
+ tunnel_sw_if_index,
+ 1 /* packets */ ,
+ len /* bytes */ );
+
+ vnet_buffer (b0)->sw_if_index[VLIB_RX] = tunnel_sw_if_index;
+
+ drop0:
+ if (PREDICT_TRUE (next1 > GRE_INPUT_NEXT_DROP))
+ {
+ if (is_ipv6)
+ {
+ gre_mk_key6 (&ip6_1->dst_address,
+ &ip6_1->src_address,
+ vnet_buffer (b1)->ip.fib_index,
+ ttype1, 0, &key1.gtk_v6);
+ }
+ else
+ {
+ gre_mk_key4 (ip4_1->dst_address,
+ ip4_1->src_address,
+ vnet_buffer (b1)->ip.fib_index,
+ ttype1, 0, &key1.gtk_v4);
+ }
+
+ if ((!is_ipv6 && !gre_match_key4 (&cached_tunnel_key.gtk_v4,
+ &key1.gtk_v4)) ||
+ (is_ipv6 && !gre_match_key6 (&cached_tunnel_key.gtk_v6,
+ &key1.gtk_v6)))
+ {
+ gre_tunnel_t *t;
+ uword *p;
+
+ if (!is_ipv6)
+ {
+ p = hash_get_mem (gm->tunnel_by_key4, &key1.gtk_v4);
+ }
+ else
+ {
+ p = hash_get_mem (gm->tunnel_by_key6, &key1.gtk_v6);
+ }
+ if (!p)
+ {
+ next1 = GRE_INPUT_NEXT_DROP;
+ b1->error = node->errors[GRE_ERROR_NO_SUCH_TUNNEL];
+ goto drop1;
+ }
+ t = pool_elt_at_index (gm->tunnels, p[0]);
+ tunnel_sw_if_index = t->sw_if_index;
+
+ cached_tunnel_sw_if_index = tunnel_sw_if_index;
+ if (!is_ipv6)
+ {
+ cached_tunnel_key.gtk_v4 = key1.gtk_v4;
+ }
+ else
+ {
+ cached_tunnel_key.gtk_v6 = key1.gtk_v6;
+ }
+ }
+ else
+ {
+ tunnel_sw_if_index = cached_tunnel_sw_if_index;
+ }
+ }
+ else
+ {
+ next1 = GRE_INPUT_NEXT_DROP;
+ goto drop1;
+ }
+ len = vlib_buffer_length_in_chain (vm, b1);
+ vlib_increment_combined_counter (im->combined_sw_if_counters
+ + VNET_INTERFACE_COUNTER_RX,
+ thread_index,
+ tunnel_sw_if_index,
+ 1 /* packets */ ,
+ len /* bytes */ );
+
+ vnet_buffer (b1)->sw_if_index[VLIB_RX] = tunnel_sw_if_index;
+
+ drop1:
+ if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
+ {
+ gre_rx_trace_t *tr = vlib_add_trace (vm, node,
+ b0, sizeof (*tr));
+ tr->tunnel_id = tunnel_sw_if_index;
+ if (!is_ipv6)
+ {
+ tr->length = ip4_0->length;
+ tr->src.ip4.as_u32 = ip4_0->src_address.as_u32;
+ tr->dst.ip4.as_u32 = ip4_0->dst_address.as_u32;
+ }
+ else
+ {
+ tr->length = ip6_0->payload_length;
+ tr->src.ip6.as_u64[0] = ip6_0->src_address.as_u64[0];
+ tr->src.ip6.as_u64[1] = ip6_0->src_address.as_u64[1];
+ tr->dst.ip6.as_u64[0] = ip6_0->dst_address.as_u64[0];
+ tr->dst.ip6.as_u64[1] = ip6_0->dst_address.as_u64[1];
+ }
+ }
+
+ if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED))
+ {
+ gre_rx_trace_t *tr = vlib_add_trace (vm, node,
+ b1, sizeof (*tr));
+ tr->tunnel_id = tunnel_sw_if_index;
+ if (!is_ipv6)
+ {
+ tr->length = ip4_1->length;
+ tr->src.ip4.as_u32 = ip4_1->src_address.as_u32;
+ tr->dst.ip4.as_u32 = ip4_1->dst_address.as_u32;
+ }
+ else
+ {
+ tr->length = ip6_1->payload_length;
+ tr->src.ip6.as_u64[0] = ip6_1->src_address.as_u64[0];
+ tr->src.ip6.as_u64[1] = ip6_1->src_address.as_u64[1];
+ tr->dst.ip6.as_u64[0] = ip6_1->dst_address.as_u64[0];
+ tr->dst.ip6.as_u64[1] = ip6_1->dst_address.as_u64[1];
+ }
+ }
+
+ vlib_buffer_advance (b0, sizeof (*h0));
+ vlib_buffer_advance (b1, sizeof (*h1));