X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fmpls%2Fmpls_tunnel.c;h=b03a4a57f689394927f868b5c0bd4bde317a8838;hb=8ae63db02066a2b5ac18a89fd63dc0dd2a811ab3;hp=008b5907019326f7f6b645e87607cd903170164f;hpb=6e366be38ff4f71d4ad5a24929519dc3c874ed36;p=vpp.git diff --git a/src/vnet/mpls/mpls_tunnel.c b/src/vnet/mpls/mpls_tunnel.c index 008b5907019..b03a4a57f68 100644 --- a/src/vnet/mpls/mpls_tunnel.c +++ b/src/vnet/mpls/mpls_tunnel.c @@ -40,6 +40,144 @@ static u32 *mpls_tunnel_db; */ static const char *mpls_tunnel_attribute_names[] = MPLS_TUNNEL_ATTRIBUTES; +/** + * @brief Packet trace structure + */ +typedef struct mpls_tunnel_trace_t_ +{ + /** + * Tunnel-id / index in tunnel vector + */ + u32 tunnel_id; +} mpls_tunnel_trace_t; + +static u8 * +format_mpls_tunnel_tx_trace (u8 * s, + va_list * args) +{ + CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); + CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); + mpls_tunnel_trace_t * t = va_arg (*args, mpls_tunnel_trace_t *); + + s = format (s, "MPLS: tunnel %d", t->tunnel_id); + return s; +} + +typedef enum +{ + MPLS_TUNNEL_ENCAP_NEXT_L2_MIDCHAIN, + MPLS_TUNNEL_ENCAP_N_NEXT, +} mpls_tunnel_encap_next_t; + +/** + * @brief TX function. Only called L2. L3 traffic uses the adj-midchains + */ +VLIB_NODE_FN (mpls_tunnel_tx) (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + u32 *from = vlib_frame_vector_args (frame); + vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b; + u16 nexts[VLIB_FRAME_SIZE], *next; + u32 n_left; + + n_left = frame->n_vectors; + b = bufs; + next = nexts; + + vlib_get_buffers (vm, from, bufs, n_left); + + while (n_left > 2) + { + const mpls_tunnel_t *mt0, *mt1; + u32 sw_if_index0, sw_if_index1; + + sw_if_index0 = vnet_buffer(b[0])->sw_if_index[VLIB_TX]; + sw_if_index1 = vnet_buffer(b[1])->sw_if_index[VLIB_TX]; + + mt0 = pool_elt_at_index(mpls_tunnel_pool, + mpls_tunnel_db[sw_if_index0]); + mt1 = pool_elt_at_index(mpls_tunnel_pool, + mpls_tunnel_db[sw_if_index1]); + + vnet_buffer(b[0])->ip.adj_index[VLIB_TX] = mt0->mt_l2_lb.dpoi_index; + vnet_buffer(b[1])->ip.adj_index[VLIB_TX] = mt1->mt_l2_lb.dpoi_index; + next[0] = mt0->mt_l2_lb.dpoi_next_node; + next[1] = mt1->mt_l2_lb.dpoi_next_node; + + /* since we are coming out of the L2 world, where the vlib_buffer + * union is used for other things, make sure it is clean for + * MPLS from now on. + */ + vnet_buffer(b[0])->mpls.first = 0; + vnet_buffer(b[1])->mpls.first = 0; + + if (PREDICT_FALSE(b[0]->flags & VLIB_BUFFER_IS_TRACED)) + { + mpls_tunnel_trace_t *tr = vlib_add_trace (vm, node, + b[0], sizeof (*tr)); + tr->tunnel_id = mpls_tunnel_db[sw_if_index0]; + } + if (PREDICT_FALSE(b[1]->flags & VLIB_BUFFER_IS_TRACED)) + { + mpls_tunnel_trace_t *tr = vlib_add_trace (vm, node, + b[1], sizeof (*tr)); + tr->tunnel_id = mpls_tunnel_db[sw_if_index1]; + } + + b += 2; + n_left -= 2; + next += 2; + } + while (n_left) + { + const mpls_tunnel_t *mt0; + u32 sw_if_index0; + + sw_if_index0 = vnet_buffer(b[0])->sw_if_index[VLIB_TX]; + mt0 = pool_elt_at_index(mpls_tunnel_pool, + mpls_tunnel_db[sw_if_index0]); + + vnet_buffer(b[0])->ip.adj_index[VLIB_TX] = mt0->mt_l2_lb.dpoi_index; + next[0] = mt0->mt_l2_lb.dpoi_next_node; + + /* since we are coming out of the L2 world, where the vlib_buffer + * union is used for other things, make sure it is clean for + * MPLS from now on. + */ + vnet_buffer(b[0])->mpls.first = 0; + + if (PREDICT_FALSE(b[0]->flags & VLIB_BUFFER_IS_TRACED)) + { + mpls_tunnel_trace_t *tr = vlib_add_trace (vm, node, + b[0], sizeof (*tr)); + tr->tunnel_id = mpls_tunnel_db[sw_if_index0]; + } + + b += 1; + n_left -= 1; + next += 1; + } + + vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors); + + return frame->n_vectors; +} + +VLIB_REGISTER_NODE (mpls_tunnel_tx) = +{ + .name = "mpls-tunnel-tx", + .vector_size = sizeof (u32), + .format_trace = format_mpls_tunnel_tx_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + .n_errors = 0, + .n_next_nodes = 0, + /* MPLS_TUNNEL_ENCAP_N_NEXT, */ + /* .next_nodes = { */ + /* [MPLS_TUNNEL_ENCAP_NEXT_L2_MIDCHAIN] = "mpls-load-balance", */ + /* }, */ +}; + /** * @brief Get a tunnel object from a SW interface index */ @@ -127,10 +265,8 @@ mpls_tunnel_collect_forwarding (fib_node_index_t pl_index, * found a matching extension. stack it to obtain the forwarding * info for this path. */ - ctx->next_hops = fib_path_ext_stack(path_ext, - ctx->fct, - ctx->fct, - ctx->next_hops); + ctx->next_hops = + fib_path_ext_stack (path_ext, DPO_PROTO_MPLS, ctx->fct, ctx->next_hops); return (FIB_PATH_LIST_WALK_CONTINUE); } @@ -317,7 +453,6 @@ mpls_tunnel_restack (mpls_tunnel_t *mt) /* * Stack a load-balance that drops, whilst we have no paths */ - vnet_hw_interface_t * hi; dpo_id_t dpo = DPO_INVALID; mpls_tunnel_mk_lb(mt, @@ -325,8 +460,7 @@ mpls_tunnel_restack (mpls_tunnel_t *mt) FIB_FORW_CHAIN_TYPE_ETHERNET, &dpo); - hi = vnet_get_hw_interface(vnet_get_main(), mt->mt_hw_if_index); - dpo_stack_from_node(hi->tx_node_index, + dpo_stack_from_node(mpls_tunnel_tx.index, &mt->mt_l2_lb, &dpo); dpo_reset(&dpo); @@ -451,106 +585,11 @@ format_mpls_tunnel_device (u8 * s, va_list * args) return (format (s, "MPLS-tunnel: id %d\n", dev_instance)); } -/** - * @brief Packet trace structure - */ -typedef struct mpls_tunnel_trace_t_ -{ - /** - * Tunnel-id / index in tunnel vector - */ - u32 tunnel_id; -} mpls_tunnel_trace_t; - -static u8 * -format_mpls_tunnel_tx_trace (u8 * s, - va_list * args) -{ - CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); - CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); - mpls_tunnel_trace_t * t = va_arg (*args, mpls_tunnel_trace_t *); - - s = format (s, "MPLS: tunnel %d", t->tunnel_id); - return s; -} - -/** - * @brief TX function. Only called L2. L3 traffic uses the adj-midchains - */ -static uword -mpls_tunnel_tx (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) -{ - u32 next_index; - u32 * from, * to_next, n_left_from, n_left_to_next; - vnet_interface_output_runtime_t * rd = (void *) node->runtime_data; - const mpls_tunnel_t *mt; - - mt = pool_elt_at_index(mpls_tunnel_pool, rd->dev_instance); - - /* Vector of buffer / pkt indices we're supposed to process */ - from = vlib_frame_vector_args (frame); - - /* Number of buffers / pkts */ - n_left_from = frame->n_vectors; - - /* Speculatively send the first buffer to the last disposition we used */ - next_index = node->cached_next_index; - - while (n_left_from > 0) - { - /* set up to enqueue to our disposition with index = next_index */ - vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - - /* - * FIXME DUAL LOOP - */ - while (n_left_from > 0 && n_left_to_next > 0) - { - vlib_buffer_t * b0; - u32 bi0; - - bi0 = from[0]; - to_next[0] = bi0; - from += 1; - to_next += 1; - n_left_from -= 1; - n_left_to_next -= 1; - - b0 = vlib_get_buffer(vm, bi0); - - vnet_buffer(b0)->ip.adj_index[VLIB_TX] = mt->mt_l2_lb.dpoi_index; - /* since we are coming out of the L2 world, where the vlib_buffer - * union is used for other things, make sure it is clean for - * MPLS from now on. - */ - vnet_buffer(b0)->mpls.first = 0; - - if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) - { - mpls_tunnel_trace_t *tr = vlib_add_trace (vm, node, - b0, sizeof (*tr)); - tr->tunnel_id = rd->dev_instance; - } - - vlib_validate_buffer_enqueue_x1 (vm, node, next_index, - to_next, n_left_to_next, - bi0, mt->mt_l2_lb.dpoi_next_node); - } - - vlib_put_next_frame (vm, node, next_index, n_left_to_next); - } - - return frame->n_vectors; -} - VNET_DEVICE_CLASS (mpls_tunnel_class) = { .name = "MPLS tunnel device", .format_device_name = format_mpls_tunnel_name, .format_device = format_mpls_tunnel_device, .format_tx_trace = format_mpls_tunnel_tx_trace, - .tx_function = mpls_tunnel_tx, .admin_up_down_function = mpls_tunnel_admin_up_down, }; @@ -576,10 +615,10 @@ mpls_tunnel_walk (mpls_tunnel_walk_cb_t cb, { u32 mti; - pool_foreach_index(mti, mpls_tunnel_pool, - ({ + pool_foreach_index (mti, mpls_tunnel_pool) + { cb(mti, ctx); - })); + } } void @@ -597,6 +636,7 @@ vnet_mpls_tunnel_del (u32 sw_if_index) mt->mt_sibling_index); dpo_reset(&mt->mt_l2_lb); + vnet_reset_interface_l3_output_node (vlib_get_main (), mt->mt_sw_if_index); vnet_delete_hw_interface (vnet_get_main(), mt->mt_hw_if_index); pool_put(mpls_tunnel_pool, mt); @@ -641,6 +681,13 @@ vnet_mpls_tunnel_create (u8 l2_only, mti); hi = vnet_get_hw_interface (vnm, mt->mt_hw_if_index); + if (mt->mt_flags & MPLS_TUNNEL_FLAG_L2) + vnet_set_interface_output_node (vnm, mt->mt_hw_if_index, + mpls_tunnel_tx.index); + else + vnet_set_interface_l3_output_node (vnm->vlib_main, hi->sw_if_index, + (u8 *) "tunnel-output"); + /* Standard default MPLS tunnel MTU. */ vnet_sw_interface_set_mtu (vnm, hi->sw_if_index, 9000); @@ -885,7 +932,12 @@ done: VLIB_CLI_COMMAND (create_mpls_tunnel_command, static) = { .path = "mpls tunnel", .short_help = - "mpls tunnel [multicast] [l2-only] via [next-hop-address] [next-hop-interface] [next-hop-table ] [weight ] [preference ] [udp-encap-id ] [ip4-lookup-in-table ] [ip6-lookup-in-table ] [mpls-lookup-in-table ] [resolve-via-host] [resolve-via-connected] [rx-ip4 ] [out-labels ]", + "mpls tunnel [multicast] [l2-only] via [next-hop-address] " + "[next-hop-interface] [next-hop-table ] [weight ] " + "[preference ] [udp-encap-id ] [ip4-lookup-in-table " + "] [ip6-lookup-in-table ] [mpls-lookup-in-table ] " + "[resolve-via-host] [resolve-via-connected] [rx-ip4|rx-ip6 ] " + "[out-labels ]", .function = vnet_create_mpls_tunnel_command_fn, }; @@ -944,12 +996,12 @@ show_mpls_tunnel_command_fn (vlib_main_t * vm, if (~0 == mti) { - pool_foreach (mt, mpls_tunnel_pool, - ({ + pool_foreach (mt, mpls_tunnel_pool) + { vlib_cli_output (vm, "[@%d] %U", mt - mpls_tunnel_pool, format_mpls_tunnel, mt); - })); + } } else {