aboutsummaryrefslogtreecommitdiffstats
path: root/vnet
diff options
context:
space:
mode:
authorMatus Fabian <matfabia@cisco.com>2016-06-20 08:10:42 -0700
committerDave Barach <openvpp@barachs.net>2016-07-26 15:52:03 +0000
commit70e6a8dd52b5c2814737b9a75763ff239a7e053d (patch)
tree403733620fb32f571da1b9bf5be9ce740a9b1054 /vnet
parentac0798db359eb0de2eae1a54b63dfaa9534984c8 (diff)
policer classify
JIRA: VPP-114 If the classifier finds a matching entry, it sends packet to the policer, packet should be pre-colored for color-aware policers. Change-Id: I10cb53b49907137769418f230df2cab577d0f3a0 Signed-off-by: Matus Fabian <matfabia@cisco.com>
Diffstat (limited to 'vnet')
-rw-r--r--vnet/Makefile.am4
-rw-r--r--vnet/vnet/classify/policer_classify.c232
-rw-r--r--vnet/vnet/classify/policer_classify.h55
-rw-r--r--vnet/vnet/classify/vnet_classify.c45
-rw-r--r--vnet/vnet/classify/vnet_classify.h4
-rw-r--r--vnet/vnet/ip/ip4.h1
-rw-r--r--vnet/vnet/ip/ip4_forward.c9
-rw-r--r--vnet/vnet/ip/ip6.h1
-rw-r--r--vnet/vnet/ip/ip6_forward.c8
-rw-r--r--vnet/vnet/ip/ip_init.c3
-rw-r--r--vnet/vnet/l2/l2_input.h3
-rw-r--r--vnet/vnet/policer/node_funcs.c477
-rw-r--r--vnet/vnet/policer/policer.c72
-rw-r--r--vnet/vnet/policer/policer.h7
-rw-r--r--vnet/vnet/policer/xlate.c6
-rw-r--r--vnet/vnet/policer/xlate.h1
16 files changed, 884 insertions, 44 deletions
diff --git a/vnet/Makefile.am b/vnet/Makefile.am
index 47e14b73..e9a73474 100644
--- a/vnet/Makefile.am
+++ b/vnet/Makefile.am
@@ -230,11 +230,13 @@ libvnet_la_SOURCES += \
vnet/classify/vnet_classify.c \
vnet/classify/ip_classify.c \
vnet/classify/input_acl.c \
+ vnet/classify/policer_classify.c \
vnet/classify/vnet_classify.h
nobase_include_HEADERS += \
vnet/classify/vnet_classify.h \
- vnet/classify/input_acl.h
+ vnet/classify/input_acl.h \
+ vnet/classify/policer_classify.h
########################################
# Layer 3 protocols go here
diff --git a/vnet/vnet/classify/policer_classify.c b/vnet/vnet/classify/policer_classify.c
new file mode 100644
index 00000000..c4c44849
--- /dev/null
+++ b/vnet/vnet/classify/policer_classify.c
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <vnet/classify/policer_classify.h>
+
+static void
+vnet_policer_classify_feature_enable (vlib_main_t * vnm,
+ policer_classify_main_t * pcm,
+ u32 sw_if_index,
+ policer_classify_table_id_t tid,
+ int feature_enable)
+{
+ if (tid == POLICER_CLASSIFY_TABLE_L2)
+ {
+ l2input_intf_bitmap_enable (sw_if_index, L2INPUT_FEAT_POLICER_CLAS,
+ feature_enable);
+ }
+ else
+ {
+ ip_lookup_main_t * lm;
+ ip_config_main_t * ipcm;
+ u32 ftype;
+ u32 ci;
+
+ if (tid == POLICER_CLASSIFY_TABLE_IP4)
+ {
+ lm = &ip4_main.lookup_main;
+ ftype = ip4_main.ip4_unicast_rx_feature_policer_classify;
+ }
+ else
+ {
+ lm = &ip6_main.lookup_main;
+ ftype = ip6_main.ip6_unicast_rx_feature_policer_classify;
+ }
+
+ ipcm = &lm->rx_config_mains[VNET_UNICAST];
+
+ ci = ipcm->config_index_by_sw_if_index[sw_if_index];
+ ci = (feature_enable ? vnet_config_add_feature : vnet_config_del_feature)
+ (vnm, &ipcm->config_main, ci, ftype, 0, 0);
+
+ ipcm->config_index_by_sw_if_index[sw_if_index] = ci;
+ pcm->vnet_config_main[tid] = &ipcm->config_main;
+ }
+}
+
+int vnet_set_policer_classify_intfc (vlib_main_t * vm, u32 sw_if_index,
+ u32 ip4_table_index, u32 ip6_table_index,
+ u32 l2_table_index, u32 is_add)
+{
+ policer_classify_main_t * pcm = &policer_classify_main;
+ vnet_classify_main_t * vcm = pcm->vnet_classify_main;
+ u32 pct[POLICER_CLASSIFY_N_TABLES] = {ip4_table_index, ip6_table_index,
+ l2_table_index};
+ u32 ti;
+
+ /* Assume that we've validated sw_if_index in the API layer */
+
+ for (ti = 0; ti < POLICER_CLASSIFY_N_TABLES; ti++)
+ {
+ if (pct[ti] == ~0)
+ continue;
+
+ if (pool_is_free_index (vcm->tables, pct[ti]))
+ return VNET_API_ERROR_NO_SUCH_TABLE;
+
+ vec_validate_init_empty
+ (pcm->classify_table_index_by_sw_if_index[ti], sw_if_index, ~0);
+
+ /* Reject any DEL operation with wrong sw_if_index */
+ if (!is_add &&
+ (pct[ti] != pcm->classify_table_index_by_sw_if_index[ti][sw_if_index]))
+ {
+ clib_warning ("Non-existent intf_idx=%d with table_index=%d for delete",
+ sw_if_index, pct[ti]);
+ return VNET_API_ERROR_NO_SUCH_TABLE;
+ }
+
+ /* Return ok on ADD operaton if feature is already enabled */
+ if (is_add &&
+ pcm->classify_table_index_by_sw_if_index[ti][sw_if_index] != ~0)
+ return 0;
+
+ vnet_policer_classify_feature_enable (vm, pcm, sw_if_index, ti, is_add);
+
+ if (is_add)
+ pcm->classify_table_index_by_sw_if_index[ti][sw_if_index] = pct[ti];
+ else
+ pcm->classify_table_index_by_sw_if_index[ti][sw_if_index] = ~0;
+ }
+
+
+ return 0;
+}
+
+static clib_error_t *
+set_policer_classify_command_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ vnet_main_t * vnm = vnet_get_main();
+ u32 sw_if_index = ~0;
+ u32 ip4_table_index = ~0;
+ u32 ip6_table_index = ~0;
+ u32 l2_table_index = ~0;
+ u32 is_add = 1;
+ u32 idx_cnt = 0;
+ int rv;
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "interface %U", unformat_vnet_sw_interface,
+ vnm, &sw_if_index))
+ ;
+ else if (unformat (input, "ip4-table %d", &ip4_table_index))
+ idx_cnt++;
+ else if (unformat (input, "ip6-table %d", &ip6_table_index))
+ idx_cnt++;
+ else if (unformat (input, "l2-table %d", &l2_table_index))
+ idx_cnt++;
+ else if (unformat (input, "del"))
+ is_add = 0;
+ else
+ break;
+ }
+
+ if (sw_if_index == ~0)
+ return clib_error_return (0, "Interface must be specified.");
+
+ if (!idx_cnt)
+ return clib_error_return (0, "Table index should be specified.");
+
+ if (idx_cnt > 1)
+ return clib_error_return (0, "Only one table index per API is allowed.");
+
+ rv = vnet_set_policer_classify_intfc(vm, sw_if_index, ip4_table_index,
+ ip6_table_index, l2_table_index, is_add);
+
+ switch (rv)
+ {
+ case 0:
+ break;
+
+ case VNET_API_ERROR_NO_MATCHING_INTERFACE:
+ return clib_error_return (0, "No such interface");
+
+ case VNET_API_ERROR_NO_SUCH_ENTRY:
+ return clib_error_return (0, "No such classifier table");
+ }
+ return 0;
+}
+
+VLIB_CLI_COMMAND (set_input_acl_command, static) = {
+ .path = "set policer classify",
+ .short_help =
+ "set policer classify interface <int> [ip4-table <index>]\n"
+ " [ip6-table <index>] [l2-table <index>] [del]",
+ .function = set_policer_classify_command_fn,
+};
+
+static uword
+unformat_table_type (unformat_input_t * input, va_list * va)
+{
+ u32 * r = va_arg (*va, u32 *);
+ u32 tid;
+
+ if (unformat (input, "ip4"))
+ tid = POLICER_CLASSIFY_TABLE_IP4;
+ else if (unformat (input, "ip6"))
+ tid = POLICER_CLASSIFY_TABLE_IP6;
+ else if (unformat (input, "l2"))
+ tid = POLICER_CLASSIFY_TABLE_L2;
+ else
+ return 0;
+
+ *r = tid;
+ return 1;
+}
+static clib_error_t *
+show_policer_classify_command_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ policer_classify_main_t * pcm = &policer_classify_main;
+ u32 type = POLICER_CLASSIFY_N_TABLES;
+ u32 * vec_tbl;
+ int i;
+
+ if (unformat (input, "type %U", unformat_table_type, &type))
+ ;
+ else
+ return clib_error_return (0, "Type must be specified.");;
+
+ if (type == POLICER_CLASSIFY_N_TABLES)
+ return clib_error_return (0, "Invalid table type.");
+
+ vec_tbl = pcm->classify_table_index_by_sw_if_index[type];
+
+ if (vec_len(vec_tbl))
+ vlib_cli_output (vm, "%10s%20s\t\t%s", "Intfc idx", "Classify table",
+ "Interface name");
+ else
+ vlib_cli_output (vm, "No tables configured.");
+
+ for (i = 0; i < vec_len (vec_tbl); i++)
+ {
+ if (vec_elt(vec_tbl, i) == ~0)
+ continue;
+
+ vlib_cli_output (vm, "%10d%20d\t\t%U", i, vec_elt(vec_tbl, i),
+ format_vnet_sw_if_index_name, pcm->vnet_main, i);
+ }
+
+ return 0;
+}
+
+VLIB_CLI_COMMAND (show_policer_classify_command, static) = {
+ .path = "show classify policer",
+ .short_help = "show classify policer type [ip4|ip6|l2]",
+ .function = show_policer_classify_command_fn,
+};
diff --git a/vnet/vnet/classify/policer_classify.h b/vnet/vnet/classify/policer_classify.h
new file mode 100644
index 00000000..30656444
--- /dev/null
+++ b/vnet/vnet/classify/policer_classify.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2016 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __included_vnet_policer_classify_h__
+#define __included_vnet_policer_classify_h__
+
+#include <vlib/vlib.h>
+#include <vnet/vnet.h>
+#include <vnet/classify/vnet_classify.h>
+
+typedef enum {
+ POLICER_CLASSIFY_TABLE_IP4,
+ POLICER_CLASSIFY_TABLE_IP6,
+ POLICER_CLASSIFY_TABLE_L2,
+ POLICER_CLASSIFY_N_TABLES,
+} policer_classify_table_id_t;
+
+typedef enum {
+ POLICER_CLASSIFY_NEXT_INDEX_DROP,
+ POLICER_CLASSIFY_NEXT_INDEX_N_NEXT,
+} policer_classify_next_index_t;
+
+typedef struct {
+ /* Classifier table vectors */
+ u32 * classify_table_index_by_sw_if_index [POLICER_CLASSIFY_N_TABLES];
+
+ /* L2 next nodes for each feature */
+ u32 feat_next_node_index[32];
+
+ /* Convenience variables */
+ vlib_main_t * vlib_main;
+ vnet_main_t * vnet_main;
+ vnet_classify_main_t * vnet_classify_main;
+ vnet_config_main_t * vnet_config_main [POLICER_CLASSIFY_N_TABLES];
+} policer_classify_main_t;
+
+policer_classify_main_t policer_classify_main;
+
+int vnet_set_policer_classify_intfc (vlib_main_t * vm, u32 sw_if_index,
+ u32 ip4_table_index, u32 ip6_table_index,
+ u32 l2_table_index, u32 is_add);
+
+#endif /* __included_vnet_policer_classify_h__ */
diff --git a/vnet/vnet/classify/vnet_classify.c b/vnet/vnet/classify/vnet_classify.c
index 11d3714c..23aa5159 100644
--- a/vnet/vnet/classify/vnet_classify.c
+++ b/vnet/vnet/classify/vnet_classify.c
@@ -88,6 +88,14 @@ vnet_classify_register_unformat_acl_next_index_fn (unformat_function_t * fn)
vec_add1 (cm->unformat_acl_next_index_fns, fn);
}
+void
+vnet_classify_register_unformat_policer_next_index_fn (unformat_function_t * fn)
+{
+ vnet_classify_main_t * cm = &vnet_classify_main;
+
+ vec_add1 (cm->unformat_policer_next_index_fns, fn);
+}
+
void vnet_classify_register_unformat_opaque_index_fn (unformat_function_t * fn)
{
vnet_classify_main_t * cm = &vnet_classify_main;
@@ -1141,6 +1149,37 @@ uword unformat_acl_next_index (unformat_input_t * input, va_list * args)
return 1;
}
+uword unformat_policer_next_index (unformat_input_t * input, va_list * args)
+{
+ u32 * next_indexp = va_arg (*args, u32 *);
+ vnet_classify_main_t * cm = &vnet_classify_main;
+ u32 next_index = 0;
+ u32 tmp;
+ int i;
+
+ /* First try registered unformat fns, allowing override... */
+ for (i = 0; i < vec_len (cm->unformat_policer_next_index_fns); i++)
+ {
+ if (unformat (input, "%U", cm->unformat_policer_next_index_fns[i], &tmp))
+ {
+ next_index = tmp;
+ goto out;
+ }
+ }
+
+ if (unformat (input, "%d", &tmp))
+ {
+ next_index = tmp;
+ goto out;
+ }
+
+ return 0;
+
+ out:
+ *next_indexp = next_index;
+ return 1;
+}
+
static clib_error_t *
classify_table_command_fn (vlib_main_t * vm,
unformat_input_t * input,
@@ -1763,6 +1802,9 @@ classify_session_command_fn (vlib_main_t * vm,
else if (unformat (input, "acl-hit-next %U", unformat_acl_next_index,
&hit_next_index))
;
+ else if (unformat (input, "policer-hit-next %U",
+ unformat_policer_next_index, &hit_next_index))
+ ;
else if (unformat (input, "opaque-index %lld", &opaque_index))
;
else if (unformat (input, "match %U", unformat_classify_match,
@@ -1813,7 +1855,8 @@ classify_session_command_fn (vlib_main_t * vm,
VLIB_CLI_COMMAND (classify_session_command, static) = {
.path = "classify session",
.short_help =
- "classify session [hit-next|l2-hit-next|acl-hit-next <next_index>]"
+ "classify session [hit-next|l2-hit-next|acl-hit-next <next_index>|"
+ "policer-hit-next <policer_name>]"
"\n table-index <nn> match [hex] [l2] [l3 ip4] [opaque-index <index>]",
.function = classify_session_command_fn,
};
diff --git a/vnet/vnet/classify/vnet_classify.h b/vnet/vnet/classify/vnet_classify.h
index b19704eb..f609aaa4 100644
--- a/vnet/vnet/classify/vnet_classify.h
+++ b/vnet/vnet/classify/vnet_classify.h
@@ -162,6 +162,7 @@ struct _vnet_classify_main {
unformat_function_t ** unformat_l2_next_index_fns;
unformat_function_t ** unformat_ip_next_index_fns;
unformat_function_t ** unformat_acl_next_index_fns;
+ unformat_function_t ** unformat_policer_next_index_fns;
unformat_function_t ** unformat_opaque_index_fns;
/* convenience variables */
@@ -484,6 +485,9 @@ void vnet_classify_register_unformat_l2_next_index_fn
void vnet_classify_register_unformat_acl_next_index_fn
(unformat_function_t * fn);
+void vnet_classify_register_unformat_policer_next_index_fn
+(unformat_function_t * fn);
+
void vnet_classify_register_unformat_opaque_index_fn (unformat_function_t * fn);
#endif /* __included_vnet_classify_h__ */
diff --git a/vnet/vnet/ip/ip4.h b/vnet/vnet/ip/ip4.h
index 5ea4ebf5..fb04893a 100644
--- a/vnet/vnet/ip/ip4.h
+++ b/vnet/vnet/ip/ip4.h
@@ -137,6 +137,7 @@ typedef struct ip4_main_t {
u32 ip4_unicast_rx_feature_check_access;
u32 ip4_unicast_rx_feature_source_reachable_via_rx;
u32 ip4_unicast_rx_feature_source_reachable_via_any;
+ u32 ip4_unicast_rx_feature_policer_classify;
u32 ip4_unicast_rx_feature_ipsec;
u32 ip4_unicast_rx_feature_vpath;
u32 ip4_unicast_rx_feature_lookup;
diff --git a/vnet/vnet/ip/ip4_forward.c b/vnet/vnet/ip/ip4_forward.c
index d2e761fe..2ccdd37c 100644
--- a/vnet/vnet/ip/ip4_forward.c
+++ b/vnet/vnet/ip/ip4_forward.c
@@ -1380,11 +1380,18 @@ VNET_IP4_UNICAST_FEATURE_INIT (ip4_source_check_1, static) = {
VNET_IP4_UNICAST_FEATURE_INIT (ip4_source_check_2, static) = {
.node_name = "ip4-source-check-via-any",
- .runs_before = {"ipsec-input-ip4", 0},
+ .runs_before = {"ip4-policer-classify", 0},
.feature_index =
&ip4_main.ip4_unicast_rx_feature_source_reachable_via_any,
};
+VNET_IP4_UNICAST_FEATURE_INIT (ip4_policer_classify, static) = {
+ .node_name = "ip4-policer-classify",
+ .runs_before = {"ipsec-input-ip4", 0},
+ .feature_index =
+ &ip4_main.ip4_unicast_rx_feature_policer_classify,
+};
+
VNET_IP4_UNICAST_FEATURE_INIT (ip4_ipsec, static) = {
.node_name = "ipsec-input-ip4",
.runs_before = {"vpath-input-ip4", 0},
diff --git a/vnet/vnet/ip/ip6.h b/vnet/vnet/ip/ip6.h
index 22d1a4fe..3d6c9f42 100644
--- a/vnet/vnet/ip/ip6.h
+++ b/vnet/vnet/ip/ip6.h
@@ -148,6 +148,7 @@ typedef struct ip6_main_t {
/* Built-in unicast feature path indices, see ip_feature_init_cast(...) */
u32 ip6_unicast_rx_feature_check_access;
+ u32 ip6_unicast_rx_feature_policer_classify;
u32 ip6_unicast_rx_feature_ipsec;
u32 ip6_unicast_rx_feature_l2tp_decap;
u32 ip6_unicast_rx_feature_vpath;
diff --git a/vnet/vnet/ip/ip6_forward.c b/vnet/vnet/ip/ip6_forward.c
index 823daa69..57057a72 100644
--- a/vnet/vnet/ip/ip6_forward.c
+++ b/vnet/vnet/ip/ip6_forward.c
@@ -1260,10 +1260,16 @@ VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (ip6_sw_interface_admin_up_down);
/* Built-in ip6 unicast rx feature path definition */
VNET_IP6_UNICAST_FEATURE_INIT (ip6_inacl, static) = {
.node_name = "ip6-inacl",
- .runs_before = {"ipsec-input-ip6", 0},
+ .runs_before = {"ip6-policer-classify", 0},
.feature_index = &ip6_main.ip6_unicast_rx_feature_check_access,
};
+VNET_IP6_UNICAST_FEATURE_INIT (ip6_policer_classify, static) = {
+ .node_name = "ip6-policer-classify",
+ .runs_before = {"ipsec-input-ip6", 0},
+ .feature_index = &ip6_main.ip6_unicast_rx_feature_policer_classify,
+};
+
VNET_IP6_UNICAST_FEATURE_INIT (ip6_ipsec, static) = {
.node_name = "ipsec-input-ip6",
.runs_before = {"l2tp-decap", 0},
diff --git a/vnet/vnet/ip/ip_init.c b/vnet/vnet/ip/ip_init.c
index 8b6659de..c0c1c956 100644
--- a/vnet/vnet/ip/ip_init.c
+++ b/vnet/vnet/ip/ip_init.c
@@ -133,6 +133,9 @@ do { \
if ((error = vlib_call_init_function (vm, input_acl_init)))
return error;
+ if ((error = vlib_call_init_function (vm, policer_classify_init)))
+ return error;
+
return error;
}
diff --git a/vnet/vnet/l2/l2_input.h b/vnet/vnet/l2/l2_input.h
index 50649e79..f0407554 100644
--- a/vnet/vnet/l2/l2_input.h
+++ b/vnet/vnet/l2/l2_input.h
@@ -109,7 +109,8 @@ l2input_bd_config_from_index (l2input_main_t * l2im, u32 bd_index)
_(ACL, "l2-input-acl") \
_(QOS, "feature-bitmap-drop") \
_(CFM, "feature-bitmap-drop") \
- _(SPAN, "feature-bitmap-drop")
+ _(SPAN, "feature-bitmap-drop") \
+ _(POLICER_CLAS, "l2-policer-classify")
// Feature bitmap positions
typedef enum {
diff --git a/vnet/vnet/policer/node_funcs.c b/vnet/vnet/policer/node_funcs.c
index 6147ea51..0858a86d 100644
--- a/vnet/vnet/policer/node_funcs.c
+++ b/vnet/vnet/policer/node_funcs.c
@@ -19,6 +19,8 @@
#include <vnet/vnet.h>
#include <vnet/policer/policer.h>
#include <vnet/ip/ip.h>
+#include <vnet/classify/policer_classify.h>
+#include <vnet/classify/vnet_classify.h>
#define IP4_NON_DSCP_BITS 0x03
#define IP4_DSCP_SHIFT 2
@@ -93,6 +95,31 @@ void vnet_policer_mark (vlib_buffer_t * b, u8 dscp)
}
}
+static_always_inline
+u8 vnet_policer_police (vlib_main_t * vm,
+ vlib_buffer_t * b,
+ u32 policer_index,
+ u64 time_in_policer_periods,
+ policer_result_e packet_color)
+{
+ u8 act;
+ u32 len;
+ u32 col;
+ policer_read_response_type_st *pol;
+ vnet_policer_main_t * pm = &vnet_policer_main;
+
+ len = vlib_buffer_length_in_chain (vm, b);
+ pol = &pm->policers [policer_index];
+ col = vnet_police_packet (pol, len,
+ packet_color,
+ time_in_policer_periods);
+ act = pol->action[col];
+ if (PREDICT_TRUE(act == SSE2_QOS_ACTION_MARK_AND_TRANSMIT))
+ vnet_policer_mark(b, pol->mark_dscp[col]);
+
+ return act;
+ }
+
static inline
uword vnet_policer_inline (vlib_main_t * vm,
vlib_node_runtime_t * node,
@@ -126,9 +153,6 @@ uword vnet_policer_inline (vlib_main_t * vm,
u32 next0, next1;
u32 sw_if_index0, sw_if_index1;
u32 pi0 = 0, pi1 = 0;
- u32 len0, len1;
- u32 col0, col1;
- policer_read_response_type_st * pol0, * pol1;
u8 act0, act1;
/* Prefetch next iteration. */
@@ -182,19 +206,11 @@ uword vnet_policer_inline (vlib_main_t * vm,
pm->policer_index_by_sw_if_index [sw_if_index1];
}
- len0 = vlib_buffer_length_in_chain (vm, b0);
- pol0 = &pm->policers [pi0];
- col0 = vnet_police_packet (pol0, len0,
- POLICE_CONFORM /* no chaining */,
- time_in_policer_periods);
- act0 = pol0->action[col0];
+ act0 = vnet_policer_police(vm, b0, pi0, time_in_policer_periods,
+ POLICE_CONFORM /* no chaining */);
- len1 = vlib_buffer_length_in_chain (vm, b1);
- pol1 = &pm->policers [pi1];
- col1 = vnet_police_packet (pol1, len1,
- POLICE_CONFORM /* no chaining */,
- time_in_policer_periods);
- act1 = pol1->action[col1];
+ act1 = vnet_policer_police(vm, b1, pi1, time_in_policer_periods,
+ POLICE_CONFORM /* no chaining */);
if (PREDICT_FALSE(act0 == SSE2_QOS_ACTION_DROP)) /* drop action */
{
@@ -203,8 +219,6 @@ uword vnet_policer_inline (vlib_main_t * vm,
}
else /* transmit or mark-and-transmit action */
{
- if (PREDICT_TRUE(act0 == SSE2_QOS_ACTION_MARK_AND_TRANSMIT))
- vnet_policer_mark(b0, pol0->mark_dscp[col0]);
transmitted++;
}
@@ -215,8 +229,6 @@ uword vnet_policer_inline (vlib_main_t * vm,
}
else /* transmit or mark-and-transmit action */
{
- if (PREDICT_TRUE(act1 == SSE2_QOS_ACTION_MARK_AND_TRANSMIT))
- vnet_policer_mark(b1, pol1->mark_dscp[col1]);
transmitted++;
}
@@ -252,9 +264,6 @@ uword vnet_policer_inline (vlib_main_t * vm,
u32 next0;
u32 sw_if_index0;
u32 pi0 = 0;
- u32 len0;
- u32 col0;
- policer_read_response_type_st * pol0;
u8 act0;
bi0 = from[0];
@@ -282,13 +291,9 @@ uword vnet_policer_inline (vlib_main_t * vm,
pm->policer_index_by_sw_if_index [sw_if_index0];
}
- len0 = vlib_buffer_length_in_chain (vm, b0);
- pol0 = &pm->policers [pi0];
- col0 = vnet_police_packet (pol0, len0,
- POLICE_CONFORM /* no chaining */,
- time_in_policer_periods);
- act0 = pol0->action[col0];
-
+ act0 = vnet_policer_police(vm, b0, pi0, time_in_policer_periods,
+ POLICE_CONFORM /* no chaining */);
+
if (PREDICT_FALSE(act0 == SSE2_QOS_ACTION_DROP)) /* drop action */
{
next0 = VNET_POLICER_NEXT_DROP;
@@ -296,8 +301,6 @@ uword vnet_policer_inline (vlib_main_t * vm,
}
else /* transmit or mark-and-transmit action */
{
- if (PREDICT_TRUE(act0 == SSE2_QOS_ACTION_MARK_AND_TRANSMIT))
- vnet_policer_mark(b0, pol0->mark_dscp[col0]);
transmitted++;
}
@@ -507,3 +510,415 @@ VLIB_CLI_COMMAND (test_patch_command, static) = {
#endif /* TEST_CODE */
+
+
+typedef struct {
+ u32 sw_if_index;
+ u32 next_index;
+ u32 table_index;
+ u32 offset;
+ u32 policer_index;
+} policer_classify_trace_t;
+
+static u8 *
+format_policer_classify_trace (u8 * s, va_list * args)
+{
+ CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
+ CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
+ policer_classify_trace_t * t = va_arg (*args, policer_classify_trace_t *);
+
+ s = format (s, "POLICER_CLASSIFY: sw_if_index %d next %d table %d offset %d"
+ " policer_index %d",
+ t->sw_if_index, t->next_index, t->table_index, t->offset,
+ t->policer_index);
+ return s;
+}
+
+#define foreach_policer_classify_error \
+_(MISS, "Policer classify misses") \
+_(HIT, "Policer classify hits") \
+_(CHAIN_HIT, "Polcier classify hits after chain walk") \
+_(DROP, "Policer classify action drop")
+
+typedef enum {
+#define _(sym,str) POLICER_CLASSIFY_ERROR_##sym,
+ foreach_policer_classify_error
+#undef _
+ POLICER_CLASSIFY_N_ERROR,
+} policer_classify_error_t;
+
+static char * policer_classify_error_strings[] = {
+#define _(sym,string) string,
+ foreach_policer_classify_error
+#undef _
+};
+
+static inline uword
+policer_classify_inline (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame,
+ policer_classify_table_id_t tid)
+{
+ u32 n_left_from, * from, * to_next;
+ policer_classify_next_index_t next_index;
+ policer_classify_main_t * pcm = &policer_classify_main;
+ vnet_classify_main_t * vcm = pcm->vnet_classify_main;
+ f64 now = vlib_time_now (vm);
+ u32 hits = 0;
+ u32 misses = 0;
+ u32 chain_hits = 0;
+ u32 drop = 0;
+ u32 n_next_nodes;
+ u64 time_in_policer_periods;
+
+ time_in_policer_periods =
+ clib_cpu_time_now() >> POLICER_TICKS_PER_PERIOD_SHIFT;
+
+ n_next_nodes = node->n_next_nodes;
+
+ from = vlib_frame_vector_args (frame);
+ n_left_from = frame->n_vectors;
+
+ /* First pass: compute hashes */
+ while (n_left_from > 2)
+ {
+ vlib_buffer_t * b0, * b1;
+ u32 bi0, bi1;
+ u8 * h0, * h1;
+ u32 sw_if_index0, sw_if_index1;
+ u32 table_index0, table_index1;
+ vnet_classify_table_t * t0, * t1;
+
+ /* Prefetch next iteration */
+ {
+ vlib_buffer_t * p1, * p2;
+
+ p1 = vlib_get_buffer (vm, from[1]);
+ p2 = vlib_get_buffer (vm, from[2]);
+
+ vlib_prefetch_buffer_header (p1, STORE);
+ CLIB_PREFETCH (p1->data, CLIB_CACHE_LINE_BYTES, STORE);
+ vlib_prefetch_buffer_header (p2, STORE);
+ CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
+ }
+
+ bi0 = from[0];
+ b0 = vlib_get_buffer (vm, bi0);
+ h0 = b0->data;
+
+ bi1 = from[1];
+ b1 = vlib_get_buffer (vm, bi1);
+ h1 = b1->data;
+
+ sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
+ table_index0 = pcm->classify_table_index_by_sw_if_index[tid][sw_if_index0];
+
+ sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX];
+ table_index1 = pcm->classify_table_index_by_sw_if_index[tid][sw_if_index1];
+
+ t0 = pool_elt_at_index (vcm->tables, table_index0);
+
+ t1 = pool_elt_at_index (vcm->tables, table_index1);
+
+ vnet_buffer(b0)->l2_classify.hash =
+ vnet_classify_hash_packet (t0, (u8 *) h0);
+
+ vnet_classify_prefetch_bucket (t0, vnet_buffer(b0)->l2_classify.hash);
+
+ vnet_buffer(b1)->l2_classify.hash =
+ vnet_classify_hash_packet (t1, (u8 *) h1);
+
+ vnet_classify_prefetch_bucket (t1, vnet_buffer(b1)->l2_classify.hash);
+
+ vnet_buffer(b0)->l2_classify.table_index = table_index0;
+
+ vnet_buffer(b1)->l2_classify.table_index = table_index1;
+
+ from += 2;
+ n_left_from -= 2;
+ }
+
+ while (n_left_from > 0)
+ {
+ vlib_buffer_t * b0;
+ u32 bi0;
+ u8 * h0;
+ u32 sw_if_index0;
+ u32 table_index0;
+ vnet_classify_table_t * t0;
+
+ bi0 = from[0];
+ b0 = vlib_get_buffer (vm, bi0);
+ h0 = b0->data;
+
+ sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
+ table_index0 = pcm->classify_table_index_by_sw_if_index[tid][sw_if_index0];
+
+ t0 = pool_elt_at_index (vcm->tables, table_index0);
+ vnet_buffer(b0)->l2_classify.hash =
+ vnet_classify_hash_packet (t0, (u8 *) h0);
+
+ vnet_buffer(b0)->l2_classify.table_index = table_index0;
+ vnet_classify_prefetch_bucket (t0, vnet_buffer(b0)->l2_classify.hash);
+
+ from++;
+ n_left_from--;
+ }
+
+ next_index = node->cached_next_index;
+ from = vlib_frame_vector_args (frame);
+ n_left_from = frame->n_vectors;
+
+ while (n_left_from > 0)
+ {
+ u32 n_left_to_next;
+
+ vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
+
+ /* Not enough load/store slots to dual loop... */
+ while (n_left_from > 0 && n_left_to_next > 0)
+ {
+ u32 bi0;
+ vlib_buffer_t * b0;
+ u32 next0 = POLICER_CLASSIFY_NEXT_INDEX_DROP;
+ u32 table_index0;
+ vnet_classify_table_t * t0;
+ vnet_classify_entry_t * e0;
+ u64 hash0;
+ u8 * h0;
+ u8 act0;
+
+ /* Stride 3 seems to work best */
+ if (PREDICT_TRUE (n_left_from > 3))
+ {
+ vlib_buffer_t * p1 = vlib_get_buffer(vm, from[3]);
+ vnet_classify_table_t * tp1;
+ u32 table_index1;
+ u64 phash1;
+
+ table_index1 = vnet_buffer(p1)->l2_classify.table_index;
+
+ if (PREDICT_TRUE (table_index1 != ~0))
+ {
+ tp1 = pool_elt_at_index (vcm->tables, table_index1);
+ phash1 = vnet_buffer(p1)->l2_classify.hash;
+ vnet_classify_prefetch_entry (tp1, phash1);
+ }
+ }
+
+ /* Speculatively enqueue b0 to the current next frame */
+ bi0 = from[0];
+ to_next[0] = bi0;
+ from += 1;
+ to_next += 1;
+ n_left_from -= 1;
+ n_left_to_next -= 1;
+
+ b0 = vlib_get_buffer (vm, bi0);
+ h0 = b0->data;
+ table_index0 = vnet_buffer(b0)->l2_classify.table_index;
+ e0 = 0;
+ t0 = 0;
+
+ if (tid == POLICER_CLASSIFY_TABLE_L2)
+ {
+ /* Feature bitmap update */
+ vnet_buffer(b0)->l2.feature_bitmap &= ~L2INPUT_FEAT_POLICER_CLAS;
+ /* Determine the next node */
+ next0 = feat_bitmap_get_next_node_index(pcm->feat_next_node_index,
+ vnet_buffer(b0)->l2.feature_bitmap);
+ }
+ else
+ vnet_get_config_data (pcm->vnet_config_main[tid],
+ &b0->current_config_index,
+ &next0,
+ /* # bytes of config data */ 0);
+
+ vnet_buffer(b0)->l2_classify.opaque_index = ~0;
+
+ if (PREDICT_TRUE(table_index0 != ~0))
+ {
+ hash0 = vnet_buffer(b0)->l2_classify.hash;
+ t0 = pool_elt_at_index (vcm->tables, table_index0);
+ e0 = vnet_classify_find_entry (t0, (u8 *) h0, hash0, now);
+
+ if (e0)
+ {
+ act0 = vnet_policer_police(vm,
+ b0,
+ e0->next_index,
+ time_in_policer_periods,
+ e0->opaque_index);
+ if (PREDICT_FALSE(act0 == SSE2_QOS_ACTION_DROP))
+ {
+ next0 = POLICER_CLASSIFY_NEXT_INDEX_DROP;
+ b0->error = node->errors[POLICER_CLASSIFY_ERROR_DROP];
+ drop++;
+ }
+ hits++;
+ }
+ else
+ {
+ while (1)
+ {
+ if (PREDICT_TRUE(t0->next_table_index != ~0))
+ {
+ t0 = pool_elt_at_index (vcm->tables,
+ t0->next_table_index);
+ }
+ else
+ {
+ next0 = (t0->miss_next_index < n_next_nodes)?
+ t0->miss_next_index:next0;
+ misses++;
+ break;
+ }
+
+ hash0 = vnet_classify_hash_packet (t0, (u8 *) h0);
+ e0 = vnet_classify_find_entry (t0, (u8 *) h0, hash0, now);
+ if (e0)
+ {
+ act0 = vnet_policer_police(vm,
+ b0,
+ e0->next_index,
+ time_in_policer_periods,
+ e0->opaque_index);
+ if (PREDICT_FALSE(act0 == SSE2_QOS_ACTION_DROP))
+ {
+ next0 = POLICER_CLASSIFY_NEXT_INDEX_DROP;
+ b0->error = node->errors[POLICER_CLASSIFY_ERROR_DROP];
+ drop++;
+ }
+ hits++;
+ chain_hits++;
+ break;
+ }
+ }
+ }
+ }
+ if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
+ && (b0->flags & VLIB_BUFFER_IS_TRACED)))
+ {
+ policer_classify_trace_t * t =
+ vlib_add_trace (vm, node, b0, sizeof (*t));
+ t->sw_if_index = vnet_buffer(b0)->sw_if_index[VLIB_RX];
+ t->next_index = next0;
+ t->table_index = t0 ? t0 - vcm->tables : ~0;
+ t->offset = e0 ? vnet_classify_get_offset (t0, e0): ~0;
+ t->policer_index = e0 ? e0->next_index: ~0;
+ }
+
+ /* Verify speculative enqueue, maybe switch current next frame */
+ vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
+ n_left_to_next, bi0, next0);
+ }
+
+ vlib_put_next_frame (vm, node, next_index, n_left_to_next);
+ }
+
+ vlib_node_increment_counter (vm, node->node_index,
+ POLICER_CLASSIFY_ERROR_MISS,
+ misses);
+ vlib_node_increment_counter (vm, node->node_index,
+ POLICER_CLASSIFY_ERROR_HIT,
+ hits);
+ vlib_node_increment_counter (vm, node->node_index,
+ POLICER_CLASSIFY_ERROR_CHAIN_HIT,
+ chain_hits);
+ vlib_node_increment_counter (vm, node->node_index,
+ POLICER_CLASSIFY_ERROR_DROP,
+ drop);
+
+ return frame->n_vectors;
+}
+
+static uword
+ip4_policer_classify (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame)
+{
+ return policer_classify_inline(vm, node, frame, POLICER_CLASSIFY_TABLE_IP4);
+}
+
+VLIB_REGISTER_NODE (ip4_policer_classify_node) = {
+ .function = ip4_policer_classify,
+ .name = "ip4-policer-classify",
+ .vector_size = sizeof (u32),
+ .format_trace = format_policer_classify_trace,
+ .n_errors = ARRAY_LEN(policer_classify_error_strings),
+ .error_strings = policer_classify_error_strings,
+ .n_next_nodes = POLICER_CLASSIFY_NEXT_INDEX_N_NEXT,
+ .next_nodes = {
+ [POLICER_CLASSIFY_NEXT_INDEX_DROP] = "error-drop",
+ },
+};
+
+VLIB_NODE_FUNCTION_MULTIARCH (ip4_policer_classify_node, ip4_policer_classify);
+
+static uword
+ip6_policer_classify (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame)
+{
+ return policer_classify_inline(vm, node, frame, POLICER_CLASSIFY_TABLE_IP6);
+}
+
+VLIB_REGISTER_NODE (ip6_policer_classify_node) = {
+ .function = ip6_policer_classify,
+ .name = "ip6-policer-classify",
+ .vector_size = sizeof (u32),
+ .format_trace = format_policer_classify_trace,
+ .n_errors = ARRAY_LEN(policer_classify_error_strings),
+ .error_strings = policer_classify_error_strings,
+ .n_next_nodes = POLICER_CLASSIFY_NEXT_INDEX_N_NEXT,
+ .next_nodes = {
+ [POLICER_CLASSIFY_NEXT_INDEX_DROP] = "error-drop",
+ },
+};
+
+VLIB_NODE_FUNCTION_MULTIARCH (ip6_policer_classify_node, ip6_policer_classify);
+
+static uword
+l2_policer_classify (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * frame)
+{
+ return policer_classify_inline(vm, node, frame, POLICER_CLASSIFY_TABLE_L2);
+}
+
+VLIB_REGISTER_NODE (l2_policer_classify_node) = {
+ .function = l2_policer_classify,
+ .name = "l2-policer-classify",
+ .vector_size = sizeof (u32),
+ .format_trace = format_policer_classify_trace,
+ .n_errors = ARRAY_LEN(policer_classify_error_strings),
+ .error_strings = policer_classify_error_strings,
+ .n_next_nodes = POLICER_CLASSIFY_NEXT_INDEX_N_NEXT,
+ .next_nodes = {
+ [POLICER_CLASSIFY_NEXT_INDEX_DROP] = "error-drop",
+ },
+};
+
+VLIB_NODE_FUNCTION_MULTIARCH (l2_policer_classify_node, l2_policer_classify);
+
+
+static clib_error_t *
+policer_classify_init (vlib_main_t *vm)
+{
+ policer_classify_main_t * pcm = &policer_classify_main;
+
+ pcm->vlib_main = vm;
+ pcm->vnet_main = vnet_get_main();
+ pcm->vnet_classify_main = &vnet_classify_main;
+
+ /* Initialize L2 feature next-node indexes */
+ feat_bitmap_init_next_nodes(vm,
+ l2_policer_classify_node.index,
+ L2INPUT_N_FEAT,
+ l2input_get_feat_names(),
+ pcm->feat_next_node_index);
+
+ return 0;
+}
+
+VLIB_INIT_FUNCTION (policer_classify_init);
diff --git a/vnet/vnet/policer/policer.c b/vnet/vnet/policer/policer.c
index 8ffa967b..f60f7a74 100644
--- a/vnet/vnet/policer/policer.c
+++ b/vnet/vnet/policer/policer.c
@@ -14,30 +14,43 @@
*/
#include <stdint.h>
#include <vnet/policer/policer.h>
+#include <vnet/classify/vnet_classify.h>
clib_error_t *
policer_add_del (vlib_main_t *vm,
- u8 * name, sse2_qos_pol_cfg_params_st * cfg,
+ u8 * name,
+ sse2_qos_pol_cfg_params_st * cfg,
+ u32 * policer_index,
u8 is_add)
{
vnet_policer_main_t *pm = &vnet_policer_main;
policer_read_response_type_st test_policer;
+ policer_read_response_type_st * policer;
uword * p;
+ u32 pi;
int rv;
+ p = hash_get_mem (pm->policer_config_by_name, name);
+
if (is_add == 0)
{
- p = hash_get_mem (pm->policer_config_by_name, name);
if (p == 0)
{
vec_free(name);
return clib_error_return (0, "No such policer configuration");
}
hash_unset_mem (pm->policer_config_by_name, name);
+ hash_unset_mem (pm->policer_index_by_name, name);
vec_free(name);
return 0;
}
+ if (p != 0)
+ {
+ vec_free(name);
+ return clib_error_return (0, "Policer already exists");
+ }
+
/* Vet the configuration before adding it to the table */
rv = sse2_pol_logical_2_physical (cfg, &test_policer);
@@ -55,6 +68,11 @@ policer_add_del (vlib_main_t *vm,
clib_memcpy (pp, &test_policer, sizeof (*pp));
hash_set_mem (pm->policer_config_by_name, name, cp - pm->configs);
+ pool_get_aligned (pm->policers, policer, CLIB_CACHE_LINE_BYTES);
+ policer[0] = pp[0];
+ pi = policer - pm->policers;
+ hash_set_mem (pm->policer_index_by_name, name, pi);
+ *policer_index = pi;
}
else
{
@@ -348,6 +366,44 @@ unformat_policer_action (unformat_input_t * input, va_list * va)
return 0;
}
+static uword
+unformat_policer_classify_next_index (unformat_input_t * input, va_list * va)
+{
+ u32 * r = va_arg (*va, u32 *);
+ vnet_policer_main_t *pm = &vnet_policer_main;
+ uword * p;
+ u8 * match_name = 0;
+
+ if (unformat (input, "%s", &match_name))
+ ;
+ else
+ return 0;
+
+ p = hash_get_mem (pm->policer_index_by_name, match_name);
+
+ if (p == 0)
+ return 0;
+
+ *r = p[0];
+
+ return 1;
+}
+
+static uword
+unformat_policer_classify_precolor (unformat_input_t * input, va_list * va)
+{
+ u32 * r = va_arg (*va, u32 *);
+
+ if (unformat (input, "conform-color"))
+ *r = POLICE_CONFORM;
+ else if (unformat (input, "exceed-color"))
+ *r = POLICE_EXCEED;
+ else
+ return 0;
+
+ return 1;
+}
+
#define foreach_config_param \
_(eb) \
_(cb) \
@@ -367,6 +423,7 @@ configure_policer_command_fn (vlib_main_t * vm,
unformat_input_t _line_input, * line_input = &_line_input;
u8 is_add = 1;
u8 * name = 0;
+ u32 pi;
/* Get a line of input. */
if (! unformat_user (input, unformat_line_input, line_input))
@@ -380,6 +437,8 @@ configure_policer_command_fn (vlib_main_t * vm,
is_add = 0;
else if (unformat(line_input, "name %s", &name))
;
+ else if (unformat(line_input, "color-aware"))
+ c.color_aware = 1;
#define _(a) else if (unformat (line_input, "%U", unformat_policer_##a, &c)) ;
foreach_config_param
@@ -392,7 +451,7 @@ configure_policer_command_fn (vlib_main_t * vm,
unformat_free (line_input);
- return policer_add_del(vm, name, &c, is_add);
+ return policer_add_del(vm, name, &c, &pi, is_add);
}
VLIB_CLI_COMMAND (configure_policer_command, static) = {
@@ -453,6 +512,13 @@ clib_error_t *policer_init (vlib_main_t * vm)
pm->vnet_main = vnet_get_main();
pm->policer_config_by_name = hash_create_string (0, sizeof (uword));
+ pm->policer_index_by_name = hash_create_string (0, sizeof (uword));
+
+ vnet_classify_register_unformat_policer_next_index_fn
+ (unformat_policer_classify_next_index);
+ vnet_classify_register_unformat_opaque_index_fn
+ (unformat_policer_classify_precolor);
+
return 0;
}
diff --git a/vnet/vnet/policer/policer.h b/vnet/vnet/policer/policer.h
index fba866f4..beef5b64 100644
--- a/vnet/vnet/policer/policer.h
+++ b/vnet/vnet/policer/policer.h
@@ -32,6 +32,9 @@ typedef struct {
/* Config by name hash */
uword * policer_config_by_name;
+ /* Policer by name hash */
+ uword * policer_index_by_name;
+
/* Policer by sw_if_index vector */
u32 * policer_index_by_sw_if_index;
@@ -85,7 +88,9 @@ typedef enum {
u8 * format_policer_instance (u8 * s, va_list * va);
clib_error_t * policer_add_del (vlib_main_t *vm,
- u8 * name, sse2_qos_pol_cfg_params_st * cfg,
+ u8 * name,
+ sse2_qos_pol_cfg_params_st * cfg,
+ u32 * policer_index,
u8 is_add);
#endif /* __included_policer_h__ */
diff --git a/vnet/vnet/policer/xlate.c b/vnet/vnet/policer/xlate.c
index f47982e3..934c488c 100644
--- a/vnet/vnet/policer/xlate.c
+++ b/vnet/vnet/policer/xlate.c
@@ -1045,10 +1045,6 @@ x86_pol_compute_hw_params (sse2_qos_pol_cfg_params_st *cfg,
(cfg->rfc == SSE2_QOS_POLICER_TYPE_2R3C_RFC_4115)) {
// Two-rate policer
- if (cfg->rfc == SSE2_QOS_POLICER_TYPE_2R3C_RFC_4115) {
- hw->color_aware = 1;
- }
-
if ((cfg->rb.kbps.cir_kbps == 0) || (cfg->rb.kbps.eir_kbps == 0) || (cfg->rb.kbps.eir_kbps < cfg->rb.kbps.cir_kbps) ||
(cfg->rb.kbps.cb_bytes == 0) || (cfg->rb.kbps.eb_bytes == 0)) {
SSE2_QOS_DEBUG_ERROR("Config parameter validation failed.");
@@ -1136,6 +1132,8 @@ sse2_pol_logical_2_physical (sse2_qos_pol_cfg_params_st *cfg,
phys->action[POLICE_VIOLATE] = cfg->violate_action.action_type;
phys->mark_dscp[POLICE_VIOLATE] = cfg->violate_action.dscp;
+ phys->color_aware = cfg->color_aware;
+
#if !defined (INTERNAL_SS) && !defined (X86)
// convert logical into hw params which involves qos calculations
rc = sse2_pol_compute_hw_params(&kbps_cfg, &pol_hw);
diff --git a/vnet/vnet/policer/xlate.h b/vnet/vnet/policer/xlate.h
index d3fdeded..69a58d25 100644
--- a/vnet/vnet/policer/xlate.h
+++ b/vnet/vnet/policer/xlate.h
@@ -136,6 +136,7 @@ typedef struct sse2_qos_pol_cfg_params_st_ {
uint8_t rate_type; /* sse2_qos_rate_type_en */
uint8_t rnd_type; /* sse2_qos_round_type_en */
uint8_t rfc; /* sse2_qos_policer_type_en */
+ uint8_t color_aware;
uint8_t overwrite_bucket; /* for debugging purposes */
uint32_t current_bucket; /* for debugging purposes */
uint32_t extended_bucket; /* for debugging purposes */