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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <vlib/vlib.h>
19 #include <vnet/vnet.h>
20 #include <vnet/policer/policer.h>
21 #include <vnet/ip/ip.h>
22 #include <vnet/classify/policer_classify.h>
23 #include <vnet/classify/vnet_classify.h>
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
30 /* Dispatch functions meant to be instantiated elsewhere */
36 } vnet_policer_trace_t;
38 /* packet trace format function */
39 static u8 * format_policer_trace (u8 * s, va_list * args)
41 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
42 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
43 vnet_policer_trace_t * t = va_arg (*args, vnet_policer_trace_t *);
45 s = format (s, "VNET_POLICER: sw_if_index %d policer_index %d next %d",
46 t->sw_if_index, t->policer_index, t->next_index);
50 #define foreach_vnet_policer_error \
51 _(TRANSMIT, "Packets Transmitted") \
52 _(DROP, "Packets Dropped")
55 #define _(sym,str) VNET_POLICER_ERROR_##sym,
56 foreach_vnet_policer_error
59 } vnet_policer_error_t;
61 static char * vnet_policer_error_strings[] = {
62 #define _(sym,string) string,
63 foreach_vnet_policer_error
68 void vnet_policer_mark (vlib_buffer_t * b, u8 dscp)
70 ethernet_header_t * eh;
75 eh = (ethernet_header_t *) b->data;
76 type = clib_net_to_host_u16 (eh->type);
78 if (PREDICT_TRUE(type == ETHERNET_TYPE_IP4))
80 ip4h = (ip4_header_t *) &(b->data[sizeof(ethernet_header_t)]);;
81 ip4h->tos &= IP4_NON_DSCP_BITS;
82 ip4h->tos |= dscp << IP4_DSCP_SHIFT;
83 ip4h->checksum = ip4_header_checksum (ip4h);
87 if (PREDICT_TRUE(type == ETHERNET_TYPE_IP6))
89 ip6h = (ip6_header_t *) &(b->data[sizeof(ethernet_header_t)]);
90 ip6h->ip_version_traffic_class_and_flow_label &=
91 clib_host_to_net_u32(IP6_NON_DSCP_BITS);
92 ip6h->ip_version_traffic_class_and_flow_label |=
93 clib_host_to_net_u32(dscp << IP6_DSCP_SHIFT);
99 u8 vnet_policer_police (vlib_main_t * vm,
102 u64 time_in_policer_periods,
103 policer_result_e packet_color)
108 policer_read_response_type_st *pol;
109 vnet_policer_main_t * pm = &vnet_policer_main;
111 len = vlib_buffer_length_in_chain (vm, b);
112 pol = &pm->policers [policer_index];
113 col = vnet_police_packet (pol, len,
115 time_in_policer_periods);
116 act = pol->action[col];
117 if (PREDICT_TRUE(act == SSE2_QOS_ACTION_MARK_AND_TRANSMIT))
118 vnet_policer_mark(b, pol->mark_dscp[col]);
124 uword vnet_policer_inline (vlib_main_t * vm,
125 vlib_node_runtime_t * node,
126 vlib_frame_t * frame,
127 vnet_policer_index_t which)
129 u32 n_left_from, * from, * to_next;
130 vnet_policer_next_t next_index;
131 vnet_policer_main_t * pm = &vnet_policer_main;
132 u64 time_in_policer_periods;
135 time_in_policer_periods =
136 clib_cpu_time_now() >> POLICER_TICKS_PER_PERIOD_SHIFT;
138 from = vlib_frame_vector_args (frame);
139 n_left_from = frame->n_vectors;
140 next_index = node->cached_next_index;
142 while (n_left_from > 0)
146 vlib_get_next_frame (vm, node, next_index,
147 to_next, n_left_to_next);
149 while (n_left_from >= 4 && n_left_to_next >= 2)
152 vlib_buffer_t * b0, * b1;
154 u32 sw_if_index0, sw_if_index1;
155 u32 pi0 = 0, pi1 = 0;
158 /* Prefetch next iteration. */
160 vlib_buffer_t * b2, * b3;
162 b2 = vlib_get_buffer (vm, from[2]);
163 b3 = vlib_get_buffer (vm, from[3]);
165 vlib_prefetch_buffer_header (b2, LOAD);
166 vlib_prefetch_buffer_header (b3, LOAD);
169 /* speculatively enqueue b0 and b1 to the current next frame */
170 to_next[0] = bi0 = from[0];
171 to_next[1] = bi1 = from[1];
177 b0 = vlib_get_buffer (vm, bi0);
178 b1 = vlib_get_buffer (vm, bi1);
180 sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
181 next0 = VNET_POLICER_NEXT_TRANSMIT;
183 sw_if_index1 = vnet_buffer(b1)->sw_if_index[VLIB_RX];
184 next1 = VNET_POLICER_NEXT_TRANSMIT;
187 if (which == VNET_POLICER_INDEX_BY_SW_IF_INDEX)
189 pi0 = pm->policer_index_by_sw_if_index[sw_if_index0];
190 pi1 = pm->policer_index_by_sw_if_index[sw_if_index1];
193 if (which == VNET_POLICER_INDEX_BY_OPAQUE)
195 pi0 = vnet_buffer(b0)->policer.index;
196 pi1 = vnet_buffer(b1)->policer.index;
199 if (which == VNET_POLICER_INDEX_BY_EITHER)
201 pi0 = vnet_buffer(b0)->policer.index;
202 pi0 = (pi0 != ~0) ? pi0 :
203 pm->policer_index_by_sw_if_index [sw_if_index0];
204 pi1 = vnet_buffer(b1)->policer.index;
205 pi1 = (pi1 != ~0) ? pi1 :
206 pm->policer_index_by_sw_if_index [sw_if_index1];
209 act0 = vnet_policer_police(vm, b0, pi0, time_in_policer_periods,
210 POLICE_CONFORM /* no chaining */);
212 act1 = vnet_policer_police(vm, b1, pi1, time_in_policer_periods,
213 POLICE_CONFORM /* no chaining */);
215 if (PREDICT_FALSE(act0 == SSE2_QOS_ACTION_DROP)) /* drop action */
217 next0 = VNET_POLICER_NEXT_DROP;
218 b0->error = node->errors[VNET_POLICER_ERROR_DROP];
220 else /* transmit or mark-and-transmit action */
225 if (PREDICT_FALSE(act1 == SSE2_QOS_ACTION_DROP)) /* drop action */
227 next1 = VNET_POLICER_NEXT_DROP;
228 b1->error = node->errors[VNET_POLICER_ERROR_DROP];
230 else /* transmit or mark-and-transmit action */
236 if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)))
238 if (b0->flags & VLIB_BUFFER_IS_TRACED)
240 vnet_policer_trace_t *t =
241 vlib_add_trace (vm, node, b0, sizeof (*t));
242 t->sw_if_index = sw_if_index0;
243 t->next_index = next0;
245 if (b1->flags & VLIB_BUFFER_IS_TRACED)
247 vnet_policer_trace_t *t =
248 vlib_add_trace (vm, node, b1, sizeof (*t));
249 t->sw_if_index = sw_if_index1;
250 t->next_index = next1;
254 /* verify speculative enqueues, maybe switch current next frame */
255 vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
256 to_next, n_left_to_next,
257 bi0, bi1, next0, next1);
260 while (n_left_from > 0 && n_left_to_next > 0)
276 b0 = vlib_get_buffer (vm, bi0);
278 sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
279 next0 = VNET_POLICER_NEXT_TRANSMIT;
281 if (which == VNET_POLICER_INDEX_BY_SW_IF_INDEX)
282 pi0 = pm->policer_index_by_sw_if_index[sw_if_index0];
284 if (which == VNET_POLICER_INDEX_BY_OPAQUE)
285 pi0 = vnet_buffer(b0)->policer.index;
287 if (which == VNET_POLICER_INDEX_BY_EITHER)
289 pi0 = vnet_buffer(b0)->policer.index;
290 pi0 = (pi0 != ~0) ? pi0 :
291 pm->policer_index_by_sw_if_index [sw_if_index0];
294 act0 = vnet_policer_police(vm, b0, pi0, time_in_policer_periods,
295 POLICE_CONFORM /* no chaining */);
297 if (PREDICT_FALSE(act0 == SSE2_QOS_ACTION_DROP)) /* drop action */
299 next0 = VNET_POLICER_NEXT_DROP;
300 b0->error = node->errors[VNET_POLICER_ERROR_DROP];
302 else /* transmit or mark-and-transmit action */
307 if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
308 && (b0->flags & VLIB_BUFFER_IS_TRACED)))
310 vnet_policer_trace_t *t =
311 vlib_add_trace (vm, node, b0, sizeof (*t));
312 t->sw_if_index = sw_if_index0;
313 t->next_index = next0;
314 t->policer_index = pi0;
317 /* verify speculative enqueue, maybe switch current next frame */
318 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
319 to_next, n_left_to_next,
323 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
326 vlib_node_increment_counter (vm, node->node_index,
327 VNET_POLICER_ERROR_TRANSMIT,
329 return frame->n_vectors;
332 uword vnet_policer_by_sw_if_index (vlib_main_t * vm,
333 vlib_node_runtime_t * node,
334 vlib_frame_t * frame)
336 return vnet_policer_inline (vm, node, frame,
337 VNET_POLICER_INDEX_BY_SW_IF_INDEX);
340 uword vnet_policer_by_opaque (vlib_main_t * vm,
341 vlib_node_runtime_t * node,
342 vlib_frame_t * frame)
344 return vnet_policer_inline (vm, node, frame,
345 VNET_POLICER_INDEX_BY_OPAQUE);
348 uword vnet_policer_by_either (vlib_main_t * vm,
349 vlib_node_runtime_t * node,
350 vlib_frame_t * frame)
352 return vnet_policer_inline (vm, node, frame,
353 VNET_POLICER_INDEX_BY_EITHER);
356 void vnet_policer_node_funcs_reference (void) { }
363 VLIB_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,
370 .n_errors = ARRAY_LEN(vnet_policer_error_strings),
371 .error_strings = vnet_policer_error_strings,
373 .n_next_nodes = VNET_POLICER_N_NEXT,
375 /* edit / add dispositions here */
377 [VNET_POLICER_NEXT_TRANSMIT] = "ethernet-input",
378 [VNET_POLICER_NEXT_DROP] = "error-drop",
382 VLIB_NODE_FUNCTION_MULTIARCH (policer_by_sw_if_index_node,
383 vnet_policer_by_sw_if_index);
386 int test_policer_add_del (u32 rx_sw_if_index, u8 *config_name,
389 vnet_policer_main_t * pm = &vnet_policer_main;
390 policer_read_response_type_st * template;
391 policer_read_response_type_st * policer;
392 vnet_hw_interface_t * rxhi;
395 rxhi = vnet_get_sup_hw_interface (pm->vnet_main, rx_sw_if_index);
397 /* Make sure caller didn't pass a vlan subif, etc. */
398 if (rxhi->sw_if_index != rx_sw_if_index)
399 return VNET_API_ERROR_INVALID_SW_IF_INDEX;
404 p = hash_get_mem (pm->policer_config_by_name, config_name);
409 template = pool_elt_at_index (pm->policer_templates, p[0]);
411 vnet_hw_interface_rx_redirect_to_node
414 policer_by_sw_if_index_node.index);
416 pool_get_aligned (pm->policers, policer, CLIB_CACHE_LINE_BYTES);
418 policer[0] = template[0];
420 vec_validate (pm->policer_index_by_sw_if_index, rx_sw_if_index);
421 pm->policer_index_by_sw_if_index[rx_sw_if_index]
422 = policer - pm->policers;
427 vnet_hw_interface_rx_redirect_to_node (pm->vnet_main,
431 pi = pm->policer_index_by_sw_if_index[rx_sw_if_index];
432 pm->policer_index_by_sw_if_index[rx_sw_if_index] = ~0;
433 pool_put_index (pm->policers, pi);
439 static clib_error_t *
440 test_policer_command_fn (vlib_main_t * vm,
441 unformat_input_t * input,
442 vlib_cli_command_t * cmd)
444 vnet_policer_main_t * pm = &vnet_policer_main;
445 unformat_input_t _line_input, * line_input = &_line_input;
448 u8 * config_name = 0;
453 /* Get a line of input. */
454 if (! unformat_user (input, unformat_line_input, line_input))
457 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
459 if (unformat (line_input, "intfc %U", unformat_vnet_sw_interface,
460 pm->vnet_main, &rx_sw_if_index))
462 else if (unformat (line_input, "show"))
464 else if (unformat (line_input, "policer %s", &config_name))
466 else if (unformat (line_input, "del"))
472 return clib_error_return (0, "interface not set");
476 u32 pi = pm->policer_index_by_sw_if_index[rx_sw_if_index];
477 policer_read_response_type_st * policer;
478 policer = pool_elt_at_index (pm->policers, pi);
480 vlib_cli_output (vm, "%U", format_policer_instance, policer);
484 if (is_add && config_name == 0)
486 return clib_error_return (0, "policer config name required");
489 rv = test_policer_add_del (rx_sw_if_index, config_name, is_add);
497 return clib_error_return
498 (0, "WARNING: vnet_vnet_policer_add_del returned %d", rv);
504 VLIB_CLI_COMMAND (test_patch_command, static) = {
505 .path = "test policer",
507 "intfc <intfc> policer <policer-config-name> [del]",
508 .function = test_policer_command_fn,
512 #endif /* TEST_CODE */
521 } policer_classify_trace_t;
524 format_policer_classify_trace (u8 * s, va_list * args)
526 CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
527 CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
528 policer_classify_trace_t * t = va_arg (*args, policer_classify_trace_t *);
530 s = format (s, "POLICER_CLASSIFY: sw_if_index %d next %d table %d offset %d"
532 t->sw_if_index, t->next_index, t->table_index, t->offset,
537 #define foreach_policer_classify_error \
538 _(MISS, "Policer classify misses") \
539 _(HIT, "Policer classify hits") \
540 _(CHAIN_HIT, "Polcier classify hits after chain walk") \
541 _(DROP, "Policer classify action drop")
544 #define _(sym,str) POLICER_CLASSIFY_ERROR_##sym,
545 foreach_policer_classify_error
547 POLICER_CLASSIFY_N_ERROR,
548 } policer_classify_error_t;
550 static char * policer_classify_error_strings[] = {
551 #define _(sym,string) string,
552 foreach_policer_classify_error
557 policer_classify_inline (vlib_main_t * vm,
558 vlib_node_runtime_t * node,
559 vlib_frame_t * frame,
560 policer_classify_table_id_t tid)
562 u32 n_left_from, * from, * to_next;
563 policer_classify_next_index_t next_index;
564 policer_classify_main_t * pcm = &policer_classify_main;
565 vnet_classify_main_t * vcm = pcm->vnet_classify_main;
566 f64 now = vlib_time_now (vm);
572 u64 time_in_policer_periods;
574 time_in_policer_periods =
575 clib_cpu_time_now() >> POLICER_TICKS_PER_PERIOD_SHIFT;
577 n_next_nodes = node->n_next_nodes;
579 from = vlib_frame_vector_args (frame);
580 n_left_from = frame->n_vectors;
582 /* First pass: compute hashes */
583 while (n_left_from > 2)
585 vlib_buffer_t * b0, * b1;
588 u32 sw_if_index0, sw_if_index1;
589 u32 table_index0, table_index1;
590 vnet_classify_table_t * t0, * t1;
592 /* Prefetch next iteration */
594 vlib_buffer_t * p1, * p2;
596 p1 = vlib_get_buffer (vm, from[1]);
597 p2 = vlib_get_buffer (vm, from[2]);
599 vlib_prefetch_buffer_header (p1, STORE);
600 CLIB_PREFETCH (p1->data, CLIB_CACHE_LINE_BYTES, STORE);
601 vlib_prefetch_buffer_header (p2, STORE);
602 CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
606 b0 = vlib_get_buffer (vm, bi0);
610 b1 = vlib_get_buffer (vm, bi1);
613 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
614 table_index0 = pcm->classify_table_index_by_sw_if_index[tid][sw_if_index0];
616 sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
617 table_index1 = pcm->classify_table_index_by_sw_if_index[tid][sw_if_index1];
619 t0 = pool_elt_at_index (vcm->tables, table_index0);
621 t1 = pool_elt_at_index (vcm->tables, table_index1);
623 vnet_buffer(b0)->l2_classify.hash =
624 vnet_classify_hash_packet (t0, (u8 *) h0);
626 vnet_classify_prefetch_bucket (t0, vnet_buffer(b0)->l2_classify.hash);
628 vnet_buffer(b1)->l2_classify.hash =
629 vnet_classify_hash_packet (t1, (u8 *) h1);
631 vnet_classify_prefetch_bucket (t1, vnet_buffer(b1)->l2_classify.hash);
633 vnet_buffer(b0)->l2_classify.table_index = table_index0;
635 vnet_buffer(b1)->l2_classify.table_index = table_index1;
641 while (n_left_from > 0)
648 vnet_classify_table_t * t0;
651 b0 = vlib_get_buffer (vm, bi0);
654 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
655 table_index0 = pcm->classify_table_index_by_sw_if_index[tid][sw_if_index0];
657 t0 = pool_elt_at_index (vcm->tables, table_index0);
658 vnet_buffer(b0)->l2_classify.hash =
659 vnet_classify_hash_packet (t0, (u8 *) h0);
661 vnet_buffer(b0)->l2_classify.table_index = table_index0;
662 vnet_classify_prefetch_bucket (t0, vnet_buffer(b0)->l2_classify.hash);
668 next_index = node->cached_next_index;
669 from = vlib_frame_vector_args (frame);
670 n_left_from = frame->n_vectors;
672 while (n_left_from > 0)
676 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
678 /* Not enough load/store slots to dual loop... */
679 while (n_left_from > 0 && n_left_to_next > 0)
683 u32 next0 = POLICER_CLASSIFY_NEXT_INDEX_DROP;
685 vnet_classify_table_t * t0;
686 vnet_classify_entry_t * e0;
691 /* Stride 3 seems to work best */
692 if (PREDICT_TRUE (n_left_from > 3))
694 vlib_buffer_t * p1 = vlib_get_buffer(vm, from[3]);
695 vnet_classify_table_t * tp1;
699 table_index1 = vnet_buffer(p1)->l2_classify.table_index;
701 if (PREDICT_TRUE (table_index1 != ~0))
703 tp1 = pool_elt_at_index (vcm->tables, table_index1);
704 phash1 = vnet_buffer(p1)->l2_classify.hash;
705 vnet_classify_prefetch_entry (tp1, phash1);
709 /* Speculatively enqueue b0 to the current next frame */
717 b0 = vlib_get_buffer (vm, bi0);
719 table_index0 = vnet_buffer(b0)->l2_classify.table_index;
723 if (tid == POLICER_CLASSIFY_TABLE_L2)
725 /* Feature bitmap update */
726 vnet_buffer(b0)->l2.feature_bitmap &= ~L2INPUT_FEAT_POLICER_CLAS;
727 /* Determine the next node */
728 next0 = feat_bitmap_get_next_node_index(pcm->feat_next_node_index,
729 vnet_buffer(b0)->l2.feature_bitmap);
732 vnet_get_config_data (pcm->vnet_config_main[tid],
733 &b0->current_config_index,
735 /* # bytes of config data */ 0);
737 vnet_buffer(b0)->l2_classify.opaque_index = ~0;
739 if (PREDICT_TRUE(table_index0 != ~0))
741 hash0 = vnet_buffer(b0)->l2_classify.hash;
742 t0 = pool_elt_at_index (vcm->tables, table_index0);
743 e0 = vnet_classify_find_entry (t0, (u8 *) h0, hash0, now);
747 act0 = vnet_policer_police(vm,
750 time_in_policer_periods,
752 if (PREDICT_FALSE(act0 == SSE2_QOS_ACTION_DROP))
754 next0 = POLICER_CLASSIFY_NEXT_INDEX_DROP;
755 b0->error = node->errors[POLICER_CLASSIFY_ERROR_DROP];
764 if (PREDICT_TRUE(t0->next_table_index != ~0))
766 t0 = pool_elt_at_index (vcm->tables,
767 t0->next_table_index);
771 next0 = (t0->miss_next_index < n_next_nodes)?
772 t0->miss_next_index:next0;
777 hash0 = vnet_classify_hash_packet (t0, (u8 *) h0);
778 e0 = vnet_classify_find_entry (t0, (u8 *) h0, hash0, now);
781 act0 = vnet_policer_police(vm,
784 time_in_policer_periods,
786 if (PREDICT_FALSE(act0 == SSE2_QOS_ACTION_DROP))
788 next0 = POLICER_CLASSIFY_NEXT_INDEX_DROP;
789 b0->error = node->errors[POLICER_CLASSIFY_ERROR_DROP];
799 if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
800 && (b0->flags & VLIB_BUFFER_IS_TRACED)))
802 policer_classify_trace_t * t =
803 vlib_add_trace (vm, node, b0, sizeof (*t));
804 t->sw_if_index = vnet_buffer(b0)->sw_if_index[VLIB_RX];
805 t->next_index = next0;
806 t->table_index = t0 ? t0 - vcm->tables : ~0;
807 t->offset = (e0 && t0) ? vnet_classify_get_offset (t0, e0): ~0;
808 t->policer_index = e0 ? e0->next_index: ~0;
811 /* Verify speculative enqueue, maybe switch current next frame */
812 vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
813 n_left_to_next, bi0, next0);
816 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
819 vlib_node_increment_counter (vm, node->node_index,
820 POLICER_CLASSIFY_ERROR_MISS,
822 vlib_node_increment_counter (vm, node->node_index,
823 POLICER_CLASSIFY_ERROR_HIT,
825 vlib_node_increment_counter (vm, node->node_index,
826 POLICER_CLASSIFY_ERROR_CHAIN_HIT,
828 vlib_node_increment_counter (vm, node->node_index,
829 POLICER_CLASSIFY_ERROR_DROP,
832 return frame->n_vectors;
836 ip4_policer_classify (vlib_main_t * vm,
837 vlib_node_runtime_t * node,
838 vlib_frame_t * frame)
840 return policer_classify_inline(vm, node, frame, POLICER_CLASSIFY_TABLE_IP4);
843 VLIB_REGISTER_NODE (ip4_policer_classify_node) = {
844 .function = ip4_policer_classify,
845 .name = "ip4-policer-classify",
846 .vector_size = sizeof (u32),
847 .format_trace = format_policer_classify_trace,
848 .n_errors = ARRAY_LEN(policer_classify_error_strings),
849 .error_strings = policer_classify_error_strings,
850 .n_next_nodes = POLICER_CLASSIFY_NEXT_INDEX_N_NEXT,
852 [POLICER_CLASSIFY_NEXT_INDEX_DROP] = "error-drop",
856 VLIB_NODE_FUNCTION_MULTIARCH (ip4_policer_classify_node, ip4_policer_classify);
859 ip6_policer_classify (vlib_main_t * vm,
860 vlib_node_runtime_t * node,
861 vlib_frame_t * frame)
863 return policer_classify_inline(vm, node, frame, POLICER_CLASSIFY_TABLE_IP6);
866 VLIB_REGISTER_NODE (ip6_policer_classify_node) = {
867 .function = ip6_policer_classify,
868 .name = "ip6-policer-classify",
869 .vector_size = sizeof (u32),
870 .format_trace = format_policer_classify_trace,
871 .n_errors = ARRAY_LEN(policer_classify_error_strings),
872 .error_strings = policer_classify_error_strings,
873 .n_next_nodes = POLICER_CLASSIFY_NEXT_INDEX_N_NEXT,
875 [POLICER_CLASSIFY_NEXT_INDEX_DROP] = "error-drop",
879 VLIB_NODE_FUNCTION_MULTIARCH (ip6_policer_classify_node, ip6_policer_classify);
882 l2_policer_classify (vlib_main_t * vm,
883 vlib_node_runtime_t * node,
884 vlib_frame_t * frame)
886 return policer_classify_inline(vm, node, frame, POLICER_CLASSIFY_TABLE_L2);
889 VLIB_REGISTER_NODE (l2_policer_classify_node) = {
890 .function = l2_policer_classify,
891 .name = "l2-policer-classify",
892 .vector_size = sizeof (u32),
893 .format_trace = format_policer_classify_trace,
894 .n_errors = ARRAY_LEN(policer_classify_error_strings),
895 .error_strings = policer_classify_error_strings,
896 .n_next_nodes = POLICER_CLASSIFY_NEXT_INDEX_N_NEXT,
898 [POLICER_CLASSIFY_NEXT_INDEX_DROP] = "error-drop",
902 VLIB_NODE_FUNCTION_MULTIARCH (l2_policer_classify_node, l2_policer_classify);
905 static clib_error_t *
906 policer_classify_init (vlib_main_t *vm)
908 policer_classify_main_t * pcm = &policer_classify_main;
911 pcm->vnet_main = vnet_get_main();
912 pcm->vnet_classify_main = &vnet_classify_main;
914 /* Initialize L2 feature next-node indexes */
915 feat_bitmap_init_next_nodes(vm,
916 l2_policer_classify_node.index,
918 l2input_get_feat_names(),
919 pcm->feat_next_node_index);
924 VLIB_INIT_FUNCTION (policer_classify_init);