feature: API/CLI to enable/disable feature per interface
[vpp.git] / vnet / vnet / feature / feature.h
index 1706dec..96d573b 100644 (file)
@@ -17,6 +17,7 @@
 #define included_features_h
 
 #include <vnet/vnet.h>
+#include <vnet/api_errno.h>
 
 /** feature registration object */
 typedef struct _vnet_feature_arc_registration
@@ -29,9 +30,14 @@ typedef struct _vnet_feature_arc_registration
   char **start_nodes;
   int n_start_nodes;
   /* Feature arc index, assigned by init function */
-  u16 feature_arc_index;
+  u8 feature_arc_index;
+  u8 *arc_index_ptr;
 } vnet_feature_arc_registration_t;
 
+/* Enable feature callback. */
+typedef clib_error_t *(vnet_feature_enable_disable_function_t)
+  (u32 sw_if_index, int enable_disable);
+
 /** feature registration object */
 typedef struct _vnet_feature_registration
 {
@@ -42,12 +48,15 @@ typedef struct _vnet_feature_registration
   /** Graph node name */
   char *node_name;
   /** Pointer to this feature index, filled in by vnet_feature_arc_init */
-  u32 *feature_index;
-  u32 feature_index_u32;
+  u32 *feature_index_ptr;
+  u32 feature_index;
   /** Constraints of the form "this feature runs before X" */
   char **runs_before;
   /** Constraints of the form "this feature runs after Y" */
   char **runs_after;
+
+  /** Function to enable/disable feature  **/
+  vnet_feature_enable_disable_function_t *enable_disable_cb;
 } vnet_feature_registration_t;
 
 typedef struct vnet_feature_config_main_t_
@@ -79,6 +88,9 @@ typedef struct
   /** feature reference counts by interface */
   i16 **feature_count_by_sw_if_index;
 
+  /** Feature arc index for device-input */
+  u8 device_input_feature_arc_index;
+
   /** convenience */
   vlib_main_t *vlib_main;
   vnet_main_t *vnet_main;
@@ -111,42 +123,127 @@ static void __vnet_add_feature_registration_##x (void)           \
 __VA_ARGS__ vnet_feature_registration_t vnet_feat_##x
 
 void
-vnet_config_update_feature_count (vnet_feature_main_t * fm, u16 arc,
+vnet_config_update_feature_count (vnet_feature_main_t * fm, u8 arc,
                                  u32 sw_if_index, int is_add);
 
-u32 vnet_feature_index_from_node_name (u16 type, const char *s);
+u32 vnet_get_feature_index (u8 arc, const char *s);
+u8 vnet_get_feature_arc_index (const char *s);
+vnet_feature_registration_t *vnet_get_feature_reg (const char *arc_name,
+                                                  const char *node_name);
 
-void
+
+int
+vnet_feature_enable_disable_with_index (u8 arc_index, u32 feature_index,
+                                       u32 sw_if_index, int enable_disable,
+                                       void *feature_config,
+                                       u32 n_feature_config_bytes);
+
+int
 vnet_feature_enable_disable (const char *arc_name, const char *node_name,
                             u32 sw_if_index, int enable_disable,
                             void *feature_config,
                             u32 n_feature_config_bytes);
 
+static inline vnet_feature_config_main_t *
+vnet_get_feature_arc_config_main (u8 arc_index)
+{
+  vnet_feature_main_t *fm = &feature_main;
+
+  if (arc_index == (u8) ~ 0)
+    return 0;
+
+  return &fm->feature_config_mains[arc_index];
+}
+
+static_always_inline vnet_feature_config_main_t *
+vnet_feature_get_config_main (u16 arc)
+{
+  vnet_feature_main_t *fm = &feature_main;
+  return &fm->feature_config_mains[arc];
+}
 
 static_always_inline int
-vnet_have_features (u32 arc, u32 sw_if_index)
+vnet_have_features (u8 arc, u32 sw_if_index)
 {
   vnet_feature_main_t *fm = &feature_main;
   return clib_bitmap_get (fm->sw_if_index_has_features[arc], sw_if_index);
 }
 
 static_always_inline u32
-vnet_feature_get_config_index (u16 arc, u32 sw_if_index)
+vnet_get_feature_config_index (u8 arc, u32 sw_if_index)
 {
   vnet_feature_main_t *fm = &feature_main;
   vnet_feature_config_main_t *cm = &fm->feature_config_mains[arc];
   return vec_elt (cm->config_index_by_sw_if_index, sw_if_index);
 }
 
+static_always_inline void *
+vnet_feature_arc_start_with_data (u8 arc, u32 sw_if_index, u32 * next,
+                                 vlib_buffer_t * b, u32 n_data_bytes)
+{
+  vnet_feature_main_t *fm = &feature_main;
+  vnet_feature_config_main_t *cm;
+  cm = &fm->feature_config_mains[arc];
+
+  if (PREDICT_FALSE (vnet_have_features (arc, sw_if_index)))
+    {
+      b->feature_arc_index = arc;
+      b->current_config_index =
+       vec_elt (cm->config_index_by_sw_if_index, sw_if_index);
+      return vnet_get_config_data (&cm->config_main, &b->current_config_index,
+                                  next, n_data_bytes);
+    }
+  return 0;
+}
+
 static_always_inline void
-vnet_feature_redirect (u16 arc, u32 sw_if_index, u32 * next0,
-                      vlib_buffer_t * b0)
+vnet_feature_arc_start (u8 arc, u32 sw_if_index, u32 * next0,
+                       vlib_buffer_t * b0)
+{
+  vnet_feature_arc_start_with_data (arc, sw_if_index, next0, b0, 0);
+}
+
+static_always_inline void *
+vnet_feature_next_with_data (u32 sw_if_index, u32 * next0,
+                            vlib_buffer_t * b0, u32 n_data_bytes)
 {
   vnet_feature_main_t *fm = &feature_main;
+  u8 arc = b0->feature_arc_index;
   vnet_feature_config_main_t *cm = &fm->feature_config_mains[arc];
 
-  if (PREDICT_FALSE (vnet_have_features (arc, sw_if_index)))
+  return vnet_get_config_data (&cm->config_main,
+                              &b0->current_config_index, next0,
+                              n_data_bytes);
+}
+
+static_always_inline void
+vnet_feature_next (u32 sw_if_index, u32 * next0, vlib_buffer_t * b0)
+{
+  vnet_feature_next_with_data (sw_if_index, next0, b0, 0);
+}
+
+static_always_inline void
+vnet_feature_start_device_input_x1 (u32 sw_if_index, u32 * next0,
+                                   vlib_buffer_t * b0, u16 buffer_advanced0)
+{
+  vnet_feature_main_t *fm = &feature_main;
+  vnet_feature_config_main_t *cm;
+  u8 feature_arc_index = fm->device_input_feature_arc_index;
+  cm = &fm->feature_config_mains[feature_arc_index];
+
+  if (PREDICT_FALSE
+      (clib_bitmap_get
+       (fm->sw_if_index_has_features[feature_arc_index], sw_if_index)))
     {
+      /*
+       * Save next0 so that the last feature in the chain
+       * can skip ethernet-input if indicated...
+       */
+      vnet_buffer (b0)->device_input_feat.saved_next_index = *next0;
+      vnet_buffer (b0)->device_input_feat.buffer_advance = buffer_advanced0;
+      vlib_buffer_advance (b0, -buffer_advanced0);
+
+      b0->feature_arc_index = feature_arc_index;
       b0->current_config_index =
        vec_elt (cm->config_index_by_sw_if_index, sw_if_index);
       vnet_get_config_data (&cm->config_main, &b0->current_config_index,
@@ -155,37 +252,47 @@ vnet_feature_redirect (u16 arc, u32 sw_if_index, u32 * next0,
 }
 
 static_always_inline void
-vnet_feature_device_input_redirect_x1 (vlib_node_runtime_t * node,
-                                      u32 sw_if_index, u32 * next0,
-                                      vlib_buffer_t * b0,
-                                      u16 buffer_advanced0)
+vnet_feature_start_device_input_x2 (u32 sw_if_index,
+                                   u32 * next0,
+                                   u32 * next1,
+                                   vlib_buffer_t * b0,
+                                   vlib_buffer_t * b1,
+                                   u16 buffer_advanced0,
+                                   u16 buffer_advanced1)
 {
   vnet_feature_main_t *fm = &feature_main;
   vnet_feature_config_main_t *cm;
-
-  ASSERT (node->feature_arc_index != ~(u16) 0);
-  cm = &fm->feature_config_mains[node->feature_arc_index];
+  u8 feature_arc_index = fm->device_input_feature_arc_index;
+  cm = &fm->feature_config_mains[feature_arc_index];
 
   if (PREDICT_FALSE
       (clib_bitmap_get
-       (fm->sw_if_index_has_features[node->feature_arc_index], sw_if_index)))
+       (fm->sw_if_index_has_features[feature_arc_index], sw_if_index)))
     {
       /*
        * Save next0 so that the last feature in the chain
        * can skip ethernet-input if indicated...
        */
       vnet_buffer (b0)->device_input_feat.saved_next_index = *next0;
+      vnet_buffer (b1)->device_input_feat.saved_next_index = *next1;
       vnet_buffer (b0)->device_input_feat.buffer_advance = buffer_advanced0;
+      vnet_buffer (b1)->device_input_feat.buffer_advance = buffer_advanced1;
       vlib_buffer_advance (b0, -buffer_advanced0);
+      vlib_buffer_advance (b1, -buffer_advanced1);
 
+      b0->feature_arc_index = feature_arc_index;
+      b1->feature_arc_index = feature_arc_index;
       b0->current_config_index =
        vec_elt (cm->config_index_by_sw_if_index, sw_if_index);
+      b1->current_config_index = b0->current_config_index;
       vnet_get_config_data (&cm->config_main, &b0->current_config_index,
                            next0, /* # bytes of config data */ 0);
+      vnet_get_config_data (&cm->config_main, &b1->current_config_index,
+                           next1, /* # bytes of config data */ 0);
     }
 }
 
-#define ORDER_CONSTRAINTS (char*[])
+
 #define VNET_FEATURES(...)  (char*[]) { __VA_ARGS__, 0}
 
 clib_error_t *vnet_feature_arc_init (vlib_main_t * vm,