blob: 2fc1140a0bf7b25378e7abc18159922804618e98 [file] [log] [blame]
Neale Rannsd91c1db2017-07-31 02:30:50 -07001/*
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#ifndef __IP_PUNT_DROP_H__
17#define __IP_PUNT_DROP_H__
18
19#include <vnet/ip/ip.h>
20#include <vnet/policer/policer.h>
21#include <vnet/policer/police_inlines.h>
22
23/**
24 * IP4 punt policer configuration
25 * we police the punt rate to prevent overloading the host
26 */
27typedef struct ip_punt_policer_t_
28{
29 u32 policer_index;
Brian Russellbaebb222021-01-19 16:48:56 +000030 u32 fq_index;
Neale Rannsd91c1db2017-07-31 02:30:50 -070031} ip_punt_policer_t;
32
33typedef enum ip_punt_policer_next_t_
34{
35 IP_PUNT_POLICER_NEXT_DROP,
36 IP_PUNT_POLICER_N_NEXT,
37} ip_punt_policer_next_t;
38
39typedef struct ip_punt_policer_trace_t_
40{
41 u32 policer_index;
42 u32 next;
43} ip_punt_policer_trace_t;
44
45#define foreach_ip_punt_policer_error \
46_(DROP, "ip punt policer drop")
47
48typedef enum
49{
50#define _(sym,str) IP_PUNT_POLICER_ERROR_##sym,
51 foreach_ip_punt_policer_error
52#undef _
53 IP4_PUNT_POLICER_N_ERROR,
54} ip_punt_policer_error_t;
55
56extern u8 *format_ip_punt_policer_trace (u8 * s, va_list * args);
Brian Russellbaebb222021-01-19 16:48:56 +000057extern vlib_node_registration_t ip4_punt_policer_node;
58extern ip_punt_policer_t ip4_punt_policer_cfg;
59extern vlib_node_registration_t ip6_punt_policer_node;
60extern ip_punt_policer_t ip6_punt_policer_cfg;
Neale Rannsd91c1db2017-07-31 02:30:50 -070061
62/**
63 * IP punt policing node function
64 */
65always_inline uword
66ip_punt_policer (vlib_main_t * vm,
67 vlib_node_runtime_t * node,
68 vlib_frame_t * frame, u8 arc_index, u32 policer_index)
69{
70 u32 *from, *to_next, n_left_from, n_left_to_next, next_index;
71 u64 time_in_policer_periods;
72 vnet_feature_main_t *fm = &feature_main;
73 vnet_feature_config_main_t *cm = &fm->feature_config_mains[arc_index];
74
75 time_in_policer_periods =
76 clib_cpu_time_now () >> POLICER_TICKS_PER_PERIOD_SHIFT;
77
78 from = vlib_frame_vector_args (frame);
79 n_left_from = frame->n_vectors;
80 next_index = node->cached_next_index;
81
82 while (n_left_from > 0)
83 {
84 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
85
86 while (n_left_from >= 4 && n_left_to_next >= 2)
87 {
88 vlib_buffer_t *b0, *b1;
89 u32 next0, next1;
90 u8 act0, act1;
91 u32 bi0, bi1;
92
93 next0 = next1 = 0;
94 bi0 = to_next[0] = from[0];
95 bi1 = to_next[1] = from[1];
96
97 from += 2;
98 n_left_from -= 2;
99 to_next += 2;
100 n_left_to_next -= 2;
101
102 b0 = vlib_get_buffer (vm, bi0);
103 b1 = vlib_get_buffer (vm, bi1);
104
105 vnet_get_config_data (&cm->config_main,
106 &b0->current_config_index, &next0, 0);
107 vnet_get_config_data (&cm->config_main,
108 &b1->current_config_index, &next1, 0);
109
110 act0 = vnet_policer_police (vm, b0,
111 policer_index,
112 time_in_policer_periods,
113 POLICE_CONFORM);
114 act1 = vnet_policer_police (vm, b1,
115 policer_index,
116 time_in_policer_periods,
117 POLICE_CONFORM);
118
119 if (PREDICT_FALSE (act0 == SSE2_QOS_ACTION_DROP))
120 {
121 next0 = IP_PUNT_POLICER_NEXT_DROP;
122 b0->error = node->errors[IP_PUNT_POLICER_ERROR_DROP];
123 }
124 if (PREDICT_FALSE (act1 == SSE2_QOS_ACTION_DROP))
125 {
126 next1 = IP_PUNT_POLICER_NEXT_DROP;
127 b1->error = node->errors[IP_PUNT_POLICER_ERROR_DROP];
128 }
129
130 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
131 {
132 ip_punt_policer_trace_t *t =
133 vlib_add_trace (vm, node, b0, sizeof (*t));
134 t->next = next0;
135 t->policer_index = policer_index;
136 }
137 if (PREDICT_FALSE (b1->flags & VLIB_BUFFER_IS_TRACED))
138 {
139 ip_punt_policer_trace_t *t =
140 vlib_add_trace (vm, node, b1, sizeof (*t));
141 t->next = next1;
142 t->policer_index = policer_index;
143 }
144 vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next,
145 n_left_to_next,
146 bi0, bi1, next0, next1);
147 }
148 while (n_left_from > 0 && n_left_to_next > 0)
149 {
150 vlib_buffer_t *b0;
151 u32 next0;
152 u32 bi0;
153 u8 act0;
154
155 next0 = 0;
156 bi0 = to_next[0] = from[0];
157
158 from += 1;
159 n_left_from -= 1;
160 to_next += 1;
161 n_left_to_next -= 1;
162
163 b0 = vlib_get_buffer (vm, bi0);
164
165 vnet_get_config_data (&cm->config_main,
166 &b0->current_config_index, &next0, 0);
167
168 act0 = vnet_policer_police (vm, b0,
169 policer_index,
170 time_in_policer_periods,
171 POLICE_CONFORM);
172 if (PREDICT_FALSE (act0 == SSE2_QOS_ACTION_DROP))
173 {
174 next0 = IP_PUNT_POLICER_NEXT_DROP;
175 b0->error = node->errors[IP_PUNT_POLICER_ERROR_DROP];
176 }
177
178 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
179 {
180 ip_punt_policer_trace_t *t =
181 vlib_add_trace (vm, node, b0, sizeof (*t));
182 t->next = next0;
183 t->policer_index = policer_index;
184 }
185
186 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
187 n_left_to_next, bi0, next0);
188 }
189 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
190 }
191
192 return frame->n_vectors;
193}
194
195/**
196 * IP4 punt redirect per-rx interface configuration
197 * redirect punted traffic to another location.
198 */
199typedef struct ip_punt_redirect_rx_t_
200{
201 /**
Neale Ranns92207752019-06-03 13:21:40 +0000202 * Node linkage into the FIB graph
Neale Rannsd91c1db2017-07-31 02:30:50 -0700203 */
Neale Ranns92207752019-06-03 13:21:40 +0000204 fib_node_t node;
205
206 fib_protocol_t fproto;
207 fib_forward_chain_type_t payload_type;
208 fib_node_index_t pl;
209 u32 sibling;
Neale Rannsd91c1db2017-07-31 02:30:50 -0700210
211 /**
Neale Ranns92207752019-06-03 13:21:40 +0000212 * redirect forwarding
Neale Rannsd91c1db2017-07-31 02:30:50 -0700213 */
Neale Ranns92207752019-06-03 13:21:40 +0000214 dpo_id_t dpo;
Neale Rannsd91c1db2017-07-31 02:30:50 -0700215} ip_punt_redirect_rx_t;
216
217/**
218 * IP punt redirect configuration
219 */
220typedef struct ip_punt_redirect_t_
221{
Neale Ranns92207752019-06-03 13:21:40 +0000222 ip_punt_redirect_rx_t *pool;
Neale Rannsd91c1db2017-07-31 02:30:50 -0700223
Neale Ranns92207752019-06-03 13:21:40 +0000224 /**
225 * per-RX interface configuration.
226 * sw_if_index = 0 (from which packets are never received) is used to
227 * indicate 'from-any'
228 */
229 index_t *redirect_by_rx_sw_if_index[FIB_PROTOCOL_IP_MAX];
230} ip_punt_redirect_cfg_t;
231
232extern ip_punt_redirect_cfg_t ip_punt_redirect_cfg;
Neale Rannsd91c1db2017-07-31 02:30:50 -0700233
234/**
235 * IP punt redirect next nodes
236 */
237typedef enum ip_punt_redirect_next_t_
238{
239 IP_PUNT_REDIRECT_NEXT_DROP,
240 IP_PUNT_REDIRECT_NEXT_TX,
241 IP_PUNT_REDIRECT_NEXT_ARP,
242 IP_PUNT_REDIRECT_N_NEXT,
243} ip_punt_redirect_next_t;
244
245/**
246 * IP Punt redirect trace
247 */
248typedef struct ip4_punt_redirect_trace_t_
249{
Neale Ranns92207752019-06-03 13:21:40 +0000250 index_t rrxi;
Neale Rannsd91c1db2017-07-31 02:30:50 -0700251 u32 next;
252} ip_punt_redirect_trace_t;
253
254/**
255 * Add a punt redirect entry
256 */
Neale Ranns92207752019-06-03 13:21:40 +0000257extern void ip_punt_redirect_add (fib_protocol_t fproto,
Neale Rannsd91c1db2017-07-31 02:30:50 -0700258 u32 rx_sw_if_index,
Neale Ranns92207752019-06-03 13:21:40 +0000259 fib_forward_chain_type_t ct,
260 fib_route_path_t * rpaths);
261
262extern void ip_punt_redirect_del (fib_protocol_t fproto, u32 rx_sw_if_index);
263extern index_t ip_punt_redirect_find (fib_protocol_t fproto,
264 u32 rx_sw_if_index);
Neale Rannsd91c1db2017-07-31 02:30:50 -0700265extern u8 *format_ip_punt_redirect (u8 * s, va_list * args);
266
267extern u8 *format_ip_punt_redirect_trace (u8 * s, va_list * args);
268
Neale Ranns92207752019-06-03 13:21:40 +0000269typedef walk_rc_t (*ip_punt_redirect_walk_cb_t) (u32 rx_sw_if_index,
270 const ip_punt_redirect_rx_t *
271 redirect, void *arg);
272extern void ip_punt_redirect_walk (fib_protocol_t fproto,
273 ip_punt_redirect_walk_cb_t cb, void *ctx);
Pavel Kotucek609e1212018-11-27 09:59:44 +0100274
Neale Ranns92207752019-06-03 13:21:40 +0000275static_always_inline ip_punt_redirect_rx_t *
276ip_punt_redirect_get (index_t rrxi)
Neale Rannsd91c1db2017-07-31 02:30:50 -0700277{
Neale Ranns92207752019-06-03 13:21:40 +0000278 return (pool_elt_at_index (ip_punt_redirect_cfg.pool, rrxi));
Neale Rannsd91c1db2017-07-31 02:30:50 -0700279}
280
281always_inline uword
282ip_punt_redirect (vlib_main_t * vm,
283 vlib_node_runtime_t * node,
Neale Ranns92207752019-06-03 13:21:40 +0000284 vlib_frame_t * frame, u8 arc_index, fib_protocol_t fproto)
Neale Rannsd91c1db2017-07-31 02:30:50 -0700285{
286 u32 *from, *to_next, n_left_from, n_left_to_next, next_index;
287 vnet_feature_main_t *fm = &feature_main;
288 vnet_feature_config_main_t *cm = &fm->feature_config_mains[arc_index];
Neale Ranns92207752019-06-03 13:21:40 +0000289 index_t *redirects;
Neale Rannsd91c1db2017-07-31 02:30:50 -0700290
291 from = vlib_frame_vector_args (frame);
292 n_left_from = frame->n_vectors;
293 next_index = node->cached_next_index;
Neale Ranns92207752019-06-03 13:21:40 +0000294 redirects = ip_punt_redirect_cfg.redirect_by_rx_sw_if_index[fproto];
Neale Rannsd91c1db2017-07-31 02:30:50 -0700295
296 while (n_left_from > 0)
297 {
298 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
299
300 while (n_left_from > 0 && n_left_to_next > 0)
301 {
Neale Ranns92207752019-06-03 13:21:40 +0000302 u32 rx_sw_if_index0, rrxi0;
Neale Rannsd91c1db2017-07-31 02:30:50 -0700303 ip_punt_redirect_rx_t *rrx0;
304 vlib_buffer_t *b0;
305 u32 next0;
306 u32 bi0;
307
Neale Ranns92207752019-06-03 13:21:40 +0000308 rrxi0 = INDEX_INVALID;
Neale Rannsd91c1db2017-07-31 02:30:50 -0700309 next0 = 0;
310 bi0 = to_next[0] = from[0];
311
312 from += 1;
313 n_left_from -= 1;
314 to_next += 1;
315 n_left_to_next -= 1;
316
317 b0 = vlib_get_buffer (vm, bi0);
318
319 vnet_get_config_data (&cm->config_main,
320 &b0->current_config_index, &next0, 0);
321
322 rx_sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
323
Neale Ranns92207752019-06-03 13:21:40 +0000324 /*
325 * If config exists for this particular RX interface use it,
326 * else use the default (at RX = 0)
327 */
328 if (vec_len (redirects) > rx_sw_if_index0)
Neale Rannsd91c1db2017-07-31 02:30:50 -0700329 {
Neale Ranns92207752019-06-03 13:21:40 +0000330 rrxi0 = redirects[rx_sw_if_index0];
331 if (INDEX_INVALID == rrxi0)
332 rrxi0 = redirects[0];
Neale Rannsd91c1db2017-07-31 02:30:50 -0700333 }
Neale Ranns92207752019-06-03 13:21:40 +0000334 else if (vec_len (redirects) >= 1)
335 rrxi0 = redirects[0];
336
337 if (PREDICT_TRUE (INDEX_INVALID != rrxi0))
Neale Rannsd91c1db2017-07-31 02:30:50 -0700338 {
Neale Ranns92207752019-06-03 13:21:40 +0000339 rrx0 = ip_punt_redirect_get (rrxi0);
340 vnet_buffer (b0)->ip.adj_index[VLIB_TX] = rrx0->dpo.dpoi_index;
341 next0 = rrx0->dpo.dpoi_next_node;
Neale Rannsd91c1db2017-07-31 02:30:50 -0700342 }
343
344 if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
345 {
346 ip_punt_redirect_trace_t *t =
347 vlib_add_trace (vm, node, b0, sizeof (*t));
348 t->next = next0;
Neale Ranns92207752019-06-03 13:21:40 +0000349 t->rrxi = rrxi0;
Neale Rannsd91c1db2017-07-31 02:30:50 -0700350 }
351
352 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
353 n_left_to_next, bi0, next0);
354 }
355
356 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
357 }
358
359 return frame->n_vectors;
360}
361
362always_inline uword
363ip_drop_or_punt (vlib_main_t * vm,
364 vlib_node_runtime_t * node,
365 vlib_frame_t * frame, u8 arc_index)
366{
367 u32 *from, *to_next, n_left_from, n_left_to_next, next_index;
368
369 from = vlib_frame_vector_args (frame);
370 n_left_from = frame->n_vectors;
371 next_index = node->cached_next_index;
372
373 while (n_left_from > 0)
374 {
375 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
376
377 while (n_left_from >= 8 && n_left_to_next >= 4)
378 {
379 vlib_buffer_t *b0, *b1, *b2, *b3;
380 u32 next0, next1, next2, next3;
381 u32 bi0, bi1, bi2, bi3;
382
383 next0 = next1 = next2 = next3 = 0;
384
385 /* Prefetch next iteration. */
386 {
387 vlib_buffer_t *p4, *p5, *p6, *p7;
388
389 p4 = vlib_get_buffer (vm, from[4]);
390 p5 = vlib_get_buffer (vm, from[5]);
391 p6 = vlib_get_buffer (vm, from[6]);
392 p7 = vlib_get_buffer (vm, from[7]);
393
394 vlib_prefetch_buffer_header (p4, LOAD);
395 vlib_prefetch_buffer_header (p5, LOAD);
396 vlib_prefetch_buffer_header (p6, LOAD);
397 vlib_prefetch_buffer_header (p7, LOAD);
398 }
399
400 bi0 = to_next[0] = from[0];
401 bi1 = to_next[1] = from[1];
402 bi2 = to_next[2] = from[2];
403 bi3 = to_next[3] = from[3];
404
405 from += 4;
406 n_left_from -= 4;
407 to_next += 4;
408 n_left_to_next -= 4;
409
410 b0 = vlib_get_buffer (vm, bi0);
411 b1 = vlib_get_buffer (vm, bi1);
412 b2 = vlib_get_buffer (vm, bi2);
413 b3 = vlib_get_buffer (vm, bi3);
414
415 /* punt and drop features are not associated with a given interface
416 * so the special index 0 is used */
417 vnet_feature_arc_start (arc_index, 0, &next0, b0);
418 vnet_feature_arc_start (arc_index, 0, &next1, b1);
419 vnet_feature_arc_start (arc_index, 0, &next2, b2);
420 vnet_feature_arc_start (arc_index, 0, &next3, b3);
421
422 vlib_validate_buffer_enqueue_x4 (vm, node, next_index,
423 to_next, n_left_to_next,
424 bi0, bi1, bi2, bi3,
425 next0, next1, next2, next3);
426 }
427
428 while (n_left_from > 0 && n_left_to_next > 0)
429 {
430 vlib_buffer_t *b0;
431 u32 next0;
432 u32 bi0;
433
434 next0 = 0;
435 bi0 = to_next[0] = from[0];
436
437 from += 1;
438 n_left_from -= 1;
439 to_next += 1;
440 n_left_to_next -= 1;
441
442 b0 = vlib_get_buffer (vm, bi0);
443
444 vnet_feature_arc_start (arc_index, 0, &next0, b0);
445
446 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
447 n_left_to_next, bi0, next0);
448 }
449 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
450 }
451
452 return frame->n_vectors;
453}
454
455#endif
456
457/*
458 * fd.io coding-style-patch-verification: ON
459 *
460 * Local Variables:
461 * eval: (c-set-style "gnu")
462 * End:
463 */