VPP-521: Classify API enhancement to redirect traffic to pre-defined VRF 31/3731/8
authorSteve Shin <jonshin@cisco.com>
Tue, 8 Nov 2016 18:47:10 +0000 (10:47 -0800)
committerJohn Lo <loj@cisco.com>
Wed, 16 Nov 2016 02:29:44 +0000 (02:29 +0000)
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>
vnet/vnet/classify/vnet_classify.c
vnet/vnet/classify/vnet_classify.h
vnet/vnet/ip/ip_input_acl.c
vnet/vnet/l2/l2_input_acl.c
vpp-api-test/vat/api_format.c
vpp/vpp-api/api.c
vpp/vpp-api/custom_dump.c
vpp/vpp-api/vpe.api

index e179045..d7a0d81 100644 (file)
@@ -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);
index f609aaa..ed8442b 100644 (file)
@@ -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;
index 6331cf4..93a580c 100644 (file)
@@ -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;
                         }
                     }
index de9f679..104fcd1 100644 (file)
@@ -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);
index 65114ec..b32c159 100644 (file)
@@ -8756,6 +8756,8 @@ api_classify_add_del_table (vat_main_t * vam)
   u32 memory_size = 32 << 20;
   u8 *mask = 0;
   f64 timeout;
+  u32 current_data_flag = 0;
+  int current_data_offset = 0;
 
   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
     {
@@ -8785,6 +8787,10 @@ api_classify_add_del_table (vat_main_t * vam)
       else if (unformat (i, "acl-miss-next %U", unformat_acl_next_index,
                         &miss_next_index))
        ;
+      else if (unformat (i, "current-data-flag %d", &current_data_flag))
+       ;
+      else if (unformat (i, "current-data-offset %d", &current_data_offset))
+       ;
       else
        break;
     }
@@ -8823,6 +8829,8 @@ api_classify_add_del_table (vat_main_t * vam)
   mp->match_n_vectors = ntohl (match);
   mp->next_table_index = ntohl (next_table_index);
   mp->miss_next_index = ntohl (miss_next_index);
+  mp->current_data_flag = ntohl (current_data_flag);
+  mp->current_data_offset = ntohl (current_data_offset);
   clib_memcpy (mp->mask, mask, vec_len (mask));
 
   vec_free (mask);
@@ -9282,6 +9290,8 @@ api_classify_add_del_session (vat_main_t * vam)
   f64 timeout;
   u32 skip_n_vectors = 0;
   u32 match_n_vectors = 0;
+  u32 action = 0;
+  u32 metadata = 0;
 
   /*
    * Warning: you have to supply skip_n and match_n
@@ -9319,6 +9329,14 @@ api_classify_add_del_session (vat_main_t * vam)
        ;
       else if (unformat (i, "table-index %d", &table_index))
        ;
+      else if (unformat (i, "action set-ip4-fib-id %d", &metadata))
+       action = 1;
+      else if (unformat (i, "action set-ip6-fib-id %d", &metadata))
+       action = 2;
+      else if (unformat (i, "action %d", &action))
+       ;
+      else if (unformat (i, "metadata %d", &metadata))
+       ;
       else
        break;
     }
@@ -9342,6 +9360,8 @@ api_classify_add_del_session (vat_main_t * vam)
   mp->hit_next_index = ntohl (hit_next_index);
   mp->opaque_index = ntohl (opaque_index);
   mp->advance = ntohl (advance);
+  mp->action = action;
+  mp->metadata = ntohl (metadata);
   clib_memcpy (mp->match, match, vec_len (match));
   vec_free (match);
 
@@ -16641,12 +16661,14 @@ _(sr_multicast_map_add_del,                                             \
   "address [ip6 multicast address] sr-policy [policy name] [del]")     \
 _(classify_add_del_table,                                               \
   "buckets <nn> [skip <n>] [match <n>] [memory_size <nn-bytes>]\n"     \
-  "[del] mask <mask-value>\n"                                          \
-  " [l2-miss-next | miss-next | acl-miss-next] <name|nn>")             \
+  " [del] mask <mask-value>\n"                                          \
+  " [l2-miss-next | miss-next | acl-miss-next] <name|nn>\n"            \
+  " [current-data-flag <n>] [current-data-offset <nn>] [table <nn>]")   \
 _(classify_add_del_session,                                             \
   "[hit-next|l2-hit-next|acl-hit-next|policer-hit-next] <name|nn>\n"    \
   "  table-index <nn> skip_n <nn> match_n <nn> match [hex] [l2]\n"      \
-  "  [l3 [ip4|ip6]]")                                                  \
+  "  [l3 [ip4|ip6]] [action set-ip4-fib-id <nn>]\n"                     \
+  "  [action set-ip6-fib-id <nn> | action <n> metadata <nn>] [del]")    \
 _(classify_set_interface_ip_table,                                      \
   "<intfc> | sw_if_index <nn> table <nn>")                             \
 _(classify_set_interface_l2_tables,                                     \
index 1ecd148..b297576 100644 (file)
@@ -3922,7 +3922,9 @@ _(memory_size)                                  \
 _(skip_n_vectors)                               \
 _(match_n_vectors)                              \
 _(next_table_index)                             \
-_(miss_next_index)
+_(miss_next_index)                              \
+_(current_data_flag)                            \
+_(current_data_offset)
 
 static void vl_api_classify_add_del_table_t_handler
   (vl_api_classify_add_del_table_t * mp)
@@ -3941,17 +3943,25 @@ static void vl_api_classify_add_del_table_t_handler
 #undef _
 
   /* The underlying API fails silently, on purpose, so check here */
-  if (mp->is_add == 0)
-    if (pool_is_free_index (cm->tables, table_index))
-      {
-       rv = VNET_API_ERROR_NO_SUCH_TABLE;
-       goto out;
-      }
+  if (mp->is_add == 0)         /* delete */
+    {
+      if (pool_is_free_index (cm->tables, table_index))
+       {
+         rv = VNET_API_ERROR_NO_SUCH_TABLE;
+         goto out;
+       }
+    }
+  else                         /* add or update */
+    {
+      if (table_index != ~0 && pool_is_free_index (cm->tables, table_index))
+       table_index = ~0;
+    }
 
   rv = vnet_classify_add_del_table
     (cm, mp->mask, nbuckets, memory_size,
      skip_n_vectors, match_n_vectors,
-     next_table_index, miss_next_index, &table_index, mp->is_add);
+     next_table_index, miss_next_index, &table_index,
+     current_data_flag, current_data_offset, mp->is_add);
 
 out:
   /* *INDENT-OFF* */
@@ -3980,17 +3990,20 @@ static void vl_api_classify_add_del_session_t_handler
   vnet_classify_main_t *cm = &vnet_classify_main;
   vl_api_classify_add_del_session_reply_t *rmp;
   int rv;
-  u32 table_index, hit_next_index, opaque_index;
+  u32 table_index, hit_next_index, opaque_index, metadata;
   i32 advance;
+  u8 action;
 
   table_index = ntohl (mp->table_index);
   hit_next_index = ntohl (mp->hit_next_index);
   opaque_index = ntohl (mp->opaque_index);
   advance = ntohl (mp->advance);
+  action = mp->action;
+  metadata = ntohl (mp->metadata);
 
   rv = vnet_classify_add_del_session
     (cm, table_index, mp->match, hit_next_index, opaque_index,
-     advance, mp->is_add);
+     advance, action, metadata, mp->is_add);
 
   REPLY_MACRO (VL_API_CLASSIFY_ADD_DEL_SESSION_REPLY);
 }
index b42130d..1dc9665 100644 (file)
@@ -1222,6 +1222,10 @@ static void *vl_api_classify_add_del_table_t_print
       s = format (s, "match %d ", ntohl (mp->match_n_vectors));
       s = format (s, "next-table %d ", ntohl (mp->next_table_index));
       s = format (s, "miss-next %d ", ntohl (mp->miss_next_index));
+      s = format (s, "current-data-flag %d ", ntohl (mp->current_data_flag));
+      if (mp->current_data_flag)
+       s = format (s, "current-data-offset %d ",
+                   ntohl (mp->current_data_offset));
       s = format (s, "mask hex ");
       for (i = 0; i < ntohl (mp->match_n_vectors) * sizeof (u32x4); i++)
        s = format (s, "%02x", mp->mask[i]);
@@ -1243,6 +1247,9 @@ static void *vl_api_classify_add_del_session_t_print
   s = format (s, "hit_next_index %d ", ntohl (mp->hit_next_index));
   s = format (s, "opaque_index %d ", ntohl (mp->opaque_index));
   s = format (s, "advance %d ", ntohl (mp->advance));
+  s = format (s, "action %d ", mp->action);
+  if (mp->action)
+    s = format (s, "metadata %d ", ntohl (mp->metadata));
   if (mp->is_add == 0)
     s = format (s, "del ");
 
index e69979c..8a7fac6 100644 (file)
@@ -1766,6 +1766,17 @@ define bd_ip_mac_add_del_reply
     @param match_n_vectors - number of match vectors
     @param next_table_index - index of next table
     @param miss_next_index - index of miss table
+    @param current_data_flag - option to use current node's packet payload
+            as the starting point from where packets are classified,
+            This option is only valid for L2/L3 input ACL for now.
+            0: by default, classify data from the buffer's start location
+            1: classify packets from VPP node’s current data pointer
+    @param current_data_offset - a signed value to shift the start location of
+            the packet to be classified
+            For example, if input IP ACL node is used, L2 header’s first byte
+            can be accessible by configuring current_data_offset to -14
+            if there is no vlan tag.
+            This is valid only if current_data_flag is set to 1.
     @param mask[] - match mask
 */
 define classify_add_del_table
@@ -1780,6 +1791,8 @@ define classify_add_del_table
   u32 match_n_vectors;
   u32 next_table_index;
   u32 miss_next_index;
+  u32 current_data_flag;
+  i32 current_data_offset;
   u8 mask[0];
 };
 
@@ -1807,6 +1820,17 @@ define classify_add_del_table_reply
     @param hit_next_index - for add, hit_next_index of new session, required
     @param opaque_index - for add, opaque_index of new session
     @param advance -for add, advance value for session
+    @param action -
+           0: no action (by default)
+              metadata is not used.
+           1: Classified IP packets will be looked up from the
+              specified ipv4 fib table (configured by metadata as VRF id).
+              Only valid for L3 input ACL node
+           2: Classified IP packets will be looked up from the
+              specified ipv6 fib table (configured by metadata as VRF id).
+              Only valid for L3 input ACL node
+    @param metadata - valid only if action != 0
+           VRF id if action is 1 or 2.
     @param match[] - for add, match value for session, required
 */
 define classify_add_del_session
@@ -1818,6 +1842,8 @@ define classify_add_del_session
   u32 hit_next_index;
   u32 opaque_index;
   i32 advance;
+  u8 action;
+  u32 metadata;
   u8 match[0];
 };