2 * mpls_features.c: MPLS input and output features
4 * Copyright (c) 2016 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/mpls/mpls.h>
21 mpls_terminate (vlib_main_t * vm,
22 vlib_node_runtime_t * node,
26 u32 * buffers = vlib_frame_vector_args (frame);
27 uword n_packets = frame->n_vectors;
29 vlib_error_drop_buffers (vm, node,
34 mpls_input_node.index,
41 mpls_punt (vlib_main_t * vm,
42 vlib_node_runtime_t * node,
45 return (mpls_terminate(vm, node, frame, MPLS_ERROR_PUNT));
48 VLIB_REGISTER_NODE (mpls_punt_node) = {
49 .function = mpls_punt,
51 .vector_size = sizeof (u32),
59 VLIB_NODE_FUNCTION_MULTIARCH (mpls_punt_node, mpls_punt)
62 mpls_drop (vlib_main_t * vm,
63 vlib_node_runtime_t * node,
66 return (mpls_terminate(vm, node, frame, MPLS_ERROR_DROP));
69 VLIB_REGISTER_NODE (mpls_drop_node) = {
70 .function = mpls_drop,
72 .vector_size = sizeof (u32),
80 VLIB_NODE_FUNCTION_MULTIARCH (mpls_drop_node, mpls_drop)
83 mpls_not_enabled (vlib_main_t * vm,
84 vlib_node_runtime_t * node,
87 return (mpls_terminate(vm, node, frame, MPLS_ERROR_NOT_ENABLED));
90 VLIB_REGISTER_NODE (mpls_not_enabled_node) = {
91 .function = mpls_not_enabled,
92 .name = "mpls-not-enabled",
93 .vector_size = sizeof (u32),
101 VLIB_NODE_FUNCTION_MULTIARCH (mpls_not_enabled_node, mpls_not_enabled)
103 VNET_MPLS_FEATURE_INIT (mpls_lookup, static) = {
104 .node_name = "mpls-lookup",
105 .runs_before = ORDER_CONSTRAINTS {"mpls-not-enabled", 0},
106 .feature_index = &mpls_main.mpls_rx_feature_lookup,
109 VNET_MPLS_FEATURE_INIT (mpls_not_enabled, static) = {
110 .node_name = "mpls-not-enabled",
111 .runs_before = ORDER_CONSTRAINTS {0}, /* not before any other features */
112 .feature_index = &mpls_main.mpls_rx_feature_not_enabled,
115 /* Built-in ip4 tx feature path definition */
116 VNET_MPLS_TX_FEATURE_INIT (interface_output, static) = {
117 .node_name = "interface-output",
118 .runs_before = 0, /* not before any other features */
119 .feature_index = &mpls_main.mpls_tx_feature_interface_output,
123 static char * rx_feature_start_nodes[] =
127 static char * tx_feature_start_nodes[] =
134 mpls_feature_init (vlib_main_t * vm)
136 ip_config_main_t * cm = &mpls_main.feature_config_mains[VNET_IP_RX_UNICAST_FEAT];
137 vnet_config_main_t * vcm = &cm->config_main;
140 if ((error = ip_feature_init_cast (vm, cm, vcm,
141 rx_feature_start_nodes,
142 ARRAY_LEN(rx_feature_start_nodes),
143 mpls_main.next_feature[VNET_IP_RX_UNICAST_FEAT],
144 &mpls_main.feature_nodes[VNET_IP_RX_UNICAST_FEAT])))
147 cm = &mpls_main.feature_config_mains[VNET_IP_TX_FEAT];
148 vcm = &cm->config_main;
150 if ((error = ip_feature_init_cast (vm, cm, vcm,
151 tx_feature_start_nodes,
152 ARRAY_LEN(tx_feature_start_nodes),
153 mpls_main.next_feature[VNET_IP_TX_FEAT],
154 &mpls_main.feature_nodes[VNET_IP_TX_FEAT])))
160 static clib_error_t *
161 mpls_sw_interface_add_del (vnet_main_t * vnm,
165 vlib_main_t * vm = vnm->vlib_main;
166 mpls_main_t * mm = &mpls_main;
170 for (cast = 0; cast < VNET_N_IP_FEAT; cast++)
172 ip_config_main_t * cm = &mm->feature_config_mains[cast];
173 vnet_config_main_t * vcm = &cm->config_main;
175 if (VNET_IP_RX_MULTICAST_FEAT == cast)
178 vec_validate_init_empty (mm->mpls_enabled_by_sw_if_index, sw_if_index, 0);
179 vec_validate_init_empty (mm->fib_index_by_sw_if_index, sw_if_index, 0);
180 vec_validate_init_empty (cm->config_index_by_sw_if_index, sw_if_index, ~0);
181 ci = cm->config_index_by_sw_if_index[sw_if_index];
183 if (cast == VNET_IP_RX_UNICAST_FEAT)
184 feature_index = mm->mpls_rx_feature_not_enabled;
186 feature_index = mm->mpls_tx_feature_interface_output;
190 ci = vnet_config_add_feature (vm, vcm, ci,
193 /* # bytes of config data */ 0);
196 ci = vnet_config_del_feature (vm, vcm, ci,
199 /* # bytes of config data */ 0);
200 mm->mpls_enabled_by_sw_if_index[sw_if_index] = 0;;
202 cm->config_index_by_sw_if_index[sw_if_index] = ci;
205 return /* no error */ 0;
208 VNET_SW_INTERFACE_ADD_DEL_FUNCTION (mpls_sw_interface_add_del);
210 #define foreach_af_cast \
211 _(VNET_IP_RX_UNICAST_FEAT, "mpls input") \
212 _(VNET_IP_TX_FEAT, "mpls output") \
214 static clib_error_t *
215 show_mpls_features_command_fn (vlib_main_t * vm,
216 unformat_input_t * input,
217 vlib_cli_command_t * cmd)
219 mpls_main_t * mm = &mpls_main;
223 vlib_cli_output (vm, "Available MPLS feature nodes");
227 features = mm->feature_nodes[c]; \
228 vlib_cli_output (vm, "%s:", s); \
229 for (i = 0; i < vec_len(features); i++) \
230 vlib_cli_output (vm, " %s\n", features[i]); \
238 VLIB_CLI_COMMAND (show_ip_features_command, static) = {
239 .path = "show mpls features",
240 .short_help = "show mpls features",
241 .function = show_mpls_features_command_fn,
244 static clib_error_t *
245 show_mpls_interface_features_command_fn (vlib_main_t * vm,
246 unformat_input_t * input,
247 vlib_cli_command_t * cmd)
249 vnet_main_t * vnm = vnet_get_main();
252 if (! unformat (input, "%U", unformat_vnet_sw_interface,
254 return clib_error_return (0, "Interface not specified...");
256 vlib_cli_output (vm, "MPLS feature paths configured on %U...",
257 format_vnet_sw_if_index_name, vnm, sw_if_index);
259 ip_interface_features_show (vm, "MPLS",
260 mpls_main.feature_config_mains,
266 VLIB_CLI_COMMAND (show_mpls_interface_features_command, static) = {
267 .path = "show mpls interface features",
268 .short_help = "show mpls interface features <intfc>",
269 .function = show_mpls_interface_features_command_fn,