ip6: ip6_not_enabled_node is a sibling of ip6-drop
[vpp.git] / src / vnet / ip / ip6_punt_drop.c
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include <vnet/ip/ip.h>
17 #include <vnet/ip/ip_punt_drop.h>
18 #include <vnet/policer/policer.h>
19 #include <vnet/policer/police_inlines.h>
20
21 /* *INDENT-OFF* */
22 VNET_FEATURE_ARC_INIT (ip6_punt) =
23 {
24   .arc_name  = "ip6-punt",
25   .start_nodes = VNET_FEATURES ("ip6-punt"),
26 };
27
28 VNET_FEATURE_ARC_INIT (ip6_drop) =
29 {
30   .arc_name  = "ip6-drop",
31   .start_nodes = VNET_FEATURES ("ip6-drop", "ip6-not-enabled"),
32 };
33 /* *INDENT-ON* */
34
35 extern ip_punt_policer_t ip6_punt_policer_cfg;
36
37 #ifndef CLIB_MARCH_VARIANT
38 ip_punt_policer_t ip6_punt_policer_cfg;
39 #endif /* CLIB_MARCH_VARIANT */
40
41 static char *ip6_punt_policer_handoff_error_strings[] = { "congestion drop" };
42
43 VLIB_NODE_FN (ip6_punt_policer_handoff_node)
44 (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
45 {
46   return policer_handoff (vm, node, frame, ip6_punt_policer_cfg.fq_index,
47                           ip6_punt_policer_cfg.policer_index);
48 }
49
50 VLIB_REGISTER_NODE (ip6_punt_policer_handoff_node) = {
51   .name = "ip6-punt-policer-handoff",
52   .vector_size = sizeof (u32),
53   .format_trace = format_policer_handoff_trace,
54   .type = VLIB_NODE_TYPE_INTERNAL,
55   .n_errors = ARRAY_LEN(ip6_punt_policer_handoff_error_strings),
56   .error_strings = ip6_punt_policer_handoff_error_strings,
57
58   .n_next_nodes = 1,
59   .next_nodes = {
60     [0] = "error-drop",
61   },
62 };
63
64 static char *ip6_punt_policer_error_strings[] = {
65 #define _(sym,string) string,
66   foreach_ip_punt_policer_error
67 #undef _
68 };
69
70 VLIB_NODE_FN (ip6_punt_policer_node) (vlib_main_t * vm,
71                                       vlib_node_runtime_t * node,
72                                       vlib_frame_t * frame)
73 {
74   return (ip_punt_policer (vm, node, frame,
75                            vnet_feat_arc_ip6_punt.feature_arc_index,
76                            ip6_punt_policer_cfg.policer_index));
77 }
78
79
80 /* *INDENT-OFF* */
81
82 VLIB_REGISTER_NODE (ip6_punt_policer_node) = {
83   .name = "ip6-punt-policer",
84   .vector_size = sizeof (u32),
85   .n_next_nodes = IP_PUNT_POLICER_N_NEXT,
86   .format_trace = format_ip_punt_policer_trace,
87   .n_errors = ARRAY_LEN(ip6_punt_policer_error_strings),
88   .error_strings = ip6_punt_policer_error_strings,
89
90   /* edit / add dispositions here */
91   .next_nodes = {
92     [IP_PUNT_POLICER_NEXT_DROP] = "ip6-drop",
93     [IP_PUNT_POLICER_NEXT_HANDOFF] = "ip6-punt-policer-handoff",
94   },
95 };
96
97 VNET_FEATURE_INIT (ip6_punt_policer_node, static) = {
98   .arc_name = "ip6-punt",
99   .node_name = "ip6-punt-policer",
100   .runs_before = VNET_FEATURES("ip6-punt-redirect")
101 };
102 /* *INDENT-ON* */
103
104 VLIB_NODE_FN (ip6_drop_node) (vlib_main_t * vm, vlib_node_runtime_t * node,
105                               vlib_frame_t * frame)
106 {
107   if (node->flags & VLIB_NODE_FLAG_TRACE)
108     ip6_forward_next_trace (vm, node, frame, VLIB_TX);
109
110   return ip_drop_or_punt (vm, node, frame,
111                           vnet_feat_arc_ip6_drop.feature_arc_index);
112
113 }
114
115 VLIB_NODE_FN (ip6_not_enabled_node) (vlib_main_t * vm,
116                                      vlib_node_runtime_t * node,
117                                      vlib_frame_t * frame)
118 {
119   if (node->flags & VLIB_NODE_FLAG_TRACE)
120     ip6_forward_next_trace (vm, node, frame, VLIB_TX);
121
122   return ip_drop_or_punt (vm, node, frame,
123                           vnet_feat_arc_ip6_drop.feature_arc_index);
124
125 }
126
127 VLIB_NODE_FN (ip6_punt_node) (vlib_main_t * vm, vlib_node_runtime_t * node,
128                               vlib_frame_t * frame)
129 {
130   if (node->flags & VLIB_NODE_FLAG_TRACE)
131     ip6_forward_next_trace (vm, node, frame, VLIB_TX);
132
133   return ip_drop_or_punt (vm, node, frame,
134                           vnet_feat_arc_ip6_punt.feature_arc_index);
135 }
136
137 /* *INDENT-OFF* */
138 VLIB_REGISTER_NODE (ip6_drop_node) =
139 {
140   .name = "ip6-drop",
141   .vector_size = sizeof (u32),
142   .format_trace = format_ip6_forward_next_trace,
143   .n_next_nodes = 1,
144   .next_nodes = {
145     [0] = "error-drop",
146   },
147 };
148
149 VLIB_REGISTER_NODE (ip6_not_enabled_node) = {
150   .name = "ip6-not-enabled",
151   .vector_size = sizeof (u32),
152   .format_trace = format_ip6_forward_next_trace,
153   .sibling_of = "ip6-drop",
154 };
155
156 VLIB_REGISTER_NODE (ip6_punt_node) =
157 {
158   .name = "ip6-punt",
159   .vector_size = sizeof (u32),
160   .format_trace = format_ip6_forward_next_trace,
161   .n_next_nodes = 1,
162   .next_nodes = {
163     [0] = "error-punt",
164   },
165 };
166
167 VNET_FEATURE_INIT (ip6_punt_end_of_arc, static) = {
168   .arc_name = "ip6-punt",
169   .node_name = "error-punt",
170   .runs_before = 0, /* not before any other features */
171 };
172
173 VNET_FEATURE_INIT (ip6_drop_end_of_arc, static) = {
174   .arc_name = "ip6-drop",
175   .node_name = "error-drop",
176   .runs_before = 0, /* not before any other features */
177 };
178 /* *INDENT-ON */
179
180 #ifndef CLIB_MARCH_VARIANT
181 void
182 ip6_punt_policer_add_del (u8 is_add, u32 policer_index)
183 {
184   ip6_punt_policer_cfg.policer_index = policer_index;
185
186   vnet_feature_enable_disable ("ip6-punt", "ip6-punt-policer",
187                                0, is_add, 0, 0);
188 }
189 #endif /* CLIB_MARCH_VARIANT */
190
191 static clib_error_t *
192 ip6_punt_police_cmd (vlib_main_t * vm,
193                      unformat_input_t * main_input,
194                      vlib_cli_command_t * cmd)
195 {
196   unformat_input_t _line_input, *line_input = &_line_input;
197   clib_error_t *error = 0;
198   u32 policer_index;
199   u8 is_add = 1;
200
201   policer_index = ~0;
202
203   if (!unformat_user (main_input, unformat_line_input, line_input))
204     return 0;
205
206   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
207     {
208       if (unformat (line_input, "%d", &policer_index))
209         ;
210       else if (unformat (line_input, "del"))
211         is_add = 0;
212       else if (unformat (line_input, "add"))
213         is_add = 1;
214       else
215         {
216           error = unformat_parse_error (line_input);
217           goto done;
218         }
219     }
220
221   if (is_add && ~0 == policer_index)
222   {
223       error = clib_error_return (0, "expected policer index `%U'",
224                                  format_unformat_error, line_input);
225       goto done;
226   }
227   if (!is_add)
228       policer_index = ~0;
229
230   ip6_punt_policer_add_del(is_add, policer_index);
231
232 done:
233   unformat_free (line_input);
234   return (error);
235 }
236
237 /*?
238  *
239  * @cliexpar
240  * @cliexcmd{set ip punt policer <INDEX>}
241  ?*/
242 /* *INDENT-OFF* */
243 VLIB_CLI_COMMAND (ip6_punt_policer_command, static) =
244 {
245   .path = "ip6 punt policer",
246   .function = ip6_punt_police_cmd,
247   .short_help = "ip6 punt policer [add|del] <index>",
248 };
249
250 /* *INDENT-ON* */
251
252 #define foreach_ip6_punt_redirect_error         \
253 _(DROP, "ip6 punt redirect drop")
254
255 typedef enum
256 {
257 #define _(sym,str) IP6_PUNT_REDIRECT_ERROR_##sym,
258   foreach_ip6_punt_redirect_error
259 #undef _
260     IP6_PUNT_REDIRECT_N_ERROR,
261 } ip6_punt_redirect_error_t;
262
263 static char *ip6_punt_redirect_error_strings[] = {
264 #define _(sym,string) string,
265   foreach_ip6_punt_redirect_error
266 #undef _
267 };
268
269 VLIB_NODE_FN (ip6_punt_redirect_node) (vlib_main_t * vm,
270                                        vlib_node_runtime_t * node,
271                                        vlib_frame_t * frame)
272 {
273   return (ip_punt_redirect (vm, node, frame,
274                             vnet_feat_arc_ip6_punt.feature_arc_index,
275                             FIB_PROTOCOL_IP6));
276 }
277
278 /* *INDENT-OFF* */
279 VLIB_REGISTER_NODE (ip6_punt_redirect_node) = {
280   .name = "ip6-punt-redirect",
281   .vector_size = sizeof (u32),
282   .n_next_nodes = IP_PUNT_REDIRECT_N_NEXT,
283   .format_trace = format_ip_punt_redirect_trace,
284   .n_errors = ARRAY_LEN(ip6_punt_redirect_error_strings),
285   .error_strings = ip6_punt_redirect_error_strings,
286
287   /* edit / add dispositions here */
288   .next_nodes = {
289     [IP_PUNT_REDIRECT_NEXT_DROP] = "ip6-drop",
290     [IP_PUNT_REDIRECT_NEXT_TX] = "ip6-rewrite",
291     [IP_PUNT_REDIRECT_NEXT_ARP] = "ip6-discover-neighbor",
292   },
293 };
294
295 VNET_FEATURE_INIT (ip6_punt_redirect_node, static) = {
296   .arc_name = "ip6-punt",
297   .node_name = "ip6-punt-redirect",
298   .runs_before = VNET_FEATURES("error-punt")
299 };
300 /* *INDENT-ON* */
301
302 #ifndef CLIB_MARCH_VARIANT
303
304 void
305 ip6_punt_redirect_add_paths (u32 rx_sw_if_index,
306                              const fib_route_path_t *rpaths)
307 {
308   ip_punt_redirect_add (FIB_PROTOCOL_IP6,
309                         rx_sw_if_index,
310                         FIB_FORW_CHAIN_TYPE_UNICAST_IP6, rpaths);
311
312   vnet_feature_enable_disable ("ip6-punt", "ip6-punt-redirect", 0, 1, 0, 0);
313 }
314
315 void
316 ip6_punt_redirect_del (u32 rx_sw_if_index)
317 {
318   vnet_feature_enable_disable ("ip6-punt", "ip6-punt-redirect", 0, 0, 0, 0);
319
320   ip_punt_redirect_del (FIB_PROTOCOL_IP6, rx_sw_if_index);
321 }
322 #endif /* CLIB_MARCH_VARIANT */
323
324 static clib_error_t *
325 ip6_punt_redirect_cmd (vlib_main_t * vm,
326                        unformat_input_t * main_input,
327                        vlib_cli_command_t * cmd)
328 {
329   unformat_input_t _line_input, *line_input = &_line_input;
330   fib_route_path_t *rpaths = NULL, rpath;
331   dpo_proto_t payload_proto = DPO_PROTO_IP6;
332   clib_error_t *error = 0;
333   u32 rx_sw_if_index = ~0;
334   vnet_main_t *vnm;
335   u8 is_add;
336
337   is_add = 1;
338   vnm = vnet_get_main ();
339
340   if (!unformat_user (main_input, unformat_line_input, line_input))
341     return 0;
342
343   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
344     {
345       if (unformat (line_input, "del"))
346         is_add = 0;
347       else if (unformat (line_input, "add"))
348         is_add = 1;
349       else if (unformat (line_input, "rx all"))
350         rx_sw_if_index = 0;
351       else if (unformat (line_input, "rx %U",
352                          unformat_vnet_sw_interface, vnm, &rx_sw_if_index))
353         ;
354       else if (unformat (line_input, "via %U",
355                          unformat_fib_route_path, &rpath, &payload_proto))
356         vec_add1 (rpaths, rpath);
357       else
358         {
359           error = unformat_parse_error (line_input);
360           goto done;
361         }
362     }
363
364   if (~0 == rx_sw_if_index)
365     {
366       error = unformat_parse_error (line_input);
367       goto done;
368     }
369
370   if (is_add)
371     {
372       if (vec_len (rpaths))
373         ip6_punt_redirect_add_paths (rx_sw_if_index, rpaths);
374     }
375   else
376     {
377       ip6_punt_redirect_del (rx_sw_if_index);
378     }
379
380 done:
381   vec_free (rpaths);
382   unformat_free (line_input);
383   return (error);
384 }
385
386 /*?
387  *
388  * @cliexpar
389  * @cliexcmd{set ip punt policer <INDEX>}
390  ?*/
391 /* *INDENT-OFF* */
392 VLIB_CLI_COMMAND (ip6_punt_redirect_command, static) =
393 {
394   .path = "ip6 punt redirect",
395   .function = ip6_punt_redirect_cmd,
396   .short_help = "ip6 punt redirect [add|del] rx [<interface>|all] via [<nh>] <tx_interface>",
397 };
398 /* *INDENT-ON* */
399
400 #ifndef CLIB_MARCH_VARIANT
401
402 #endif /* CLIB_MARCH_VARIANT */
403
404 static clib_error_t *
405 ip6_punt_redirect_show_cmd (vlib_main_t * vm,
406                             unformat_input_t * main_input,
407                             vlib_cli_command_t * cmd)
408 {
409   vlib_cli_output (vm, "%U", format_ip_punt_redirect, FIB_PROTOCOL_IP6);
410
411   return (NULL);
412 }
413
414 /*?
415  *
416  * @cliexpar
417  * @cliexcmd{set ip punt policer <INDEX>}
418  ?*/
419 /* *INDENT-OFF* */
420 VLIB_CLI_COMMAND (show_ip6_punt_redirect_command, static) =
421 {
422   .path = "show ip6 punt redirect",
423   .function = ip6_punt_redirect_show_cmd,
424   .short_help = "show ip6 punt redirect",
425   .is_mp_safe = 1,
426 };
427 /* *INDENT-ON* */
428
429 /*
430  * fd.io coding-style-patch-verification: ON
431  *
432  * Local Variables:
433  * eval: (c-set-style "gnu")
434  * End:
435  */