feature: add interface-output arc 22/4022/5
authorDamjan Marion <damarion@cisco.com>
Tue, 29 Nov 2016 13:55:43 +0000 (14:55 +0100)
committerOle Trøan <otroan@employees.org>
Fri, 2 Dec 2016 14:14:50 +0000 (14:14 +0000)
Change-Id: Ifea275a312e0f2474cdc3a336ac51ea83e403c74
Signed-off-by: Damjan Marion <damarion@cisco.com>
vnet/vnet/config.c
vnet/vnet/interface.c
vnet/vnet/interface.h
vnet/vnet/interface_output.c

index be48df6..03189d7 100644 (file)
@@ -174,7 +174,6 @@ vnet_config_init (vlib_main_t * vm,
                     STRUCT_SIZE_OF (vnet_config_t, config_string_vector[0]),
                     sizeof (uword));
 
-  ASSERT (n_start_node_names >= 1);
   ASSERT (n_feature_node_names >= 1);
 
   vec_resize (cm->start_node_indices, n_start_node_names);
index 6e3d7f2..8c19ca7 100644 (file)
@@ -687,7 +687,9 @@ vnet_register_interface (vnet_main_t * vnm,
   vnet_hw_interface_class_t *hw_class =
     vnet_get_hw_interface_class (vnm, hw_class_index);
   vlib_main_t *vm = vnm->vlib_main;
-  u32 hw_index;
+  vnet_feature_config_main_t *fcm;
+  vnet_config_main_t *cm;
+  u32 hw_index, i;
   char *tx_node_name, *output_node_name;
 
   pool_get (im->hw_interfaces, hw);
@@ -832,6 +834,28 @@ vnet_register_interface (vnet_main_t * vnm,
       vlib_node_add_next_with_slot (vm, hw->output_node_index,
                                    hw->tx_node_index,
                                    VNET_INTERFACE_OUTPUT_NEXT_TX);
+
+      /* add interface to the list of "output-interface" feature arc start nodes
+         and clone nexts from 1st interface if it exists */
+      fcm = vnet_feature_get_config_main (im->output_feature_arc_index);
+      cm = &fcm->config_main;
+      i = vec_len (cm->start_node_indices);
+      vec_validate (cm->start_node_indices, i);
+      cm->start_node_indices[i] = hw->output_node_index;
+      if (hw_index)
+       {
+         /* copy nexts from 1st interface */
+         vnet_hw_interface_t *first_hw;
+         vlib_node_t *first_node;
+
+         first_hw = vnet_get_hw_interface (vnm, /* hw_if_index */ 0);
+         first_node = vlib_get_node (vm, first_hw->output_node_index);
+
+         /* 1st 2 nexts are already added above */
+         for (i = 2; i < vec_len (first_node->next_nodes); i++)
+           vlib_node_add_next_with_slot (vm, hw->output_node_index,
+                                         first_node->next_nodes[i], i);
+       }
     }
 
   setup_output_node (vm, hw->output_node_index, hw_class);
index 412574d..d3076a5 100644 (file)
@@ -621,6 +621,8 @@ typedef struct
   u32 pcap_pkts_to_capture;
   uword *pcap_drop_filter_hash;
 
+  /* feature_arc_index */
+  u8 output_feature_arc_index;
 } vnet_interface_main_t;
 
 static inline void
index 46e8a98..502fa7b 100644 (file)
@@ -38,6 +38,7 @@
  */
 
 #include <vnet/vnet.h>
+#include <vnet/feature/feature.h>
 
 typedef struct
 {
@@ -430,6 +431,8 @@ vnet_interface_output_node_no_flatten (vlib_main_t * vm,
   u32 cpu_index = vm->cpu_index;
   vnet_interface_main_t *im = &vnm->interface_main;
   u32 next_index = VNET_INTERFACE_OUTPUT_NEXT_TX;
+  u32 current_config_index = ~0;
+  u8 arc = im->output_feature_arc_index;
 
   n_buffers = frame->n_vectors;
 
@@ -472,6 +475,17 @@ vnet_interface_output_node_no_flatten (vlib_main_t * vm,
   n_bytes = 0;
   n_packets = 0;
 
+  /* interface-output feature arc handling */
+  if (PREDICT_FALSE (vnet_have_features (arc, rt->sw_if_index)))
+    {
+      vnet_feature_config_main_t *fcm;
+      fcm = vnet_feature_get_config_main (arc);
+      current_config_index = vnet_get_feature_config_index (arc,
+                                                           rt->sw_if_index);
+      vnet_get_config_data (&fcm->config_main, &current_config_index,
+                           &next_index, 0);
+    }
+
   while (from < from_end)
     {
       /* Get new next frame since previous incomplete frame may have less
@@ -512,6 +526,14 @@ vnet_interface_output_node_no_flatten (vlib_main_t * vm,
          n_bytes += n_bytes_b0 + n_bytes_b1;
          n_packets += 2;
 
+         if (PREDICT_FALSE (current_config_index != ~0))
+           {
+             b0->feature_arc_index = arc;
+             b1->feature_arc_index = arc;
+             b0->current_config_index = current_config_index;
+             b1->current_config_index = current_config_index;
+           }
+
          if (PREDICT_FALSE (tx_swif0 != rt->sw_if_index))
            {
              /* update vlan subif tx counts, if required */
@@ -555,6 +577,12 @@ vnet_interface_output_node_no_flatten (vlib_main_t * vm,
          n_bytes += n_bytes_b0;
          n_packets += 1;
 
+         if (PREDICT_FALSE (current_config_index != ~0))
+           {
+             b0->feature_arc_index = arc;
+             b0->current_config_index = current_config_index;
+           }
+
          if (PREDICT_FALSE (tx_swif0 != rt->sw_if_index))
            {
 
@@ -1134,6 +1162,77 @@ VLIB_REGISTER_NODE (vnet_per_buffer_interface_output_node,static) = {
 VLIB_NODE_FUNCTION_MULTIARCH (vnet_per_buffer_interface_output_node,
                              vnet_per_buffer_interface_output);
 
+static uword
+interface_tx_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
+                     vlib_frame_t * from_frame)
+{
+  vnet_main_t *vnm = vnet_get_main ();
+  u32 last_sw_if_index = ~0;
+  vlib_frame_t *to_frame = 0;
+  vnet_hw_interface_t *hw = 0;
+  u32 *from, *to_next = 0;
+  u32 n_left_from;
+
+  from = vlib_frame_vector_args (from_frame);
+  n_left_from = from_frame->n_vectors;
+  while (n_left_from > 0)
+    {
+      u32 bi0;
+      vlib_buffer_t *b0;
+      u32 sw_if_index0;
+
+      bi0 = from[0];
+      from++;
+      n_left_from--;
+      b0 = vlib_get_buffer (vm, bi0);
+      sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_TX];
+
+      if (PREDICT_FALSE ((last_sw_if_index != sw_if_index0) || to_frame == 0))
+       {
+         if (to_frame)
+           {
+             hw = vnet_get_sup_hw_interface (vnm, last_sw_if_index);
+             vlib_put_frame_to_node (vm, hw->tx_node_index, to_frame);
+           }
+         last_sw_if_index = sw_if_index0;
+         hw = vnet_get_sup_hw_interface (vnm, sw_if_index0);
+         to_frame = vlib_get_frame_to_node (vm, hw->tx_node_index);
+         to_next = vlib_frame_vector_args (to_frame);
+       }
+
+      to_next[0] = bi0;
+      to_next++;
+      to_frame->n_vectors++;
+    }
+  vlib_put_frame_to_node (vm, hw->tx_node_index, to_frame);
+  return from_frame->n_vectors;
+}
+
+/* *INDENT-OFF* */
+VLIB_REGISTER_NODE (interface_tx, static) = {
+  .function = interface_tx_node_fn,
+  .name = "interface-tx",
+  .vector_size = sizeof (u32),
+  .n_next_nodes = 1,
+  .next_nodes = {
+    [0] = "error-drop",
+  },
+};
+
+VNET_FEATURE_ARC_INIT (interface_output, static) =
+{
+  .arc_name  = "interface-output",
+  .start_nodes = VNET_FEATURES (0),
+  .arc_index_ptr = &vnet_main.interface_main.output_feature_arc_index,
+};
+
+VNET_FEATURE_INIT (interface_tx, static) = {
+  .arc_name = "interface-output",
+  .node_name = "interface-tx",
+  .runs_before = 0,
+};
+/* *INDENT-ON* */
+
 clib_error_t *
 vnet_per_buffer_interface_output_hw_interface_add_del (vnet_main_t * vnm,
                                                       u32 hw_if_index,