vlib: vlib_validate_buffer_enqueue_with_aux_x1

This change implement a flavour of vlib_validate_buffer_enqueue_x1 with
aux data support

Change-Id: I2ecf7af49cf15ecd23b12d8acd57fe90546c1af7
Type: improvement
Signed-off-by: Mohammed Hawari <mohammed@hawari.fr>
diff --git a/src/vlib/buffer_node.h b/src/vlib/buffer_node.h
index 5bc547a..c0268b2 100644
--- a/src/vlib/buffer_node.h
+++ b/src/vlib/buffer_node.h
@@ -236,6 +236,53 @@
     }									\
 } while (0)
 
+/** \brief Finish enqueueing one buffer forward in the graph, along with its
+ aux_data if possible. Standard single loop boilerplate element. This is a
+ MACRO, with MULTIPLE SIDE EFFECTS. In the ideal case, <code>next_index ==
+ next0</code>, which means that the speculative enqueue at the top of the
+ single loop has correctly dealt with the packet in hand. In that case, the
+ macro does nothing at all. This function MAY return to_next_aux = NULL if
+ next_index does not support aux data
+
+ @param vm vlib_main_t pointer, varies by thread
+ @param node current node vlib_node_runtime_t pointer
+ @param next_index speculated next index used for both packets
+ @param to_next speculated vector pointer used for both packets
+ @param to_next_aux speculated aux_data pointer used for both packets
+ @param n_left_to_next number of slots left in speculated vector
+ @param bi0 first buffer index
+ @param aux0 first aux_data
+ @param next0 actual next index to be used for the first packet
+
+ @return @c next_index -- speculative next index to be used for future packets
+ @return @c to_next -- speculative frame to be used for future packets
+ @return @c n_left_to_next -- number of slots left in speculative frame
+*/
+#define vlib_validate_buffer_enqueue_with_aux_x1(                             \
+  vm, node, next_index, to_next, to_next_aux, n_left_to_next, bi0, aux0,      \
+  next0)                                                                      \
+  do                                                                          \
+    {                                                                         \
+      ASSERT (bi0 != 0);                                                      \
+      if (PREDICT_FALSE (next0 != next_index))                                \
+	{                                                                     \
+	  vlib_put_next_frame (vm, node, next_index, n_left_to_next + 1);     \
+	  next_index = next0;                                                 \
+	  vlib_get_next_frame_with_aux_safe (vm, node, next_index, to_next,   \
+					     to_next_aux, n_left_to_next);    \
+                                                                              \
+	  to_next[0] = bi0;                                                   \
+	  to_next += 1;                                                       \
+	  if (to_next_aux)                                                    \
+	    {                                                                 \
+	      to_next_aux[0] = aux0;                                          \
+	      to_next_aux += 1;                                               \
+	    }                                                                 \
+	  n_left_to_next -= 1;                                                \
+	}                                                                     \
+    }                                                                         \
+  while (0)
+
 always_inline uword
 generic_buffer_node_inline (vlib_main_t * vm,
 			    vlib_node_runtime_t * node,
diff --git a/src/vlib/node_funcs.h b/src/vlib/node_funcs.h
index 62a1fec..0f9f30a 100644
--- a/src/vlib/node_funcs.h
+++ b/src/vlib/node_funcs.h
@@ -498,6 +498,16 @@
   (v);									\
 })
 
+#define vlib_set_next_frame_with_aux_safe(vm, node, next_index, v, aux)       \
+  ({                                                                          \
+    uword _n_left;                                                            \
+    vlib_get_next_frame_with_aux_safe ((vm), (node), (next_index), (v),       \
+				       (aux), _n_left);                       \
+    ASSERT (_n_left > 0);                                                     \
+    vlib_put_next_frame ((vm), (node), (next_index), _n_left - 1);            \
+    (v);                                                                      \
+  })
+
 always_inline void
 vlib_set_next_frame_buffer (vlib_main_t * vm,
 			    vlib_node_runtime_t * node,
@@ -508,6 +518,20 @@
   p[0] = buffer_index;
 }
 
+always_inline void
+vlib_set_next_frame_buffer_with_aux_safe (vlib_main_t *vm,
+					  vlib_node_runtime_t *node,
+					  u32 next_index, u32 buffer_index,
+					  u32 aux)
+{
+  u32 *p;
+  u32 *a;
+  p = vlib_set_next_frame_with_aux_safe (vm, node, next_index, p, a);
+  p[0] = buffer_index;
+  if (a)
+    a[0] = aux;
+}
+
 vlib_frame_t *vlib_get_frame_to_node (vlib_main_t * vm, u32 to_node_index);
 void vlib_put_frame_to_node (vlib_main_t * vm, u32 to_node_index,
 			     vlib_frame_t * f);