feature: introduce feature arc end nodes
[vpp.git] / vnet / vnet / feature / feature.h
index b026cdf..b27aaf1 100644 (file)
@@ -29,11 +29,17 @@ typedef struct _vnet_feature_arc_registration
   /** Start nodes */
   char **start_nodes;
   int n_start_nodes;
+  /** End node */
+  char *end_node;
   /* Feature arc index, assigned by init function */
   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
 {
@@ -50,12 +56,16 @@ typedef struct _vnet_feature_registration
   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_
 {
   vnet_config_main_t config_main;
   u32 *config_index_by_sw_if_index;
+  u32 end_feature_index;
 } vnet_feature_config_main_t;
 
 typedef struct
@@ -121,6 +131,9 @@ vnet_config_update_feature_count (vnet_feature_main_t * fm, u8 arc,
 
 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);
+
 
 int
 vnet_feature_enable_disable_with_index (u8 arc_index, u32 feature_index,
@@ -145,6 +158,13 @@ vnet_get_feature_arc_config_main (u8 arc_index)
   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 (u8 arc, u32 sw_if_index)
 {
@@ -275,6 +295,70 @@ vnet_feature_start_device_input_x2 (u32 sw_if_index,
     }
 }
 
+static_always_inline void
+vnet_feature_start_device_input_x4 (u32 sw_if_index,
+                                   u32 * next0,
+                                   u32 * next1,
+                                   u32 * next2,
+                                   u32 * next3,
+                                   vlib_buffer_t * b0,
+                                   vlib_buffer_t * b1,
+                                   vlib_buffer_t * b2,
+                                   vlib_buffer_t * b3,
+                                   u16 buffer_advanced0,
+                                   u16 buffer_advanced1,
+                                   u16 buffer_advanced2,
+                                   u16 buffer_advanced3)
+{
+  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 (b1)->device_input_feat.saved_next_index = *next1;
+      vnet_buffer (b2)->device_input_feat.saved_next_index = *next2;
+      vnet_buffer (b3)->device_input_feat.saved_next_index = *next3;
+
+      vnet_buffer (b0)->device_input_feat.buffer_advance = buffer_advanced0;
+      vnet_buffer (b1)->device_input_feat.buffer_advance = buffer_advanced1;
+      vnet_buffer (b2)->device_input_feat.buffer_advance = buffer_advanced2;
+      vnet_buffer (b3)->device_input_feat.buffer_advance = buffer_advanced3;
+
+      vlib_buffer_advance (b0, -buffer_advanced0);
+      vlib_buffer_advance (b1, -buffer_advanced1);
+      vlib_buffer_advance (b2, -buffer_advanced2);
+      vlib_buffer_advance (b3, -buffer_advanced3);
+
+      b0->feature_arc_index = feature_arc_index;
+      b1->feature_arc_index = feature_arc_index;
+      b2->feature_arc_index = feature_arc_index;
+      b3->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;
+      b2->current_config_index = b0->current_config_index;
+      b3->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);
+      vnet_get_config_data (&cm->config_main, &b2->current_config_index,
+                           next2, /* # bytes of config data */ 0);
+      vnet_get_config_data (&cm->config_main, &b3->current_config_index,
+                           next3, /* # bytes of config data */ 0);
+    }
+}
 
 #define VNET_FEATURES(...)  (char*[]) { __VA_ARGS__, 0}