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