aboutsummaryrefslogtreecommitdiffstats
path: root/vnet
diff options
context:
space:
mode:
authorSteve Shin <jonshin@cisco.com>2016-11-08 10:47:10 -0800
committerJohn Lo <loj@cisco.com>2016-11-16 02:29:44 +0000
commit25e26dc5136137c771715145dd5b2884060ff9eb (patch)
tree9279b106952a9a603060a185bda6b9f2e89ec8f4 /vnet
parent9c6ae5f43b1f3141d37d6d7b3963926302826f08 (diff)
VPP-521: Classify API enhancement to redirect traffic to pre-defined VRF
Ingress packets are punted to the “Input ACL node” where traffic is classified based on n-tuple keys. If no matched session is found from the classify tables, then it will be passed to “the lookup node” for normal packet forwarding. If a classify session is hit from one of classify tables, then packet vnet buffer field sw_if_index[VLIB_TX] will be updated to the new FIB index used for subsequent IP lookup for this packet. Change-Id: Ifdea63196ddb81c2d5c43b8c98e11ddbf5b11858 Signed-off-by: Steve Shin <jonshin@cisco.com>
Diffstat (limited to 'vnet')
-rw-r--r--vnet/vnet/classify/vnet_classify.c89
-rw-r--r--vnet/vnet/classify/vnet_classify.h31
-rw-r--r--vnet/vnet/ip/ip_input_acl.c38
-rw-r--r--vnet/vnet/l2/l2_input_acl.c36
4 files changed, 159 insertions, 35 deletions
diff --git a/vnet/vnet/classify/vnet_classify.c b/vnet/vnet/classify/vnet_classify.c
index e179045814c..d7a0d815e5c 100644
--- a/vnet/vnet/classify/vnet_classify.c
+++ b/vnet/vnet/classify/vnet_classify.c
@@ -17,6 +17,7 @@
#include <vnet/ip/ip.h>
#include <vnet/api_errno.h> /* for API error numbers */
#include <vnet/l2/l2_classify.h> /* for L2_INPUT_CLASSIFY_NEXT_xxx */
+#include <vnet/fib/fib_table.h>
vnet_classify_main_t vnet_classify_main;
@@ -571,9 +572,9 @@ static u8 * format_classify_entry (u8 * s, va_list * args)
vnet_classify_entry_t * e = va_arg (*args, vnet_classify_entry_t *);
s = format
- (s, "[%u]: next_index %d advance %d opaque %d\n",
+ (s, "[%u]: next_index %d advance %d opaque %d action %d metadata %d\n",
vnet_classify_get_offset (t, e), e->next_index, e->advance,
- e->opaque_index);
+ e->opaque_index, e->action, e->metadata);
s = format (s, " k: %U\n", format_hex_bytes, e->key,
@@ -653,24 +654,37 @@ int vnet_classify_add_del_table (vnet_classify_main_t * cm,
u32 next_table_index,
u32 miss_next_index,
u32 * table_index,
+ u8 current_data_flag,
+ i16 current_data_offset,
int is_add)
{
vnet_classify_table_t * t;
if (is_add)
{
- *table_index = ~0;
- if (memory_size == 0)
- return VNET_API_ERROR_INVALID_MEMORY_SIZE;
-
- if (nbuckets == 0)
- return VNET_API_ERROR_INVALID_VALUE;
-
- t = vnet_classify_new_table (cm, mask, nbuckets, memory_size,
- skip, match);
- t->next_table_index = next_table_index;
- t->miss_next_index = miss_next_index;
- *table_index = t - cm->tables;
+ if (*table_index == ~0) /* add */
+ {
+ if (memory_size == 0)
+ return VNET_API_ERROR_INVALID_MEMORY_SIZE;
+
+ if (nbuckets == 0)
+ return VNET_API_ERROR_INVALID_VALUE;
+
+ t = vnet_classify_new_table (cm, mask, nbuckets, memory_size,
+ skip, match);
+ t->next_table_index = next_table_index;
+ t->miss_next_index = miss_next_index;
+ t->current_data_flag = current_data_flag;
+ t->current_data_offset = current_data_offset;
+ *table_index = t - cm->tables;
+ }
+ else /* update */
+ {
+ vnet_classify_main_t *cm = &vnet_classify_main;
+ t = pool_elt_at_index (cm->tables, *table_index);
+
+ t->next_table_index = next_table_index;
+ }
return 0;
}
@@ -1376,6 +1390,8 @@ classify_table_command_fn (vlib_main_t * vm,
u32 miss_next_index = ~0;
u32 memory_size = 2<<20;
u32 tmp;
+ u32 current_data_flag = 0;
+ int current_data_offset = 0;
u8 * mask = 0;
vnet_classify_main_t * cm = &vnet_classify_main;
@@ -1413,18 +1429,22 @@ classify_table_command_fn (vlib_main_t * vm,
else if (unformat (input, "acl-miss-next %U", unformat_acl_next_index,
&miss_next_index))
;
-
+ else if (unformat (input, "current-data-flag %d", &current_data_flag))
+ ;
+ else if (unformat (input, "current-data-offset %d", &current_data_offset))
+ ;
+
else
break;
}
- if (is_add && mask == 0)
+ if (is_add && mask == 0 && table_index == ~0)
return clib_error_return (0, "Mask required");
- if (is_add && skip == ~0)
+ if (is_add && skip == ~0 && table_index == ~0)
return clib_error_return (0, "skip count required");
- if (is_add && match == ~0)
+ if (is_add && match == ~0 && table_index == ~0)
return clib_error_return (0, "match count required");
if (!is_add && table_index == ~0)
@@ -1432,7 +1452,7 @@ classify_table_command_fn (vlib_main_t * vm,
rv = vnet_classify_add_del_table (cm, mask, nbuckets, memory_size,
skip, match, next_table_index, miss_next_index,
- &table_index, is_add);
+ &table_index, current_data_flag, current_data_offset, is_add);
switch (rv)
{
case 0:
@@ -1449,7 +1469,8 @@ VLIB_CLI_COMMAND (classify_table, static) = {
.path = "classify table",
.short_help =
"classify table [miss-next|l2-miss_next|acl-miss-next <next_index>]"
- "\n mask <mask-value> buckets <nn> [skip <n>] [match <n>] [del]",
+ "\n mask <mask-value> buckets <nn> [skip <n>] [match <n>]"
+ "\n [current-data-flag <n>] [current-data-offset <n>] [table <n>] [del]",
.function = classify_table_command_fn,
};
@@ -1473,8 +1494,9 @@ static u8 * format_vnet_classify_table (u8 * s, va_list * args)
s = format (s, "\n Heap: %U", format_mheap, t->mheap, 0 /*verbose*/);
- s = format (s, "\n nbuckets %d, skip %d match %d",
- t->nbuckets, t->skip_n_vectors, t->match_n_vectors);
+ s = format (s, "\n nbuckets %d, skip %d match %d flag %d offset %d",
+ t->nbuckets, t->skip_n_vectors, t->match_n_vectors,
+ t->current_data_flag, t->current_data_offset);
s = format (s, "\n mask %U", format_hex_bytes, t->mask,
t->match_n_vectors * sizeof (u32x4));
@@ -1974,6 +1996,8 @@ int vnet_classify_add_del_session (vnet_classify_main_t * cm,
u32 hit_next_index,
u32 opaque_index,
i32 advance,
+ u8 action,
+ u32 metadata,
int is_add)
{
vnet_classify_table_t * t;
@@ -1993,6 +2017,11 @@ int vnet_classify_add_del_session (vnet_classify_main_t * cm,
e->hits = 0;
e->last_heard = 0;
e->flags = 0;
+ e->action = action;
+ if (e->action == CLASSIFY_ACTION_SET_IP4_FIB_INDEX)
+ e->metadata = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, metadata);
+ else if (e->action == CLASSIFY_ACTION_SET_IP6_FIB_INDEX)
+ e->metadata = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, metadata);
/* Copy key data, honoring skip_n_vectors */
clib_memcpy (&e->key, match + t->skip_n_vectors * sizeof (u32x4),
@@ -2020,6 +2049,8 @@ classify_session_command_fn (vlib_main_t * vm,
u64 opaque_index = ~0;
u8 * match = 0;
i32 advance = 0;
+ u32 action = 0;
+ u32 metadata = 0;
int i, rv;
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
@@ -2050,6 +2081,10 @@ classify_session_command_fn (vlib_main_t * vm,
;
else if (unformat (input, "table-index %d", &table_index))
;
+ else if (unformat (input, "action set-ip4-fib-id %d", &metadata))
+ action = 1;
+ else if (unformat (input, "action set-ip6-fib-id %d", &metadata))
+ action = 2;
else
{
/* Try registered opaque-index unformat fns */
@@ -2073,7 +2108,8 @@ classify_session_command_fn (vlib_main_t * vm,
rv = vnet_classify_add_del_session (cm, table_index, match,
hit_next_index,
- opaque_index, advance, is_add);
+ opaque_index, advance,
+ action, metadata, is_add);
switch(rv)
{
@@ -2093,7 +2129,8 @@ VLIB_CLI_COMMAND (classify_session_command, static) = {
.short_help =
"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>]",
+ "\n table-index <nn> match [hex] [l2] [l3 ip4] [opaque-index <index>]"
+ "\n [action set-ip4-fib-id <n>] [action set-ip6-fib-id <n>] [del]",
.function = classify_session_command_fn,
};
@@ -2323,7 +2360,7 @@ test_classify_command_fn (vlib_main_t * vm,
rv = vnet_classify_add_del_session (cm, t - cm->tables, (u8 *) data,
IP_LOOKUP_NEXT_DROP,
i+100 /* opaque_index */,
- 0 /* advance */,
+ 0 /* advance */, 0, 0,
1 /* is_add */);
if (rv != 0)
@@ -2362,7 +2399,7 @@ test_classify_command_fn (vlib_main_t * vm,
rv = vnet_classify_add_del_session (cm, t - cm->tables, key_minus_skip,
IP_LOOKUP_NEXT_DROP,
i+100 /* opaque_index */,
- 0 /* advance */,
+ 0 /* advance */, 0, 0,
0 /* is_add */);
if (rv != 0)
clib_warning ("del: returned %d", rv);
diff --git a/vnet/vnet/classify/vnet_classify.h b/vnet/vnet/classify/vnet_classify.h
index f609aaa49d6..ed8442b3dce 100644
--- a/vnet/vnet/classify/vnet_classify.h
+++ b/vnet/vnet/classify/vnet_classify.h
@@ -46,6 +46,25 @@ extern vlib_node_registration_t ip6_classify_node;
#define U32X4_ALIGNED(p) PREDICT_TRUE((((intptr_t)p) & 0xf) == 0)
+/*
+ * Classify table option to process packets
+ * CLASSIFY_FLAG_USE_CURR_DATA:
+ * - classify packets starting from VPP node’s current data pointer
+ */
+#define CLASSIFY_FLAG_USE_CURR_DATA 1
+
+/*
+ * Classify session action
+ * CLASSIFY_ACTION_SET_IP4_FIB_INDEX:
+ * - Classified IP packets will be looked up
+ * from the specified ipv4 fib table
+ * CLASSIFY_ACTION_SET_IP6_FIB_INDEX:
+ * - Classified IP packets will be looked up
+ * from the specified ipv6 fib table
+ */
+#define CLASSIFY_ACTION_SET_IP4_FIB_INDEX 1
+#define CLASSIFY_ACTION_SET_IP6_FIB_INDEX 2
+
struct _vnet_classify_main;
typedef struct _vnet_classify_main vnet_classify_main_t;
@@ -71,9 +90,12 @@ typedef CLIB_PACKED(struct _vnet_classify_entry {
};
/* Really only need 1 bit */
- u32 flags;
+ u8 flags;
#define VNET_CLASSIFY_ENTRY_FREE (1<<0)
+ u8 action;
+ u16 metadata;
+
/* Hit counter, last heard time */
union {
u64 hits;
@@ -131,6 +153,9 @@ typedef struct {
u32 log2_nbuckets;
int entries_per_page;
u32 active_elements;
+ u32 current_data_flag;
+ int current_data_offset;
+ u32 data_offset;
/* Index of next table to try */
u32 next_table_index;
@@ -449,6 +474,8 @@ int vnet_classify_add_del_session (vnet_classify_main_t * cm,
u32 hit_next_index,
u32 opaque_index,
i32 advance,
+ u8 action,
+ u32 metadata,
int is_add);
int vnet_classify_add_del_table (vnet_classify_main_t * cm,
@@ -460,6 +487,8 @@ int vnet_classify_add_del_table (vnet_classify_main_t * cm,
u32 next_table_index,
u32 miss_next_index,
u32 * table_index,
+ u8 current_data_flag,
+ i16 current_data_offset,
int is_add);
unformat_function_t unformat_ip4_mask;
diff --git a/vnet/vnet/ip/ip_input_acl.c b/vnet/vnet/ip/ip_input_acl.c
index 6331cf4fa6b..93a580ce47c 100644
--- a/vnet/vnet/ip/ip_input_acl.c
+++ b/vnet/vnet/ip/ip_input_acl.c
@@ -115,11 +115,9 @@ ip_inacl_inline (vlib_main_t * vm,
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 = am->classify_table_index_by_sw_if_index[tid][sw_if_index0];
@@ -131,11 +129,21 @@ ip_inacl_inline (vlib_main_t * vm,
t1 = pool_elt_at_index (vcm->tables, table_index1);
+ if (t0->current_data_flag == CLASSIFY_FLAG_USE_CURR_DATA)
+ h0 = (void *)vlib_buffer_get_current (b0) + t0->current_data_offset;
+ else
+ h0 = b0->data;
+
vnet_buffer(b0)->l2_classify.hash =
vnet_classify_hash_packet (t0, (u8 *) h0);
vnet_classify_prefetch_bucket (t0, vnet_buffer(b0)->l2_classify.hash);
+ if (t1->current_data_flag == CLASSIFY_FLAG_USE_CURR_DATA)
+ h1 = (void *)vlib_buffer_get_current (b1) + t1->current_data_offset;
+ else
+ h1 = b1->data;
+
vnet_buffer(b1)->l2_classify.hash =
vnet_classify_hash_packet (t1, (u8 *) h1);
@@ -160,12 +168,17 @@ ip_inacl_inline (vlib_main_t * vm,
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 = am->classify_table_index_by_sw_if_index[tid][sw_if_index0];
t0 = pool_elt_at_index (vcm->tables, table_index0);
+
+ if (t0->current_data_flag == CLASSIFY_FLAG_USE_CURR_DATA)
+ h0 = (void *)vlib_buffer_get_current (b0) + t0->current_data_offset;
+ else
+ h0 = b0->data;
+
vnet_buffer(b0)->l2_classify.hash =
vnet_classify_hash_packet (t0, (u8 *) h0);
@@ -227,7 +240,6 @@ ip_inacl_inline (vlib_main_t * vm,
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;
@@ -243,6 +255,11 @@ ip_inacl_inline (vlib_main_t * vm,
hash0 = vnet_buffer(b0)->l2_classify.hash;
t0 = pool_elt_at_index (vcm->tables, table_index0);
+ if (t0->current_data_flag == CLASSIFY_FLAG_USE_CURR_DATA)
+ h0 = (void *)vlib_buffer_get_current (b0) + t0->current_data_offset;
+ else
+ h0 = b0->data;
+
e0 = vnet_classify_find_entry (t0, (u8 *) h0, hash0,
now);
if (e0)
@@ -263,6 +280,10 @@ ip_inacl_inline (vlib_main_t * vm,
error0 = (next0 == ACL_NEXT_INDEX_DENY)?
IP6_ERROR_INACL_SESSION_DENY:IP6_ERROR_NONE;
b0->error = error_node->errors[error0];
+
+ if (e0->action == CLASSIFY_ACTION_SET_IP4_FIB_INDEX ||
+ e0->action == CLASSIFY_ACTION_SET_IP6_FIB_INDEX)
+ vnet_buffer (b0)->sw_if_index[VLIB_TX] = e0->metadata;
}
else
{
@@ -288,6 +309,11 @@ ip_inacl_inline (vlib_main_t * vm,
break;
}
+ if (t0->current_data_flag == CLASSIFY_FLAG_USE_CURR_DATA)
+ h0 = (void *)vlib_buffer_get_current (b0) + t0->current_data_offset;
+ else
+ h0 = b0->data;
+
hash0 = vnet_classify_hash_packet (t0, (u8 *) h0);
e0 = vnet_classify_find_entry
(t0, (u8 *) h0, hash0, now);
@@ -308,6 +334,10 @@ ip_inacl_inline (vlib_main_t * vm,
error0 = (next0 == ACL_NEXT_INDEX_DENY)?
IP6_ERROR_INACL_SESSION_DENY:IP6_ERROR_NONE;
b0->error = error_node->errors[error0];
+
+ if (e0->action == CLASSIFY_ACTION_SET_IP4_FIB_INDEX ||
+ e0->action == CLASSIFY_ACTION_SET_IP6_FIB_INDEX)
+ vnet_buffer (b0)->sw_if_index[VLIB_TX] = e0->metadata;
break;
}
}
diff --git a/vnet/vnet/l2/l2_input_acl.c b/vnet/vnet/l2/l2_input_acl.c
index de9f6791225..104fcd15b85 100644
--- a/vnet/vnet/l2/l2_input_acl.c
+++ b/vnet/vnet/l2/l2_input_acl.c
@@ -137,11 +137,9 @@ l2_inacl_node_fn (vlib_main_t * vm,
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 =
@@ -155,11 +153,21 @@ l2_inacl_node_fn (vlib_main_t * vm,
t1 = pool_elt_at_index (vcm->tables, table_index1);
+ if (t0->current_data_flag == CLASSIFY_FLAG_USE_CURR_DATA)
+ h0 = (void *) vlib_buffer_get_current (b0) + t0->current_data_offset;
+ else
+ h0 = b0->data;
+
vnet_buffer (b0)->l2_classify.hash =
vnet_classify_hash_packet (t0, (u8 *) h0);
vnet_classify_prefetch_bucket (t0, vnet_buffer (b0)->l2_classify.hash);
+ if (t1->current_data_flag == CLASSIFY_FLAG_USE_CURR_DATA)
+ h1 = (void *) vlib_buffer_get_current (b1) + t1->current_data_offset;
+ else
+ h1 = b1->data;
+
vnet_buffer (b1)->l2_classify.hash =
vnet_classify_hash_packet (t1, (u8 *) h1);
@@ -184,13 +192,18 @@ l2_inacl_node_fn (vlib_main_t * vm,
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 =
am->classify_table_index_by_sw_if_index[tid][sw_if_index0];
t0 = pool_elt_at_index (vcm->tables, table_index0);
+
+ if (t0->current_data_flag == CLASSIFY_FLAG_USE_CURR_DATA)
+ h0 = (void *) vlib_buffer_get_current (b0) + t0->current_data_offset;
+ else
+ h0 = b0->data;
+
vnet_buffer (b0)->l2_classify.hash =
vnet_classify_hash_packet (t0, (u8 *) h0);
@@ -251,7 +264,7 @@ l2_inacl_node_fn (vlib_main_t * vm,
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;
@@ -270,6 +283,13 @@ l2_inacl_node_fn (vlib_main_t * vm,
hash0 = vnet_buffer (b0)->l2_classify.hash;
t0 = pool_elt_at_index (vcm->tables, table_index0);
+ if (t0->current_data_flag == CLASSIFY_FLAG_USE_CURR_DATA)
+ h0 =
+ (void *) vlib_buffer_get_current (b0) +
+ t0->current_data_offset;
+ else
+ h0 = b0->data;
+
e0 = vnet_classify_find_entry (t0, (u8 *) h0, hash0, now);
if (e0)
{
@@ -308,6 +328,14 @@ l2_inacl_node_fn (vlib_main_t * vm,
break;
}
+ if (t0->current_data_flag ==
+ CLASSIFY_FLAG_USE_CURR_DATA)
+ h0 =
+ (void *) vlib_buffer_get_current (b0) +
+ t0->current_data_offset;
+ else
+ h0 = b0->data;
+
hash0 = vnet_classify_hash_packet (t0, (u8 *) h0);
e0 = vnet_classify_find_entry
(t0, (u8 *) h0, hash0, now);