-u8 * format_mpls_encap_index (u8 * s, va_list * args)
-{
- mpls_main_t * mm = va_arg (*args, mpls_main_t *);
- u32 entry_index = va_arg (*args, u32);
- mpls_encap_t * e;
- int i;
-
- e = pool_elt_at_index (mm->encaps, entry_index);
-
- for (i = 0; i < vec_len (e->labels); i++)
- s = format
- (s, "%d ", vnet_mpls_uc_get_label(clib_net_to_host_u32
- (e->labels[i].label_exp_s_ttl)));
-
- return s;
-}
-
-u8 * format_mpls_ethernet_tunnel (u8 * s, va_list * args)
-{
- mpls_eth_tunnel_t * t = va_arg (*args, mpls_eth_tunnel_t *);
- mpls_main_t * mm = &mpls_main;
-
- s = format (s, "[%d]: dst %U, adj %U/%d, labels %U\n",
- t - mm->eth_tunnels,
- format_ethernet_address, &t->tunnel_dst,
- format_ip4_address, &t->intfc_address,
- t->mask_width,
- format_mpls_encap_index, mm, t->encap_index);
-
-
- s = format (s, " tx on %U, rx fib index %d",
- format_vnet_sw_if_index_name, mm->vnet_main, t->tx_sw_if_index,
- t->inner_fib_index);
-
- return s;
-}
-
-static clib_error_t *
-show_mpls_tunnel_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- mpls_main_t * mm = &mpls_main;
- mpls_eth_tunnel_t * et;
-
- if (pool_elts (mm->eth_tunnels))
- {
- vlib_cli_output (vm, "MPLS-Ethernet tunnels");
- pool_foreach (et, mm->eth_tunnels,
- ({
- vlib_cli_output (vm, "%U", format_mpls_ethernet_tunnel, et);
- }));
- }
- else
- vlib_cli_output (vm, "No MPLS-Ethernet tunnels");
-
- return 0;
-}
-
-VLIB_CLI_COMMAND (show_mpls_tunnel_command, static) = {
- .path = "show mpls tunnel",
- .short_help = "show mpls tunnel",
- .function = show_mpls_tunnel_command_fn,
-};
-
-
-/* force inclusion from application's main.c */
-clib_error_t *mpls_interface_init (vlib_main_t *vm)
-{
- clib_error_t * error;
-
- if ((error = vlib_call_init_function (vm, mpls_policy_encap_init)))
- return error;
-
- return 0;
-}
-VLIB_INIT_FUNCTION(mpls_interface_init);
-
-
-static u8 * mpls_ethernet_rewrite (mpls_main_t *mm, mpls_eth_tunnel_t * t)
-{
- u8 * rewrite_data = 0;
- mpls_encap_t * e;
- mpls_unicast_header_t *lp0;
- int i;
-
- /* look up the encap label stack using the RX FIB and adjacency address*/
- e = mpls_encap_by_fib_and_dest (mm, t->inner_fib_index,
- t->intfc_address.as_u32);
-
- if (e == 0)
- {
- clib_warning ("no label for inner fib index %d, dst %U",
- t->inner_fib_index, format_ip4_address,
- &t->intfc_address);
- return 0;
- }
-
- vec_validate (rewrite_data,
- sizeof (mpls_unicast_header_t) * vec_len(e->labels) -1);
-
- /* Copy the encap label stack */
- lp0 = (mpls_unicast_header_t *) rewrite_data;
-
- for (i = 0; i < vec_len(e->labels); i++)
- lp0[i] = e->labels[i];
-
- return (rewrite_data);
-}
-
-int vnet_mpls_ethernet_add_del_tunnel (u8 *dst,
- ip4_address_t *intfc,
- u32 mask_width,
- u32 inner_fib_id,
- u32 tx_sw_if_index,
- u32 * tunnel_sw_if_index,
- u8 l2_only,
- u8 is_add)
-{
- ip4_main_t * im = &ip4_main;
- ip_lookup_main_t * lm = &im->lookup_main;
- mpls_main_t * mm = &mpls_main;
- vnet_main_t * vnm = vnet_get_main();
- mpls_eth_tunnel_t *tp;
- u32 inner_fib_index = 0;
- ip_adjacency_t adj;
- u32 adj_index;
- u8 * rewrite_data;
- int found_tunnel = 0;
- mpls_encap_t * e = 0;
- u32 hw_if_index = ~0;
- vnet_hw_interface_t * hi;
- u32 slot;
- u32 dummy;
-
- if (tunnel_sw_if_index == 0)
- tunnel_sw_if_index = &dummy;
-
- *tunnel_sw_if_index = ~0;
-
- if (inner_fib_id != (u32)~0)
- {
- uword * p;
-
- p = hash_get (im->fib_index_by_table_id, inner_fib_id);
- if (! p)
- return VNET_API_ERROR_NO_SUCH_FIB;
- inner_fib_index = p[0];
- }
-
- /* suppress duplicate mpls interface generation. */
- pool_foreach (tp, mm->eth_tunnels,
- ({
- /*
- * If we have a tunnel which matches (src, dst, intfc/mask)
- * AND the expected route is in the FIB, it's a dup
- */
- if (!memcmp (&tp->tunnel_dst, dst, sizeof (*dst))
- && !memcmp (&tp->intfc_address, intfc, sizeof (*intfc))
- && tp->inner_fib_index == inner_fib_index
- && FIB_NODE_INDEX_INVALID != tp->fei)
- {
- found_tunnel = 1;
-
- if (is_add)
- {
- if (l2_only)
- return 1;
- else
- {
- e = mpls_encap_by_fib_and_dest (mm, inner_fib_index,
- intfc->as_u32);
- if (e == 0)
- return VNET_API_ERROR_NO_SUCH_LABEL;
-
- goto reinstall_it;
- }
- }
- else
- {
- /* Delete */
- goto add_del_route;
- }
-
- }
- }));
-
- /* Delete, and we can't find the tunnel */
- if (is_add == 0 && found_tunnel == 0)
- return VNET_API_ERROR_NO_SUCH_ENTRY;
-
- e = mpls_encap_by_fib_and_dest (mm, inner_fib_index, intfc->as_u32);
- if (e == 0)
- return VNET_API_ERROR_NO_SUCH_LABEL;
-
- pool_get(mm->eth_tunnels, tp);
- memset (tp, 0, sizeof (*tp));
-
- if (vec_len (mm->free_eth_sw_if_indices) > 0)
- {
- hw_if_index =
- mm->free_eth_sw_if_indices[vec_len(mm->free_eth_sw_if_indices)-1];
- _vec_len (mm->free_eth_sw_if_indices) -= 1;
- hi = vnet_get_hw_interface (vnm, hw_if_index);
- hi->dev_instance = tp - mm->eth_tunnels;
- hi->hw_instance = tp - mm->eth_tunnels;
- }
- else
- {
- hw_if_index = vnet_register_interface
- (vnm, mpls_eth_device_class.index, tp - mm->eth_tunnels,
- mpls_eth_hw_interface_class.index,
- tp - mm->eth_tunnels);
- hi = vnet_get_hw_interface (vnm, hw_if_index);
-
- /* ... to make the IP and L2 x-connect cases identical */
- slot = vlib_node_add_named_next_with_slot
- (vnm->vlib_main, hi->tx_node_index,
- "interface-output", MPLS_ETH_OUTPUT_NEXT_OUTPUT);
-
- ASSERT (slot == MPLS_ETH_OUTPUT_NEXT_OUTPUT);
- }
-
- *tunnel_sw_if_index = hi->sw_if_index;
- vnet_sw_interface_set_flags (vnm, hi->sw_if_index,
- VNET_SW_INTERFACE_FLAG_ADMIN_UP);
-
- tp->hw_if_index = hw_if_index;
-
- reinstall_it:
- clib_memcpy(tp->tunnel_dst, dst, sizeof (tp->tunnel_dst));
- tp->intfc_address.as_u32 = intfc->as_u32;
- tp->mask_width = mask_width;
- tp->inner_fib_index = inner_fib_index;
- tp->encap_index = e - mm->encaps;
- tp->tx_sw_if_index = tx_sw_if_index;
- tp->l2_only = l2_only;
-
- /* Create the adjacency and add to v4 fib */
- memset(&adj, 0, sizeof (adj));
- adj.lookup_next_index = IP_LOOKUP_NEXT_REWRITE;
-
- rewrite_data = mpls_ethernet_rewrite (mm, tp);
- if (rewrite_data == 0)
- {
- if (*tunnel_sw_if_index != ~0)
- {
- hi = vnet_get_hw_interface (vnm, tp->hw_if_index);
- vnet_sw_interface_set_flags (vnm, hi->sw_if_index,
- 0 /* admin down */);
- vec_add1 (mm->free_eth_sw_if_indices, tp->hw_if_index);
- }
-
- pool_put (mm->eth_tunnels, tp);
- return VNET_API_ERROR_NO_SUCH_LABEL;
- }
-
- vnet_rewrite_for_sw_interface
- (vnm,
- VNET_LINK_MPLS,
- tx_sw_if_index,
- ip4_rewrite_node.index,
- tp->tunnel_dst,
- &adj.rewrite_header,
- sizeof (adj.rewrite_data));
-
- /*
- * Prepend the (0,1,2) VLAN tag ethernet header
- * we just built to the mpls header stack
- */
- vec_insert (rewrite_data, adj.rewrite_header.data_bytes, 0);
- clib_memcpy(rewrite_data,
- vnet_rewrite_get_data_internal(&adj.rewrite_header,
- sizeof (adj.rewrite_data)),
- adj.rewrite_header.data_bytes);
-
- vnet_rewrite_set_data_internal (&adj.rewrite_header,
- sizeof(adj.rewrite_data),
- rewrite_data,
- vec_len(rewrite_data));
-
- vec_free (tp->rewrite_data);
-
- tp->rewrite_data = rewrite_data;
-
- if (!l2_only)
- ip_add_adjacency (lm, &adj, 1 /* one adj */,
- &adj_index);
-
- add_del_route:
-
- if (!l2_only)
- {
- const fib_prefix_t pfx = {
- .fp_addr = {
- .ip4 = tp->intfc_address,
- },
- .fp_len = tp->mask_width,
- .fp_proto = FIB_PROTOCOL_IP4,
- };
- if (is_add)
- tp->fei = fib_table_entry_special_add(tp->inner_fib_index,
- &pfx,
- FIB_SOURCE_API,
- FIB_ENTRY_FLAG_NONE,
- adj_index);
- else
- {
- fib_table_entry_delete(tp->inner_fib_index, &pfx, FIB_SOURCE_API);
- tp->fei = FIB_NODE_INDEX_INVALID;
- }
- }
- if (is_add == 0 && found_tunnel)
- {
- hi = vnet_get_hw_interface (vnm, tp->hw_if_index);
- vnet_sw_interface_set_flags (vnm, hi->sw_if_index,
- 0 /* admin down */);
- vec_add1 (mm->free_eth_sw_if_indices, tp->hw_if_index);
- vec_free (tp->rewrite_data);
- pool_put (mm->eth_tunnels, tp);
- }
-
- return 0;
-}
-
-static clib_error_t *
-create_mpls_ethernet_tunnel_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- unformat_input_t _line_input, * line_input = &_line_input;
- vnet_main_t * vnm = vnet_get_main();
- ip4_address_t intfc;
- int adj_set = 0;
- u8 dst[6];
- int dst_set = 0, intfc_set = 0;
- u32 mask_width;
- u32 inner_fib_id = (u32)~0;
- int rv;
- u8 is_del = 0;
- u8 l2_only = 0;
- u32 tx_sw_if_index;
- u32 sw_if_index = ~0;
-
- /* Get a line of input. */
- if (! unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (line_input, "dst %U",
- unformat_ethernet_address, &dst))
- dst_set = 1;
- else if (unformat (line_input, "adj %U/%d",
- unformat_ip4_address, &intfc, &mask_width))
- adj_set = 1;
- else if (unformat (line_input, "tx-intfc %U",
- unformat_vnet_sw_interface, vnm, &tx_sw_if_index))
- intfc_set = 1;
- else if (unformat (line_input, "fib-id %d", &inner_fib_id))
- ;
- else if (unformat (line_input, "l2-only"))
- l2_only = 1;
- else if (unformat (line_input, "del"))
- is_del = 1;
- else
- return clib_error_return (0, "unknown input '%U'",
- format_unformat_error, line_input);
- }
-
- if (!intfc_set)
- return clib_error_return (0, "missing tx-intfc");
-
- if (!dst_set)
- return clib_error_return (0, "missing: dst <ethernet-address>");
-
- if (!adj_set)
- return clib_error_return (0, "missing: intfc <ip-address>/<mask-width>");
-
-
- rv = vnet_mpls_ethernet_add_del_tunnel (dst, &intfc, mask_width,
- inner_fib_id, tx_sw_if_index,
- &sw_if_index,
- l2_only, !is_del);
-
- switch (rv)
- {
- case 0:
- if (!is_del)
- vlib_cli_output(vm, "%U\n", format_vnet_sw_if_index_name, vnet_get_main(), sw_if_index);
- break;
- case VNET_API_ERROR_NO_SUCH_FIB:
- return clib_error_return (0, "rx fib ID %d doesn't exist\n",
- inner_fib_id);
-
- case VNET_API_ERROR_NO_SUCH_ENTRY:
- return clib_error_return (0, "tunnel not found\n");
-
- case VNET_API_ERROR_NO_SUCH_LABEL:
- /*
- * This happens when there's no MPLS label for the dst address
- * no need for two error messages.
- */
- return clib_error_return (0, "no label for %U in fib %d",
- format_ip4_address, &intfc, inner_fib_id);
- break;
-
- default:
- return clib_error_return (0, "vnet_mpls_ethernet_add_del_tunnel returned %d", rv);
- break;
- }
- return 0;
-}
-
-
-VLIB_CLI_COMMAND (create_mpls_ethernet_tunnel_command, static) = {
- .path = "create mpls ethernet tunnel",
- .short_help =
- "create mpls ethernet tunnel [del] dst <mac-addr> intfc <addr>/<mw>",
- .function = create_mpls_ethernet_tunnel_command_fn,
-};
-
-
-int vnet_mpls_policy_tunnel_add_rewrite (mpls_main_t * mm,
- mpls_encap_t * e,
- u32 policy_tunnel_index)
-{
- mpls_eth_tunnel_t * t;
- ip_adjacency_t adj;
- u8 * rewrite_data = 0;
- u8 * label_start;
- mpls_unicast_header_t *lp;
- int i;
-
- if (pool_is_free_index (mm->eth_tunnels, policy_tunnel_index))
- return VNET_API_ERROR_NO_SUCH_ENTRY;
-
- t = pool_elt_at_index (mm->eth_tunnels, policy_tunnel_index);
-
- memset (&adj, 0, sizeof (adj));
-
- /* Build L2 encap */
- vnet_rewrite_for_sw_interface
- (mm->vnet_main,
- VNET_LINK_MPLS,
- t->tx_sw_if_index,
- mpls_policy_encap_node.index,
- t->tunnel_dst,
- &adj.rewrite_header,
- sizeof (adj.rewrite_data));
-
- vec_validate (rewrite_data, adj.rewrite_header.data_bytes -1);
-
- clib_memcpy(rewrite_data,
- vnet_rewrite_get_data_internal(&adj.rewrite_header,
- sizeof (adj.rewrite_data)),
- adj.rewrite_header.data_bytes);
-
- /* Append the label stack */
-
- vec_add2 (rewrite_data, label_start, vec_len(e->labels) * sizeof (u32));
-
- lp = (mpls_unicast_header_t *) label_start;
-
- for (i = 0; i < vec_len(e->labels); i++)
- lp[i] = e->labels[i];
-
- /* Remember the rewrite data */
- e->rewrite = rewrite_data;
- e->output_next_index = adj.rewrite_header.next_index;
-
- return 0;
-}
-
-int vnet_mpls_ethernet_add_del_policy_tunnel (u8 *dst,
- ip4_address_t *intfc,
- u32 mask_width,
- u32 inner_fib_id,
- u32 tx_sw_if_index,
- u32 * tunnel_sw_if_index,
- u32 classify_table_index,
- u32 * new_tunnel_index,
- u8 l2_only,
- u8 is_add)
-{
- ip4_main_t * im = &ip4_main;
- mpls_main_t * mm = &mpls_main;
- vnet_main_t * vnm = vnet_get_main();
- mpls_eth_tunnel_t *tp;
- u32 inner_fib_index = 0;
- int found_tunnel = 0;
- mpls_encap_t * e = 0;
- u32 hw_if_index = ~0;
- vnet_hw_interface_t * hi;
- u32 slot;
- u32 dummy;
-
- if (tunnel_sw_if_index == 0)
- tunnel_sw_if_index = &dummy;
-
- *tunnel_sw_if_index = ~0;
-
- if (inner_fib_id != (u32)~0)
- {
- uword * p;
-
- p = hash_get (im->fib_index_by_table_id, inner_fib_id);
- if (! p)
- return VNET_API_ERROR_NO_SUCH_FIB;
- inner_fib_index = p[0];
- }
-
- /* suppress duplicate mpls interface generation. */
- pool_foreach (tp, mm->eth_tunnels,
- ({
- /*
- * If we have a tunnel which matches (src, dst, intfc/mask)
- * AND the expected route is in the FIB, it's a dup
- */
- if (!memcmp (&tp->tunnel_dst, dst, sizeof (*dst))
- && !memcmp (&tp->intfc_address, intfc, sizeof (*intfc))
- && tp->inner_fib_index == inner_fib_index
- && FIB_NODE_INDEX_INVALID != tp->fei)
- {
- found_tunnel = 1;
-
- if (is_add)
- {
- if (l2_only)
- return 1;
- else
- {
- goto reinstall_it;
- }
- }
- else
- {
- /* Delete */
- goto add_del_route;
- }
-
- }
- }));
-
- /* Delete, and we can't find the tunnel */
- if (is_add == 0 && found_tunnel == 0)
- return VNET_API_ERROR_NO_SUCH_ENTRY;
-
- pool_get(mm->eth_tunnels, tp);
- memset (tp, 0, sizeof (*tp));
-
- if (vec_len (mm->free_eth_sw_if_indices) > 0)
- {
- hw_if_index =
- mm->free_eth_sw_if_indices[vec_len(mm->free_eth_sw_if_indices)-1];
- _vec_len (mm->free_eth_sw_if_indices) -= 1;
- hi = vnet_get_hw_interface (vnm, hw_if_index);
- hi->dev_instance = tp - mm->eth_tunnels;
- hi->hw_instance = tp - mm->eth_tunnels;
- }
- else
- {
- hw_if_index = vnet_register_interface
- (vnm, mpls_eth_device_class.index, tp - mm->eth_tunnels,
- mpls_eth_hw_interface_class.index,
- tp - mm->eth_tunnels);
- hi = vnet_get_hw_interface (vnm, hw_if_index);
-
- /* ... to make the IP and L2 x-connect cases identical */
- slot = vlib_node_add_named_next_with_slot
- (vnm->vlib_main, hi->tx_node_index,
- "interface-output", MPLS_ETH_OUTPUT_NEXT_OUTPUT);
-
- ASSERT (slot == MPLS_ETH_OUTPUT_NEXT_OUTPUT);
- }
-
- *tunnel_sw_if_index = hi->sw_if_index;
- vnet_sw_interface_set_flags (vnm, hi->sw_if_index,
- VNET_SW_INTERFACE_FLAG_ADMIN_UP);
-
- tp->hw_if_index = hw_if_index;
-
- reinstall_it:
- clib_memcpy(tp->tunnel_dst, dst, sizeof (tp->tunnel_dst));
- tp->intfc_address.as_u32 = intfc->as_u32;
- tp->mask_width = mask_width;
- tp->inner_fib_index = inner_fib_index;
- tp->encap_index = e - mm->encaps;
- tp->tx_sw_if_index = tx_sw_if_index;
- tp->l2_only = l2_only;
- tp->fei = FIB_NODE_INDEX_INVALID;
-
- if (new_tunnel_index)
- *new_tunnel_index = tp - mm->eth_tunnels;
-
- add_del_route:
-
- if (!l2_only)
- {
- const fib_prefix_t pfx = {
- .fp_addr = {
- .ip4 = tp->intfc_address,
- },
- .fp_len = tp->mask_width,
- .fp_proto = FIB_PROTOCOL_IP4,
- };
- dpo_id_t dpo = DPO_INVALID;
-
- if (is_add)
- {
- dpo_set(&dpo,
- DPO_CLASSIFY,
- DPO_PROTO_IP4,
- classify_dpo_create(DPO_PROTO_IP4,
- classify_table_index));
-
- tp->fei = fib_table_entry_special_dpo_add(tp->inner_fib_index,
- &pfx,
- FIB_SOURCE_API,
- FIB_ENTRY_FLAG_EXCLUSIVE,
- &dpo);
- dpo_reset(&dpo);
- }
- else
- {
- fib_table_entry_delete(tp->inner_fib_index, &pfx, FIB_SOURCE_API);
- tp->fei = FIB_NODE_INDEX_INVALID;
- }
- }
- if (is_add == 0 && found_tunnel)
- {
- hi = vnet_get_hw_interface (vnm, tp->hw_if_index);
- vnet_sw_interface_set_flags (vnm, hi->sw_if_index,
- 0 /* admin down */);
- vec_add1 (mm->free_eth_sw_if_indices, tp->hw_if_index);
- pool_put (mm->eth_tunnels, tp);
- }
-
- return 0;
-}
-
-static clib_error_t *
-create_mpls_ethernet_policy_tunnel_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- unformat_input_t _line_input, * line_input = &_line_input;
- vnet_main_t * vnm = vnet_get_main();
- ip4_address_t intfc;
- int adj_set = 0;
- u8 dst[6];
- int dst_set = 0, intfc_set = 0;
- u32 mask_width;
- u32 inner_fib_id = (u32)~0;
- u32 classify_table_index = (u32)~0;
- u32 new_tunnel_index;
- int rv;
- u8 is_del = 0;
- u8 l2_only = 0;
- u32 tx_sw_if_index;
-
- /* Get a line of input. */
- if (! unformat_user (input, unformat_line_input, line_input))
- return 0;
-
- while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (line_input, "dst %U",
- unformat_ethernet_address, &dst))
- dst_set = 1;
- else if (unformat (line_input, "adj %U/%d",
- unformat_ip4_address, &intfc, &mask_width))
- adj_set = 1;
- else if (unformat (line_input, "tx-intfc %U",
- unformat_vnet_sw_interface, vnm, &tx_sw_if_index))
- intfc_set = 1;
- else if (unformat (line_input, "classify-table-index %d",
- &classify_table_index))
- ;
- else if (unformat (line_input, "fib-id %d", &inner_fib_id))
- ;
- else if (unformat (line_input, "l2-only"))
- l2_only = 1;
- else if (unformat (line_input, "del"))
- is_del = 1;
- else
- return clib_error_return (0, "unknown input '%U'",
- format_unformat_error, line_input);
- }
-
- if (classify_table_index == ~0)
- return clib_error_return (0, "missing classify_table_index");
-
- if (!intfc_set)
- return clib_error_return (0, "missing tx-intfc");
-
- if (!dst_set)
- return clib_error_return (0, "missing: dst <ethernet-address>");
-
- if (!adj_set)
- return clib_error_return (0, "missing: intfc <ip-address>/<mask-width>");
-
-
- rv = vnet_mpls_ethernet_add_del_policy_tunnel (dst, &intfc, mask_width,
- inner_fib_id, tx_sw_if_index,
- 0 /* tunnel sw_if_index */,
- classify_table_index,
- &new_tunnel_index,
- l2_only, !is_del);
- switch (rv)
- {
- case 0:
- if (!is_del)
- vlib_cli_output(vm, "%U\n", format_vnet_sw_if_index_name, vnet_get_main(), new_tunnel_index);
- break;
- case VNET_API_ERROR_NO_SUCH_FIB:
- return clib_error_return (0, "rx fib ID %d doesn't exist\n",
- inner_fib_id);
-
- case VNET_API_ERROR_NO_SUCH_ENTRY:
- return clib_error_return (0, "tunnel not found\n");
-
- case VNET_API_ERROR_NO_SUCH_LABEL:
- /*
- * This happens when there's no MPLS label for the dst address
- * no need for two error messages.
- */
- return clib_error_return (0, "no label for %U in fib %d",
- format_ip4_address, &intfc, inner_fib_id);
- break;
-
- default:
- return clib_error_return (0, "vnet_mpls_ethernet_add_del_policy_tunnel returned %d", rv);
- break;
- }
-
- return 0;
-}
-
-VLIB_CLI_COMMAND (create_mpls_ethernet_policy_tunnel_command, static) = {
- .path = "create mpls ethernet policy tunnel",
- .short_help =
- "create mpls ethernet policy tunnel [del] dst <mac-addr> intfc <addr>/<mw>\n"
- " classify-table-index <nn>",
- .function = create_mpls_ethernet_policy_tunnel_command_fn,
-};
-