Line data Source code
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 1151 : VNET_FEATURE_ARC_INIT (ip6_punt) =
23 : {
24 : .arc_name = "ip6-punt",
25 : .start_nodes = VNET_FEATURES ("ip6-punt"),
26 : };
27 :
28 1151 : 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 2303 : VLIB_NODE_FN (ip6_punt_policer_handoff_node)
44 : (vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
45 : {
46 3 : return policer_handoff (vm, node, frame, ip6_punt_policer_cfg.fq_index,
47 : ip6_punt_policer_cfg.policer_index);
48 : }
49 :
50 183788 : 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 2319 : VLIB_NODE_FN (ip6_punt_policer_node) (vlib_main_t * vm,
71 : vlib_node_runtime_t * node,
72 : vlib_frame_t * frame)
73 : {
74 38 : return (ip_punt_policer (vm, node, frame,
75 19 : vnet_feat_arc_ip6_punt.feature_arc_index,
76 : ip6_punt_policer_cfg.policer_index));
77 : }
78 :
79 :
80 : /* *INDENT-OFF* */
81 :
82 183788 : 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 76635 : 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 2871 : VLIB_NODE_FN (ip6_drop_node) (vlib_main_t * vm, vlib_node_runtime_t * node,
105 : vlib_frame_t * frame)
106 : {
107 571 : if (node->flags & VLIB_NODE_FLAG_TRACE)
108 186 : ip6_forward_next_trace (vm, node, frame, VLIB_TX);
109 :
110 1142 : return ip_drop_or_punt (vm, node, frame,
111 571 : vnet_feat_arc_ip6_drop.feature_arc_index);
112 :
113 : }
114 :
115 3067 : VLIB_NODE_FN (ip6_not_enabled_node) (vlib_main_t * vm,
116 : vlib_node_runtime_t * node,
117 : vlib_frame_t * frame)
118 : {
119 767 : if (node->flags & VLIB_NODE_FLAG_TRACE)
120 20 : ip6_forward_next_trace (vm, node, frame, VLIB_TX);
121 :
122 1534 : return ip_drop_or_punt (vm, node, frame,
123 767 : vnet_feat_arc_ip6_drop.feature_arc_index);
124 :
125 : }
126 :
127 2400 : VLIB_NODE_FN (ip6_punt_node) (vlib_main_t * vm, vlib_node_runtime_t * node,
128 : vlib_frame_t * frame)
129 : {
130 100 : if (node->flags & VLIB_NODE_FLAG_TRACE)
131 60 : ip6_forward_next_trace (vm, node, frame, VLIB_TX);
132 :
133 200 : return ip_drop_or_punt (vm, node, frame,
134 100 : vnet_feat_arc_ip6_punt.feature_arc_index);
135 : }
136 :
137 : /* *INDENT-OFF* */
138 183788 : 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 183788 : 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 183788 : 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 76635 : 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 76635 : 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 6 : ip6_punt_policer_add_del (u8 is_add, u32 policer_index)
183 : {
184 6 : ip6_punt_policer_cfg.policer_index = policer_index;
185 :
186 6 : vnet_feature_enable_disable ("ip6-punt", "ip6-punt-policer",
187 : 0, is_add, 0, 0);
188 6 : }
189 : #endif /* CLIB_MARCH_VARIANT */
190 :
191 : static clib_error_t *
192 0 : ip6_punt_police_cmd (vlib_main_t * vm,
193 : unformat_input_t * main_input,
194 : vlib_cli_command_t * cmd)
195 : {
196 0 : unformat_input_t _line_input, *line_input = &_line_input;
197 0 : clib_error_t *error = 0;
198 : u32 policer_index;
199 0 : u8 is_add = 1;
200 :
201 0 : policer_index = ~0;
202 :
203 0 : if (!unformat_user (main_input, unformat_line_input, line_input))
204 0 : return 0;
205 :
206 0 : while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
207 : {
208 0 : if (unformat (line_input, "%d", &policer_index))
209 : ;
210 0 : else if (unformat (line_input, "del"))
211 0 : is_add = 0;
212 0 : else if (unformat (line_input, "add"))
213 0 : is_add = 1;
214 : else
215 : {
216 0 : error = unformat_parse_error (line_input);
217 0 : goto done;
218 : }
219 : }
220 :
221 0 : if (is_add && ~0 == policer_index)
222 : {
223 0 : error = clib_error_return (0, "expected policer index `%U'",
224 : format_unformat_error, line_input);
225 0 : goto done;
226 : }
227 0 : if (!is_add)
228 0 : policer_index = ~0;
229 :
230 0 : ip6_punt_policer_add_del(is_add, policer_index);
231 :
232 0 : done:
233 0 : unformat_free (line_input);
234 0 : return (error);
235 : }
236 :
237 : /*?
238 : *
239 : * @cliexpar
240 : * @cliexcmd{set ip punt policer <INDEX>}
241 : ?*/
242 : /* *INDENT-OFF* */
243 285289 : 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 2351 : VLIB_NODE_FN (ip6_punt_redirect_node) (vlib_main_t * vm,
270 : vlib_node_runtime_t * node,
271 : vlib_frame_t * frame)
272 : {
273 102 : return (ip_punt_redirect (vm, node, frame,
274 51 : vnet_feat_arc_ip6_punt.feature_arc_index,
275 : FIB_PROTOCOL_IP6));
276 : }
277 :
278 : /* *INDENT-OFF* */
279 183788 : 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 76635 : 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 : static u32 ip6_punt_redirect_enable_counts;
305 :
306 : void
307 21 : ip6_punt_redirect_add_paths (u32 rx_sw_if_index,
308 : const fib_route_path_t *rpaths)
309 : {
310 21 : ip_punt_redirect_add (FIB_PROTOCOL_IP6,
311 : rx_sw_if_index,
312 : FIB_FORW_CHAIN_TYPE_UNICAST_IP6, rpaths);
313 :
314 21 : if (1 == ++ip6_punt_redirect_enable_counts)
315 12 : vnet_feature_enable_disable ("ip6-punt", "ip6-punt-redirect", 0, 1, 0, 0);
316 21 : }
317 :
318 : void
319 21 : ip6_punt_redirect_del (u32 rx_sw_if_index)
320 : {
321 21 : ASSERT (ip6_punt_redirect_enable_counts);
322 21 : if (0 == --ip6_punt_redirect_enable_counts)
323 12 : vnet_feature_enable_disable ("ip6-punt", "ip6-punt-redirect", 0, 0, 0, 0);
324 :
325 21 : ip_punt_redirect_del (FIB_PROTOCOL_IP6, rx_sw_if_index);
326 21 : }
327 : #endif /* CLIB_MARCH_VARIANT */
328 :
329 : static clib_error_t *
330 0 : ip6_punt_redirect_cmd (vlib_main_t * vm,
331 : unformat_input_t * main_input,
332 : vlib_cli_command_t * cmd)
333 : {
334 0 : unformat_input_t _line_input, *line_input = &_line_input;
335 0 : fib_route_path_t *rpaths = NULL, rpath;
336 0 : dpo_proto_t payload_proto = DPO_PROTO_IP6;
337 0 : clib_error_t *error = 0;
338 0 : u32 rx_sw_if_index = ~0;
339 : vnet_main_t *vnm;
340 : u8 is_add;
341 :
342 0 : is_add = 1;
343 0 : vnm = vnet_get_main ();
344 :
345 0 : if (!unformat_user (main_input, unformat_line_input, line_input))
346 0 : return 0;
347 :
348 0 : while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
349 : {
350 0 : if (unformat (line_input, "del"))
351 0 : is_add = 0;
352 0 : else if (unformat (line_input, "add"))
353 0 : is_add = 1;
354 0 : else if (unformat (line_input, "rx all"))
355 0 : rx_sw_if_index = 0;
356 0 : else if (unformat (line_input, "rx %U",
357 : unformat_vnet_sw_interface, vnm, &rx_sw_if_index))
358 : ;
359 0 : else if (unformat (line_input, "via %U",
360 : unformat_fib_route_path, &rpath, &payload_proto))
361 0 : vec_add1 (rpaths, rpath);
362 : else
363 : {
364 0 : error = unformat_parse_error (line_input);
365 0 : goto done;
366 : }
367 : }
368 :
369 0 : if (~0 == rx_sw_if_index)
370 : {
371 0 : error = unformat_parse_error (line_input);
372 0 : goto done;
373 : }
374 :
375 0 : if (is_add)
376 : {
377 0 : if (vec_len (rpaths))
378 0 : ip6_punt_redirect_add_paths (rx_sw_if_index, rpaths);
379 : }
380 : else
381 : {
382 0 : ip6_punt_redirect_del (rx_sw_if_index);
383 : }
384 :
385 0 : done:
386 0 : vec_free (rpaths);
387 0 : unformat_free (line_input);
388 0 : return (error);
389 : }
390 :
391 : /*?
392 : *
393 : * @cliexpar
394 : * @cliexcmd{set ip punt policer <INDEX>}
395 : ?*/
396 : /* *INDENT-OFF* */
397 285289 : VLIB_CLI_COMMAND (ip6_punt_redirect_command, static) =
398 : {
399 : .path = "ip6 punt redirect",
400 : .function = ip6_punt_redirect_cmd,
401 : .short_help = "ip6 punt redirect [add|del] rx [<interface>|all] via [<nh>] <tx_interface>",
402 : };
403 : /* *INDENT-ON* */
404 :
405 : #ifndef CLIB_MARCH_VARIANT
406 :
407 : #endif /* CLIB_MARCH_VARIANT */
408 :
409 : static clib_error_t *
410 0 : ip6_punt_redirect_show_cmd (vlib_main_t * vm,
411 : unformat_input_t * main_input,
412 : vlib_cli_command_t * cmd)
413 : {
414 0 : vlib_cli_output (vm, "%U", format_ip_punt_redirect, FIB_PROTOCOL_IP6);
415 :
416 0 : return (NULL);
417 : }
418 :
419 : /*?
420 : *
421 : * @cliexpar
422 : * @cliexcmd{set ip punt policer <INDEX>}
423 : ?*/
424 : /* *INDENT-OFF* */
425 285289 : VLIB_CLI_COMMAND (show_ip6_punt_redirect_command, static) =
426 : {
427 : .path = "show ip6 punt redirect",
428 : .function = ip6_punt_redirect_show_cmd,
429 : .short_help = "show ip6 punt redirect",
430 : .is_mp_safe = 1,
431 : };
432 : /* *INDENT-ON* */
433 :
434 : /*
435 : * fd.io coding-style-patch-verification: ON
436 : *
437 : * Local Variables:
438 : * eval: (c-set-style "gnu")
439 : * End:
440 : */
|