-int vnet_mpls_add_del_decap (u32 rx_fib_id,
- u32 tx_fib_id,
- u32 label_host_byte_order,
- int s_bit, int next_index, int is_add)
-{
- mpls_main_t * mm = &mpls_main;
- ip4_main_t * im = &ip4_main;
- mpls_decap_t * d;
- u32 rx_fib_index, tx_fib_index_or_output_swif_index;
- uword *p;
- u64 key;
-
- p = hash_get (im->fib_index_by_table_id, rx_fib_id);
- if (! p)
- return VNET_API_ERROR_NO_SUCH_FIB;
-
- rx_fib_index = p[0];
-
- /* L3 decap => transform fib ID to fib index */
- if (next_index == MPLS_LOOKUP_NEXT_IP4_INPUT)
- {
- p = hash_get (im->fib_index_by_table_id, tx_fib_id);
- if (! p)
- return VNET_API_ERROR_NO_SUCH_INNER_FIB;
-
- tx_fib_index_or_output_swif_index = p[0];
- }
- else
- {
- /* L2 decap, tx_fib_id is actually the output sw_if_index */
- tx_fib_index_or_output_swif_index = tx_fib_id;
- }
-
- key = ((u64) rx_fib_index<<32) | ((u64) label_host_byte_order<<12)
- | ((u64) s_bit<<8);
-
- p = hash_get (mm->mpls_decap_by_rx_fib_and_label, key);
-
- /* If deleting, or replacing an old entry */
- if (is_add == 0 || p)
- {
- if (is_add == 0 && p == 0)
- return VNET_API_ERROR_NO_SUCH_LABEL;
-
- d = pool_elt_at_index (mm->decaps, p[0]);
- hash_unset (mm->mpls_decap_by_rx_fib_and_label, key);
- pool_put (mm->decaps, d);
- /* Deleting, we're done... */
- if (is_add == 0)
- return 0;
- }
-
- /* add decap entry... */
- pool_get (mm->decaps, d);
- memset (d, 0, sizeof (*d));
- d->tx_fib_index = tx_fib_index_or_output_swif_index;
- d->next_index = next_index;
-
- hash_set (mm->mpls_decap_by_rx_fib_and_label, key, d - mm->decaps);
-
- return 0;
-}
-
-uword
-unformat_mpls_gre_input_next (unformat_input_t * input, va_list * args)
-{
- u32 * result = va_arg (*args, u32 *);
- int rv = 0;
-
- if (unformat (input, "lookup"))
- {
- *result = MPLS_LOOKUP_NEXT_IP4_INPUT;
- rv = 1;
- }
- else if (unformat (input, "output"))
- {
- *result = MPLS_LOOKUP_NEXT_L2_OUTPUT;
- rv = 1;
- }
- return rv;
-}
-
-static clib_error_t *
-mpls_add_decap_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- vnet_main_t * vnm = vnet_get_main();
- u32 rx_fib_id = 0;
- u32 tx_fib_or_sw_if_index;
- u32 label;
- int s_bit = 1;
- u32 next_index = 1; /* ip4_lookup, see node.c */
- int tx_fib_id_set = 0;
- int label_set = 0;
- int rv;
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "fib %d", &tx_fib_or_sw_if_index))
- tx_fib_id_set = 1;
- else if (unformat (input, "sw_if_index %d", &tx_fib_or_sw_if_index))
- tx_fib_id_set = 1;
- else if (unformat (input, "%U", unformat_vnet_sw_interface, vnm,
- &tx_fib_or_sw_if_index))
- tx_fib_id_set = 1;
- else if (unformat (input, "rx-fib %d", &rx_fib_id))
- ;
- else if (unformat (input, "label %d", &label))
- label_set = 1;
- else if (unformat (input, "s-bit-clear"))
- s_bit = 0;
- else if (unformat (input, "next %U", unformat_mpls_gre_input_next,
- &next_index))
- ;
- else
- break;
- }
-
- if (tx_fib_id_set == 0)
- return clib_error_return (0, "lookup FIB ID not set");
- if (label_set == 0)
- return clib_error_return (0, "missing label");
-
- rv = vnet_mpls_add_del_decap (rx_fib_id, tx_fib_or_sw_if_index,
- label, s_bit, next_index, 1 /* is_add */);
- switch (rv)
- {
- case 0:
- break;
-
- case VNET_API_ERROR_NO_SUCH_FIB:
- return clib_error_return (0, "no such rx fib id %d", rx_fib_id);
-
- case VNET_API_ERROR_NO_SUCH_INNER_FIB:
- return clib_error_return (0, "no such tx fib / swif %d",
- tx_fib_or_sw_if_index);
-
- default:
- return clib_error_return (0, "vnet_mpls_add_del_decap returned %d",
- rv);
- }
- return 0;
-}
-
-VLIB_CLI_COMMAND (mpls_add_decap_command, static) = {
- .path = "mpls decap add",
- .short_help =
- "mpls decap add fib <id> label <nn> [s-bit-clear] [next-index <nn>]",
- .function = mpls_add_decap_command_fn,
-};
-
-static clib_error_t *
-mpls_del_decap_command_fn (vlib_main_t * vm,
- unformat_input_t * input,
- vlib_cli_command_t * cmd)
-{
- u32 rx_fib_id = 0;
- u32 tx_fib_id = 0;
- u32 label;
- int s_bit = 1;
- int label_set = 0;
- int rv;
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "rx-fib %d", &rx_fib_id))
- ;
- else if (unformat (input, "label %d", &label))
- label_set = 1;
- else if (unformat (input, "s-bit-clear"))
- s_bit = 0;
- }
-
- if (!label_set)
- return clib_error_return (0, "label not set");
-
- rv = vnet_mpls_add_del_decap (rx_fib_id,
- tx_fib_id /* not interesting */,
- label, s_bit,
- 0 /* next_index not interesting */,
- 0 /* is_add */);
- switch (rv)
- {
- case 0:
- break;
-
- case VNET_API_ERROR_NO_SUCH_FIB:
- return clib_error_return (0, "no such rx fib id %d", rx_fib_id);
-
- case VNET_API_ERROR_NO_SUCH_INNER_FIB:
- return clib_error_return (0, "no such lookup fib id %d", tx_fib_id);
-
- case VNET_API_ERROR_NO_SUCH_LABEL:
- return clib_error_return (0, "no such label %d rx fib id %d",
- label, rx_fib_id);
-
- default:
- return clib_error_return (0, "vnet_mpls_add_del_decap returned %d",
- rv);
- }
- return 0;
-}
-
-
-VLIB_CLI_COMMAND (mpls_del_decap_command, static) = {
- .path = "mpls decap delete",
- .short_help = "mpls decap delete label <label> rx-fib <id> [s-bit-clear]",
- .function = mpls_del_decap_command_fn,
-};
-