summaryrefslogtreecommitdiffstats
path: root/vnet/vnet/policer/node_funcs.c
diff options
context:
space:
mode:
Diffstat (limited to 'vnet/vnet/policer/node_funcs.c')
-rw-r--r--vnet/vnet/policer/node_funcs.c72
1 files changed, 62 insertions, 10 deletions
diff --git a/vnet/vnet/policer/node_funcs.c b/vnet/vnet/policer/node_funcs.c
index 739ce4551b6..6147ea51c1a 100644
--- a/vnet/vnet/policer/node_funcs.c
+++ b/vnet/vnet/policer/node_funcs.c
@@ -18,6 +18,12 @@
#include <vlib/vlib.h>
#include <vnet/vnet.h>
#include <vnet/policer/policer.h>
+#include <vnet/ip/ip.h>
+
+#define IP4_NON_DSCP_BITS 0x03
+#define IP4_DSCP_SHIFT 2
+#define IP6_NON_DSCP_BITS 0xf03fffff
+#define IP6_DSCP_SHIFT 22
/* Dispatch functions meant to be instantiated elsewhere */
@@ -56,6 +62,37 @@ static char * vnet_policer_error_strings[] = {
#undef _
};
+static_always_inline
+void vnet_policer_mark (vlib_buffer_t * b, u8 dscp)
+{
+ ethernet_header_t * eh;
+ ip4_header_t * ip4h;
+ ip6_header_t * ip6h;
+ u16 type;
+
+ eh = (ethernet_header_t *) b->data;
+ type = clib_net_to_host_u16 (eh->type);
+
+ if (PREDICT_TRUE(type == ETHERNET_TYPE_IP4))
+ {
+ ip4h = (ip4_header_t *) &(b->data[sizeof(ethernet_header_t)]);;
+ ip4h->tos &= IP4_NON_DSCP_BITS;
+ ip4h->tos |= dscp << IP4_DSCP_SHIFT;
+ ip4h->checksum = ip4_header_checksum (ip4h);
+ }
+ else
+ {
+ if (PREDICT_TRUE(type == ETHERNET_TYPE_IP6))
+ {
+ ip6h = (ip6_header_t *) &(b->data[sizeof(ethernet_header_t)]);
+ ip6h->ip_version_traffic_class_and_flow_label &=
+ clib_host_to_net_u32(IP6_NON_DSCP_BITS);
+ ip6h->ip_version_traffic_class_and_flow_label |=
+ clib_host_to_net_u32(dscp << IP6_DSCP_SHIFT);
+ }
+ }
+}
+
static inline
uword vnet_policer_inline (vlib_main_t * vm,
vlib_node_runtime_t * node,
@@ -92,6 +129,7 @@ uword vnet_policer_inline (vlib_main_t * vm,
u32 len0, len1;
u32 col0, col1;
policer_read_response_type_st * pol0, * pol1;
+ u8 act0, act1;
/* Prefetch next iteration. */
{
@@ -149,28 +187,38 @@ uword vnet_policer_inline (vlib_main_t * vm,
col0 = vnet_police_packet (pol0, len0,
POLICE_CONFORM /* no chaining */,
time_in_policer_periods);
+ act0 = pol0->action[col0];
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);
-
- if (PREDICT_FALSE(col0 > 0))
+ act1 = pol1->action[col1];
+
+ if (PREDICT_FALSE(act0 == SSE2_QOS_ACTION_DROP)) /* drop action */
{
next0 = VNET_POLICER_NEXT_DROP;
b0->error = node->errors[VNET_POLICER_ERROR_DROP];
}
- else
- transmitted++;
-
- if (PREDICT_FALSE(col1 > 0))
+ 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++;
+ }
+
+ if (PREDICT_FALSE(act1 == SSE2_QOS_ACTION_DROP)) /* drop action */
{
next1 = VNET_POLICER_NEXT_DROP;
b1->error = node->errors[VNET_POLICER_ERROR_DROP];
}
- else
- transmitted++;
+ 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++;
+ }
if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)))
@@ -207,6 +255,7 @@ uword vnet_policer_inline (vlib_main_t * vm,
u32 len0;
u32 col0;
policer_read_response_type_st * pol0;
+ u8 act0;
bi0 = from[0];
to_next[0] = bi0;
@@ -238,14 +287,17 @@ uword vnet_policer_inline (vlib_main_t * vm,
col0 = vnet_police_packet (pol0, len0,
POLICE_CONFORM /* no chaining */,
time_in_policer_periods);
+ act0 = pol0->action[col0];
- if (PREDICT_FALSE(col0 > 0))
+ if (PREDICT_FALSE(act0 == SSE2_QOS_ACTION_DROP)) /* drop action */
{
next0 = VNET_POLICER_NEXT_DROP;
b0->error = node->errors[VNET_POLICER_ERROR_DROP];
}
- else
+ 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++;
}