From aeb06f4bb55afb8cc181d4c81808652c20d040d4 Mon Sep 17 00:00:00 2001 From: John Lo Date: Sat, 15 Oct 2016 17:45:35 -0400 Subject: [PATCH] Support MPLSoGRE with the new FIB 2.0 Note that the new way to provision MPLSoGRE is using the "normal" GRE tunnel such as in the following example: create gre tunnel src 10.0.3.1 dst 10.0.3.3 set in state gre0 up set int ip addr gre0 10.0.4.1/30 set int mpls gre0 enable ip route table 4 6.0.0.0/24 via 10.0.4.2 gre0 out-label 30 mpls local-label add 30 eos ip4-lookup-in-table 4 The previous CLIs/APIs used to configure MPLSoGRE tunnel such as "create mpls gre tunnel...", "mpls encap|decap add label .." and "show mpls tunnel", etc. can not be used. They will be deprecated in a later update to the VPP code base. Change-Id: I244916841924dc2b87d2143691cd8476716c06b1 Signed-off-by: John Lo --- vnet/vnet/gre/node.c | 125 +++++-------------------------------------- vnet/vnet/mpls/mpls.c | 38 +++++++++---- vnet/vnet/mpls/mpls_output.c | 14 +++-- 3 files changed, 50 insertions(+), 127 deletions(-) diff --git a/vnet/vnet/gre/node.c b/vnet/vnet/gre/node.c index b55f5511916..556f1a81837 100644 --- a/vnet/vnet/gre/node.c +++ b/vnet/vnet/gre/node.c @@ -68,7 +68,6 @@ gre_input (vlib_main_t * vm, vlib_frame_t * from_frame) { gre_main_t * gm = &gre_main; - mpls_main_t * mm = &mpls_main; ip4_main_t * ip4m = &ip4_main; gre_input_runtime_t * rt = (void *) node->runtime_data; __attribute__((unused)) u32 n_left_from, next_index, * from, * to_next; @@ -169,9 +168,10 @@ gre_input (vlib_main_t * vm, /* RPF check for ip4/ip6 input */ - if (PREDICT_FALSE(next0 == GRE_INPUT_NEXT_IP4_INPUT - || next0 == GRE_INPUT_NEXT_IP6_INPUT - || next0 == GRE_INPUT_NEXT_ETHERNET_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); @@ -205,40 +205,6 @@ gre_input (vlib_main_t * vm, tunnel_fib_index = cached_tunnel_fib_index; } } - else if (PREDICT_TRUE(next0 == GRE_INPUT_NEXT_MPLS_INPUT)) - { - u64 key = ((u64)(vnet_buffer(b0)->gre.dst) << 32) | - (u64)(vnet_buffer(b0)->gre.src); - - if (cached_tunnel_key != key) - { - vnet_hw_interface_t * hi; - mpls_gre_tunnel_t * t; - uword * p; - - p = hash_get (gm->tunnel_by_key, key); - if (!p) - { - next0 = GRE_INPUT_NEXT_DROP; - b0->error = node->errors[GRE_ERROR_NO_SUCH_TUNNEL]; - goto drop0; - } - t = pool_elt_at_index (mm->gre_tunnels, p[0]); - 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 { next0 = GRE_INPUT_NEXT_DROP; @@ -256,9 +222,10 @@ gre_input (vlib_main_t * vm, 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 - || next1 == GRE_INPUT_NEXT_ETHERNET_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); @@ -292,41 +259,6 @@ drop0: tunnel_fib_index = cached_tunnel_fib_index; } } - else if (PREDICT_TRUE(next1 == GRE_INPUT_NEXT_MPLS_INPUT)) - { - u64 key = ((u64)(vnet_buffer(b1)->gre.dst) << 32) | - (u64)(vnet_buffer(b1)->gre.src); - - if (cached_tunnel_key != key) - { - vnet_hw_interface_t * hi; - mpls_gre_tunnel_t * t; - uword * p; - - ip4_main_t * ip4m = &ip4_main; - p = hash_get (gm->tunnel_by_key, key); - if (!p) - { - next1 = GRE_INPUT_NEXT_DROP; - b1->error = node->errors[GRE_ERROR_NO_SUCH_TUNNEL]; - goto drop1; - } - t = pool_elt_at_index (mm->gre_tunnels, p[0]); - 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; @@ -417,9 +349,10 @@ drop1: so we can increase counters and help forward node to pick right FIB */ /* RPF check for ip4/ip6 input */ - if (PREDICT_FALSE(next0 == GRE_INPUT_NEXT_IP4_INPUT - || next0 == GRE_INPUT_NEXT_IP6_INPUT - || next0 == GRE_INPUT_NEXT_ETHERNET_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); @@ -453,40 +386,6 @@ drop1: tunnel_fib_index = cached_tunnel_fib_index; } } - else if (PREDICT_TRUE(next0 == GRE_INPUT_NEXT_MPLS_INPUT)) - { - u64 key = ((u64)(vnet_buffer(b0)->gre.dst) << 32) | - (u64)(vnet_buffer(b0)->gre.src); - - if (cached_tunnel_key != key) - { - vnet_hw_interface_t * hi; - mpls_gre_tunnel_t * t; - uword * p; - - p = hash_get (gm->tunnel_by_key, key); - if (!p) - { - next0 = GRE_INPUT_NEXT_DROP; - b0->error = node->errors[GRE_ERROR_NO_SUCH_TUNNEL]; - goto drop; - } - t = pool_elt_at_index (mm->gre_tunnels, p[0]); - 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 { next0 = GRE_INPUT_NEXT_DROP; diff --git a/vnet/vnet/mpls/mpls.c b/vnet/vnet/mpls/mpls.c index de57da880f2..b28736ba5a7 100644 --- a/vnet/vnet/mpls/mpls.c +++ b/vnet/vnet/mpls/mpls.c @@ -746,6 +746,7 @@ vnet_mpls_local_label (vlib_main_t * vm, eos = MPLS_EOS; is_del = 0; local_label = MPLS_LABEL_INVALID; + memset(&pfx, 0, sizeof(pfx)); /* Get a line of input. */ if (! unformat_user (input, unformat_line_input, line_input)) @@ -754,7 +755,6 @@ vnet_mpls_local_label (vlib_main_t * vm, while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) { memset(&rpath, 0, sizeof(rpath)); - memset(&pfx, 0, sizeof(pfx)); if (unformat (line_input, "table %d", &table_id)) ; @@ -763,9 +763,9 @@ vnet_mpls_local_label (vlib_main_t * vm, else if (unformat (line_input, "add")) is_del = 0; else if (unformat (line_input, "eos")) - eos = MPLS_EOS; + pfx.fp_eos = MPLS_EOS; else if (unformat (line_input, "non-eos")) - eos = MPLS_NON_EOS; + pfx.fp_eos = MPLS_NON_EOS; else if (unformat (line_input, "%U/%d", unformat_ip4_address, &pfx.fp_addr.ip4, @@ -791,6 +791,7 @@ vnet_mpls_local_label (vlib_main_t * vm, rpath.frp_label = MPLS_LABEL_INVALID; rpath.frp_proto = FIB_PROTOCOL_IP4; rpath.frp_sw_if_index = FIB_NODE_INDEX_INVALID; + pfx.fp_payload_proto = FIB_PROTOCOL_IP4; vec_add1(rpaths, rpath); } else if (unformat (line_input, @@ -801,14 +802,16 @@ vnet_mpls_local_label (vlib_main_t * vm, rpath.frp_proto = FIB_PROTOCOL_IP6; rpath.frp_sw_if_index = FIB_NODE_INDEX_INVALID; vec_add1(rpaths, rpath); + pfx.fp_payload_proto = FIB_PROTOCOL_IP6; } else if (unformat (line_input, "mpls-lookup-in-table %d", &rpath.frp_fib_index)) { rpath.frp_label = MPLS_LABEL_INVALID; - rpath.frp_proto = FIB_PROTOCOL_IP4; + rpath.frp_proto = FIB_PROTOCOL_MPLS; rpath.frp_sw_if_index = FIB_NODE_INDEX_INVALID; + pfx.fp_payload_proto = FIB_PROTOCOL_MPLS; vec_add1(rpaths, rpath); } else @@ -851,11 +854,26 @@ vnet_mpls_local_label (vlib_main_t * vm, else { fib_node_index_t lfe, fib_index; - fib_prefix_t prefix = { - .fp_proto = FIB_PROTOCOL_MPLS, - .fp_label = local_label, - .fp_eos = eos, - }; + u32 fi; + + pfx.fp_proto = FIB_PROTOCOL_MPLS; + pfx.fp_len = 21; + pfx.fp_label = local_label; + + /* + * the CLI parsing stored table Ids, swap to FIB indicies + */ + fi = fib_table_id_find_fib_index(pfx.fp_payload_proto, + rpaths[0].frp_fib_index); + + if (~0 == fi) + { + error = clib_error_return(0 , "%U Via table %d does not exist", + format_fib_protocol, pfx.fp_payload_proto, + rpaths[0].frp_fib_index); + goto done; + } + rpaths[0].frp_fib_index = fi; fib_index = mpls_fib_index_from_table_id(table_id); @@ -867,7 +885,7 @@ vnet_mpls_local_label (vlib_main_t * vm, } lfe = fib_table_entry_path_add2(fib_index, - &prefix, + &pfx, FIB_SOURCE_CLI, FIB_ENTRY_FLAG_NONE, rpaths); diff --git a/vnet/vnet/mpls/mpls_output.c b/vnet/vnet/mpls/mpls_output.c index 299e1dd242a..1d5d18224e3 100644 --- a/vnet/vnet/mpls/mpls_output.c +++ b/vnet/vnet/mpls/mpls_output.c @@ -52,7 +52,8 @@ format_mpls_output_trace (u8 * s, va_list * args) static inline uword mpls_output_inline (vlib_main_t * vm, vlib_node_runtime_t * node, - vlib_frame_t * from_frame) + vlib_frame_t * from_frame, + int is_midchain) { u32 n_left_from, next_index, * from, * to_next, cpu_index; vlib_node_runtime_t * error_node; @@ -121,6 +122,11 @@ mpls_output_inline (vlib_main_t * vm, vnet_buffer (p0)->sw_if_index[VLIB_TX] = adj0[0].rewrite_header.sw_if_index; next0 = adj0[0].rewrite_header.next_index; + + if (is_midchain) + { + adj0->sub_type.midchain.fixup_func(vm, adj0, p0); + } } else { @@ -165,7 +171,7 @@ mpls_output (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame) { - return (mpls_output_inline(vm, node, from_frame)); + return (mpls_output_inline(vm, node, from_frame, /* is_midchain */ 0)); } VLIB_REGISTER_NODE (mpls_output_node) = { @@ -193,11 +199,11 @@ mpls_midchain (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame) { - return (mpls_output_inline(vm, node, from_frame)); + return (mpls_output_inline(vm, node, from_frame, /* is_midchain */ 1)); } VLIB_REGISTER_NODE (mpls_midchain_node) = { - .function = mpls_output, + .function = mpls_midchain, .name = "mpls-midchain", .vector_size = sizeof (u32), -- 2.16.6