2 * interface.c: mpls interfaces
4 * Copyright (c) 2012 Cisco and/or its affiliates.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 #include <vnet/vnet.h>
19 #include <vnet/mpls/mpls.h>
20 #include <vnet/fib/mpls_fib.h>
21 #include <vnet/fib/ip4_fib.h>
22 #include <vnet/adj/adj_midchain.h>
23 #include <vnet/dpo/classify_dpo.h>
27 mpls_interface_state_change_function_t *function;
28 uword function_opaque;
29 } mpls_interface_state_change_callback_t;
31 /** Functions to call when interface becomes MPLS enabled/disabled. */
32 static mpls_interface_state_change_callback_t *state_change_callbacks;
35 mpls_sw_interface_is_enabled (u32 sw_if_index)
37 mpls_main_t * mm = &mpls_main;
39 if (vec_len(mm->mpls_enabled_by_sw_if_index) <= sw_if_index)
42 return (mm->mpls_enabled_by_sw_if_index[sw_if_index]);
46 mpls_interface_state_change_add_callback (
47 mpls_interface_state_change_function_t *function, uword opaque)
49 mpls_interface_state_change_callback_t cb = {
51 .function_opaque = opaque,
53 vec_add1 (state_change_callbacks, cb);
57 mpls_sw_interface_enable_disable (mpls_main_t *mm, u32 sw_if_index,
60 fib_node_index_t lfib_index;
61 vnet_main_t *vnm = vnet_get_main ();
62 vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
64 vec_validate_init_empty (mm->mpls_enabled_by_sw_if_index, sw_if_index, 0);
66 lfib_index = fib_table_find(FIB_PROTOCOL_MPLS,
67 MPLS_FIB_DEFAULT_TABLE_ID);
70 return VNET_API_ERROR_NO_SUCH_FIB;
73 * enable/disable only on the 1<->0 transition
77 if (1 != ++mm->mpls_enabled_by_sw_if_index[sw_if_index])
80 fib_table_lock (lfib_index, FIB_PROTOCOL_MPLS, FIB_SOURCE_INTERFACE);
82 vec_validate(mm->fib_index_by_sw_if_index, sw_if_index);
83 mm->fib_index_by_sw_if_index[sw_if_index] = lfib_index;
87 ASSERT(mm->mpls_enabled_by_sw_if_index[sw_if_index] > 0);
88 if (0 != --mm->mpls_enabled_by_sw_if_index[sw_if_index])
91 fib_table_unlock (mm->fib_index_by_sw_if_index[sw_if_index],
92 FIB_PROTOCOL_MPLS, FIB_SOURCE_INTERFACE);
95 vnet_feature_enable_disable ("mpls-input", "mpls-not-enabled",
96 sw_if_index, !is_enable, 0, 0);
100 else if (hi->l3_if_count)
104 mpls_interface_state_change_callback_t *cb;
105 vec_foreach (cb, state_change_callbacks)
106 cb->function (mm, cb->function_opaque, sw_if_index, is_enable);
112 static clib_error_t *
113 mpls_interface_enable_disable (vlib_main_t * vm,
114 unformat_input_t * input,
115 vlib_cli_command_t * cmd)
117 vnet_main_t * vnm = vnet_get_main();
118 clib_error_t * error = 0;
119 u32 sw_if_index, enable;
124 if (! unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
126 error = clib_error_return (0, "unknown interface `%U'",
127 format_unformat_error, input);
131 if (unformat (input, "enable"))
133 else if (unformat (input, "disable"))
137 error = clib_error_return (0, "expected 'enable' or 'disable'",
138 format_unformat_error, input);
142 rv = mpls_sw_interface_enable_disable (&mpls_main, sw_if_index, enable);
144 if (VNET_API_ERROR_NO_SUCH_FIB == rv)
145 error = clib_error_return (0, "default MPLS table must be created first");
152 * This command enables an interface to accept MPLS packets
155 * @cliexstart{set interface mpls}
156 * set interface mpls GigEthernet0/8/0 enable
159 VLIB_CLI_COMMAND (set_interface_ip_table_command, static) = {
160 .path = "set interface mpls",
161 .function = mpls_interface_enable_disable,
162 .short_help = "Enable/Disable an interface for MPLS forwarding",
166 show_mpls_one_interface (vnet_main_t *vnm, vlib_main_t *vm, u32 sw_if_index,
169 mpls_main_t *mm = &mpls_main;
172 enabled = mm->mpls_enabled_by_sw_if_index[sw_if_index];
176 vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name, vnm,
178 vlib_cli_output (vm, " MPLS enabled");
182 vlib_cli_output (vm, "%U\n", format_vnet_sw_if_index_name, vnm,
184 vlib_cli_output (vm, " MPLS disabled");
189 show_mpls_interface_walk (vnet_main_t *vnm, vnet_sw_interface_t *si, void *ctx)
191 show_mpls_one_interface (vnm, ctx, si->sw_if_index, false);
193 return (WALK_CONTINUE);
196 static clib_error_t *
197 show_mpls_interface (vlib_main_t *vm, unformat_input_t *input,
198 vlib_cli_command_t *cmd)
200 vnet_main_t *vnm = vnet_get_main ();
205 if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
208 if (~0 == sw_if_index)
210 vnet_sw_interface_walk (vnm, show_mpls_interface_walk, vm);
214 show_mpls_one_interface (vnm, vm, sw_if_index, true);
221 * This command displays the MPLS forwarding state of an interface
224 * @cliexstart{show mpls interface}
225 * set mpls interface GigEthernet0/8/0
228 VLIB_CLI_COMMAND (show_mpls_interface_command, static) = {
229 .path = "show mpls interface",
230 .function = show_mpls_interface,
231 .short_help = "Show MPLS interface forwarding",