A Protocol Independent Hierarchical FIB (VPP-352)
[vpp.git] / vnet / vnet / mpls / mpls_features.c
1 /*
2  * mpls_features.c: MPLS input and output features
3  *
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:
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17
18 #include <vnet/mpls/mpls.h>
19
20 always_inline uword
21 mpls_terminate (vlib_main_t * vm,
22                 vlib_node_runtime_t * node,
23                 vlib_frame_t * frame,
24                 int error_code)
25 {
26   u32 * buffers = vlib_frame_vector_args (frame);
27   uword n_packets = frame->n_vectors;
28
29   vlib_error_drop_buffers (vm, node,
30                            buffers,
31                            /* stride */ 1,
32                            n_packets,
33                            /* next */ 0,
34                            mpls_input_node.index,
35                            error_code);
36
37   return n_packets;
38 }
39
40 static uword
41 mpls_punt (vlib_main_t * vm,
42            vlib_node_runtime_t * node,
43            vlib_frame_t * frame)
44 {
45     return (mpls_terminate(vm, node, frame, MPLS_ERROR_PUNT));
46 }
47
48 VLIB_REGISTER_NODE (mpls_punt_node) = {
49   .function = mpls_punt,
50   .name = "mpls-punt",
51   .vector_size = sizeof (u32),
52
53   .n_next_nodes = 1,
54   .next_nodes = {
55     [0] = "error-punt",
56   },
57 };
58
59 VLIB_NODE_FUNCTION_MULTIARCH (mpls_punt_node, mpls_punt)
60
61 static uword
62 mpls_drop (vlib_main_t * vm,
63            vlib_node_runtime_t * node,
64            vlib_frame_t * frame)
65 {
66     return (mpls_terminate(vm, node, frame, MPLS_ERROR_DROP));
67 }
68
69 VLIB_REGISTER_NODE (mpls_drop_node) = {
70   .function = mpls_drop,
71   .name = "mpls-drop",
72   .vector_size = sizeof (u32),
73
74   .n_next_nodes = 1,
75   .next_nodes = {
76     [0] = "error-drop",
77   },
78 };
79
80 VLIB_NODE_FUNCTION_MULTIARCH (mpls_drop_node, mpls_drop)
81
82 static uword
83 mpls_not_enabled (vlib_main_t * vm,
84                   vlib_node_runtime_t * node,
85                   vlib_frame_t * frame)
86 {
87     return (mpls_terminate(vm, node, frame, MPLS_ERROR_NOT_ENABLED));
88 }
89
90 VLIB_REGISTER_NODE (mpls_not_enabled_node) = {
91   .function = mpls_not_enabled,
92   .name = "mpls-not-enabled",
93   .vector_size = sizeof (u32),
94
95   .n_next_nodes = 1,
96   .next_nodes = {
97     [0] = "error-drop",
98   },
99 };
100
101 VLIB_NODE_FUNCTION_MULTIARCH (mpls_not_enabled_node, mpls_not_enabled)
102
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,
107 };
108
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,
113 };
114
115 static char * feature_start_nodes[] =
116 {
117     "mpls-input",
118 };
119
120 clib_error_t *
121 mpls_feature_init (vlib_main_t * vm)
122 {
123   ip_config_main_t * cm = &mpls_main.rx_config_mains;
124   vnet_config_main_t * vcm = &cm->config_main;
125
126   return (ip_feature_init_cast (vm, cm, vcm,
127                                 feature_start_nodes,
128                                 ARRAY_LEN(feature_start_nodes),
129                                 VNET_IP_RX_UNICAST_FEAT,
130                                 VNET_L3_PACKET_TYPE_MPLS_UNICAST));
131 }
132
133 static clib_error_t *
134 mpls_sw_interface_add_del (vnet_main_t * vnm,
135                            u32 sw_if_index,
136                            u32 is_add)
137 {
138   vlib_main_t * vm = vnm->vlib_main;
139   mpls_main_t * mm = &mpls_main;
140   ip_config_main_t * cm = &mm->rx_config_mains;
141   vnet_config_main_t * vcm = &cm->config_main;
142   u32 drop_feature_index;
143   u32 ci;
144
145   vec_validate_init_empty (mm->mpls_enabled_by_sw_if_index, sw_if_index, 0);
146   vec_validate_init_empty (mm->fib_index_by_sw_if_index, sw_if_index, 0);
147   vec_validate_init_empty (cm->config_index_by_sw_if_index, sw_if_index, ~0);
148   ci = cm->config_index_by_sw_if_index[sw_if_index];
149
150   drop_feature_index = mm->mpls_rx_feature_not_enabled;
151
152   if (is_add)
153     ci = vnet_config_add_feature (vm, vcm, ci,
154                                   drop_feature_index,
155                                   /* config data */ 0,
156                                   /* # bytes of config data */ 0);
157   else
158    {
159      ci = vnet_config_del_feature (vm, vcm, ci,
160                                    drop_feature_index,
161                                    /* config data */ 0,
162                                    /* # bytes of config data */ 0);
163      mm->mpls_enabled_by_sw_if_index[sw_if_index] = 0;;
164    }
165
166   cm->config_index_by_sw_if_index[sw_if_index] = ci;
167
168   return /* no error */ 0;
169 }
170
171 VNET_SW_INTERFACE_ADD_DEL_FUNCTION (mpls_sw_interface_add_del);
172
173 static clib_error_t *
174 show_mpls_features_command_fn (vlib_main_t * vm,
175                                unformat_input_t * input,
176                                vlib_cli_command_t * cmd)
177 {
178   mpls_main_t * mm = &mpls_main;
179   int i;
180   char ** features;
181
182   vlib_cli_output (vm, "Available MPLS feature nodes");
183
184   do {
185     features = mm->feature_nodes;
186     for (i = 0; i < vec_len(features); i++)
187       vlib_cli_output (vm, "  %s\n", features[i]);
188   } while(0);
189
190   return 0;
191 }
192
193 VLIB_CLI_COMMAND (show_ip_features_command, static) = {
194   .path = "show mpls features",
195   .short_help = "show mpls features",
196   .function = show_mpls_features_command_fn,
197 };
198
199 static clib_error_t *
200 show_mpls_interface_features_command_fn (vlib_main_t * vm,
201                                          unformat_input_t * input,
202                                          vlib_cli_command_t * cmd)
203 {
204   vnet_main_t * vnm = vnet_get_main();
205   mpls_main_t * mm = &mpls_main;
206
207   ip_config_main_t * cm;
208   vnet_config_main_t * vcm;
209   vnet_config_t * cfg;
210   u32 cfg_index;
211   vnet_config_feature_t * feat;
212   vlib_node_t * n;
213   u32 sw_if_index;
214   u32 node_index;
215   u32 current_config_index;
216   int i;
217
218   if (! unformat (input, "%U", unformat_vnet_sw_interface,
219                   vnm, &sw_if_index))
220     return clib_error_return (0, "Interface not specified...");
221
222   vlib_cli_output (vm, "MPLS feature paths configured on %U...",
223                    format_vnet_sw_if_index_name, vnm, sw_if_index);
224
225   cm = &mm->rx_config_mains;
226   vcm = &cm->config_main;
227
228   current_config_index = vec_elt (cm->config_index_by_sw_if_index,
229                                   sw_if_index);
230
231   ASSERT(current_config_index
232          < vec_len (vcm->config_pool_index_by_user_index));
233
234   cfg_index =
235       vcm->config_pool_index_by_user_index[current_config_index];
236   cfg = pool_elt_at_index (vcm->config_pool, cfg_index);
237
238   for (i = 0; i < vec_len(cfg->features); i++)
239   {
240       feat = cfg->features + i;
241       node_index = feat->node_index;
242       n = vlib_get_node (vm, node_index);
243       vlib_cli_output (vm, "  %v", n->name);
244   }
245
246   return 0;
247 }
248
249 VLIB_CLI_COMMAND (show_mpls_interface_features_command, static) = {
250   .path = "show mpls interface features",
251   .short_help = "show mpls interface features <intfc>",
252   .function = show_mpls_interface_features_command_fn,
253 };
254