vlib: fixed the issue of vpp crash caused by interface up/down
[vpp.git] / src / vlib / node_funcs.h
index 263017d..b1d5c7b 100644 (file)
 
 #include <vppinfra/fifo.h>
 #include <vppinfra/tw_timer_1t_3w_1024sl_ov.h>
+#include <vppinfra/interrupt.h>
+
+#ifdef CLIB_SANITIZE_ADDR
+#include <sanitizer/asan_interface.h>
+#endif
+
+static_always_inline void
+vlib_process_start_switch_stack (vlib_main_t * vm, vlib_process_t * p)
+{
+#ifdef CLIB_SANITIZE_ADDR
+  void *stack = p ? (void *) p->stack : vlib_thread_stacks[vm->thread_index];
+  u32 stack_bytes = p ? p->log2_n_stack_bytes : VLIB_THREAD_STACK_SIZE;
+  __sanitizer_start_switch_fiber (&vm->asan_stack_save, stack, stack_bytes);
+#endif
+}
+
+static_always_inline void
+vlib_process_finish_switch_stack (vlib_main_t * vm)
+{
+#ifdef CLIB_SANITIZE_ADDR
+  const void *bottom_old;
+  size_t size_old;
+
+  __sanitizer_finish_switch_fiber (&vm->asan_stack_save, &bottom_old,
+                                  &size_old);
+#endif
+}
 
 /** \brief Get vlib node by index.
  @warning This function will ASSERT if @c i is out of range.
@@ -175,6 +202,10 @@ vlib_node_set_state (vlib_main_t * vm, u32 node_index,
       nm->input_node_counts_by_state[new_state] += 1;
     }
 
+  if (PREDICT_FALSE (r->state == VLIB_NODE_STATE_DISABLED))
+    vlib_node_runtime_perf_counter (vm, r, 0, 0, 0,
+                                   VLIB_NODE_RUNTIME_PERF_RESET);
+
   n->state = new_state;
   r->state = new_state;
 }
@@ -194,36 +225,40 @@ vlib_node_get_state (vlib_main_t * vm, u32 node_index)
 }
 
 always_inline void
-vlib_node_set_interrupt_pending_with_data (vlib_main_t * vm, u32 node_index,
-                                          u32 data)
+vlib_node_set_flag (vlib_main_t *vm, u32 node_index, u16 flag, u8 enable)
 {
-  vlib_node_main_t *nm = &vm->node_main;
-  vlib_node_t *n = vec_elt (nm->nodes, node_index);
-  vlib_node_interrupt_t *i;
-  ASSERT (n->type == VLIB_NODE_TYPE_INPUT);
+  vlib_node_runtime_t *r;
+  vlib_node_t *n;
 
-  if (vm == vlib_get_main ())
+  n = vlib_get_node (vm, node_index);
+  r = vlib_node_get_runtime (vm, node_index);
+
+  if (enable)
     {
-      /* local thread */
-      vec_add2 (nm->pending_local_interrupts, i, 1);
-      i->node_runtime_index = n->runtime_index;
-      i->data = data;
+      n->flags |= flag;
+      r->flags |= flag;
     }
   else
     {
-      /* remote thread */
-      clib_spinlock_lock (&nm->pending_interrupt_lock);
-      vec_add2 (nm->pending_remote_interrupts, i, 1);
-      i->node_runtime_index = n->runtime_index;
-      i->data = data;
-      clib_spinlock_unlock (&nm->pending_interrupt_lock);
+      n->flags &= ~flag;
+      r->flags &= ~flag;
     }
 }
 
 always_inline void
-vlib_node_set_interrupt_pending (vlib_main_t * vm, u32 node_index)
+vlib_node_set_interrupt_pending (vlib_main_t *vm, u32 node_index)
 {
-  vlib_node_set_interrupt_pending_with_data (vm, node_index, 0);
+  vlib_node_main_t *nm = &vm->node_main;
+  vlib_node_t *n = vec_elt (nm->nodes, node_index);
+
+  ASSERT (n->type == VLIB_NODE_TYPE_INPUT);
+
+  if (vm != vlib_get_main ())
+    clib_interrupt_set_atomic (nm->interrupts, n->runtime_index);
+  else
+    clib_interrupt_set (nm->interrupts, n->runtime_index);
+
+  __atomic_store_n (nm->pending_interrupts, 1, __ATOMIC_RELEASE);
 }
 
 always_inline vlib_process_t *
@@ -424,6 +459,13 @@ vlib_current_process (vlib_main_t * vm)
   return vlib_get_current_process (vm)->node_runtime.node_index;
 }
 
+always_inline u32
+vlib_get_current_process_node_index (vlib_main_t * vm)
+{
+  vlib_process_t *process = vlib_get_current_process (vm);
+  return process->node_runtime.node_index;
+}
+
 /** Returns TRUE if a process suspend time is less than 10us
     @param dt - remaining poll time in seconds
     @returns 1 if dt < 10e-6, 0 otherwise
@@ -456,8 +498,11 @@ vlib_process_suspend (vlib_main_t * vm, f64 dt)
     {
       /* expiration time in 10us ticks */
       p->resume_clock_interval = dt * 1e5;
+      vlib_process_start_switch_stack (vm, 0);
       clib_longjmp (&p->return_longjmp, VLIB_PROCESS_RETURN_LONGJMP_SUSPEND);
     }
+  else
+    vlib_process_finish_switch_stack (vm);
 
   return r;
 }
@@ -625,8 +670,13 @@ vlib_process_wait_for_event (vlib_main_t * vm)
       r =
        clib_setjmp (&p->resume_longjmp, VLIB_PROCESS_RESUME_LONGJMP_SUSPEND);
       if (r == VLIB_PROCESS_RESUME_LONGJMP_SUSPEND)
-       clib_longjmp (&p->return_longjmp,
-                     VLIB_PROCESS_RETURN_LONGJMP_SUSPEND);
+       {
+         vlib_process_start_switch_stack (vm, 0);
+         clib_longjmp (&p->return_longjmp,
+                       VLIB_PROCESS_RETURN_LONGJMP_SUSPEND);
+       }
+      else
+       vlib_process_finish_switch_stack (vm);
     }
 
   return p->non_empty_event_type_bitmap;
@@ -649,8 +699,13 @@ vlib_process_wait_for_one_time_event (vlib_main_t * vm,
       r =
        clib_setjmp (&p->resume_longjmp, VLIB_PROCESS_RESUME_LONGJMP_SUSPEND);
       if (r == VLIB_PROCESS_RESUME_LONGJMP_SUSPEND)
-       clib_longjmp (&p->return_longjmp,
-                     VLIB_PROCESS_RETURN_LONGJMP_SUSPEND);
+       {
+         vlib_process_start_switch_stack (vm, 0);
+         clib_longjmp (&p->return_longjmp,
+                       VLIB_PROCESS_RETURN_LONGJMP_SUSPEND);
+       }
+      else
+       vlib_process_finish_switch_stack (vm);
     }
 
   return vlib_process_get_events_helper (p, with_type_index, data_vector);
@@ -673,8 +728,13 @@ vlib_process_wait_for_event_with_type (vlib_main_t * vm,
       r =
        clib_setjmp (&p->resume_longjmp, VLIB_PROCESS_RESUME_LONGJMP_SUSPEND);
       if (r == VLIB_PROCESS_RESUME_LONGJMP_SUSPEND)
-       clib_longjmp (&p->return_longjmp,
-                     VLIB_PROCESS_RETURN_LONGJMP_SUSPEND);
+       {
+         vlib_process_start_switch_stack (vm, 0);
+         clib_longjmp (&p->return_longjmp,
+                       VLIB_PROCESS_RETURN_LONGJMP_SUSPEND);
+       }
+      else
+       vlib_process_finish_switch_stack (vm);
 
       /* See if unknown event type has been signaled now. */
       if (!h)
@@ -715,8 +775,11 @@ vlib_process_wait_for_event_or_clock (vlib_main_t * vm, f64 dt)
   if (r == VLIB_PROCESS_RESUME_LONGJMP_SUSPEND)
     {
       p->resume_clock_interval = dt * 1e5;
+      vlib_process_start_switch_stack (vm, 0);
       clib_longjmp (&p->return_longjmp, VLIB_PROCESS_RETURN_LONGJMP_SUSPEND);
     }
+  else
+    vlib_process_finish_switch_stack (vm);
 
   /* Return amount of time still left to sleep.
      If <= 0 then we've been waken up by the clock (and not an event). */
@@ -785,7 +848,7 @@ vlib_process_signal_event_helper (vlib_node_main_t * nm,
     if (!data_vec && vec_len (nm->recycled_event_data_vectors))
       {
        data_vec = vec_pop (nm->recycled_event_data_vectors);
-       _vec_len (data_vec) = 0;
+       vec_reset_length (data_vec);
       }
 
     l = vec_len (data_vec);
@@ -1147,6 +1210,9 @@ void vlib_node_rename (vlib_main_t * vm, u32 node_index, char *fmt, ...);
    macro. */
 u32 vlib_register_node (vlib_main_t * vm, vlib_node_registration_t * r);
 
+/* Register all node function variants */
+void vlib_register_all_node_march_variants (vlib_main_t *vm);
+
 /* Register all static nodes registered via VLIB_REGISTER_NODE. */
 void vlib_register_all_static_nodes (vlib_main_t * vm);
 
@@ -1155,6 +1221,12 @@ void vlib_start_process (vlib_main_t * vm, uword process_index);
 
 /* Sync up runtime and main node stats. */
 void vlib_node_sync_stats (vlib_main_t * vm, vlib_node_t * n);
+void vlib_node_runtime_sync_stats (vlib_main_t *vm, vlib_node_runtime_t *r,
+                                  uword n_calls, uword n_vectors,
+                                  uword n_clocks);
+void vlib_node_runtime_sync_stats_node (vlib_node_t *n, vlib_node_runtime_t *r,
+                                       uword n_calls, uword n_vectors,
+                                       uword n_clocks);
 
 /* Node graph initialization function. */
 clib_error_t *vlib_node_main_init (vlib_main_t * vm);
@@ -1188,6 +1260,22 @@ vlib_node_increment_counter (vlib_main_t * vm, u32 node_index,
 u32 vlib_process_create (vlib_main_t * vm, char *name,
                         vlib_node_function_t * f, u32 log2_n_stack_bytes);
 
+always_inline int
+vlib_node_set_dispatch_wrapper (vlib_main_t *vm, vlib_node_function_t *fn)
+{
+  if (fn && vm->dispatch_wrapper_fn)
+    return 1;
+  vm->dispatch_wrapper_fn = fn;
+  return 0;
+}
+
+int vlib_node_set_march_variant (vlib_main_t *vm, u32 node_index,
+                                clib_march_variant_type_t march_variant);
+
+vlib_node_function_t *
+vlib_node_get_preferred_node_fn_variant (vlib_main_t *vm,
+                                        vlib_node_fn_registration_t *regs);
+
 #endif /* included_vlib_node_funcs_h */
 
 /*