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 */
37 } vnet_policer_trace_t;
39 /* packet trace format function */
41 format_policer_trace (u8 * s, va_list * args)
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 *);
45 vnet_policer_trace_t *t = va_arg (*args, vnet_policer_trace_t *);
47 s = format (s, "VNET_POLICER: sw_if_index %d policer_index %d next %d",
48 t->sw_if_index, t->policer_index, t->next_index);
52 #define foreach_vnet_policer_error \
53 _(TRANSMIT, "Packets Transmitted") \
54 _(DROP, "Packets Dropped")
58 #define _(sym,str) VNET_POLICER_ERROR_##sym,
59 foreach_vnet_policer_error
62 } vnet_policer_error_t;
64 static char *vnet_policer_error_strings[] = {
65 #define _(sym,string) string,
66 foreach_vnet_policer_error
70 static_always_inline void
71 vnet_policer_mark (vlib_buffer_t * b, u8 dscp)
73 ethernet_header_t *eh;
78 eh = (ethernet_header_t *) b->data;
79 type = clib_net_to_host_u16 (eh->type);
81 if (PREDICT_TRUE (type == ETHERNET_TYPE_IP4))
83 ip4h = (ip4_header_t *) & (b->data[sizeof (ethernet_header_t)]);;
84 ip4h->tos &= IP4_NON_DSCP_BITS;
85 ip4h->tos |= dscp << IP4_DSCP_SHIFT;
86 ip4h->checksum = ip4_header_checksum (ip4h);
90 if (PREDICT_TRUE (type == ETHERNET_TYPE_IP6))
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);
102 u8 vnet_policer_police (vlib_main_t * vm,
105 u64 time_in_policer_periods,
106 policer_result_e packet_color)
111 policer_read_response_type_st *pol;
112 vnet_policer_main_t *pm = &vnet_policer_main;
114 len = vlib_buffer_length_in_chain (vm, b);
115 pol = &pm->policers[policer_index];
116 col = vnet_police_packet (pol, len, packet_color, time_in_policer_periods);
117 act = pol->action[col];
118 if (PREDICT_TRUE (act == SSE2_QOS_ACTION_MARK_AND_TRANSMIT))
119 vnet_policer_mark (b, pol->mark_dscp[col]);
125 vnet_policer_inline (vlib_main_t * vm,
126 vlib_node_runtime_t * node,
127 vlib_frame_t * frame, 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, to_next, n_left_to_next);
148 while (n_left_from >= 4 && n_left_to_next >= 2)
151 vlib_buffer_t *b0, *b1;
153 u32 sw_if_index0, sw_if_index1;
154 u32 pi0 = 0, pi1 = 0;
157 /* Prefetch next iteration. */
159 vlib_buffer_t *b2, *b3;
161 b2 = vlib_get_buffer (vm, from[2]);
162 b3 = vlib_get_buffer (vm, from[3]);
164 vlib_prefetch_buffer_header (b2, LOAD);
165 vlib_prefetch_buffer_header (b3, LOAD);
168 /* speculatively enqueue b0 and b1 to the current next frame */
169 to_next[0] = bi0 = from[0];
170 to_next[1] = bi1 = from[1];
176 b0 = vlib_get_buffer (vm, bi0);
177 b1 = vlib_get_buffer (vm, bi1);
179 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
180 next0 = VNET_POLICER_NEXT_TRANSMIT;
182 sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
183 next1 = VNET_POLICER_NEXT_TRANSMIT;
186 if (which == VNET_POLICER_INDEX_BY_SW_IF_INDEX)
188 pi0 = pm->policer_index_by_sw_if_index[sw_if_index0];
189 pi1 = pm->policer_index_by_sw_if_index[sw_if_index1];
192 if (which == VNET_POLICER_INDEX_BY_OPAQUE)
194 pi0 = vnet_buffer (b0)->policer.index;
195 pi1 = vnet_buffer (b1)->policer.index;
198 if (which == VNET_POLICER_INDEX_BY_EITHER)
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];
208 act0 = vnet_policer_police (vm, b0, pi0, time_in_policer_periods,
209 POLICE_CONFORM /* no chaining */ );
211 act1 = vnet_policer_police (vm, b1, pi1, time_in_policer_periods,
212 POLICE_CONFORM /* no chaining */ );
214 if (PREDICT_FALSE (act0 == SSE2_QOS_ACTION_DROP)) /* drop action */
216 next0 = VNET_POLICER_NEXT_DROP;
217 b0->error = node->errors[VNET_POLICER_ERROR_DROP];
219 else /* transmit or mark-and-transmit action */
224 if (PREDICT_FALSE (act1 == SSE2_QOS_ACTION_DROP)) /* drop action */
226 next1 = VNET_POLICER_NEXT_DROP;
227 b1->error = node->errors[VNET_POLICER_ERROR_DROP];
229 else /* transmit or mark-and-transmit action */
235 if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)))
237 if (b0->flags & VLIB_BUFFER_IS_TRACED)
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;
244 if (b1->flags & VLIB_BUFFER_IS_TRACED)
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;
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);
259 while (n_left_from > 0 && n_left_to_next > 0)
275 b0 = vlib_get_buffer (vm, bi0);
277 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
278 next0 = VNET_POLICER_NEXT_TRANSMIT;
280 if (which == VNET_POLICER_INDEX_BY_SW_IF_INDEX)
281 pi0 = pm->policer_index_by_sw_if_index[sw_if_index0];
283 if (which == VNET_POLICER_INDEX_BY_OPAQUE)
284 pi0 = vnet_buffer (b0)->policer.index;
286 if (which == VNET_POLICER_INDEX_BY_EITHER)
288 pi0 = vnet_buffer (b0)->policer.index;
289 pi0 = (pi0 != ~0) ? pi0 :
290 pm->policer_index_by_sw_if_index[sw_if_index0];
293 act0 = vnet_policer_police (vm, b0, pi0, time_in_policer_periods,
294 POLICE_CONFORM /* no chaining */ );
296 if (PREDICT_FALSE (act0 == SSE2_QOS_ACTION_DROP)) /* drop action */
298 next0 = VNET_POLICER_NEXT_DROP;
299 b0->error = node->errors[VNET_POLICER_ERROR_DROP];
301 else /* transmit or mark-and-transmit action */
306 if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
307 && (b0->flags & VLIB_BUFFER_IS_TRACED)))
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;
316 /* verify speculative enqueue, maybe switch current next frame */
317 vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
318 to_next, n_left_to_next,
322 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
325 vlib_node_increment_counter (vm, node->node_index,
326 VNET_POLICER_ERROR_TRANSMIT, transmitted);
327 return frame->n_vectors;
331 vnet_policer_by_sw_if_index (vlib_main_t * vm,
332 vlib_node_runtime_t * node, vlib_frame_t * frame)
334 return vnet_policer_inline (vm, node, frame,
335 VNET_POLICER_INDEX_BY_SW_IF_INDEX);
339 vnet_policer_by_opaque (vlib_main_t * vm,
340 vlib_node_runtime_t * node, vlib_frame_t * frame)
342 return vnet_policer_inline (vm, node, frame, VNET_POLICER_INDEX_BY_OPAQUE);
346 vnet_policer_by_either (vlib_main_t * vm,
347 vlib_node_runtime_t * node, vlib_frame_t * frame)
349 return vnet_policer_inline (vm, node, frame, VNET_POLICER_INDEX_BY_EITHER);
353 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);
388 test_policer_add_del (u32 rx_sw_if_index, u8 * config_name, int is_add)
390 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;
396 rxhi = vnet_get_sup_hw_interface (pm->vnet_main, rx_sw_if_index);
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;
405 p = hash_get_mem (pm->policer_config_by_name, config_name);
410 template = pool_elt_at_index (pm->policer_templates, p[0]);
412 vnet_hw_interface_rx_redirect_to_node
413 (pm->vnet_main, rxhi->hw_if_index, policer_by_sw_if_index_node.index);
415 pool_get_aligned (pm->policers, policer, CLIB_CACHE_LINE_BYTES);
417 policer[0] = template[0];
419 vec_validate (pm->policer_index_by_sw_if_index, rx_sw_if_index);
420 pm->policer_index_by_sw_if_index[rx_sw_if_index]
421 = policer - pm->policers;
426 vnet_hw_interface_rx_redirect_to_node (pm->vnet_main,
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);
438 static clib_error_t *
439 test_policer_command_fn (vlib_main_t * vm,
440 unformat_input_t * input, vlib_cli_command_t * cmd)
442 vnet_policer_main_t *pm = &vnet_policer_main;
443 unformat_input_t _line_input, *line_input = &_line_input;
450 clib_error_t *error = NULL;
452 /* Get a line of input. */
453 if (!unformat_user (input, unformat_line_input, line_input))
456 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
458 if (unformat (line_input, "intfc %U", unformat_vnet_sw_interface,
459 pm->vnet_main, &rx_sw_if_index))
461 else if (unformat (line_input, "show"))
463 else if (unformat (line_input, "policer %s", &config_name))
465 else if (unformat (line_input, "del"))
473 error = clib_error_return (0, "interface not set");
479 u32 pi = pm->policer_index_by_sw_if_index[rx_sw_if_index];
480 policer_read_response_type_st *policer;
481 policer = pool_elt_at_index (pm->policers, pi);
483 vlib_cli_output (vm, "%U", format_policer_instance, policer);
487 if (is_add && config_name == 0)
489 error = clib_error_return (0, "policer config name required");
493 rv = test_policer_add_del (rx_sw_if_index, config_name, is_add);
501 error = clib_error_return
502 (0, "WARNING: vnet_vnet_policer_add_del returned %d", rv);
507 unformat_free (line_input);
513 VLIB_CLI_COMMAND (test_patch_command, static) = {
514 .path = "test policer",
516 "intfc <intfc> policer <policer-config-name> [del]",
517 .function = test_policer_command_fn,
521 #endif /* TEST_CODE */
531 } policer_classify_trace_t;
534 format_policer_classify_trace (u8 * s, va_list * args)
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 *);
538 policer_classify_trace_t *t = va_arg (*args, policer_classify_trace_t *);
540 s = format (s, "POLICER_CLASSIFY: sw_if_index %d next %d table %d offset %d"
542 t->sw_if_index, t->next_index, t->table_index, t->offset,
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")
555 #define _(sym,str) POLICER_CLASSIFY_ERROR_##sym,
556 foreach_policer_classify_error
558 POLICER_CLASSIFY_N_ERROR,
559 } policer_classify_error_t;
561 static char *policer_classify_error_strings[] = {
562 #define _(sym,string) string,
563 foreach_policer_classify_error
568 policer_classify_inline (vlib_main_t * vm,
569 vlib_node_runtime_t * node,
570 vlib_frame_t * frame,
571 policer_classify_table_id_t tid)
573 u32 n_left_from, *from, *to_next;
574 policer_classify_next_index_t next_index;
575 policer_classify_main_t *pcm = &policer_classify_main;
576 vnet_classify_main_t *vcm = pcm->vnet_classify_main;
577 f64 now = vlib_time_now (vm);
583 u64 time_in_policer_periods;
585 time_in_policer_periods =
586 clib_cpu_time_now () >> POLICER_TICKS_PER_PERIOD_SHIFT;
588 n_next_nodes = node->n_next_nodes;
590 from = vlib_frame_vector_args (frame);
591 n_left_from = frame->n_vectors;
593 /* First pass: compute hashes */
594 while (n_left_from > 2)
596 vlib_buffer_t *b0, *b1;
599 u32 sw_if_index0, sw_if_index1;
600 u32 table_index0, table_index1;
601 vnet_classify_table_t *t0, *t1;
603 /* Prefetch next iteration */
605 vlib_buffer_t *p1, *p2;
607 p1 = vlib_get_buffer (vm, from[1]);
608 p2 = vlib_get_buffer (vm, from[2]);
610 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);
617 b0 = vlib_get_buffer (vm, bi0);
621 b1 = vlib_get_buffer (vm, bi1);
624 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
626 pcm->classify_table_index_by_sw_if_index[tid][sw_if_index0];
628 sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
630 pcm->classify_table_index_by_sw_if_index[tid][sw_if_index1];
632 t0 = pool_elt_at_index (vcm->tables, table_index0);
634 t1 = pool_elt_at_index (vcm->tables, table_index1);
636 vnet_buffer (b0)->l2_classify.hash =
637 vnet_classify_hash_packet (t0, (u8 *) h0);
639 vnet_classify_prefetch_bucket (t0, vnet_buffer (b0)->l2_classify.hash);
641 vnet_buffer (b1)->l2_classify.hash =
642 vnet_classify_hash_packet (t1, (u8 *) h1);
644 vnet_classify_prefetch_bucket (t1, vnet_buffer (b1)->l2_classify.hash);
646 vnet_buffer (b0)->l2_classify.table_index = table_index0;
648 vnet_buffer (b1)->l2_classify.table_index = table_index1;
654 while (n_left_from > 0)
661 vnet_classify_table_t *t0;
664 b0 = vlib_get_buffer (vm, bi0);
667 sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
669 pcm->classify_table_index_by_sw_if_index[tid][sw_if_index0];
671 t0 = pool_elt_at_index (vcm->tables, table_index0);
672 vnet_buffer (b0)->l2_classify.hash =
673 vnet_classify_hash_packet (t0, (u8 *) h0);
675 vnet_buffer (b0)->l2_classify.table_index = table_index0;
676 vnet_classify_prefetch_bucket (t0, vnet_buffer (b0)->l2_classify.hash);
682 next_index = node->cached_next_index;
683 from = vlib_frame_vector_args (frame);
684 n_left_from = frame->n_vectors;
686 while (n_left_from > 0)
690 vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
692 /* Not enough load/store slots to dual loop... */
693 while (n_left_from > 0 && n_left_to_next > 0)
697 u32 next0 = POLICER_CLASSIFY_NEXT_INDEX_DROP;
699 vnet_classify_table_t *t0;
700 vnet_classify_entry_t *e0;
705 /* Stride 3 seems to work best */
706 if (PREDICT_TRUE (n_left_from > 3))
708 vlib_buffer_t *p1 = vlib_get_buffer (vm, from[3]);
709 vnet_classify_table_t *tp1;
713 table_index1 = vnet_buffer (p1)->l2_classify.table_index;
715 if (PREDICT_TRUE (table_index1 != ~0))
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);
723 /* Speculatively enqueue b0 to the current next frame */
731 b0 = vlib_get_buffer (vm, bi0);
733 table_index0 = vnet_buffer (b0)->l2_classify.table_index;
737 if (tid == POLICER_CLASSIFY_TABLE_L2)
739 /* Feature bitmap update */
740 vnet_buffer (b0)->l2.feature_bitmap &=
741 ~L2INPUT_FEAT_POLICER_CLAS;
742 /* Determine the next node */
744 feat_bitmap_get_next_node_index (pcm->feat_next_node_index,
749 vnet_get_config_data (pcm->vnet_config_main[tid],
750 &b0->current_config_index, &next0,
751 /* # bytes of config data */ 0);
753 vnet_buffer (b0)->l2_classify.opaque_index = ~0;
755 if (PREDICT_TRUE (table_index0 != ~0))
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);
763 act0 = vnet_policer_police (vm,
766 time_in_policer_periods,
768 if (PREDICT_FALSE (act0 == SSE2_QOS_ACTION_DROP))
770 next0 = POLICER_CLASSIFY_NEXT_INDEX_DROP;
771 b0->error = node->errors[POLICER_CLASSIFY_ERROR_DROP];
780 if (PREDICT_TRUE (t0->next_table_index != ~0))
782 t0 = pool_elt_at_index (vcm->tables,
783 t0->next_table_index);
787 next0 = (t0->miss_next_index < n_next_nodes) ?
788 t0->miss_next_index : next0;
793 hash0 = vnet_classify_hash_packet (t0, (u8 *) h0);
795 vnet_classify_find_entry (t0, (u8 *) h0, hash0, now);
798 act0 = vnet_policer_police (vm,
801 time_in_policer_periods,
803 if (PREDICT_FALSE (act0 == SSE2_QOS_ACTION_DROP))
805 next0 = POLICER_CLASSIFY_NEXT_INDEX_DROP;
807 node->errors[POLICER_CLASSIFY_ERROR_DROP];
817 if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
818 && (b0->flags & VLIB_BUFFER_IS_TRACED)))
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;
829 /* 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);
834 vlib_put_next_frame (vm, node, next_index, n_left_to_next);
837 vlib_node_increment_counter (vm, node->node_index,
838 POLICER_CLASSIFY_ERROR_MISS, misses);
839 vlib_node_increment_counter (vm, node->node_index,
840 POLICER_CLASSIFY_ERROR_HIT, hits);
841 vlib_node_increment_counter (vm, node->node_index,
842 POLICER_CLASSIFY_ERROR_CHAIN_HIT, chain_hits);
843 vlib_node_increment_counter (vm, node->node_index,
844 POLICER_CLASSIFY_ERROR_DROP, drop);
846 return frame->n_vectors;
850 ip4_policer_classify (vlib_main_t * vm,
851 vlib_node_runtime_t * node, vlib_frame_t * frame)
853 return policer_classify_inline (vm, node, frame,
854 POLICER_CLASSIFY_TABLE_IP4);
858 VLIB_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,
867 [POLICER_CLASSIFY_NEXT_INDEX_DROP] = "error-drop",
871 VLIB_NODE_FUNCTION_MULTIARCH (ip4_policer_classify_node, ip4_policer_classify);
875 ip6_policer_classify (vlib_main_t * vm,
876 vlib_node_runtime_t * node, vlib_frame_t * frame)
878 return policer_classify_inline (vm, node, frame,
879 POLICER_CLASSIFY_TABLE_IP6);
883 VLIB_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,
892 [POLICER_CLASSIFY_NEXT_INDEX_DROP] = "error-drop",
896 VLIB_NODE_FUNCTION_MULTIARCH (ip6_policer_classify_node, ip6_policer_classify);
900 l2_policer_classify (vlib_main_t * vm,
901 vlib_node_runtime_t * node, vlib_frame_t * frame)
903 return policer_classify_inline (vm, node, frame, POLICER_CLASSIFY_TABLE_L2);
906 VLIB_REGISTER_NODE (l2_policer_classify_node) =
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 =
914 [POLICER_CLASSIFY_NEXT_INDEX_DROP] = "error-drop",}
917 VLIB_NODE_FUNCTION_MULTIARCH (l2_policer_classify_node, l2_policer_classify);
920 static clib_error_t *
921 policer_classify_init (vlib_main_t * vm)
923 policer_classify_main_t *pcm = &policer_classify_main;
926 pcm->vnet_main = vnet_get_main ();
927 pcm->vnet_classify_main = &vnet_classify_main;
929 /* Initialize L2 feature next-node indexes */
930 feat_bitmap_init_next_nodes (vm,
931 l2_policer_classify_node.index,
933 l2input_get_feat_names (),
934 pcm->feat_next_node_index);
939 VLIB_INIT_FUNCTION (policer_classify_init);
942 * fd.io coding-style-patch-verification: ON
945 * eval: (c-set-style "gnu")