blob: 457dd09fd126a2ed2906acd3ef2094c0e925d95a [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -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 */
Damjan Marione936bbe2016-02-25 23:17:38 +010015
16#include <stdint.h>
17
Ed Warnickecb9cada2015-12-08 15:45:58 -070018#include <vlib/vlib.h>
19#include <vnet/vnet.h>
20#include <vnet/policer/policer.h>
Matus Fabian4ac74c92016-05-31 07:33:29 -070021#include <vnet/ip/ip.h>
Matus Fabian70e6a8d2016-06-20 08:10:42 -070022#include <vnet/classify/policer_classify.h>
23#include <vnet/classify/vnet_classify.h>
Matus Fabian4ac74c92016-05-31 07:33:29 -070024
25#define IP4_NON_DSCP_BITS 0x03
26#define IP4_DSCP_SHIFT 2
27#define IP6_NON_DSCP_BITS 0xf03fffff
28#define IP6_DSCP_SHIFT 22
Ed Warnickecb9cada2015-12-08 15:45:58 -070029
30/* Dispatch functions meant to be instantiated elsewhere */
31
Damjan Marion3891cd82016-10-27 10:27:00 +020032typedef struct
33{
Ed Warnickecb9cada2015-12-08 15:45:58 -070034 u32 next_index;
35 u32 sw_if_index;
36 u32 policer_index;
37} vnet_policer_trace_t;
38
39/* packet trace format function */
Damjan Marion3891cd82016-10-27 10:27:00 +020040static u8 *
41format_policer_trace (u8 * s, va_list * args)
Ed Warnickecb9cada2015-12-08 15:45:58 -070042{
43 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
44 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
Damjan Marion3891cd82016-10-27 10:27:00 +020045 vnet_policer_trace_t *t = va_arg (*args, vnet_policer_trace_t *);
46
Ed Warnickecb9cada2015-12-08 15:45:58 -070047 s = format (s, "VNET_POLICER: sw_if_index %d policer_index %d next %d",
Damjan Marion3891cd82016-10-27 10:27:00 +020048 t->sw_if_index, t->policer_index, t->next_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -070049 return s;
50}
51
52#define foreach_vnet_policer_error \
53_(TRANSMIT, "Packets Transmitted") \
54_(DROP, "Packets Dropped")
55
Damjan Marion3891cd82016-10-27 10:27:00 +020056typedef enum
57{
Ed Warnickecb9cada2015-12-08 15:45:58 -070058#define _(sym,str) VNET_POLICER_ERROR_##sym,
59 foreach_vnet_policer_error
60#undef _
Damjan Marion3891cd82016-10-27 10:27:00 +020061 VNET_POLICER_N_ERROR,
Ed Warnickecb9cada2015-12-08 15:45:58 -070062} vnet_policer_error_t;
63
Damjan Marion3891cd82016-10-27 10:27:00 +020064static char *vnet_policer_error_strings[] = {
Ed Warnickecb9cada2015-12-08 15:45:58 -070065#define _(sym,string) string,
66 foreach_vnet_policer_error
67#undef _
68};
69
Damjan Marion3891cd82016-10-27 10:27:00 +020070static_always_inline void
71vnet_policer_mark (vlib_buffer_t * b, u8 dscp)
Matus Fabian4ac74c92016-05-31 07:33:29 -070072{
Damjan Marion3891cd82016-10-27 10:27:00 +020073 ethernet_header_t *eh;
74 ip4_header_t *ip4h;
75 ip6_header_t *ip6h;
Matus Fabian4ac74c92016-05-31 07:33:29 -070076 u16 type;
77
78 eh = (ethernet_header_t *) b->data;
79 type = clib_net_to_host_u16 (eh->type);
80
Damjan Marion3891cd82016-10-27 10:27:00 +020081 if (PREDICT_TRUE (type == ETHERNET_TYPE_IP4))
Matus Fabian4ac74c92016-05-31 07:33:29 -070082 {
Damjan Marion3891cd82016-10-27 10:27:00 +020083 ip4h = (ip4_header_t *) & (b->data[sizeof (ethernet_header_t)]);;
Matus Fabian4ac74c92016-05-31 07:33:29 -070084 ip4h->tos &= IP4_NON_DSCP_BITS;
85 ip4h->tos |= dscp << IP4_DSCP_SHIFT;
86 ip4h->checksum = ip4_header_checksum (ip4h);
87 }
88 else
89 {
Damjan Marion3891cd82016-10-27 10:27:00 +020090 if (PREDICT_TRUE (type == ETHERNET_TYPE_IP6))
91 {
92 ip6h = (ip6_header_t *) & (b->data[sizeof (ethernet_header_t)]);
93 ip6h->ip_version_traffic_class_and_flow_label &=
94 clib_host_to_net_u32 (IP6_NON_DSCP_BITS);
95 ip6h->ip_version_traffic_class_and_flow_label |=
96 clib_host_to_net_u32 (dscp << IP6_DSCP_SHIFT);
97 }
Matus Fabian4ac74c92016-05-31 07:33:29 -070098 }
99}
100
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700101static_always_inline
Damjan Marion3891cd82016-10-27 10:27:00 +0200102 u8 vnet_policer_police (vlib_main_t * vm,
103 vlib_buffer_t * b,
104 u32 policer_index,
105 u64 time_in_policer_periods,
106 policer_result_e packet_color)
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700107{
108 u8 act;
109 u32 len;
110 u32 col;
111 policer_read_response_type_st *pol;
Damjan Marion3891cd82016-10-27 10:27:00 +0200112 vnet_policer_main_t *pm = &vnet_policer_main;
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700113
114 len = vlib_buffer_length_in_chain (vm, b);
Damjan Marion3891cd82016-10-27 10:27:00 +0200115 pol = &pm->policers[policer_index];
116 col = vnet_police_packet (pol, len, packet_color, time_in_policer_periods);
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700117 act = pol->action[col];
Damjan Marion3891cd82016-10-27 10:27:00 +0200118 if (PREDICT_TRUE (act == SSE2_QOS_ACTION_MARK_AND_TRANSMIT))
119 vnet_policer_mark (b, pol->mark_dscp[col]);
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700120
121 return act;
Damjan Marion3891cd82016-10-27 10:27:00 +0200122}
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700123
Damjan Marion3891cd82016-10-27 10:27:00 +0200124static inline uword
125vnet_policer_inline (vlib_main_t * vm,
126 vlib_node_runtime_t * node,
127 vlib_frame_t * frame, vnet_policer_index_t which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700128{
Damjan Marion3891cd82016-10-27 10:27:00 +0200129 u32 n_left_from, *from, *to_next;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700130 vnet_policer_next_t next_index;
Damjan Marion3891cd82016-10-27 10:27:00 +0200131 vnet_policer_main_t *pm = &vnet_policer_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700132 u64 time_in_policer_periods;
133 u32 transmitted = 0;
134
Damjan Marion3891cd82016-10-27 10:27:00 +0200135 time_in_policer_periods =
136 clib_cpu_time_now () >> POLICER_TICKS_PER_PERIOD_SHIFT;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700137
138 from = vlib_frame_vector_args (frame);
139 n_left_from = frame->n_vectors;
140 next_index = node->cached_next_index;
141
142 while (n_left_from > 0)
143 {
144 u32 n_left_to_next;
145
Damjan Marion3891cd82016-10-27 10:27:00 +0200146 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700147
148 while (n_left_from >= 4 && n_left_to_next >= 2)
149 {
Damjan Marion3891cd82016-10-27 10:27:00 +0200150 u32 bi0, bi1;
151 vlib_buffer_t *b0, *b1;
152 u32 next0, next1;
153 u32 sw_if_index0, sw_if_index1;
154 u32 pi0 = 0, pi1 = 0;
155 u8 act0, act1;
156
Ed Warnickecb9cada2015-12-08 15:45:58 -0700157 /* Prefetch next iteration. */
158 {
Damjan Marion3891cd82016-10-27 10:27:00 +0200159 vlib_buffer_t *b2, *b3;
160
Ed Warnickecb9cada2015-12-08 15:45:58 -0700161 b2 = vlib_get_buffer (vm, from[2]);
162 b3 = vlib_get_buffer (vm, from[3]);
Damjan Marion3891cd82016-10-27 10:27:00 +0200163
Ed Warnickecb9cada2015-12-08 15:45:58 -0700164 vlib_prefetch_buffer_header (b2, LOAD);
165 vlib_prefetch_buffer_header (b3, LOAD);
166 }
167
Damjan Marion3891cd82016-10-27 10:27:00 +0200168 /* speculatively enqueue b0 and b1 to the current next frame */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700169 to_next[0] = bi0 = from[0];
170 to_next[1] = bi1 = from[1];
171 from += 2;
172 to_next += 2;
173 n_left_from -= 2;
174 n_left_to_next -= 2;
175
176 b0 = vlib_get_buffer (vm, bi0);
177 b1 = vlib_get_buffer (vm, bi1);
178
Damjan Marion3891cd82016-10-27 10:27:00 +0200179 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
180 next0 = VNET_POLICER_NEXT_TRANSMIT;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700181
Damjan Marion3891cd82016-10-27 10:27:00 +0200182 sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
183 next1 = VNET_POLICER_NEXT_TRANSMIT;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700184
185
Damjan Marion3891cd82016-10-27 10:27:00 +0200186 if (which == VNET_POLICER_INDEX_BY_SW_IF_INDEX)
187 {
188 pi0 = pm->policer_index_by_sw_if_index[sw_if_index0];
189 pi1 = pm->policer_index_by_sw_if_index[sw_if_index1];
190 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700191
Damjan Marion3891cd82016-10-27 10:27:00 +0200192 if (which == VNET_POLICER_INDEX_BY_OPAQUE)
193 {
194 pi0 = vnet_buffer (b0)->policer.index;
195 pi1 = vnet_buffer (b1)->policer.index;
196 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700197
Damjan Marion3891cd82016-10-27 10:27:00 +0200198 if (which == VNET_POLICER_INDEX_BY_EITHER)
199 {
200 pi0 = vnet_buffer (b0)->policer.index;
201 pi0 = (pi0 != ~0) ? pi0 :
202 pm->policer_index_by_sw_if_index[sw_if_index0];
203 pi1 = vnet_buffer (b1)->policer.index;
204 pi1 = (pi1 != ~0) ? pi1 :
205 pm->policer_index_by_sw_if_index[sw_if_index1];
206 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700207
Damjan Marion3891cd82016-10-27 10:27:00 +0200208 act0 = vnet_policer_police (vm, b0, pi0, time_in_policer_periods,
209 POLICE_CONFORM /* no chaining */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700210
Damjan Marion3891cd82016-10-27 10:27:00 +0200211 act1 = vnet_policer_police (vm, b1, pi1, time_in_policer_periods,
212 POLICE_CONFORM /* no chaining */ );
Matus Fabian4ac74c92016-05-31 07:33:29 -0700213
Damjan Marion3891cd82016-10-27 10:27:00 +0200214 if (PREDICT_FALSE (act0 == SSE2_QOS_ACTION_DROP)) /* drop action */
215 {
216 next0 = VNET_POLICER_NEXT_DROP;
217 b0->error = node->errors[VNET_POLICER_ERROR_DROP];
218 }
219 else /* transmit or mark-and-transmit action */
220 {
221 transmitted++;
222 }
Matus Fabian4ac74c92016-05-31 07:33:29 -0700223
Damjan Marion3891cd82016-10-27 10:27:00 +0200224 if (PREDICT_FALSE (act1 == SSE2_QOS_ACTION_DROP)) /* drop action */
225 {
226 next1 = VNET_POLICER_NEXT_DROP;
227 b1->error = node->errors[VNET_POLICER_ERROR_DROP];
228 }
229 else /* transmit or mark-and-transmit action */
230 {
231 transmitted++;
232 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700233
234
Damjan Marion3891cd82016-10-27 10:27:00 +0200235 if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
236 {
237 if (b0->flags & VLIB_BUFFER_IS_TRACED)
238 {
239 vnet_policer_trace_t *t =
240 vlib_add_trace (vm, node, b0, sizeof (*t));
241 t->sw_if_index = sw_if_index0;
242 t->next_index = next0;
243 }
244 if (b1->flags & VLIB_BUFFER_IS_TRACED)
245 {
246 vnet_policer_trace_t *t =
247 vlib_add_trace (vm, node, b1, sizeof (*t));
248 t->sw_if_index = sw_if_index1;
249 t->next_index = next1;
250 }
251 }
252
253 /* verify speculative enqueues, maybe switch current next frame */
254 vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
255 to_next, n_left_to_next,
256 bi0, bi1, next0, next1);
257 }
258
Ed Warnickecb9cada2015-12-08 15:45:58 -0700259 while (n_left_from > 0 && n_left_to_next > 0)
260 {
Damjan Marion3891cd82016-10-27 10:27:00 +0200261 u32 bi0;
262 vlib_buffer_t *b0;
263 u32 next0;
264 u32 sw_if_index0;
265 u32 pi0 = 0;
266 u8 act0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700267
268 bi0 = from[0];
269 to_next[0] = bi0;
270 from += 1;
271 to_next += 1;
272 n_left_from -= 1;
273 n_left_to_next -= 1;
274
275 b0 = vlib_get_buffer (vm, bi0);
276
Damjan Marion3891cd82016-10-27 10:27:00 +0200277 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
278 next0 = VNET_POLICER_NEXT_TRANSMIT;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700279
Damjan Marion3891cd82016-10-27 10:27:00 +0200280 if (which == VNET_POLICER_INDEX_BY_SW_IF_INDEX)
281 pi0 = pm->policer_index_by_sw_if_index[sw_if_index0];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700282
Damjan Marion3891cd82016-10-27 10:27:00 +0200283 if (which == VNET_POLICER_INDEX_BY_OPAQUE)
284 pi0 = vnet_buffer (b0)->policer.index;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700285
Damjan Marion3891cd82016-10-27 10:27:00 +0200286 if (which == VNET_POLICER_INDEX_BY_EITHER)
287 {
288 pi0 = vnet_buffer (b0)->policer.index;
289 pi0 = (pi0 != ~0) ? pi0 :
290 pm->policer_index_by_sw_if_index[sw_if_index0];
291 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700292
Damjan Marion3891cd82016-10-27 10:27:00 +0200293 act0 = vnet_policer_police (vm, b0, pi0, time_in_policer_periods,
294 POLICE_CONFORM /* no chaining */ );
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700295
Damjan Marion3891cd82016-10-27 10:27:00 +0200296 if (PREDICT_FALSE (act0 == SSE2_QOS_ACTION_DROP)) /* drop action */
297 {
298 next0 = VNET_POLICER_NEXT_DROP;
299 b0->error = node->errors[VNET_POLICER_ERROR_DROP];
300 }
301 else /* transmit or mark-and-transmit action */
302 {
303 transmitted++;
304 }
305
306 if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
307 && (b0->flags & VLIB_BUFFER_IS_TRACED)))
308 {
309 vnet_policer_trace_t *t =
310 vlib_add_trace (vm, node, b0, sizeof (*t));
311 t->sw_if_index = sw_if_index0;
312 t->next_index = next0;
313 t->policer_index = pi0;
314 }
315
316 /* verify speculative enqueue, maybe switch current next frame */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700317 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
318 to_next, n_left_to_next,
319 bi0, next0);
320 }
321
322 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
323 }
324
Damjan Marion3891cd82016-10-27 10:27:00 +0200325 vlib_node_increment_counter (vm, node->node_index,
326 VNET_POLICER_ERROR_TRANSMIT, transmitted);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700327 return frame->n_vectors;
328}
329
Damjan Marion3891cd82016-10-27 10:27:00 +0200330uword
331vnet_policer_by_sw_if_index (vlib_main_t * vm,
332 vlib_node_runtime_t * node, vlib_frame_t * frame)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700333{
Damjan Marion3891cd82016-10-27 10:27:00 +0200334 return vnet_policer_inline (vm, node, frame,
335 VNET_POLICER_INDEX_BY_SW_IF_INDEX);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700336}
337
Damjan Marion3891cd82016-10-27 10:27:00 +0200338uword
339vnet_policer_by_opaque (vlib_main_t * vm,
340 vlib_node_runtime_t * node, vlib_frame_t * frame)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700341{
Damjan Marion3891cd82016-10-27 10:27:00 +0200342 return vnet_policer_inline (vm, node, frame, VNET_POLICER_INDEX_BY_OPAQUE);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700343}
344
Damjan Marion3891cd82016-10-27 10:27:00 +0200345uword
346vnet_policer_by_either (vlib_main_t * vm,
347 vlib_node_runtime_t * node, vlib_frame_t * frame)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700348{
Damjan Marion3891cd82016-10-27 10:27:00 +0200349 return vnet_policer_inline (vm, node, frame, VNET_POLICER_INDEX_BY_EITHER);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700350}
351
Damjan Marion3891cd82016-10-27 10:27:00 +0200352void
353vnet_policer_node_funcs_reference (void)
354{
355}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700356
357
358#define TEST_CODE 1
359
360#ifdef TEST_CODE
361
Damjan Marion3891cd82016-10-27 10:27:00 +0200362/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700363VLIB_REGISTER_NODE (policer_by_sw_if_index_node, static) = {
364 .function = vnet_policer_by_sw_if_index,
365 .name = "policer-by-sw-if-index",
366 .vector_size = sizeof (u32),
367 .format_trace = format_policer_trace,
368 .type = VLIB_NODE_TYPE_INTERNAL,
Damjan Marion3891cd82016-10-27 10:27:00 +0200369
Ed Warnickecb9cada2015-12-08 15:45:58 -0700370 .n_errors = ARRAY_LEN(vnet_policer_error_strings),
371 .error_strings = vnet_policer_error_strings,
Damjan Marion3891cd82016-10-27 10:27:00 +0200372
Ed Warnickecb9cada2015-12-08 15:45:58 -0700373 .n_next_nodes = VNET_POLICER_N_NEXT,
374
375 /* edit / add dispositions here */
376 .next_nodes = {
377 [VNET_POLICER_NEXT_TRANSMIT] = "ethernet-input",
378 [VNET_POLICER_NEXT_DROP] = "error-drop",
379 },
380};
381
Damjan Marion1c80e832016-05-11 23:07:18 +0200382VLIB_NODE_FUNCTION_MULTIARCH (policer_by_sw_if_index_node,
383 vnet_policer_by_sw_if_index);
Damjan Marion3891cd82016-10-27 10:27:00 +0200384/* *INDENT-ON* */
Damjan Marion1c80e832016-05-11 23:07:18 +0200385
Ed Warnickecb9cada2015-12-08 15:45:58 -0700386
Damjan Marion3891cd82016-10-27 10:27:00 +0200387int
388test_policer_add_del (u32 rx_sw_if_index, u8 * config_name, int is_add)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700389{
Damjan Marion3891cd82016-10-27 10:27:00 +0200390 vnet_policer_main_t *pm = &vnet_policer_main;
391 policer_read_response_type_st *template;
392 policer_read_response_type_st *policer;
393 vnet_hw_interface_t *rxhi;
394 uword *p;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700395
396 rxhi = vnet_get_sup_hw_interface (pm->vnet_main, rx_sw_if_index);
397
398 /* Make sure caller didn't pass a vlan subif, etc. */
399 if (rxhi->sw_if_index != rx_sw_if_index)
400 return VNET_API_ERROR_INVALID_SW_IF_INDEX;
401
402 if (is_add)
403 {
Damjan Marion3891cd82016-10-27 10:27:00 +0200404
Ed Warnickecb9cada2015-12-08 15:45:58 -0700405 p = hash_get_mem (pm->policer_config_by_name, config_name);
406
407 if (p == 0)
Damjan Marion3891cd82016-10-27 10:27:00 +0200408 return -2;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700409
410 template = pool_elt_at_index (pm->policer_templates, p[0]);
411
Damjan Marion3891cd82016-10-27 10:27:00 +0200412 vnet_hw_interface_rx_redirect_to_node
413 (pm->vnet_main, rxhi->hw_if_index, policer_by_sw_if_index_node.index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700414
415 pool_get_aligned (pm->policers, policer, CLIB_CACHE_LINE_BYTES);
416
417 policer[0] = template[0];
418
419 vec_validate (pm->policer_index_by_sw_if_index, rx_sw_if_index);
Damjan Marion3891cd82016-10-27 10:27:00 +0200420 pm->policer_index_by_sw_if_index[rx_sw_if_index]
421 = policer - pm->policers;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700422 }
423 else
424 {
425 u32 pi;
Damjan Marion3891cd82016-10-27 10:27:00 +0200426 vnet_hw_interface_rx_redirect_to_node (pm->vnet_main,
427 rxhi->hw_if_index,
428 ~0 /* disable */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700429
430 pi = pm->policer_index_by_sw_if_index[rx_sw_if_index];
431 pm->policer_index_by_sw_if_index[rx_sw_if_index] = ~0;
432 pool_put_index (pm->policers, pi);
433 }
Damjan Marion3891cd82016-10-27 10:27:00 +0200434
Ed Warnickecb9cada2015-12-08 15:45:58 -0700435 return 0;
436}
437
438static clib_error_t *
439test_policer_command_fn (vlib_main_t * vm,
Damjan Marion3891cd82016-10-27 10:27:00 +0200440 unformat_input_t * input, vlib_cli_command_t * cmd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700441{
Damjan Marion3891cd82016-10-27 10:27:00 +0200442 vnet_policer_main_t *pm = &vnet_policer_main;
443 unformat_input_t _line_input, *line_input = &_line_input;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700444 u32 rx_sw_if_index;
445 int rv;
Damjan Marion3891cd82016-10-27 10:27:00 +0200446 u8 *config_name = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700447 int rx_set = 0;
448 int is_add = 1;
449 int is_show = 0;
Billy McFalla9a20e72017-02-15 11:39:12 -0500450 clib_error_t *error = NULL;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700451
452 /* Get a line of input. */
Damjan Marion3891cd82016-10-27 10:27:00 +0200453 if (!unformat_user (input, unformat_line_input, line_input))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700454 return 0;
455
456 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
457 {
458 if (unformat (line_input, "intfc %U", unformat_vnet_sw_interface,
Damjan Marion3891cd82016-10-27 10:27:00 +0200459 pm->vnet_main, &rx_sw_if_index))
460 rx_set = 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700461 else if (unformat (line_input, "show"))
Damjan Marion3891cd82016-10-27 10:27:00 +0200462 is_show = 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700463 else if (unformat (line_input, "policer %s", &config_name))
Damjan Marion3891cd82016-10-27 10:27:00 +0200464 ;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700465 else if (unformat (line_input, "del"))
Damjan Marion3891cd82016-10-27 10:27:00 +0200466 is_add = 0;
467 else
468 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700469 }
470
471 if (rx_set == 0)
Billy McFalla9a20e72017-02-15 11:39:12 -0500472 {
473 error = clib_error_return (0, "interface not set");
474 goto done;
475 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700476
477 if (is_show)
478 {
479 u32 pi = pm->policer_index_by_sw_if_index[rx_sw_if_index];
Damjan Marion3891cd82016-10-27 10:27:00 +0200480 policer_read_response_type_st *policer;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700481 policer = pool_elt_at_index (pm->policers, pi);
Damjan Marion3891cd82016-10-27 10:27:00 +0200482
Ed Warnickecb9cada2015-12-08 15:45:58 -0700483 vlib_cli_output (vm, "%U", format_policer_instance, policer);
Billy McFalla9a20e72017-02-15 11:39:12 -0500484 goto done;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700485 }
486
487 if (is_add && config_name == 0)
488 {
Billy McFalla9a20e72017-02-15 11:39:12 -0500489 error = clib_error_return (0, "policer config name required");
490 goto done;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700491 }
492
493 rv = test_policer_add_del (rx_sw_if_index, config_name, is_add);
494
495 switch (rv)
496 {
497 case 0:
498 break;
499
500 default:
Billy McFalla9a20e72017-02-15 11:39:12 -0500501 error = clib_error_return
Damjan Marion3891cd82016-10-27 10:27:00 +0200502 (0, "WARNING: vnet_vnet_policer_add_del returned %d", rv);
Billy McFalla9a20e72017-02-15 11:39:12 -0500503 goto done;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700504 }
Damjan Marion3891cd82016-10-27 10:27:00 +0200505
Billy McFalla9a20e72017-02-15 11:39:12 -0500506done:
507 unformat_free (line_input);
508
509 return error;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700510}
511
Damjan Marion3891cd82016-10-27 10:27:00 +0200512/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700513VLIB_CLI_COMMAND (test_patch_command, static) = {
514 .path = "test policer",
Damjan Marion3891cd82016-10-27 10:27:00 +0200515 .short_help =
Ed Warnickecb9cada2015-12-08 15:45:58 -0700516 "intfc <intfc> policer <policer-config-name> [del]",
517 .function = test_policer_command_fn,
518};
Damjan Marion3891cd82016-10-27 10:27:00 +0200519/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700520
521#endif /* TEST_CODE */
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700522
523
Damjan Marion3891cd82016-10-27 10:27:00 +0200524typedef struct
525{
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700526 u32 sw_if_index;
527 u32 next_index;
528 u32 table_index;
529 u32 offset;
530 u32 policer_index;
531} policer_classify_trace_t;
532
533static u8 *
534format_policer_classify_trace (u8 * s, va_list * args)
535{
536 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
537 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
Damjan Marion3891cd82016-10-27 10:27:00 +0200538 policer_classify_trace_t *t = va_arg (*args, policer_classify_trace_t *);
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700539
540 s = format (s, "POLICER_CLASSIFY: sw_if_index %d next %d table %d offset %d"
Damjan Marion3891cd82016-10-27 10:27:00 +0200541 " policer_index %d",
542 t->sw_if_index, t->next_index, t->table_index, t->offset,
543 t->policer_index);
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700544 return s;
545}
546
547#define foreach_policer_classify_error \
548_(MISS, "Policer classify misses") \
549_(HIT, "Policer classify hits") \
550_(CHAIN_HIT, "Polcier classify hits after chain walk") \
551_(DROP, "Policer classify action drop")
552
Damjan Marion3891cd82016-10-27 10:27:00 +0200553typedef enum
554{
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700555#define _(sym,str) POLICER_CLASSIFY_ERROR_##sym,
556 foreach_policer_classify_error
557#undef _
Damjan Marion3891cd82016-10-27 10:27:00 +0200558 POLICER_CLASSIFY_N_ERROR,
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700559} policer_classify_error_t;
560
Damjan Marion3891cd82016-10-27 10:27:00 +0200561static char *policer_classify_error_strings[] = {
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700562#define _(sym,string) string,
563 foreach_policer_classify_error
564#undef _
565};
566
567static inline uword
568policer_classify_inline (vlib_main_t * vm,
Damjan Marion3891cd82016-10-27 10:27:00 +0200569 vlib_node_runtime_t * node,
570 vlib_frame_t * frame,
571 policer_classify_table_id_t tid)
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700572{
Damjan Marion3891cd82016-10-27 10:27:00 +0200573 u32 n_left_from, *from, *to_next;
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700574 policer_classify_next_index_t next_index;
Damjan Marion3891cd82016-10-27 10:27:00 +0200575 policer_classify_main_t *pcm = &policer_classify_main;
576 vnet_classify_main_t *vcm = pcm->vnet_classify_main;
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700577 f64 now = vlib_time_now (vm);
578 u32 hits = 0;
579 u32 misses = 0;
580 u32 chain_hits = 0;
581 u32 drop = 0;
582 u32 n_next_nodes;
583 u64 time_in_policer_periods;
584
585 time_in_policer_periods =
Damjan Marion3891cd82016-10-27 10:27:00 +0200586 clib_cpu_time_now () >> POLICER_TICKS_PER_PERIOD_SHIFT;
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700587
588 n_next_nodes = node->n_next_nodes;
589
590 from = vlib_frame_vector_args (frame);
591 n_left_from = frame->n_vectors;
592
593 /* First pass: compute hashes */
594 while (n_left_from > 2)
595 {
Damjan Marion3891cd82016-10-27 10:27:00 +0200596 vlib_buffer_t *b0, *b1;
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700597 u32 bi0, bi1;
Damjan Marion3891cd82016-10-27 10:27:00 +0200598 u8 *h0, *h1;
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700599 u32 sw_if_index0, sw_if_index1;
600 u32 table_index0, table_index1;
Damjan Marion3891cd82016-10-27 10:27:00 +0200601 vnet_classify_table_t *t0, *t1;
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700602
603 /* Prefetch next iteration */
604 {
Damjan Marion3891cd82016-10-27 10:27:00 +0200605 vlib_buffer_t *p1, *p2;
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700606
Damjan Marion3891cd82016-10-27 10:27:00 +0200607 p1 = vlib_get_buffer (vm, from[1]);
608 p2 = vlib_get_buffer (vm, from[2]);
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700609
Damjan Marion3891cd82016-10-27 10:27:00 +0200610 vlib_prefetch_buffer_header (p1, STORE);
611 CLIB_PREFETCH (p1->data, CLIB_CACHE_LINE_BYTES, STORE);
612 vlib_prefetch_buffer_header (p2, STORE);
613 CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700614 }
615
616 bi0 = from[0];
617 b0 = vlib_get_buffer (vm, bi0);
618 h0 = b0->data;
619
620 bi1 = from[1];
621 b1 = vlib_get_buffer (vm, bi1);
622 h1 = b1->data;
623
624 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
Damjan Marion3891cd82016-10-27 10:27:00 +0200625 table_index0 =
626 pcm->classify_table_index_by_sw_if_index[tid][sw_if_index0];
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700627
628 sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
Damjan Marion3891cd82016-10-27 10:27:00 +0200629 table_index1 =
630 pcm->classify_table_index_by_sw_if_index[tid][sw_if_index1];
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700631
632 t0 = pool_elt_at_index (vcm->tables, table_index0);
633
634 t1 = pool_elt_at_index (vcm->tables, table_index1);
635
Damjan Marion3891cd82016-10-27 10:27:00 +0200636 vnet_buffer (b0)->l2_classify.hash =
637 vnet_classify_hash_packet (t0, (u8 *) h0);
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700638
Damjan Marion3891cd82016-10-27 10:27:00 +0200639 vnet_classify_prefetch_bucket (t0, vnet_buffer (b0)->l2_classify.hash);
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700640
Damjan Marion3891cd82016-10-27 10:27:00 +0200641 vnet_buffer (b1)->l2_classify.hash =
642 vnet_classify_hash_packet (t1, (u8 *) h1);
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700643
Damjan Marion3891cd82016-10-27 10:27:00 +0200644 vnet_classify_prefetch_bucket (t1, vnet_buffer (b1)->l2_classify.hash);
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700645
Damjan Marion3891cd82016-10-27 10:27:00 +0200646 vnet_buffer (b0)->l2_classify.table_index = table_index0;
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700647
Damjan Marion3891cd82016-10-27 10:27:00 +0200648 vnet_buffer (b1)->l2_classify.table_index = table_index1;
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700649
650 from += 2;
651 n_left_from -= 2;
652 }
653
654 while (n_left_from > 0)
655 {
Damjan Marion3891cd82016-10-27 10:27:00 +0200656 vlib_buffer_t *b0;
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700657 u32 bi0;
Damjan Marion3891cd82016-10-27 10:27:00 +0200658 u8 *h0;
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700659 u32 sw_if_index0;
660 u32 table_index0;
Damjan Marion3891cd82016-10-27 10:27:00 +0200661 vnet_classify_table_t *t0;
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700662
663 bi0 = from[0];
664 b0 = vlib_get_buffer (vm, bi0);
665 h0 = b0->data;
666
667 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
Damjan Marion3891cd82016-10-27 10:27:00 +0200668 table_index0 =
669 pcm->classify_table_index_by_sw_if_index[tid][sw_if_index0];
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700670
671 t0 = pool_elt_at_index (vcm->tables, table_index0);
Damjan Marion3891cd82016-10-27 10:27:00 +0200672 vnet_buffer (b0)->l2_classify.hash =
673 vnet_classify_hash_packet (t0, (u8 *) h0);
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700674
Damjan Marion3891cd82016-10-27 10:27:00 +0200675 vnet_buffer (b0)->l2_classify.table_index = table_index0;
676 vnet_classify_prefetch_bucket (t0, vnet_buffer (b0)->l2_classify.hash);
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700677
678 from++;
679 n_left_from--;
680 }
681
682 next_index = node->cached_next_index;
683 from = vlib_frame_vector_args (frame);
684 n_left_from = frame->n_vectors;
685
686 while (n_left_from > 0)
687 {
688 u32 n_left_to_next;
689
690 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
691
692 /* Not enough load/store slots to dual loop... */
693 while (n_left_from > 0 && n_left_to_next > 0)
Damjan Marion3891cd82016-10-27 10:27:00 +0200694 {
695 u32 bi0;
696 vlib_buffer_t *b0;
697 u32 next0 = POLICER_CLASSIFY_NEXT_INDEX_DROP;
698 u32 table_index0;
699 vnet_classify_table_t *t0;
700 vnet_classify_entry_t *e0;
701 u64 hash0;
702 u8 *h0;
703 u8 act0;
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700704
Damjan Marion3891cd82016-10-27 10:27:00 +0200705 /* Stride 3 seems to work best */
706 if (PREDICT_TRUE (n_left_from > 3))
707 {
708 vlib_buffer_t *p1 = vlib_get_buffer (vm, from[3]);
709 vnet_classify_table_t *tp1;
710 u32 table_index1;
711 u64 phash1;
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700712
Damjan Marion3891cd82016-10-27 10:27:00 +0200713 table_index1 = vnet_buffer (p1)->l2_classify.table_index;
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700714
Damjan Marion3891cd82016-10-27 10:27:00 +0200715 if (PREDICT_TRUE (table_index1 != ~0))
716 {
717 tp1 = pool_elt_at_index (vcm->tables, table_index1);
718 phash1 = vnet_buffer (p1)->l2_classify.hash;
719 vnet_classify_prefetch_entry (tp1, phash1);
720 }
721 }
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700722
Damjan Marion3891cd82016-10-27 10:27:00 +0200723 /* Speculatively enqueue b0 to the current next frame */
724 bi0 = from[0];
725 to_next[0] = bi0;
726 from += 1;
727 to_next += 1;
728 n_left_from -= 1;
729 n_left_to_next -= 1;
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700730
Damjan Marion3891cd82016-10-27 10:27:00 +0200731 b0 = vlib_get_buffer (vm, bi0);
732 h0 = b0->data;
733 table_index0 = vnet_buffer (b0)->l2_classify.table_index;
734 e0 = 0;
735 t0 = 0;
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700736
Damjan Marion3891cd82016-10-27 10:27:00 +0200737 if (tid == POLICER_CLASSIFY_TABLE_L2)
738 {
739 /* Feature bitmap update */
740 vnet_buffer (b0)->l2.feature_bitmap &=
741 ~L2INPUT_FEAT_POLICER_CLAS;
742 /* Determine the next node */
743 next0 =
744 feat_bitmap_get_next_node_index (pcm->feat_next_node_index,
745 vnet_buffer (b0)->
746 l2.feature_bitmap);
747 }
748 else
749 vnet_get_config_data (pcm->vnet_config_main[tid],
750 &b0->current_config_index, &next0,
751 /* # bytes of config data */ 0);
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700752
Damjan Marion3891cd82016-10-27 10:27:00 +0200753 vnet_buffer (b0)->l2_classify.opaque_index = ~0;
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700754
Damjan Marion3891cd82016-10-27 10:27:00 +0200755 if (PREDICT_TRUE (table_index0 != ~0))
756 {
757 hash0 = vnet_buffer (b0)->l2_classify.hash;
758 t0 = pool_elt_at_index (vcm->tables, table_index0);
759 e0 = vnet_classify_find_entry (t0, (u8 *) h0, hash0, now);
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700760
Damjan Marion3891cd82016-10-27 10:27:00 +0200761 if (e0)
762 {
763 act0 = vnet_policer_police (vm,
764 b0,
765 e0->next_index,
766 time_in_policer_periods,
767 e0->opaque_index);
768 if (PREDICT_FALSE (act0 == SSE2_QOS_ACTION_DROP))
769 {
770 next0 = POLICER_CLASSIFY_NEXT_INDEX_DROP;
771 b0->error = node->errors[POLICER_CLASSIFY_ERROR_DROP];
772 drop++;
773 }
774 hits++;
775 }
776 else
777 {
778 while (1)
779 {
780 if (PREDICT_TRUE (t0->next_table_index != ~0))
781 {
782 t0 = pool_elt_at_index (vcm->tables,
783 t0->next_table_index);
784 }
785 else
786 {
787 next0 = (t0->miss_next_index < n_next_nodes) ?
788 t0->miss_next_index : next0;
789 misses++;
790 break;
791 }
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700792
Damjan Marion3891cd82016-10-27 10:27:00 +0200793 hash0 = vnet_classify_hash_packet (t0, (u8 *) h0);
794 e0 =
795 vnet_classify_find_entry (t0, (u8 *) h0, hash0, now);
796 if (e0)
797 {
798 act0 = vnet_policer_police (vm,
799 b0,
800 e0->next_index,
801 time_in_policer_periods,
802 e0->opaque_index);
803 if (PREDICT_FALSE (act0 == SSE2_QOS_ACTION_DROP))
804 {
805 next0 = POLICER_CLASSIFY_NEXT_INDEX_DROP;
806 b0->error =
807 node->errors[POLICER_CLASSIFY_ERROR_DROP];
808 drop++;
809 }
810 hits++;
811 chain_hits++;
812 break;
813 }
814 }
815 }
816 }
817 if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
818 && (b0->flags & VLIB_BUFFER_IS_TRACED)))
819 {
820 policer_classify_trace_t *t =
821 vlib_add_trace (vm, node, b0, sizeof (*t));
822 t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX];
823 t->next_index = next0;
824 t->table_index = t0 ? t0 - vcm->tables : ~0;
825 t->offset = (e0 && t0) ? vnet_classify_get_offset (t0, e0) : ~0;
826 t->policer_index = e0 ? e0->next_index : ~0;
827 }
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700828
Damjan Marion3891cd82016-10-27 10:27:00 +0200829 /* Verify speculative enqueue, maybe switch current next frame */
830 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
831 n_left_to_next, bi0, next0);
832 }
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700833
834 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
835 }
836
837 vlib_node_increment_counter (vm, node->node_index,
Damjan Marion3891cd82016-10-27 10:27:00 +0200838 POLICER_CLASSIFY_ERROR_MISS, misses);
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700839 vlib_node_increment_counter (vm, node->node_index,
Damjan Marion3891cd82016-10-27 10:27:00 +0200840 POLICER_CLASSIFY_ERROR_HIT, hits);
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700841 vlib_node_increment_counter (vm, node->node_index,
Damjan Marion3891cd82016-10-27 10:27:00 +0200842 POLICER_CLASSIFY_ERROR_CHAIN_HIT, chain_hits);
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700843 vlib_node_increment_counter (vm, node->node_index,
Damjan Marion3891cd82016-10-27 10:27:00 +0200844 POLICER_CLASSIFY_ERROR_DROP, drop);
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700845
846 return frame->n_vectors;
847}
848
849static uword
850ip4_policer_classify (vlib_main_t * vm,
Damjan Marion3891cd82016-10-27 10:27:00 +0200851 vlib_node_runtime_t * node, vlib_frame_t * frame)
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700852{
Damjan Marion3891cd82016-10-27 10:27:00 +0200853 return policer_classify_inline (vm, node, frame,
854 POLICER_CLASSIFY_TABLE_IP4);
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700855}
856
Damjan Marion3891cd82016-10-27 10:27:00 +0200857/* *INDENT-OFF* */
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700858VLIB_REGISTER_NODE (ip4_policer_classify_node) = {
859 .function = ip4_policer_classify,
860 .name = "ip4-policer-classify",
861 .vector_size = sizeof (u32),
862 .format_trace = format_policer_classify_trace,
863 .n_errors = ARRAY_LEN(policer_classify_error_strings),
864 .error_strings = policer_classify_error_strings,
865 .n_next_nodes = POLICER_CLASSIFY_NEXT_INDEX_N_NEXT,
866 .next_nodes = {
867 [POLICER_CLASSIFY_NEXT_INDEX_DROP] = "error-drop",
868 },
869};
870
871VLIB_NODE_FUNCTION_MULTIARCH (ip4_policer_classify_node, ip4_policer_classify);
Damjan Marion3891cd82016-10-27 10:27:00 +0200872/* *INDENT-ON* */
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700873
874static uword
875ip6_policer_classify (vlib_main_t * vm,
Damjan Marion3891cd82016-10-27 10:27:00 +0200876 vlib_node_runtime_t * node, vlib_frame_t * frame)
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700877{
Damjan Marion3891cd82016-10-27 10:27:00 +0200878 return policer_classify_inline (vm, node, frame,
879 POLICER_CLASSIFY_TABLE_IP6);
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700880}
881
Damjan Marion3891cd82016-10-27 10:27:00 +0200882/* *INDENT-OFF* */
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700883VLIB_REGISTER_NODE (ip6_policer_classify_node) = {
884 .function = ip6_policer_classify,
885 .name = "ip6-policer-classify",
886 .vector_size = sizeof (u32),
887 .format_trace = format_policer_classify_trace,
888 .n_errors = ARRAY_LEN(policer_classify_error_strings),
889 .error_strings = policer_classify_error_strings,
890 .n_next_nodes = POLICER_CLASSIFY_NEXT_INDEX_N_NEXT,
891 .next_nodes = {
892 [POLICER_CLASSIFY_NEXT_INDEX_DROP] = "error-drop",
893 },
894};
895
896VLIB_NODE_FUNCTION_MULTIARCH (ip6_policer_classify_node, ip6_policer_classify);
Damjan Marion3891cd82016-10-27 10:27:00 +0200897/* *INDENT-ON* */
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700898
899static uword
900l2_policer_classify (vlib_main_t * vm,
Damjan Marion3891cd82016-10-27 10:27:00 +0200901 vlib_node_runtime_t * node, vlib_frame_t * frame)
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700902{
Damjan Marion3891cd82016-10-27 10:27:00 +0200903 return policer_classify_inline (vm, node, frame, POLICER_CLASSIFY_TABLE_L2);
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700904}
905
Damjan Marion3891cd82016-10-27 10:27:00 +0200906VLIB_REGISTER_NODE (l2_policer_classify_node) =
907{
908 .function = l2_policer_classify,.name = "l2-policer-classify",.vector_size =
909 sizeof (u32),.format_trace = format_policer_classify_trace,.n_errors =
910 ARRAY_LEN (policer_classify_error_strings),.error_strings =
911 policer_classify_error_strings,.n_next_nodes =
912 POLICER_CLASSIFY_NEXT_INDEX_N_NEXT,.next_nodes =
913 {
914 [POLICER_CLASSIFY_NEXT_INDEX_DROP] = "error-drop",}
915,};
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700916
917VLIB_NODE_FUNCTION_MULTIARCH (l2_policer_classify_node, l2_policer_classify);
918
919
920static clib_error_t *
Damjan Marion3891cd82016-10-27 10:27:00 +0200921policer_classify_init (vlib_main_t * vm)
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700922{
Damjan Marion3891cd82016-10-27 10:27:00 +0200923 policer_classify_main_t *pcm = &policer_classify_main;
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700924
925 pcm->vlib_main = vm;
Damjan Marion3891cd82016-10-27 10:27:00 +0200926 pcm->vnet_main = vnet_get_main ();
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700927 pcm->vnet_classify_main = &vnet_classify_main;
928
929 /* Initialize L2 feature next-node indexes */
Damjan Marion3891cd82016-10-27 10:27:00 +0200930 feat_bitmap_init_next_nodes (vm,
931 l2_policer_classify_node.index,
932 L2INPUT_N_FEAT,
933 l2input_get_feat_names (),
934 pcm->feat_next_node_index);
Matus Fabian70e6a8d2016-06-20 08:10:42 -0700935
936 return 0;
937}
938
939VLIB_INIT_FUNCTION (policer_classify_init);
Damjan Marion3891cd82016-10-27 10:27:00 +0200940
941/*
942 * fd.io coding-style-patch-verification: ON
943 *
944 * Local Variables:
945 * eval: (c-set-style "gnu")
946 * End:
947 */