policer: add policer handoff 87/30887/2
authorBrian Russell <brian@graphiant.com>
Tue, 19 Jan 2021 16:50:56 +0000 (16:50 +0000)
committerNeale Ranns <neale@graphiant.com>
Thu, 28 Jan 2021 10:26:35 +0000 (10:26 +0000)
Add thread handoff for packets being policed. Note that the handoff
currently requires the policer index to be passed in. This is suitable
for use in the ip[46] punt paths where each policer node will only
ever use a single policer. For the more general case, this will be
expanded in future to use a policer index stored in packet metadata.

Type: improvement
Signed-off-by: Brian Russell <brian@graphiant.com>
Change-Id: I85a0ecbcfb025f8844e763224cd3de1561249aca

src/vnet/policer/police_inlines.h
src/vnet/policer/policer.c

index 64386e6..afcc772 100644 (file)
@@ -78,6 +78,73 @@ vnet_policer_police (vlib_main_t * vm,
   return act;
 }
 
+typedef enum
+{
+  POLICER_HANDOFF_ERROR_CONGESTION_DROP,
+} policer_handoff_error_t;
+
+typedef struct policer_handoff_trace_t_
+{
+  u32 policer_index;
+  u32 current_worker_index;
+  u32 next_worker_index;
+} policer_handoff_trace_t;
+
+extern u8 *format_policer_handoff_trace (u8 *s, va_list *args);
+
+/* Do worker handoff based on the policer's thread_index */
+static_always_inline uword
+policer_handoff (vlib_main_t *vm, vlib_node_runtime_t *node,
+                vlib_frame_t *frame, u32 fq_index, u32 policer_index)
+{
+  vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b;
+  u16 thread_indices[VLIB_FRAME_SIZE], *ti;
+  u32 n_enq, n_left_from, *from;
+  vnet_policer_main_t *pm;
+  policer_read_response_type_st *policer;
+  u32 this_thread, policer_thread;
+
+  pm = &vnet_policer_main;
+  policer = &pm->policers[policer_index];
+  policer_thread = policer->thread_index;
+
+  this_thread = vm->thread_index;
+  from = vlib_frame_vector_args (frame);
+  n_left_from = frame->n_vectors;
+  vlib_get_buffers (vm, from, bufs, n_left_from);
+
+  b = bufs;
+  ti = thread_indices;
+
+  while (n_left_from > 0)
+    {
+      ti[0] = policer_thread;
+
+      if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) &&
+                        b[0]->flags & VLIB_BUFFER_IS_TRACED))
+       {
+         policer_handoff_trace_t *t =
+           vlib_add_trace (vm, node, b[0], sizeof (*t));
+         t->current_worker_index = this_thread;
+         t->next_worker_index = policer_thread;
+         t->policer_index = policer_index;
+       }
+
+      n_left_from--;
+      ti++;
+      b++;
+    }
+
+  n_enq = vlib_buffer_enqueue_to_thread (vm, fq_index, from, thread_indices,
+                                        frame->n_vectors, 1);
+
+  if (n_enq < frame->n_vectors)
+    vlib_node_increment_counter (vm, node->node_index,
+                                POLICER_HANDOFF_ERROR_CONGESTION_DROP,
+                                frame->n_vectors - n_enq);
+
+  return n_enq;
+}
 #endif // __POLICE_INLINES_H__
 
 /*
index 7ad87a6..80fa1e6 100644 (file)
  */
 #include <stdint.h>
 #include <vnet/policer/policer.h>
+#include <vnet/policer/police_inlines.h>
 #include <vnet/classify/vnet_classify.h>
 
 vnet_policer_main_t vnet_policer_main;
 
+u8 *
+format_policer_handoff_trace (u8 *s, va_list *args)
+{
+  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
+  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
+  policer_handoff_trace_t *t = va_arg (*args, policer_handoff_trace_t *);
+
+  s = format (s, "policer %d, handoff thread %d to %d", t->policer_index,
+             t->current_worker_index, t->next_worker_index);
+
+  return s;
+}
+
 clib_error_t *
 policer_add_del (vlib_main_t * vm,
                 u8 * name,