X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fgre%2Finterface.c;h=f2c679cb9b5cfc0371e6c8353c9d2c47c7b3ed9b;hb=a0455ffdbe9c2765d61d8c8efb7bb73f998ffb5b;hp=f0c289700fa7e1e37d9866bc54947c430aecc82b;hpb=ae0d46ee6f26ec0ce714720102dce37364d0dee7;p=vpp.git diff --git a/src/vnet/gre/interface.c b/src/vnet/gre/interface.c index f0c289700fa..f2c679cb9b5 100644 --- a/src/vnet/gre/interface.c +++ b/src/vnet/gre/interface.c @@ -16,11 +16,9 @@ */ #include -#include #include #include -#include -#include +#include #include #include #include @@ -157,6 +155,45 @@ gre_tunnel_stack (adj_index_t ai) } } +/** + * mgre_tunnel_stack + * + * 'stack' (resolve the recursion for) the tunnel's midchain adjacency + */ +static void +mgre_tunnel_stack (adj_index_t ai) +{ + gre_main_t *gm = &gre_main; + const ip_adjacency_t *adj; + const gre_tunnel_t *gt; + u32 sw_if_index; + + adj = adj_get (ai); + sw_if_index = adj->rewrite_header.sw_if_index; + + if ((vec_len (gm->tunnel_index_by_sw_if_index) <= sw_if_index) || + (~0 == gm->tunnel_index_by_sw_if_index[sw_if_index])) + return; + + gt = pool_elt_at_index (gm->tunnels, + gm->tunnel_index_by_sw_if_index[sw_if_index]); + + if ((vnet_hw_interface_get_flags (vnet_get_main (), gt->hw_if_index) & + VNET_HW_INTERFACE_FLAG_LINK_UP) == 0) + { + adj_midchain_delegate_unstack (ai); + } + else + { + const teib_entry_t *ne; + + ne = teib_entry_find_46 (sw_if_index, adj->ia_nh_proto, + &adj->sub_type.nbr.next_hop); + if (NULL != ne) + teib_entry_adj_stack (ne, ai); + } +} + /** * @brief Call back when restacking all adjacencies on a GRE interface */ @@ -167,6 +204,13 @@ gre_adj_walk_cb (adj_index_t ai, void *ctx) return (ADJ_WALK_RC_CONTINUE); } +static adj_walk_rc_t +mgre_adj_walk_cb (adj_index_t ai, void *ctx) +{ + mgre_tunnel_stack (ai); + + return (ADJ_WALK_RC_CONTINUE); +} static void gre_tunnel_restack (gre_tunnel_t * gt) @@ -178,7 +222,15 @@ gre_tunnel_restack (gre_tunnel_t * gt) */ FOR_EACH_FIB_IP_PROTOCOL (proto) { - adj_nbr_walk (gt->sw_if_index, proto, gre_adj_walk_cb, NULL); + switch (gt->mode) + { + case TUNNEL_MODE_P2P: + adj_nbr_walk (gt->sw_if_index, proto, gre_adj_walk_cb, NULL); + break; + case TUNNEL_MODE_MP: + adj_nbr_walk (gt->sw_if_index, proto, mgre_adj_walk_cb, NULL); + break; + } } } @@ -204,7 +256,7 @@ gre_teib_mk_key (const gre_tunnel_t * t, } /** - * An NHRP entry has been added + * An TEIB entry has been added */ static void gre_teib_entry_added (const teib_entry_t * ne) @@ -530,10 +582,9 @@ vnet_gre_tunnel_add_del (vnet_gre_tunnel_add_del_args_t * a, { u32 outer_fib_index; - if (!a->is_ipv6) - outer_fib_index = ip4_fib_index_from_table_id (a->outer_table_id); - else - outer_fib_index = ip6_fib_index_from_table_id (a->outer_table_id); + outer_fib_index = fib_table_find ((a->is_ipv6 ? + FIB_PROTOCOL_IP6 : + FIB_PROTOCOL_IP4), a->outer_table_id); if (~0 == outer_fib_index) return VNET_API_ERROR_NO_SUCH_FIB; @@ -596,6 +647,7 @@ create_gre_tunnel_command_fn (vlib_main_t * vm, u32 outer_table_id = 0; gre_tunnel_type_t t_type = GRE_TUNNEL_TYPE_L3; tunnel_mode_t t_mode = TUNNEL_MODE_P2P; + tunnel_encap_decap_flags_t flags = TUNNEL_ENCAP_DECAP_FLAG_NONE; u32 session_id = 0; int rv; u8 is_add = 1; @@ -624,6 +676,11 @@ create_gre_tunnel_command_fn (vlib_main_t * vm, t_type = GRE_TUNNEL_TYPE_TEB; else if (unformat (line_input, "erspan %d", &session_id)) t_type = GRE_TUNNEL_TYPE_ERSPAN; + else + if (unformat + (line_input, "flags %U", unformat_tunnel_encap_decap_flags, + &flags)) + ; else { error = clib_error_return (0, "unknown input `%U'", @@ -665,6 +722,7 @@ create_gre_tunnel_command_fn (vlib_main_t * vm, a->session_id = session_id; a->is_ipv6 = !ip46_address_is_ip4 (&src); a->instance = instance; + a->flags = flags; clib_memcpy (&a->src, &src, sizeof (a->src)); clib_memcpy (&a->dst, &dst, sizeof (a->dst)); @@ -738,10 +796,10 @@ show_gre_tunnel_command_fn (vlib_main_t * vm, if (~0 == ti) { /* *INDENT-OFF* */ - pool_foreach (t, gm->tunnels, - ({ + pool_foreach (t, gm->tunnels) + { vlib_cli_output (vm, "%U", format_gre_tunnel, t); - })); + } /* *INDENT-ON* */ } else