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