A Protocol Independent Hierarchical FIB (VPP-352)
[vpp.git] / vnet / vnet / classify / vnet_classify.c
index 11d3714..7716fc9 100644 (file)
@@ -16,7 +16,7 @@
 #include <vnet/classify/input_acl.h>
 #include <vnet/ip/ip.h>
 #include <vnet/api_errno.h>     /* for API error numbers */
-#include <vnet/l2/l2_classify.h> /* for L2_CLASSIFY_NEXT_xxx */
+#include <vnet/l2/l2_classify.h> /* for L2_INPUT_CLASSIFY_NEXT_xxx */
 
 vnet_classify_main_t vnet_classify_main;
 
@@ -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;
@@ -972,8 +980,11 @@ uword unformat_classify_mask (unformat_input_t * input, va_list * args)
           if (l2 == 0)
             vec_validate (l2, 13);
           mask = l2;
-          vec_append (mask, l3);
-          vec_free (l3);
+          if (l3)
+            {
+              vec_append (mask, l3);
+              vec_free (l3);
+            }
         }
 
       /* Scan forward looking for the first significant mask octet */
@@ -1012,14 +1023,14 @@ uword unformat_classify_mask (unformat_input_t * input, va_list * args)
   return 0;
 }
 
-#define foreach_l2_next                         \
+#define foreach_l2_input_next                   \
 _(drop, DROP)                                   \
 _(ethernet, ETHERNET_INPUT)                     \
 _(ip4, IP4_INPUT)                               \
 _(ip6, IP6_INPUT)                              \
 _(li, LI)
 
-uword unformat_l2_next_index (unformat_input_t * input, va_list * args)
+uword unformat_l2_input_next_index (unformat_input_t * input, va_list * args)
 {
   vnet_classify_main_t * cm = &vnet_classify_main;
   u32 * miss_next_indexp = va_arg (*args, u32 *);
@@ -1038,8 +1049,47 @@ uword unformat_l2_next_index (unformat_input_t * input, va_list * args)
     }
 
 #define _(n,N) \
-  if (unformat (input, #n)) { next_index = L2_CLASSIFY_NEXT_##N; goto out;}
-  foreach_l2_next;
+  if (unformat (input, #n)) { next_index = L2_INPUT_CLASSIFY_NEXT_##N; goto out;}
+  foreach_l2_input_next;
+#undef _
+  
+  if (unformat (input, "%d", &tmp))
+    { 
+      next_index = tmp; 
+      goto out; 
+    }
+  
+  return 0;
+
+ out:
+  *miss_next_indexp = next_index;
+  return 1;
+}
+
+#define foreach_l2_output_next                   \
+_(drop, DROP)
+
+uword unformat_l2_output_next_index (unformat_input_t * input, va_list * args)
+{
+  vnet_classify_main_t * cm = &vnet_classify_main;
+  u32 * miss_next_indexp = va_arg (*args, u32 *);
+  u32 next_index = 0;
+  u32 tmp;
+  int i;
+  
+  /* First try registered unformat fns, allowing override... */
+  for (i = 0; i < vec_len (cm->unformat_l2_next_index_fns); i++)
+    {
+      if (unformat (input, "%U", cm->unformat_l2_next_index_fns[i], &tmp))
+        {
+          next_index = tmp;
+          goto out;
+        }
+    }
+
+#define _(n,N) \
+  if (unformat (input, #n)) { next_index = L2_OUTPUT_CLASSIFY_NEXT_##N; goto out;}
+  foreach_l2_output_next;
 #undef _
   
   if (unformat (input, "%d", &tmp))
@@ -1056,9 +1106,7 @@ uword unformat_l2_next_index (unformat_input_t * input, va_list * args)
 }
 
 #define foreach_ip_next                         \
-_(miss, MISS)                                   \
 _(drop, DROP)                                   \
-_(local, LOCAL)                                 \
 _(rewrite, REWRITE)
 
 uword unformat_ip_next_index (unformat_input_t * input, va_list * args)
@@ -1141,6 +1189,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,
@@ -1183,7 +1262,10 @@ classify_table_command_fn (vlib_main_t * vm,
     else if (unformat (input, "miss-next %U", unformat_ip_next_index,
                        &miss_next_index))
       ;
-    else if (unformat (input, "l2-miss-next %U", unformat_l2_next_index,
+    else if (unformat (input, "l2-input-miss-next %U", unformat_l2_input_next_index,
+                       &miss_next_index))
+        ;
+    else if (unformat (input, "l2-output-miss-next %U", unformat_l2_output_next_index,
                        &miss_next_index))
       ;
     else if (unformat (input, "acl-miss-next %U", unformat_acl_next_index,
@@ -1676,8 +1758,11 @@ uword unformat_classify_match (unformat_input_t * input, va_list * args)
           if (l2 == 0)
             vec_validate_aligned (l2, 13, sizeof(u32x4));
           match = l2;
-          vec_append_aligned (match, l3, sizeof(u32x4));
-          vec_free (l3);
+          if (l3)
+            {
+              vec_append_aligned (match, l3, sizeof(u32x4));
+              vec_free (l3);
+            }
         }
 
       /* Make sure the vector is big enough even if key is all 0's */
@@ -1757,12 +1842,18 @@ classify_session_command_fn (vlib_main_t * vm,
       else if (unformat (input, "hit-next %U", unformat_ip_next_index,
                          &hit_next_index))
         ;
-      else if (unformat (input, "l2-hit-next %U", unformat_l2_next_index,
+      else if (unformat (input, "l2-input-hit-next %U", unformat_l2_input_next_index,
+                         &hit_next_index))
+        ;
+      else if (unformat (input, "l2-output-hit-next %U", unformat_l2_output_next_index,
                          &hit_next_index))
         ;
       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 +1904,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,
 };
@@ -1880,18 +1972,18 @@ unformat_acl_next_node (unformat_input_t * input, va_list * args)
 }
 
 static uword 
-unformat_l2_next_node (unformat_input_t * input, va_list * args)
+unformat_l2_input_next_node (unformat_input_t * input, va_list * args)
 {
   vnet_classify_main_t * cm = &vnet_classify_main;
   u32 * next_indexp = va_arg (*args, u32 *);
   u32 node_index;
   u32 next_index;
 
-  if (unformat (input, "node %U", unformat_vlib_node,
+  if (unformat (input, "input-node %U", unformat_vlib_node,
                 cm->vlib_main, &node_index))
     {
       next_index = vlib_node_add_next 
-        (cm->vlib_main, l2_classify_node.index, node_index);
+        (cm->vlib_main, l2_input_classify_node.index, node_index);
 
       *next_indexp = next_index;
       return 1;
@@ -1899,6 +1991,25 @@ unformat_l2_next_node (unformat_input_t * input, va_list * args)
   return 0;
 }
 
+static uword 
+unformat_l2_output_next_node (unformat_input_t * input, va_list * args)
+{
+  vnet_classify_main_t * cm = &vnet_classify_main;
+  u32 * next_indexp = va_arg (*args, u32 *);
+  u32 node_index;
+  u32 next_index;
+
+  if (unformat (input, "output-node %U", unformat_vlib_node,
+                cm->vlib_main, &node_index))
+    {
+      next_index = vlib_node_add_next 
+        (cm->vlib_main, l2_output_classify_node.index, node_index);
+
+      *next_indexp = next_index;
+      return 1;
+    }
+  return 0;
+}
 
 static clib_error_t * 
 vnet_classify_init (vlib_main_t * vm)
@@ -1915,7 +2026,13 @@ vnet_classify_init (vlib_main_t * vm)
     (unformat_ip_next_node);
 
   vnet_classify_register_unformat_l2_next_index_fn
-    (unformat_l2_next_node);
+    (unformat_l2_input_next_node);
+
+  vnet_classify_register_unformat_l2_next_index_fn
+    (unformat_l2_input_next_node);
+
+  vnet_classify_register_unformat_l2_next_index_fn
+    (unformat_l2_output_next_node);
 
   vnet_classify_register_unformat_acl_next_index_fn
     (unformat_acl_next_node);
@@ -2002,7 +2119,7 @@ test_classify_command_fn (vlib_main_t * vm,
                                        memory_size,
                                        0 /* skip */,
                                        3 /* vectors to match */);
-          t->miss_next_index = IP_LOOKUP_NEXT_LOCAL;
+          t->miss_next_index = IP_LOOKUP_NEXT_DROP;
           vlib_cli_output (vm, "Create table %d", t - cm->tables);
         }