#include <vlib/vlib.h>
#include <vnet/pg/pg.h>
#include <vnet/gre/gre.h>
+#include <vnet/mpls/mpls.h>
#include <vppinfra/sparse_vec.h>
#define foreach_gre_input_next \
_(PUNT, "error-punt") \
_(DROP, "error-drop") \
+_(ETHERNET_INPUT, "ethernet-input") \
_(IP4_INPUT, "ip4-input") \
-_(IP6_INPUT, "ip6-input")
+_(IP6_INPUT, "ip6-input") \
+_(MPLS_INPUT, "mpls-input")
typedef enum {
#define _(s,n) GRE_INPUT_NEXT_##s,
/* Sparse vector mapping gre protocol in network byte order
to next index. */
u16 * next_by_protocol;
-
- u32 * sparse_index_by_next_index;
} gre_input_runtime_t;
static uword
{
gre_main_t * gm = &gre_main;
gre_input_runtime_t * rt = (void *) node->runtime_data;
- __attribute__((unused)) u32 n_left_from, next_index, i_next, * from, * to_next;
+ __attribute__((unused)) u32 n_left_from, next_index, * from, * to_next;
u64 cached_tunnel_key = (u64) ~0;
- u32 cached_tunnel_sw_if_index = 0, tunnel_sw_if_index;
- u32 cached_tunnel_fib_index = 0, tunnel_fib_index;
+ u32 cached_tunnel_sw_if_index = 0, tunnel_sw_if_index = 0;
u32 cpu_index = os_get_cpu_number();
+ u32 len;
+ vnet_interface_main_t *im = &gm->vnet_main->interface_main;
from = vlib_frame_vector_args (from_frame);
n_left_from = from_frame->n_vectors;
next_index = node->cached_next_index;
- i_next = vec_elt (rt->sparse_index_by_next_index, next_index);
while (n_left_from > 0)
{
/* Index sparse array with network byte order. */
protocol0 = h0->protocol;
protocol1 = h1->protocol;
- sparse_vec_index2 (rt->next_by_protocol, protocol0, protocol1,
+ sparse_vec_index2 (rt->next_by_protocol, protocol0, protocol1,
&i0, &i1);
next0 = vec_elt(rt->next_by_protocol, i0);
next1 = vec_elt(rt->next_by_protocol, i1);
- b0->error = node->errors[next0 == SPARSE_VEC_INVALID_INDEX ? GRE_ERROR_UNKNOWN_PROTOCOL : GRE_ERROR_NONE];
- b1->error = node->errors[next1 == SPARSE_VEC_INVALID_INDEX ? GRE_ERROR_UNKNOWN_PROTOCOL : GRE_ERROR_NONE];
+ 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 = 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 = verr1 ? node->errors[GRE_ERROR_UNSUPPORTED_VERSION]
: b1->error;
next1 = verr1 ? GRE_INPUT_NEXT_DROP : next1;
+
/* RPF check for ip4/ip6 input */
- if (PREDICT_FALSE(next0 == GRE_INPUT_NEXT_IP4_INPUT
- || next0 == GRE_INPUT_NEXT_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 key = ((u64)(vnet_buffer(b0)->gre.dst) << 32) |
(u64)(vnet_buffer(b0)->gre.src);
gre_tunnel_t * t;
uword * p;
- ip4_main_t * ip4m = &ip4_main;
p = hash_get (gm->tunnel_by_key, key);
if (!p)
{
hi = vnet_get_hw_interface (gm->vnet_main,
t->hw_if_index);
tunnel_sw_if_index = hi->sw_if_index;
- tunnel_fib_index = vec_elt (ip4m->fib_index_by_sw_if_index,
- tunnel_sw_if_index);
cached_tunnel_sw_if_index = tunnel_sw_if_index;
- cached_tunnel_fib_index = tunnel_fib_index;
}
else
{
tunnel_sw_if_index = cached_tunnel_sw_if_index;
- tunnel_fib_index = cached_tunnel_fib_index;
}
-
- u32 len = vlib_buffer_length_in_chain (vm, b0);
- vnet_interface_main_t *im = &gm->vnet_main->interface_main;
- vlib_increment_combined_counter (im->combined_sw_if_counters
- + VNET_INTERFACE_COUNTER_RX,
- cpu_index,
- tunnel_sw_if_index,
- 1 /* packets */,
- len /* bytes */);
-
- vnet_buffer(b0)->sw_if_index[VLIB_TX] = tunnel_fib_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,
+ cpu_index,
+ tunnel_sw_if_index,
+ 1 /* packets */,
+ len /* bytes */);
+
+ vnet_buffer(b0)->sw_if_index[VLIB_RX] = tunnel_sw_if_index;
drop0:
- if (PREDICT_FALSE(next1 == GRE_INPUT_NEXT_IP4_INPUT
- || next1 == GRE_INPUT_NEXT_IP6_INPUT))
+ 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 key = ((u64)(vnet_buffer(b1)->gre.dst) << 32) |
(u64)(vnet_buffer(b1)->gre.src);
gre_tunnel_t * t;
uword * p;
- ip4_main_t * ip4m = &ip4_main;
p = hash_get (gm->tunnel_by_key, key);
if (!p)
{
hi = vnet_get_hw_interface (gm->vnet_main,
t->hw_if_index);
tunnel_sw_if_index = hi->sw_if_index;
- tunnel_fib_index = vec_elt (ip4m->fib_index_by_sw_if_index,
- tunnel_sw_if_index);
cached_tunnel_sw_if_index = tunnel_sw_if_index;
- cached_tunnel_fib_index = tunnel_fib_index;
}
else
{
tunnel_sw_if_index = cached_tunnel_sw_if_index;
- tunnel_fib_index = cached_tunnel_fib_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,
+ cpu_index,
+ tunnel_sw_if_index,
+ 1 /* packets */,
+ len /* bytes */);
- u32 len = vlib_buffer_length_in_chain (vm, b1);
- vnet_interface_main_t *im = &gm->vnet_main->interface_main;
- vlib_increment_combined_counter (im->combined_sw_if_counters
- + VNET_INTERFACE_COUNTER_RX,
- cpu_index,
- tunnel_sw_if_index,
- 1 /* packets */,
- len /* bytes */);
+ vnet_buffer(b1)->sw_if_index[VLIB_RX] = tunnel_sw_if_index;
- vnet_buffer(b1)->sw_if_index[VLIB_TX] = tunnel_fib_index;
- }
drop1:
- if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
+ if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
{
- gre_rx_trace_t *tr = vlib_add_trace (vm, node,
+ gre_rx_trace_t *tr = vlib_add_trace (vm, node,
b0, sizeof (*tr));
- tr->tunnel_id = ~0;
+ tr->tunnel_id = tunnel_sw_if_index;
tr->length = ip0->length;
tr->src.as_u32 = ip0->src_address.as_u32;
tr->dst.as_u32 = ip0->dst_address.as_u32;
}
- if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
+ if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED))
{
- gre_rx_trace_t *tr = vlib_add_trace (vm, node,
+ gre_rx_trace_t *tr = vlib_add_trace (vm, node,
b1, sizeof (*tr));
- tr->tunnel_id = ~0;
+ tr->tunnel_id = tunnel_sw_if_index;
tr->length = ip1->length;
tr->src.as_u32 = ip1->src_address.as_u32;
tr->dst.as_u32 = ip1->dst_address.as_u32;
next0 = vec_elt(rt->next_by_protocol, i0);
b0->error =
- node->errors[next0 == SPARSE_VEC_INVALID_INDEX
+ node->errors[i0 == SPARSE_VEC_INVALID_INDEX
? GRE_ERROR_UNKNOWN_PROTOCOL : GRE_ERROR_NONE];
version0 = clib_net_to_host_u16 (h0->flags_and_version);
: b0->error;
next0 = verr0 ? GRE_INPUT_NEXT_DROP : next0;
+
/* For IP payload we need to find source interface
so we can increase counters and help forward node to
pick right FIB */
- if (PREDICT_FALSE(next0 == GRE_INPUT_NEXT_IP4_INPUT
- || next0 == GRE_INPUT_NEXT_IP6_INPUT))
+ /* 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 key = ((u64)(vnet_buffer(b0)->gre.dst) << 32) |
(u64)(vnet_buffer(b0)->gre.src);
gre_tunnel_t * t;
uword * p;
- ip4_main_t * ip4m = &ip4_main;
p = hash_get (gm->tunnel_by_key, key);
if (!p)
{
hi = vnet_get_hw_interface (gm->vnet_main,
t->hw_if_index);
tunnel_sw_if_index = hi->sw_if_index;
- tunnel_fib_index = vec_elt (ip4m->fib_index_by_sw_if_index,
- tunnel_sw_if_index);
cached_tunnel_sw_if_index = tunnel_sw_if_index;
- cached_tunnel_fib_index = tunnel_fib_index;
}
else
{
tunnel_sw_if_index = cached_tunnel_sw_if_index;
- tunnel_fib_index = cached_tunnel_fib_index;
}
-
- u32 len = vlib_buffer_length_in_chain (vm, b0);
- vnet_interface_main_t *im = &gm->vnet_main->interface_main;
- vlib_increment_combined_counter (im->combined_sw_if_counters
- + VNET_INTERFACE_COUNTER_RX,
- cpu_index,
- tunnel_sw_if_index,
- 1 /* packets */,
- len /* bytes */);
-
- vnet_buffer(b0)->sw_if_index[VLIB_TX] = tunnel_fib_index;
}
+ else
+ {
+ next0 = GRE_INPUT_NEXT_DROP;
+ goto drop;
+ }
+ len = vlib_buffer_length_in_chain (vm, b0);
+ vlib_increment_combined_counter (im->combined_sw_if_counters
+ + VNET_INTERFACE_COUNTER_RX,
+ cpu_index,
+ tunnel_sw_if_index,
+ 1 /* packets */,
+ len /* bytes */);
+
+ vnet_buffer(b0)->sw_if_index[VLIB_RX] = tunnel_sw_if_index;
drop:
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 = ~0;
+ tr->tunnel_id = tunnel_sw_if_index;
tr->length = ip0->length;
tr->src.as_u32 = ip0->src_address.as_u32;
tr->dst.as_u32 = ip0->dst_address.as_u32;
.unformat_buffer = unformat_gre_header,
};
+VLIB_NODE_FUNCTION_MULTIARCH (gre_input_node, gre_input)
+
void
gre_register_input_protocol (vlib_main_t * vm,
gre_protocol_t protocol,
gre_protocol_info_t * pi;
gre_input_runtime_t * rt;
u16 * n;
- u32 i;
{
clib_error_t * error = vlib_call_init_function (vm, gre_input_init);
n = sparse_vec_validate (rt->next_by_protocol,
clib_host_to_net_u16 (protocol));
n[0] = pi->next_index;
-
- /* Rebuild next index -> sparse index inverse mapping when sparse vector
- is updated. */
- vec_validate (rt->sparse_index_by_next_index, pi->next_index);
- for (i = 1; i < vec_len (rt->next_by_protocol); i++)
- rt->sparse_index_by_next_index[rt->next_by_protocol[i]] = i;
}
static void
static clib_error_t * gre_input_init (vlib_main_t * vm)
{
gre_input_runtime_t * rt;
- vlib_node_t *ip4_input, *ip6_input, *mpls_unicast_input;
+ vlib_node_t *ethernet_input, *ip4_input, *ip6_input, *mpls_unicast_input;
{
clib_error_t * error;
(/* elt bytes */ sizeof (rt->next_by_protocol[0]),
/* bits in index */ BITS (((gre_header_t *) 0)->protocol));
- vec_validate (rt->sparse_index_by_next_index, GRE_INPUT_NEXT_DROP);
- vec_validate (rt->sparse_index_by_next_index, GRE_INPUT_NEXT_PUNT);
- rt->sparse_index_by_next_index[GRE_INPUT_NEXT_DROP]
- = SPARSE_VEC_INVALID_INDEX;
- rt->sparse_index_by_next_index[GRE_INPUT_NEXT_PUNT]
- = SPARSE_VEC_INVALID_INDEX;
-
/* These could be moved to the supported protocol input node defn's */
+ ethernet_input = vlib_get_node_by_name (vm, (u8 *)"ethernet-input");
+ ASSERT(ethernet_input);
ip4_input = vlib_get_node_by_name (vm, (u8 *)"ip4-input");
ASSERT(ip4_input);
ip6_input = vlib_get_node_by_name (vm, (u8 *)"ip6-input");
ASSERT(ip6_input);
- mpls_unicast_input = vlib_get_node_by_name (vm, (u8 *)"mpls-gre-input");
+ mpls_unicast_input = vlib_get_node_by_name (vm, (u8 *)"mpls-input");
ASSERT(mpls_unicast_input);
+ gre_register_input_protocol (vm, GRE_PROTOCOL_teb,
+ ethernet_input->index);
+
gre_register_input_protocol (vm, GRE_PROTOCOL_ip4,
ip4_input->index);